@ikie-dev/cli 9.8.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 (2522) hide show
  1. package/.envrc +3 -0
  2. package/.github/CODEOWNERS +16 -0
  3. package/.github/ISSUE_TEMPLATE/bug_report.yml +85 -0
  4. package/.github/ISSUE_TEMPLATE/config.yml +5 -0
  5. package/.github/ISSUE_TEMPLATE/feature_request.yml +24 -0
  6. package/.github/ISSUE_TEMPLATE/question.yml +16 -0
  7. package/.github/actions/setup/action.yml +49 -0
  8. package/.github/pull_request_template.md +18 -0
  9. package/.github/release.yml +17 -0
  10. package/.github/workflows/acp-e2e.yml +52 -0
  11. package/.github/workflows/arc-terminal-bench-poc.yml +157 -0
  12. package/.github/workflows/auto-label-pr.yml +90 -0
  13. package/.github/workflows/canary.yml +302 -0
  14. package/.github/workflows/ci.yml +114 -0
  15. package/.github/workflows/close-stale.yml +21 -0
  16. package/.github/workflows/release.yml +288 -0
  17. package/.github/workflows/require-linked-issue.yml +21 -0
  18. package/.github/workflows/stale.yml +32 -0
  19. package/.github/workflows/tui-e2e.yml +52 -0
  20. package/.github/workflows/welcome.yml +21 -0
  21. package/.gitmodules +3 -0
  22. package/.husky/pre-commit +1 -0
  23. package/.ikie/ferments/019f2735-088f-75e4-9a8f-7d7b037c2a59/runtime.json +11 -0
  24. package/.ikie/ferments/019f2735-08b3-70fe-88df-8dd1494f6a8e/runtime.json +11 -0
  25. package/.ikie/ferments/019f2735-08d3-7041-8d5e-a153e2937274/runtime.json +11 -0
  26. package/.ikie/ferments/019f2735-08f8-7591-bf1a-6c1324842331/runtime.json +12 -0
  27. package/.ikie/ferments/019f2735-0913-73d5-82b4-37012a5c1148/runtime.json +11 -0
  28. package/.ikie/ferments/019f2735-0940-76dc-b667-964b9cd9294d/runtime.json +11 -0
  29. package/.ikie/ferments/019f2735-0971-7094-92e3-b8ea4cdb9390/runtime.json +15 -0
  30. package/.ikie/ferments/019f2735-0999-72aa-9727-f6e8c3427ed6/runtime.json +15 -0
  31. package/.ikie/ferments/019f2735-09bf-76dd-88a2-c7e574b45636/runtime.json +15 -0
  32. package/.ikie/ferments/019f2735-09f1-77af-8820-89c0b3b5a182/runtime.json +13 -0
  33. package/.ikie/ferments/019f2735-0a49-77d9-b4c7-5a80bbbbafd9/runtime.json +15 -0
  34. package/.ikie/ferments/019f2735-0a79-73c3-977b-0c9164267b94/runtime.json +15 -0
  35. package/.ikie/ferments/019f2735-0abd-70ba-a794-fbb63fbf23de/runtime.json +11 -0
  36. package/.ikie/ferments/019f2735-0ad6-7079-8576-8fb651b4b698/runtime.json +15 -0
  37. package/.ikie/ferments/019f2735-0b03-70db-b5e5-59b1869aa2dc/runtime.json +15 -0
  38. package/.ikie/ferments/019f2735-0b34-7675-a4ed-39a15333e3b8/runtime.json +15 -0
  39. package/.ikie/ferments/019f2735-0b6c-716e-9f92-c391d6acb6f0/runtime.json +15 -0
  40. package/.ikie/ferments/019f2735-0b90-72be-a60d-3dd4c514d1c3/runtime.json +15 -0
  41. package/.ikie/ferments/019f2735-0baf-72e7-b5c5-99d8533b8343/runtime.json +15 -0
  42. package/.ikie/ferments/019f2735-0bd8-70f8-9d83-1a2b9152a013/runtime.json +15 -0
  43. package/.ikie/ferments/019f2735-0bfa-70de-ad20-7fe8c41b968e/runtime.json +15 -0
  44. package/.ikie/ferments/019f2735-0c26-7246-a2ab-f24f5a76fc5f/runtime.json +15 -0
  45. package/.ikie/ferments/019f2735-0c49-771b-934f-4afdb5664666/runtime.json +11 -0
  46. package/.ikie/ferments/019f2735-0c63-73f8-944e-14d19e69ba41/runtime.json +11 -0
  47. package/.ikie/ferments/019f2735-0c80-772b-8530-2df4d15b9d7a/reviews/phase-phase-1-1.json +63 -0
  48. package/.ikie/ferments/019f2735-0c80-772b-8530-2df4d15b9d7a/runtime.json +17 -0
  49. package/.ikie/ferments/019f2735-0dfc-7551-b147-aa46815027f5/reviews/phase-phase-1-1.json +63 -0
  50. package/.ikie/ferments/019f2735-0dfc-7551-b147-aa46815027f5/runtime.json +17 -0
  51. package/.ikie/ferments/019f2735-0f74-70f6-804c-e4d2145b32e1/runtime.json +11 -0
  52. package/.ikie/ferments/019f2735-1354-7041-854e-e6a577467dd0/runtime.json +11 -0
  53. package/.ikie/ferments/019f2735-1371-749f-8ea9-01f7f8734568/runtime.json +11 -0
  54. package/.ikie/ferments/019f2735-138f-72f2-ba7b-7912ad4cd7b9/runtime.json +11 -0
  55. package/.ikie/ferments/019f2735-13ad-710a-9c4d-38a30a0f4b37/runtime.json +11 -0
  56. package/.ikie/ferments/019f2735-13cb-7698-88c1-890fba497dc0/pending-proposal.json +45 -0
  57. package/.ikie/ferments/019f2735-13da-77dd-a916-8d82348671d2/pending-proposal.json +45 -0
  58. package/.ikie/ferments/019f2735-14d3-727a-81db-347c03cb2919/pending-proposal.json +45 -0
  59. package/.ikie/ferments/019f2735-1521-736e-8b75-22e94a8775f7/pending-proposal.json +45 -0
  60. package/.ikie/ferments/019f2735-1542-777c-a3a7-bc7f1edf1922/pending-proposal.json +45 -0
  61. package/.ikie/ferments/019f2735-3528-75bc-b100-8deb63dfde55/runtime.json +13 -0
  62. package/.ikie/ferments/019f2735-3553-72d8-a60d-9357420e110a/runtime.json +11 -0
  63. package/.ikie/ferments/019f2735-3569-756b-bc90-01c9ab00e413/runtime.json +11 -0
  64. package/.ikie/ferments/019f2735-3583-71d0-83f9-fc40b292190b/runtime.json +11 -0
  65. package/.ikie/ferments/019f2735-3597-7571-8332-47b3443395a6/runtime.json +11 -0
  66. package/.ikie/ferments/019f2735-35b3-74fe-a5db-82651a97cf0d/runtime.json +11 -0
  67. package/.ikie/ferments/019f2735-35de-741a-94e7-7b89c4eaaa43/runtime.json +11 -0
  68. package/.ikie/ferments/019f2735-35f5-713c-9892-f6179e783d02/runtime.json +11 -0
  69. package/.ikie/ferments/019f2735-360d-7056-a5e0-43fb3eb0f98e/runtime.json +9 -0
  70. package/.ikie/ferments/019f2735-362e-756c-b848-34f3c3c4602b/runtime.json +13 -0
  71. package/.ikie/ferments/019f2735-364a-76f9-bfba-ba52ca3852fd/runtime.json +11 -0
  72. package/.ikie/ferments/019f2735-3662-754c-8a88-807a68e0790e/runtime.json +11 -0
  73. package/.ikie/ferments/019f2735-36c2-71f9-a003-2921a1792be1/runtime.json +11 -0
  74. package/.ikie/ferments/019f2735-36d6-751d-9776-1e1def988d2d/runtime.json +9 -0
  75. package/.ikie/ferments/019f2735-36ef-70bf-a6b2-f2a0944f1b7e/runtime.json +9 -0
  76. package/.ikie/ferments/019f2735-3712-77e3-a46e-c69470e4e850/runtime.json +11 -0
  77. package/.ikie/ferments/019f2735-37cf-712f-bfaa-8fc9e29da513/runtime.json +11 -0
  78. package/.ikie/ferments/019f2735-37ed-727a-8a74-fe716d22571d/runtime.json +12 -0
  79. package/.ikie/ferments/019f2735-3810-7370-b587-eef0bb9d4d81/runtime.json +11 -0
  80. package/.ikie/ferments/019f2735-3828-71ad-9ee9-62fa0f46cad7/runtime.json +11 -0
  81. package/.ikie/ferments/019f2735-383f-722b-8d96-5038b9c9aa5a/runtime.json +11 -0
  82. package/.ikie/ferments/019f2735-385a-72c8-b269-a87a416c5a10/runtime.json +11 -0
  83. package/.ikie/ferments/019f2735-386d-73fe-be0a-1bc89a0264c4/runtime.json +13 -0
  84. package/.ikie/ferments/019f2735-388a-7276-9bee-81dcd177953f/runtime.json +11 -0
  85. package/.ikie/ferments/019f2735-82ed-74e8-870d-d8678feaf7bb/reviews/phase-phase-1-1.json +41 -0
  86. package/.ikie/ferments/019f2735-82ed-74e8-870d-d8678feaf7bb/runtime.json +11 -0
  87. package/.ikie/ferments/019f2735-831e-70aa-b9d6-1214165775d0/reviews/phase-phase-1-1.json +47 -0
  88. package/.ikie/ferments/019f2735-831e-70aa-b9d6-1214165775d0/runtime.json +13 -0
  89. package/.ikie/ferments/019f2735-835e-73b3-bb48-2d0080526fc3/reviews/phase-phase-1-1.json +40 -0
  90. package/.ikie/ferments/019f2735-835e-73b3-bb48-2d0080526fc3/runtime.json +9 -0
  91. package/.ikie/ferments/019f2735-8379-74b6-b62f-816bb5276a85/reviews/phase-phase-1-1.json +40 -0
  92. package/.ikie/ferments/019f2735-8379-74b6-b62f-816bb5276a85/runtime.json +9 -0
  93. package/.ikie/ferments/019f2735-8391-7385-bab6-03362866622a/reviews/phase-phase-1-1.json +40 -0
  94. package/.ikie/ferments/019f2735-8391-7385-bab6-03362866622a/runtime.json +9 -0
  95. package/.ikie/ferments/019f2735-83ad-7251-8280-aa6f7f3bfc5e/reviews/phase-phase-1-1.json +40 -0
  96. package/.ikie/ferments/019f2735-83ad-7251-8280-aa6f7f3bfc5e/runtime.json +9 -0
  97. package/.ikie/ferments/019f2735-83d2-77be-984e-fb65263a3a5b/reviews/phase-phase-1-1.json +40 -0
  98. package/.ikie/ferments/019f2735-83d2-77be-984e-fb65263a3a5b/runtime.json +9 -0
  99. package/.ikie/ferments/019f2735-83ec-7743-acc5-b2bf14c3cc54/reviews/phase-phase-1-1.json +62 -0
  100. package/.ikie/ferments/019f2735-83ec-7743-acc5-b2bf14c3cc54/runtime.json +9 -0
  101. package/.ikie/ferments/019f2740-c8c5-720f-b641-214bb99d8a83/runtime.json +11 -0
  102. package/.ikie/ferments/019f2740-c8fb-763f-8310-88c7e558e410/runtime.json +11 -0
  103. package/.ikie/ferments/019f2740-c917-70d2-8be6-15f376c60a70/runtime.json +11 -0
  104. package/.ikie/ferments/019f2740-c984-711f-a903-4b2251918413/runtime.json +12 -0
  105. package/.ikie/ferments/019f2740-ca09-71cf-93a5-86efc136ecd5/runtime.json +11 -0
  106. package/.ikie/ferments/019f2740-ca46-77f4-ae02-88e42f2153fb/runtime.json +15 -0
  107. package/.ikie/ferments/019f2740-ca74-72dd-8855-3feedfa071db/runtime.json +15 -0
  108. package/.ikie/ferments/019f2740-ca9a-710b-9bb7-feffa42cdb36/runtime.json +15 -0
  109. package/.ikie/ferments/019f2740-cac9-7518-ae93-973e4cf364ce/runtime.json +13 -0
  110. package/.ikie/ferments/019f2740-cb04-71c1-83a7-a448fefc6764/runtime.json +15 -0
  111. package/.ikie/ferments/019f2740-cb35-743b-bc18-434c7c233a08/runtime.json +15 -0
  112. package/.ikie/ferments/019f2740-cb6e-742c-970b-1893b4bf4e87/runtime.json +11 -0
  113. package/.ikie/ferments/019f2740-cb92-76a7-bd20-fd4f3f17664f/runtime.json +15 -0
  114. package/.ikie/ferments/019f2740-cbc1-7509-8542-302d2d1d3084/runtime.json +15 -0
  115. package/.ikie/ferments/019f2740-cbfa-719d-94c0-9d03a864e7e1/runtime.json +15 -0
  116. package/.ikie/ferments/019f2740-cc31-75f8-82a0-7d8078979000/runtime.json +15 -0
  117. package/.ikie/ferments/019f2740-cc58-765b-9f0c-c3aa2e09f27b/runtime.json +15 -0
  118. package/.ikie/ferments/019f2740-cc7c-7375-99b4-e90496e819e3/runtime.json +15 -0
  119. package/.ikie/ferments/019f2740-cca3-704a-bc20-e8c35cff6cec/runtime.json +15 -0
  120. package/.ikie/ferments/019f2740-ccd1-71cf-b8e8-be3527117f9a/runtime.json +15 -0
  121. package/.ikie/ferments/019f2740-cd0c-771f-ba4a-9188c31f3ee4/runtime.json +15 -0
  122. package/.ikie/ferments/019f2740-cd39-778e-a052-cc7f522f022d/runtime.json +11 -0
  123. package/.ikie/ferments/019f2740-cd5f-725e-8ec7-48a624398d2f/runtime.json +11 -0
  124. package/.ikie/ferments/019f2740-cd7f-713e-b20f-2321c13a86a8/reviews/phase-phase-1-1.json +63 -0
  125. package/.ikie/ferments/019f2740-cd7f-713e-b20f-2321c13a86a8/runtime.json +17 -0
  126. package/.ikie/ferments/019f2740-cf49-72fc-94b1-a262676c1136/reviews/phase-phase-1-1.json +63 -0
  127. package/.ikie/ferments/019f2740-cf49-72fc-94b1-a262676c1136/runtime.json +17 -0
  128. package/.ikie/ferments/019f2740-d16a-763d-b668-7c7cebc74c16/runtime.json +11 -0
  129. package/.ikie/ferments/019f2740-d675-747d-aa4c-b60d1616d218/runtime.json +11 -0
  130. package/.ikie/ferments/019f2740-d6ad-72de-bab7-e6344d568636/runtime.json +11 -0
  131. package/.ikie/ferments/019f2740-d6db-751a-bf3b-09d1c7ba989b/runtime.json +11 -0
  132. package/.ikie/ferments/019f2740-d712-75c8-b209-efc11bb1a22a/runtime.json +11 -0
  133. package/.ikie/ferments/019f2740-d745-764f-b758-99b0df2d6c01/pending-proposal.json +45 -0
  134. package/.ikie/ferments/019f2740-d76b-74a8-94c1-3d0cabd8cacf/pending-proposal.json +45 -0
  135. package/.ikie/ferments/019f2740-d88d-722b-8265-c8b89e1e59db/pending-proposal.json +45 -0
  136. package/.ikie/ferments/019f2740-d8f6-756a-b704-8a64a28290e8/pending-proposal.json +45 -0
  137. package/.ikie/ferments/019f2740-d90b-730f-87b9-85bee8e00a55/pending-proposal.json +45 -0
  138. package/.ikie/ferments/019f2740-f11f-76ff-9bd0-1e449804cc12/runtime.json +13 -0
  139. package/.ikie/ferments/019f2740-f155-767e-96db-6cf60c8b8dc1/runtime.json +11 -0
  140. package/.ikie/ferments/019f2740-f172-755f-a741-8e55858f5362/runtime.json +11 -0
  141. package/.ikie/ferments/019f2740-f18f-7328-b679-49f91b3c558c/runtime.json +11 -0
  142. package/.ikie/ferments/019f2740-f1b4-7289-b2f3-46f2bedf0e8f/runtime.json +11 -0
  143. package/.ikie/ferments/019f2740-f1dc-769b-bfe1-abcbcfd8ff2f/runtime.json +11 -0
  144. package/.ikie/ferments/019f2740-f1ed-760b-91dc-3bf7950fc112/runtime.json +11 -0
  145. package/.ikie/ferments/019f2740-f1fd-72dd-9c40-e6ab17b819ef/runtime.json +11 -0
  146. package/.ikie/ferments/019f2740-f23d-7588-95af-66be8cae9529/runtime.json +9 -0
  147. package/.ikie/ferments/019f2740-f269-7334-9c82-6554d9fc595a/runtime.json +13 -0
  148. package/.ikie/ferments/019f2740-f2bf-7147-9e68-cd8cb74d1604/runtime.json +11 -0
  149. package/.ikie/ferments/019f2740-f2f3-73db-9542-23a91c3632e5/runtime.json +11 -0
  150. package/.ikie/ferments/019f2740-f387-77e6-99f2-7cabb6f1ef37/runtime.json +11 -0
  151. package/.ikie/ferments/019f2740-f3af-722d-92a8-b49ab2e974fd/runtime.json +9 -0
  152. package/.ikie/ferments/019f2740-f3e6-7142-870c-ec1ee626cef4/runtime.json +9 -0
  153. package/.ikie/ferments/019f2740-f408-74f3-b1a2-3187af4e7bf8/runtime.json +11 -0
  154. package/.ikie/ferments/019f2740-f535-7419-8dc5-3c00bfeb566e/runtime.json +11 -0
  155. package/.ikie/ferments/019f2740-f546-7749-b0bd-cc0ec724f9c4/runtime.json +12 -0
  156. package/.ikie/ferments/019f2740-f576-7649-a468-cc473a719123/runtime.json +11 -0
  157. package/.ikie/ferments/019f2740-f599-7239-aa50-4bde87b6fe17/runtime.json +11 -0
  158. package/.ikie/ferments/019f2740-f5b8-7236-9b88-a0abe214d6b6/runtime.json +11 -0
  159. package/.ikie/ferments/019f2740-f5d1-73fc-9eea-06cf527069f2/runtime.json +11 -0
  160. package/.ikie/ferments/019f2740-f5fb-757e-b89e-52aeb00d53a0/runtime.json +13 -0
  161. package/.ikie/ferments/019f2740-f616-7770-96df-c4d02e293b96/runtime.json +11 -0
  162. package/.ikie/ferments/019f2741-09b2-777a-960c-544786151af2/reviews/phase-phase-1-1.json +41 -0
  163. package/.ikie/ferments/019f2741-09b2-777a-960c-544786151af2/runtime.json +11 -0
  164. package/.ikie/ferments/019f2741-0a0a-735a-b158-6a1f99b53082/reviews/phase-phase-1-1.json +47 -0
  165. package/.ikie/ferments/019f2741-0a0a-735a-b158-6a1f99b53082/runtime.json +13 -0
  166. package/.ikie/ferments/019f2741-0a87-74ec-bcb1-e88127e8739b/reviews/phase-phase-1-1.json +40 -0
  167. package/.ikie/ferments/019f2741-0a87-74ec-bcb1-e88127e8739b/runtime.json +9 -0
  168. package/.ikie/ferments/019f2741-0aaa-7399-905b-0c8f62000e15/reviews/phase-phase-1-1.json +40 -0
  169. package/.ikie/ferments/019f2741-0aaa-7399-905b-0c8f62000e15/runtime.json +9 -0
  170. package/.ikie/ferments/019f2741-0acc-7062-86e9-0d2d365446d9/reviews/phase-phase-1-1.json +40 -0
  171. package/.ikie/ferments/019f2741-0acc-7062-86e9-0d2d365446d9/runtime.json +9 -0
  172. package/.ikie/ferments/019f2741-0b14-709e-a5aa-80efb5a3c7d7/reviews/phase-phase-1-1.json +40 -0
  173. package/.ikie/ferments/019f2741-0b14-709e-a5aa-80efb5a3c7d7/runtime.json +9 -0
  174. package/.ikie/ferments/019f2741-0b3d-77ed-bdd9-322103b094e2/reviews/phase-phase-1-1.json +40 -0
  175. package/.ikie/ferments/019f2741-0b3d-77ed-bdd9-322103b094e2/runtime.json +9 -0
  176. package/.ikie/ferments/019f2741-0b7b-70ab-b3d6-ada61a3e0a92/reviews/phase-phase-1-1.json +62 -0
  177. package/.ikie/ferments/019f2741-0b7b-70ab-b3d6-ada61a3e0a92/runtime.json +9 -0
  178. package/.ikie/ferments/019f2742-b177-74a8-90f2-c1130a6ddae7/runtime.json +11 -0
  179. package/.ikie/ferments/019f2742-b193-72cf-9826-86ede671e061/runtime.json +11 -0
  180. package/.ikie/ferments/019f2742-b1af-76d9-972c-b67a2f5854d1/runtime.json +11 -0
  181. package/.ikie/ferments/019f2742-b1de-763e-8e31-a14505f9b64d/runtime.json +12 -0
  182. package/.ikie/ferments/019f2742-b25b-71fe-81de-89fc3b431b39/runtime.json +11 -0
  183. package/.ikie/ferments/019f2742-b291-7078-ba58-d4b50df3dd81/runtime.json +15 -0
  184. package/.ikie/ferments/019f2742-b2db-71a8-9d5d-da4bccc3e572/runtime.json +15 -0
  185. package/.ikie/ferments/019f2742-b305-7323-86c6-39adaa181f18/runtime.json +15 -0
  186. package/.ikie/ferments/019f2742-b330-77ad-9315-8ca801c973e8/runtime.json +13 -0
  187. package/.ikie/ferments/019f2742-b377-703f-9781-394729f9fe89/runtime.json +15 -0
  188. package/.ikie/ferments/019f2742-b3af-75aa-9bb7-750cb6af56e4/runtime.json +15 -0
  189. package/.ikie/ferments/019f2742-b3fb-7159-a969-be0073f90b6d/runtime.json +11 -0
  190. package/.ikie/ferments/019f2742-b41a-730e-ae6e-89421276e69d/runtime.json +15 -0
  191. package/.ikie/ferments/019f2742-b44e-75ec-824c-f6b77f643438/runtime.json +15 -0
  192. package/.ikie/ferments/019f2742-b47d-70c6-af2f-04922c1aef02/runtime.json +15 -0
  193. package/.ikie/ferments/019f2742-b4ad-748b-86db-3c8ae8907dbc/runtime.json +15 -0
  194. package/.ikie/ferments/019f2742-b4d5-72ff-a1b0-0da356ab94e6/runtime.json +15 -0
  195. package/.ikie/ferments/019f2742-b508-71fd-8181-7bb013178e5e/runtime.json +15 -0
  196. package/.ikie/ferments/019f2742-b536-7129-8b5c-2e132b38a98e/runtime.json +15 -0
  197. package/.ikie/ferments/019f2742-b55d-738b-8663-88a05c1e44b5/runtime.json +15 -0
  198. package/.ikie/ferments/019f2742-b587-714c-b043-f0a553a22404/runtime.json +15 -0
  199. package/.ikie/ferments/019f2742-b5b5-74ff-a850-a24ff317c1df/runtime.json +11 -0
  200. package/.ikie/ferments/019f2742-b5f5-72ba-b6b8-a4d62df39a2c/runtime.json +11 -0
  201. package/.ikie/ferments/019f2742-b621-7530-8e63-d252ae47ffd6/reviews/phase-phase-1-1.json +63 -0
  202. package/.ikie/ferments/019f2742-b621-7530-8e63-d252ae47ffd6/runtime.json +17 -0
  203. package/.ikie/ferments/019f2742-b7c0-756d-8014-e96fec9713ee/reviews/phase-phase-1-1.json +63 -0
  204. package/.ikie/ferments/019f2742-b7c0-756d-8014-e96fec9713ee/runtime.json +17 -0
  205. package/.ikie/ferments/019f2742-b95b-76bb-a4a6-e5cc31788fe3/runtime.json +11 -0
  206. package/.ikie/ferments/019f2742-be6b-759b-ba34-29d0245dc929/runtime.json +11 -0
  207. package/.ikie/ferments/019f2742-be98-73ba-aac5-07ad4f7d887d/runtime.json +11 -0
  208. package/.ikie/ferments/019f2742-beba-703c-aadb-32c590404bfa/runtime.json +11 -0
  209. package/.ikie/ferments/019f2742-bee0-76ad-9e47-81cff634877f/runtime.json +11 -0
  210. package/.ikie/ferments/019f2742-bf10-742f-a792-7aa3836d81ad/pending-proposal.json +45 -0
  211. package/.ikie/ferments/019f2742-bf36-779c-b126-2ccb8ec97138/pending-proposal.json +45 -0
  212. package/.ikie/ferments/019f2742-c098-74ee-9a07-575f50989d9f/pending-proposal.json +45 -0
  213. package/.ikie/ferments/019f2742-c135-74fe-aefa-d1a5db536132/pending-proposal.json +45 -0
  214. package/.ikie/ferments/019f2742-c19a-779c-a175-27330932470d/pending-proposal.json +45 -0
  215. package/.ikie/ferments/019f2742-db2a-745f-b7c8-8fb383e044e7/runtime.json +13 -0
  216. package/.ikie/ferments/019f2742-db83-77ac-b1d2-a422571fbcf6/runtime.json +11 -0
  217. package/.ikie/ferments/019f2742-dba7-779e-9560-7df90ddab3c4/runtime.json +11 -0
  218. package/.ikie/ferments/019f2742-dbd2-740c-9f94-9f313c07ee52/runtime.json +11 -0
  219. package/.ikie/ferments/019f2742-dbfb-77b3-8e3f-b0d20bd29689/runtime.json +11 -0
  220. package/.ikie/ferments/019f2742-dc10-769d-b9a2-bab4851f5cf5/runtime.json +11 -0
  221. package/.ikie/ferments/019f2742-dc23-7235-a215-8b86d261566a/runtime.json +11 -0
  222. package/.ikie/ferments/019f2742-dc37-762d-a5da-87ff3f2206b0/runtime.json +11 -0
  223. package/.ikie/ferments/019f2742-dc65-73c8-aa07-f803b1066c8b/runtime.json +9 -0
  224. package/.ikie/ferments/019f2742-dc91-7165-bbfe-4659f754c4a6/runtime.json +13 -0
  225. package/.ikie/ferments/019f2742-dcd1-7252-ad9b-12c0dab633e6/runtime.json +11 -0
  226. package/.ikie/ferments/019f2742-dceb-75ba-b8cb-557e60aa4a9b/runtime.json +11 -0
  227. package/.ikie/ferments/019f2742-dd2f-77a6-b71c-a9543ac1145f/runtime.json +11 -0
  228. package/.ikie/ferments/019f2742-dd6a-70ab-aff3-ae678e8be52f/runtime.json +9 -0
  229. package/.ikie/ferments/019f2742-dd85-7529-90c0-2cb497df7711/runtime.json +9 -0
  230. package/.ikie/ferments/019f2742-dda0-715e-ae24-693bfa79f191/runtime.json +11 -0
  231. package/.ikie/ferments/019f2742-deb9-7319-9599-d96743413a8c/runtime.json +11 -0
  232. package/.ikie/ferments/019f2742-dee3-705e-9550-b7701bc8dfbf/runtime.json +12 -0
  233. package/.ikie/ferments/019f2742-df10-71bf-8ac0-8e4a8c40cfa8/runtime.json +11 -0
  234. package/.ikie/ferments/019f2742-df29-735f-817c-2819becd5092/runtime.json +11 -0
  235. package/.ikie/ferments/019f2742-df46-7592-b070-7bdf50095ce2/runtime.json +11 -0
  236. package/.ikie/ferments/019f2742-df66-75e4-9926-4d5dacd457f4/runtime.json +11 -0
  237. package/.ikie/ferments/019f2742-df96-71c4-973e-045dc4f272e0/runtime.json +13 -0
  238. package/.ikie/ferments/019f2742-dfca-7353-bfd3-f010ec0726e8/runtime.json +11 -0
  239. package/.ikie/ferments/019f2742-f0fb-77cb-9a95-25a7231702b7/reviews/phase-phase-1-1.json +41 -0
  240. package/.ikie/ferments/019f2742-f0fb-77cb-9a95-25a7231702b7/runtime.json +11 -0
  241. package/.ikie/ferments/019f2742-f145-77ec-a4c7-fafd1605d492/reviews/phase-phase-1-1.json +47 -0
  242. package/.ikie/ferments/019f2742-f145-77ec-a4c7-fafd1605d492/runtime.json +13 -0
  243. package/.ikie/ferments/019f2742-f1dc-74bd-8452-067d9c1b909d/reviews/phase-phase-1-1.json +40 -0
  244. package/.ikie/ferments/019f2742-f1dc-74bd-8452-067d9c1b909d/runtime.json +9 -0
  245. package/.ikie/ferments/019f2742-f1fd-745d-b989-9a2d3ec7594d/reviews/phase-phase-1-1.json +40 -0
  246. package/.ikie/ferments/019f2742-f1fd-745d-b989-9a2d3ec7594d/runtime.json +9 -0
  247. package/.ikie/ferments/019f2742-f21a-7398-9190-8bba01c6248e/reviews/phase-phase-1-1.json +40 -0
  248. package/.ikie/ferments/019f2742-f21a-7398-9190-8bba01c6248e/runtime.json +9 -0
  249. package/.ikie/ferments/019f2742-f23a-73b1-89d2-1272093e6d2d/reviews/phase-phase-1-1.json +40 -0
  250. package/.ikie/ferments/019f2742-f23a-73b1-89d2-1272093e6d2d/runtime.json +9 -0
  251. package/.ikie/ferments/019f2742-f25c-74d1-80b3-129a992edd3f/reviews/phase-phase-1-1.json +40 -0
  252. package/.ikie/ferments/019f2742-f25c-74d1-80b3-129a992edd3f/runtime.json +9 -0
  253. package/.ikie/ferments/019f2742-f285-708d-bdd2-c2875cc16158/reviews/phase-phase-1-1.json +62 -0
  254. package/.ikie/ferments/019f2742-f285-708d-bdd2-c2875cc16158/runtime.json +9 -0
  255. package/.ikie/ferments/019f2745-3a6e-7769-8da0-1994b591349d/runtime.json +11 -0
  256. package/.ikie/ferments/019f2745-3a8c-74db-bd6b-b4a1164b381a/runtime.json +11 -0
  257. package/.ikie/ferments/019f2745-3aad-7249-b742-f1e6722d5c97/runtime.json +11 -0
  258. package/.ikie/ferments/019f2745-3ae9-76fb-861c-49f13c1db883/runtime.json +12 -0
  259. package/.ikie/ferments/019f2745-3b16-721b-b523-469846e0c9e5/runtime.json +11 -0
  260. package/.ikie/ferments/019f2745-3b53-7119-ae88-20cf3d567e91/runtime.json +11 -0
  261. package/.ikie/ferments/019f2745-3ba2-71b6-9fab-faaf750f8535/runtime.json +15 -0
  262. package/.ikie/ferments/019f2745-3bed-764b-9b4b-79b4d7daa35d/runtime.json +15 -0
  263. package/.ikie/ferments/019f2745-3c3e-7792-8df7-d88bab7aa48d/runtime.json +15 -0
  264. package/.ikie/ferments/019f2745-3c81-770d-bcf9-6d163ffeb285/runtime.json +13 -0
  265. package/.ikie/ferments/019f2745-3cca-748d-9740-8c55644c9afa/runtime.json +15 -0
  266. package/.ikie/ferments/019f2745-3d12-71cc-923f-520142ddf544/runtime.json +15 -0
  267. package/.ikie/ferments/019f2745-3d79-7083-8865-8f54989080e0/runtime.json +11 -0
  268. package/.ikie/ferments/019f2745-3da9-74f9-a640-86b4685f40a0/runtime.json +15 -0
  269. package/.ikie/ferments/019f2745-3ddf-721b-8a40-3a2318b6bc0a/runtime.json +15 -0
  270. package/.ikie/ferments/019f2745-3e2a-76a8-8c61-ef15db41aef2/runtime.json +15 -0
  271. package/.ikie/ferments/019f2745-3e5d-75bb-ab71-b4aa83c491b7/runtime.json +15 -0
  272. package/.ikie/ferments/019f2745-3e7e-7437-848a-100463c72f90/runtime.json +15 -0
  273. package/.ikie/ferments/019f2745-3ea7-7729-9000-7874145f4bb5/runtime.json +15 -0
  274. package/.ikie/ferments/019f2745-3ecf-760c-931c-3dc5996b06b1/runtime.json +15 -0
  275. package/.ikie/ferments/019f2745-3f05-72d8-ad71-d1df02c5939a/runtime.json +15 -0
  276. package/.ikie/ferments/019f2745-3f37-74ad-9e02-6e0d3854b664/runtime.json +15 -0
  277. package/.ikie/ferments/019f2745-3f65-740d-8094-58f60c9cdcec/runtime.json +11 -0
  278. package/.ikie/ferments/019f2745-3f91-7219-8eec-f5f7873a434a/runtime.json +11 -0
  279. package/.ikie/ferments/019f2745-3fc5-706a-8188-5a3b4e13a796/reviews/phase-phase-1-1.json +63 -0
  280. package/.ikie/ferments/019f2745-3fc5-706a-8188-5a3b4e13a796/runtime.json +17 -0
  281. package/.ikie/ferments/019f2745-417c-77ad-bdaf-380b81846577/reviews/phase-phase-1-1.json +63 -0
  282. package/.ikie/ferments/019f2745-417c-77ad-bdaf-380b81846577/runtime.json +17 -0
  283. package/.ikie/ferments/019f2745-4372-72ff-a50c-3eaad36a726b/runtime.json +11 -0
  284. package/.ikie/ferments/019f2745-4859-714b-a8b7-0a82d35b87c7/runtime.json +11 -0
  285. package/.ikie/ferments/019f2745-488a-724f-91a9-d621e9f2b3f7/runtime.json +11 -0
  286. package/.ikie/ferments/019f2745-48ae-7741-8598-03ede47b4594/runtime.json +11 -0
  287. package/.ikie/ferments/019f2745-48e9-710f-889b-e88aa5d7e60e/runtime.json +11 -0
  288. package/.ikie/ferments/019f2745-4917-7268-9b76-f8bb1215ea19/pending-proposal.json +45 -0
  289. package/.ikie/ferments/019f2745-493c-775d-a10d-4a2cf8305a4e/pending-proposal.json +45 -0
  290. package/.ikie/ferments/019f2745-4abd-7319-9e11-4b348ab24547/pending-proposal.json +45 -0
  291. package/.ikie/ferments/019f2745-4b10-726d-ad1f-c086e7d4dfc0/pending-proposal.json +45 -0
  292. package/.ikie/ferments/019f2745-4b21-75a6-b151-472f4eb9b95d/pending-proposal.json +45 -0
  293. package/.ikie/ferments/019f2745-5dd5-741b-85e2-1d67ce09a138/runtime.json +13 -0
  294. package/.ikie/ferments/019f2745-5e14-73dd-bd03-3b5765f70fac/runtime.json +11 -0
  295. package/.ikie/ferments/019f2745-5e2e-70b5-9348-35ebbdb8ec8e/runtime.json +11 -0
  296. package/.ikie/ferments/019f2745-5e4f-7626-b075-6b6d30099847/runtime.json +11 -0
  297. package/.ikie/ferments/019f2745-5e71-7768-b436-e739555f1038/runtime.json +11 -0
  298. package/.ikie/ferments/019f2745-5e8a-77c5-ba98-cb2802c55266/runtime.json +11 -0
  299. package/.ikie/ferments/019f2745-5ea8-707f-b034-9c98e6ca720b/runtime.json +11 -0
  300. package/.ikie/ferments/019f2745-5ebd-73aa-a919-150c9bb014f9/runtime.json +11 -0
  301. package/.ikie/ferments/019f2745-5ed6-71e9-9a20-360fa807f598/runtime.json +9 -0
  302. package/.ikie/ferments/019f2745-5ef8-7199-bd13-69b5c883541b/runtime.json +13 -0
  303. package/.ikie/ferments/019f2745-5f30-73f9-a647-9e7518599c32/runtime.json +11 -0
  304. package/.ikie/ferments/019f2745-5f53-7358-897a-37717d64d996/runtime.json +11 -0
  305. package/.ikie/ferments/019f2745-5fb6-736b-b42d-bbc3c1916321/runtime.json +11 -0
  306. package/.ikie/ferments/019f2745-5fea-730e-b57b-d7f1965d5934/runtime.json +9 -0
  307. package/.ikie/ferments/019f2745-6014-77cb-b01f-d93baf8af409/runtime.json +9 -0
  308. package/.ikie/ferments/019f2745-602f-74b9-8eed-bb29fa4a76d4/runtime.json +11 -0
  309. package/.ikie/ferments/019f2745-60e2-7562-8e7c-2ded6cf75426/runtime.json +11 -0
  310. package/.ikie/ferments/019f2745-6114-703e-ac05-5ba11b255b62/runtime.json +12 -0
  311. package/.ikie/ferments/019f2745-6160-733e-93f5-df586c6afc0a/runtime.json +11 -0
  312. package/.ikie/ferments/019f2745-6179-702b-84fb-09bc60f8c04c/runtime.json +11 -0
  313. package/.ikie/ferments/019f2745-618d-74dc-a174-28a134d353fa/runtime.json +11 -0
  314. package/.ikie/ferments/019f2745-619e-72a8-8377-34127bfc774f/runtime.json +11 -0
  315. package/.ikie/ferments/019f2745-61ae-767e-8a2e-a5ca6bc84a88/runtime.json +13 -0
  316. package/.ikie/ferments/019f2745-61c7-760c-9914-a9bf3c96acd8/runtime.json +11 -0
  317. package/.ikie/ferments/019f2745-79a2-70b8-bcd0-fbaee13849db/reviews/phase-phase-1-1.json +41 -0
  318. package/.ikie/ferments/019f2745-79a2-70b8-bcd0-fbaee13849db/runtime.json +11 -0
  319. package/.ikie/ferments/019f2745-79e7-74d5-b867-e23b027a8512/reviews/phase-phase-1-1.json +47 -0
  320. package/.ikie/ferments/019f2745-79e7-74d5-b867-e23b027a8512/runtime.json +13 -0
  321. package/.ikie/ferments/019f2745-7a5b-703e-999e-dd5cb98133eb/reviews/phase-phase-1-1.json +40 -0
  322. package/.ikie/ferments/019f2745-7a5b-703e-999e-dd5cb98133eb/runtime.json +9 -0
  323. package/.ikie/ferments/019f2745-7a90-732a-b09a-9aa29e2390cd/reviews/phase-phase-1-1.json +40 -0
  324. package/.ikie/ferments/019f2745-7a90-732a-b09a-9aa29e2390cd/runtime.json +9 -0
  325. package/.ikie/ferments/019f2745-7aad-731c-ac2a-cf71d20fb709/reviews/phase-phase-1-1.json +40 -0
  326. package/.ikie/ferments/019f2745-7aad-731c-ac2a-cf71d20fb709/runtime.json +9 -0
  327. package/.ikie/ferments/019f2745-7ad2-70ff-986b-83679208066a/reviews/phase-phase-1-1.json +40 -0
  328. package/.ikie/ferments/019f2745-7ad2-70ff-986b-83679208066a/runtime.json +9 -0
  329. package/.ikie/ferments/019f2745-7af8-735c-8200-f49b201f5b7f/reviews/phase-phase-1-1.json +40 -0
  330. package/.ikie/ferments/019f2745-7af8-735c-8200-f49b201f5b7f/runtime.json +9 -0
  331. package/.ikie/ferments/019f2745-7b17-7489-b4d5-b83e4feeb641/reviews/phase-phase-1-1.json +62 -0
  332. package/.ikie/ferments/019f2745-7b17-7489-b4d5-b83e4feeb641/runtime.json +9 -0
  333. package/.ikie/ferments/019f2747-700f-77dd-8fec-eec70eb204bf/runtime.json +11 -0
  334. package/.ikie/ferments/019f2747-702b-748d-83a8-a44d909b5d84/runtime.json +11 -0
  335. package/.ikie/ferments/019f2747-704a-77c6-a068-5eff8527f149/runtime.json +11 -0
  336. package/.ikie/ferments/019f2747-7075-7628-9088-9c79d85087be/runtime.json +12 -0
  337. package/.ikie/ferments/019f2747-70e4-7157-aa37-d8201f07134a/runtime.json +11 -0
  338. package/.ikie/ferments/019f2747-7139-74da-8f85-02b76ecfc932/runtime.json +15 -0
  339. package/.ikie/ferments/019f2747-7156-762f-8c31-84ae357e2edd/runtime.json +15 -0
  340. package/.ikie/ferments/019f2747-7175-76e7-9d21-15608a6463ca/runtime.json +15 -0
  341. package/.ikie/ferments/019f2747-71c8-777c-8106-df11073ad85f/runtime.json +13 -0
  342. package/.ikie/ferments/019f2747-7209-71f5-8f4e-ccfd46653321/runtime.json +15 -0
  343. package/.ikie/ferments/019f2747-723d-728f-baa8-dd3b4b239037/runtime.json +15 -0
  344. package/.ikie/ferments/019f2747-728d-749b-9e9a-962ea824d13d/runtime.json +11 -0
  345. package/.ikie/ferments/019f2747-72b0-756e-b648-c5491d46dc37/runtime.json +15 -0
  346. package/.ikie/ferments/019f2747-72e8-747e-9e5b-93005dd51d36/runtime.json +15 -0
  347. package/.ikie/ferments/019f2747-7319-702b-84bd-aed70c3f60c3/runtime.json +15 -0
  348. package/.ikie/ferments/019f2747-734a-732c-89d8-47fa74a13f6b/runtime.json +15 -0
  349. package/.ikie/ferments/019f2747-7372-72ce-99d0-ddeeb20c73e5/runtime.json +15 -0
  350. package/.ikie/ferments/019f2747-73a1-723d-b064-2240965b5460/runtime.json +15 -0
  351. package/.ikie/ferments/019f2747-73cd-71b5-9b21-481224573278/runtime.json +15 -0
  352. package/.ikie/ferments/019f2747-73f7-779f-a227-64ba479c2615/runtime.json +15 -0
  353. package/.ikie/ferments/019f2747-743e-759e-856b-283e346eec66/runtime.json +15 -0
  354. package/.ikie/ferments/019f2747-74ac-702b-877f-1b4447f77938/runtime.json +11 -0
  355. package/.ikie/ferments/019f2747-74cc-773a-ad3a-febf5e9e5a57/runtime.json +11 -0
  356. package/.ikie/ferments/019f2747-750b-77dc-aa24-230eef901e40/reviews/phase-phase-1-1.json +63 -0
  357. package/.ikie/ferments/019f2747-750b-77dc-aa24-230eef901e40/runtime.json +17 -0
  358. package/.ikie/ferments/019f2747-76f2-72c9-8764-82fdd0429215/reviews/phase-phase-1-1.json +63 -0
  359. package/.ikie/ferments/019f2747-76f2-72c9-8764-82fdd0429215/runtime.json +17 -0
  360. package/.ikie/ferments/019f2747-795d-7452-9810-a64e86f3d5c5/runtime.json +11 -0
  361. package/.ikie/ferments/019f2747-7ee1-770e-ace1-bc0f5571f69a/runtime.json +11 -0
  362. package/.ikie/ferments/019f2747-7f01-738d-a2a2-c7aa33365582/runtime.json +11 -0
  363. package/.ikie/ferments/019f2747-7f40-712b-bea9-8a20399c9dfd/runtime.json +11 -0
  364. package/.ikie/ferments/019f2747-7fb4-70c9-aaf6-af4ac5fbebef/runtime.json +11 -0
  365. package/.ikie/ferments/019f2747-7fe2-77e7-90d5-dcee3cbe73ea/pending-proposal.json +45 -0
  366. package/.ikie/ferments/019f2747-7ff9-7028-ac25-77ab9c513710/pending-proposal.json +45 -0
  367. package/.ikie/ferments/019f2747-81c3-7320-8a96-88880d06cc14/pending-proposal.json +45 -0
  368. package/.ikie/ferments/019f2747-8236-76c0-b17c-1f13a22af974/pending-proposal.json +45 -0
  369. package/.ikie/ferments/019f2747-824b-77ba-90bd-67bcb4e9d5d6/pending-proposal.json +45 -0
  370. package/.ikie/ferments/019f2747-a18a-77f4-802d-18ab07f51261/runtime.json +13 -0
  371. package/.ikie/ferments/019f2747-a1b6-76cf-9688-94e8f41b179f/runtime.json +11 -0
  372. package/.ikie/ferments/019f2747-a1e2-730b-a56d-cb622d190c49/runtime.json +11 -0
  373. package/.ikie/ferments/019f2747-a20b-739e-a524-b5b2cdabdf49/runtime.json +11 -0
  374. package/.ikie/ferments/019f2747-a228-7026-9fe2-79fc90d7c622/runtime.json +11 -0
  375. package/.ikie/ferments/019f2747-a244-71b5-8ceb-d6094c7a5d28/runtime.json +11 -0
  376. package/.ikie/ferments/019f2747-a25d-723e-9962-ed1f266a9709/runtime.json +11 -0
  377. package/.ikie/ferments/019f2747-a275-734d-9ede-ae9644a179b6/runtime.json +11 -0
  378. package/.ikie/ferments/019f2747-a2a4-7280-b8c4-d8233d9e322a/runtime.json +9 -0
  379. package/.ikie/ferments/019f2747-a2ca-767d-8a35-9043b18e5ec7/runtime.json +13 -0
  380. package/.ikie/ferments/019f2747-a2f5-745d-929e-9fb2ef5d333f/runtime.json +11 -0
  381. package/.ikie/ferments/019f2747-a317-76b9-8954-2b7a4487a352/runtime.json +11 -0
  382. package/.ikie/ferments/019f2747-a380-7746-be44-cb9e1920561f/runtime.json +11 -0
  383. package/.ikie/ferments/019f2747-a3a2-77ac-9fe5-2a844b64872d/runtime.json +9 -0
  384. package/.ikie/ferments/019f2747-a3b7-70ee-ba83-b3c43d3122c8/runtime.json +9 -0
  385. package/.ikie/ferments/019f2747-a3e7-76e9-96f0-143c82d8005b/runtime.json +11 -0
  386. package/.ikie/ferments/019f2747-a4d3-737b-8d80-2dc63a0fbe1a/runtime.json +11 -0
  387. package/.ikie/ferments/019f2747-a506-7442-919f-50ae2b602e7a/runtime.json +12 -0
  388. package/.ikie/ferments/019f2747-a53e-76cb-9876-a81dd08e3fe7/runtime.json +11 -0
  389. package/.ikie/ferments/019f2747-a56a-7208-ad93-0fdcbc41c1ed/runtime.json +11 -0
  390. package/.ikie/ferments/019f2747-a581-73fc-aac5-a44f696ccbe8/runtime.json +11 -0
  391. package/.ikie/ferments/019f2747-a595-71d2-9c2d-d846e9803665/runtime.json +11 -0
  392. package/.ikie/ferments/019f2747-a5a7-73c6-b881-f9c0a08f3af3/runtime.json +13 -0
  393. package/.ikie/ferments/019f2747-a5be-7777-94c0-0849e693ffcb/runtime.json +11 -0
  394. package/.ikie/ferments/019f2747-b3e6-706a-912c-71d57080c7c1/reviews/phase-phase-1-1.json +41 -0
  395. package/.ikie/ferments/019f2747-b3e6-706a-912c-71d57080c7c1/runtime.json +11 -0
  396. package/.ikie/ferments/019f2747-b464-75bd-9c0b-c6b5e5de789e/reviews/phase-phase-1-1.json +47 -0
  397. package/.ikie/ferments/019f2747-b464-75bd-9c0b-c6b5e5de789e/runtime.json +13 -0
  398. package/.ikie/ferments/019f2747-b4f2-719c-86a6-763c494a680c/reviews/phase-phase-1-1.json +40 -0
  399. package/.ikie/ferments/019f2747-b4f2-719c-86a6-763c494a680c/runtime.json +9 -0
  400. package/.ikie/ferments/019f2747-b52b-75cd-b664-8c2aedd87893/reviews/phase-phase-1-1.json +40 -0
  401. package/.ikie/ferments/019f2747-b52b-75cd-b664-8c2aedd87893/runtime.json +9 -0
  402. package/.ikie/ferments/019f2747-b551-7188-81a3-7b7e8371aea4/reviews/phase-phase-1-1.json +40 -0
  403. package/.ikie/ferments/019f2747-b551-7188-81a3-7b7e8371aea4/runtime.json +9 -0
  404. package/.ikie/ferments/019f2747-b5a5-703f-98e6-5eac131044ed/reviews/phase-phase-1-1.json +40 -0
  405. package/.ikie/ferments/019f2747-b5a5-703f-98e6-5eac131044ed/runtime.json +9 -0
  406. package/.ikie/ferments/019f2747-b5cc-7560-80d8-509578bdae44/reviews/phase-phase-1-1.json +40 -0
  407. package/.ikie/ferments/019f2747-b5cc-7560-80d8-509578bdae44/runtime.json +9 -0
  408. package/.ikie/ferments/019f2747-b5f7-7079-ba17-833018701a06/reviews/phase-phase-1-1.json +62 -0
  409. package/.ikie/ferments/019f2747-b5f7-7079-ba17-833018701a06/runtime.json +9 -0
  410. package/.ikie/ferments/019f274a-bb4e-77b1-9f03-633b22b8e54c/runtime.json +11 -0
  411. package/.ikie/ferments/019f274a-bb6e-7715-92a0-c73da2ff97da/runtime.json +11 -0
  412. package/.ikie/ferments/019f274a-bb89-75b5-9daa-c57ef85c64c1/runtime.json +11 -0
  413. package/.ikie/ferments/019f274a-bbb7-72ad-9695-3227786b16ef/runtime.json +12 -0
  414. package/.ikie/ferments/019f274a-bbfb-70da-95f3-54a3e507888d/runtime.json +11 -0
  415. package/.ikie/ferments/019f274a-bc37-771a-8e77-b8d5476a8a1e/runtime.json +15 -0
  416. package/.ikie/ferments/019f274a-bc61-7024-9311-148a94a6713e/runtime.json +15 -0
  417. package/.ikie/ferments/019f274a-bca0-76a9-b966-59bbe3fb5bdd/runtime.json +15 -0
  418. package/.ikie/ferments/019f274a-bcc9-774d-adc2-aa99e82abb79/runtime.json +13 -0
  419. package/.ikie/ferments/019f274a-bcfb-737e-9c7d-b9db4762b624/runtime.json +15 -0
  420. package/.ikie/ferments/019f274a-bd3f-725b-9d39-b672191556ac/runtime.json +15 -0
  421. package/.ikie/ferments/019f274a-bd82-75a8-b936-350a55a7a1da/runtime.json +11 -0
  422. package/.ikie/ferments/019f274a-bda4-71b2-aa8b-7ba6f6103814/runtime.json +15 -0
  423. package/.ikie/ferments/019f274a-bddc-70ff-90f8-f1648dede718/runtime.json +15 -0
  424. package/.ikie/ferments/019f274a-be12-70bd-b935-0173946e60c2/runtime.json +15 -0
  425. package/.ikie/ferments/019f274a-be51-7719-b04b-d720a1d215f7/runtime.json +15 -0
  426. package/.ikie/ferments/019f274a-be8c-7084-aa78-4d139084333b/runtime.json +15 -0
  427. package/.ikie/ferments/019f274a-bebc-70b7-8c8d-fc7b50eda266/runtime.json +15 -0
  428. package/.ikie/ferments/019f274a-bee6-732f-b9ee-9fb3f1966e3d/runtime.json +15 -0
  429. package/.ikie/ferments/019f274a-bf19-76bc-8ab4-fe8c3fb28875/runtime.json +15 -0
  430. package/.ikie/ferments/019f274a-bf40-755b-bd4f-eec6d8e7a4de/runtime.json +15 -0
  431. package/.ikie/ferments/019f274a-bf74-7013-beb9-08aab0dc8866/runtime.json +11 -0
  432. package/.ikie/ferments/019f274a-bfa3-718d-ab5d-ededc4cf9e63/runtime.json +11 -0
  433. package/.ikie/ferments/019f274a-bfd6-7689-b29b-2c3ebfe1afd3/reviews/phase-phase-1-1.json +63 -0
  434. package/.ikie/ferments/019f274a-bfd6-7689-b29b-2c3ebfe1afd3/runtime.json +17 -0
  435. package/.ikie/ferments/019f274a-c186-77ea-a92c-78fa52657710/reviews/phase-phase-1-1.json +63 -0
  436. package/.ikie/ferments/019f274a-c186-77ea-a92c-78fa52657710/runtime.json +17 -0
  437. package/.ikie/ferments/019f274a-c3cf-77e8-9917-76d94992456a/runtime.json +11 -0
  438. package/.ikie/ferments/019f274a-c8eb-7071-9900-1668ccf13dad/runtime.json +11 -0
  439. package/.ikie/ferments/019f274a-c928-7276-9fd8-c8fdfbd215ff/runtime.json +11 -0
  440. package/.ikie/ferments/019f274a-c957-7698-8a97-54584a38f472/runtime.json +11 -0
  441. package/.ikie/ferments/019f274a-c97f-71b5-8fd9-727b49c9b72c/runtime.json +11 -0
  442. package/.ikie/ferments/019f274a-c9ad-76bb-99f8-b8f7840ad3ab/pending-proposal.json +45 -0
  443. package/.ikie/ferments/019f274a-c9cf-73ad-8229-d03bd5389697/pending-proposal.json +45 -0
  444. package/.ikie/ferments/019f274a-cb01-720a-b512-e49f820b9be5/pending-proposal.json +45 -0
  445. package/.ikie/ferments/019f274a-cbba-764d-a8e7-da6a060d9cd1/pending-proposal.json +45 -0
  446. package/.ikie/ferments/019f274a-cbdd-744f-84e9-af64527ff116/pending-proposal.json +45 -0
  447. package/.ikie/ferments/019f274a-efc1-75b6-ad54-83a9fcb061af/runtime.json +13 -0
  448. package/.ikie/ferments/019f274a-effe-713a-9672-ca8c839b0936/runtime.json +11 -0
  449. package/.ikie/ferments/019f274a-f03c-7194-b9e6-a24620ef1b89/runtime.json +11 -0
  450. package/.ikie/ferments/019f274a-f058-758c-9ecf-f6af131a0798/runtime.json +11 -0
  451. package/.ikie/ferments/019f274a-f06e-712d-b720-09a6188a152a/runtime.json +11 -0
  452. package/.ikie/ferments/019f274a-f085-715e-8b5b-07587107bc86/runtime.json +11 -0
  453. package/.ikie/ferments/019f274a-f0a8-755b-b747-adaa0f997d8a/runtime.json +11 -0
  454. package/.ikie/ferments/019f274a-f0cd-765c-90ce-48685c67299c/runtime.json +11 -0
  455. package/.ikie/ferments/019f274a-f0e1-71a8-bafc-cc3eeff4f275/runtime.json +9 -0
  456. package/.ikie/ferments/019f274a-f104-73c0-be62-16f724e0d4c6/runtime.json +13 -0
  457. package/.ikie/ferments/019f274a-f129-70ea-aa16-254d0fc662bf/runtime.json +11 -0
  458. package/.ikie/ferments/019f274a-f14b-7742-8e88-7a3fe9d16f08/runtime.json +11 -0
  459. package/.ikie/ferments/019f274a-f18b-7148-afb1-b9ff1ab54bbc/runtime.json +11 -0
  460. package/.ikie/ferments/019f274a-f1a2-734d-bf87-6f80955a3b64/runtime.json +9 -0
  461. package/.ikie/ferments/019f274a-f1c0-75a7-8675-f4fcf15df9bd/runtime.json +9 -0
  462. package/.ikie/ferments/019f274a-f1e2-7346-b97f-9340f86e6397/runtime.json +11 -0
  463. package/.ikie/ferments/019f274a-f2a1-7758-a891-413d15c9c29c/runtime.json +11 -0
  464. package/.ikie/ferments/019f274a-f2bc-76fd-b2dc-e14feea4fb86/runtime.json +12 -0
  465. package/.ikie/ferments/019f274a-f2e0-7474-97b8-79e01d130940/runtime.json +11 -0
  466. package/.ikie/ferments/019f274a-f2fa-70fb-a2da-0fb3e9a729ef/runtime.json +11 -0
  467. package/.ikie/ferments/019f274a-f30f-71bc-bf7f-198ef4b68568/runtime.json +11 -0
  468. package/.ikie/ferments/019f274a-f326-768b-b55e-e340dd3bf7fc/runtime.json +11 -0
  469. package/.ikie/ferments/019f274a-f339-75a5-9d45-d9393ccf3436/runtime.json +13 -0
  470. package/.ikie/ferments/019f274a-f35b-7386-9eb0-8f1e45618131/runtime.json +11 -0
  471. package/.ikie/ferments/019f274a-f96b-7633-9b6d-6722ea8232a2/reviews/phase-phase-1-1.json +41 -0
  472. package/.ikie/ferments/019f274a-f96b-7633-9b6d-6722ea8232a2/runtime.json +11 -0
  473. package/.ikie/ferments/019f274a-f9b7-769e-94ac-8f5c7e23ee88/reviews/phase-phase-1-1.json +47 -0
  474. package/.ikie/ferments/019f274a-f9b7-769e-94ac-8f5c7e23ee88/runtime.json +13 -0
  475. package/.ikie/ferments/019f274a-fa07-70b1-bc68-1a9d3378deff/reviews/phase-phase-1-1.json +40 -0
  476. package/.ikie/ferments/019f274a-fa07-70b1-bc68-1a9d3378deff/runtime.json +9 -0
  477. package/.ikie/ferments/019f274a-fa2f-7658-86ad-cc69215f1c94/reviews/phase-phase-1-1.json +40 -0
  478. package/.ikie/ferments/019f274a-fa2f-7658-86ad-cc69215f1c94/runtime.json +9 -0
  479. package/.ikie/ferments/019f274a-fa46-72ca-a252-65a5b2995bc4/reviews/phase-phase-1-1.json +40 -0
  480. package/.ikie/ferments/019f274a-fa46-72ca-a252-65a5b2995bc4/runtime.json +9 -0
  481. package/.ikie/ferments/019f274a-fa70-705f-9112-d48e1042f1d4/reviews/phase-phase-1-1.json +40 -0
  482. package/.ikie/ferments/019f274a-fa70-705f-9112-d48e1042f1d4/runtime.json +9 -0
  483. package/.ikie/ferments/019f274a-fa94-73e5-9fc3-ea21ee5cfc59/reviews/phase-phase-1-1.json +40 -0
  484. package/.ikie/ferments/019f274a-fa94-73e5-9fc3-ea21ee5cfc59/runtime.json +9 -0
  485. package/.ikie/ferments/019f274a-fab9-720d-9ce3-0041a27f83e0/reviews/phase-phase-1-1.json +62 -0
  486. package/.ikie/ferments/019f274a-fab9-720d-9ce3-0041a27f83e0/runtime.json +9 -0
  487. package/.ikie/ferments/019f274c-7608-76f8-89c7-6e3b7d9095b2/runtime.json +11 -0
  488. package/.ikie/ferments/019f274c-762a-717c-9ec2-530d37897051/runtime.json +11 -0
  489. package/.ikie/ferments/019f274c-7644-76fc-a27d-c699d368a511/runtime.json +11 -0
  490. package/.ikie/ferments/019f274c-7667-7260-87b3-f2ad6ff10c04/runtime.json +12 -0
  491. package/.ikie/ferments/019f274c-7696-753f-8634-5cb24d2aabaa/runtime.json +11 -0
  492. package/.ikie/ferments/019f274c-76c8-76e8-b4d8-0cabd7f32047/runtime.json +15 -0
  493. package/.ikie/ferments/019f274c-76f5-732e-88f3-0461f79b7733/runtime.json +15 -0
  494. package/.ikie/ferments/019f274c-771b-762e-abb6-1bfe6838545b/runtime.json +15 -0
  495. package/.ikie/ferments/019f274c-774a-769f-b15f-d36a990c8aa2/runtime.json +13 -0
  496. package/.ikie/ferments/019f274c-7791-7040-9c73-fe5922824edc/runtime.json +15 -0
  497. package/.ikie/ferments/019f274c-77c3-76f9-a5c6-e0f5030f615c/runtime.json +15 -0
  498. package/.ikie/ferments/019f274c-7805-70eb-ac17-888c2a0ab5cb/runtime.json +11 -0
  499. package/.ikie/ferments/019f274c-7820-71da-9baf-d7953b547620/runtime.json +15 -0
  500. package/.ikie/ferments/019f274c-7855-708f-bbe8-a9e13258cc98/runtime.json +15 -0
  501. package/.ikie/ferments/019f274c-7886-70fc-9572-b96090b16cf9/runtime.json +15 -0
  502. package/.ikie/ferments/019f274c-78b7-756e-82ef-8a8e953000bf/runtime.json +15 -0
  503. package/.ikie/ferments/019f274c-78df-7198-b1dd-58c3ea1e0d6e/runtime.json +15 -0
  504. package/.ikie/ferments/019f274c-7902-77d4-b443-b105d0a3acd5/runtime.json +15 -0
  505. package/.ikie/ferments/019f274c-7926-7628-82dc-e71e8f5d58f0/runtime.json +15 -0
  506. package/.ikie/ferments/019f274c-7948-7755-bc18-c8d9975c762f/runtime.json +15 -0
  507. package/.ikie/ferments/019f274c-7972-72a5-bc5e-e47579f25c32/runtime.json +15 -0
  508. package/.ikie/ferments/019f274c-7998-71bf-960e-caba2791ece7/runtime.json +11 -0
  509. package/.ikie/ferments/019f274c-79c4-71c6-97ef-0dac30d26152/runtime.json +11 -0
  510. package/.ikie/ferments/019f274c-79e3-7249-8bac-82b74fbd9d1d/reviews/phase-phase-1-1.json +63 -0
  511. package/.ikie/ferments/019f274c-79e3-7249-8bac-82b74fbd9d1d/runtime.json +17 -0
  512. package/.ikie/ferments/019f274c-7b11-769e-b05b-354105048fb2/reviews/phase-phase-1-1.json +63 -0
  513. package/.ikie/ferments/019f274c-7b11-769e-b05b-354105048fb2/runtime.json +17 -0
  514. package/.ikie/ferments/019f274c-7c7b-73ad-98d3-739e5f0187ec/runtime.json +11 -0
  515. package/.ikie/ferments/019f274c-8054-728f-96c1-6cae4b96c94e/runtime.json +11 -0
  516. package/.ikie/ferments/019f274c-8072-7209-82b0-84facff2e61a/runtime.json +11 -0
  517. package/.ikie/ferments/019f274c-8094-77ec-81dd-e50e61dc11db/runtime.json +11 -0
  518. package/.ikie/ferments/019f274c-80bc-75c9-89e8-540dba77996e/runtime.json +11 -0
  519. package/.ikie/ferments/019f274c-80dd-7439-a5b0-b36fcf77c8f1/pending-proposal.json +45 -0
  520. package/.ikie/ferments/019f274c-80f1-71ac-bd32-fd151f38519c/pending-proposal.json +45 -0
  521. package/.ikie/ferments/019f274c-81dc-70e6-a5c9-249b196c75c3/pending-proposal.json +45 -0
  522. package/.ikie/ferments/019f274c-8238-772c-9da3-f27e467100a7/pending-proposal.json +45 -0
  523. package/.ikie/ferments/019f274c-824a-76d9-aac3-c51171e256b4/pending-proposal.json +45 -0
  524. package/.ikie/ferments/019f274c-a854-7349-b76a-4a0bc2ecc2f7/runtime.json +11 -0
  525. package/.ikie/ferments/019f274c-a872-701b-a311-51267fc54aa5/runtime.json +11 -0
  526. package/.ikie/ferments/019f274c-a8a2-756e-9051-15fcd0be1584/runtime.json +11 -0
  527. package/.ikie/ferments/019f274c-a8d8-767c-8190-d30a2e78815f/runtime.json +12 -0
  528. package/.ikie/ferments/019f274c-a914-701e-95ab-9eeca15f5ccd/runtime.json +11 -0
  529. package/.ikie/ferments/019f274c-a951-720f-bc99-2ea22021a624/runtime.json +15 -0
  530. package/.ikie/ferments/019f274c-a978-750b-aecb-a5a2aa684cdf/runtime.json +15 -0
  531. package/.ikie/ferments/019f274c-a9a6-71e9-82ac-66c74cf51964/runtime.json +15 -0
  532. package/.ikie/ferments/019f274c-a9e0-77ae-96eb-dad523b6a843/runtime.json +13 -0
  533. package/.ikie/ferments/019f274c-aa2c-7658-a652-ca1a27093c42/runtime.json +15 -0
  534. package/.ikie/ferments/019f274c-aa77-72b4-a8de-56a2217c759f/runtime.json +15 -0
  535. package/.ikie/ferments/019f274c-aacf-74fa-943c-26412ddd8b5d/runtime.json +11 -0
  536. package/.ikie/ferments/019f274c-ab08-709f-aaff-09f10230738f/runtime.json +15 -0
  537. package/.ikie/ferments/019f274c-ab66-730b-86a5-7571dac8802c/runtime.json +15 -0
  538. package/.ikie/ferments/019f274c-abb2-77d2-91b6-ea175f561d8a/runtime.json +15 -0
  539. package/.ikie/ferments/019f274c-ac01-74ff-a2c6-28dbadc051e7/runtime.json +15 -0
  540. package/.ikie/ferments/019f274c-ac4b-75ad-93a6-aa6af74ca708/runtime.json +15 -0
  541. package/.ikie/ferments/019f274c-ac80-77b4-bfcf-f7a7187a42f6/runtime.json +15 -0
  542. package/.ikie/ferments/019f274c-acd9-7239-ad37-73d57031d1bc/runtime.json +15 -0
  543. package/.ikie/ferments/019f274c-ad22-74bb-9cf2-ed681dd73504/runtime.json +15 -0
  544. package/.ikie/ferments/019f274c-ad7d-720c-89bf-5a79ceec8173/runtime.json +15 -0
  545. package/.ikie/ferments/019f274c-adca-762a-b177-4d76b886003b/runtime.json +11 -0
  546. package/.ikie/ferments/019f274c-ae26-7109-bfaa-39d692fdc1ac/runtime.json +11 -0
  547. package/.ikie/ferments/019f274c-ae59-76bb-80ae-f556e764f2ca/reviews/phase-phase-1-1.json +63 -0
  548. package/.ikie/ferments/019f274c-ae59-76bb-80ae-f556e764f2ca/runtime.json +17 -0
  549. package/.ikie/ferments/019f274c-b059-76e5-9b73-bedc0d4b5aaa/reviews/phase-phase-1-1.json +63 -0
  550. package/.ikie/ferments/019f274c-b059-76e5-9b73-bedc0d4b5aaa/runtime.json +17 -0
  551. package/.ikie/ferments/019f274c-b21f-700a-adda-4bfd9d27a0ac/runtime.json +11 -0
  552. package/.ikie/ferments/019f274c-b91a-7306-8825-3581ef16ab34/runtime.json +11 -0
  553. package/.ikie/ferments/019f274c-b966-737f-a1c7-e8e7d3af929c/runtime.json +11 -0
  554. package/.ikie/ferments/019f274c-b99d-74dd-b8e8-1ddc50293a9a/runtime.json +11 -0
  555. package/.ikie/ferments/019f274c-ba0e-72ae-ad14-983edb8d90ac/runtime.json +11 -0
  556. package/.ikie/ferments/019f274c-ba4f-7101-b851-12564620c50f/pending-proposal.json +45 -0
  557. package/.ikie/ferments/019f274c-ba63-712c-858f-96cee1384cec/pending-proposal.json +45 -0
  558. package/.ikie/ferments/019f274c-bbe3-7343-a8b0-e6f91c3ab922/pending-proposal.json +45 -0
  559. package/.ikie/ferments/019f274c-bc4a-740e-a12a-9c04181702d9/pending-proposal.json +45 -0
  560. package/.ikie/ferments/019f274c-bc7b-707c-90b9-d30cf92b5fb9/pending-proposal.json +45 -0
  561. package/.ikie/ferments/019f274c-e044-750a-a9e1-623de3afa666/runtime.json +13 -0
  562. package/.ikie/ferments/019f274c-e07a-77cb-9f17-726e4afb3ee1/runtime.json +11 -0
  563. package/.ikie/ferments/019f274c-e0a2-754a-ac70-aac9cd3d3dc2/runtime.json +11 -0
  564. package/.ikie/ferments/019f274c-e0ba-72de-bf83-25a8319eddc5/runtime.json +11 -0
  565. package/.ikie/ferments/019f274c-e0cf-77c1-9c23-65745da294b4/runtime.json +11 -0
  566. package/.ikie/ferments/019f274c-e0e7-77f7-9436-0537e2095c6b/runtime.json +11 -0
  567. package/.ikie/ferments/019f274c-e103-70d7-abd9-01305b905259/runtime.json +11 -0
  568. package/.ikie/ferments/019f274c-e121-7328-9eab-3babb40f26b3/runtime.json +11 -0
  569. package/.ikie/ferments/019f274c-e135-76d4-9176-2033e41fa5a8/runtime.json +9 -0
  570. package/.ikie/ferments/019f274c-e157-7043-9b54-fd7c40cb0793/runtime.json +13 -0
  571. package/.ikie/ferments/019f274c-e181-718e-804d-d0edfaabd5cd/runtime.json +11 -0
  572. package/.ikie/ferments/019f274c-e19b-72ab-bf87-b7a53037becb/runtime.json +11 -0
  573. package/.ikie/ferments/019f274c-e20a-716e-8cab-f0cd93259148/runtime.json +11 -0
  574. package/.ikie/ferments/019f274c-e228-73a3-a655-48bc44db0325/runtime.json +9 -0
  575. package/.ikie/ferments/019f274c-e243-7609-bec4-905caa78d674/runtime.json +9 -0
  576. package/.ikie/ferments/019f274c-e258-76ba-912c-bab41dfeaac2/runtime.json +11 -0
  577. package/.ikie/ferments/019f274c-e35a-776b-a644-52ee82afec4d/runtime.json +11 -0
  578. package/.ikie/ferments/019f274c-e378-73e8-943d-f2fc2ee875ef/runtime.json +12 -0
  579. package/.ikie/ferments/019f274c-e3a6-757d-b33c-c6fbdd9cf8c7/runtime.json +11 -0
  580. package/.ikie/ferments/019f274c-e3c9-77a7-be2b-43891355a506/runtime.json +11 -0
  581. package/.ikie/ferments/019f274c-e3db-776b-8de6-fb1aeab60a7b/runtime.json +11 -0
  582. package/.ikie/ferments/019f274c-e3f4-700e-8780-2dee3c117eb8/runtime.json +11 -0
  583. package/.ikie/ferments/019f274c-e409-71af-a0f9-ff159811e472/runtime.json +13 -0
  584. package/.ikie/ferments/019f274c-e432-73cd-bd34-39f0e34a568d/runtime.json +11 -0
  585. package/.ikie/ferments/019f274c-eb55-73fe-bb2a-34b4a2df3f4e/reviews/phase-phase-1-1.json +41 -0
  586. package/.ikie/ferments/019f274c-eb55-73fe-bb2a-34b4a2df3f4e/runtime.json +11 -0
  587. package/.ikie/ferments/019f274c-eb9b-728e-93e2-80afb71ae50e/reviews/phase-phase-1-1.json +47 -0
  588. package/.ikie/ferments/019f274c-eb9b-728e-93e2-80afb71ae50e/runtime.json +13 -0
  589. package/.ikie/ferments/019f274c-ebf3-77bb-8f8a-6081787fbcb3/reviews/phase-phase-1-1.json +40 -0
  590. package/.ikie/ferments/019f274c-ebf3-77bb-8f8a-6081787fbcb3/runtime.json +9 -0
  591. package/.ikie/ferments/019f274c-ec22-7123-8c8f-0c129c2e0719/reviews/phase-phase-1-1.json +40 -0
  592. package/.ikie/ferments/019f274c-ec22-7123-8c8f-0c129c2e0719/runtime.json +9 -0
  593. package/.ikie/ferments/019f274c-ec85-757c-9600-8be68ceccb55/reviews/phase-phase-1-1.json +40 -0
  594. package/.ikie/ferments/019f274c-ec85-757c-9600-8be68ceccb55/runtime.json +9 -0
  595. package/.ikie/ferments/019f274c-ecd9-704e-8c99-65c64be0a8e1/reviews/phase-phase-1-1.json +40 -0
  596. package/.ikie/ferments/019f274c-ecd9-704e-8c99-65c64be0a8e1/runtime.json +9 -0
  597. package/.ikie/ferments/019f274c-ecee-70bb-9087-da3b4c57d281/reviews/phase-phase-1-1.json +40 -0
  598. package/.ikie/ferments/019f274c-ecee-70bb-9087-da3b4c57d281/runtime.json +9 -0
  599. package/.ikie/ferments/019f274c-ed18-77bf-8cde-812d1e273bda/reviews/phase-phase-1-1.json +62 -0
  600. package/.ikie/ferments/019f274c-ed18-77bf-8cde-812d1e273bda/runtime.json +9 -0
  601. package/.ikie/ferments/019f274f-0303-7543-9aa9-fa7f54d5f6c6/runtime.json +11 -0
  602. package/.ikie/ferments/019f274f-032c-70aa-b5b5-d695429a50bc/runtime.json +11 -0
  603. package/.ikie/ferments/019f274f-036d-763c-8cf9-cb62245aff49/runtime.json +11 -0
  604. package/.ikie/ferments/019f274f-03bd-709c-85ee-698745beac66/runtime.json +12 -0
  605. package/.ikie/ferments/019f274f-0404-75cf-8731-f0182bd84d87/runtime.json +11 -0
  606. package/.ikie/ferments/019f274f-0442-75fe-8cc3-44bfe5dd84bf/runtime.json +15 -0
  607. package/.ikie/ferments/019f274f-048f-759f-ae18-5fe9975647bf/runtime.json +15 -0
  608. package/.ikie/ferments/019f274f-04f1-72fa-a2ba-0b9e066ae6eb/runtime.json +15 -0
  609. package/.ikie/ferments/019f274f-0541-728d-8893-0b0b45547a56/runtime.json +13 -0
  610. package/.ikie/ferments/019f274f-058e-7508-b67a-ebe736113e1e/runtime.json +15 -0
  611. package/.ikie/ferments/019f274f-0625-77d9-bf99-bcdf0ca2d5b2/runtime.json +15 -0
  612. package/.ikie/ferments/019f274f-0694-715c-b008-29a3cf0d6c9c/runtime.json +11 -0
  613. package/.ikie/ferments/019f274f-06b1-71fb-a812-3fd3cefda2ea/runtime.json +15 -0
  614. package/.ikie/ferments/019f274f-06e9-701b-9396-dca2be2330e5/runtime.json +15 -0
  615. package/.ikie/ferments/019f274f-072b-76b2-8d77-32d0ad5abb81/runtime.json +15 -0
  616. package/.ikie/ferments/019f274f-0770-75ce-886f-c1c12d6682eb/runtime.json +15 -0
  617. package/.ikie/ferments/019f274f-07ab-75fc-a71b-ca3b4b4acca5/runtime.json +15 -0
  618. package/.ikie/ferments/019f274f-07f0-72cd-a577-316526b45983/runtime.json +15 -0
  619. package/.ikie/ferments/019f274f-0837-72ed-94f2-dd68e9273549/runtime.json +15 -0
  620. package/.ikie/ferments/019f274f-0866-765d-a2fc-8cce9d53e417/runtime.json +15 -0
  621. package/.ikie/ferments/019f274f-08bb-737e-8f23-4b2e069bc7e5/runtime.json +15 -0
  622. package/.ikie/ferments/019f274f-08f6-73aa-968a-85f55d5e047c/runtime.json +11 -0
  623. package/.ikie/ferments/019f274f-0949-77b7-8d2c-46fbeb423e3a/runtime.json +11 -0
  624. package/.ikie/ferments/019f274f-0979-71ad-91b5-d2e52366b74d/reviews/phase-phase-1-1.json +63 -0
  625. package/.ikie/ferments/019f274f-0979-71ad-91b5-d2e52366b74d/runtime.json +17 -0
  626. package/.ikie/ferments/019f274f-0b57-7329-884a-43e712cd093c/reviews/phase-phase-1-1.json +63 -0
  627. package/.ikie/ferments/019f274f-0b57-7329-884a-43e712cd093c/runtime.json +17 -0
  628. package/.ikie/ferments/019f274f-0d87-772d-a6f3-b71179eec14f/runtime.json +11 -0
  629. package/.ikie/ferments/019f274f-12f0-73be-b630-54a329974d0b/runtime.json +11 -0
  630. package/.ikie/ferments/019f274f-1332-7202-90be-f7e94dd16e66/runtime.json +11 -0
  631. package/.ikie/ferments/019f274f-1368-778a-b044-0306086fe9cf/runtime.json +11 -0
  632. package/.ikie/ferments/019f274f-13a9-7287-974d-8db5c1b7dda6/runtime.json +11 -0
  633. package/.ikie/ferments/019f274f-13d1-7069-91d8-2e4efe8d8982/pending-proposal.json +45 -0
  634. package/.ikie/ferments/019f274f-13f8-717c-92c9-9bc9b37ee2cc/pending-proposal.json +45 -0
  635. package/.ikie/ferments/019f274f-1566-753b-b053-f14ccb779e36/pending-proposal.json +45 -0
  636. package/.ikie/ferments/019f274f-15d3-76f8-8467-e368f0c40baf/pending-proposal.json +45 -0
  637. package/.ikie/ferments/019f274f-15f0-716f-92e7-d966f4476b09/pending-proposal.json +45 -0
  638. package/.ikie/ferments/019f274f-2a19-762d-be24-59afdd71b303/runtime.json +13 -0
  639. package/.ikie/ferments/019f274f-2a74-74cb-ab51-dd779739478e/runtime.json +11 -0
  640. package/.ikie/ferments/019f274f-2a92-71e1-9e68-15f750efc6ec/runtime.json +11 -0
  641. package/.ikie/ferments/019f274f-2ab1-73eb-8930-b9d161230fcc/runtime.json +11 -0
  642. package/.ikie/ferments/019f274f-2ad9-70ea-83a9-f8ae1af1edcf/runtime.json +11 -0
  643. package/.ikie/ferments/019f274f-2b02-77ea-b187-43489c9a88f8/runtime.json +11 -0
  644. package/.ikie/ferments/019f274f-2b2d-728c-9b69-7a6e4956a88c/runtime.json +11 -0
  645. package/.ikie/ferments/019f274f-2b42-7358-b1fa-9754d2ca530d/runtime.json +11 -0
  646. package/.ikie/ferments/019f274f-2b74-77ee-b062-8b111368fc58/runtime.json +9 -0
  647. package/.ikie/ferments/019f274f-2b9b-703b-8abd-5b4ff212ce66/runtime.json +13 -0
  648. package/.ikie/ferments/019f274f-2bd6-7109-93ec-12f609270c84/runtime.json +11 -0
  649. package/.ikie/ferments/019f274f-2bea-75cf-b3d2-aedca4b0c8a4/runtime.json +11 -0
  650. package/.ikie/ferments/019f274f-2c1c-7085-b221-ecf2a371e6cf/runtime.json +11 -0
  651. package/.ikie/ferments/019f274f-2c2f-71fb-9b03-41d6f8a5d2d6/runtime.json +9 -0
  652. package/.ikie/ferments/019f274f-2c5d-719d-a913-5255a7b3e376/runtime.json +9 -0
  653. package/.ikie/ferments/019f274f-2c92-75bb-b691-4efd9b706418/runtime.json +11 -0
  654. package/.ikie/ferments/019f274f-2d9e-7186-b8f9-0d5863265329/runtime.json +11 -0
  655. package/.ikie/ferments/019f274f-2dbb-73f9-8231-b52b6e1eb863/runtime.json +12 -0
  656. package/.ikie/ferments/019f274f-2ddf-7477-a5a2-a20be1921fbf/runtime.json +11 -0
  657. package/.ikie/ferments/019f274f-2e01-710b-8175-18eeb0e792e2/runtime.json +11 -0
  658. package/.ikie/ferments/019f274f-2e26-7217-a41e-3bd106e0a9cf/runtime.json +11 -0
  659. package/.ikie/ferments/019f274f-2e3a-72bc-9945-37a576bb7ef1/runtime.json +11 -0
  660. package/.ikie/ferments/019f274f-2e61-77e5-85ab-dda905bded90/runtime.json +13 -0
  661. package/.ikie/ferments/019f274f-2e7e-73ea-a7c9-14ab5125c3d3/runtime.json +11 -0
  662. package/.ikie/ferments/019f274f-4262-76b9-884a-9ff2121f2c3a/reviews/phase-phase-1-1.json +41 -0
  663. package/.ikie/ferments/019f274f-4262-76b9-884a-9ff2121f2c3a/runtime.json +11 -0
  664. package/.ikie/ferments/019f274f-42ce-753f-ba6d-c1c2be5b7c71/reviews/phase-phase-1-1.json +47 -0
  665. package/.ikie/ferments/019f274f-42ce-753f-ba6d-c1c2be5b7c71/runtime.json +13 -0
  666. package/.ikie/ferments/019f274f-4353-75ed-bad2-0f74d61ceff5/reviews/phase-phase-1-1.json +40 -0
  667. package/.ikie/ferments/019f274f-4353-75ed-bad2-0f74d61ceff5/runtime.json +9 -0
  668. package/.ikie/ferments/019f274f-4379-7716-af61-2381f422540e/reviews/phase-phase-1-1.json +40 -0
  669. package/.ikie/ferments/019f274f-4379-7716-af61-2381f422540e/runtime.json +9 -0
  670. package/.ikie/ferments/019f274f-43a1-716c-ba31-4b705e8afb1a/reviews/phase-phase-1-1.json +40 -0
  671. package/.ikie/ferments/019f274f-43a1-716c-ba31-4b705e8afb1a/runtime.json +9 -0
  672. package/.ikie/ferments/019f274f-43de-761a-b793-fca5ca243eea/reviews/phase-phase-1-1.json +40 -0
  673. package/.ikie/ferments/019f274f-43de-761a-b793-fca5ca243eea/runtime.json +9 -0
  674. package/.ikie/ferments/019f274f-4401-73e9-b9d8-99631bab030b/reviews/phase-phase-1-1.json +40 -0
  675. package/.ikie/ferments/019f274f-4401-73e9-b9d8-99631bab030b/runtime.json +9 -0
  676. package/.ikie/ferments/019f274f-442b-770b-b411-feeb46ae7a8d/reviews/phase-phase-1-1.json +62 -0
  677. package/.ikie/ferments/019f274f-442b-770b-b411-feeb46ae7a8d/runtime.json +9 -0
  678. package/.ikie/ferments/019f275c-3e9e-7557-b50e-0e56cc6b07f5/runtime.json +11 -0
  679. package/.ikie/ferments/019f275c-3ec3-73ea-b557-77cc517095f2/runtime.json +11 -0
  680. package/.ikie/ferments/019f275c-3ee5-774f-876e-3caacb9b1d95/runtime.json +11 -0
  681. package/.ikie/ferments/019f275c-3f28-73ee-8eae-568fec8011b6/runtime.json +12 -0
  682. package/.ikie/ferments/019f275c-3f57-70a8-ba4d-d179cceaabbf/runtime.json +11 -0
  683. package/.ikie/ferments/019f275c-3f88-72cb-abb5-8e0e176e1dd2/runtime.json +15 -0
  684. package/.ikie/ferments/019f275c-3fb4-7248-9c23-874baa6e2a9d/runtime.json +15 -0
  685. package/.ikie/ferments/019f275c-3fe1-759b-afd9-f5e47564de48/runtime.json +15 -0
  686. package/.ikie/ferments/019f275c-401f-74e8-b968-d325ae2faf56/runtime.json +13 -0
  687. package/.ikie/ferments/019f275c-4067-752e-a0d8-d85f670f9473/runtime.json +15 -0
  688. package/.ikie/ferments/019f275c-40a2-74de-b858-ef4ad52484ea/runtime.json +15 -0
  689. package/.ikie/ferments/019f275c-4105-738f-95d0-6e9f7f9568fb/runtime.json +11 -0
  690. package/.ikie/ferments/019f275c-411b-76e9-b030-df118a1b23b4/runtime.json +15 -0
  691. package/.ikie/ferments/019f275c-4153-74ec-8b93-e2e0e82c27b0/runtime.json +15 -0
  692. package/.ikie/ferments/019f275c-4199-739b-9af9-b1cfc26623c3/runtime.json +15 -0
  693. package/.ikie/ferments/019f275c-41cb-746b-8481-7ca9d82a8b64/runtime.json +15 -0
  694. package/.ikie/ferments/019f275c-4209-756f-b335-8e6dfe51bac1/runtime.json +15 -0
  695. package/.ikie/ferments/019f275c-424c-7512-ac17-b8c04dcf82ac/runtime.json +15 -0
  696. package/.ikie/ferments/019f275c-4269-74eb-a213-e221479a26e5/runtime.json +15 -0
  697. package/.ikie/ferments/019f275c-428b-71ea-acda-027b98d191d1/runtime.json +15 -0
  698. package/.ikie/ferments/019f275c-42bb-75da-b330-e9f101c36d5c/runtime.json +15 -0
  699. package/.ikie/ferments/019f275c-42e3-777a-8e8c-80772f6d6bcb/runtime.json +11 -0
  700. package/.ikie/ferments/019f275c-430b-7779-bcc7-95a0b6fc693d/runtime.json +11 -0
  701. package/.ikie/ferments/019f275c-432e-71f9-b65d-88d26f3b185f/reviews/phase-phase-1-1.json +63 -0
  702. package/.ikie/ferments/019f275c-432e-71f9-b65d-88d26f3b185f/runtime.json +17 -0
  703. package/.ikie/ferments/019f275c-447e-756d-8ec0-091e54bcc7b4/reviews/phase-phase-1-1.json +63 -0
  704. package/.ikie/ferments/019f275c-447e-756d-8ec0-091e54bcc7b4/runtime.json +17 -0
  705. package/.ikie/ferments/019f275c-4602-757e-9283-3606516f4d15/runtime.json +11 -0
  706. package/.ikie/ferments/019f275c-4a3b-75f0-8355-8524d1589242/runtime.json +11 -0
  707. package/.ikie/ferments/019f275c-4a5c-744e-9792-deb33fe1e244/runtime.json +11 -0
  708. package/.ikie/ferments/019f275c-4a79-73d2-beae-4e85f8906581/runtime.json +11 -0
  709. package/.ikie/ferments/019f275c-4a97-70b9-98d1-53d9326b4c95/runtime.json +11 -0
  710. package/.ikie/ferments/019f275c-4ac1-7452-ab7a-485bde641591/pending-proposal.json +45 -0
  711. package/.ikie/ferments/019f275c-4ad7-77ba-8a63-d8586db466e7/pending-proposal.json +45 -0
  712. package/.ikie/ferments/019f275c-4bee-77b9-8470-98c4aafeae43/pending-proposal.json +45 -0
  713. package/.ikie/ferments/019f275c-4c3d-712b-95f6-a671b7884658/pending-proposal.json +45 -0
  714. package/.ikie/ferments/019f275c-4c4e-73a0-accb-e76c29bc1f6d/pending-proposal.json +45 -0
  715. package/.ikie/ferments/019f275c-7598-775d-beed-cde3b6cb74e6/runtime.json +13 -0
  716. package/.ikie/ferments/019f275c-75c0-773d-9c0c-dd4943fc6092/runtime.json +11 -0
  717. package/.ikie/ferments/019f275c-75dc-7629-8a52-1eba66275779/runtime.json +11 -0
  718. package/.ikie/ferments/019f275c-75f3-742b-8494-e8a1facb02bb/runtime.json +11 -0
  719. package/.ikie/ferments/019f275c-760c-705e-8d98-7963d8830086/runtime.json +11 -0
  720. package/.ikie/ferments/019f275c-7627-763c-ae8e-20dde59c64b9/runtime.json +11 -0
  721. package/.ikie/ferments/019f275c-763c-74ae-b835-b52b57c52e9b/runtime.json +11 -0
  722. package/.ikie/ferments/019f275c-7650-7499-b744-7f38cfa776f4/runtime.json +11 -0
  723. package/.ikie/ferments/019f275c-766d-75b8-ba35-69e472baf630/runtime.json +9 -0
  724. package/.ikie/ferments/019f275c-7687-72cc-beac-339a11625f14/runtime.json +13 -0
  725. package/.ikie/ferments/019f275c-76a6-773d-a4c1-19a5ec313596/runtime.json +11 -0
  726. package/.ikie/ferments/019f275c-76c1-71b9-a49e-4b520fcef543/runtime.json +11 -0
  727. package/.ikie/ferments/019f275c-7706-761f-a9cf-7e412e88015d/runtime.json +11 -0
  728. package/.ikie/ferments/019f275c-772b-745f-a74d-de30f52a3316/runtime.json +9 -0
  729. package/.ikie/ferments/019f275c-7746-759c-a116-c2cd08e2f29b/runtime.json +9 -0
  730. package/.ikie/ferments/019f275c-7760-709d-83bc-4d6fff7ac768/runtime.json +11 -0
  731. package/.ikie/ferments/019f275c-780e-74db-9d7d-bcc430c1a964/runtime.json +11 -0
  732. package/.ikie/ferments/019f275c-7826-734e-8113-90111e82d96a/runtime.json +12 -0
  733. package/.ikie/ferments/019f275c-7849-72ed-8fb0-d1815d2f66d3/runtime.json +11 -0
  734. package/.ikie/ferments/019f275c-785f-716e-b077-eee453653ee0/runtime.json +11 -0
  735. package/.ikie/ferments/019f275c-7871-70fe-b543-bcdaaa10d320/runtime.json +11 -0
  736. package/.ikie/ferments/019f275c-7888-777d-8edf-1a5a906679d7/runtime.json +11 -0
  737. package/.ikie/ferments/019f275c-78b3-722e-9d1a-f354b0d0fa96/runtime.json +13 -0
  738. package/.ikie/ferments/019f275c-78cb-7568-ad11-191bc98cabe5/runtime.json +11 -0
  739. package/.ikie/ferments/019f275c-8905-76ae-beb3-2ec9138b799b/reviews/phase-phase-1-1.json +41 -0
  740. package/.ikie/ferments/019f275c-8905-76ae-beb3-2ec9138b799b/runtime.json +11 -0
  741. package/.ikie/ferments/019f275c-8970-713f-a498-af24ac57355a/reviews/phase-phase-1-1.json +47 -0
  742. package/.ikie/ferments/019f275c-8970-713f-a498-af24ac57355a/runtime.json +13 -0
  743. package/.ikie/ferments/019f275c-89c6-712f-b3c9-d9459bdaba76/reviews/phase-phase-1-1.json +40 -0
  744. package/.ikie/ferments/019f275c-89c6-712f-b3c9-d9459bdaba76/runtime.json +9 -0
  745. package/.ikie/ferments/019f275c-89e8-7105-9ba9-eda02056339a/reviews/phase-phase-1-1.json +40 -0
  746. package/.ikie/ferments/019f275c-89e8-7105-9ba9-eda02056339a/runtime.json +9 -0
  747. package/.ikie/ferments/019f275c-8a0d-71cb-bbb3-aa061c305aab/reviews/phase-phase-1-1.json +40 -0
  748. package/.ikie/ferments/019f275c-8a0d-71cb-bbb3-aa061c305aab/runtime.json +9 -0
  749. package/.ikie/ferments/019f275c-8a31-758b-87c7-1b2ec8b0bd7a/reviews/phase-phase-1-1.json +40 -0
  750. package/.ikie/ferments/019f275c-8a31-758b-87c7-1b2ec8b0bd7a/runtime.json +9 -0
  751. package/.ikie/ferments/019f275c-8a4f-7649-a250-4074bed6f208/reviews/phase-phase-1-1.json +40 -0
  752. package/.ikie/ferments/019f275c-8a4f-7649-a250-4074bed6f208/runtime.json +9 -0
  753. package/.ikie/ferments/019f275c-8a6e-706d-af6d-f6636f3b229e/reviews/phase-phase-1-1.json +62 -0
  754. package/.ikie/ferments/019f275c-8a6e-706d-af6d-f6636f3b229e/runtime.json +9 -0
  755. package/.ikie/ferments/019f275e-8903-721d-98f8-0135ab6b4698/runtime.json +11 -0
  756. package/.ikie/ferments/019f275e-8920-7644-a529-664b63f9bab1/runtime.json +11 -0
  757. package/.ikie/ferments/019f275e-8938-75c2-85ab-f5a50138a4eb/runtime.json +11 -0
  758. package/.ikie/ferments/019f275e-895e-74a1-b263-2f73d989898e/runtime.json +12 -0
  759. package/.ikie/ferments/019f275e-8977-75ee-9e9a-cc069fff1cfa/runtime.json +11 -0
  760. package/.ikie/ferments/019f275e-899d-773b-abe3-e93c56f57cf1/runtime.json +11 -0
  761. package/.ikie/ferments/019f275e-89d1-72ea-9362-d4ce4079e846/runtime.json +15 -0
  762. package/.ikie/ferments/019f275e-89f9-7007-b382-a55e983d9520/runtime.json +15 -0
  763. package/.ikie/ferments/019f275e-8a1d-7687-a56e-94ead3cafbf8/runtime.json +15 -0
  764. package/.ikie/ferments/019f275e-8a49-760f-9639-3ce1494f37e9/runtime.json +13 -0
  765. package/.ikie/ferments/019f275e-8a7d-7461-b978-c3478b99b386/runtime.json +15 -0
  766. package/.ikie/ferments/019f275e-8aac-736d-bd96-6b442359993b/runtime.json +15 -0
  767. package/.ikie/ferments/019f275e-8ae6-7298-a523-d2fb7287bed3/runtime.json +11 -0
  768. package/.ikie/ferments/019f275e-8b01-7059-85a1-a665334ced3e/runtime.json +15 -0
  769. package/.ikie/ferments/019f275e-8b29-7295-be5b-0468763ab101/runtime.json +15 -0
  770. package/.ikie/ferments/019f275e-8b51-7204-9d30-0a67dae9c341/runtime.json +15 -0
  771. package/.ikie/ferments/019f275e-8b78-71eb-a8a3-1448d3373912/runtime.json +15 -0
  772. package/.ikie/ferments/019f275e-8b9d-76bf-9caa-0fed193b85bf/runtime.json +15 -0
  773. package/.ikie/ferments/019f275e-8bc0-71df-9356-19d3075c9568/runtime.json +15 -0
  774. package/.ikie/ferments/019f275e-8be2-75bd-be4a-ba2ede0e95f3/runtime.json +15 -0
  775. package/.ikie/ferments/019f275e-8c0b-714a-a389-20ffe6d0e66d/runtime.json +15 -0
  776. package/.ikie/ferments/019f275e-8c30-7371-86af-78e5f5ac8b23/runtime.json +15 -0
  777. package/.ikie/ferments/019f275e-8c5a-7383-bd79-c7fec3a71946/runtime.json +11 -0
  778. package/.ikie/ferments/019f275e-8c75-76b1-bcaa-81e67fc35aa8/runtime.json +11 -0
  779. package/.ikie/ferments/019f275e-8caa-71e9-9e66-0d30c4a03123/reviews/phase-phase-1-1.json +63 -0
  780. package/.ikie/ferments/019f275e-8caa-71e9-9e66-0d30c4a03123/runtime.json +17 -0
  781. package/.ikie/ferments/019f275e-8e59-7787-84f8-fcf93ec75949/reviews/phase-phase-1-1.json +63 -0
  782. package/.ikie/ferments/019f275e-8e59-7787-84f8-fcf93ec75949/runtime.json +17 -0
  783. package/.ikie/ferments/019f275e-8ffb-70c2-844e-e1f4fa4c2cc4/runtime.json +11 -0
  784. package/.ikie/ferments/019f275e-949b-7158-a426-07bcca442439/runtime.json +11 -0
  785. package/.ikie/ferments/019f275e-94c6-7479-abcb-c22fc19445a0/runtime.json +11 -0
  786. package/.ikie/ferments/019f275e-94eb-76e9-a148-fb5001492823/runtime.json +11 -0
  787. package/.ikie/ferments/019f275e-9516-765a-b8ee-e88e5ab2530f/runtime.json +11 -0
  788. package/.ikie/ferments/019f275e-9539-740f-bbdb-09b82f71fc81/pending-proposal.json +45 -0
  789. package/.ikie/ferments/019f275e-954f-73e0-9286-fdf09cb1cbc6/pending-proposal.json +45 -0
  790. package/.ikie/ferments/019f275e-967d-73dc-bfaf-18e44335cff8/pending-proposal.json +45 -0
  791. package/.ikie/ferments/019f275e-96f0-702d-b0d2-f2aeb1c7ee15/pending-proposal.json +45 -0
  792. package/.ikie/ferments/019f275e-9708-770c-bae2-2652e32be3cf/pending-proposal.json +45 -0
  793. package/.ikie/ferments/019f275e-c992-77a4-960a-d6d51983c9d6/runtime.json +13 -0
  794. package/.ikie/ferments/019f275e-c9cf-724a-a59f-8e34f026db5e/runtime.json +11 -0
  795. package/.ikie/ferments/019f275e-c9e6-7647-9517-b2b25cd1f495/runtime.json +11 -0
  796. package/.ikie/ferments/019f275e-ca11-716b-832b-11fc14ce1ded/runtime.json +11 -0
  797. package/.ikie/ferments/019f275e-ca2f-74df-90fa-2eed00b55ecf/runtime.json +11 -0
  798. package/.ikie/ferments/019f275e-ca49-77ed-bb62-cd9c3c1176a5/runtime.json +11 -0
  799. package/.ikie/ferments/019f275e-ca62-77ca-aed0-74728cab4be4/runtime.json +11 -0
  800. package/.ikie/ferments/019f275e-ca7a-76aa-a860-42152a699337/runtime.json +11 -0
  801. package/.ikie/ferments/019f275e-ca9b-766c-9ad4-2f86ff5c9dbe/runtime.json +9 -0
  802. package/.ikie/ferments/019f275e-cabc-77cf-a94a-9f8988667998/runtime.json +13 -0
  803. package/.ikie/ferments/019f275e-cae6-76d9-8682-d138cbd0e3cf/runtime.json +11 -0
  804. package/.ikie/ferments/019f275e-cb0a-7361-8e72-84e44afa7847/runtime.json +11 -0
  805. package/.ikie/ferments/019f275e-cb67-71dd-a7b7-35d98fca2379/runtime.json +11 -0
  806. package/.ikie/ferments/019f275e-cb8c-75c8-9a02-812c50dbcc28/runtime.json +9 -0
  807. package/.ikie/ferments/019f275e-cba7-74c5-8a0e-facff616ecf0/runtime.json +9 -0
  808. package/.ikie/ferments/019f275e-cbc6-719a-a1e9-86fad18fb0de/runtime.json +11 -0
  809. package/.ikie/ferments/019f275e-cc83-7608-878d-3b107b55db48/runtime.json +11 -0
  810. package/.ikie/ferments/019f275e-cc96-72f9-9e5d-a350ea59c5b7/runtime.json +12 -0
  811. package/.ikie/ferments/019f275e-ccb5-72bf-8ad6-8ea4f87f86c0/runtime.json +11 -0
  812. package/.ikie/ferments/019f275e-ccd9-77de-89ff-25fa626c05b4/runtime.json +11 -0
  813. package/.ikie/ferments/019f275e-ccfb-777a-8a40-1ccaf4c139c4/runtime.json +11 -0
  814. package/.ikie/ferments/019f275e-cd15-7785-be69-1f9ef80faa52/runtime.json +11 -0
  815. package/.ikie/ferments/019f275e-cd31-7629-9034-57bcde8cf8e1/runtime.json +13 -0
  816. package/.ikie/ferments/019f275e-cd56-74be-8cdd-94af39b5593b/runtime.json +11 -0
  817. package/.ikie/ferments/019f275e-db71-73fb-9992-6d52de708265/reviews/phase-phase-1-1.json +41 -0
  818. package/.ikie/ferments/019f275e-db71-73fb-9992-6d52de708265/runtime.json +11 -0
  819. package/.ikie/ferments/019f275e-dbc0-725b-bb55-3eca5072215b/reviews/phase-phase-1-1.json +47 -0
  820. package/.ikie/ferments/019f275e-dbc0-725b-bb55-3eca5072215b/runtime.json +13 -0
  821. package/.ikie/ferments/019f275e-dc11-7320-bc60-fbca50c8e709/reviews/phase-phase-1-1.json +40 -0
  822. package/.ikie/ferments/019f275e-dc11-7320-bc60-fbca50c8e709/runtime.json +9 -0
  823. package/.ikie/ferments/019f275e-dc39-73ee-9d63-d8fbb906d877/reviews/phase-phase-1-1.json +40 -0
  824. package/.ikie/ferments/019f275e-dc39-73ee-9d63-d8fbb906d877/runtime.json +9 -0
  825. package/.ikie/ferments/019f275e-dc60-7649-9918-b236d9a16cef/reviews/phase-phase-1-1.json +40 -0
  826. package/.ikie/ferments/019f275e-dc60-7649-9918-b236d9a16cef/runtime.json +9 -0
  827. package/.ikie/ferments/019f275e-dc83-7030-aa35-3a78b18fadb4/reviews/phase-phase-1-1.json +40 -0
  828. package/.ikie/ferments/019f275e-dc83-7030-aa35-3a78b18fadb4/runtime.json +9 -0
  829. package/.ikie/ferments/019f275e-dcb3-706f-b3b0-b44556b7d3cb/reviews/phase-phase-1-1.json +40 -0
  830. package/.ikie/ferments/019f275e-dcb3-706f-b3b0-b44556b7d3cb/runtime.json +9 -0
  831. package/.ikie/ferments/019f275e-dcd6-717c-afe6-82a959a0fcbd/reviews/phase-phase-1-1.json +62 -0
  832. package/.ikie/ferments/019f275e-dcd6-717c-afe6-82a959a0fcbd/runtime.json +9 -0
  833. package/.ikie/ferments/019f2764-6cde-7610-b409-ee715ca796e8/runtime.json +11 -0
  834. package/.ikie/ferments/019f2764-6cfa-733d-8231-937535e2e6b8/runtime.json +11 -0
  835. package/.ikie/ferments/019f2764-6d11-7611-b216-dcdaa468d686/runtime.json +11 -0
  836. package/.ikie/ferments/019f2764-6d33-728f-901c-4fef8141050d/runtime.json +12 -0
  837. package/.ikie/ferments/019f2764-6d5d-7314-9e98-3851effc803f/runtime.json +11 -0
  838. package/.ikie/ferments/019f2764-6d87-722e-bf53-0dd6182ea7c6/runtime.json +15 -0
  839. package/.ikie/ferments/019f2764-6daa-7052-b766-8aef8e542b88/runtime.json +15 -0
  840. package/.ikie/ferments/019f2764-6dc9-73fc-8665-a3f8b51f7450/runtime.json +15 -0
  841. package/.ikie/ferments/019f2764-6df3-7368-94a2-5369f3276848/runtime.json +13 -0
  842. package/.ikie/ferments/019f2764-6e25-762c-a0e0-0ef60c6e2653/runtime.json +15 -0
  843. package/.ikie/ferments/019f2764-6e58-733d-ab0e-8fad4b2c665e/runtime.json +15 -0
  844. package/.ikie/ferments/019f2764-6ead-742a-afc5-e10a044333ec/runtime.json +11 -0
  845. package/.ikie/ferments/019f2764-6ec9-7566-a4f0-e0d14f80e103/runtime.json +15 -0
  846. package/.ikie/ferments/019f2764-6efe-727d-a81b-36fbde2904b3/runtime.json +15 -0
  847. package/.ikie/ferments/019f2764-6f3d-7292-bbf4-88e9ee6b077e/runtime.json +15 -0
  848. package/.ikie/ferments/019f2764-6f6c-758f-9427-652571b7494f/runtime.json +15 -0
  849. package/.ikie/ferments/019f2764-6faa-700b-8d2d-cbed35957db8/runtime.json +15 -0
  850. package/.ikie/ferments/019f2764-6fcb-71d8-9daf-225746805ba4/runtime.json +15 -0
  851. package/.ikie/ferments/019f2764-6ff0-7573-9208-e236e2969c5a/runtime.json +15 -0
  852. package/.ikie/ferments/019f2764-7012-77ce-97c9-6e99dd0367b3/runtime.json +15 -0
  853. package/.ikie/ferments/019f2764-703d-7554-8008-5104879d081d/runtime.json +15 -0
  854. package/.ikie/ferments/019f2764-7082-7399-80d5-659015dc6129/runtime.json +11 -0
  855. package/.ikie/ferments/019f2764-70b4-7581-b83e-9945010b008b/runtime.json +11 -0
  856. package/.ikie/ferments/019f2764-70d2-71a1-8b2f-1db7c0de5d5b/reviews/phase-phase-1-1.json +63 -0
  857. package/.ikie/ferments/019f2764-70d2-71a1-8b2f-1db7c0de5d5b/runtime.json +17 -0
  858. package/.ikie/ferments/019f2764-7256-714b-9804-17a6ad3c7996/reviews/phase-phase-1-1.json +63 -0
  859. package/.ikie/ferments/019f2764-7256-714b-9804-17a6ad3c7996/runtime.json +17 -0
  860. package/.ikie/ferments/019f2764-742b-711f-9997-ae6ce141d7d9/runtime.json +11 -0
  861. package/.ikie/ferments/019f2764-78e4-765c-bcf6-ae76955d98c0/runtime.json +11 -0
  862. package/.ikie/ferments/019f2764-7900-7573-afaf-c32d1b6a7be0/runtime.json +11 -0
  863. package/.ikie/ferments/019f2764-7920-7463-b2c3-132980285998/runtime.json +11 -0
  864. package/.ikie/ferments/019f2764-7947-721f-9c5e-6fc087b2e912/runtime.json +11 -0
  865. package/.ikie/ferments/019f2764-7967-735b-9066-12a93c490f17/pending-proposal.json +45 -0
  866. package/.ikie/ferments/019f2764-798b-749d-b86b-90c55c838b29/pending-proposal.json +45 -0
  867. package/.ikie/ferments/019f2764-7a9f-747c-81ce-f27825e1cefb/pending-proposal.json +45 -0
  868. package/.ikie/ferments/019f2764-7afc-745a-8d70-a2ebf234977d/pending-proposal.json +45 -0
  869. package/.ikie/ferments/019f2764-7b0f-715d-a410-e707593c0f1b/pending-proposal.json +45 -0
  870. package/.ikie/ferments/019f2764-a49c-750d-8022-8d5ef7b34341/runtime.json +13 -0
  871. package/.ikie/ferments/019f2764-a4c0-7779-a268-1589e2c4d025/runtime.json +11 -0
  872. package/.ikie/ferments/019f2764-a4e2-706f-8cc3-f71f13a5334c/runtime.json +11 -0
  873. package/.ikie/ferments/019f2764-a4fc-765c-b248-0fd90d273737/runtime.json +11 -0
  874. package/.ikie/ferments/019f2764-a511-7719-b577-47d9389dc68c/runtime.json +11 -0
  875. package/.ikie/ferments/019f2764-a524-731c-91d5-99c2242128e7/runtime.json +11 -0
  876. package/.ikie/ferments/019f2764-a53c-7308-a4a2-2c4ebd0af1f2/runtime.json +11 -0
  877. package/.ikie/ferments/019f2764-a555-762a-b6ec-c7a1ea59914b/runtime.json +11 -0
  878. package/.ikie/ferments/019f2764-a56e-776a-8421-d52ce16332e6/runtime.json +9 -0
  879. package/.ikie/ferments/019f2764-a584-75ad-8cf4-02ad739aeac6/runtime.json +13 -0
  880. package/.ikie/ferments/019f2764-a5a6-716c-8803-03dfe8638639/runtime.json +11 -0
  881. package/.ikie/ferments/019f2764-a5cb-75a8-9184-8bc493e04858/runtime.json +11 -0
  882. package/.ikie/ferments/019f2764-a613-726d-9770-828b95668f3d/runtime.json +11 -0
  883. package/.ikie/ferments/019f2764-a62b-703f-ad34-e560da58091f/runtime.json +9 -0
  884. package/.ikie/ferments/019f2764-a646-75a7-a048-e1c6a57c17db/runtime.json +9 -0
  885. package/.ikie/ferments/019f2764-a65d-7369-8043-22e8aa877564/runtime.json +11 -0
  886. package/.ikie/ferments/019f2764-a714-7737-9aca-229d1f730df1/runtime.json +11 -0
  887. package/.ikie/ferments/019f2764-a725-71af-91db-6146483607ce/runtime.json +12 -0
  888. package/.ikie/ferments/019f2764-a748-721c-a9bb-9a5cd1a6390b/runtime.json +11 -0
  889. package/.ikie/ferments/019f2764-a761-7632-84ba-5d4da92e371d/runtime.json +11 -0
  890. package/.ikie/ferments/019f2764-a776-76dd-a48e-148e4d5e6dcd/runtime.json +11 -0
  891. package/.ikie/ferments/019f2764-a78f-77d0-9647-ffb2ed828229/runtime.json +11 -0
  892. package/.ikie/ferments/019f2764-a7ab-716e-958d-c3f3c4d33a34/runtime.json +13 -0
  893. package/.ikie/ferments/019f2764-a7cb-775b-8844-8faa27f1ac1c/runtime.json +11 -0
  894. package/.ikie/ferments/019f2764-bd5e-773d-9b24-9da824db3174/reviews/phase-phase-1-1.json +41 -0
  895. package/.ikie/ferments/019f2764-bd5e-773d-9b24-9da824db3174/runtime.json +11 -0
  896. package/.ikie/ferments/019f2764-bda9-7207-b421-beff2d49cd2a/reviews/phase-phase-1-1.json +47 -0
  897. package/.ikie/ferments/019f2764-bda9-7207-b421-beff2d49cd2a/runtime.json +13 -0
  898. package/.ikie/ferments/019f2764-be1e-775f-b937-81b9fd368168/reviews/phase-phase-1-1.json +40 -0
  899. package/.ikie/ferments/019f2764-be1e-775f-b937-81b9fd368168/runtime.json +9 -0
  900. package/.ikie/ferments/019f2764-be38-7792-b549-8583fd6c5e70/reviews/phase-phase-1-1.json +40 -0
  901. package/.ikie/ferments/019f2764-be38-7792-b549-8583fd6c5e70/runtime.json +9 -0
  902. package/.ikie/ferments/019f2764-be5e-73da-85c5-508167795c94/reviews/phase-phase-1-1.json +40 -0
  903. package/.ikie/ferments/019f2764-be5e-73da-85c5-508167795c94/runtime.json +9 -0
  904. package/.ikie/ferments/019f2764-be82-721a-aa06-3b54c6236827/reviews/phase-phase-1-1.json +40 -0
  905. package/.ikie/ferments/019f2764-be82-721a-aa06-3b54c6236827/runtime.json +9 -0
  906. package/.ikie/ferments/019f2764-be97-703d-8e0a-6496ed0a83ca/reviews/phase-phase-1-1.json +40 -0
  907. package/.ikie/ferments/019f2764-be97-703d-8e0a-6496ed0a83ca/runtime.json +9 -0
  908. package/.ikie/ferments/019f2764-bebc-756a-a6ca-0f40b9705a0f/reviews/phase-phase-1-1.json +62 -0
  909. package/.ikie/ferments/019f2764-bebc-756a-a6ca-0f40b9705a0f/runtime.json +9 -0
  910. package/.ikie/ferments/019f2766-a81a-73aa-ba58-4a0192a7b079/runtime.json +11 -0
  911. package/.ikie/ferments/019f2766-a839-708c-b3bf-4c3f2279558e/runtime.json +11 -0
  912. package/.ikie/ferments/019f2766-a852-7641-a85f-69ea0ce5d73b/runtime.json +11 -0
  913. package/.ikie/ferments/019f2766-a877-74b8-b1de-3ffbbcb6f14b/runtime.json +12 -0
  914. package/.ikie/ferments/019f2766-a892-767d-b447-2e7a666f42f0/runtime.json +11 -0
  915. package/.ikie/ferments/019f2766-a8c2-7178-b06c-00d7646d1966/runtime.json +11 -0
  916. package/.ikie/ferments/019f2766-a8f5-713b-92d4-c4c70e48c5db/runtime.json +15 -0
  917. package/.ikie/ferments/019f2766-a91c-76a8-9d47-7e07b7843506/runtime.json +15 -0
  918. package/.ikie/ferments/019f2766-a944-7458-bae5-e3c38b3eec06/runtime.json +15 -0
  919. package/.ikie/ferments/019f2766-a973-77da-b2c0-d4f59f145d19/runtime.json +13 -0
  920. package/.ikie/ferments/019f2766-a9ae-701f-b8af-2d02369bc2f1/runtime.json +15 -0
  921. package/.ikie/ferments/019f2766-a9e5-7319-882f-58450ee132ea/runtime.json +15 -0
  922. package/.ikie/ferments/019f2766-aa3a-722b-9ed0-f38465896d02/runtime.json +11 -0
  923. package/.ikie/ferments/019f2766-aa58-7389-b25e-688385ff4a7f/runtime.json +15 -0
  924. package/.ikie/ferments/019f2766-aa8c-72f1-8b4e-a5260ac64189/runtime.json +15 -0
  925. package/.ikie/ferments/019f2766-aab7-7310-a9ec-b3027823b960/runtime.json +15 -0
  926. package/.ikie/ferments/019f2766-aae0-714c-b796-491d0c0d0e5b/runtime.json +15 -0
  927. package/.ikie/ferments/019f2766-ab05-740a-9fe0-2882dcad789b/runtime.json +15 -0
  928. package/.ikie/ferments/019f2766-ab2d-7188-9d25-545da08208e3/runtime.json +15 -0
  929. package/.ikie/ferments/019f2766-ab55-71d1-aafa-b6c62c6d7c7c/runtime.json +15 -0
  930. package/.ikie/ferments/019f2766-ab7f-76a1-9cde-c84ebb38a76c/runtime.json +15 -0
  931. package/.ikie/ferments/019f2766-abad-71db-9b6c-c341a91e609c/runtime.json +15 -0
  932. package/.ikie/ferments/019f2766-abd1-7392-a14e-a62f58887e86/runtime.json +11 -0
  933. package/.ikie/ferments/019f2766-abee-7229-9251-77f5474df062/runtime.json +11 -0
  934. package/.ikie/ferments/019f2766-ac13-77ab-ad1f-179bbf19f285/reviews/phase-phase-1-1.json +63 -0
  935. package/.ikie/ferments/019f2766-ac13-77ab-ad1f-179bbf19f285/runtime.json +17 -0
  936. package/.ikie/ferments/019f2766-ad4e-771a-8809-da61d5e9187d/reviews/phase-phase-1-1.json +63 -0
  937. package/.ikie/ferments/019f2766-ad4e-771a-8809-da61d5e9187d/runtime.json +17 -0
  938. package/.ikie/ferments/019f2766-aec7-72c7-8400-65d8774d93fe/runtime.json +11 -0
  939. package/.ikie/ferments/019f2766-b2e5-775e-a211-97476c9184fa/runtime.json +11 -0
  940. package/.ikie/ferments/019f2766-b303-70c5-a66a-e39ce29d0a4a/runtime.json +11 -0
  941. package/.ikie/ferments/019f2766-b32e-7618-860c-3cf1a98c2562/runtime.json +11 -0
  942. package/.ikie/ferments/019f2766-b353-719b-9299-207b9a3b41b3/runtime.json +11 -0
  943. package/.ikie/ferments/019f2766-b374-72e3-a804-8f3c82dc2059/pending-proposal.json +45 -0
  944. package/.ikie/ferments/019f2766-b38b-75ca-83c3-d4e5625f814b/pending-proposal.json +45 -0
  945. package/.ikie/ferments/019f2766-b495-73d6-a0d3-b26c033d4769/pending-proposal.json +45 -0
  946. package/.ikie/ferments/019f2766-b4e1-70f8-a38e-c478ab72c091/pending-proposal.json +45 -0
  947. package/.ikie/ferments/019f2766-b4f5-7671-b2c4-76d6f9f68cd3/pending-proposal.json +45 -0
  948. package/.ikie/ferments/019f2766-d341-7410-8d94-056f70b5d884/runtime.json +11 -0
  949. package/.ikie/ferments/019f2766-d35f-71a3-bdd3-c749aa870ff8/runtime.json +11 -0
  950. package/.ikie/ferments/019f2766-d382-70be-9a79-094070335d58/runtime.json +11 -0
  951. package/.ikie/ferments/019f2766-d3ae-75c7-b83e-4636e859cf7d/runtime.json +12 -0
  952. package/.ikie/ferments/019f2766-d3c7-778d-b399-f3e13fa34204/runtime.json +11 -0
  953. package/.ikie/ferments/019f2766-d3f0-7730-9e47-9bbc5483d5c9/runtime.json +11 -0
  954. package/.ikie/ferments/019f2766-d422-74ab-8e0b-6b5f139658b8/runtime.json +15 -0
  955. package/.ikie/ferments/019f2766-d448-7428-94ec-084521c6f60a/runtime.json +15 -0
  956. package/.ikie/ferments/019f2766-d46e-730e-89a6-dd0907baa5aa/runtime.json +15 -0
  957. package/.ikie/ferments/019f2766-d49b-71df-91f7-b4fb8e050c88/runtime.json +13 -0
  958. package/.ikie/ferments/019f2766-d4d6-72fd-b5ab-8aa8554c3ac8/runtime.json +15 -0
  959. package/.ikie/ferments/019f2766-d50b-7146-a0e2-bcc33cbf8168/runtime.json +15 -0
  960. package/.ikie/ferments/019f2766-d54e-7614-a157-8c6225b09552/runtime.json +11 -0
  961. package/.ikie/ferments/019f2766-d571-72f9-ac5f-9a58f8913af1/runtime.json +15 -0
  962. package/.ikie/ferments/019f2766-d5aa-7756-b523-29a10b1f0f93/runtime.json +15 -0
  963. package/.ikie/ferments/019f2766-d5ce-77b9-9746-ca5281e76d1e/runtime.json +15 -0
  964. package/.ikie/ferments/019f2766-d5f2-76ee-92f0-88e85515bb8c/runtime.json +15 -0
  965. package/.ikie/ferments/019f2766-d617-7669-8175-57038e3790b0/runtime.json +15 -0
  966. package/.ikie/ferments/019f2766-d63b-72aa-a6ca-f355b068db00/runtime.json +15 -0
  967. package/.ikie/ferments/019f2766-d664-754e-b827-42f9c6fc161b/runtime.json +15 -0
  968. package/.ikie/ferments/019f2766-d68c-710d-8769-befe67aad042/runtime.json +15 -0
  969. package/.ikie/ferments/019f2766-d6af-767c-9547-eee7f9c08dcf/runtime.json +15 -0
  970. package/.ikie/ferments/019f2766-d6d5-751e-8752-dcdc451712e2/runtime.json +11 -0
  971. package/.ikie/ferments/019f2766-d6f7-77b8-807d-75d914ff0302/runtime.json +11 -0
  972. package/.ikie/ferments/019f2766-d720-7159-97a9-820f305b3805/reviews/phase-phase-1-1.json +63 -0
  973. package/.ikie/ferments/019f2766-d720-7159-97a9-820f305b3805/runtime.json +17 -0
  974. package/.ikie/ferments/019f2766-d87f-729d-be05-90c4adb20ade/reviews/phase-phase-1-1.json +63 -0
  975. package/.ikie/ferments/019f2766-d87f-729d-be05-90c4adb20ade/runtime.json +17 -0
  976. package/.ikie/ferments/019f2766-da17-724b-ab3c-7154c7845381/runtime.json +11 -0
  977. package/.ikie/ferments/019f2766-ddf5-7470-a884-297c8936753a/runtime.json +11 -0
  978. package/.ikie/ferments/019f2766-de1a-7283-89b6-a249b9c8bdc1/runtime.json +11 -0
  979. package/.ikie/ferments/019f2766-de39-7771-a717-14beb4313f79/runtime.json +11 -0
  980. package/.ikie/ferments/019f2766-de5b-7418-bbcc-2ed38543137c/runtime.json +11 -0
  981. package/.ikie/ferments/019f2766-de7d-76cc-a74f-def9d1d99ac3/pending-proposal.json +45 -0
  982. package/.ikie/ferments/019f2766-de92-75a2-bcae-86efd5efe066/pending-proposal.json +45 -0
  983. package/.ikie/ferments/019f2766-dfb5-771c-adc0-9e948e0b8f18/pending-proposal.json +45 -0
  984. package/.ikie/ferments/019f2766-dff6-71cd-a14e-ab9e88792ca4/pending-proposal.json +45 -0
  985. package/.ikie/ferments/019f2766-e006-727b-83d9-af9c71158bef/pending-proposal.json +45 -0
  986. package/.ikie/ferments/019f2767-0345-74ba-a163-0c909ee37df1/runtime.json +11 -0
  987. package/.ikie/ferments/019f2767-036c-713d-9ef9-58a1191bd341/runtime.json +11 -0
  988. package/.ikie/ferments/019f2767-0387-72e6-b8b6-314fedade6e0/runtime.json +11 -0
  989. package/.ikie/ferments/019f2767-03af-738b-acde-360fa30a55f8/runtime.json +12 -0
  990. package/.ikie/ferments/019f2767-03cc-76e8-ae01-5b33c85fb46b/runtime.json +11 -0
  991. package/.ikie/ferments/019f2767-0409-7745-8f9d-a41ce8b7b11e/runtime.json +11 -0
  992. package/.ikie/ferments/019f2767-0467-70a9-8a75-2688109ab9c3/runtime.json +15 -0
  993. package/.ikie/ferments/019f2767-0493-7047-b2c9-a7ed6f70c89f/runtime.json +15 -0
  994. package/.ikie/ferments/019f2767-04b7-7486-a7cf-5ad7a09060a7/runtime.json +15 -0
  995. package/.ikie/ferments/019f2767-050f-713f-ba94-c01b549b3dfa/runtime.json +13 -0
  996. package/.ikie/ferments/019f2767-0561-7481-90da-2febe6cffddd/runtime.json +15 -0
  997. package/.ikie/ferments/019f2767-059c-74bb-b3fb-5e762939b3f6/runtime.json +15 -0
  998. package/.ikie/ferments/019f2767-05f6-7778-87d7-bd17f16cbfb5/runtime.json +11 -0
  999. package/.ikie/ferments/019f2767-0621-765e-9af4-4fd53e8fa0ec/runtime.json +15 -0
  1000. package/.ikie/ferments/019f2767-0652-77a4-86f8-fd32c3d03927/runtime.json +15 -0
  1001. package/.ikie/ferments/019f2767-067b-734b-85e5-cd7fc79c73cb/runtime.json +15 -0
  1002. package/.ikie/ferments/019f2767-06aa-71fa-a287-db9463cdae51/runtime.json +15 -0
  1003. package/.ikie/ferments/019f2767-06d5-771d-8f7b-cb18b2f9f122/runtime.json +15 -0
  1004. package/.ikie/ferments/019f2767-070a-7043-87fe-09012eaea4d6/runtime.json +15 -0
  1005. package/.ikie/ferments/019f2767-0733-707e-b141-7af7e0e43e30/runtime.json +15 -0
  1006. package/.ikie/ferments/019f2767-0751-7478-ae88-39af753f8f08/runtime.json +15 -0
  1007. package/.ikie/ferments/019f2767-0791-73af-be60-fe5a809f66bc/runtime.json +15 -0
  1008. package/.ikie/ferments/019f2767-07c5-720a-b9b7-1f96816c4122/runtime.json +11 -0
  1009. package/.ikie/ferments/019f2767-07e4-74fc-bf92-5f4c9c1cefab/runtime.json +11 -0
  1010. package/.ikie/ferments/019f2767-080c-77c8-a174-e8b97bd69510/reviews/phase-phase-1-1.json +63 -0
  1011. package/.ikie/ferments/019f2767-080c-77c8-a174-e8b97bd69510/runtime.json +17 -0
  1012. package/.ikie/ferments/019f2767-0986-7509-b1d0-7650aae65deb/reviews/phase-phase-1-1.json +63 -0
  1013. package/.ikie/ferments/019f2767-0986-7509-b1d0-7650aae65deb/runtime.json +17 -0
  1014. package/.ikie/ferments/019f2767-0b6e-7011-aec4-f728f98727ed/runtime.json +11 -0
  1015. package/.ikie/ferments/019f2767-10a6-75cc-850a-34d704f7eac9/runtime.json +11 -0
  1016. package/.ikie/ferments/019f2767-10cf-70aa-a00c-086ec4813201/runtime.json +11 -0
  1017. package/.ikie/ferments/019f2767-1101-74f7-8518-da795dd7aef7/runtime.json +11 -0
  1018. package/.ikie/ferments/019f2767-1140-738e-b9ce-35b94e415549/runtime.json +11 -0
  1019. package/.ikie/ferments/019f2767-1172-75a9-8f24-74316bfc7d53/pending-proposal.json +45 -0
  1020. package/.ikie/ferments/019f2767-118b-7048-a5d7-cffbef0e44e2/pending-proposal.json +45 -0
  1021. package/.ikie/ferments/019f2767-12be-730b-92b2-0bba958b78a1/pending-proposal.json +45 -0
  1022. package/.ikie/ferments/019f2767-131f-720b-b45a-382835a523ef/pending-proposal.json +45 -0
  1023. package/.ikie/ferments/019f2767-1335-74eb-b84c-9af1e9e52ff0/pending-proposal.json +45 -0
  1024. package/.ikie/ferments/019f2767-4563-715a-8c3c-cadf61ab94cf/runtime.json +13 -0
  1025. package/.ikie/ferments/019f2767-45b2-701b-990c-a8a30ff2c5f2/runtime.json +11 -0
  1026. package/.ikie/ferments/019f2767-45d7-705e-a8fc-202c2c894d5f/runtime.json +11 -0
  1027. package/.ikie/ferments/019f2767-45ee-773f-a4e7-6022c91b113c/runtime.json +11 -0
  1028. package/.ikie/ferments/019f2767-4613-7769-b4fa-6abde054e49d/runtime.json +11 -0
  1029. package/.ikie/ferments/019f2767-4626-704a-9d3e-6d51ff2c45c6/runtime.json +11 -0
  1030. package/.ikie/ferments/019f2767-4637-7346-b00e-35216ec55688/runtime.json +11 -0
  1031. package/.ikie/ferments/019f2767-4649-709c-9269-7d92ac49807a/runtime.json +11 -0
  1032. package/.ikie/ferments/019f2767-465e-76ec-a7c0-c63d79f0807f/runtime.json +9 -0
  1033. package/.ikie/ferments/019f2767-4679-76c1-8e62-1c105c4c6b0b/runtime.json +13 -0
  1034. package/.ikie/ferments/019f2767-4692-762a-963b-a53456d259fc/runtime.json +11 -0
  1035. package/.ikie/ferments/019f2767-46a7-7236-9510-fd0d5ecf273f/runtime.json +11 -0
  1036. package/.ikie/ferments/019f2767-46ee-705c-ad1a-e028ca79062a/runtime.json +11 -0
  1037. package/.ikie/ferments/019f2767-4702-741b-bb09-b4fd8cd9f15a/runtime.json +9 -0
  1038. package/.ikie/ferments/019f2767-4720-7192-9e90-89cc2710255a/runtime.json +9 -0
  1039. package/.ikie/ferments/019f2767-475f-70dc-9883-271aaa69c2b4/runtime.json +11 -0
  1040. package/.ikie/ferments/019f2767-4852-749f-9c8b-920b2c2b25d3/runtime.json +11 -0
  1041. package/.ikie/ferments/019f2767-486c-7309-a9ff-92579b04dc8c/runtime.json +12 -0
  1042. package/.ikie/ferments/019f2767-4899-771f-9f50-89e448dff488/runtime.json +11 -0
  1043. package/.ikie/ferments/019f2767-48ae-7328-a163-a959e2087743/runtime.json +11 -0
  1044. package/.ikie/ferments/019f2767-48ce-717a-828c-6b765da0a306/runtime.json +11 -0
  1045. package/.ikie/ferments/019f2767-48ef-707c-a17e-9db9da0eee1f/runtime.json +11 -0
  1046. package/.ikie/ferments/019f2767-490b-704b-9369-05fcbb050e2b/runtime.json +13 -0
  1047. package/.ikie/ferments/019f2767-4938-752e-a022-f76dadf8fcaf/runtime.json +11 -0
  1048. package/.ikie/ferments/019f2767-5cc6-73b9-b8e4-cb3719bbdc8d/reviews/phase-phase-1-1.json +41 -0
  1049. package/.ikie/ferments/019f2767-5cc6-73b9-b8e4-cb3719bbdc8d/runtime.json +11 -0
  1050. package/.ikie/ferments/019f2767-5d22-7419-840b-e18d2fe5a41d/reviews/phase-phase-1-1.json +47 -0
  1051. package/.ikie/ferments/019f2767-5d22-7419-840b-e18d2fe5a41d/runtime.json +13 -0
  1052. package/.ikie/ferments/019f2767-5d8c-75b0-bf28-5a0781cd0686/reviews/phase-phase-1-1.json +40 -0
  1053. package/.ikie/ferments/019f2767-5d8c-75b0-bf28-5a0781cd0686/runtime.json +9 -0
  1054. package/.ikie/ferments/019f2767-5dae-76e9-b23a-366527e3a529/reviews/phase-phase-1-1.json +40 -0
  1055. package/.ikie/ferments/019f2767-5dae-76e9-b23a-366527e3a529/runtime.json +9 -0
  1056. package/.ikie/ferments/019f2767-5dd4-73bf-821e-d74e53b266e1/reviews/phase-phase-1-1.json +40 -0
  1057. package/.ikie/ferments/019f2767-5dd4-73bf-821e-d74e53b266e1/runtime.json +9 -0
  1058. package/.ikie/ferments/019f2767-5de9-7518-a677-02b4926a0196/reviews/phase-phase-1-1.json +40 -0
  1059. package/.ikie/ferments/019f2767-5de9-7518-a677-02b4926a0196/runtime.json +9 -0
  1060. package/.ikie/ferments/019f2767-5dff-772a-b855-57afbb5e9c7e/reviews/phase-phase-1-1.json +40 -0
  1061. package/.ikie/ferments/019f2767-5dff-772a-b855-57afbb5e9c7e/runtime.json +9 -0
  1062. package/.ikie/ferments/019f2767-5e39-76a5-8dcc-6f9004f4a58e/reviews/phase-phase-1-1.json +62 -0
  1063. package/.ikie/ferments/019f2767-5e39-76a5-8dcc-6f9004f4a58e/runtime.json +9 -0
  1064. package/.ikie/ferments/019f2769-b766-74eb-844e-9903bf64f06d/runtime.json +11 -0
  1065. package/.ikie/ferments/019f2769-b784-72fa-a138-7bdc2fc6e070/runtime.json +11 -0
  1066. package/.ikie/ferments/019f2769-b79d-745b-b577-2ee15d5649b0/runtime.json +11 -0
  1067. package/.ikie/ferments/019f2769-b7c3-75be-9db0-360b0deea44b/runtime.json +12 -0
  1068. package/.ikie/ferments/019f2769-b7e0-758f-bd6a-734520ad3afa/runtime.json +11 -0
  1069. package/.ikie/ferments/019f2769-b807-721e-8827-30e490c8823c/runtime.json +11 -0
  1070. package/.ikie/ferments/019f2769-b836-727d-9c7f-b5a5f03dcc56/runtime.json +15 -0
  1071. package/.ikie/ferments/019f2769-b858-76ae-9fe0-b56d97afdf9b/runtime.json +15 -0
  1072. package/.ikie/ferments/019f2769-b87a-716c-9c81-14f1fa52f217/runtime.json +15 -0
  1073. package/.ikie/ferments/019f2769-b8a2-73dc-9d6d-ac781b700816/runtime.json +13 -0
  1074. package/.ikie/ferments/019f2769-b8d1-7689-9405-e97b063ec3a1/runtime.json +15 -0
  1075. package/.ikie/ferments/019f2769-b904-7154-8946-12e041f89921/runtime.json +15 -0
  1076. package/.ikie/ferments/019f2769-b941-713f-8e2b-1a608dec7ca6/runtime.json +11 -0
  1077. package/.ikie/ferments/019f2769-b95b-7122-bb5d-0bb3a2ad220a/runtime.json +15 -0
  1078. package/.ikie/ferments/019f2769-b97d-728d-b8fb-b1f302b1d819/runtime.json +15 -0
  1079. package/.ikie/ferments/019f2769-b99d-747b-853b-e415c006bfd2/runtime.json +15 -0
  1080. package/.ikie/ferments/019f2769-b9c0-76d6-a254-fba31ac6b662/runtime.json +15 -0
  1081. package/.ikie/ferments/019f2769-b9dd-7349-b246-95853d5d3af0/runtime.json +15 -0
  1082. package/.ikie/ferments/019f2769-b9fe-774f-80cd-06bfedd8a956/runtime.json +15 -0
  1083. package/.ikie/ferments/019f2769-ba1e-70d2-af18-3ea245abc903/runtime.json +15 -0
  1084. package/.ikie/ferments/019f2769-ba45-7730-aae9-9ca14bc6a81b/runtime.json +15 -0
  1085. package/.ikie/ferments/019f2769-ba72-7273-903c-d33bcd036a6b/runtime.json +15 -0
  1086. package/.ikie/ferments/019f2769-ba93-70f3-8884-7b067dd711a4/runtime.json +11 -0
  1087. package/.ikie/ferments/019f2769-baad-714f-8207-a7d630f37e84/runtime.json +11 -0
  1088. package/.ikie/ferments/019f2769-bac7-75ae-95cb-dda85f7fd6a8/reviews/phase-phase-1-1.json +63 -0
  1089. package/.ikie/ferments/019f2769-bac7-75ae-95cb-dda85f7fd6a8/runtime.json +17 -0
  1090. package/.ikie/ferments/019f2769-bbf3-745d-87d3-d594593afbf0/reviews/phase-phase-1-1.json +63 -0
  1091. package/.ikie/ferments/019f2769-bbf3-745d-87d3-d594593afbf0/runtime.json +17 -0
  1092. package/.ikie/ferments/019f2769-bd4e-735d-b931-2077f62d385a/runtime.json +11 -0
  1093. package/.ikie/ferments/019f2769-c103-723f-aebe-ab3ae76aedd9/runtime.json +11 -0
  1094. package/.ikie/ferments/019f2769-c11e-771a-b365-96bf54691b95/runtime.json +11 -0
  1095. package/.ikie/ferments/019f2769-c13b-749e-840d-5136528371f3/runtime.json +11 -0
  1096. package/.ikie/ferments/019f2769-c15a-7065-83b5-2064b699a6d9/runtime.json +11 -0
  1097. package/.ikie/ferments/019f2769-c175-77b2-80df-918134508175/pending-proposal.json +45 -0
  1098. package/.ikie/ferments/019f2769-c189-7508-8a46-3ff461bf759f/pending-proposal.json +45 -0
  1099. package/.ikie/ferments/019f2769-c27c-71eb-910f-36daf69588f8/pending-proposal.json +45 -0
  1100. package/.ikie/ferments/019f2769-c2c5-71bd-b6a6-dd0f8365cc7c/pending-proposal.json +45 -0
  1101. package/.ikie/ferments/019f2769-c2d6-7260-bab6-3e46b6e9100c/pending-proposal.json +45 -0
  1102. package/.ikie/ferments/019f2769-e6d9-700b-a486-64cad0909610/runtime.json +11 -0
  1103. package/.ikie/ferments/019f2769-e6f5-7524-955a-dd4d91813ee5/runtime.json +11 -0
  1104. package/.ikie/ferments/019f2769-e713-715e-9450-42b5250709c8/runtime.json +11 -0
  1105. package/.ikie/ferments/019f2769-e738-7537-b5d5-5209200233da/runtime.json +12 -0
  1106. package/.ikie/ferments/019f2769-e769-752f-b806-14f369200356/runtime.json +11 -0
  1107. package/.ikie/ferments/019f2769-e795-77e8-bc69-fa7496923f00/runtime.json +15 -0
  1108. package/.ikie/ferments/019f2769-e7bb-72a8-ba2a-6d90fe6003cc/runtime.json +15 -0
  1109. package/.ikie/ferments/019f2769-e7e1-719b-becd-d456fe580bf8/runtime.json +15 -0
  1110. package/.ikie/ferments/019f2769-e80b-7539-ac23-4ccf01499e01/runtime.json +13 -0
  1111. package/.ikie/ferments/019f2769-e83e-77c7-8415-7b3e76c827b1/runtime.json +15 -0
  1112. package/.ikie/ferments/019f2769-e86c-7008-8cdb-4d2ae411fc57/runtime.json +15 -0
  1113. package/.ikie/ferments/019f2769-e8ac-7480-b1cc-6913e20e012f/runtime.json +11 -0
  1114. package/.ikie/ferments/019f2769-e8ca-76bd-b0be-bee2f2a97d7d/runtime.json +15 -0
  1115. package/.ikie/ferments/019f2769-e904-7759-b2aa-dbb47427c11b/runtime.json +15 -0
  1116. package/.ikie/ferments/019f2769-e92a-7285-bbd7-ed4220ac3f44/runtime.json +15 -0
  1117. package/.ikie/ferments/019f2769-e95e-77eb-9e17-6b2ad4532f0c/runtime.json +15 -0
  1118. package/.ikie/ferments/019f2769-e992-75ea-adf9-53f548b600a0/runtime.json +15 -0
  1119. package/.ikie/ferments/019f2769-e9b9-75bc-ab7a-a4ba5e8f1124/runtime.json +15 -0
  1120. package/.ikie/ferments/019f2769-e9ec-700b-990f-320c347ee271/runtime.json +15 -0
  1121. package/.ikie/ferments/019f2769-ea15-72cb-96af-a45603082ee1/runtime.json +15 -0
  1122. package/.ikie/ferments/019f2769-ea42-735c-b71e-259c75688841/runtime.json +15 -0
  1123. package/.ikie/ferments/019f2769-ea6f-7074-acde-65385abd199a/runtime.json +11 -0
  1124. package/.ikie/ferments/019f2769-ea98-759c-aeda-90b28cab640c/runtime.json +11 -0
  1125. package/.ikie/ferments/019f2769-eac3-70a7-993e-435d9a1dfd91/reviews/phase-phase-1-1.json +63 -0
  1126. package/.ikie/ferments/019f2769-eac3-70a7-993e-435d9a1dfd91/runtime.json +17 -0
  1127. package/.ikie/ferments/019f2769-ec3c-7674-829a-fba66a9bc62e/reviews/phase-phase-1-1.json +63 -0
  1128. package/.ikie/ferments/019f2769-ec3c-7674-829a-fba66a9bc62e/runtime.json +17 -0
  1129. package/.ikie/ferments/019f2769-edcb-748c-be28-51e21c608c6f/runtime.json +11 -0
  1130. package/.ikie/ferments/019f2769-f2df-7759-811f-ef76a54375e8/runtime.json +11 -0
  1131. package/.ikie/ferments/019f2769-f311-7641-88b0-81c54945642f/runtime.json +11 -0
  1132. package/.ikie/ferments/019f2769-f363-723b-80f1-b52334dc6a15/runtime.json +11 -0
  1133. package/.ikie/ferments/019f2769-f38e-72cc-a4ac-81cefc3a95f4/runtime.json +11 -0
  1134. package/.ikie/ferments/019f2769-f3b6-763a-bf65-011ce164f5d4/pending-proposal.json +45 -0
  1135. package/.ikie/ferments/019f2769-f3c7-745e-9da1-37e14b1cfddf/pending-proposal.json +45 -0
  1136. package/.ikie/ferments/019f2769-f4e4-71b1-83f1-b16014904ec3/pending-proposal.json +45 -0
  1137. package/.ikie/ferments/019f2769-f556-761d-b331-acc7cc02317d/pending-proposal.json +45 -0
  1138. package/.ikie/ferments/019f2769-f56d-77af-82f3-b9915ca80a61/pending-proposal.json +45 -0
  1139. package/.ikie/ferments/019f276a-23f9-7653-8be0-dca748ac5e0f/runtime.json +13 -0
  1140. package/.ikie/ferments/019f276a-2428-731f-959b-8d346551f0c4/runtime.json +11 -0
  1141. package/.ikie/ferments/019f276a-2446-7250-be5c-bdb0ac1ef2fa/runtime.json +11 -0
  1142. package/.ikie/ferments/019f276a-2462-764e-a7f4-d9ab3876fbd2/runtime.json +11 -0
  1143. package/.ikie/ferments/019f276a-2482-768b-919e-d81a0709abd5/runtime.json +11 -0
  1144. package/.ikie/ferments/019f276a-2494-77ee-8b28-72b9b0d19d56/runtime.json +11 -0
  1145. package/.ikie/ferments/019f276a-24aa-76fd-8fba-2a1d73960010/runtime.json +11 -0
  1146. package/.ikie/ferments/019f276a-24c3-7799-bd35-0a3374f3e469/runtime.json +11 -0
  1147. package/.ikie/ferments/019f276a-24f1-7498-a372-975f72302a0d/runtime.json +9 -0
  1148. package/.ikie/ferments/019f276a-251e-71ac-ba90-af2a49c22b6b/runtime.json +13 -0
  1149. package/.ikie/ferments/019f276a-2545-746f-bdf3-ca3c11ab9968/runtime.json +11 -0
  1150. package/.ikie/ferments/019f276a-256d-765b-9f94-90047d4ca21e/runtime.json +11 -0
  1151. package/.ikie/ferments/019f276a-25cb-753b-9905-7250e4eea970/runtime.json +11 -0
  1152. package/.ikie/ferments/019f276a-25f8-73a2-aede-f2c017fa80c9/runtime.json +9 -0
  1153. package/.ikie/ferments/019f276a-2613-774b-80c0-3b206ac95435/runtime.json +9 -0
  1154. package/.ikie/ferments/019f276a-264e-73a3-90ad-017ef8ea05b6/runtime.json +11 -0
  1155. package/.ikie/ferments/019f276a-2760-758f-b0a6-cd04a8b0ee76/runtime.json +11 -0
  1156. package/.ikie/ferments/019f276a-277b-73a9-8655-6bf7018262dc/runtime.json +12 -0
  1157. package/.ikie/ferments/019f276a-27a6-709d-a90f-f1784e248fca/runtime.json +11 -0
  1158. package/.ikie/ferments/019f276a-27b7-75bf-b0b5-013581917821/runtime.json +11 -0
  1159. package/.ikie/ferments/019f276a-27ce-759a-93de-474988efc050/runtime.json +11 -0
  1160. package/.ikie/ferments/019f276a-27e9-7564-999a-73beef96d35c/runtime.json +11 -0
  1161. package/.ikie/ferments/019f276a-27fc-714b-9ddb-117b439b664e/runtime.json +13 -0
  1162. package/.ikie/ferments/019f276a-2824-762e-8def-3c17aa4041f9/runtime.json +11 -0
  1163. package/.ikie/ferments/019f276a-38fe-725b-9c16-f1b5174302d0/reviews/phase-phase-1-1.json +41 -0
  1164. package/.ikie/ferments/019f276a-38fe-725b-9c16-f1b5174302d0/runtime.json +11 -0
  1165. package/.ikie/ferments/019f276a-393c-75e2-b29f-092b82105a74/reviews/phase-phase-1-1.json +47 -0
  1166. package/.ikie/ferments/019f276a-393c-75e2-b29f-092b82105a74/runtime.json +13 -0
  1167. package/.ikie/ferments/019f276a-3990-75f9-9b6f-ab6d45bf8e32/reviews/phase-phase-1-1.json +40 -0
  1168. package/.ikie/ferments/019f276a-3990-75f9-9b6f-ab6d45bf8e32/runtime.json +9 -0
  1169. package/.ikie/ferments/019f276a-39ab-76bb-be69-8658a1b6a76f/reviews/phase-phase-1-1.json +40 -0
  1170. package/.ikie/ferments/019f276a-39ab-76bb-be69-8658a1b6a76f/runtime.json +9 -0
  1171. package/.ikie/ferments/019f276a-39c9-76ac-95a8-2d5575d26573/reviews/phase-phase-1-1.json +40 -0
  1172. package/.ikie/ferments/019f276a-39c9-76ac-95a8-2d5575d26573/runtime.json +9 -0
  1173. package/.ikie/ferments/019f276a-39f6-76cc-9011-3f6b08068155/reviews/phase-phase-1-1.json +40 -0
  1174. package/.ikie/ferments/019f276a-39f6-76cc-9011-3f6b08068155/runtime.json +9 -0
  1175. package/.ikie/ferments/019f276a-3a0c-76a9-80b2-2bb7952fe9d7/reviews/phase-phase-1-1.json +40 -0
  1176. package/.ikie/ferments/019f276a-3a0c-76a9-80b2-2bb7952fe9d7/runtime.json +9 -0
  1177. package/.ikie/ferments/019f276a-3a22-7140-8a4d-0d17ada653b3/reviews/phase-phase-1-1.json +62 -0
  1178. package/.ikie/ferments/019f276a-3a22-7140-8a4d-0d17ada653b3/runtime.json +9 -0
  1179. package/.ikie/ferments/019f276c-2f88-74ae-8bc2-5cec42d56757/runtime.json +11 -0
  1180. package/.ikie/ferments/019f276c-2fb8-7599-b61c-e73c85399ee0/runtime.json +11 -0
  1181. package/.ikie/ferments/019f276c-2fd9-75db-8e13-8e9137cecedd/runtime.json +11 -0
  1182. package/.ikie/ferments/019f276c-302f-760f-97e7-2f10f283dfe1/runtime.json +12 -0
  1183. package/.ikie/ferments/019f276c-3060-77ca-a0e3-d49781feca6d/runtime.json +11 -0
  1184. package/.ikie/ferments/019f276c-3091-744e-9394-a59b9f37db9e/runtime.json +11 -0
  1185. package/.ikie/ferments/019f276c-30da-76ba-bd76-a72e053f218d/runtime.json +15 -0
  1186. package/.ikie/ferments/019f276c-3110-7277-ab9a-820992db76da/runtime.json +15 -0
  1187. package/.ikie/ferments/019f276c-314a-740f-b533-a31c4e9ebd52/runtime.json +15 -0
  1188. package/.ikie/ferments/019f276c-3189-732c-a4ec-09e4f1e3a8da/runtime.json +13 -0
  1189. package/.ikie/ferments/019f276c-31ce-75c8-a4e9-507d408920b6/runtime.json +15 -0
  1190. package/.ikie/ferments/019f276c-320e-710b-b32a-4577244dcc6a/runtime.json +15 -0
  1191. package/.ikie/ferments/019f276c-3262-7611-af21-ad12693acdd5/runtime.json +11 -0
  1192. package/.ikie/ferments/019f276c-3288-7559-b7c3-299dd548decb/runtime.json +15 -0
  1193. package/.ikie/ferments/019f276c-32c4-70a0-899d-ad17469a015c/runtime.json +15 -0
  1194. package/.ikie/ferments/019f276c-32f0-7036-86ae-19c9f703cd9a/runtime.json +15 -0
  1195. package/.ikie/ferments/019f276c-3324-7021-8f89-d46fbfa45e00/runtime.json +15 -0
  1196. package/.ikie/ferments/019f276c-334b-71df-b20d-d9a7bcccdc0a/runtime.json +15 -0
  1197. package/.ikie/ferments/019f276c-3379-7593-957a-ee9631368280/runtime.json +15 -0
  1198. package/.ikie/ferments/019f276c-33a9-705d-a590-eff1c46bcd67/runtime.json +15 -0
  1199. package/.ikie/ferments/019f276c-33d5-7784-b35a-01d3c06b16c0/runtime.json +15 -0
  1200. package/.ikie/ferments/019f276c-341c-76ce-b950-7a7e7472eeb8/runtime.json +15 -0
  1201. package/.ikie/ferments/019f276c-3462-744d-b42a-9756a33b7223/runtime.json +11 -0
  1202. package/.ikie/ferments/019f276c-348e-706a-9791-5213dfd00593/runtime.json +11 -0
  1203. package/.ikie/ferments/019f276c-34b6-70f9-b678-d3a7d876758c/reviews/phase-phase-1-1.json +63 -0
  1204. package/.ikie/ferments/019f276c-34b6-70f9-b678-d3a7d876758c/runtime.json +17 -0
  1205. package/.ikie/ferments/019f276c-3640-75da-915e-b0dba80bfcda/reviews/phase-phase-1-1.json +63 -0
  1206. package/.ikie/ferments/019f276c-3640-75da-915e-b0dba80bfcda/runtime.json +17 -0
  1207. package/.ikie/ferments/019f276c-37df-76f9-b7a8-1285ee0ac11d/runtime.json +11 -0
  1208. package/.ikie/ferments/019f276c-3caa-748a-a0aa-9e068f18f2ac/runtime.json +11 -0
  1209. package/.ikie/ferments/019f276c-3cc8-7347-9764-dd4ab7f87646/runtime.json +11 -0
  1210. package/.ikie/ferments/019f276c-3cef-75dd-be90-593fd20a850d/runtime.json +11 -0
  1211. package/.ikie/ferments/019f276c-3d14-72af-ae89-6c0605227a05/runtime.json +11 -0
  1212. package/.ikie/ferments/019f276c-3d36-716c-ac4e-59444fdec814/pending-proposal.json +45 -0
  1213. package/.ikie/ferments/019f276c-3d4c-7208-9130-7f168aeba08e/pending-proposal.json +45 -0
  1214. package/.ikie/ferments/019f276c-3e7f-7552-a37f-61442d720fb9/pending-proposal.json +45 -0
  1215. package/.ikie/ferments/019f276c-3ed9-74f2-9332-d5a492d39130/pending-proposal.json +45 -0
  1216. package/.ikie/ferments/019f276c-3ef4-757e-b0c6-9d7c6f0326e7/pending-proposal.json +45 -0
  1217. package/.ikie/ferments/019f276c-651d-70ac-bfb4-5d033388e28c/runtime.json +13 -0
  1218. package/.ikie/ferments/019f276c-6546-7569-b609-74b2258985a8/runtime.json +11 -0
  1219. package/.ikie/ferments/019f276c-6566-71e2-b937-390aea78900a/runtime.json +11 -0
  1220. package/.ikie/ferments/019f276c-657c-75ee-864b-5b5601e3b9d1/runtime.json +11 -0
  1221. package/.ikie/ferments/019f276c-6590-7729-a6e7-466ace311e0d/runtime.json +11 -0
  1222. package/.ikie/ferments/019f276c-65a5-779f-a3da-36bc91cf31f3/runtime.json +11 -0
  1223. package/.ikie/ferments/019f276c-65b9-77f0-97fc-fcf70d7125b8/runtime.json +11 -0
  1224. package/.ikie/ferments/019f276c-65cd-74ef-9094-db3c5a98348b/runtime.json +11 -0
  1225. package/.ikie/ferments/019f276c-65e3-7632-9df9-58cfa083a065/runtime.json +9 -0
  1226. package/.ikie/ferments/019f276c-65fb-763a-aec7-54ece64d7342/runtime.json +13 -0
  1227. package/.ikie/ferments/019f276c-661a-74e9-81b1-d1ba625c04b0/runtime.json +11 -0
  1228. package/.ikie/ferments/019f276c-6630-7748-ab90-869f75ed2de5/runtime.json +11 -0
  1229. package/.ikie/ferments/019f276c-6670-758f-b0da-673d81bd319e/runtime.json +11 -0
  1230. package/.ikie/ferments/019f276c-6687-71fa-8286-2d25de36c9b4/runtime.json +9 -0
  1231. package/.ikie/ferments/019f276c-669d-7679-91d5-4df6315d3823/runtime.json +9 -0
  1232. package/.ikie/ferments/019f276c-66b3-72a6-974d-1bc3477eb6f2/runtime.json +11 -0
  1233. package/.ikie/ferments/019f276c-6769-776c-9868-0c929ee31f5f/runtime.json +11 -0
  1234. package/.ikie/ferments/019f276c-678e-7588-a059-c1efd9e9c9a6/runtime.json +12 -0
  1235. package/.ikie/ferments/019f276c-67af-729c-a5f8-79e8e78bbe9b/runtime.json +11 -0
  1236. package/.ikie/ferments/019f276c-67c3-70b8-8606-aad72ab0cd6f/runtime.json +11 -0
  1237. package/.ikie/ferments/019f276c-67d7-734c-83fd-132c54564004/runtime.json +11 -0
  1238. package/.ikie/ferments/019f276c-67ec-710d-8497-eba65301d741/runtime.json +11 -0
  1239. package/.ikie/ferments/019f276c-6805-742c-8a1c-f370733226ae/runtime.json +13 -0
  1240. package/.ikie/ferments/019f276c-6825-7768-8ca1-f5dac5c1d374/runtime.json +11 -0
  1241. package/.ikie/ferments/019f276c-7f49-751d-bbb8-f828debd3cb9/reviews/phase-phase-1-1.json +41 -0
  1242. package/.ikie/ferments/019f276c-7f49-751d-bbb8-f828debd3cb9/runtime.json +11 -0
  1243. package/.ikie/ferments/019f276c-7f7b-74d0-b46e-e8efa73fb5b5/reviews/phase-phase-1-1.json +47 -0
  1244. package/.ikie/ferments/019f276c-7f7b-74d0-b46e-e8efa73fb5b5/runtime.json +13 -0
  1245. package/.ikie/ferments/019f276c-8004-74fe-b37f-f9fc659f7f0c/reviews/phase-phase-1-1.json +40 -0
  1246. package/.ikie/ferments/019f276c-8004-74fe-b37f-f9fc659f7f0c/runtime.json +9 -0
  1247. package/.ikie/ferments/019f276c-8025-7328-afef-6703215c208c/reviews/phase-phase-1-1.json +40 -0
  1248. package/.ikie/ferments/019f276c-8025-7328-afef-6703215c208c/runtime.json +9 -0
  1249. package/.ikie/ferments/019f276c-8043-749c-8cbb-47d0df9819df/reviews/phase-phase-1-1.json +40 -0
  1250. package/.ikie/ferments/019f276c-8043-749c-8cbb-47d0df9819df/runtime.json +9 -0
  1251. package/.ikie/ferments/019f276c-8062-7436-99eb-80e09bc6b067/reviews/phase-phase-1-1.json +40 -0
  1252. package/.ikie/ferments/019f276c-8062-7436-99eb-80e09bc6b067/runtime.json +9 -0
  1253. package/.ikie/ferments/019f276c-8081-727c-aa11-d606a64b88ed/reviews/phase-phase-1-1.json +40 -0
  1254. package/.ikie/ferments/019f276c-8081-727c-aa11-d606a64b88ed/runtime.json +9 -0
  1255. package/.ikie/ferments/019f276c-80b6-7528-8687-e11cc4691930/reviews/phase-phase-1-1.json +62 -0
  1256. package/.ikie/ferments/019f276c-80b6-7528-8687-e11cc4691930/runtime.json +9 -0
  1257. package/AGENTS.md +120 -0
  1258. package/CLA.md +39 -0
  1259. package/CODE_OF_CONDUCT.md +83 -0
  1260. package/CONTRIBUTING.md +57 -0
  1261. package/LICENSE +203 -0
  1262. package/NOTICE +28 -0
  1263. package/README.md +568 -0
  1264. package/SECURITY.md +36 -0
  1265. package/TODO.md +33 -0
  1266. package/benchmark/audit-session/README.md +217 -0
  1267. package/benchmark/audit-session/audit-session-prompt.md +557 -0
  1268. package/benchmark/audit-session/audit-session.sh +323 -0
  1269. package/benchmark/manual/README.md +166 -0
  1270. package/benchmark/manual/__pycache__/check-session.cpython-313.pyc +0 -0
  1271. package/benchmark/manual/analyze-session.py +290 -0
  1272. package/benchmark/manual/benchmark.json +4 -0
  1273. package/benchmark/manual/check-session.py +268 -0
  1274. package/benchmark/manual/compare-sessions.py +118 -0
  1275. package/benchmark/manual/lib.sh +284 -0
  1276. package/benchmark/manual/new-session-claude.sh +86 -0
  1277. package/benchmark/manual/new-session.sh +191 -0
  1278. package/benchmark/manual/run-evaluation.sh +201 -0
  1279. package/benchmark/manual/seeds/explore-refactor/cmd/server/main.go +37 -0
  1280. package/benchmark/manual/seeds/explore-refactor/go.mod +3 -0
  1281. package/benchmark/manual/seeds/explore-refactor/internal/handler/audit.go +39 -0
  1282. package/benchmark/manual/seeds/explore-refactor/internal/handler/invitation.go +56 -0
  1283. package/benchmark/manual/seeds/explore-refactor/internal/handler/team.go +86 -0
  1284. package/benchmark/manual/seeds/explore-refactor/internal/handler/user.go +126 -0
  1285. package/benchmark/manual/seeds/explore-refactor/internal/model/model.go +37 -0
  1286. package/benchmark/manual/seeds/explore-refactor/internal/repository/audit.go +57 -0
  1287. package/benchmark/manual/seeds/explore-refactor/internal/repository/invitation.go +58 -0
  1288. package/benchmark/manual/seeds/explore-refactor/internal/repository/team.go +66 -0
  1289. package/benchmark/manual/seeds/explore-refactor/internal/repository/user.go +91 -0
  1290. package/benchmark/manual/seeds/explore-refactor/internal/service/invitation.go +45 -0
  1291. package/benchmark/manual/seeds/explore-refactor/internal/service/team.go +62 -0
  1292. package/benchmark/manual/seeds/explore-refactor/internal/service/user.go +94 -0
  1293. package/benchmark/manual/self-improvement.md +203 -0
  1294. package/benchmark/manual/session-summary.py +95 -0
  1295. package/benchmark/manual/start-self-improvement.sh +27 -0
  1296. package/benchmark/manual/tasks.md +154 -0
  1297. package/benchmark/terminal-bench-2/README.md +261 -0
  1298. package/benchmark/terminal-bench-2/config/retry.yaml +48 -0
  1299. package/benchmark/terminal-bench-2/docs/ferment-terminal-bench-analysis.md +233 -0
  1300. package/benchmark/terminal-bench-2/pyproject.toml +32 -0
  1301. package/benchmark/terminal-bench-2/scripts/analyze-ferment-bench.py +1193 -0
  1302. package/benchmark/terminal-bench-2/scripts/run-claude-code-ikie.sh +41 -0
  1303. package/benchmark/terminal-bench-2/scripts/run-gsd-ikie.sh +29 -0
  1304. package/benchmark/terminal-bench-2/scripts/run-local.sh +32 -0
  1305. package/benchmark/terminal-bench-2/scripts/run-opencode-ikie.sh +30 -0
  1306. package/benchmark/terminal-bench-2/scripts/run-release.sh +28 -0
  1307. package/benchmark/terminal-bench-2/src/ikie_agent/__init__.py +6 -0
  1308. package/benchmark/terminal-bench-2/src/ikie_agent/agent.py +445 -0
  1309. package/benchmark/terminal-bench-2/src/ikie_agent/agent_test.py +233 -0
  1310. package/benchmark/terminal-bench-2/src/ikie_agent/claude_code_ikie.py +356 -0
  1311. package/benchmark/terminal-bench-2/src/ikie_agent/claude_code_ikie_test.py +506 -0
  1312. package/benchmark/terminal-bench-2/src/ikie_agent/config.py +56 -0
  1313. package/benchmark/terminal-bench-2/src/ikie_agent/gateway.py +163 -0
  1314. package/benchmark/terminal-bench-2/src/ikie_agent/gsd_ikie.py +340 -0
  1315. package/benchmark/terminal-bench-2/src/ikie_agent/gsd_ikie_test.py +304 -0
  1316. package/benchmark/terminal-bench-2/src/ikie_agent/messages.py +27 -0
  1317. package/benchmark/terminal-bench-2/src/ikie_agent/opencode_ikie.py +146 -0
  1318. package/benchmark/terminal-bench-2/src/ikie_agent/opencode_ikie_test.py +308 -0
  1319. package/benchmark/terminal-bench-2/src/ikie_agent/release.py +174 -0
  1320. package/benchmark/terminal-bench-2/src/ikie_agent/retry_config_test.py +55 -0
  1321. package/benchmark/terminal-bench-2/uv.lock +1948 -0
  1322. package/biome.json +54 -0
  1323. package/docs/agents.md +295 -0
  1324. package/docs/bash-tool-guard.md +206 -0
  1325. package/docs/expected-execution-scenarios.md +348 -0
  1326. package/docs/ferment-storage-schema.md +199 -0
  1327. package/docs/ferment.md +633 -0
  1328. package/docs/hooks.md +263 -0
  1329. package/docs/subagents/README.md +22 -0
  1330. package/docs/subagents/code-reviewer.md +39 -0
  1331. package/docs/subagents/research-assistant.md +81 -0
  1332. package/docs/subagents/test-writer.md +49 -0
  1333. package/docs/teleport.md +424 -0
  1334. package/docs/windows/README.md +226 -0
  1335. package/extensions/active-tools.ts +74 -0
  1336. package/ikie.png +0 -0
  1337. package/package.json +125 -0
  1338. package/patches/@earendil-works__pi-ai@0.78.1.patch +68 -0
  1339. package/patches/@earendil-works__pi-coding-agent@0.78.1.patch +535 -0
  1340. package/patches/@earendil-works__pi-tui.patch +171 -0
  1341. package/patches/playwright-core@1.59.1.patch +24 -0
  1342. package/resources/oauth/error.html +185 -0
  1343. package/resources/oauth/success.html +185 -0
  1344. package/scripts/build-binary.js +113 -0
  1345. package/scripts/build-proxy-helper.js +66 -0
  1346. package/scripts/copy-resources.js +104 -0
  1347. package/scripts/dev-overlay.sh +52 -0
  1348. package/scripts/dev-startup.sh +82 -0
  1349. package/scripts/install-local.js +34 -0
  1350. package/scripts/install.ps1 +258 -0
  1351. package/scripts/install.sh +160 -0
  1352. package/scripts/package-release-asset.js +82 -0
  1353. package/scripts/patch-pi-ai-oauth.js +109 -0
  1354. package/scripts/run-tui-e2e.js +153 -0
  1355. package/scripts/set-version.js +31 -0
  1356. package/scripts/verify-acp-load.mjs +358 -0
  1357. package/scripts/verify-acp.mjs +217 -0
  1358. package/src/__mocks__/earendil-clipboard-image.js +6 -0
  1359. package/src/agent-discovery/agents/claude-code.test.ts +156 -0
  1360. package/src/agent-discovery/agents/claude-code.ts +85 -0
  1361. package/src/agent-discovery/agents/cursor.test.ts +178 -0
  1362. package/src/agent-discovery/agents/cursor.ts +74 -0
  1363. package/src/agent-discovery/agents/opencode.test.ts +461 -0
  1364. package/src/agent-discovery/agents/opencode.ts +156 -0
  1365. package/src/agent-discovery/agents/skills-only.test.ts +77 -0
  1366. package/src/agent-discovery/agents/skills-only.ts +47 -0
  1367. package/src/agent-discovery/engine.test.ts +408 -0
  1368. package/src/agent-discovery/engine.ts +117 -0
  1369. package/src/agent-discovery/index.ts +75 -0
  1370. package/src/agent-discovery/jsonc.ts +52 -0
  1371. package/src/ansi.ts +51 -0
  1372. package/src/api/me.test.ts +86 -0
  1373. package/src/api/me.ts +59 -0
  1374. package/src/auth/validator.test.ts +106 -0
  1375. package/src/auth/validator.ts +103 -0
  1376. package/src/auxiliary-files/resolver.test.ts +85 -0
  1377. package/src/auxiliary-files/resolver.ts +27 -0
  1378. package/src/auxiliary-files/validator.test.ts +68 -0
  1379. package/src/auxiliary-files/validator.ts +31 -0
  1380. package/src/cli-args.test.ts +232 -0
  1381. package/src/cli-args.ts +94 -0
  1382. package/src/cli-auth/callback-server.test.ts +169 -0
  1383. package/src/cli-auth/callback-server.ts +165 -0
  1384. package/src/cli-auth/index.test.ts +103 -0
  1385. package/src/cli-auth/index.ts +117 -0
  1386. package/src/cli-auth/oauth-page.ts +94 -0
  1387. package/src/cli.ts +564 -0
  1388. package/src/commands/_helpers.ts +87 -0
  1389. package/src/commands/banner.test.ts +39 -0
  1390. package/src/commands/banner.ts +74 -0
  1391. package/src/commands/claude.ts +28 -0
  1392. package/src/commands/config.test.ts +149 -0
  1393. package/src/commands/config.ts +98 -0
  1394. package/src/commands/cursor.ts +23 -0
  1395. package/src/commands/dispatch.test.ts +102 -0
  1396. package/src/commands/dispatch.ts +40 -0
  1397. package/src/commands/gsd2.ts +23 -0
  1398. package/src/commands/help.ts +104 -0
  1399. package/src/commands/login.ts +46 -0
  1400. package/src/commands/openclaw.ts +23 -0
  1401. package/src/commands/opencode.ts +31 -0
  1402. package/src/commands/registry.ts +44 -0
  1403. package/src/commands/resources.ts +77 -0
  1404. package/src/commands/setup-tools.test.ts +231 -0
  1405. package/src/commands/setup-tools.ts +164 -0
  1406. package/src/commands/setup.ts +28 -0
  1407. package/src/commands/update.test.ts +312 -0
  1408. package/src/commands/update.ts +291 -0
  1409. package/src/commands/version.ts +9 -0
  1410. package/src/components/editor.test.ts +182 -0
  1411. package/src/components/editor.ts +186 -0
  1412. package/src/components/footer.test.ts +790 -0
  1413. package/src/components/footer.ts +640 -0
  1414. package/src/components/logo-art.test.ts +30 -0
  1415. package/src/components/logo-art.ts +66 -0
  1416. package/src/components/logo.test.ts +316 -0
  1417. package/src/components/logo.ts +127 -0
  1418. package/src/components/tool-block.test.ts +75 -0
  1419. package/src/components/tool-block.ts +166 -0
  1420. package/src/config/footer-config.test.ts +191 -0
  1421. package/src/config/footer-config.ts +130 -0
  1422. package/src/config/json.test.ts +78 -0
  1423. package/src/config/json.ts +112 -0
  1424. package/src/config/scope.test.ts +49 -0
  1425. package/src/config/scope.ts +38 -0
  1426. package/src/config/shell-profile.test.ts +130 -0
  1427. package/src/config/shell-profile.ts +131 -0
  1428. package/src/config.test.ts +723 -0
  1429. package/src/config.ts +697 -0
  1430. package/src/entry.ts +62 -0
  1431. package/src/env.ts +4 -0
  1432. package/src/expand-state.ts +41 -0
  1433. package/src/extensions/activity.test.ts +160 -0
  1434. package/src/extensions/activity.ts +192 -0
  1435. package/src/extensions/agent-worker-context.test.ts +31 -0
  1436. package/src/extensions/agent-worker-context.ts +11 -0
  1437. package/src/extensions/agents/default-agents.test.ts +24 -0
  1438. package/src/extensions/agents/discovery-priority.test.ts +65 -0
  1439. package/src/extensions/agents/env.ts +33 -0
  1440. package/src/extensions/agents/index.test.ts +32 -0
  1441. package/src/extensions/agents/index.ts +2226 -0
  1442. package/src/extensions/agents/manager/agent-manager.test.ts +896 -0
  1443. package/src/extensions/agents/manager/agent-manager.ts +714 -0
  1444. package/src/extensions/agents/manager/agent-runner.test.ts +1846 -0
  1445. package/src/extensions/agents/manager/agent-runner.ts +964 -0
  1446. package/src/extensions/agents/manager/budget-retry-guard.test.ts +95 -0
  1447. package/src/extensions/agents/manager/budget-retry-guard.ts +57 -0
  1448. package/src/extensions/agents/manager/constants.ts +1 -0
  1449. package/src/extensions/agents/manager/group-join.ts +136 -0
  1450. package/src/extensions/agents/manager/output-file.test.ts +31 -0
  1451. package/src/extensions/agents/manager/output-file.ts +92 -0
  1452. package/src/extensions/agents/manager/session-file.test.ts +59 -0
  1453. package/src/extensions/agents/manager/session-file.ts +37 -0
  1454. package/src/extensions/agents/manager/usage.ts +52 -0
  1455. package/src/extensions/agents/memory/memory.test.ts +54 -0
  1456. package/src/extensions/agents/memory/memory.ts +166 -0
  1457. package/src/extensions/agents/memory.test.ts +54 -0
  1458. package/src/extensions/agents/package-resources.test.ts +147 -0
  1459. package/src/extensions/agents/package-resources.ts +37 -0
  1460. package/src/extensions/agents/personas/__snapshots__/default-agents.test.ts.snap +75 -0
  1461. package/src/extensions/agents/personas/agent-types.test.ts +33 -0
  1462. package/src/extensions/agents/personas/agent-types.ts +150 -0
  1463. package/src/extensions/agents/personas/custom-agents.test.ts +171 -0
  1464. package/src/extensions/agents/personas/custom-agents.ts +147 -0
  1465. package/src/extensions/agents/personas/default-agents.test.ts +101 -0
  1466. package/src/extensions/agents/personas/default-agents.ts +335 -0
  1467. package/src/extensions/agents/personas/discovery-priority.test.ts +65 -0
  1468. package/src/extensions/agents/personas/types.ts +229 -0
  1469. package/src/extensions/agents/prompt/context.ts +54 -0
  1470. package/src/extensions/agents/prompt/prompts.test.ts +314 -0
  1471. package/src/extensions/agents/prompt/prompts.ts +164 -0
  1472. package/src/extensions/agents/prompt/skill-loader.test.ts +41 -0
  1473. package/src/extensions/agents/prompt/skill-loader.ts +80 -0
  1474. package/src/extensions/agents/resolution/invocation-config.test.ts +81 -0
  1475. package/src/extensions/agents/resolution/invocation-config.ts +68 -0
  1476. package/src/extensions/agents/resolution/model-resolver.ts +85 -0
  1477. package/src/extensions/agents/resume-tool.test.ts +146 -0
  1478. package/src/extensions/agents/resume-tool.ts +90 -0
  1479. package/src/extensions/agents/settings.ts +163 -0
  1480. package/src/extensions/agents/skill-loader.test.ts +41 -0
  1481. package/src/extensions/agents/tool-result.ts +4 -0
  1482. package/src/extensions/agents/ui/agent-widget.ts +458 -0
  1483. package/src/extensions/agents/ui/conversation-viewer.ts +261 -0
  1484. package/src/extensions/agents/worker-budget-policy.ts +48 -0
  1485. package/src/extensions/agents/worker-report.test.ts +69 -0
  1486. package/src/extensions/agents/worker-report.ts +72 -0
  1487. package/src/extensions/assistant-prefix.ts +80 -0
  1488. package/src/extensions/bash-collapse.test.ts +21 -0
  1489. package/src/extensions/bash-collapse.ts +3 -0
  1490. package/src/extensions/bash-default-timeout.test.ts +189 -0
  1491. package/src/extensions/bash-default-timeout.ts +73 -0
  1492. package/src/extensions/bash-tool-guard-events.ts +39 -0
  1493. package/src/extensions/bash-tool-guard.integration.test.ts +771 -0
  1494. package/src/extensions/bash-tool-guard.test.ts +890 -0
  1495. package/src/extensions/bash-tool-guard.ts +640 -0
  1496. package/src/extensions/behaviours/bash-tokenize.test.ts +125 -0
  1497. package/src/extensions/behaviours/bash-tokenize.ts +272 -0
  1498. package/src/extensions/behaviours/bodies/bound-tool-output.md +11 -0
  1499. package/src/extensions/behaviours/bodies/gh-cli.md +80 -0
  1500. package/src/extensions/behaviours/bodies/git-hygiene.md +13 -0
  1501. package/src/extensions/behaviours/bodies/glab-cli.md +95 -0
  1502. package/src/extensions/behaviours/bodies/python-edit.md +10 -0
  1503. package/src/extensions/behaviours/bodies/re-read-before-edit.md +10 -0
  1504. package/src/extensions/behaviours/bodies.d.ts +7 -0
  1505. package/src/extensions/behaviours/build.test.ts +89 -0
  1506. package/src/extensions/behaviours/build.ts +63 -0
  1507. package/src/extensions/behaviours/engine.test.ts +300 -0
  1508. package/src/extensions/behaviours/engine.ts +131 -0
  1509. package/src/extensions/behaviours/eval-engine.test.ts +165 -0
  1510. package/src/extensions/behaviours/eval-engine.ts +104 -0
  1511. package/src/extensions/behaviours/frontmatter.ts +22 -0
  1512. package/src/extensions/behaviours/index.ts +35 -0
  1513. package/src/extensions/behaviours/matchers.test.ts +153 -0
  1514. package/src/extensions/behaviours/matchers.ts +69 -0
  1515. package/src/extensions/behaviours/registry.ts +73 -0
  1516. package/src/extensions/behaviours/session-context.test.ts +192 -0
  1517. package/src/extensions/behaviours/session-context.ts +170 -0
  1518. package/src/extensions/behaviours/stats.ts +47 -0
  1519. package/src/extensions/behaviours/tool-args.smoke.test.ts +34 -0
  1520. package/src/extensions/behaviours/tool-args.ts +65 -0
  1521. package/src/extensions/behaviours/triggers.ts +164 -0
  1522. package/src/extensions/behaviours/types.ts +49 -0
  1523. package/src/extensions/behaviours/wiring.smoke.test.ts +488 -0
  1524. package/src/extensions/behaviours/wiring.ts +196 -0
  1525. package/src/extensions/branch-command.test.ts +208 -0
  1526. package/src/extensions/branch-command.ts +89 -0
  1527. package/src/extensions/claude-code-hook-adapter/definition.test.ts +51 -0
  1528. package/src/extensions/claude-code-hook-adapter/definition.ts +36 -0
  1529. package/src/extensions/claude-code-hook-adapter/index.ts +6 -0
  1530. package/src/extensions/claude-code-skills/definition.test.ts +228 -0
  1531. package/src/extensions/claude-code-skills/definition.ts +475 -0
  1532. package/src/extensions/claude-code-skills/index.test.ts +227 -0
  1533. package/src/extensions/claude-code-skills/index.ts +101 -0
  1534. package/src/extensions/clipboard-image.test.ts +383 -0
  1535. package/src/extensions/clipboard-image.ts +266 -0
  1536. package/src/extensions/compaction-thresholds.test.ts +8 -0
  1537. package/src/extensions/compaction-thresholds.ts +13 -0
  1538. package/src/extensions/curator/index.test.ts +33 -0
  1539. package/src/extensions/curator/index.ts +296 -0
  1540. package/src/extensions/curator/review.test.ts +82 -0
  1541. package/src/extensions/curator/review.ts +438 -0
  1542. package/src/extensions/curator/state.test.ts +79 -0
  1543. package/src/extensions/curator/state.ts +61 -0
  1544. package/src/extensions/curator/transitions.test.ts +96 -0
  1545. package/src/extensions/curator/transitions.ts +56 -0
  1546. package/src/extensions/customize-footer-command.test.ts +258 -0
  1547. package/src/extensions/customize-footer-command.ts +158 -0
  1548. package/src/extensions/deferred-action.ts +38 -0
  1549. package/src/extensions/disabled/tool-result-pruning.test.ts +397 -0
  1550. package/src/extensions/disabled/tool-result-pruning.ts +181 -0
  1551. package/src/extensions/exit-utils.ts +8 -0
  1552. package/src/extensions/exploration-guard.test.ts +646 -0
  1553. package/src/extensions/exploration-guard.ts +293 -0
  1554. package/src/extensions/ferment/action-tool-names.ts +25 -0
  1555. package/src/extensions/ferment/agent-spawn-guard.test.ts +339 -0
  1556. package/src/extensions/ferment/agent-spawn-guard.ts +188 -0
  1557. package/src/extensions/ferment/ask-user.test.ts +838 -0
  1558. package/src/extensions/ferment/ask-user.ts +569 -0
  1559. package/src/extensions/ferment/auto-compaction.test.ts +933 -0
  1560. package/src/extensions/ferment/auto-compaction.ts +525 -0
  1561. package/src/extensions/ferment/breadcrumb-renderer.ts +46 -0
  1562. package/src/extensions/ferment/colors.ts +95 -0
  1563. package/src/extensions/ferment/command-parser.test.ts +82 -0
  1564. package/src/extensions/ferment/command-parser.ts +52 -0
  1565. package/src/extensions/ferment/commands.test.ts +1659 -0
  1566. package/src/extensions/ferment/commands.ts +1025 -0
  1567. package/src/extensions/ferment/constants.ts +37 -0
  1568. package/src/extensions/ferment/contextual-options.test.ts +70 -0
  1569. package/src/extensions/ferment/contextual-options.ts +107 -0
  1570. package/src/extensions/ferment/continuation.test.ts +141 -0
  1571. package/src/extensions/ferment/continuation.ts +59 -0
  1572. package/src/extensions/ferment/derive-state.test.ts +222 -0
  1573. package/src/extensions/ferment/derive-state.ts +158 -0
  1574. package/src/extensions/ferment/domain-events-emitter.ts +255 -0
  1575. package/src/extensions/ferment/domain-events.ts +146 -0
  1576. package/src/extensions/ferment/events.test.ts +616 -0
  1577. package/src/extensions/ferment/events.ts +561 -0
  1578. package/src/extensions/ferment/footer-status.test.ts +62 -0
  1579. package/src/extensions/ferment/footer-status.ts +61 -0
  1580. package/src/extensions/ferment/format.test.ts +55 -0
  1581. package/src/extensions/ferment/format.ts +111 -0
  1582. package/src/extensions/ferment/fsm-adapter.test.ts +43 -0
  1583. package/src/extensions/ferment/fsm-adapter.ts +112 -0
  1584. package/src/extensions/ferment/gate-registry.test.ts +176 -0
  1585. package/src/extensions/ferment/gate-registry.ts +352 -0
  1586. package/src/extensions/ferment/gate-validation.test.ts +319 -0
  1587. package/src/extensions/ferment/gate-validation.ts +160 -0
  1588. package/src/extensions/ferment/git-init.test.ts +146 -0
  1589. package/src/extensions/ferment/git-init.ts +66 -0
  1590. package/src/extensions/ferment/index.test.ts +1439 -0
  1591. package/src/extensions/ferment/index.ts +337 -0
  1592. package/src/extensions/ferment/judge.test.ts +172 -0
  1593. package/src/extensions/ferment/judge.ts +342 -0
  1594. package/src/extensions/ferment/nudge.test.ts +700 -0
  1595. package/src/extensions/ferment/nudge.ts +332 -0
  1596. package/src/extensions/ferment/oneshot.test.ts +115 -0
  1597. package/src/extensions/ferment/oneshot.ts +52 -0
  1598. package/src/extensions/ferment/pending-proposal-store.test.ts +272 -0
  1599. package/src/extensions/ferment/pending-proposal-store.ts +142 -0
  1600. package/src/extensions/ferment/phase-editor.test.ts +174 -0
  1601. package/src/extensions/ferment/phase-editor.ts +148 -0
  1602. package/src/extensions/ferment/phase-evidence.test.ts +154 -0
  1603. package/src/extensions/ferment/phase-evidence.ts +179 -0
  1604. package/src/extensions/ferment/plan-review-trigger.ts +34 -0
  1605. package/src/extensions/ferment/plan-review.test.ts +182 -0
  1606. package/src/extensions/ferment/plan-review.ts +205 -0
  1607. package/src/extensions/ferment/progress-overlay.test.ts +197 -0
  1608. package/src/extensions/ferment/progress-overlay.ts +326 -0
  1609. package/src/extensions/ferment/project-tests.test.ts +160 -0
  1610. package/src/extensions/ferment/project-tests.ts +246 -0
  1611. package/src/extensions/ferment/prompt-block.test.ts +501 -0
  1612. package/src/extensions/ferment/prompt-block.ts +203 -0
  1613. package/src/extensions/ferment/prompt-ui.test.ts +311 -0
  1614. package/src/extensions/ferment/prompt-ui.ts +302 -0
  1615. package/src/extensions/ferment/resume.test.ts +218 -0
  1616. package/src/extensions/ferment/resume.ts +180 -0
  1617. package/src/extensions/ferment/review-evidence.ts +269 -0
  1618. package/src/extensions/ferment/runtime-state-store.test.ts +148 -0
  1619. package/src/extensions/ferment/runtime-state-store.ts +132 -0
  1620. package/src/extensions/ferment/runtime.test.ts +38 -0
  1621. package/src/extensions/ferment/runtime.ts +208 -0
  1622. package/src/extensions/ferment/scheduler.ts +226 -0
  1623. package/src/extensions/ferment/scoping-benchmark.test.ts +137 -0
  1624. package/src/extensions/ferment/scoping-confirmation.test.ts +209 -0
  1625. package/src/extensions/ferment/scoping-confirmation.ts +87 -0
  1626. package/src/extensions/ferment/scoping-flow.integration.test.ts +203 -0
  1627. package/src/extensions/ferment/scoping.test.ts +235 -0
  1628. package/src/extensions/ferment/scoping.ts +208 -0
  1629. package/src/extensions/ferment/state.test.ts +300 -0
  1630. package/src/extensions/ferment/state.ts +696 -0
  1631. package/src/extensions/ferment/tips.test.ts +171 -0
  1632. package/src/extensions/ferment/tips.ts +61 -0
  1633. package/src/extensions/ferment/todo-headless-wiring.test.ts +641 -0
  1634. package/src/extensions/ferment/todo-sync.test.ts +805 -0
  1635. package/src/extensions/ferment/todo-sync.ts +520 -0
  1636. package/src/extensions/ferment/tool-helpers.test.ts +121 -0
  1637. package/src/extensions/ferment/tool-helpers.ts +217 -0
  1638. package/src/extensions/ferment/tool-names.test.ts +55 -0
  1639. package/src/extensions/ferment/tool-names.ts +78 -0
  1640. package/src/extensions/ferment/tool-schemas.test.ts +587 -0
  1641. package/src/extensions/ferment/tool-schemas.ts +428 -0
  1642. package/src/extensions/ferment/tool-scope.test.ts +373 -0
  1643. package/src/extensions/ferment/tool-scope.ts +176 -0
  1644. package/src/extensions/ferment/tools/knowledge.ts +60 -0
  1645. package/src/extensions/ferment/tools/lifecycle.test.ts +1196 -0
  1646. package/src/extensions/ferment/tools/lifecycle.ts +1296 -0
  1647. package/src/extensions/ferment/tools/phases.test.ts +379 -0
  1648. package/src/extensions/ferment/tools/phases.ts +757 -0
  1649. package/src/extensions/ferment/tools/steps.test.ts +998 -0
  1650. package/src/extensions/ferment/tools/steps.ts +765 -0
  1651. package/src/extensions/ferment/tools.integration.test.ts +1975 -0
  1652. package/src/extensions/ferment/ui.ts +10 -0
  1653. package/src/extensions/ferment/worker-prompt.test.ts +285 -0
  1654. package/src/extensions/ferment/worker-prompt.ts +85 -0
  1655. package/src/extensions/ferment/worktree.ts +44 -0
  1656. package/src/extensions/format.ts +12 -0
  1657. package/src/extensions/help.ts +172 -0
  1658. package/src/extensions/hide-thinking.test.ts +407 -0
  1659. package/src/extensions/hide-thinking.ts +375 -0
  1660. package/src/extensions/hook-adapters/adapter.integration.test.ts +134 -0
  1661. package/src/extensions/hook-adapters/adapter.test.ts +1062 -0
  1662. package/src/extensions/hook-adapters/adapter.ts +784 -0
  1663. package/src/extensions/hook-adapters/discovery.test.ts +105 -0
  1664. package/src/extensions/hook-adapters/discovery.ts +213 -0
  1665. package/src/extensions/ide-adapter/ARCHITECTURE.md +77 -0
  1666. package/src/extensions/ide-adapter/CONTRACT.md +129 -0
  1667. package/src/extensions/ide-adapter/README.md +24 -0
  1668. package/src/extensions/ide-adapter/at-mentions.test.ts +40 -0
  1669. package/src/extensions/ide-adapter/at-mentions.ts +44 -0
  1670. package/src/extensions/ide-adapter/index.test.ts +434 -0
  1671. package/src/extensions/ide-adapter/index.ts +250 -0
  1672. package/src/extensions/ide-adapter/lockfile.test.ts +137 -0
  1673. package/src/extensions/ide-adapter/lockfile.ts +82 -0
  1674. package/src/extensions/ide-adapter/mcp-client.test.ts +285 -0
  1675. package/src/extensions/ide-adapter/mcp-client.ts +208 -0
  1676. package/src/extensions/ide-adapter/types.ts +47 -0
  1677. package/src/extensions/ikie-minimal-tints.ts +124 -0
  1678. package/src/extensions/ikie-process.ts +49 -0
  1679. package/src/extensions/improve/SKILL.md +51 -0
  1680. package/src/extensions/improve/index.ts +72 -0
  1681. package/src/extensions/input-history.test.ts +475 -0
  1682. package/src/extensions/input-history.ts +111 -0
  1683. package/src/extensions/llm-response-log.test.ts +200 -0
  1684. package/src/extensions/llm-response-log.ts +87 -0
  1685. package/src/extensions/login/flow.test.ts +47 -0
  1686. package/src/extensions/login/flow.ts +638 -0
  1687. package/src/extensions/login/index.ts +57 -0
  1688. package/src/extensions/login/startup-auth.test.ts +510 -0
  1689. package/src/extensions/login/startup-auth.ts +205 -0
  1690. package/src/extensions/loop-guard.test.ts +993 -0
  1691. package/src/extensions/loop-guard.ts +710 -0
  1692. package/src/extensions/lsp/client.ts +501 -0
  1693. package/src/extensions/lsp/edits.test.ts +69 -0
  1694. package/src/extensions/lsp/edits.ts +78 -0
  1695. package/src/extensions/lsp/lsp-entry.test.ts +24 -0
  1696. package/src/extensions/lsp/servers.ts +76 -0
  1697. package/src/extensions/lsp/types.ts +166 -0
  1698. package/src/extensions/lsp/utils.test.ts +81 -0
  1699. package/src/extensions/lsp/utils.ts +80 -0
  1700. package/src/extensions/lsp.test.ts +1049 -0
  1701. package/src/extensions/lsp.ts +470 -0
  1702. package/src/extensions/mcp-adapter/CHANGELOG.md +264 -0
  1703. package/src/extensions/mcp-adapter/LICENSE +21 -0
  1704. package/src/extensions/mcp-adapter/README.md +316 -0
  1705. package/src/extensions/mcp-adapter/app-bridge.bundle.js +10430 -0
  1706. package/src/extensions/mcp-adapter/bm25.ts +187 -0
  1707. package/src/extensions/mcp-adapter/cache-resolver.integration.test.ts +282 -0
  1708. package/src/extensions/mcp-adapter/commands.ts +235 -0
  1709. package/src/extensions/mcp-adapter/config.test.ts +189 -0
  1710. package/src/extensions/mcp-adapter/config.ts +233 -0
  1711. package/src/extensions/mcp-adapter/consent-manager.ts +64 -0
  1712. package/src/extensions/mcp-adapter/context-providers.test.ts +123 -0
  1713. package/src/extensions/mcp-adapter/context-providers.ts +55 -0
  1714. package/src/extensions/mcp-adapter/direct-tool-visibility.test.ts +61 -0
  1715. package/src/extensions/mcp-adapter/direct-tool-visibility.ts +47 -0
  1716. package/src/extensions/mcp-adapter/direct-tools.ts +413 -0
  1717. package/src/extensions/mcp-adapter/errors.ts +198 -0
  1718. package/src/extensions/mcp-adapter/glimpse-ui.ts +78 -0
  1719. package/src/extensions/mcp-adapter/host-html-template.ts +423 -0
  1720. package/src/extensions/mcp-adapter/index.test.ts +323 -0
  1721. package/src/extensions/mcp-adapter/index.ts +604 -0
  1722. package/src/extensions/mcp-adapter/init.ts +402 -0
  1723. package/src/extensions/mcp-adapter/lifecycle.ts +93 -0
  1724. package/src/extensions/mcp-adapter/logger.ts +169 -0
  1725. package/src/extensions/mcp-adapter/mcp-auth-flow.ts +394 -0
  1726. package/src/extensions/mcp-adapter/mcp-auth.ts +267 -0
  1727. package/src/extensions/mcp-adapter/mcp-callback-server.ts +284 -0
  1728. package/src/extensions/mcp-adapter/mcp-oauth-provider.ts +288 -0
  1729. package/src/extensions/mcp-adapter/mcp-panel.test.ts +321 -0
  1730. package/src/extensions/mcp-adapter/mcp-panel.ts +835 -0
  1731. package/src/extensions/mcp-adapter/metadata-cache.test.ts +83 -0
  1732. package/src/extensions/mcp-adapter/metadata-cache.ts +332 -0
  1733. package/src/extensions/mcp-adapter/npx-resolver.ts +429 -0
  1734. package/src/extensions/mcp-adapter/oauth-handler.ts +57 -0
  1735. package/src/extensions/mcp-adapter/proxy-modes.test.ts +147 -0
  1736. package/src/extensions/mcp-adapter/proxy-modes.ts +1035 -0
  1737. package/src/extensions/mcp-adapter/resource-tools.ts +17 -0
  1738. package/src/extensions/mcp-adapter/server-manager.ts +355 -0
  1739. package/src/extensions/mcp-adapter/state.ts +45 -0
  1740. package/src/extensions/mcp-adapter/tool-metadata.test.ts +115 -0
  1741. package/src/extensions/mcp-adapter/tool-metadata.ts +185 -0
  1742. package/src/extensions/mcp-adapter/tool-registrar.ts +46 -0
  1743. package/src/extensions/mcp-adapter/types.ts +423 -0
  1744. package/src/extensions/mcp-adapter/ui-resource-handler.ts +143 -0
  1745. package/src/extensions/mcp-adapter/ui-server.ts +619 -0
  1746. package/src/extensions/mcp-adapter/ui-session.ts +378 -0
  1747. package/src/extensions/mcp-adapter/ui-stream-types.ts +93 -0
  1748. package/src/extensions/mcp-adapter/utils.ts +76 -0
  1749. package/src/extensions/model-catalog/builtin-models.ts +180 -0
  1750. package/src/extensions/model-catalog/guidelines/claude-family.ts +49 -0
  1751. package/src/extensions/model-catalog/guidelines/default-orchestration-guidelines.ts +11 -0
  1752. package/src/extensions/model-catalog/guidelines/default-phase-guidelines.ts +59 -0
  1753. package/src/extensions/model-catalog/guidelines/guidelines-resolver.test.ts +191 -0
  1754. package/src/extensions/model-catalog/guidelines/guidelines-resolver.ts +39 -0
  1755. package/src/extensions/model-catalog/guidelines/kimi-family.ts +82 -0
  1756. package/src/extensions/model-catalog/guidelines/minimax-family.ts +62 -0
  1757. package/src/extensions/model-catalog/guidelines/nemotron-family.ts +53 -0
  1758. package/src/extensions/model-catalog/index.ts +10 -0
  1759. package/src/extensions/model-catalog/model-metadata.test.ts +688 -0
  1760. package/src/extensions/model-catalog/model-metadata.ts +250 -0
  1761. package/src/extensions/model-catalog/model-registry.test.ts +228 -0
  1762. package/src/extensions/model-catalog/model-registry.ts +116 -0
  1763. package/src/extensions/model-catalog/ref-utils.ts +22 -0
  1764. package/src/extensions/model-catalog/types.ts +41 -0
  1765. package/src/extensions/model-guard.test.ts +756 -0
  1766. package/src/extensions/model-guard.ts +402 -0
  1767. package/src/extensions/model-switch.test.ts +1105 -0
  1768. package/src/extensions/model-switch.ts +261 -0
  1769. package/src/extensions/onboarding/picker-editor.ts +22 -0
  1770. package/src/extensions/onboarding/session-mode-picker.test.ts +135 -0
  1771. package/src/extensions/onboarding/session-mode-picker.ts +136 -0
  1772. package/src/extensions/onboarding/session-mode-startup.test.ts +237 -0
  1773. package/src/extensions/onboarding/session-mode-startup.ts +36 -0
  1774. package/src/extensions/onboarding/session-mode.test.ts +501 -0
  1775. package/src/extensions/onboarding/session-mode.ts +363 -0
  1776. package/src/extensions/orchestration/continuation-nudge.test.ts +595 -0
  1777. package/src/extensions/orchestration/continuation-nudge.ts +270 -0
  1778. package/src/extensions/orchestration/model-metadata.test.ts +671 -0
  1779. package/src/extensions/orchestration/model-metadata.ts +246 -0
  1780. package/src/extensions/orchestration/model-ref-utils.ts +5 -0
  1781. package/src/extensions/orchestration/model-registry/builtin-models.ts +223 -0
  1782. package/src/extensions/orchestration/model-registry/guidelines/claude-family.ts +49 -0
  1783. package/src/extensions/orchestration/model-registry/guidelines/default-orchestration-guidelines.ts +11 -0
  1784. package/src/extensions/orchestration/model-registry/guidelines/default-phase-guidelines.ts +67 -0
  1785. package/src/extensions/orchestration/model-registry/guidelines/guidelines-resolver.test.ts +273 -0
  1786. package/src/extensions/orchestration/model-registry/guidelines/guidelines-resolver.ts +39 -0
  1787. package/src/extensions/orchestration/model-registry/guidelines/kimi-family.ts +89 -0
  1788. package/src/extensions/orchestration/model-registry/guidelines/minimax-family.ts +68 -0
  1789. package/src/extensions/orchestration/model-registry/guidelines/nemotron-family.ts +60 -0
  1790. package/src/extensions/orchestration/model-registry/index.ts +4 -0
  1791. package/src/extensions/orchestration/model-registry/model-registry.test.ts +228 -0
  1792. package/src/extensions/orchestration/model-registry/model-registry.ts +116 -0
  1793. package/src/extensions/orchestration/model-registry/types.ts +41 -0
  1794. package/src/extensions/orchestration/model-roles-command.test.ts +367 -0
  1795. package/src/extensions/orchestration/model-roles-command.ts +531 -0
  1796. package/src/extensions/orchestration/model-roles.test.ts +448 -0
  1797. package/src/extensions/orchestration/model-roles.ts +302 -0
  1798. package/src/extensions/orchestration/orchestration-instructions.test.ts +459 -0
  1799. package/src/extensions/orchestration/orchestration-instructions.ts +614 -0
  1800. package/src/extensions/orphan-tool-result-sanitizer.test.ts +198 -0
  1801. package/src/extensions/orphan-tool-result-sanitizer.ts +128 -0
  1802. package/src/extensions/permissions/classifier-model.test.ts +127 -0
  1803. package/src/extensions/permissions/classifier-model.ts +65 -0
  1804. package/src/extensions/permissions/classifier.test.ts +334 -0
  1805. package/src/extensions/permissions/classifier.ts +228 -0
  1806. package/src/extensions/permissions/commands.ts +244 -0
  1807. package/src/extensions/permissions/config.test.ts +101 -0
  1808. package/src/extensions/permissions/config.ts +143 -0
  1809. package/src/extensions/permissions/constants.ts +1 -0
  1810. package/src/extensions/permissions/index.test.ts +1822 -0
  1811. package/src/extensions/permissions/index.ts +1193 -0
  1812. package/src/extensions/permissions/keybindings.test.ts +130 -0
  1813. package/src/extensions/permissions/keybindings.ts +91 -0
  1814. package/src/extensions/permissions/mode-controller-registry.ts +50 -0
  1815. package/src/extensions/permissions/mode-controller.ts +91 -0
  1816. package/src/extensions/permissions/mode.test.ts +51 -0
  1817. package/src/extensions/permissions/mode.ts +29 -0
  1818. package/src/extensions/permissions/plan-persistence.test.ts +56 -0
  1819. package/src/extensions/permissions/plan-persistence.ts +12 -0
  1820. package/src/extensions/permissions/plan-persona.test.ts +42 -0
  1821. package/src/extensions/permissions/prompter.ts +21 -0
  1822. package/src/extensions/permissions/prompts/classifier-system-prompt.ts +33 -0
  1823. package/src/extensions/permissions/prompts/plan-mode-supplement.test.ts +59 -0
  1824. package/src/extensions/permissions/prompts/plan-mode-supplement.ts +38 -0
  1825. package/src/extensions/permissions/prompts.test.ts +67 -0
  1826. package/src/extensions/permissions/prompts.ts +212 -0
  1827. package/src/extensions/permissions/rules.test.ts +327 -0
  1828. package/src/extensions/permissions/rules.ts +210 -0
  1829. package/src/extensions/permissions/select-utils.ts +2 -0
  1830. package/src/extensions/permissions/session-memory.test.ts +75 -0
  1831. package/src/extensions/permissions/session-memory.ts +94 -0
  1832. package/src/extensions/permissions/taxonomy.test.ts +684 -0
  1833. package/src/extensions/permissions/taxonomy.ts +616 -0
  1834. package/src/extensions/permissions/types.ts +70 -0
  1835. package/src/extensions/pi-compat.test.ts +201 -0
  1836. package/src/extensions/pi-package-lookup/index.test.ts +177 -0
  1837. package/src/extensions/pi-package-lookup/index.ts +263 -0
  1838. package/src/extensions/pi-package-lookup/native-compat.test.ts +230 -0
  1839. package/src/extensions/pi-package-lookup/native-compat.ts +279 -0
  1840. package/src/extensions/plugin-package-hook-adapter/definition.test.ts +220 -0
  1841. package/src/extensions/plugin-package-hook-adapter/definition.ts +60 -0
  1842. package/src/extensions/plugin-package-hook-adapter/index.ts +4 -0
  1843. package/src/extensions/prompt-construction/context-files.test.ts +167 -0
  1844. package/src/extensions/prompt-construction/context-files.ts +111 -0
  1845. package/src/extensions/prompt-construction/index.ts +8 -0
  1846. package/src/extensions/prompt-construction/prompt-enrichment.test.ts +1103 -0
  1847. package/src/extensions/prompt-construction/prompt-enrichment.ts +588 -0
  1848. package/src/extensions/prompt-construction/system-prompt-blocks.test.ts +323 -0
  1849. package/src/extensions/prompt-construction/system-prompt-blocks.ts +122 -0
  1850. package/src/extensions/prompt-construction/system-prompt.test.ts +528 -0
  1851. package/src/extensions/prompt-construction/system-prompt.ts +316 -0
  1852. package/src/extensions/prompt-construction/tool-visibility.test.ts +170 -0
  1853. package/src/extensions/prompt-construction/tool-visibility.ts +121 -0
  1854. package/src/extensions/prompt-summary.test.ts +56 -0
  1855. package/src/extensions/prompt-summary.ts +258 -0
  1856. package/src/extensions/questionnaire/constants.ts +6 -0
  1857. package/src/extensions/questionnaire/index.ts +8 -0
  1858. package/src/extensions/questionnaire/questionnaire-fallback.test.ts +948 -0
  1859. package/src/extensions/questionnaire/questionnaire-fallback.ts +230 -0
  1860. package/src/extensions/questionnaire/questionnaire-form.ts +314 -0
  1861. package/src/extensions/questionnaire/questionnaire-reducer.test.ts +508 -0
  1862. package/src/extensions/questionnaire/questionnaire-reducer.ts +510 -0
  1863. package/src/extensions/questionnaire/questionnaire.test.ts +425 -0
  1864. package/src/extensions/questionnaire/questionnaire.ts +280 -0
  1865. package/src/extensions/report-bug.test.ts +301 -0
  1866. package/src/extensions/report-bug.ts +93 -0
  1867. package/src/extensions/review-write-guard.integration.test.ts +167 -0
  1868. package/src/extensions/review-write-guard.test.ts +150 -0
  1869. package/src/extensions/review-write-guard.ts +143 -0
  1870. package/src/extensions/rtk-rewrite.test.ts +325 -0
  1871. package/src/extensions/rtk-rewrite.ts +201 -0
  1872. package/src/extensions/session-metadata/index.test.ts +158 -0
  1873. package/src/extensions/session-metadata/index.ts +66 -0
  1874. package/src/extensions/session-name.test.ts +248 -0
  1875. package/src/extensions/session-name.ts +192 -0
  1876. package/src/extensions/session-repair/orphan-tool-result-repair.test.ts +227 -0
  1877. package/src/extensions/session-repair/orphan-tool-result-repair.ts +183 -0
  1878. package/src/extensions/shared-footer.ts +24 -0
  1879. package/src/extensions/shared-input.test.ts +27 -0
  1880. package/src/extensions/shared-input.ts +24 -0
  1881. package/src/extensions/shutdown-marker.test.ts +195 -0
  1882. package/src/extensions/shutdown-marker.ts +61 -0
  1883. package/src/extensions/skills-manager/index.test.ts +17 -0
  1884. package/src/extensions/skills-manager/index.ts +18 -0
  1885. package/src/extensions/skills-manager/skill-manager.test.ts +350 -0
  1886. package/src/extensions/skills-manager/skill-manager.ts +508 -0
  1887. package/src/extensions/skills-manager/tool.test.ts +234 -0
  1888. package/src/extensions/skills-manager/tool.ts +241 -0
  1889. package/src/extensions/skills-manager/usage.test.ts +119 -0
  1890. package/src/extensions/skills-manager/usage.ts +249 -0
  1891. package/src/extensions/slash-commands.ts +22 -0
  1892. package/src/extensions/spinner.ts +117 -0
  1893. package/src/extensions/stale-ctx.ts +15 -0
  1894. package/src/extensions/startup-update.test.ts +130 -0
  1895. package/src/extensions/startup-update.ts +33 -0
  1896. package/src/extensions/stats/api.ts +168 -0
  1897. package/src/extensions/stats/display.ts +210 -0
  1898. package/src/extensions/stats/index.ts +130 -0
  1899. package/src/extensions/stats/stats.test.ts +547 -0
  1900. package/src/extensions/stats/types.ts +263 -0
  1901. package/src/extensions/stats/visual.ts +439 -0
  1902. package/src/extensions/strip-images.test.ts +118 -0
  1903. package/src/extensions/strip-images.ts +162 -0
  1904. package/src/extensions/superpowers/config.ts +10 -0
  1905. package/src/extensions/superpowers.test.ts +17 -0
  1906. package/src/extensions/superpowers.ts +5 -0
  1907. package/src/extensions/surveys/index.test.ts +200 -0
  1908. package/src/extensions/surveys/index.ts +107 -0
  1909. package/src/extensions/surveys/survey.test.ts +157 -0
  1910. package/src/extensions/surveys/survey.ts +204 -0
  1911. package/src/extensions/tags.test.ts +275 -0
  1912. package/src/extensions/tags.ts +662 -0
  1913. package/src/extensions/telemetry/README.md +113 -0
  1914. package/src/extensions/telemetry/accumulator.test.ts +260 -0
  1915. package/src/extensions/telemetry/accumulator.ts +146 -0
  1916. package/src/extensions/telemetry/config-snapshot.test.ts +259 -0
  1917. package/src/extensions/telemetry/config-snapshot.ts +177 -0
  1918. package/src/extensions/telemetry/handlers/messages.test.ts +422 -0
  1919. package/src/extensions/telemetry/handlers/messages.ts +113 -0
  1920. package/src/extensions/telemetry/handlers/session.test.ts +198 -0
  1921. package/src/extensions/telemetry/handlers/session.ts +24 -0
  1922. package/src/extensions/telemetry/handlers/tools.test.ts +416 -0
  1923. package/src/extensions/telemetry/handlers/tools.ts +171 -0
  1924. package/src/extensions/telemetry/handlers/transport-errors.test.ts +178 -0
  1925. package/src/extensions/telemetry/handlers/transport-errors.ts +42 -0
  1926. package/src/extensions/telemetry/helpers.test.ts +266 -0
  1927. package/src/extensions/telemetry/helpers.ts +146 -0
  1928. package/src/extensions/telemetry/index.test.ts +1170 -0
  1929. package/src/extensions/telemetry/index.ts +609 -0
  1930. package/src/extensions/telemetry/pre-session.test.ts +390 -0
  1931. package/src/extensions/telemetry/pre-session.ts +135 -0
  1932. package/src/extensions/telemetry/session-context.test.ts +487 -0
  1933. package/src/extensions/telemetry/session-context.ts +281 -0
  1934. package/src/extensions/telemetry/session-type.ts +5 -0
  1935. package/src/extensions/telemetry/settings-change-emitter.test.ts +197 -0
  1936. package/src/extensions/telemetry/settings-change-emitter.ts +127 -0
  1937. package/src/extensions/telemetry/survey.test.ts +140 -0
  1938. package/src/extensions/telemetry/survey.ts +70 -0
  1939. package/src/extensions/telemetry/transport.test.ts +301 -0
  1940. package/src/extensions/telemetry/transport.ts +217 -0
  1941. package/src/extensions/teleport/commands/args.test.ts +166 -0
  1942. package/src/extensions/teleport/commands/args.ts +226 -0
  1943. package/src/extensions/teleport/commands/attach.test.ts +209 -0
  1944. package/src/extensions/teleport/commands/attach.ts +91 -0
  1945. package/src/extensions/teleport/commands/errors.ts +26 -0
  1946. package/src/extensions/teleport/commands/remote-sessions.test.ts +350 -0
  1947. package/src/extensions/teleport/commands/remote-sessions.ts +193 -0
  1948. package/src/extensions/teleport/commands/ssh-config.ts +25 -0
  1949. package/src/extensions/teleport/commands/sync.test.ts +104 -0
  1950. package/src/extensions/teleport/commands/sync.ts +205 -0
  1951. package/src/extensions/teleport/commands/teleport.test.ts +593 -0
  1952. package/src/extensions/teleport/commands/teleport.ts +359 -0
  1953. package/src/extensions/teleport/commands/terminal.test.ts +228 -0
  1954. package/src/extensions/teleport/commands/terminal.ts +97 -0
  1955. package/src/extensions/teleport/commands/workspace-ref.test.ts +269 -0
  1956. package/src/extensions/teleport/commands/workspace-ref.ts +105 -0
  1957. package/src/extensions/teleport/index.test.ts +72 -0
  1958. package/src/extensions/teleport/index.ts +66 -0
  1959. package/src/extensions/teleport/overlay/keybindings.test.ts +101 -0
  1960. package/src/extensions/teleport/overlay/keybindings.ts +65 -0
  1961. package/src/extensions/teleport/overlay/overlay-component.test.ts +102 -0
  1962. package/src/extensions/teleport/overlay/overlay-component.ts +284 -0
  1963. package/src/extensions/teleport/overlay/reconnect-banner.test.ts +63 -0
  1964. package/src/extensions/teleport/overlay/reconnect-banner.ts +69 -0
  1965. package/src/extensions/teleport/overlay/tab-bar.test.ts +72 -0
  1966. package/src/extensions/teleport/overlay/tab-bar.ts +146 -0
  1967. package/src/extensions/teleport/overlay/tab-manager.test.ts +484 -0
  1968. package/src/extensions/teleport/overlay/tab-manager.ts +293 -0
  1969. package/src/extensions/teleport/preflight/git.test.ts +94 -0
  1970. package/src/extensions/teleport/preflight/git.ts +40 -0
  1971. package/src/extensions/teleport/preflight/index.test.ts +97 -0
  1972. package/src/extensions/teleport/preflight/index.ts +43 -0
  1973. package/src/extensions/teleport/preflight/rsync.test.ts +39 -0
  1974. package/src/extensions/teleport/preflight/rsync.ts +23 -0
  1975. package/src/extensions/teleport/preflight/workspace-size.ts +2 -0
  1976. package/src/extensions/teleport/provisioning/concurrency.ts +40 -0
  1977. package/src/extensions/teleport/provisioning/constants.ts +3 -0
  1978. package/src/extensions/teleport/provisioning/estimate-bytes.test.ts +107 -0
  1979. package/src/extensions/teleport/provisioning/estimate-bytes.ts +123 -0
  1980. package/src/extensions/teleport/provisioning/git-provision.test.ts +76 -0
  1981. package/src/extensions/teleport/provisioning/git-provision.ts +54 -0
  1982. package/src/extensions/teleport/provisioning/include-list.test.ts +222 -0
  1983. package/src/extensions/teleport/provisioning/include-list.ts +203 -0
  1984. package/src/extensions/teleport/provisioning/paths.ts +54 -0
  1985. package/src/extensions/teleport/provisioning/proxy-command.ts +30 -0
  1986. package/src/extensions/teleport/provisioning/rsync-runner.test.ts +544 -0
  1987. package/src/extensions/teleport/provisioning/rsync-runner.ts +675 -0
  1988. package/src/extensions/teleport/pty/mouse-capture.ts +7 -0
  1989. package/src/extensions/teleport/pty/reconnect-supervisor.ts +117 -0
  1990. package/src/extensions/teleport/pty/terminal-component.test.ts +282 -0
  1991. package/src/extensions/teleport/pty/terminal-component.ts +331 -0
  1992. package/src/extensions/teleport/pty/websocket-transport.test.ts +440 -0
  1993. package/src/extensions/teleport/pty/websocket-transport.ts +228 -0
  1994. package/src/extensions/teleport/pty/xterm-core.test.ts +79 -0
  1995. package/src/extensions/teleport/pty/xterm-core.ts +159 -0
  1996. package/src/extensions/teleport/session-filter.ts +10 -0
  1997. package/src/extensions/teleport/ssh-config/paths.ts +27 -0
  1998. package/src/extensions/teleport/ssh-config/render.test.ts +111 -0
  1999. package/src/extensions/teleport/ssh-config/render.ts +97 -0
  2000. package/src/extensions/teleport/ssh-config/sync.test.ts +170 -0
  2001. package/src/extensions/teleport/ssh-config/sync.ts +92 -0
  2002. package/src/extensions/teleport/types.ts +14 -0
  2003. package/src/extensions/teleport/ui/format-bytes.ts +13 -0
  2004. package/src/extensions/teleport/ui/git-token-prompt.ts +164 -0
  2005. package/src/extensions/teleport/ui/help-modal.ts +100 -0
  2006. package/src/extensions/teleport/ui/progress.test.ts +236 -0
  2007. package/src/extensions/teleport/ui/progress.ts +345 -0
  2008. package/src/extensions/teleport/ui/remote-sessions-panel.test.ts +221 -0
  2009. package/src/extensions/teleport/ui/remote-sessions-panel.ts +309 -0
  2010. package/src/extensions/teleport/ui/sessions-table.ts +24 -0
  2011. package/src/extensions/teleport/ui/sync-progress-row.ts +30 -0
  2012. package/src/extensions/teleport/ui/tty-handoff.ts +131 -0
  2013. package/src/extensions/teleport/ui/workspaces-panel.test.ts +307 -0
  2014. package/src/extensions/teleport/ui/workspaces-panel.ts +364 -0
  2015. package/src/extensions/teleport/ui/workspaces-table.ts +12 -0
  2016. package/src/extensions/terminal-colors.ts +256 -0
  2017. package/src/extensions/terminal-compat/keyboard-capability.test.ts +69 -0
  2018. package/src/extensions/terminal-compat/keyboard-capability.ts +103 -0
  2019. package/src/extensions/terminal-compat/startup-warning.test.ts +273 -0
  2020. package/src/extensions/terminal-compat/startup-warning.ts +77 -0
  2021. package/src/extensions/theme-selector.test.ts +297 -0
  2022. package/src/extensions/theme-selector.ts +156 -0
  2023. package/src/extensions/thinking-steps/index.ts +429 -0
  2024. package/src/extensions/thinking-steps/internal-patch.ts +483 -0
  2025. package/src/extensions/thinking-steps/parse.ts +1376 -0
  2026. package/src/extensions/thinking-steps/persistence.ts +95 -0
  2027. package/src/extensions/thinking-steps/render.ts +496 -0
  2028. package/src/extensions/thinking-steps/state.ts +482 -0
  2029. package/src/extensions/thinking-steps/types.ts +55 -0
  2030. package/src/extensions/tips/general-tips.test.ts +33 -0
  2031. package/src/extensions/tips/general-tips.ts +81 -0
  2032. package/src/extensions/tips/index.test.ts +198 -0
  2033. package/src/extensions/tips/index.ts +231 -0
  2034. package/src/extensions/tips/presenter.test.ts +160 -0
  2035. package/src/extensions/tips/presenter.ts +170 -0
  2036. package/src/extensions/tips/registry.test.ts +59 -0
  2037. package/src/extensions/tips/registry.ts +66 -0
  2038. package/src/extensions/tips/tip-row.test.ts +97 -0
  2039. package/src/extensions/tips/tip-row.ts +48 -0
  2040. package/src/extensions/tips/tips-panel.test.ts +222 -0
  2041. package/src/extensions/tips/tips-panel.ts +310 -0
  2042. package/src/extensions/tips/types.ts +21 -0
  2043. package/src/extensions/todos/command.test.ts +103 -0
  2044. package/src/extensions/todos/command.ts +266 -0
  2045. package/src/extensions/todos/constants.ts +1 -0
  2046. package/src/extensions/todos/index.test.ts +405 -0
  2047. package/src/extensions/todos/index.ts +238 -0
  2048. package/src/extensions/todos/prompt-block.test.ts +219 -0
  2049. package/src/extensions/todos/prompt-block.ts +176 -0
  2050. package/src/extensions/todos/reducer.test.ts +141 -0
  2051. package/src/extensions/todos/reducer.ts +155 -0
  2052. package/src/extensions/todos/scope.test.ts +42 -0
  2053. package/src/extensions/todos/scope.ts +109 -0
  2054. package/src/extensions/todos/store.test.ts +78 -0
  2055. package/src/extensions/todos/store.ts +92 -0
  2056. package/src/extensions/todos/tool.test.ts +84 -0
  2057. package/src/extensions/todos/tool.ts +240 -0
  2058. package/src/extensions/todos/types.ts +79 -0
  2059. package/src/extensions/todos/widget.test.ts +348 -0
  2060. package/src/extensions/todos/widget.ts +332 -0
  2061. package/src/extensions/tool-grouping.test.ts +387 -0
  2062. package/src/extensions/tool-grouping.ts +346 -0
  2063. package/src/extensions/tool-rendering.test.ts +401 -0
  2064. package/src/extensions/tool-rendering.ts +4511 -0
  2065. package/src/extensions/trace-id.test.ts +230 -0
  2066. package/src/extensions/trace-id.ts +46 -0
  2067. package/src/extensions/ui-branch-poll.test.ts +164 -0
  2068. package/src/extensions/ui-branch-poll.ts +57 -0
  2069. package/src/extensions/ui.test.ts +185 -0
  2070. package/src/extensions/ui.ts +649 -0
  2071. package/src/extensions/web-fetch/browser-pool.test.ts +237 -0
  2072. package/src/extensions/web-fetch/browser-pool.ts +145 -0
  2073. package/src/extensions/web-fetch/cache.test.ts +196 -0
  2074. package/src/extensions/web-fetch/cache.ts +114 -0
  2075. package/src/extensions/web-fetch/content-converter.test.ts +341 -0
  2076. package/src/extensions/web-fetch/content-converter.ts +188 -0
  2077. package/src/extensions/web-fetch/execute-handler.test.ts +384 -0
  2078. package/src/extensions/web-fetch/execute-handler.ts +131 -0
  2079. package/src/extensions/web-fetch/index.ts +113 -0
  2080. package/src/extensions/web-fetch/integration.test.ts +618 -0
  2081. package/src/extensions/web-fetch/page-fetcher.test.ts +532 -0
  2082. package/src/extensions/web-fetch/page-fetcher.ts +358 -0
  2083. package/src/extensions/web-fetch/url-validator.test.ts +230 -0
  2084. package/src/extensions/web-fetch/url-validator.ts +153 -0
  2085. package/src/extensions/web-search/execute-handler.test.ts +216 -0
  2086. package/src/extensions/web-search/execute-handler.ts +151 -0
  2087. package/src/extensions/web-search/index.ts +107 -0
  2088. package/src/ferment/engine.test.ts +279 -0
  2089. package/src/ferment/engine.ts +320 -0
  2090. package/src/ferment/event-mapper.ts +313 -0
  2091. package/src/ferment/event-store.property.test.ts +240 -0
  2092. package/src/ferment/event-store.test.ts +780 -0
  2093. package/src/ferment/event-store.ts +1332 -0
  2094. package/src/ferment/fsm.test.ts +630 -0
  2095. package/src/ferment/fsm.ts +466 -0
  2096. package/src/ferment/lifecycle.ts +35 -0
  2097. package/src/ferment/state-machine.test.ts +1215 -0
  2098. package/src/ferment/state-machine.ts +994 -0
  2099. package/src/ferment/stats.test.ts +31 -0
  2100. package/src/ferment/stats.ts +334 -0
  2101. package/src/ferment/store.test.ts +543 -0
  2102. package/src/ferment/store.ts +906 -0
  2103. package/src/ferment/success-criteria.ts +51 -0
  2104. package/src/ferment/text.ts +11 -0
  2105. package/src/ferment/title.test.ts +35 -0
  2106. package/src/ferment/title.ts +28 -0
  2107. package/src/ferment/types.ts +277 -0
  2108. package/src/fs-paths.test.ts +104 -0
  2109. package/src/fs-paths.ts +112 -0
  2110. package/src/integrations/__fixtures__/models.ts +72 -0
  2111. package/src/integrations/bun-sqlite.d.ts +22 -0
  2112. package/src/integrations/claude-code.test.ts +488 -0
  2113. package/src/integrations/claude-code.ts +221 -0
  2114. package/src/integrations/constants.ts +9 -0
  2115. package/src/integrations/cursor.test.ts +91 -0
  2116. package/src/integrations/cursor.ts +188 -0
  2117. package/src/integrations/detect.ts +92 -0
  2118. package/src/integrations/gsd2.test.ts +146 -0
  2119. package/src/integrations/gsd2.ts +162 -0
  2120. package/src/integrations/models.ts +212 -0
  2121. package/src/integrations/openclaw.test.ts +314 -0
  2122. package/src/integrations/openclaw.ts +276 -0
  2123. package/src/integrations/opencode.test.ts +216 -0
  2124. package/src/integrations/opencode.ts +226 -0
  2125. package/src/integrations/provider/opencode.ts +37 -0
  2126. package/src/integrations/registry.test.ts +43 -0
  2127. package/src/integrations/registry.ts +33 -0
  2128. package/src/integrations/spawn.ts +88 -0
  2129. package/src/integrations/types.ts +35 -0
  2130. package/src/login-command-patch.test.ts +609 -0
  2131. package/src/login-command-patch.ts +299 -0
  2132. package/src/models.test.ts +827 -0
  2133. package/src/models.ts +379 -0
  2134. package/src/modes/acp/acp-prompter.ts +64 -0
  2135. package/src/modes/acp/acp-ui-context.test.ts +1001 -0
  2136. package/src/modes/acp/acp-ui-context.ts +435 -0
  2137. package/src/modes/acp/capabilities.ts +36 -0
  2138. package/src/modes/acp/commands.test.ts +29 -0
  2139. package/src/modes/acp/commands.ts +19 -0
  2140. package/src/modes/acp/permission-prompter-registry.ts +17 -0
  2141. package/src/modes/acp/server.test.ts +4392 -0
  2142. package/src/modes/acp/server.ts +1569 -0
  2143. package/src/modes/acp/utils.ts +10 -0
  2144. package/src/oauth-page-patch.test.ts +84 -0
  2145. package/src/ollama.test.ts +1469 -0
  2146. package/src/ollama.ts +491 -0
  2147. package/src/paste-interceptor.test.ts +179 -0
  2148. package/src/paste-interceptor.ts +61 -0
  2149. package/src/paste-to-editor-patch.test.ts +24 -0
  2150. package/src/paste-to-editor-patch.ts +27 -0
  2151. package/src/posthog-device.ts +31 -0
  2152. package/src/proxy.test.ts +36 -0
  2153. package/src/proxy.ts +36 -0
  2154. package/src/resources/bash-hook-discovery.ts +69 -0
  2155. package/src/resources/bash-hooks.test.ts +93 -0
  2156. package/src/resources/bash-hooks.ts +109 -0
  2157. package/src/resources/claude-code-hook-resources.ts +35 -0
  2158. package/src/resources/definitions.test.ts +92 -0
  2159. package/src/resources/definitions.ts +149 -0
  2160. package/src/resources/extension.test.ts +168 -0
  2161. package/src/resources/extension.ts +114 -0
  2162. package/src/resources/filter.ts +11 -0
  2163. package/src/resources/package-resources.test.ts +234 -0
  2164. package/src/resources/package-resources.ts +152 -0
  2165. package/src/resources/rtk-install.test.ts +37 -0
  2166. package/src/resources/rtk-install.ts +289 -0
  2167. package/src/resources/store.test.ts +118 -0
  2168. package/src/resources/store.ts +76 -0
  2169. package/src/resources/tool-blocker.ts +14 -0
  2170. package/src/resources/types.ts +23 -0
  2171. package/src/resources/ui.test.ts +74 -0
  2172. package/src/resources/ui.ts +221 -0
  2173. package/src/sandbox/cloud/auth.test.ts +219 -0
  2174. package/src/sandbox/cloud/auth.ts +127 -0
  2175. package/src/sandbox/cloud/http.test.ts +88 -0
  2176. package/src/sandbox/cloud/http.ts +46 -0
  2177. package/src/sandbox/cloud/index.ts +18 -0
  2178. package/src/sandbox/cloud/keys.test.ts +44 -0
  2179. package/src/sandbox/cloud/keys.ts +34 -0
  2180. package/src/sandbox/cloud/readiness.test.ts +115 -0
  2181. package/src/sandbox/cloud/readiness.ts +122 -0
  2182. package/src/sandbox/cloud/types.ts +70 -0
  2183. package/src/sandbox/cloud/uri.test.ts +51 -0
  2184. package/src/sandbox/cloud/uri.ts +30 -0
  2185. package/src/sandbox/cloud/workspaces.test.ts +249 -0
  2186. package/src/sandbox/cloud/workspaces.ts +161 -0
  2187. package/src/sandbox/constants.ts +2 -0
  2188. package/src/sandbox/git-credentials.test.ts +89 -0
  2189. package/src/sandbox/git-credentials.ts +72 -0
  2190. package/src/sandbox/worker/client.test.ts +156 -0
  2191. package/src/sandbox/worker/client.ts +201 -0
  2192. package/src/sandbox/worker/git-identity.test.ts +99 -0
  2193. package/src/sandbox/worker/git-identity.ts +69 -0
  2194. package/src/sandbox/worker/index.ts +36 -0
  2195. package/src/sandbox/worker/secrets.test.ts +61 -0
  2196. package/src/sandbox/worker/secrets.ts +28 -0
  2197. package/src/sandbox/worker/sessions.test.ts +197 -0
  2198. package/src/sandbox/worker/sessions.ts +32 -0
  2199. package/src/sandbox/worker/status.test.ts +57 -0
  2200. package/src/sandbox/worker/status.ts +6 -0
  2201. package/src/sandbox/worker/types.ts +119 -0
  2202. package/src/set-package-dir.ts +5 -0
  2203. package/src/settings-watcher.test.ts +116 -0
  2204. package/src/settings-watcher.ts +79 -0
  2205. package/src/setup-wizard/apply-tools.test.ts +131 -0
  2206. package/src/setup-wizard/apply-tools.ts +70 -0
  2207. package/src/setup-wizard/index.ts +107 -0
  2208. package/src/setup-wizard/prompt.ts +126 -0
  2209. package/src/setup-wizard/shell-profile.test.ts +154 -0
  2210. package/src/setup-wizard/shell-profile.ts +169 -0
  2211. package/src/setup-wizard/state.ts +45 -0
  2212. package/src/setup-wizard/steps/auth.test.ts +145 -0
  2213. package/src/setup-wizard/steps/auth.ts +130 -0
  2214. package/src/setup-wizard/steps/done.test.ts +267 -0
  2215. package/src/setup-wizard/steps/done.ts +121 -0
  2216. package/src/setup-wizard/steps/rtk.ts +6 -0
  2217. package/src/setup-wizard/steps/telemetry.test.ts +46 -0
  2218. package/src/setup-wizard/steps/telemetry.ts +41 -0
  2219. package/src/setup-wizard/steps/tools.ts +45 -0
  2220. package/src/setup-wizard/steps/welcome.ts +42 -0
  2221. package/src/setup-wizard.test.ts +384 -0
  2222. package/src/setup-wizard.ts +405 -0
  2223. package/src/shared/planning/entry-trigger-registry.test.ts +427 -0
  2224. package/src/shared/planning/entry-trigger-registry.ts +216 -0
  2225. package/src/shared/planning/plan-artifact-store.test.ts +338 -0
  2226. package/src/shared/planning/plan-artifact-store.ts +244 -0
  2227. package/src/shared/planning/plan-decomposition.test.ts +183 -0
  2228. package/src/shared/planning/plan-decomposition.ts +338 -0
  2229. package/src/shared/planning/planning-stop-nudge.test.ts +217 -0
  2230. package/src/shared/planning/planning-stop-nudge.ts +133 -0
  2231. package/src/shared/planning/prompt-supplement-registry.test.ts +264 -0
  2232. package/src/shared/planning/prompt-supplement-registry.ts +250 -0
  2233. package/src/shared/planning/read-only-tool-registry.test.ts +96 -0
  2234. package/src/shared/planning/read-only-tool-registry.ts +98 -0
  2235. package/src/shared/planning/shared-planning-process.test.ts +224 -0
  2236. package/src/shared/planning/shared-planning-process.ts +128 -0
  2237. package/src/shared/planning/tool-catalog.test.ts +344 -0
  2238. package/src/shared/planning/tool-catalog.ts +258 -0
  2239. package/src/shared/planning/tool-profile-manager.test.ts +409 -0
  2240. package/src/shared/planning/tool-profile-manager.ts +281 -0
  2241. package/src/skill-paths.test.ts +33 -0
  2242. package/src/skill-paths.ts +18 -0
  2243. package/src/skills-wizard.ts +44 -0
  2244. package/src/ssh-proxy.test.ts +102 -0
  2245. package/src/ssh-proxy.ts +79 -0
  2246. package/src/startup-context.ts +23 -0
  2247. package/src/startup-settings.test.ts +37 -0
  2248. package/src/startup-settings.ts +26 -0
  2249. package/src/terminal-bg-probe.test.ts +131 -0
  2250. package/src/terminal-bg-probe.ts +238 -0
  2251. package/src/theme-file-watcher.ts +95 -0
  2252. package/src/types/before-provider-headers.ts +48 -0
  2253. package/src/types/pi-coding-agent-utils.d.ts +34 -0
  2254. package/src/update/extract.ts +75 -0
  2255. package/src/update/github.test.ts +133 -0
  2256. package/src/update/github.ts +190 -0
  2257. package/src/update/install.test.ts +210 -0
  2258. package/src/update/install.ts +205 -0
  2259. package/src/update/paths.test.ts +97 -0
  2260. package/src/update/paths.ts +109 -0
  2261. package/src/update/state.test.ts +215 -0
  2262. package/src/update/state.ts +94 -0
  2263. package/src/update/workflow.test.ts +397 -0
  2264. package/src/update/workflow.ts +217 -0
  2265. package/src/upstream-retry-patch.test.ts +77 -0
  2266. package/src/upstream-retry-patch.ts +41 -0
  2267. package/src/utils/clipboard-image.test.ts +117 -0
  2268. package/src/utils/clipboard-image.ts +316 -0
  2269. package/src/utils/clipboard-linux-routing.test.ts +100 -0
  2270. package/src/utils/clipboard-linux-subprocess.test.ts +176 -0
  2271. package/src/utils/clipboard-linux-subprocess.ts +58 -0
  2272. package/src/utils/clipboard-native-harness-wsl.test.ts +109 -0
  2273. package/src/utils/clipboard-native-harness.test.ts +54 -0
  2274. package/src/utils/clipboard-native-harness.ts +146 -0
  2275. package/src/utils/clipboard-read.test.ts +88 -0
  2276. package/src/utils/clipboard-read.ts +69 -0
  2277. package/src/utils/export-post-process.test.ts +539 -0
  2278. package/src/utils/export-post-process.ts +213 -0
  2279. package/src/utils/http.test.ts +302 -0
  2280. package/src/utils/http.ts +106 -0
  2281. package/src/utils/image-registry.test.ts +88 -0
  2282. package/src/utils/image-registry.ts +132 -0
  2283. package/src/utils/image-utils.test.ts +58 -0
  2284. package/src/utils/image-utils.ts +38 -0
  2285. package/src/utils/os-metadata.ts +65 -0
  2286. package/src/utils/sandbox.test.ts +98 -0
  2287. package/src/utils/sandbox.ts +24 -0
  2288. package/src/utils/session-metadata-store.test.ts +228 -0
  2289. package/src/utils/session-metadata-store.ts +96 -0
  2290. package/src/utils/spawn-ikie-subprocess.ts +57 -0
  2291. package/src/utils/trace-id-export.test.ts +343 -0
  2292. package/src/utils/trace-id-export.ts +84 -0
  2293. package/src/utils.test.ts +38 -0
  2294. package/src/utils.ts +65 -0
  2295. package/test-cases/README.md +54 -0
  2296. package/test-cases/bitcoin-price.md +52 -0
  2297. package/test-cases/golang-question.md +29 -0
  2298. package/test-cases/offender.md +32 -0
  2299. package/test-cases/pi-mono-design.md +27 -0
  2300. package/test-cases/pi-mono-tool-card-loop.txt +1381 -0
  2301. package/test-cases/pi-mono-tool-card.md +60 -0
  2302. package/test-cases/pokemon.md +27 -0
  2303. package/test-cases/problem-740.md +20 -0
  2304. package/test-cases/python-project.md +24 -0
  2305. package/test-cases/remove-home-directory.md +53 -0
  2306. package/test-cases/use-gh.md +25 -0
  2307. package/tests/e2e/acp/all-capabilities.test.ts +102 -0
  2308. package/tests/e2e/acp/elicitation-dialogs.test.ts +139 -0
  2309. package/tests/e2e/acp/elicitation-only.test.ts +76 -0
  2310. package/tests/e2e/acp/message-id.test.ts +139 -0
  2311. package/tests/e2e/acp/no-capabilities.test.ts +71 -0
  2312. package/tests/e2e/acp/permission-flow.test.ts +237 -0
  2313. package/tests/e2e/acp/support/acp-fixture.ts +413 -0
  2314. package/tests/e2e/acp/support/scenarios.ts +55 -0
  2315. package/tests/e2e/acp/support/test-dialog-extension.js +22 -0
  2316. package/tests/e2e/acp/support/test-ui-extension.js +14 -0
  2317. package/tests/e2e/acp/vitest.config.ts +12 -0
  2318. package/tests/e2e/tui/ask-user-form.test.ts +310 -0
  2319. package/tests/e2e/tui/basic-session-lifecycle.test.ts +20 -0
  2320. package/tests/e2e/tui/branch-resume.test.ts +71 -0
  2321. package/tests/e2e/tui/cooking-animation.test.ts +213 -0
  2322. package/tests/e2e/tui/editor-narrow-layout.test.ts +47 -0
  2323. package/tests/e2e/tui/extension-custom-headers.test.ts +75 -0
  2324. package/tests/e2e/tui/ferment-draft-proposal-persistence.test.ts +125 -0
  2325. package/tests/e2e/tui/ferment-new-runs-planning.test.ts +211 -0
  2326. package/tests/e2e/tui/ferment-phase-review.test.ts +78 -0
  2327. package/tests/e2e/tui/ferment-plan-review-suppression.test.ts +404 -0
  2328. package/tests/e2e/tui/multi-model-command.test.ts +624 -0
  2329. package/tests/e2e/tui/nudge-wiring.test.ts +129 -0
  2330. package/tests/e2e/tui/ollama-models.test.ts +143 -0
  2331. package/tests/e2e/tui/oneshot-bypasses-dropdown.test.ts +97 -0
  2332. package/tests/e2e/tui/plan-mode-tool-switch.test.ts +73 -0
  2333. package/tests/e2e/tui/plan-review-dismissal.test.ts +291 -0
  2334. package/tests/e2e/tui/plan-to-ferment-promo.test.ts +204 -0
  2335. package/tests/e2e/tui/skip-list.js +9 -0
  2336. package/tests/e2e/tui/support/assertions.ts +41 -0
  2337. package/tests/e2e/tui/support/fake-ollama-server.ts +356 -0
  2338. package/tests/e2e/tui/support/fake-openai-server.ts +361 -0
  2339. package/tests/e2e/tui/support/ikie-fixture.ts +374 -0
  2340. package/tests/e2e/tui/theme-selector.test.ts +99 -0
  2341. package/tests/e2e/tui/todo-overlay.test.ts +163 -0
  2342. package/tests/e2e/tui/todo-widget-ferment.test.ts +346 -0
  2343. package/tests/e2e/tui/tui-test.config.ts +6 -0
  2344. package/tests/smoke/agent-session-tracking.test.ts +203 -0
  2345. package/tests/smoke/binary.test.ts +186 -0
  2346. package/tests/smoke/ferment-oneshot-exit.test.ts +514 -0
  2347. package/tests/smoke/harness.ts +236 -0
  2348. package/tests/smoke/interactive-paste.test.ts +167 -0
  2349. package/tests/smoke/vitest.config.ts +12 -0
  2350. package/tests/smoke/web-fetch.test.ts +41 -0
  2351. package/tests/smoke/web-search.test.ts +47 -0
  2352. package/themes/catppuccin-macchiato.json +82 -0
  2353. package/themes/dark.json +87 -0
  2354. package/themes/dracula.json +79 -0
  2355. package/themes/github-dark.json +80 -0
  2356. package/themes/github-light.json +80 -0
  2357. package/themes/ikie-light.json +92 -0
  2358. package/themes/ikie-minimal.json +79 -0
  2359. package/themes/ikie.json +96 -0
  2360. package/themes/light.json +86 -0
  2361. package/themes/lucent-orng.json +79 -0
  2362. package/themes/monokai.json +78 -0
  2363. package/themes/neon.json +87 -0
  2364. package/themes/night-owl.json +87 -0
  2365. package/themes/nord.json +82 -0
  2366. package/themes/one-dark.json +79 -0
  2367. package/themes/solarized-dark.json +81 -0
  2368. package/themes/solarized-light.json +81 -0
  2369. package/tools/proxy-helper/Makefile +11 -0
  2370. package/tools/proxy-helper/cmd/proxy/proxy.go +211 -0
  2371. package/tools/proxy-helper/cmd/proxy/proxy_test.go +309 -0
  2372. package/tools/proxy-helper/go.mod +13 -0
  2373. package/tools/proxy-helper/go.sum +12 -0
  2374. package/tools/proxy-helper/main.go +29 -0
  2375. package/tools/proxy-helper/pkg/cast/cast.go +287 -0
  2376. package/tsconfig.json +17 -0
  2377. package/vendor/superpowers/.claude-plugin/marketplace.json +20 -0
  2378. package/vendor/superpowers/.claude-plugin/plugin.json +20 -0
  2379. package/vendor/superpowers/.codex-plugin/plugin.json +47 -0
  2380. package/vendor/superpowers/.cursor-plugin/plugin.json +25 -0
  2381. package/vendor/superpowers/.gitattributes +18 -0
  2382. package/vendor/superpowers/.github/FUNDING.yml +3 -0
  2383. package/vendor/superpowers/.github/ISSUE_TEMPLATE/bug_report.md +52 -0
  2384. package/vendor/superpowers/.github/ISSUE_TEMPLATE/config.yml +5 -0
  2385. package/vendor/superpowers/.github/ISSUE_TEMPLATE/feature_request.md +34 -0
  2386. package/vendor/superpowers/.github/ISSUE_TEMPLATE/platform_support.md +23 -0
  2387. package/vendor/superpowers/.github/PULL_REQUEST_TEMPLATE.md +126 -0
  2388. package/vendor/superpowers/.opencode/INSTALL.md +110 -0
  2389. package/vendor/superpowers/.opencode/plugins/superpowers.js +135 -0
  2390. package/vendor/superpowers/.version-bump.json +20 -0
  2391. package/vendor/superpowers/CLAUDE.md +106 -0
  2392. package/vendor/superpowers/CODE_OF_CONDUCT.md +128 -0
  2393. package/vendor/superpowers/GEMINI.md +2 -0
  2394. package/vendor/superpowers/LICENSE +21 -0
  2395. package/vendor/superpowers/README.md +233 -0
  2396. package/vendor/superpowers/RELEASE-NOTES.md +1180 -0
  2397. package/vendor/superpowers/assets/app-icon.png +0 -0
  2398. package/vendor/superpowers/assets/superpowers-small.svg +1 -0
  2399. package/vendor/superpowers/docs/README.opencode.md +157 -0
  2400. package/vendor/superpowers/docs/plans/2025-11-22-opencode-support-design.md +294 -0
  2401. package/vendor/superpowers/docs/plans/2025-11-22-opencode-support-implementation.md +1095 -0
  2402. package/vendor/superpowers/docs/plans/2025-11-28-skills-improvements-from-user-feedback.md +711 -0
  2403. package/vendor/superpowers/docs/plans/2026-01-17-visual-brainstorming.md +571 -0
  2404. package/vendor/superpowers/docs/superpowers/plans/2026-01-22-document-review-system.md +301 -0
  2405. package/vendor/superpowers/docs/superpowers/plans/2026-02-19-visual-brainstorming-refactor.md +523 -0
  2406. package/vendor/superpowers/docs/superpowers/plans/2026-03-11-zero-dep-brainstorm-server.md +479 -0
  2407. package/vendor/superpowers/docs/superpowers/plans/2026-03-23-codex-app-compatibility.md +564 -0
  2408. package/vendor/superpowers/docs/superpowers/plans/2026-04-06-worktree-rototill.md +879 -0
  2409. package/vendor/superpowers/docs/superpowers/specs/2026-01-22-document-review-system-design.md +136 -0
  2410. package/vendor/superpowers/docs/superpowers/specs/2026-02-19-visual-brainstorming-refactor-design.md +162 -0
  2411. package/vendor/superpowers/docs/superpowers/specs/2026-03-11-zero-dep-brainstorm-server-design.md +118 -0
  2412. package/vendor/superpowers/docs/superpowers/specs/2026-03-23-codex-app-compatibility-design.md +244 -0
  2413. package/vendor/superpowers/docs/superpowers/specs/2026-04-06-worktree-rototill-design.md +342 -0
  2414. package/vendor/superpowers/docs/testing.md +303 -0
  2415. package/vendor/superpowers/docs/windows/polyglot-hooks.md +212 -0
  2416. package/vendor/superpowers/gemini-extension.json +6 -0
  2417. package/vendor/superpowers/hooks/hooks-cursor.json +10 -0
  2418. package/vendor/superpowers/hooks/hooks.json +16 -0
  2419. package/vendor/superpowers/hooks/run-hook.cmd +46 -0
  2420. package/vendor/superpowers/hooks/session-start +57 -0
  2421. package/vendor/superpowers/package.json +6 -0
  2422. package/vendor/superpowers/scripts/bump-version.sh +220 -0
  2423. package/vendor/superpowers/scripts/sync-to-codex-plugin.sh +462 -0
  2424. package/vendor/superpowers/skills/brainstorming/SKILL.md +164 -0
  2425. package/vendor/superpowers/skills/brainstorming/scripts/frame-template.html +214 -0
  2426. package/vendor/superpowers/skills/brainstorming/scripts/helper.js +88 -0
  2427. package/vendor/superpowers/skills/brainstorming/scripts/server.cjs +354 -0
  2428. package/vendor/superpowers/skills/brainstorming/scripts/start-server.sh +148 -0
  2429. package/vendor/superpowers/skills/brainstorming/scripts/stop-server.sh +56 -0
  2430. package/vendor/superpowers/skills/brainstorming/spec-document-reviewer-prompt.md +49 -0
  2431. package/vendor/superpowers/skills/brainstorming/visual-companion.md +287 -0
  2432. package/vendor/superpowers/skills/dispatching-parallel-agents/SKILL.md +182 -0
  2433. package/vendor/superpowers/skills/executing-plans/SKILL.md +70 -0
  2434. package/vendor/superpowers/skills/finishing-a-development-branch/SKILL.md +251 -0
  2435. package/vendor/superpowers/skills/receiving-code-review/SKILL.md +213 -0
  2436. package/vendor/superpowers/skills/requesting-code-review/SKILL.md +103 -0
  2437. package/vendor/superpowers/skills/requesting-code-review/code-reviewer.md +168 -0
  2438. package/vendor/superpowers/skills/subagent-driven-development/SKILL.md +279 -0
  2439. package/vendor/superpowers/skills/subagent-driven-development/code-quality-reviewer-prompt.md +25 -0
  2440. package/vendor/superpowers/skills/subagent-driven-development/implementer-prompt.md +113 -0
  2441. package/vendor/superpowers/skills/subagent-driven-development/spec-reviewer-prompt.md +61 -0
  2442. package/vendor/superpowers/skills/systematic-debugging/CREATION-LOG.md +119 -0
  2443. package/vendor/superpowers/skills/systematic-debugging/SKILL.md +296 -0
  2444. package/vendor/superpowers/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
  2445. package/vendor/superpowers/skills/systematic-debugging/condition-based-waiting.md +115 -0
  2446. package/vendor/superpowers/skills/systematic-debugging/defense-in-depth.md +122 -0
  2447. package/vendor/superpowers/skills/systematic-debugging/find-polluter.sh +63 -0
  2448. package/vendor/superpowers/skills/systematic-debugging/root-cause-tracing.md +169 -0
  2449. package/vendor/superpowers/skills/systematic-debugging/test-academic.md +14 -0
  2450. package/vendor/superpowers/skills/systematic-debugging/test-pressure-1.md +58 -0
  2451. package/vendor/superpowers/skills/systematic-debugging/test-pressure-2.md +68 -0
  2452. package/vendor/superpowers/skills/systematic-debugging/test-pressure-3.md +69 -0
  2453. package/vendor/superpowers/skills/test-driven-development/SKILL.md +371 -0
  2454. package/vendor/superpowers/skills/test-driven-development/testing-anti-patterns.md +299 -0
  2455. package/vendor/superpowers/skills/using-git-worktrees/SKILL.md +215 -0
  2456. package/vendor/superpowers/skills/using-superpowers/SKILL.md +117 -0
  2457. package/vendor/superpowers/skills/using-superpowers/references/codex-tools.md +59 -0
  2458. package/vendor/superpowers/skills/using-superpowers/references/copilot-tools.md +42 -0
  2459. package/vendor/superpowers/skills/using-superpowers/references/gemini-tools.md +51 -0
  2460. package/vendor/superpowers/skills/verification-before-completion/SKILL.md +139 -0
  2461. package/vendor/superpowers/skills/writing-plans/SKILL.md +152 -0
  2462. package/vendor/superpowers/skills/writing-plans/plan-document-reviewer-prompt.md +49 -0
  2463. package/vendor/superpowers/skills/writing-skills/SKILL.md +655 -0
  2464. package/vendor/superpowers/skills/writing-skills/anthropic-best-practices.md +1150 -0
  2465. package/vendor/superpowers/skills/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -0
  2466. package/vendor/superpowers/skills/writing-skills/graphviz-conventions.dot +172 -0
  2467. package/vendor/superpowers/skills/writing-skills/persuasion-principles.md +187 -0
  2468. package/vendor/superpowers/skills/writing-skills/render-graphs.js +168 -0
  2469. package/vendor/superpowers/skills/writing-skills/testing-skills-with-subagents.md +384 -0
  2470. package/vendor/superpowers/tests/brainstorm-server/package-lock.json +36 -0
  2471. package/vendor/superpowers/tests/brainstorm-server/package.json +10 -0
  2472. package/vendor/superpowers/tests/brainstorm-server/server.test.js +427 -0
  2473. package/vendor/superpowers/tests/brainstorm-server/windows-lifecycle.test.sh +351 -0
  2474. package/vendor/superpowers/tests/brainstorm-server/ws-protocol.test.js +392 -0
  2475. package/vendor/superpowers/tests/claude-code/README.md +170 -0
  2476. package/vendor/superpowers/tests/claude-code/analyze-token-usage.py +168 -0
  2477. package/vendor/superpowers/tests/claude-code/run-skill-tests.sh +188 -0
  2478. package/vendor/superpowers/tests/claude-code/test-document-review-system.sh +177 -0
  2479. package/vendor/superpowers/tests/claude-code/test-helpers.sh +202 -0
  2480. package/vendor/superpowers/tests/claude-code/test-requesting-code-review.sh +214 -0
  2481. package/vendor/superpowers/tests/claude-code/test-subagent-driven-development-integration.sh +322 -0
  2482. package/vendor/superpowers/tests/claude-code/test-subagent-driven-development.sh +165 -0
  2483. package/vendor/superpowers/tests/claude-code/test-worktree-native-preference.sh +176 -0
  2484. package/vendor/superpowers/tests/codex-plugin-sync/test-sync-to-codex-plugin.sh +615 -0
  2485. package/vendor/superpowers/tests/explicit-skill-requests/prompts/action-oriented.txt +3 -0
  2486. package/vendor/superpowers/tests/explicit-skill-requests/prompts/after-planning-flow.txt +17 -0
  2487. package/vendor/superpowers/tests/explicit-skill-requests/prompts/claude-suggested-it.txt +11 -0
  2488. package/vendor/superpowers/tests/explicit-skill-requests/prompts/i-know-what-sdd-means.txt +8 -0
  2489. package/vendor/superpowers/tests/explicit-skill-requests/prompts/mid-conversation-execute-plan.txt +3 -0
  2490. package/vendor/superpowers/tests/explicit-skill-requests/prompts/please-use-brainstorming.txt +1 -0
  2491. package/vendor/superpowers/tests/explicit-skill-requests/prompts/skip-formalities.txt +3 -0
  2492. package/vendor/superpowers/tests/explicit-skill-requests/prompts/subagent-driven-development-please.txt +1 -0
  2493. package/vendor/superpowers/tests/explicit-skill-requests/prompts/use-systematic-debugging.txt +1 -0
  2494. package/vendor/superpowers/tests/explicit-skill-requests/run-all.sh +70 -0
  2495. package/vendor/superpowers/tests/explicit-skill-requests/run-claude-describes-sdd.sh +100 -0
  2496. package/vendor/superpowers/tests/explicit-skill-requests/run-extended-multiturn-test.sh +113 -0
  2497. package/vendor/superpowers/tests/explicit-skill-requests/run-haiku-test.sh +144 -0
  2498. package/vendor/superpowers/tests/explicit-skill-requests/run-multiturn-test.sh +143 -0
  2499. package/vendor/superpowers/tests/explicit-skill-requests/run-test.sh +136 -0
  2500. package/vendor/superpowers/tests/opencode/run-tests.sh +165 -0
  2501. package/vendor/superpowers/tests/opencode/setup.sh +88 -0
  2502. package/vendor/superpowers/tests/opencode/test-bootstrap-caching.mjs +124 -0
  2503. package/vendor/superpowers/tests/opencode/test-bootstrap-caching.sh +32 -0
  2504. package/vendor/superpowers/tests/opencode/test-plugin-loading.sh +82 -0
  2505. package/vendor/superpowers/tests/opencode/test-priority.sh +217 -0
  2506. package/vendor/superpowers/tests/opencode/test-tools.sh +95 -0
  2507. package/vendor/superpowers/tests/skill-triggering/prompts/dispatching-parallel-agents.txt +8 -0
  2508. package/vendor/superpowers/tests/skill-triggering/prompts/executing-plans.txt +1 -0
  2509. package/vendor/superpowers/tests/skill-triggering/prompts/requesting-code-review.txt +3 -0
  2510. package/vendor/superpowers/tests/skill-triggering/prompts/systematic-debugging.txt +11 -0
  2511. package/vendor/superpowers/tests/skill-triggering/prompts/test-driven-development.txt +7 -0
  2512. package/vendor/superpowers/tests/skill-triggering/prompts/writing-plans.txt +10 -0
  2513. package/vendor/superpowers/tests/skill-triggering/run-all.sh +60 -0
  2514. package/vendor/superpowers/tests/skill-triggering/run-test.sh +88 -0
  2515. package/vendor/superpowers/tests/subagent-driven-dev/go-fractals/design.md +81 -0
  2516. package/vendor/superpowers/tests/subagent-driven-dev/go-fractals/plan.md +172 -0
  2517. package/vendor/superpowers/tests/subagent-driven-dev/go-fractals/scaffold.sh +45 -0
  2518. package/vendor/superpowers/tests/subagent-driven-dev/run-test.sh +106 -0
  2519. package/vendor/superpowers/tests/subagent-driven-dev/svelte-todo/design.md +70 -0
  2520. package/vendor/superpowers/tests/subagent-driven-dev/svelte-todo/plan.md +222 -0
  2521. package/vendor/superpowers/tests/subagent-driven-dev/svelte-todo/scaffold.sh +46 -0
  2522. package/vitest.config.ts +22 -0
@@ -0,0 +1,4392 @@
1
+ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs"
2
+ import { tmpdir } from "node:os"
3
+ import { join, resolve } from "node:path"
4
+ import type {
5
+ AgentSideConnection,
6
+ ListSessionsRequest,
7
+ RequestPermissionRequest,
8
+ SessionNotification,
9
+ TextContent,
10
+ } from "@agentclientprotocol/sdk"
11
+ import type { AssistantMessage } from "@earendil-works/pi-ai"
12
+ import type {
13
+ AgentSession,
14
+ AgentSessionEvent,
15
+ AgentSessionEventListener,
16
+ AuthStorage,
17
+ ExtensionContext,
18
+ ExtensionUIContext,
19
+ ModelRegistry,
20
+ SessionInfo as PiSessionInfo,
21
+ SessionManager,
22
+ Theme,
23
+ } from "@earendil-works/pi-coding-agent"
24
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"
25
+
26
+ const THEME_KEY = Symbol.for("@earendil-works/pi-coding-agent:theme")
27
+ const THEME_KEY_OLD = Symbol.for("@mariozechner/pi-coding-agent:theme")
28
+
29
+ import { _resetState as _resetHideThinking, _setHideThinking } from "../../extensions/hide-thinking.js"
30
+ import { PERMISSIONS_ENV_KEY } from "../../extensions/permissions/constants.js"
31
+ import { getSessionPermissionFlagController } from "../../extensions/permissions/mode-controller-registry.js"
32
+ import { ALL_PERMISSION_MODES } from "../../extensions/permissions/types.js"
33
+ import { getAcpPrompter } from "./permission-prompter-registry.js"
34
+ import {
35
+ type AcpSessionFactory,
36
+ type AcpSessionLister,
37
+ type AcpSessionLoader,
38
+ IkieAcpAgent,
39
+ assertSessionHasModel,
40
+ buildSessionModelState,
41
+ describeToolCall,
42
+ initializeHeadlessTheme,
43
+ isHiddenToolCall,
44
+ shouldEmitThinking,
45
+ stripAnsi,
46
+ toAcpSessionInfo,
47
+ userMessageText,
48
+ } from "./server.js"
49
+
50
+ // Minimal fake of AgentSession surface used by IkieAcpAgent. The factory seam
51
+ // means we only need to stand in for the methods the ACP server actually calls:
52
+ // sessionId, subscribe, prompt, abort, dispose. loadSession also reads
53
+ // `sessionManager.getBranch()` for replay and `model` for the response, so the
54
+ // fake exposes settable fields for both.
55
+ class FakeAgentSession {
56
+ readonly sessionId: string
57
+ private listeners = new Set<AgentSessionEventListener>()
58
+ disposed = false
59
+ aborted = false
60
+ model: { provider: string; id: string; name?: string; input?: string[] } | undefined = {
61
+ provider: "test",
62
+ id: "test-model",
63
+ name: "Test Model",
64
+ input: ["text"],
65
+ }
66
+ modelRegistry = {
67
+ getAvailable: () =>
68
+ this.model
69
+ ? [
70
+ {
71
+ provider: this.model.provider,
72
+ id: this.model.id,
73
+ name: this.model.name ?? this.model.id,
74
+ },
75
+ ]
76
+ : [],
77
+ }
78
+ promptImpl: (text: string, opts?: { images?: unknown[] }) => Promise<void> = async () => {}
79
+ abortImpl: () => Promise<void> = async () => {}
80
+ bindExtensionsImpl: (_bindings: unknown) => Promise<void> = async () => {}
81
+ lastPromptImages?: unknown[]
82
+ promptCalls: Array<{ prompt: string; opts?: { images?: unknown[] } }> = []
83
+ // Branch entries returned to the replay walker. Tests fill this with the
84
+ // shape buildSessionContext consumers expect (type:"message" + role).
85
+ branch: unknown[] = []
86
+ sessionManager = {
87
+ getBranch: () => this.branch,
88
+ }
89
+ // Captures whatever setUIContext the agent installs so tests can assert
90
+ // on it. The real AgentSession exposes this via its extensionRunner
91
+ // getter; the fake keeps it on the session root for simpler test wiring.
92
+ setUIContextCalls: unknown[] = []
93
+ extensionRunner = {
94
+ setUIContext: (ui: unknown) => {
95
+ this.setUIContextCalls.push(ui)
96
+ },
97
+ emit: async (_event: unknown) => {
98
+ // Real runner exposes emit for session lifecycle events; the fake
99
+ // just resolves so disposeSessionRecord's session_shutdown hook
100
+ // doesn't throw.
101
+ },
102
+ }
103
+
104
+ constructor(sessionId: string) {
105
+ this.sessionId = sessionId
106
+ }
107
+
108
+ subscribe(listener: AgentSessionEventListener): () => void {
109
+ this.listeners.add(listener)
110
+ return () => {
111
+ this.listeners.delete(listener)
112
+ }
113
+ }
114
+
115
+ emit(event: AgentSessionEvent): void {
116
+ for (const l of [...this.listeners]) l(event)
117
+ }
118
+
119
+ async prompt(text: string, opts?: { images?: unknown[] }): Promise<void> {
120
+ this.lastPromptImages = opts?.images
121
+ this.promptCalls.push({ prompt: text, opts })
122
+ await this.promptImpl(text, opts)
123
+ }
124
+
125
+ async setModel(model: { provider: string; id: string }): Promise<void> {
126
+ this.model = model
127
+ }
128
+
129
+ async abort(): Promise<void> {
130
+ this.aborted = true
131
+ await this.abortImpl()
132
+ }
133
+
134
+ async bindExtensions(bindings: unknown): Promise<void> {
135
+ await this.bindExtensionsImpl(bindings)
136
+ }
137
+
138
+ dispose(): void {
139
+ this.disposed = true
140
+ this.listeners.clear()
141
+ }
142
+ }
143
+
144
+ function asSession(fake: FakeAgentSession): AgentSession {
145
+ return fake as unknown as AgentSession
146
+ }
147
+
148
+ function makeConn(): AgentSideConnection {
149
+ const stub = {
150
+ sessionUpdate: async (_p: SessionNotification) => {},
151
+ }
152
+ return stub as unknown as AgentSideConnection
153
+ }
154
+
155
+ // Recording variant of makeConn: captures every sessionUpdate the agent emits
156
+ // so tests can assert on the full notification stream (tool_call, partial
157
+ // tool_call_update, terminal tool_call_update, etc.).
158
+ function makeRecordingConn(): {
159
+ conn: AgentSideConnection
160
+ updates: SessionNotification[]
161
+ } {
162
+ const updates: SessionNotification[] = []
163
+ const stub = {
164
+ sessionUpdate: async (p: SessionNotification) => {
165
+ updates.push(p)
166
+ },
167
+ requestPermission: vi.fn().mockResolvedValue({ outcome: "cancelled" }),
168
+ }
169
+ return { conn: stub as unknown as AgentSideConnection, updates }
170
+ }
171
+
172
+ const delay = (ms: number) => new Promise<void>((r) => setTimeout(r, ms))
173
+
174
+ function agentEnd(): AgentSessionEvent {
175
+ return { type: "agent_end", messages: [], willRetry: false }
176
+ }
177
+
178
+ // Drop the incidental `available_commands_update` re-broadcast on session
179
+ // resume so replay tests can assert on transcript shape alone.
180
+ function replayOnly(updates: SessionNotification[]): SessionNotification[] {
181
+ return updates.filter((u) => u.update.sessionUpdate !== "available_commands_update")
182
+ }
183
+
184
+ describe("IkieAcpAgent turn lifecycle", () => {
185
+ let fake: FakeAgentSession
186
+ let agent: IkieAcpAgent
187
+ let sessionId: string
188
+
189
+ beforeEach(async () => {
190
+ fake = new FakeAgentSession("session-a")
191
+ const sessionFactory: AcpSessionFactory = async () => asSession(fake)
192
+ agent = new IkieAcpAgent(makeConn(), {
193
+ extensionFactories: [],
194
+ agentDir: "/tmp/fake-agent-dir",
195
+ sessionFactory,
196
+ })
197
+ const res = await agent.newSession({ cwd: "/tmp", mcpServers: [] })
198
+ sessionId = res.sessionId
199
+ })
200
+
201
+ // initialize() should declare image support based on cached models.json
202
+ describe("initialize capability detection", () => {
203
+ const tempAgentDir = "/tmp/ikie-acp-test-agent-dir"
204
+
205
+ beforeEach(() => {
206
+ // Clean up and create temp agent dir
207
+ try {
208
+ rmSync(tempAgentDir, { recursive: true, force: true })
209
+ } catch {}
210
+ mkdirSync(tempAgentDir, { recursive: true })
211
+ })
212
+
213
+ afterEach(() => {
214
+ try {
215
+ rmSync(tempAgentDir, { recursive: true, force: true })
216
+ } catch {}
217
+ })
218
+
219
+ it("declares image: true when cached models include vision models", async () => {
220
+ // Stub API key so models are considered "available" (configured auth)
221
+ const restoreEnv = (key: string, value: string | undefined) => {
222
+ const original = process.env[key]
223
+ process.env[key] = value
224
+ return () => {
225
+ process.env[key] = original
226
+ }
227
+ }
228
+ const cleanup = restoreEnv("OPENAI_API_KEY", "fake-key-for-testing")
229
+
230
+ try {
231
+ const modelsJson = {
232
+ providers: {
233
+ openai: {
234
+ models: [
235
+ {
236
+ id: "gpt-4o",
237
+ name: "GPT-4o",
238
+ input: ["text", "image"],
239
+ },
240
+ ],
241
+ },
242
+ },
243
+ }
244
+ writeFileSync(resolve(tempAgentDir, "models.json"), JSON.stringify(modelsJson))
245
+
246
+ const testAgent = new IkieAcpAgent(makeConn(), {
247
+ extensionFactories: [],
248
+ agentDir: tempAgentDir,
249
+ sessionFactory: async () => asSession(fake),
250
+ })
251
+
252
+ const response = await testAgent.initialize({ protocolVersion: 1 })
253
+ expect(response.agentCapabilities?.promptCapabilities?.image).toBe(true)
254
+ } finally {
255
+ cleanup()
256
+ }
257
+ })
258
+
259
+ it("declares image capability based on available models", async () => {
260
+ // ModelRegistry merges cached models with built-in defaults.
261
+ // This test verifies the initialize() method correctly queries
262
+ // the registry and returns a boolean for image support.
263
+ const testAgent = new IkieAcpAgent(makeConn(), {
264
+ extensionFactories: [],
265
+ agentDir: tempAgentDir,
266
+ sessionFactory: async () => asSession(fake),
267
+ })
268
+
269
+ const response = await testAgent.initialize({ protocolVersion: 1 })
270
+ // The result depends on merged models (cached + built-in).
271
+ // Just verify it's a boolean (the logic ran successfully).
272
+ expect(typeof response.agentCapabilities?.promptCapabilities?.image).toBe("boolean")
273
+ })
274
+ })
275
+
276
+ // session.prompt() is the source of truth for "turn is done". When events
277
+ // arrive AFTER session.prompt resolves (e.g. a slow downstream handler
278
+ // awaited something), the turn was already finalized on session.prompt
279
+ // resolve — late events must be dropped. agent_end no longer drives
280
+ // finalization, so it cannot be used as a barrier. If this ever regresses
281
+ // to "wait for late agent_end", we'd be vulnerable to the chained
282
+ // agent.continue() bug again.
283
+ it("drops late turn events that arrive after session.prompt resolves", async () => {
284
+ let lateEventsFired = false
285
+ fake.promptImpl = async () => {
286
+ await delay(5)
287
+ setTimeout(() => {
288
+ fake.emit({ type: "agent_start" })
289
+ fake.emit(agentEnd())
290
+ lateEventsFired = true
291
+ }, 30)
292
+ }
293
+
294
+ const result = await agent.prompt({
295
+ sessionId,
296
+ prompt: [{ type: "text", text: "hi" }],
297
+ })
298
+ expect(result.stopReason).toBe("end_turn")
299
+ expect(lateEventsFired).toBe(false)
300
+
301
+ await delay(40)
302
+ expect(lateEventsFired).toBe(true)
303
+ })
304
+
305
+ // Extension-command / input-handler / no-op path: session.prompt returns
306
+ // without emitting any agent events. The ACP handler must synthesize
307
+ // end_turn itself — no agent_end is ever coming.
308
+ it("synthesizes end_turn when the turn short-circuits without agent_start", async () => {
309
+ fake.promptImpl = async () => {
310
+ // No events emitted — exactly like an extension-command path.
311
+ }
312
+
313
+ const result = await agent.prompt({
314
+ sessionId,
315
+ prompt: [{ type: "text", text: "/help" }],
316
+ })
317
+
318
+ expect(result.stopReason).toBe("end_turn")
319
+ })
320
+
321
+ // Regression: pi-mono's _runAgentPrompt chains multiple agent.prompt /
322
+ // agent.continue calls when retries, queued follow-up messages, or
323
+ // compaction are pending. Each chained call emits its own agent_start +
324
+ // agent_end pair. Previously the ACP handler finalized on the FIRST
325
+ // agent_end, sending end_turn mid-stream — the client then tried to send
326
+ // a new prompt and hit pi-mono's "Agent is already processing" throw
327
+ // because session.prompt was still running the chained continues.
328
+ // Now: end_turn is sent exactly once, only after session.prompt()
329
+ // resolves (i.e. after ALL chained calls complete).
330
+ it("sends exactly one end_turn after chained agent.continue() cycles complete", async () => {
331
+ const { conn: recordingConn, updates } = makeRecordingConn()
332
+ const localAgent = new IkieAcpAgent(recordingConn, {
333
+ extensionFactories: [],
334
+ agentDir: "/tmp/fake-agent-dir",
335
+ sessionFactory: async () => asSession(fake),
336
+ })
337
+ const res = await localAgent.newSession({ cwd: "/tmp", mcpServers: [] })
338
+ const localSessionId = res.sessionId
339
+
340
+ fake.promptImpl = async () => {
341
+ // Cycle 1 — first agent.prompt call.
342
+ fake.emit({ type: "agent_start" })
343
+ fake.emit({
344
+ type: "message_update",
345
+ assistantMessageEvent: {
346
+ type: "text_delta",
347
+ delta: "first",
348
+ contentIndex: 0,
349
+ partial: {} as unknown as AssistantMessage,
350
+ },
351
+ message: {} as unknown as AssistantMessage,
352
+ })
353
+ fake.emit(agentEnd())
354
+ await delay(5)
355
+ // Cycle 2 — agent.continue() (e.g. follow-up message queued,
356
+ // retry needed, or compaction). The user-visible bug is that the
357
+ // FIRST agent_end used to trigger end_turn here, dropping cycle 2.
358
+ fake.emit({ type: "agent_start" })
359
+ fake.emit({
360
+ type: "message_update",
361
+ assistantMessageEvent: {
362
+ type: "text_delta",
363
+ delta: "second",
364
+ contentIndex: 0,
365
+ partial: {} as unknown as AssistantMessage,
366
+ },
367
+ message: {} as unknown as AssistantMessage,
368
+ })
369
+ fake.emit(agentEnd())
370
+ }
371
+
372
+ const result = await localAgent.prompt({
373
+ sessionId: localSessionId,
374
+ prompt: [{ type: "text", text: "go" }],
375
+ })
376
+
377
+ // Single end_turn, with stopReason "end_turn".
378
+ expect(result.stopReason).toBe("end_turn")
379
+
380
+ // Both cycles' chunks reach the client. Under the OLD behavior,
381
+ // the first agent_end would have cleared entry.turn and dropped
382
+ // every cycle-2 event — so this assertion is the bug-reproducer.
383
+ const chunks = updates.flatMap((u) =>
384
+ u.update.sessionUpdate === "agent_message_chunk" ? [(u.update.content as TextContent).text] : [],
385
+ )
386
+ expect(chunks).toEqual(["first", "second"])
387
+ })
388
+
389
+ // Cancel arrives between chained agent.continue() cycles. Cycle 1 completes
390
+ // normally (agent_start → message_update → agent_end), then the client calls
391
+ // cancel() before cycle 2 starts. session.prompt() resolves (abort may or may
392
+ // not prevent the next continue), and the .then() handler sees cancelled=true.
393
+ // The first cycle's chunks must still reach the client; the result must be
394
+ // "cancelled", not "end_turn".
395
+ it("resolves cancelled when cancel arrives between chained agent.continue() cycles", async () => {
396
+ const { conn: recordingConn, updates } = makeRecordingConn()
397
+ const localAgent = new IkieAcpAgent(recordingConn, {
398
+ extensionFactories: [],
399
+ agentDir: "/tmp/fake-agent-dir",
400
+ sessionFactory: async () => asSession(fake),
401
+ })
402
+ const res = await localAgent.newSession({ cwd: "/tmp", mcpServers: [] })
403
+ const localSessionId = res.sessionId
404
+
405
+ let cancelSeen = false
406
+ fake.promptImpl = async () => {
407
+ // Cycle 1 — completes normally.
408
+ fake.emit({ type: "agent_start" })
409
+ fake.emit({
410
+ type: "message_update",
411
+ assistantMessageEvent: {
412
+ type: "text_delta",
413
+ delta: "before-cancel",
414
+ contentIndex: 0,
415
+ partial: {} as unknown as AssistantMessage,
416
+ },
417
+ message: {} as unknown as AssistantMessage,
418
+ })
419
+ fake.emit(agentEnd())
420
+
421
+ // Simulate the async boundary between chained calls where
422
+ // _handlePostAgentRun decides whether to continue. The client's
423
+ // cancel() lands here.
424
+ while (!cancelSeen) await delay(5)
425
+
426
+ // Cycle 2 — would have run, but abort arrived. In real pi-mono the
427
+ // next agent.continue() may not even start; simulate the benign case
428
+ // where it does start but produces nothing meaningful before abort
429
+ // tears it down.
430
+ fake.emit({ type: "agent_start" })
431
+ fake.emit(agentEnd())
432
+ }
433
+ fake.abortImpl = async () => {
434
+ cancelSeen = true
435
+ }
436
+
437
+ const promptP = localAgent.prompt({
438
+ sessionId: localSessionId,
439
+ prompt: [{ type: "text", text: "go" }],
440
+ })
441
+ // Let cycle 1 complete and the promptImpl pause at the while-loop.
442
+ await delay(20)
443
+ await localAgent.cancel({ sessionId: localSessionId })
444
+
445
+ const result = await promptP
446
+ expect(result.stopReason).toBe("cancelled")
447
+ expect(fake.aborted).toBe(true)
448
+
449
+ // Cycle 1's chunk must have been delivered before cancellation.
450
+ const chunks = updates.flatMap((u) =>
451
+ u.update.sessionUpdate === "agent_message_chunk" ? [(u.update.content as TextContent).text] : [],
452
+ )
453
+ expect(chunks).toContain("before-cancel")
454
+ })
455
+
456
+ // Client cancels mid-turn: cancelled=true is set on the turn context, then
457
+ // agent_end fires and the subscriber finalizes with stopReason=cancelled.
458
+ it("resolves cancelled when cancel fires before agent_end", async () => {
459
+ let cancelSeen = false
460
+ fake.promptImpl = async () => {
461
+ fake.emit({ type: "agent_start" })
462
+ // Wait until cancel() runs.
463
+ while (!cancelSeen) await delay(5)
464
+ // pi-mono's abort path still emits agent_end on teardown.
465
+ fake.emit(agentEnd())
466
+ }
467
+ fake.abortImpl = async () => {
468
+ cancelSeen = true
469
+ }
470
+
471
+ const promptP = agent.prompt({
472
+ sessionId,
473
+ prompt: [{ type: "text", text: "run forever" }],
474
+ })
475
+ // Give the prompt a moment to arm the turn context.
476
+ await delay(10)
477
+ await agent.cancel({ sessionId })
478
+
479
+ const result = await promptP
480
+ expect(result.stopReason).toBe("cancelled")
481
+ expect(fake.aborted).toBe(true)
482
+ })
483
+
484
+ // Cancel path where pi-mono surfaces abortion as a rejection instead of a
485
+ // final agent_end: the RPC contract still demands stopReason="cancelled",
486
+ // not a JSON-RPC error. The prompt() catch block must honor cancelled=true
487
+ // and resolve, not reject.
488
+ it("resolves cancelled when session.prompt rejects after cancel", async () => {
489
+ let cancelSeen = false
490
+ fake.promptImpl = async () => {
491
+ fake.emit({ type: "agent_start" })
492
+ while (!cancelSeen) await delay(5)
493
+ // Simulate pi-mono's "abort throws out of prompt()" variant — no
494
+ // agent_end is emitted before the rejection.
495
+ throw new Error("AbortError: operation was aborted")
496
+ }
497
+ fake.abortImpl = async () => {
498
+ cancelSeen = true
499
+ }
500
+
501
+ const promptP = agent.prompt({
502
+ sessionId,
503
+ prompt: [{ type: "text", text: "run forever" }],
504
+ })
505
+ await delay(10)
506
+ await agent.cancel({ sessionId })
507
+
508
+ const result = await promptP
509
+ expect(result.stopReason).toBe("cancelled")
510
+ expect(fake.aborted).toBe(true)
511
+ })
512
+
513
+ // If session.prompt throws (pre-turn validation, config error, etc.), the
514
+ // outer RPC promise must reject — not hang — regardless of whether any
515
+ // events were emitted before the throw.
516
+ it("rejects the outer prompt when session.prompt throws", async () => {
517
+ fake.promptImpl = async () => {
518
+ throw new Error("no model configured")
519
+ }
520
+
521
+ await expect(agent.prompt({ sessionId, prompt: [{ type: "text", text: "x" }] })).rejects.toThrow(
522
+ /no model configured/,
523
+ )
524
+ })
525
+
526
+ // Chained continues: cycle 1 succeeds but cycle 2's agent.continue() throws
527
+ // a non-abort error (e.g. context overflow during compaction retry). The
528
+ // .catch() handler must propagate the error since cancelled is false — the
529
+ // client sees a JSON-RPC error, not a silent end_turn that hides the failure.
530
+ it("rejects the outer prompt when a chained agent.continue() throws a non-abort error", async () => {
531
+ fake.promptImpl = async () => {
532
+ // Cycle 1 — completes normally.
533
+ fake.emit({ type: "agent_start" })
534
+ fake.emit({
535
+ type: "message_update",
536
+ assistantMessageEvent: {
537
+ type: "text_delta",
538
+ delta: "partial",
539
+ contentIndex: 0,
540
+ partial: {} as unknown as AssistantMessage,
541
+ },
542
+ message: {} as unknown as AssistantMessage,
543
+ })
544
+ fake.emit(agentEnd())
545
+ await delay(5)
546
+ // Cycle 2 — blows up.
547
+ fake.emit({ type: "agent_start" })
548
+ throw new Error("context window overflow during compaction")
549
+ }
550
+
551
+ await expect(agent.prompt({ sessionId, prompt: [{ type: "text", text: "go" }] })).rejects.toThrow(
552
+ /context window overflow during compaction/,
553
+ )
554
+ })
555
+
556
+ // shutdown() must not leave pending PromptResponse promises dangling.
557
+ // When the caller awaits shutdown (e.g. runAcpMode's finally after
558
+ // conn.closed resolves) an in-flight turn must be rejected so the prompt
559
+ // caller's await settles rather than hanging until process exit.
560
+ it("rejects in-flight turns when shutdown() is called", async () => {
561
+ let resumePrompt!: () => void
562
+ const pending = new Promise<void>((resolve) => {
563
+ resumePrompt = resolve
564
+ })
565
+ fake.promptImpl = async () => {
566
+ fake.emit({ type: "agent_start" })
567
+ await pending // never resolves on its own in this test
568
+ }
569
+
570
+ const promptP = agent.prompt({
571
+ sessionId,
572
+ prompt: [{ type: "text", text: "hang forever" }],
573
+ })
574
+ // Pre-attach catch handler so the rejection fires synchronously during
575
+ // shutdown without landing as an unhandled rejection.
576
+ const caught = promptP.catch((err) => err)
577
+ // Arm the turn.
578
+ await delay(10)
579
+
580
+ await agent.shutdown()
581
+ const err = await caught
582
+ expect(err).toBeInstanceOf(Error)
583
+ expect((err as Error).message).toMatch(/shutting down/)
584
+ // Cleanup the dangling promptImpl.
585
+ resumePrompt()
586
+ expect(fake.disposed).toBe(true)
587
+ })
588
+
589
+ // Misbehaving client sends a block type our capabilities declared as
590
+ // unsupported (image/audio/embeddedContext). The server drops it silently
591
+ // from the text payload but must warn on stderr so a dev debugging the
592
+ // resulting empty-turn sees what happened. Warn exactly once per type.
593
+ it("warns once on stderr for unsupported prompt block types", async () => {
594
+ const writes: string[] = []
595
+ const origWrite = process.stderr.write.bind(process.stderr)
596
+ // biome-ignore lint/suspicious/noExplicitAny: test-only stderr capture
597
+ ;(process.stderr.write as any) = (chunk: string | Uint8Array) => {
598
+ writes.push(typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8"))
599
+ return true
600
+ }
601
+ try {
602
+ const r1 = await agent.prompt({
603
+ sessionId,
604
+ // biome-ignore lint/suspicious/noExplicitAny: unsupported block on purpose
605
+ prompt: [{ type: "audio" as any, data: "x" } as any],
606
+ })
607
+ expect(r1.stopReason).toBe("end_turn")
608
+ // Second call with same unsupported type: no new warning (deduped).
609
+ const r2 = await agent.prompt({
610
+ sessionId,
611
+ // biome-ignore lint/suspicious/noExplicitAny: unsupported block on purpose
612
+ prompt: [{ type: "audio" as any, data: "y" } as any],
613
+ })
614
+ expect(r2.stopReason).toBe("end_turn")
615
+ // New unsupported type: warns again.
616
+ const r3 = await agent.prompt({
617
+ sessionId,
618
+ // biome-ignore lint/suspicious/noExplicitAny: unsupported block on purpose
619
+ prompt: [{ type: "embeddedContext" as any, data: "z" } as any],
620
+ })
621
+ expect(r3.stopReason).toBe("end_turn")
622
+ } finally {
623
+ process.stderr.write = origWrite
624
+ }
625
+ const matches = writes.filter((w) => w.includes("acp prompt: dropping"))
626
+ expect(matches).toHaveLength(2)
627
+ expect(matches.some((w) => w.includes("audio block"))).toBe(true)
628
+ expect(matches.some((w) => w.includes("embeddedContext block"))).toBe(true)
629
+ })
630
+
631
+ // Image blocks are supported when model supports vision: they should be
632
+ // extracted and passed to session.prompt() without warnings.
633
+ it("accepts image blocks when model supports vision", async () => {
634
+ fake.model = {
635
+ provider: "test",
636
+ id: "vision-model",
637
+ input: ["text", "image"],
638
+ }
639
+ fake.promptImpl = async () => {
640
+ fake.emit({ type: "agent_start" })
641
+ await delay(5)
642
+ fake.emit(agentEnd())
643
+ }
644
+
645
+ const result = await agent.prompt({
646
+ sessionId,
647
+ prompt: [
648
+ { type: "text", text: "describe this image" },
649
+ { type: "image", data: "base64data", mimeType: "image/png" },
650
+ ],
651
+ })
652
+ expect(result.stopReason).toBe("end_turn")
653
+ // Verify images were passed to session.prompt
654
+ expect(fake.lastPromptImages).toHaveLength(1)
655
+ expect(fake.lastPromptImages?.[0]).toMatchObject({
656
+ type: "image",
657
+ data: "base64data",
658
+ mimeType: "image/png",
659
+ })
660
+ })
661
+
662
+ // Image blocks are dropped when model doesn't support vision: they should
663
+ // be silently discarded with a warning.
664
+ it("drops image blocks when model has no vision support", async () => {
665
+ fake.model = { provider: "test", id: "text-only-model", input: ["text"] }
666
+ fake.promptImpl = async () => {
667
+ fake.emit({ type: "agent_start" })
668
+ await delay(5)
669
+ fake.emit(agentEnd())
670
+ }
671
+
672
+ const writes: string[] = []
673
+ const origWrite = process.stderr.write.bind(process.stderr)
674
+ // biome-ignore lint/suspicious/noExplicitAny: test-only stderr capture
675
+ ;(process.stderr.write as any) = (chunk: string | Uint8Array) => {
676
+ writes.push(typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8"))
677
+ return true
678
+ }
679
+
680
+ try {
681
+ const result = await agent.prompt({
682
+ sessionId,
683
+ prompt: [
684
+ { type: "text", text: "describe this image" },
685
+ { type: "image", data: "base64data", mimeType: "image/png" },
686
+ ],
687
+ })
688
+ expect(result.stopReason).toBe("end_turn")
689
+ // Images should be dropped, not passed to session.prompt (passed as empty array)
690
+ expect(fake.lastPromptImages).toEqual([])
691
+ } finally {
692
+ process.stderr.write = origWrite
693
+ }
694
+
695
+ const matches = writes.filter((w) =>
696
+ w.includes("acp prompt: dropping image block (active model has no vision input)"),
697
+ )
698
+ expect(matches).toHaveLength(1)
699
+ })
700
+
701
+ // Defensive: once a turn is finalized (short-circuit, shutdown, cancel),
702
+ // stray tool_execution_{start,end} must not emit tool_call notifications
703
+ // to the client. Clients would otherwise see tool activity on a turn they
704
+ // consider complete. Checked alongside the existing agent_end drop test.
705
+ it("drops stray tool_execution_start/end after a short-circuited turn", async () => {
706
+ const localFake = new FakeAgentSession("session-tool-late")
707
+ const factory: AcpSessionFactory = async () => asSession(localFake)
708
+ const { conn, updates } = makeRecordingConn()
709
+ const localAgent = new IkieAcpAgent(conn, {
710
+ extensionFactories: [],
711
+ agentDir: "/tmp/fake-agent-dir",
712
+ sessionFactory: factory,
713
+ })
714
+ const { sessionId: sid } = await localAgent.newSession({
715
+ cwd: "/tmp",
716
+ mcpServers: [],
717
+ })
718
+
719
+ localFake.promptImpl = async () => {
720
+ // Short-circuit: no events.
721
+ }
722
+ const result = await localAgent.prompt({
723
+ sessionId: sid,
724
+ prompt: [{ type: "text", text: "/help" }],
725
+ })
726
+ expect(result.stopReason).toBe("end_turn")
727
+ const updatesBefore = updates.length
728
+
729
+ // Stray tool events arrive after finalization — must be dropped.
730
+ localFake.emit({
731
+ type: "tool_execution_start",
732
+ toolCallId: "tc-late",
733
+ toolName: "bash",
734
+ args: { command: "late" },
735
+ })
736
+ localFake.emit({
737
+ type: "tool_execution_end",
738
+ toolCallId: "tc-late",
739
+ toolName: "bash",
740
+ result: { content: [{ type: "text", text: "late" }] },
741
+ isError: false,
742
+ })
743
+ expect(updates.length).toBe(updatesBefore)
744
+ })
745
+
746
+ // Defensive: a late agent_end arriving after the short-circuit path has
747
+ // already finalized must be a no-op, not a crash or double-resolve.
748
+ it("ignores a late agent_end after a short-circuited turn", async () => {
749
+ fake.promptImpl = async () => {
750
+ // No events.
751
+ }
752
+ const result = await agent.prompt({
753
+ sessionId,
754
+ prompt: [{ type: "text", text: "/help" }],
755
+ })
756
+ expect(result.stopReason).toBe("end_turn")
757
+
758
+ // Stray agent_end arrives later (shouldn't happen in production, but
759
+ // the guard in onSessionEvent must keep us safe either way).
760
+ expect(() => fake.emit(agentEnd())).not.toThrow()
761
+ })
762
+
763
+ // Resource safety on the newSession error path: if subscribe (or any step
764
+ // between factory-returns-session and sessions.set) throws, the live session
765
+ // must be disposed — nothing else will ever clean it up.
766
+ it("disposes the session if subscribe throws during newSession", async () => {
767
+ const leaky = new FakeAgentSession("session-leak")
768
+ leaky.subscribe = () => {
769
+ throw new Error("subscribe boom")
770
+ }
771
+ const factory: AcpSessionFactory = async () => asSession(leaky)
772
+ const localAgent = new IkieAcpAgent(makeConn(), {
773
+ extensionFactories: [],
774
+ agentDir: "/tmp/fake-agent-dir",
775
+ sessionFactory: factory,
776
+ })
777
+
778
+ await expect(localAgent.newSession({ cwd: "/tmp", mcpServers: [] })).rejects.toThrow(/subscribe boom/)
779
+ expect(leaky.disposed).toBe(true)
780
+ })
781
+
782
+ it("unregisters the ACP permission prompter if bindExtensions throws during newSession", async () => {
783
+ const leaky = new FakeAgentSession("session-bind-leak")
784
+ leaky.bindExtensionsImpl = async () => {
785
+ throw new Error("bind boom")
786
+ }
787
+ const factory: AcpSessionFactory = async () => asSession(leaky)
788
+ const localAgent = new IkieAcpAgent(makeConn(), {
789
+ extensionFactories: [],
790
+ agentDir: "/tmp/fake-agent-dir",
791
+ sessionFactory: factory,
792
+ })
793
+
794
+ await expect(localAgent.newSession({ cwd: "/tmp", mcpServers: [] })).rejects.toThrow(/bind boom/)
795
+ expect(leaky.disposed).toBe(true)
796
+ expect(getAcpPrompter("session-bind-leak")).toBeUndefined()
797
+ })
798
+
799
+ it("registers an ACP permission prompter that maps allow_once through requestPermission", async () => {
800
+ const requests: RequestPermissionRequest[] = []
801
+ const conn = {
802
+ sessionUpdate: async (_p: SessionNotification) => {},
803
+ requestPermission: async (params: RequestPermissionRequest) => {
804
+ requests.push(params)
805
+ return { outcome: { outcome: "selected", optionId: "choice-0" } }
806
+ },
807
+ } as unknown as AgentSideConnection
808
+ const localFake = new FakeAgentSession("session-permission")
809
+ const localAgent = new IkieAcpAgent(conn, {
810
+ extensionFactories: [],
811
+ agentDir: "/tmp/fake-agent-dir",
812
+ sessionFactory: async () => asSession(localFake),
813
+ })
814
+ await localAgent.newSession({ cwd: "/tmp", mcpServers: [] })
815
+
816
+ const prompter = getAcpPrompter("session-permission")
817
+ expect(prompter).toBeDefined()
818
+ const result = await prompter?.request({
819
+ toolCallId: "tc-permission",
820
+ toolName: "bash",
821
+ input: { command: "touch allowed.txt" },
822
+ choices: [
823
+ { kind: "allow-once", label: "Allow once" },
824
+ { kind: "deny", label: "Deny" },
825
+ ],
826
+ })
827
+
828
+ expect(result).toEqual({ kind: "allow-once" })
829
+ expect(requests).toHaveLength(1)
830
+ expect(requests[0]).toMatchObject({
831
+ sessionId: "session-permission",
832
+ toolCall: {
833
+ toolCallId: "tc-permission",
834
+ title: "touch allowed.txt",
835
+ kind: "execute",
836
+ status: "pending",
837
+ rawInput: { command: "touch allowed.txt" },
838
+ },
839
+ options: [
840
+ { optionId: "choice-0", name: "Allow once", kind: "allow_once" },
841
+ { optionId: "choice-1", name: "Deny", kind: "reject_once" },
842
+ ],
843
+ })
844
+
845
+ await localAgent.shutdown()
846
+ expect(getAcpPrompter("session-permission")).toBeUndefined()
847
+ })
848
+
849
+ it("maps ACP permission cancellation to an aborted prompt result", async () => {
850
+ const requests: RequestPermissionRequest[] = []
851
+ const conn = {
852
+ sessionUpdate: async (_p: SessionNotification) => {},
853
+ requestPermission: async (params: RequestPermissionRequest) => {
854
+ requests.push(params)
855
+ return {
856
+ outcome: { outcome: "cancelled" },
857
+ }
858
+ },
859
+ } as unknown as AgentSideConnection
860
+ const localFake = new FakeAgentSession("session-permission-cancel")
861
+ const localAgent = new IkieAcpAgent(conn, {
862
+ extensionFactories: [],
863
+ agentDir: "/tmp/fake-agent-dir",
864
+ sessionFactory: async () => asSession(localFake),
865
+ })
866
+ await localAgent.newSession({ cwd: "/tmp", mcpServers: [] })
867
+
868
+ const prompter = getAcpPrompter("session-permission-cancel")
869
+ const result = await prompter?.request({
870
+ toolCallId: "tc-cancel",
871
+ toolName: "write",
872
+ input: { path: "/tmp/out.txt", content: "x" },
873
+ choices: [{ kind: "allow-once", label: "Allow once" }],
874
+ })
875
+
876
+ expect(result).toEqual({ kind: "aborted" })
877
+ expect(requests).toHaveLength(1)
878
+
879
+ const abort = new AbortController()
880
+ abort.abort()
881
+ const skippedResult = await prompter?.request({
882
+ toolCallId: "tc-cancel-retry",
883
+ toolName: "write",
884
+ input: { path: "/tmp/out.txt", content: "x" },
885
+ choices: [{ kind: "allow-once", label: "Allow once" }],
886
+ signal: abort.signal,
887
+ })
888
+
889
+ expect(skippedResult).toEqual({ kind: "aborted" })
890
+ expect(requests).toHaveLength(1)
891
+ await localAgent.shutdown()
892
+ })
893
+
894
+ it("closes a live session and unregisters its ACP permission prompter", async () => {
895
+ expect(getAcpPrompter(sessionId)).toBeDefined()
896
+
897
+ await agent.unstable_closeSession({ sessionId })
898
+
899
+ expect(fake.disposed).toBe(true)
900
+ expect(getAcpPrompter(sessionId)).toBeUndefined()
901
+ await expect(
902
+ agent.prompt({
903
+ sessionId,
904
+ prompt: [{ type: "text", text: "hello" }],
905
+ }),
906
+ ).rejects.toMatchObject({ code: -32602 })
907
+ })
908
+
909
+ it("cancels an in-flight turn when closing a session", async () => {
910
+ let releasePrompt!: () => void
911
+ const promptReleased = new Promise<void>((resolve) => {
912
+ releasePrompt = resolve
913
+ })
914
+ fake.promptImpl = async () => {
915
+ fake.emit({ type: "agent_start" })
916
+ await promptReleased
917
+ }
918
+
919
+ const result = agent.prompt({
920
+ sessionId,
921
+ prompt: [{ type: "text", text: "hello" }],
922
+ })
923
+ await delay(0)
924
+ await agent.unstable_closeSession({ sessionId })
925
+ releasePrompt()
926
+
927
+ await expect(result).resolves.toEqual({ stopReason: "cancelled" })
928
+ expect(fake.aborted).toBe(true)
929
+ expect(fake.disposed).toBe(true)
930
+ })
931
+
932
+ it("keeps a same-id reload isolated while close awaits abort", async () => {
933
+ const sid = "session-close-reload"
934
+ const oldFake = new FakeAgentSession(sid)
935
+ const newFake = new FakeAgentSession(sid)
936
+ const { conn, updates } = makeRecordingConn()
937
+ let loaderCalls = 0
938
+ let releaseOldPrompt!: () => void
939
+ const oldPromptReleased = new Promise<void>((resolve) => {
940
+ releaseOldPrompt = resolve
941
+ })
942
+ let releaseNewPrompt!: () => void
943
+ const newPromptReleased = new Promise<void>((resolve) => {
944
+ releaseNewPrompt = resolve
945
+ })
946
+ let markNewPromptStarted!: () => void
947
+ const newPromptStarted = new Promise<void>((resolve) => {
948
+ markNewPromptStarted = resolve
949
+ })
950
+ let newPrompt: Promise<unknown> | undefined
951
+ const localAgent = new IkieAcpAgent(conn, {
952
+ extensionFactories: [],
953
+ agentDir: "/tmp/fake-agent-dir",
954
+ sessionFactory: async () => asSession(oldFake),
955
+ sessionLoader: async () => {
956
+ loaderCalls++
957
+ return asSession(newFake)
958
+ },
959
+ })
960
+
961
+ oldFake.promptImpl = async () => {
962
+ oldFake.emit({ type: "agent_start" })
963
+ await oldPromptReleased
964
+ }
965
+ newFake.promptImpl = async () => {
966
+ newFake.emit({ type: "agent_start" })
967
+ markNewPromptStarted()
968
+ await newPromptReleased
969
+ newFake.emit(agentEnd())
970
+ }
971
+ oldFake.abortImpl = async () => {
972
+ await localAgent.loadSession({
973
+ sessionId: sid,
974
+ cwd: "/tmp",
975
+ mcpServers: [],
976
+ })
977
+ newPrompt = localAgent.prompt({
978
+ sessionId: sid,
979
+ prompt: [{ type: "text", text: "new turn" }],
980
+ })
981
+ await newPromptStarted
982
+ oldFake.emit({
983
+ type: "message_update",
984
+ assistantMessageEvent: { type: "text_delta", delta: "stale old event" },
985
+ } as unknown as AgentSessionEvent)
986
+ releaseNewPrompt()
987
+ }
988
+
989
+ await localAgent.newSession({ cwd: "/tmp", mcpServers: [] })
990
+ const oldPrompt = localAgent.prompt({
991
+ sessionId: sid,
992
+ prompt: [{ type: "text", text: "old turn" }],
993
+ })
994
+ await delay(0)
995
+
996
+ await localAgent.unstable_closeSession({ sessionId: sid })
997
+ releaseOldPrompt()
998
+
999
+ await expect(oldPrompt).resolves.toEqual({ stopReason: "cancelled" })
1000
+ await expect(newPrompt).resolves.toEqual({ stopReason: "end_turn" })
1001
+ expect(loaderCalls).toBe(1)
1002
+ expect(getAcpPrompter(sid)).toBeDefined()
1003
+ expect(
1004
+ updates.some(
1005
+ (u) =>
1006
+ u.update.sessionUpdate === "agent_message_chunk" &&
1007
+ (u.update as { content: { text: string } }).content.text === "stale old event",
1008
+ ),
1009
+ ).toBe(false)
1010
+
1011
+ await localAgent.shutdown()
1012
+ })
1013
+
1014
+ // mcpServers is declared in the ACP request shape but ikie has no hook to
1015
+ // wire them into a live session — pi-coding-agent loads MCP servers from its
1016
+ // own config. Silently dropping them would leave the client believing those
1017
+ // servers are available; reject up-front with invalidParams instead.
1018
+ it("rejects newSession when mcpServers is non-empty", async () => {
1019
+ const factoryCalled = { count: 0 }
1020
+ const factory: AcpSessionFactory = async () => {
1021
+ factoryCalled.count++
1022
+ return asSession(new FakeAgentSession("unused"))
1023
+ }
1024
+ const localAgent = new IkieAcpAgent(makeConn(), {
1025
+ extensionFactories: [],
1026
+ agentDir: "/tmp/fake-agent-dir",
1027
+ sessionFactory: factory,
1028
+ })
1029
+ await expect(
1030
+ localAgent.newSession({
1031
+ cwd: "/tmp",
1032
+ // biome-ignore lint/suspicious/noExplicitAny: only the shape we care about
1033
+ mcpServers: [{ name: "x", command: "x", args: [] } as any],
1034
+ }),
1035
+ ).rejects.toMatchObject({ code: -32602 })
1036
+ expect(factoryCalled.count).toBe(0)
1037
+ })
1038
+
1039
+ // Empty array is fine — equivalent to "no per-session servers requested".
1040
+ it("accepts newSession with empty mcpServers array", async () => {
1041
+ const localFake = new FakeAgentSession("empty-mcp")
1042
+ const factory: AcpSessionFactory = async () => asSession(localFake)
1043
+ const localAgent = new IkieAcpAgent(makeConn(), {
1044
+ extensionFactories: [],
1045
+ agentDir: "/tmp/fake-agent-dir",
1046
+ sessionFactory: factory,
1047
+ })
1048
+ const res = await localAgent.newSession({ cwd: "/tmp", mcpServers: [] })
1049
+ expect(res.sessionId).toBe("empty-mcp")
1050
+ })
1051
+
1052
+ // If the factory itself throws (e.g. bindExtensions failure in the default
1053
+ // factory), newSession must propagate the error — the factory owns disposal
1054
+ // of anything it allocated before throwing.
1055
+ it("propagates errors thrown by the session factory", async () => {
1056
+ const throwing: AcpSessionFactory = async () => {
1057
+ throw new Error("factory refused")
1058
+ }
1059
+ const localAgent = new IkieAcpAgent(makeConn(), {
1060
+ extensionFactories: [],
1061
+ agentDir: "/tmp/fake-agent-dir",
1062
+ sessionFactory: throwing,
1063
+ })
1064
+
1065
+ await expect(localAgent.newSession({ cwd: "/tmp", mcpServers: [] })).rejects.toThrow(/factory refused/)
1066
+ })
1067
+
1068
+ // Two sessions run prompts concurrently; each turn must finalize against
1069
+ // its own agent_end. The slower session must not block the faster one.
1070
+ it("isolates turn state across parallel sessions", async () => {
1071
+ const fakeA = new FakeAgentSession("session-a")
1072
+ const fakeB = new FakeAgentSession("session-b")
1073
+ const fakes = [fakeA, fakeB]
1074
+ let i = 0
1075
+ const rotating: AcpSessionFactory = async () => asSession(fakes[i++] ?? fakes[fakes.length - 1])
1076
+ const parallelAgent = new IkieAcpAgent(makeConn(), {
1077
+ extensionFactories: [],
1078
+ agentDir: "/tmp/fake-agent-dir",
1079
+ sessionFactory: rotating,
1080
+ })
1081
+ const a = await parallelAgent.newSession({ cwd: "/tmp/a", mcpServers: [] })
1082
+ const b = await parallelAgent.newSession({ cwd: "/tmp/b", mcpServers: [] })
1083
+ expect(a.sessionId).not.toBe(b.sessionId)
1084
+
1085
+ fakeA.promptImpl = async () => {
1086
+ fakeA.emit({ type: "agent_start" })
1087
+ await delay(5)
1088
+ setTimeout(() => fakeA.emit(agentEnd()), 60)
1089
+ }
1090
+ fakeB.promptImpl = async () => {
1091
+ fakeB.emit({ type: "agent_start" })
1092
+ await delay(5)
1093
+ setTimeout(() => fakeB.emit(agentEnd()), 10)
1094
+ }
1095
+
1096
+ const [resA, resB] = await Promise.all([
1097
+ parallelAgent.prompt({
1098
+ sessionId: a.sessionId,
1099
+ prompt: [{ type: "text", text: "a" }],
1100
+ }),
1101
+ parallelAgent.prompt({
1102
+ sessionId: b.sessionId,
1103
+ prompt: [{ type: "text", text: "b" }],
1104
+ }),
1105
+ ])
1106
+ expect(resA.stopReason).toBe("end_turn")
1107
+ expect(resB.stopReason).toBe("end_turn")
1108
+ })
1109
+ })
1110
+
1111
+ // ACP ContentChunk contract (src/modes/acp/server.ts onSessionEvent):
1112
+ // "All chunks belonging to the same message share the same messageId.
1113
+ // A change in messageId indicates a new message has started." pi-mono
1114
+ // streams one text_delta / thinking_delta event per chunk, but every delta
1115
+ // within a content block shares its contentIndex — so the server can collapse
1116
+ // them onto a single messageId without coordinating across events. The block
1117
+ // below exercises both branches directly so a regression that drops the field
1118
+ // or breaks its stability surfaces as a test failure rather than a quiet
1119
+ // client-side bug.
1120
+ describe("IkieAcpAgent messageId on streaming chunks", () => {
1121
+ let fake: FakeAgentSession
1122
+ let agent: IkieAcpAgent
1123
+ let sessionId: string
1124
+ let updates: SessionNotification[]
1125
+
1126
+ beforeEach(async () => {
1127
+ fake = new FakeAgentSession("session-msgid")
1128
+ const rec = makeRecordingConn()
1129
+ updates = rec.updates
1130
+ agent = new IkieAcpAgent(rec.conn, {
1131
+ extensionFactories: [],
1132
+ agentDir: "/tmp/fake-agent-dir",
1133
+ sessionFactory: async () => asSession(fake),
1134
+ })
1135
+ const res = await agent.newSession({ cwd: "/tmp", mcpServers: [] })
1136
+ sessionId = res.sessionId
1137
+ })
1138
+
1139
+ function emitTextDeltas(contentIndex: number, deltas: string[]): void {
1140
+ for (const delta of deltas) {
1141
+ fake.emit({
1142
+ type: "message_update",
1143
+ assistantMessageEvent: {
1144
+ type: "text_delta",
1145
+ delta,
1146
+ contentIndex,
1147
+ partial: {} as unknown as AssistantMessage,
1148
+ },
1149
+ message: {} as unknown as AssistantMessage,
1150
+ })
1151
+ }
1152
+ }
1153
+
1154
+ function emitThinkingDeltas(contentIndex: number, deltas: string[]): void {
1155
+ for (const delta of deltas) {
1156
+ fake.emit({
1157
+ type: "message_update",
1158
+ assistantMessageEvent: {
1159
+ type: "thinking_delta",
1160
+ delta,
1161
+ contentIndex,
1162
+ partial: {} as unknown as AssistantMessage,
1163
+ },
1164
+ message: {} as unknown as AssistantMessage,
1165
+ })
1166
+ }
1167
+ }
1168
+
1169
+ function messageIdsFor(update: string): Array<string | null | undefined> {
1170
+ return updates
1171
+ .filter((u) => u.update.sessionUpdate === update)
1172
+ .map((u) => (u.update as { messageId?: string | null }).messageId)
1173
+ }
1174
+
1175
+ it("keeps messageId stable across deltas within a block and flips it when contentIndex advances", async () => {
1176
+ // Two text blocks back-to-back. The first three deltas share index 0
1177
+ // (one messageId); the next three share index 1 (a different one).
1178
+ fake.promptImpl = async () => {
1179
+ fake.emit({ type: "agent_start" })
1180
+ emitTextDeltas(0, ["a", "b", "c"])
1181
+ emitTextDeltas(1, ["d", "e", "f"])
1182
+ fake.emit(agentEnd())
1183
+ }
1184
+ const result = await agent.prompt({
1185
+ sessionId,
1186
+ prompt: [{ type: "text", text: "two blocks" }],
1187
+ })
1188
+ expect(result.stopReason).toBe("end_turn")
1189
+ expect(messageIdsFor("agent_message_chunk")).toEqual([
1190
+ "ikie_msg_0",
1191
+ "ikie_msg_0",
1192
+ "ikie_msg_0",
1193
+ "ikie_msg_1",
1194
+ "ikie_msg_1",
1195
+ "ikie_msg_1",
1196
+ ])
1197
+ })
1198
+
1199
+ it("emits messageId on agent_thought_chunk the same way (same contentIndex → same id)", async () => {
1200
+ // Smoke test for the thought branch: the formula is identical to the
1201
+ // text branch, so a regression that drops the field on either side
1202
+ // surfaces in at least one of the two tests.
1203
+ fake.promptImpl = async () => {
1204
+ fake.emit({ type: "agent_start" })
1205
+ emitThinkingDeltas(0, ["hmm", " ", "ok"])
1206
+ fake.emit(agentEnd())
1207
+ }
1208
+ const result = await agent.prompt({
1209
+ sessionId,
1210
+ prompt: [{ type: "text", text: "think" }],
1211
+ })
1212
+ expect(result.stopReason).toBe("end_turn")
1213
+ expect(messageIdsFor("agent_thought_chunk")).toEqual(["ikie_msg_0", "ikie_msg_0", "ikie_msg_0"])
1214
+ })
1215
+
1216
+ it("advances the counter across turns so two turns both starting at contentIndex=0 get distinct ids", async () => {
1217
+ // Regression guard for the ACP "change in messageId indicates a new
1218
+ // message" contract. pi-mono resets contentIndex to 0 on each new
1219
+ // assistant message; without a session-wide counter, turn 2's first
1220
+ // block would re-use turn 1's first block's messageId and a client
1221
+ // would merge two separate replies into one bubble.
1222
+ fake.promptImpl = async () => {
1223
+ // Turn 1: one text block at index 0.
1224
+ fake.emit({ type: "agent_start" })
1225
+ emitTextDeltas(0, ["hello"])
1226
+ fake.emit(agentEnd())
1227
+ // Turn 2 (chained continue): another text block at index 0 again.
1228
+ // contentIndex resets per assistant message, but the session-wide
1229
+ // counter must keep advancing.
1230
+ fake.emit({ type: "agent_start" })
1231
+ emitTextDeltas(0, ["world"])
1232
+ fake.emit(agentEnd())
1233
+ }
1234
+ const result = await agent.prompt({
1235
+ sessionId,
1236
+ prompt: [{ type: "text", text: "two turns" }],
1237
+ })
1238
+ expect(result.stopReason).toBe("end_turn")
1239
+ expect(messageIdsFor("agent_message_chunk")).toEqual(["ikie_msg_0", "ikie_msg_1"])
1240
+ })
1241
+ })
1242
+
1243
+ // Streaming tools (bash in particular) emit tool_execution_update with a
1244
+ // partialResult payload for every output chunk. The ACP server translates each
1245
+ // of these into a tool_call_update with status="in_progress" and content carrying
1246
+ // the partial output — distinct from the terminal completed/failed update that
1247
+ // accompanies tool_execution_end. The block below covers that branch directly.
1248
+ describe("IkieAcpAgent tool execution stream", () => {
1249
+ let fake: FakeAgentSession
1250
+ let agent: IkieAcpAgent
1251
+ let sessionId: string
1252
+ let updates: SessionNotification[]
1253
+
1254
+ beforeEach(async () => {
1255
+ fake = new FakeAgentSession("session-tool")
1256
+ const sessionFactory: AcpSessionFactory = async () => asSession(fake)
1257
+ const rec = makeRecordingConn()
1258
+ updates = rec.updates
1259
+ agent = new IkieAcpAgent(rec.conn, {
1260
+ extensionFactories: [],
1261
+ agentDir: "/tmp/fake-agent-dir",
1262
+ sessionFactory,
1263
+ })
1264
+ const res = await agent.newSession({ cwd: "/tmp", mcpServers: [] })
1265
+ sessionId = res.sessionId
1266
+ })
1267
+
1268
+ it("forwards partial tool_execution_update events as in_progress tool_call_update notifications with content", async () => {
1269
+ fake.promptImpl = async () => {
1270
+ fake.emit({ type: "agent_start" })
1271
+ fake.emit({
1272
+ type: "tool_execution_start",
1273
+ toolCallId: "tc-1",
1274
+ toolName: "bash",
1275
+ args: { command: "printf a; sleep 0; printf b" },
1276
+ })
1277
+ fake.emit({
1278
+ type: "tool_execution_update",
1279
+ toolCallId: "tc-1",
1280
+ toolName: "bash",
1281
+ args: { command: "printf a; sleep 0; printf b" },
1282
+ partialResult: { content: [{ type: "text", text: "a" }] },
1283
+ })
1284
+ fake.emit({
1285
+ type: "tool_execution_update",
1286
+ toolCallId: "tc-1",
1287
+ toolName: "bash",
1288
+ args: { command: "printf a; sleep 0; printf b" },
1289
+ partialResult: { content: [{ type: "text", text: "ab" }] },
1290
+ })
1291
+ fake.emit({
1292
+ type: "tool_execution_end",
1293
+ toolCallId: "tc-1",
1294
+ toolName: "bash",
1295
+ result: { content: [{ type: "text", text: "ab" }] },
1296
+ isError: false,
1297
+ })
1298
+ fake.emit(agentEnd())
1299
+ }
1300
+
1301
+ const res = await agent.prompt({
1302
+ sessionId,
1303
+ prompt: [{ type: "text", text: "run" }],
1304
+ })
1305
+ expect(res.stopReason).toBe("end_turn")
1306
+
1307
+ const toolCallUpdates = updates.filter((u) => u.update.sessionUpdate === "tool_call_update")
1308
+ const partials = toolCallUpdates.filter((u) => {
1309
+ const up = u.update as { status?: string; content?: unknown[] }
1310
+ return up.status === "in_progress" && Array.isArray(up.content) && up.content.length > 0
1311
+ })
1312
+ expect(partials).toHaveLength(2)
1313
+ // Each partial must carry the agent_session partialResult content verbatim
1314
+ // as ACP tool_call content blocks — proving the partialResult -> content
1315
+ // translation (toolResultContent) ran on the stream path, not only at end.
1316
+ const firstContent = (partials[0].update as { content: Array<{ content: { text: string } }> }).content
1317
+ expect(firstContent[0].content.text).toBe("a")
1318
+ const secondContent = (partials[1].update as { content: Array<{ content: { text: string } }> }).content
1319
+ expect(secondContent[0].content.text).toBe("ab")
1320
+
1321
+ // Terminal completed update still fires after the partials.
1322
+ const terminal = toolCallUpdates.find((u) => (u.update as { status?: string }).status === "completed")
1323
+ expect(terminal).toBeDefined()
1324
+ })
1325
+
1326
+ // web_fetch (and MCP image tools whose blocks survive transformMcpContent)
1327
+ // can return image blocks in a tool result. toolResultContent must forward
1328
+ // them as ACP image content; before this they were dropped and the client
1329
+ // saw a completed tool call with empty content.
1330
+ it("forwards an image block on tool_execution_end as ACP image content", async () => {
1331
+ fake.promptImpl = async () => {
1332
+ fake.emit({ type: "agent_start" })
1333
+ fake.emit({ type: "tool_execution_start", toolCallId: "tc-img", toolName: "web_fetch", args: { url: "x" } })
1334
+ fake.emit({
1335
+ type: "tool_execution_end",
1336
+ toolCallId: "tc-img",
1337
+ toolName: "web_fetch",
1338
+ result: { content: [{ type: "image", data: "aGVsbG8=", mimeType: "image/png" }] },
1339
+ isError: false,
1340
+ })
1341
+ fake.emit(agentEnd())
1342
+ }
1343
+
1344
+ const res = await agent.prompt({ sessionId, prompt: [{ type: "text", text: "run" }] })
1345
+ expect(res.stopReason).toBe("end_turn")
1346
+
1347
+ const completed = updates.find(
1348
+ (u) => u.update.sessionUpdate === "tool_call_update" && (u.update as { status?: string }).status === "completed",
1349
+ )
1350
+ expect(completed).toBeDefined()
1351
+ const content = (completed?.update as { content: unknown[] }).content
1352
+ expect(content).toEqual([{ type: "content", content: { type: "image", data: "aGVsbG8=", mimeType: "image/png" } }])
1353
+ })
1354
+
1355
+ // The image path also runs on the streaming branch: an image-only partial
1356
+ // must produce an in_progress update rather than being swallowed as empty.
1357
+ it("forwards image blocks from a streaming partialResult", async () => {
1358
+ fake.promptImpl = async () => {
1359
+ fake.emit({ type: "agent_start" })
1360
+ fake.emit({ type: "tool_execution_start", toolCallId: "tc-img2", toolName: "web_fetch", args: { url: "x" } })
1361
+ fake.emit({
1362
+ type: "tool_execution_update",
1363
+ toolCallId: "tc-img2",
1364
+ toolName: "web_fetch",
1365
+ args: { url: "x" },
1366
+ partialResult: { content: [{ type: "image", data: "Zm9v", mimeType: "image/jpeg" }] },
1367
+ })
1368
+ fake.emit({
1369
+ type: "tool_execution_end",
1370
+ toolCallId: "tc-img2",
1371
+ toolName: "web_fetch",
1372
+ result: { content: [{ type: "image", data: "Zm9v", mimeType: "image/jpeg" }] },
1373
+ isError: false,
1374
+ })
1375
+ fake.emit(agentEnd())
1376
+ }
1377
+
1378
+ const res = await agent.prompt({ sessionId, prompt: [{ type: "text", text: "run" }] })
1379
+ expect(res.stopReason).toBe("end_turn")
1380
+
1381
+ const partial = updates.find(
1382
+ (u) =>
1383
+ u.update.sessionUpdate === "tool_call_update" && (u.update as { status?: string }).status === "in_progress",
1384
+ )
1385
+ expect(partial).toBeDefined()
1386
+ const content = (partial?.update as { content: unknown[] }).content
1387
+ expect(content).toEqual([{ type: "content", content: { type: "image", data: "Zm9v", mimeType: "image/jpeg" } }])
1388
+ })
1389
+
1390
+ // A result mixing text and image blocks forwards every block, in order.
1391
+ it("forwards text and image blocks together, preserving order", async () => {
1392
+ fake.promptImpl = async () => {
1393
+ fake.emit({ type: "agent_start" })
1394
+ fake.emit({ type: "tool_execution_start", toolCallId: "tc-mix", toolName: "web_fetch", args: { url: "x" } })
1395
+ fake.emit({
1396
+ type: "tool_execution_end",
1397
+ toolCallId: "tc-mix",
1398
+ toolName: "web_fetch",
1399
+ result: {
1400
+ content: [
1401
+ { type: "text", text: "before" },
1402
+ { type: "image", data: "YmFy", mimeType: "image/png" },
1403
+ ],
1404
+ },
1405
+ isError: false,
1406
+ })
1407
+ fake.emit(agentEnd())
1408
+ }
1409
+
1410
+ const res = await agent.prompt({ sessionId, prompt: [{ type: "text", text: "run" }] })
1411
+ expect(res.stopReason).toBe("end_turn")
1412
+
1413
+ const completed = updates.find(
1414
+ (u) => u.update.sessionUpdate === "tool_call_update" && (u.update as { status?: string }).status === "completed",
1415
+ )
1416
+ const content = (completed?.update as { content: unknown[] }).content
1417
+ expect(content).toEqual([
1418
+ { type: "content", content: { type: "text", text: "before" } },
1419
+ { type: "content", content: { type: "image", data: "YmFy", mimeType: "image/png" } },
1420
+ ])
1421
+ })
1422
+
1423
+ // Guard on server.ts:213-214: an empty partialResult must NOT produce a
1424
+ // tool_call_update — an in_progress update with empty content is noise for
1425
+ // clients that render the stream as it arrives.
1426
+ it("skips tool_execution_update events whose partialResult carries no content", async () => {
1427
+ fake.promptImpl = async () => {
1428
+ fake.emit({ type: "agent_start" })
1429
+ fake.emit({
1430
+ type: "tool_execution_start",
1431
+ toolCallId: "tc-2",
1432
+ toolName: "bash",
1433
+ args: { command: "true" },
1434
+ })
1435
+ // Empty partial shapes we can plausibly see: null, undefined, missing content, empty array.
1436
+ fake.emit({
1437
+ type: "tool_execution_update",
1438
+ toolCallId: "tc-2",
1439
+ toolName: "bash",
1440
+ args: { command: "true" },
1441
+ partialResult: null,
1442
+ })
1443
+ fake.emit({
1444
+ type: "tool_execution_update",
1445
+ toolCallId: "tc-2",
1446
+ toolName: "bash",
1447
+ args: { command: "true" },
1448
+ partialResult: { content: [] },
1449
+ })
1450
+ fake.emit({
1451
+ type: "tool_execution_end",
1452
+ toolCallId: "tc-2",
1453
+ toolName: "bash",
1454
+ result: { content: [{ type: "text", text: "" }] },
1455
+ isError: false,
1456
+ })
1457
+ fake.emit(agentEnd())
1458
+ }
1459
+
1460
+ const res = await agent.prompt({
1461
+ sessionId,
1462
+ prompt: [{ type: "text", text: "run" }],
1463
+ })
1464
+ expect(res.stopReason).toBe("end_turn")
1465
+
1466
+ const toolCallUpdates = updates.filter((u) => u.update.sessionUpdate === "tool_call_update")
1467
+ const partials = toolCallUpdates.filter((u) => (u.update as { status?: string }).status === "in_progress")
1468
+ expect(partials).toHaveLength(0)
1469
+ // Terminal completed update still present.
1470
+ const terminal = toolCallUpdates.find((u) => (u.update as { status?: string }).status === "completed")
1471
+ expect(terminal).toBeDefined()
1472
+ })
1473
+
1474
+ it("suppresses ACP tool notifications for system Agent tool calls", async () => {
1475
+ fake.promptImpl = async () => {
1476
+ fake.emit({ type: "agent_start" })
1477
+ fake.emit({
1478
+ type: "tool_execution_start",
1479
+ toolCallId: "tc-system-agent",
1480
+ toolName: "Agent",
1481
+ args: {
1482
+ prompt: "classify",
1483
+ description: "permission classifier",
1484
+ visibility: "system",
1485
+ },
1486
+ })
1487
+ fake.emit({
1488
+ type: "tool_execution_update",
1489
+ toolCallId: "tc-system-agent",
1490
+ toolName: "Agent",
1491
+ args: {
1492
+ prompt: "classify",
1493
+ description: "permission classifier",
1494
+ visibility: "system",
1495
+ },
1496
+ partialResult: {
1497
+ content: [{ type: "text", text: "System agent started." }],
1498
+ },
1499
+ })
1500
+ fake.emit({
1501
+ type: "tool_execution_end",
1502
+ toolCallId: "tc-system-agent",
1503
+ toolName: "Agent",
1504
+ result: { content: [{ type: "text", text: "System agent started." }] },
1505
+ isError: false,
1506
+ })
1507
+ fake.emit(agentEnd())
1508
+ }
1509
+
1510
+ const res = await agent.prompt({
1511
+ sessionId,
1512
+ prompt: [{ type: "text", text: "run" }],
1513
+ })
1514
+ expect(res.stopReason).toBe("end_turn")
1515
+ expect(updates.some((u) => u.update.sessionUpdate === "tool_call")).toBe(false)
1516
+ expect(updates.some((u) => u.update.sessionUpdate === "tool_call_update")).toBe(false)
1517
+ })
1518
+
1519
+ it("suppresses system Agent updates even if an update arrives before the start event", async () => {
1520
+ fake.promptImpl = async () => {
1521
+ fake.emit({ type: "agent_start" })
1522
+ fake.emit({
1523
+ type: "tool_execution_update",
1524
+ toolCallId: "tc-system-agent-update-first",
1525
+ toolName: "Agent",
1526
+ args: {
1527
+ prompt: "classify",
1528
+ description: "permission classifier",
1529
+ visibility: "system",
1530
+ },
1531
+ partialResult: {
1532
+ content: [{ type: "text", text: "System agent started." }],
1533
+ },
1534
+ })
1535
+ fake.emit({
1536
+ type: "tool_execution_end",
1537
+ toolCallId: "tc-system-agent-update-first",
1538
+ toolName: "Agent",
1539
+ result: { content: [{ type: "text", text: "System agent started." }] },
1540
+ isError: false,
1541
+ })
1542
+ fake.emit(agentEnd())
1543
+ }
1544
+
1545
+ const res = await agent.prompt({
1546
+ sessionId,
1547
+ prompt: [{ type: "text", text: "run" }],
1548
+ })
1549
+ expect(res.stopReason).toBe("end_turn")
1550
+ expect(updates.some((u) => u.update.sessionUpdate === "tool_call")).toBe(false)
1551
+ expect(updates.some((u) => u.update.sessionUpdate === "tool_call_update")).toBe(false)
1552
+ })
1553
+ })
1554
+
1555
+ describe("isHiddenToolCall", () => {
1556
+ it("returns false for non-Agent tool names", () => {
1557
+ expect(isHiddenToolCall("bash", {})).toBe(false)
1558
+ expect(isHiddenToolCall("read", { visibility: "system" })).toBe(false)
1559
+ })
1560
+
1561
+ it("returns false when visibility is missing", () => {
1562
+ expect(isHiddenToolCall("Agent", {})).toBe(false)
1563
+ expect(isHiddenToolCall("Agent", { prompt: "hello" })).toBe(false)
1564
+ })
1565
+
1566
+ it("returns false when visibility is not 'system' (any casing)", () => {
1567
+ expect(isHiddenToolCall("Agent", { visibility: "public" })).toBe(false)
1568
+ expect(isHiddenToolCall("Agent", { visibility: "private" })).toBe(false)
1569
+ })
1570
+
1571
+ it("returns true when visibility is 'system' (case-insensitive)", () => {
1572
+ expect(isHiddenToolCall("Agent", { visibility: "system" })).toBe(true)
1573
+ expect(isHiddenToolCall("Agent", { visibility: "System" })).toBe(true)
1574
+ expect(isHiddenToolCall("Agent", { visibility: "SYSTEM" })).toBe(true)
1575
+ })
1576
+
1577
+ it("returns true for Agent with mixed-case 'System' visibility", () => {
1578
+ expect(isHiddenToolCall("Agent", { visibility: "SyStEm" })).toBe(true)
1579
+ })
1580
+ })
1581
+
1582
+ // Coverage for assertSessionHasModel: ACP clients (Zed) should see authRequired
1583
+ // (-32000), not a generic internal error, when the model is unavailable — that
1584
+ // error code routes to the client's auth UI instead of an opaque failure toast.
1585
+ describe("assertSessionHasModel", () => {
1586
+ it("throws RequestError with code -32000 when model is missing", () => {
1587
+ try {
1588
+ assertSessionHasModel({ model: undefined } as Parameters<typeof assertSessionHasModel>[0])
1589
+ throw new Error("expected throw")
1590
+ } catch (err) {
1591
+ expect((err as { code?: number }).code).toBe(-32000)
1592
+ expect((err as Error).message).toMatch(/No model available/)
1593
+ }
1594
+ })
1595
+
1596
+ it("is a no-op when model is present", () => {
1597
+ expect(() =>
1598
+ assertSessionHasModel({
1599
+ model: {} as NonNullable<Parameters<typeof assertSessionHasModel>[0]["model"]>,
1600
+ }),
1601
+ ).not.toThrow()
1602
+ })
1603
+ })
1604
+
1605
+ describe("initializeHeadlessTheme", () => {
1606
+ beforeEach(() => {
1607
+ vi.stubGlobal(THEME_KEY, undefined)
1608
+ vi.stubGlobal(THEME_KEY_OLD, undefined)
1609
+ })
1610
+
1611
+ afterEach(() => {
1612
+ vi.unstubAllGlobals()
1613
+ })
1614
+
1615
+ it("initializes pi's global theme proxy for headless sessions", () => {
1616
+ const globals = globalThis as Record<symbol, unknown>
1617
+
1618
+ expect(globals[THEME_KEY]).toBeUndefined()
1619
+ expect(globals[THEME_KEY_OLD]).toBeUndefined()
1620
+
1621
+ initializeHeadlessTheme({ getTheme: () => "default" })
1622
+
1623
+ expect(globals[THEME_KEY]).toBeDefined()
1624
+ expect(globals[THEME_KEY_OLD]).toBeDefined()
1625
+ const initializedTheme = globals[THEME_KEY] as {
1626
+ getFgAnsi(color: string): string
1627
+ }
1628
+ expect(() => initializedTheme.getFgAnsi("accent")).not.toThrow()
1629
+ })
1630
+ })
1631
+
1632
+ describe("buildSessionModelState", () => {
1633
+ it("returns null when model is missing", () => {
1634
+ const fake = new FakeAgentSession("s1")
1635
+ fake.model = undefined
1636
+ const result = buildSessionModelState(fake as unknown as Parameters<typeof buildSessionModelState>[0])
1637
+ expect(result).toBeNull()
1638
+ })
1639
+
1640
+ it("returns currentModelId and availableModels when model is present", () => {
1641
+ const fake = new FakeAgentSession("s1")
1642
+ fake.model = { provider: "openai", id: "gpt-4" }
1643
+ fake.modelRegistry = {
1644
+ getAvailable: () => [
1645
+ { provider: "openai", id: "gpt-4", name: "GPT-4" },
1646
+ { provider: "anthropic", id: "claude-3", name: "Claude 3" },
1647
+ ],
1648
+ }
1649
+ const result = buildSessionModelState(fake as unknown as Parameters<typeof buildSessionModelState>[0])
1650
+ expect(result).toEqual({
1651
+ currentModelId: "openai/gpt-4",
1652
+ availableModels: [
1653
+ { modelId: "openai/gpt-4", name: "GPT-4" },
1654
+ { modelId: "anthropic/claude-3", name: "Claude 3" },
1655
+ ],
1656
+ })
1657
+ })
1658
+
1659
+ it("returns empty availableModels when registry has no models", () => {
1660
+ const fake = new FakeAgentSession("s1")
1661
+ fake.model = { provider: "openai", id: "gpt-4" }
1662
+ fake.modelRegistry = { getAvailable: () => [] }
1663
+ const result = buildSessionModelState(fake as unknown as Parameters<typeof buildSessionModelState>[0])
1664
+ expect(result).toEqual({
1665
+ currentModelId: "openai/gpt-4",
1666
+ availableModels: [],
1667
+ })
1668
+ })
1669
+ })
1670
+
1671
+ describe("newSession model state", () => {
1672
+ it("returns model state in the response when a model is available", async () => {
1673
+ const fake = new FakeAgentSession("session-model")
1674
+ fake.model = { provider: "openai", id: "gpt-4" }
1675
+ fake.modelRegistry = {
1676
+ getAvailable: () => [
1677
+ { provider: "openai", id: "gpt-4", name: "GPT-4" },
1678
+ { provider: "anthropic", id: "claude-3", name: "Claude 3" },
1679
+ ],
1680
+ }
1681
+ const factory: AcpSessionFactory = async () => asSession(fake)
1682
+ const agent = new IkieAcpAgent(makeConn(), {
1683
+ extensionFactories: [],
1684
+ agentDir: "/tmp/fake-agent-dir",
1685
+ sessionFactory: factory,
1686
+ })
1687
+ const res = await agent.newSession({ cwd: "/tmp", mcpServers: [] })
1688
+ expect(res.sessionId).toBe("session-model")
1689
+ expect(res.models).toBeDefined()
1690
+ expect(res.models?.currentModelId).toBe("openai/gpt-4")
1691
+ expect(res.models?.availableModels).toHaveLength(2)
1692
+ expect(res.models?.availableModels[0]).toEqual({
1693
+ modelId: "openai/gpt-4",
1694
+ name: "GPT-4",
1695
+ })
1696
+ expect(res.models?.availableModels[1]).toEqual({
1697
+ modelId: "anthropic/claude-3",
1698
+ name: "Claude 3",
1699
+ })
1700
+ })
1701
+
1702
+ it("rejects with authRequired when no model is active", async () => {
1703
+ const fake = new FakeAgentSession("session-empty")
1704
+ fake.model = undefined
1705
+ const factory: AcpSessionFactory = async () => asSession(fake)
1706
+ const agent = new IkieAcpAgent(makeConn(), {
1707
+ extensionFactories: [],
1708
+ agentDir: "/tmp/fake-agent-dir",
1709
+ sessionFactory: factory,
1710
+ })
1711
+ await expect(agent.newSession({ cwd: "/tmp", mcpServers: [] })).rejects.toMatchObject({ code: -32000 })
1712
+ expect(fake.disposed).toBe(true)
1713
+ })
1714
+
1715
+ it("returns configOptions in newSession response", async () => {
1716
+ const fake = new FakeAgentSession("test-session-config")
1717
+ const sessionFactory: AcpSessionFactory = async () => asSession(fake)
1718
+ const agent = new IkieAcpAgent(makeConn(), {
1719
+ extensionFactories: [],
1720
+ agentDir: "/tmp/fake-agent-dir",
1721
+ sessionFactory,
1722
+ })
1723
+
1724
+ const res = await agent.newSession({ cwd: "/tmp", mcpServers: [] })
1725
+
1726
+ expect(res.configOptions).toBeDefined()
1727
+ expect(res.configOptions).toHaveLength(1)
1728
+ expect(res.configOptions?.[0].id).toBe("permissions-mode")
1729
+ expect(res.configOptions?.[0].type).toBe("select")
1730
+ expect(res.configOptions?.[0].currentValue).toBeDefined()
1731
+ })
1732
+ })
1733
+
1734
+ describe("newSession available commands", () => {
1735
+ it("sends available_commands_update with /bug command on session init", async () => {
1736
+ const fake = new FakeAgentSession("session-commands")
1737
+ const factory: AcpSessionFactory = async () => asSession(fake)
1738
+ const { conn, updates } = makeRecordingConn()
1739
+ const agent = new IkieAcpAgent(conn, {
1740
+ extensionFactories: [],
1741
+ agentDir: "/tmp/fake-agent-dir",
1742
+ sessionFactory: factory,
1743
+ })
1744
+ await agent.newSession({ cwd: "/tmp", mcpServers: [] })
1745
+
1746
+ // Find the available_commands_update notification
1747
+ const update = updates.find((u) => u.update.sessionUpdate === "available_commands_update")
1748
+ expect(update).toBeDefined()
1749
+ expect(update?.sessionId).toBe("session-commands")
1750
+
1751
+ const updatePayload = update?.update as { availableCommands: Array<Record<string, unknown>> }
1752
+ expect(updatePayload.availableCommands).toHaveLength(1)
1753
+
1754
+ const cmd = updatePayload.availableCommands[0]
1755
+ expect(cmd).toMatchObject({
1756
+ name: "bug",
1757
+ description: expect.any(String),
1758
+ input: { hint: expect.any(String) },
1759
+ })
1760
+ })
1761
+ })
1762
+
1763
+ describe("loadSession available commands", () => {
1764
+ it("sends available_commands_update alongside the transcript replay", async () => {
1765
+ const fake = new FakeAgentSession("session-load-test")
1766
+ fake.branch = [userTextEntry("previous message", "u1", null)]
1767
+ const loader: AcpSessionLoader = async () => asSession(fake)
1768
+ const { conn, updates } = makeRecordingConn()
1769
+ const agent = new IkieAcpAgent(conn, {
1770
+ extensionFactories: [],
1771
+ agentDir: "/tmp/fake-agent-dir",
1772
+ sessionFactory: async () => asSession(new FakeAgentSession("unused")),
1773
+ sessionLoader: loader,
1774
+ })
1775
+
1776
+ await agent.loadSession({ sessionId: "session-load-test", cwd: "/tmp", mcpServers: [] })
1777
+
1778
+ // loadSessionFresh re-broadcasts the command palette on resume.
1779
+ const cmdUpdate = updates.find((u) => u.update.sessionUpdate === "available_commands_update")
1780
+ expect(cmdUpdate).toBeDefined()
1781
+ expect(updates.find((u) => u.update.sessionUpdate === "user_message_chunk")).toBeDefined()
1782
+ })
1783
+ })
1784
+
1785
+ describe("unstable_setSessionModel", () => {
1786
+ it("switches to a valid model", async () => {
1787
+ const fake = new FakeAgentSession("switch-session")
1788
+ fake.model = { provider: "provider-a", id: "model-a" }
1789
+ fake.modelRegistry = {
1790
+ getAvailable: () => [
1791
+ { provider: "provider-a", id: "model-a", name: "Model A" },
1792
+ { provider: "provider-b", id: "model-b", name: "Model B" },
1793
+ ],
1794
+ }
1795
+ const factory: AcpSessionFactory = async () => asSession(fake)
1796
+ const agent = new IkieAcpAgent(makeConn(), {
1797
+ extensionFactories: [],
1798
+ agentDir: "/tmp/fake-agent-dir",
1799
+ sessionFactory: factory,
1800
+ })
1801
+ await agent.newSession({ cwd: "/tmp", mcpServers: [] })
1802
+ const res = await agent.unstable_setSessionModel({
1803
+ sessionId: "switch-session",
1804
+ modelId: "provider-b/model-b",
1805
+ })
1806
+ expect(res).toEqual({})
1807
+ expect(fake.model?.provider).toBe("provider-b")
1808
+ expect(fake.model?.id).toBe("model-b")
1809
+ })
1810
+
1811
+ it("throws invalidParams for unknown modelId", async () => {
1812
+ const fake = new FakeAgentSession("switch-session")
1813
+ fake.model = { provider: "provider-a", id: "model-a" }
1814
+ fake.modelRegistry = {
1815
+ getAvailable: () => [{ provider: "provider-a", id: "model-a", name: "Model A" }],
1816
+ }
1817
+ const factory: AcpSessionFactory = async () => asSession(fake)
1818
+ const agent = new IkieAcpAgent(makeConn(), {
1819
+ extensionFactories: [],
1820
+ agentDir: "/tmp/fake-agent-dir",
1821
+ sessionFactory: factory,
1822
+ })
1823
+ await agent.newSession({ cwd: "/tmp", mcpServers: [] })
1824
+ await expect(
1825
+ agent.unstable_setSessionModel({
1826
+ sessionId: "switch-session",
1827
+ modelId: "unknown",
1828
+ }),
1829
+ ).rejects.toThrow()
1830
+ })
1831
+
1832
+ it("prompt still works after switching model", async () => {
1833
+ const fake = new FakeAgentSession("switch-session")
1834
+ fake.model = { provider: "provider-a", id: "model-a" }
1835
+ fake.modelRegistry = {
1836
+ getAvailable: () => [
1837
+ { provider: "provider-a", id: "model-a", name: "Model A" },
1838
+ { provider: "provider-b", id: "model-b", name: "Model B" },
1839
+ ],
1840
+ }
1841
+ const factory: AcpSessionFactory = async () => asSession(fake)
1842
+ const agent = new IkieAcpAgent(makeConn(), {
1843
+ extensionFactories: [],
1844
+ agentDir: "/tmp/fake-agent-dir",
1845
+ sessionFactory: factory,
1846
+ })
1847
+ await agent.newSession({ cwd: "/tmp", mcpServers: [] })
1848
+ await agent.unstable_setSessionModel({
1849
+ sessionId: "switch-session",
1850
+ modelId: "provider-b/model-b",
1851
+ })
1852
+ const result = await agent.prompt({
1853
+ sessionId: "switch-session",
1854
+ prompt: [{ type: "text", text: "hello" }],
1855
+ })
1856
+ expect(result).toBeDefined()
1857
+ expect(fake.model?.provider).toBe("provider-b")
1858
+ expect(fake.model?.id).toBe("model-b")
1859
+ })
1860
+
1861
+ it("throws invalidParams for unknown sessionId", async () => {
1862
+ const agent = new IkieAcpAgent(makeConn(), {
1863
+ extensionFactories: [],
1864
+ agentDir: "/tmp/fake-agent-dir",
1865
+ })
1866
+ await expect(
1867
+ agent.unstable_setSessionModel({
1868
+ sessionId: "no-such-session",
1869
+ modelId: "model-a",
1870
+ }),
1871
+ ).rejects.toThrow()
1872
+ })
1873
+ })
1874
+
1875
+ describe("setSessionConfigOption", () => {
1876
+ it("sets permission mode via setSessionConfigOption and returns configOptions", async () => {
1877
+ const fake = new FakeAgentSession("test-session")
1878
+ const sessionFactory: AcpSessionFactory = async () => asSession(fake)
1879
+ const agent = new IkieAcpAgent(makeConn(), {
1880
+ extensionFactories: [],
1881
+ agentDir: "/tmp/fake-agent-dir",
1882
+ sessionFactory,
1883
+ })
1884
+
1885
+ const { sessionId } = await agent.newSession({
1886
+ cwd: "/tmp",
1887
+ mcpServers: [],
1888
+ })
1889
+
1890
+ const res = await agent.setSessionConfigOption({
1891
+ sessionId,
1892
+ configId: "permissions-mode",
1893
+ value: "plan",
1894
+ })
1895
+
1896
+ expect(res.configOptions).toHaveLength(1)
1897
+ expect(res.configOptions[0].id).toBe("permissions-mode")
1898
+ expect(res.configOptions[0].currentValue).toBe("plan")
1899
+ })
1900
+
1901
+ it("sets all valid permission modes", async () => {
1902
+ const fake = new FakeAgentSession("test-session-modes")
1903
+ const sessionFactory: AcpSessionFactory = async () => asSession(fake)
1904
+ const agent = new IkieAcpAgent(makeConn(), {
1905
+ extensionFactories: [],
1906
+ agentDir: "/tmp/fake-agent-dir",
1907
+ sessionFactory,
1908
+ })
1909
+
1910
+ await agent.newSession({ cwd: "/tmp", mcpServers: [] })
1911
+
1912
+ for (const mode of ALL_PERMISSION_MODES) {
1913
+ const res = await agent.setSessionConfigOption({
1914
+ sessionId: "test-session-modes",
1915
+ configId: "permissions-mode",
1916
+ value: mode,
1917
+ })
1918
+ expect(res.configOptions).toHaveLength(1)
1919
+ expect(res.configOptions[0].currentValue).toBe(mode)
1920
+ }
1921
+ })
1922
+
1923
+ it("rejects invalid permission mode value", async () => {
1924
+ const fake = new FakeAgentSession("test-session-invalid")
1925
+ const sessionFactory: AcpSessionFactory = async () => asSession(fake)
1926
+ const agent = new IkieAcpAgent(makeConn(), {
1927
+ extensionFactories: [],
1928
+ agentDir: "/tmp/fake-agent-dir",
1929
+ sessionFactory,
1930
+ })
1931
+
1932
+ await agent.newSession({ cwd: "/tmp", mcpServers: [] })
1933
+
1934
+ await expect(
1935
+ agent.setSessionConfigOption({
1936
+ sessionId: "test-session-invalid",
1937
+ configId: "permissions-mode",
1938
+ value: "invalid-mode",
1939
+ }),
1940
+ ).rejects.toMatchObject({ code: -32602 })
1941
+ })
1942
+
1943
+ it("rejects unknown configId", async () => {
1944
+ const fake = new FakeAgentSession("test-session-unknown-config")
1945
+ const sessionFactory: AcpSessionFactory = async () => asSession(fake)
1946
+ const agent = new IkieAcpAgent(makeConn(), {
1947
+ extensionFactories: [],
1948
+ agentDir: "/tmp/fake-agent-dir",
1949
+ sessionFactory,
1950
+ })
1951
+
1952
+ await agent.newSession({ cwd: "/tmp", mcpServers: [] })
1953
+
1954
+ await expect(
1955
+ agent.setSessionConfigOption({
1956
+ sessionId: "test-session-unknown-config",
1957
+ configId: "unknown-config",
1958
+ value: "plan",
1959
+ }),
1960
+ ).rejects.toMatchObject({ code: -32602 })
1961
+ })
1962
+
1963
+ it("rejects unknown sessionId", async () => {
1964
+ const agent = new IkieAcpAgent(makeConn(), {
1965
+ extensionFactories: [],
1966
+ agentDir: "/tmp/fake-agent-dir",
1967
+ })
1968
+
1969
+ await expect(
1970
+ agent.setSessionConfigOption({
1971
+ sessionId: "no-such-session",
1972
+ configId: "permissions-mode",
1973
+ value: "plan",
1974
+ }),
1975
+ ).rejects.toMatchObject({ code: -32602 })
1976
+ })
1977
+
1978
+ it("returns configOptions with correct structure", async () => {
1979
+ const fake = new FakeAgentSession("test-session-structure")
1980
+ const sessionFactory: AcpSessionFactory = async () => asSession(fake)
1981
+ const agent = new IkieAcpAgent(makeConn(), {
1982
+ extensionFactories: [],
1983
+ agentDir: "/tmp/fake-agent-dir",
1984
+ sessionFactory,
1985
+ })
1986
+
1987
+ await agent.newSession({ cwd: "/tmp", mcpServers: [] })
1988
+
1989
+ const res = await agent.setSessionConfigOption({
1990
+ sessionId: "test-session-structure",
1991
+ configId: "permissions-mode",
1992
+ value: "auto",
1993
+ })
1994
+
1995
+ expect(res.configOptions[0]).toMatchObject({
1996
+ id: "permissions-mode",
1997
+ name: "Permissions Mode",
1998
+ type: "select",
1999
+ category: "mode",
2000
+ currentValue: "auto",
2001
+ })
2002
+ // Verify options array is present with all valid modes
2003
+ // biome-ignore lint/suspicious/noExplicitAny: union type requires assertion
2004
+ const selectOption = res.configOptions[0] as any
2005
+ expect(selectOption.options).toHaveLength(4)
2006
+ expect(selectOption.options.map((o: { value: string }) => o.value)).toEqual(ALL_PERMISSION_MODES)
2007
+ })
2008
+
2009
+ it("emits config_option_update when permission mode changes", async () => {
2010
+ const { conn, updates } = makeRecordingConn()
2011
+ const fake = new FakeAgentSession("test-session-notify")
2012
+ const sessionFactory: AcpSessionFactory = async () => asSession(fake)
2013
+ const agent = new IkieAcpAgent(conn, {
2014
+ extensionFactories: [],
2015
+ agentDir: "/tmp/fake-agent-dir",
2016
+ sessionFactory,
2017
+ })
2018
+
2019
+ // Create a session (this subscribes to mode changes)
2020
+ const { sessionId } = await agent.newSession({
2021
+ cwd: "/tmp",
2022
+ mcpServers: [],
2023
+ })
2024
+
2025
+ // Change the mode using setSessionConfigOption (this emits the notification)
2026
+ await agent.setSessionConfigOption({
2027
+ sessionId,
2028
+ configId: "permissions-mode",
2029
+ value: "plan",
2030
+ })
2031
+
2032
+ // Check that config_option_update was emitted
2033
+ const configUpdates = updates.filter((u) => u.update.sessionUpdate === "config_option_update")
2034
+ expect(configUpdates).toHaveLength(1)
2035
+ expect(configUpdates[0].sessionId).toBe(sessionId)
2036
+ // Type assertion needed because SessionUpdate is a union type
2037
+ const configUpdate = configUpdates[0].update as {
2038
+ sessionUpdate: "config_option_update"
2039
+ configOptions: Array<{ id: string; currentValue: string }>
2040
+ }
2041
+ expect(configUpdate.configOptions[0].id).toBe("permissions-mode")
2042
+ expect(configUpdate.configOptions[0].currentValue).toBe("plan")
2043
+ })
2044
+
2045
+ it("session-scoped mode is used by permissions extension for tool gating", async () => {
2046
+ const fake = new FakeAgentSession("test-session-enforcement")
2047
+ const sessionFactory: AcpSessionFactory = async () => asSession(fake)
2048
+ const agent = new IkieAcpAgent(makeConn(), {
2049
+ extensionFactories: [],
2050
+ agentDir: "/tmp/fake-agent-dir",
2051
+ sessionFactory,
2052
+ })
2053
+
2054
+ // Create a session
2055
+ const { sessionId } = await agent.newSession({
2056
+ cwd: "/tmp",
2057
+ mcpServers: [],
2058
+ })
2059
+
2060
+ // Verify initial mode is default
2061
+ const initialRes = await agent.setSessionConfigOption({
2062
+ sessionId,
2063
+ configId: "permissions-mode",
2064
+ value: "default",
2065
+ })
2066
+ expect(initialRes.configOptions[0].currentValue).toBe("default")
2067
+
2068
+ // Switch to plan mode via ACP
2069
+ await agent.setSessionConfigOption({
2070
+ sessionId,
2071
+ configId: "permissions-mode",
2072
+ value: "plan",
2073
+ })
2074
+
2075
+ // Verify the mode was updated
2076
+ const controller = getSessionPermissionFlagController(sessionId)
2077
+ expect(controller).toBeDefined()
2078
+ expect(controller?.getMode()).toEqual({ mode: "plan", source: "user" })
2079
+
2080
+ // Verify mode can be switched back
2081
+ await agent.setSessionConfigOption({
2082
+ sessionId,
2083
+ configId: "permissions-mode",
2084
+ value: "yolo",
2085
+ })
2086
+ expect(controller?.getMode()).toEqual({ mode: "yolo", source: "user" })
2087
+
2088
+ // Cleanup
2089
+ await agent.unstable_closeSession({ sessionId })
2090
+ const afterClose = getSessionPermissionFlagController(sessionId)
2091
+ expect(afterClose).toBeUndefined()
2092
+ })
2093
+
2094
+ it("mode changes via setSessionConfigOption are visible to permissions extension currentMode", async () => {
2095
+ const fake = new FakeAgentSession("test-session-permissions-integration")
2096
+ // Ensure clean env state - previous tests may have set this
2097
+ vi.stubEnv(PERMISSIONS_ENV_KEY, "")
2098
+ Reflect.deleteProperty(process.env, PERMISSIONS_ENV_KEY)
2099
+
2100
+ const sessionFactory: AcpSessionFactory = async () => asSession(fake)
2101
+ const agent = new IkieAcpAgent(makeConn(), {
2102
+ extensionFactories: [],
2103
+ agentDir: "/tmp/fake-agent-dir",
2104
+ sessionFactory,
2105
+ })
2106
+
2107
+ // Create a session
2108
+ const { sessionId } = await agent.newSession({
2109
+ cwd: "/tmp",
2110
+ mcpServers: [],
2111
+ })
2112
+
2113
+ // Verify the session controller is registered
2114
+ const controller = getSessionPermissionFlagController(sessionId)
2115
+ expect(controller).toBeDefined()
2116
+ expect(controller?.getMode()).toEqual({ mode: "default", source: "user" })
2117
+
2118
+ // Change to plan mode via ACP
2119
+ await agent.setSessionConfigOption({
2120
+ sessionId,
2121
+ configId: "permissions-mode",
2122
+ value: "plan",
2123
+ })
2124
+
2125
+ // Verify the controller reflects the new mode
2126
+
2127
+ expect(controller?.getMode()).toEqual({ mode: "plan", source: "user" })
2128
+
2129
+ await agent.unstable_closeSession({ sessionId })
2130
+ })
2131
+
2132
+ it("delivers config_option_update to multiple concurrent sessions independently", async () => {
2133
+ const updates1: SessionNotification[] = []
2134
+ const updates2: SessionNotification[] = []
2135
+
2136
+ // Create a connection that splits notifications by sessionId
2137
+ const conn = {
2138
+ sessionUpdate: async (msg: SessionNotification) => {
2139
+ if (msg.sessionId === "multi-session-1") {
2140
+ updates1.push(msg)
2141
+ } else if (msg.sessionId === "multi-session-2") {
2142
+ updates2.push(msg)
2143
+ }
2144
+ },
2145
+ } as unknown as AgentSideConnection
2146
+
2147
+ let callCount = 0
2148
+ const fake1 = new FakeAgentSession("multi-session-1")
2149
+ const fake2 = new FakeAgentSession("multi-session-2")
2150
+
2151
+ // One agent with a session factory that returns different sessions
2152
+ const agent = new IkieAcpAgent(conn, {
2153
+ extensionFactories: [],
2154
+ agentDir: "/tmp/fake-agent-dir",
2155
+ sessionFactory: async () => {
2156
+ callCount++
2157
+ return asSession(callCount === 1 ? fake1 : fake2)
2158
+ },
2159
+ })
2160
+
2161
+ const { sessionId: sid1 } = await agent.newSession({
2162
+ cwd: "/tmp",
2163
+ mcpServers: [],
2164
+ })
2165
+ const { sessionId: sid2 } = await agent.newSession({
2166
+ cwd: "/tmp",
2167
+ mcpServers: [],
2168
+ })
2169
+
2170
+ // Verify sessions are under the same agent (same entries map)
2171
+ expect(sid1).toBe("multi-session-1")
2172
+ expect(sid2).toBe("multi-session-2")
2173
+
2174
+ const filter = (u: SessionNotification) => u.update.sessionUpdate === "config_option_update"
2175
+
2176
+ // Change mode via session 1 — only session 1 is notified
2177
+ await agent.setSessionConfigOption({
2178
+ sessionId: sid1,
2179
+ configId: "permissions-mode",
2180
+ value: "yolo",
2181
+ })
2182
+
2183
+ // Session 1 should have exactly 1 notification (its own)
2184
+ expect(updates1.filter(filter)).toHaveLength(1)
2185
+ // Session 2 should have no notification yet
2186
+ expect(updates2.filter(filter)).toHaveLength(0)
2187
+
2188
+ // Change mode via session 2 — only session 2 is notified
2189
+ await agent.setSessionConfigOption({
2190
+ sessionId: sid2,
2191
+ configId: "permissions-mode",
2192
+ value: "auto",
2193
+ })
2194
+
2195
+ // Session 1 should still have only 1 notification
2196
+ expect(updates1.filter(filter)).toHaveLength(1)
2197
+ // Session 2 should now have exactly 1 notification
2198
+ expect(updates2.filter(filter)).toHaveLength(1)
2199
+ })
2200
+ })
2201
+
2202
+ describe("ACP mode controller integration with permissions extension", () => {
2203
+ // Import permissions extension test utilities
2204
+ async function createPermissionsHarness(tools: string[], flags: Record<string, unknown> = {}) {
2205
+ const { default: permissionsExtension } = await import("../../extensions/permissions/index.js")
2206
+ const handlers = new Map<string, Array<(...args: unknown[]) => unknown>>()
2207
+ const commands = new Map<
2208
+ string,
2209
+ {
2210
+ description: string
2211
+ handler: (args: string, ctx: unknown) => Promise<void> | void
2212
+ }
2213
+ >()
2214
+ let activeTools: string[] = []
2215
+
2216
+ const pi = {
2217
+ on: (event: string, handler: (...args: unknown[]) => unknown) => {
2218
+ const list = handlers.get(event) ?? []
2219
+ list.push(handler)
2220
+ handlers.set(event, list)
2221
+ },
2222
+ registerCommand: (
2223
+ name: string,
2224
+ command: {
2225
+ description: string
2226
+ handler: (args: string, ctx: unknown) => Promise<void> | void
2227
+ },
2228
+ ) => {
2229
+ commands.set(name, command)
2230
+ },
2231
+ getAllTools: () => tools,
2232
+ getActiveTools: () => activeTools,
2233
+ setActiveTools: (names: string[]) => {
2234
+ activeTools = names.filter((n) => tools.includes(n))
2235
+ },
2236
+ getFlag: (name: string) => flags[name],
2237
+ registerFlag: () => {},
2238
+ sendMessage: () => {},
2239
+ getEnvironment: () => ({
2240
+ environmentInfo: {
2241
+ permittedTools: new Set(tools),
2242
+ },
2243
+ }),
2244
+ setActiveToolIdsByServer: () => {},
2245
+ } as unknown as import("@earendil-works/pi-coding-agent").ExtensionAPI
2246
+
2247
+ permissionsExtension(pi)
2248
+
2249
+ return {
2250
+ async fireSessionStart(ctx: unknown) {
2251
+ for (const handler of handlers.get("session_start") ?? []) {
2252
+ await handler({}, ctx)
2253
+ }
2254
+ },
2255
+ async fireToolCall(event: { toolName: string; input: unknown }, ctx: unknown) {
2256
+ const toolHandlers = handlers.get("tool_call") ?? []
2257
+ for (const handler of toolHandlers) {
2258
+ const result = await handler(event, ctx)
2259
+ if (result) return result
2260
+ }
2261
+ return undefined
2262
+ },
2263
+ commands,
2264
+ }
2265
+ }
2266
+
2267
+ function createMockContext(sessionId: string, cwd: string): ExtensionContext {
2268
+ return {
2269
+ sessionManager: { getSessionId: vi.fn().mockReturnValue(sessionId) } as unknown as SessionManager,
2270
+ cwd,
2271
+ mode: "rpc",
2272
+ hasUI: true,
2273
+ ui: {
2274
+ notify: vi.fn(),
2275
+ setStatus: vi.fn(),
2276
+ onTerminalInput: vi.fn(),
2277
+ theme: { fg: vi.fn(), bg: vi.fn(), getFgAnsi: vi.fn() } as unknown as Theme,
2278
+ } as unknown as ExtensionUIContext,
2279
+ modelRegistry: {
2280
+ authStorage: {} as AuthStorage,
2281
+ getApiKeyAndHeaders: vi.fn().mockReturnValue({ ok: true, apiKey: "test" }),
2282
+ getAvailable: vi.fn().mockReturnValue([
2283
+ {
2284
+ id: "kimi",
2285
+ name: "kimi",
2286
+ },
2287
+ ]),
2288
+ find: vi.fn().mockReturnValue({ id: "kimi", name: "kimi" }),
2289
+ } as unknown as ModelRegistry,
2290
+ } as unknown as ExtensionContext
2291
+ }
2292
+
2293
+ afterEach(() => {
2294
+ vi.unstubAllEnvs()
2295
+ })
2296
+
2297
+ it("plan mode via ACP blocks write operations through permissions extension", async () => {
2298
+ // Clean env state
2299
+ vi.stubEnv(PERMISSIONS_ENV_KEY, "")
2300
+ Reflect.deleteProperty(process.env, PERMISSIONS_ENV_KEY)
2301
+
2302
+ const sessionId = "test-plan-mode-session"
2303
+ const cwd = "/tmp"
2304
+
2305
+ // Set up permissions extension with write tool
2306
+ const harness = await createPermissionsHarness(["write", "read"])
2307
+
2308
+ // Create an ACP session (registers the controller)
2309
+ const fake = new FakeAgentSession(sessionId)
2310
+ const agent = new IkieAcpAgent(makeConn(), {
2311
+ extensionFactories: [],
2312
+ agentDir: "/tmp/fake-agent-dir",
2313
+ sessionFactory: async () => asSession(fake),
2314
+ })
2315
+
2316
+ await agent.newSession({ cwd, mcpServers: [] })
2317
+
2318
+ // Fire session_start so the permissions extension subscribes to the controller
2319
+ const mockCtx = createMockContext(sessionId, cwd)
2320
+ await harness.fireSessionStart(mockCtx)
2321
+
2322
+ // Verify controller is registered
2323
+ const controller = getSessionPermissionFlagController(sessionId)
2324
+ expect(controller).toBeDefined()
2325
+
2326
+ // Switch to plan mode via ACP
2327
+ await agent.setSessionConfigOption({
2328
+ sessionId,
2329
+ configId: "permissions-mode",
2330
+ value: "plan",
2331
+ })
2332
+
2333
+ // Verify controller mode is plan
2334
+ expect(controller?.getMode()).toEqual({ mode: "plan", source: "user" })
2335
+ const writeToolEvent = {
2336
+ toolName: "write",
2337
+ input: { path: "/tmp/test.txt", content: "hello" },
2338
+ }
2339
+
2340
+ const result = (await harness.fireToolCall(writeToolEvent, mockCtx)) as
2341
+ | { block: boolean; reason: string }
2342
+ | undefined
2343
+
2344
+ // Should be blocked in plan mode
2345
+ expect(result).toBeDefined()
2346
+ expect(result?.block).toBe(true)
2347
+ expect(result?.reason).toContain("Plan")
2348
+
2349
+ // Cleanup
2350
+ await agent.unstable_closeSession({ sessionId })
2351
+ })
2352
+
2353
+ it("yolo mode via ACP allows write operations through permissions extension", async () => {
2354
+ // Clean env state
2355
+ vi.stubEnv(PERMISSIONS_ENV_KEY, "")
2356
+ Reflect.deleteProperty(process.env, PERMISSIONS_ENV_KEY)
2357
+
2358
+ const sessionId = "test-yolo-mode-session"
2359
+ const cwd = "/tmp"
2360
+
2361
+ // Set up permissions extension
2362
+ const harness = await createPermissionsHarness(["write", "read", "bash"])
2363
+
2364
+ // Create an ACP session
2365
+ const fake = new FakeAgentSession(sessionId)
2366
+ const agent = new IkieAcpAgent(makeConn(), {
2367
+ extensionFactories: [],
2368
+ agentDir: "/tmp/fake-agent-dir",
2369
+ sessionFactory: async () => asSession(fake),
2370
+ })
2371
+
2372
+ await agent.newSession({ cwd, mcpServers: [] })
2373
+
2374
+ // Fire session_start so the permissions extension subscribes to the controller
2375
+ const mockCtx = createMockContext(sessionId, cwd)
2376
+ await harness.fireSessionStart(mockCtx)
2377
+
2378
+ // Switch to yolo mode via ACP
2379
+ await agent.setSessionConfigOption({
2380
+ sessionId,
2381
+ configId: "permissions-mode",
2382
+ value: "yolo",
2383
+ })
2384
+
2385
+ // Verify controller mode is yolo
2386
+ const controller = getSessionPermissionFlagController(sessionId)
2387
+ expect(controller?.getMode()).toEqual({ mode: "yolo", source: "user" })
2388
+ const writeToolEvent = {
2389
+ toolName: "write",
2390
+ input: { path: "/tmp/test.txt", content: "hello" },
2391
+ }
2392
+
2393
+ const result = await harness.fireToolCall(writeToolEvent, mockCtx)
2394
+
2395
+ // Should NOT be blocked in yolo mode
2396
+ expect(result).toBeUndefined()
2397
+
2398
+ // Cleanup
2399
+ await agent.unstable_closeSession({ sessionId })
2400
+ })
2401
+
2402
+ it("setSessionConfigOption emits exactly one config_option_update when permissions extension is active", async () => {
2403
+ // Regression test for the double-notification bug:
2404
+ // setSessionConfigOption -> controller.setMode fires the ACP notification subscriber.
2405
+ // The permissions extension's session_start subscriber also fires changeMode ->
2406
+ // setRuntimePermissionMode, which must NOT re-enter controller.setMode (which would
2407
+ // fire a second notification). The insideControllerCallback guard prevents this.
2408
+ vi.stubEnv(PERMISSIONS_ENV_KEY, "")
2409
+ Reflect.deleteProperty(process.env, PERMISSIONS_ENV_KEY)
2410
+
2411
+ const sessionId = "test-no-double-notify"
2412
+ const cwd = "/tmp"
2413
+
2414
+ const harness = await createPermissionsHarness(["write", "read"])
2415
+
2416
+ const { conn, updates } = makeRecordingConn()
2417
+ const fake = new FakeAgentSession(sessionId)
2418
+ const agent = new IkieAcpAgent(conn, {
2419
+ extensionFactories: [],
2420
+ agentDir: "/tmp/fake-agent-dir",
2421
+ sessionFactory: async () => asSession(fake),
2422
+ })
2423
+
2424
+ await agent.newSession({ cwd, mcpServers: [] })
2425
+
2426
+ // Fire session_start so the permissions extension subscribes to the controller.
2427
+ const mockCtx = createMockContext(sessionId, cwd)
2428
+ await harness.fireSessionStart(mockCtx)
2429
+
2430
+ // Drain any notifications emitted during session setup.
2431
+ updates.length = 0
2432
+
2433
+ // Change mode — this is the operation that previously emitted two notifications.
2434
+ await agent.setSessionConfigOption({
2435
+ sessionId,
2436
+ configId: "permissions-mode",
2437
+ value: "plan",
2438
+ })
2439
+
2440
+ const configUpdates = updates.filter((u) => u.update.sessionUpdate === "config_option_update")
2441
+ expect(configUpdates).toHaveLength(1)
2442
+ // biome-ignore lint/suspicious/noExplicitAny: union type requires assertion
2443
+ const update = configUpdates[0].update as any
2444
+ expect(update.configOptions[0].currentValue).toBe("plan")
2445
+
2446
+ await agent.unstable_closeSession({ sessionId })
2447
+ })
2448
+
2449
+ it("leaving plan mode via ACP restores write/edit tools and emits exactly one config update", async () => {
2450
+ // Changing permissions-mode through ACP must run the full changeMode transition,
2451
+ // including restoring tool visibility and aborting stale permission prompts.
2452
+ // The skipNotify flag should prevent duplicate ACP config updates.
2453
+ vi.stubEnv(PERMISSIONS_ENV_KEY, "")
2454
+ Reflect.deleteProperty(process.env, PERMISSIONS_ENV_KEY)
2455
+
2456
+ const sessionId = "test-leave-plan-mode"
2457
+ const cwd = "/tmp"
2458
+
2459
+ // Set up harness with write and edit tools that would be hidden in plan mode
2460
+ const harness = await createPermissionsHarness(["write", "edit", "read", "bash"])
2461
+
2462
+ const { conn, updates } = makeRecordingConn()
2463
+ const fake = new FakeAgentSession(sessionId)
2464
+ const agent = new IkieAcpAgent(conn, {
2465
+ extensionFactories: [],
2466
+ agentDir: "/tmp/fake-agent-dir",
2467
+ sessionFactory: async () => asSession(fake),
2468
+ })
2469
+
2470
+ await agent.newSession({ cwd, mcpServers: [] })
2471
+
2472
+ // Fire session_start so the permissions extension subscribes to the controller
2473
+ const mockCtx = createMockContext(sessionId, cwd)
2474
+ await harness.fireSessionStart(mockCtx)
2475
+
2476
+ // Clear any notifications from setup
2477
+ updates.length = 0
2478
+
2479
+ // Start in plan mode via ACP
2480
+ await agent.setSessionConfigOption({
2481
+ sessionId,
2482
+ configId: "permissions-mode",
2483
+ value: "plan",
2484
+ })
2485
+
2486
+ // Verify we're in plan mode - write/edit should be blocked by permissions extension
2487
+ const writeBlockedResult = (await harness.fireToolCall(
2488
+ { toolName: "write", input: { path: "/tmp/test.txt", content: "hello" } },
2489
+ mockCtx,
2490
+ )) as { block: boolean; reason: string }
2491
+ expect(writeBlockedResult?.block).toBe(true)
2492
+ expect(writeBlockedResult?.reason).toContain("Plan mode")
2493
+
2494
+ // Clear notifications from entering plan mode
2495
+ updates.length = 0
2496
+
2497
+ // Test leaving plan mode to yolo
2498
+ await agent.setSessionConfigOption({
2499
+ sessionId,
2500
+ configId: "permissions-mode",
2501
+ value: "yolo",
2502
+ })
2503
+
2504
+ // Verify exactly one config_option_update was emitted
2505
+ const yoloConfigUpdates = updates.filter((u) => u.update.sessionUpdate === "config_option_update")
2506
+ expect(yoloConfigUpdates).toHaveLength(1)
2507
+ // biome-ignore lint/suspicious/noExplicitAny: union type requires assertion
2508
+ const yoloUpdate = yoloConfigUpdates[0].update as any
2509
+ expect(yoloUpdate.configOptions[0].currentValue).toBe("yolo")
2510
+
2511
+ // Verify write operations are now allowed (permissions extension allows them in yolo)
2512
+ const writeAllowedResult = await harness.fireToolCall(
2513
+ { toolName: "write", input: { path: "/tmp/test.txt", content: "hello" } },
2514
+ mockCtx,
2515
+ )
2516
+ expect(writeAllowedResult).toBeUndefined() // Not blocked
2517
+
2518
+ // Reset and test leaving plan mode to default
2519
+ updates.length = 0
2520
+
2521
+ // Go back to plan mode
2522
+ await agent.setSessionConfigOption({
2523
+ sessionId,
2524
+ configId: "permissions-mode",
2525
+ value: "plan",
2526
+ })
2527
+ updates.length = 0 // Clear notifications
2528
+
2529
+ // Verify tools are blocked again in plan mode
2530
+ const writeBlockedAgain = (await harness.fireToolCall(
2531
+ { toolName: "write", input: { path: "/tmp/test.txt", content: "hello" } },
2532
+ mockCtx,
2533
+ )) as { block: boolean; reason: string }
2534
+ expect(writeBlockedAgain?.block).toBe(true)
2535
+
2536
+ // Leave plan mode to default
2537
+ await agent.setSessionConfigOption({
2538
+ sessionId,
2539
+ configId: "permissions-mode",
2540
+ value: "default",
2541
+ })
2542
+
2543
+ // Verify exactly one config_option_update was emitted
2544
+ const defaultConfigUpdates = updates.filter((u) => u.update.sessionUpdate === "config_option_update")
2545
+ expect(defaultConfigUpdates).toHaveLength(1)
2546
+ // biome-ignore lint/suspicious/noExplicitAny: union type requires assertion
2547
+ const defaultUpdate = defaultConfigUpdates[0].update as any
2548
+ expect(defaultUpdate.configOptions[0].currentValue).toBe("default")
2549
+
2550
+ // Verify write operations are now gated behind explicit user approval
2551
+ const writeDefaultResult = (await harness.fireToolCall(
2552
+ { toolName: "write", input: { path: "/tmp/test.txt", content: "hello" } },
2553
+ mockCtx,
2554
+ )) as { block: boolean; reason: string }
2555
+ expect(writeDefaultResult.block).toBe(true)
2556
+ expect(writeDefaultResult.reason).toContain("Declined by user")
2557
+
2558
+ await agent.unstable_closeSession({ sessionId })
2559
+ })
2560
+ })
2561
+
2562
+ describe("session mode controller lifecycle", () => {
2563
+ afterEach(() => {
2564
+ vi.unstubAllEnvs()
2565
+ })
2566
+
2567
+ it("unregisters mode controller on closeSession", async () => {
2568
+ const fake = new FakeAgentSession("close-mode-ctrl")
2569
+ const sessionFactory: AcpSessionFactory = async () => asSession(fake)
2570
+ const agent = new IkieAcpAgent(makeConn(), {
2571
+ extensionFactories: [],
2572
+ agentDir: "/tmp/fake-agent-dir",
2573
+ sessionFactory,
2574
+ })
2575
+
2576
+ const { sessionId } = await agent.newSession({
2577
+ cwd: "/tmp",
2578
+ mcpServers: [],
2579
+ })
2580
+ expect(getSessionPermissionFlagController(sessionId)).toBeDefined()
2581
+
2582
+ await agent.unstable_closeSession({ sessionId })
2583
+ expect(getSessionPermissionFlagController(sessionId)).toBeUndefined()
2584
+ })
2585
+
2586
+ it("unregisters mode controllers on shutdown", async () => {
2587
+ const fake1 = new FakeAgentSession("shutdown-mode-1")
2588
+ const fake2 = new FakeAgentSession("shutdown-mode-2")
2589
+ let callCount = 0
2590
+ const agent = new IkieAcpAgent(makeConn(), {
2591
+ extensionFactories: [],
2592
+ agentDir: "/tmp/fake-agent-dir",
2593
+ sessionFactory: async () => asSession(++callCount === 1 ? fake1 : fake2),
2594
+ })
2595
+
2596
+ const r1 = await agent.newSession({ cwd: "/tmp", mcpServers: [] })
2597
+ const r2 = await agent.newSession({ cwd: "/tmp", mcpServers: [] })
2598
+ expect(getSessionPermissionFlagController(r1.sessionId)).toBeDefined()
2599
+ expect(getSessionPermissionFlagController(r2.sessionId)).toBeDefined()
2600
+
2601
+ await agent.shutdown()
2602
+ expect(getSessionPermissionFlagController(r1.sessionId)).toBeUndefined()
2603
+ expect(getSessionPermissionFlagController(r2.sessionId)).toBeUndefined()
2604
+ })
2605
+
2606
+ it("seeds initial mode from env baseline, not from live env mutations", async () => {
2607
+ vi.stubEnv(PERMISSIONS_ENV_KEY, "auto")
2608
+ const agent = new IkieAcpAgent(makeConn(), {
2609
+ extensionFactories: [],
2610
+ agentDir: "/tmp/fake-agent-dir",
2611
+ sessionFactory: async () => asSession(new FakeAgentSession("env-baseline-1")),
2612
+ })
2613
+
2614
+ // Mutate env after construction (simulates another session writing to env)
2615
+ process.env[PERMISSIONS_ENV_KEY] = "yolo"
2616
+
2617
+ const res = await agent.newSession({ cwd: "/tmp", mcpServers: [] })
2618
+ // Should use the snapshotted baseline (auto), not the live env (yolo)
2619
+ expect(res.configOptions?.[0].currentValue).toBe("auto")
2620
+ })
2621
+
2622
+ it("defaults to 'default' mode when IKIE_PERMISSIONS env is unset", async () => {
2623
+ vi.stubEnv(PERMISSIONS_ENV_KEY, "")
2624
+ Reflect.deleteProperty(process.env, PERMISSIONS_ENV_KEY)
2625
+ const agent = new IkieAcpAgent(makeConn(), {
2626
+ extensionFactories: [],
2627
+ agentDir: "/tmp/fake-agent-dir",
2628
+ sessionFactory: async () => asSession(new FakeAgentSession("env-unset")),
2629
+ })
2630
+
2631
+ const res = await agent.newSession({ cwd: "/tmp", mcpServers: [] })
2632
+ expect(res.configOptions?.[0].currentValue).toBe("default")
2633
+ })
2634
+
2635
+ it("uses defaultMode from permissions config file when env is not set", async () => {
2636
+ // Create a temp directory with a .ikie/permissions.json
2637
+ const tmpDir = mkdtempSync(join(tmpdir(), "acp-mode-config-test-"))
2638
+ const ikieDir = join(tmpDir, ".ikie")
2639
+ mkdirSync(ikieDir, { recursive: true })
2640
+ writeFileSync(join(ikieDir, "permissions.json"), JSON.stringify({ defaultMode: "plan" }))
2641
+
2642
+ vi.stubEnv(PERMISSIONS_ENV_KEY, "")
2643
+ Reflect.deleteProperty(process.env, PERMISSIONS_ENV_KEY)
2644
+
2645
+ try {
2646
+ const agent = new IkieAcpAgent(makeConn(), {
2647
+ extensionFactories: [],
2648
+ agentDir: "/tmp/fake-agent-dir",
2649
+ sessionFactory: async () => asSession(new FakeAgentSession("config-mode")),
2650
+ })
2651
+
2652
+ const res = await agent.newSession({ cwd: tmpDir, mcpServers: [] })
2653
+ expect(res.configOptions?.[0].currentValue).toBe("plan")
2654
+ } finally {
2655
+ rmSync(tmpDir, { recursive: true, force: true })
2656
+ }
2657
+ })
2658
+
2659
+ it("env IKIE_PERMISSIONS takes precedence over config defaultMode", async () => {
2660
+ // Create a temp directory with a .ikie/permissions.json
2661
+ const tmpDir = mkdtempSync(join(tmpdir(), "acp-mode-env-precedence-test-"))
2662
+ const ikieDir = join(tmpDir, ".ikie")
2663
+ mkdirSync(ikieDir, { recursive: true })
2664
+ writeFileSync(join(ikieDir, "permissions.json"), JSON.stringify({ defaultMode: "plan" }))
2665
+
2666
+ // Set env to a different mode
2667
+ vi.stubEnv(PERMISSIONS_ENV_KEY, "auto")
2668
+
2669
+ try {
2670
+ const agent = new IkieAcpAgent(makeConn(), {
2671
+ extensionFactories: [],
2672
+ agentDir: "/tmp/fake-agent-dir",
2673
+ sessionFactory: async () => asSession(new FakeAgentSession("env-precedence")),
2674
+ })
2675
+
2676
+ const res = await agent.newSession({ cwd: tmpDir, mcpServers: [] })
2677
+ // Env should take precedence over config
2678
+ expect(res.configOptions?.[0].currentValue).toBe("auto")
2679
+ } finally {
2680
+ rmSync(tmpDir, { recursive: true, force: true })
2681
+ }
2682
+ })
2683
+
2684
+ it("per-session mode changes do not leak across sessions", async () => {
2685
+ vi.stubEnv(PERMISSIONS_ENV_KEY, "")
2686
+ Reflect.deleteProperty(process.env, PERMISSIONS_ENV_KEY)
2687
+ const fake1 = new FakeAgentSession("isolate-1")
2688
+ const fake2 = new FakeAgentSession("isolate-2")
2689
+ let callCount = 0
2690
+ const agent = new IkieAcpAgent(makeConn(), {
2691
+ extensionFactories: [],
2692
+ agentDir: "/tmp/fake-agent-dir",
2693
+ sessionFactory: async () => asSession(++callCount === 1 ? fake1 : fake2),
2694
+ })
2695
+
2696
+ const r1 = await agent.newSession({ cwd: "/tmp", mcpServers: [] })
2697
+ const r2 = await agent.newSession({ cwd: "/tmp", mcpServers: [] })
2698
+
2699
+ // Both sessions start at "default"
2700
+ expect(getSessionPermissionFlagController(r1.sessionId)?.getMode()).toEqual({ mode: "default", source: "user" })
2701
+ expect(getSessionPermissionFlagController(r2.sessionId)?.getMode()).toEqual({ mode: "default", source: "user" })
2702
+
2703
+ // Change session 1 to yolo
2704
+ await agent.setSessionConfigOption({
2705
+ sessionId: r1.sessionId,
2706
+ configId: "permissions-mode",
2707
+ value: "yolo",
2708
+ })
2709
+
2710
+ // Session 1 is yolo, session 2 is still default
2711
+ expect(getSessionPermissionFlagController(r1.sessionId)?.getMode()).toEqual({ mode: "yolo", source: "user" })
2712
+ expect(getSessionPermissionFlagController(r2.sessionId)?.getMode()).toEqual({ mode: "default", source: "user" })
2713
+ })
2714
+
2715
+ it("closeSession deletes the IKIE_PERMISSIONS_<sessionId> env key", async () => {
2716
+ vi.stubEnv(PERMISSIONS_ENV_KEY, "")
2717
+ Reflect.deleteProperty(process.env, PERMISSIONS_ENV_KEY)
2718
+
2719
+ const fake = new FakeAgentSession("close-env-key")
2720
+ const agent = new IkieAcpAgent(makeConn(), {
2721
+ extensionFactories: [],
2722
+ agentDir: "/tmp/fake-agent-dir",
2723
+ sessionFactory: async () => asSession(fake),
2724
+ })
2725
+
2726
+ const { sessionId } = await agent.newSession({ cwd: "/tmp", mcpServers: [] })
2727
+
2728
+ // Set a mode so the namespaced env key is definitely written.
2729
+ await agent.setSessionConfigOption({ sessionId, configId: "permissions-mode", value: "yolo" })
2730
+ const envKey = `${PERMISSIONS_ENV_KEY}_${sessionId}`
2731
+ expect(process.env[envKey]).toBe("yolo")
2732
+
2733
+ await agent.unstable_closeSession({ sessionId })
2734
+
2735
+ expect(process.env[envKey]).toBeUndefined()
2736
+ })
2737
+
2738
+ it("shutdown deletes IKIE_PERMISSIONS_<sessionId> env keys for all sessions", async () => {
2739
+ vi.stubEnv(PERMISSIONS_ENV_KEY, "")
2740
+ Reflect.deleteProperty(process.env, PERMISSIONS_ENV_KEY)
2741
+
2742
+ const fake1 = new FakeAgentSession("shutdown-env-1")
2743
+ const fake2 = new FakeAgentSession("shutdown-env-2")
2744
+ let callCount = 0
2745
+ const agent = new IkieAcpAgent(makeConn(), {
2746
+ extensionFactories: [],
2747
+ agentDir: "/tmp/fake-agent-dir",
2748
+ sessionFactory: async () => asSession(++callCount === 1 ? fake1 : fake2),
2749
+ })
2750
+
2751
+ const r1 = await agent.newSession({ cwd: "/tmp", mcpServers: [] })
2752
+ const r2 = await agent.newSession({ cwd: "/tmp", mcpServers: [] })
2753
+
2754
+ // Write a namespaced env key for each session.
2755
+ await agent.setSessionConfigOption({ sessionId: r1.sessionId, configId: "permissions-mode", value: "plan" })
2756
+ await agent.setSessionConfigOption({ sessionId: r2.sessionId, configId: "permissions-mode", value: "auto" })
2757
+
2758
+ const key1 = `${PERMISSIONS_ENV_KEY}_${r1.sessionId}`
2759
+ const key2 = `${PERMISSIONS_ENV_KEY}_${r2.sessionId}`
2760
+ expect(process.env[key1]).toBe("plan")
2761
+ expect(process.env[key2]).toBe("auto")
2762
+
2763
+ await agent.shutdown()
2764
+
2765
+ expect(process.env[key1]).toBeUndefined()
2766
+ expect(process.env[key2]).toBeUndefined()
2767
+ })
2768
+ })
2769
+
2770
+ // Direct coverage for describeToolCall. The function drives the tool_call
2771
+ // notification's title, kind, and locations — ACP clients key UI affordances
2772
+ // off these. Two recent fixes (064ff92, 00f58f3) landed on it; table-driven
2773
+ // cases here keep the title/kind matrix from silently drifting.
2774
+ describe("describeToolCall", () => {
2775
+ it("detects hidden system Agent calls", () => {
2776
+ expect(isHiddenToolCall("Agent", { visibility: "system" })).toBe(true)
2777
+ expect(isHiddenToolCall("Agent", { visibility: "user" })).toBe(false)
2778
+ expect(isHiddenToolCall("bash", { visibility: "system" })).toBe(false)
2779
+ })
2780
+
2781
+ const longCommand = "a".repeat(120)
2782
+ const longPath = `/tmp/${"x".repeat(120)}`
2783
+ const longPattern = "p".repeat(120)
2784
+ const cases: Array<{
2785
+ name: string
2786
+ toolName: string
2787
+ args: unknown
2788
+ expect: { title: string; kind: string; locations: Array<{ path: string }> }
2789
+ }> = [
2790
+ {
2791
+ name: "bash with command uses command as title and execute kind",
2792
+ toolName: "bash",
2793
+ args: { command: "ls -la" },
2794
+ expect: { title: "ls -la", kind: "execute", locations: [] },
2795
+ },
2796
+ {
2797
+ name: "bash without command falls back to tool name",
2798
+ toolName: "bash",
2799
+ args: {},
2800
+ expect: { title: "bash", kind: "execute", locations: [] },
2801
+ },
2802
+ {
2803
+ name: "bash command is truncated at TITLE_MAX",
2804
+ toolName: "bash",
2805
+ args: { command: longCommand },
2806
+ expect: { title: `${"a".repeat(80)}…`, kind: "execute", locations: [] },
2807
+ },
2808
+ {
2809
+ name: "read with file_path uses path and populates locations",
2810
+ toolName: "read",
2811
+ args: { file_path: "/etc/hosts" },
2812
+ expect: {
2813
+ title: "/etc/hosts",
2814
+ kind: "read",
2815
+ locations: [{ path: "/etc/hosts" }],
2816
+ },
2817
+ },
2818
+ {
2819
+ name: "edit with file_path uses path and edit kind",
2820
+ toolName: "edit",
2821
+ args: { file_path: "/tmp/a.ts" },
2822
+ expect: {
2823
+ title: "/tmp/a.ts",
2824
+ kind: "edit",
2825
+ locations: [{ path: "/tmp/a.ts" }],
2826
+ },
2827
+ },
2828
+ {
2829
+ name: "write with path (not file_path) still populates locations",
2830
+ toolName: "write",
2831
+ args: { path: "/tmp/b.ts" },
2832
+ expect: {
2833
+ title: "/tmp/b.ts",
2834
+ kind: "edit",
2835
+ locations: [{ path: "/tmp/b.ts" }],
2836
+ },
2837
+ },
2838
+ {
2839
+ name: "grep with pattern uses pattern as title and search kind",
2840
+ toolName: "grep",
2841
+ args: { pattern: "foo.*bar" },
2842
+ expect: { title: "foo.*bar", kind: "search", locations: [] },
2843
+ },
2844
+ {
2845
+ name: "ls maps to read kind",
2846
+ toolName: "ls",
2847
+ args: { path: "/tmp" },
2848
+ expect: { title: "/tmp", kind: "read", locations: [{ path: "/tmp" }] },
2849
+ },
2850
+ {
2851
+ name: "find maps to search kind",
2852
+ toolName: "find",
2853
+ args: { pattern: "*.ts" },
2854
+ expect: { title: "*.ts", kind: "search", locations: [] },
2855
+ },
2856
+ {
2857
+ name: "web_fetch maps to fetch kind",
2858
+ toolName: "web_fetch",
2859
+ args: { url: "https://example.com" },
2860
+ expect: { title: "web_fetch", kind: "fetch", locations: [] },
2861
+ },
2862
+ {
2863
+ name: "web_search maps to search kind",
2864
+ toolName: "web_search",
2865
+ args: { query: "ikie" },
2866
+ expect: { title: "web_search", kind: "search", locations: [] },
2867
+ },
2868
+ {
2869
+ name: "Agent maps to think kind",
2870
+ toolName: "Agent",
2871
+ args: { prompt: "go", visibility: "user" },
2872
+ expect: { title: "Agent", kind: "think", locations: [] },
2873
+ },
2874
+ {
2875
+ name: "unknown tool falls back to other kind",
2876
+ toolName: "mcp__foo__bar",
2877
+ args: { arg: 1 },
2878
+ expect: { title: "mcp__foo__bar", kind: "other", locations: [] },
2879
+ },
2880
+ {
2881
+ name: "null args is tolerated",
2882
+ toolName: "bash",
2883
+ args: null,
2884
+ expect: { title: "bash", kind: "execute", locations: [] },
2885
+ },
2886
+ {
2887
+ name: "long path title is truncated (locations keep full path)",
2888
+ toolName: "read",
2889
+ args: { file_path: longPath },
2890
+ expect: {
2891
+ title: `${longPath.slice(0, 80)}…`,
2892
+ kind: "read",
2893
+ locations: [{ path: longPath }],
2894
+ },
2895
+ },
2896
+ {
2897
+ name: "long pattern title is truncated",
2898
+ toolName: "grep",
2899
+ args: { pattern: longPattern },
2900
+ expect: {
2901
+ title: `${longPattern.slice(0, 80)}…`,
2902
+ kind: "search",
2903
+ locations: [],
2904
+ },
2905
+ },
2906
+ ]
2907
+
2908
+ for (const c of cases) {
2909
+ it(c.name, () => {
2910
+ const result = describeToolCall(c.toolName, c.args)
2911
+ expect(result.title).toBe(c.expect.title)
2912
+ expect(result.kind).toBe(c.expect.kind)
2913
+ expect(result.locations).toEqual(c.expect.locations)
2914
+ })
2915
+ }
2916
+ })
2917
+
2918
+ // Helper for the listSessions tests: builds a pi SessionInfo with sensible
2919
+ // defaults so each test only spells out the fields it cares about.
2920
+ function makePiSession(overrides: Partial<PiSessionInfo> = {}): PiSessionInfo {
2921
+ return {
2922
+ path: "/tmp/sessions/x.jsonl",
2923
+ id: "id-x",
2924
+ cwd: "/tmp/proj",
2925
+ name: undefined,
2926
+ parentSessionPath: undefined,
2927
+ created: new Date("2026-01-01T00:00:00Z"),
2928
+ modified: new Date("2026-01-01T00:00:00Z"),
2929
+ messageCount: 0,
2930
+ firstMessage: "",
2931
+ allMessagesText: "",
2932
+ ...overrides,
2933
+ }
2934
+ }
2935
+
2936
+ // Direct coverage for the pi → ACP SessionInfo mapping. Title fallback and
2937
+ // updatedAt formatting are both load-bearing for Zed's thread-picker UI.
2938
+ describe("toAcpSessionInfo", () => {
2939
+ it("uses the user-defined name when present", () => {
2940
+ const out = toAcpSessionInfo(
2941
+ makePiSession({
2942
+ id: "s1",
2943
+ cwd: "/p",
2944
+ name: "named",
2945
+ firstMessage: "ignored",
2946
+ }),
2947
+ )
2948
+ expect(out).toEqual({
2949
+ sessionId: "s1",
2950
+ cwd: "/p",
2951
+ title: "named",
2952
+ updatedAt: "2026-01-01T00:00:00.000Z",
2953
+ })
2954
+ })
2955
+
2956
+ it("falls back to truncated firstMessage when name is absent", () => {
2957
+ const long = "q".repeat(120)
2958
+ const out = toAcpSessionInfo(makePiSession({ firstMessage: long }))
2959
+ expect(out.title).toBe(`${"q".repeat(80)}…`)
2960
+ })
2961
+
2962
+ it("returns null title when both name and firstMessage are empty", () => {
2963
+ const out = toAcpSessionInfo(makePiSession({ name: undefined, firstMessage: "" }))
2964
+ expect(out.title).toBeNull()
2965
+ })
2966
+
2967
+ it("falls back to firstMessage when name is the empty string (not just undefined)", () => {
2968
+ // Pi types `name?: string`, but a hand-edited / migrated session info
2969
+ // entry can land with name === "". A previous version used `??` which
2970
+ // only short-circuits on null/undefined, so the fallback was skipped
2971
+ // and the title became null even though firstMessage was populated.
2972
+ const out = toAcpSessionInfo(makePiSession({ name: "", firstMessage: "hello world" }))
2973
+ expect(out.title).toBe("hello world")
2974
+ })
2975
+
2976
+ it("formats updatedAt as ISO 8601 from the modified Date", () => {
2977
+ const out = toAcpSessionInfo(makePiSession({ modified: new Date("2026-05-09T12:34:56.789Z") }))
2978
+ expect(out.updatedAt).toBe("2026-05-09T12:34:56.789Z")
2979
+ })
2980
+ })
2981
+
2982
+ describe("IkieAcpAgent listSessions", () => {
2983
+ function makeAgent(lister: AcpSessionLister): IkieAcpAgent {
2984
+ return new IkieAcpAgent(makeConn(), {
2985
+ extensionFactories: [],
2986
+ agentDir: "/tmp/fake-agent-dir",
2987
+ sessionFactory: async () => asSession(new FakeAgentSession("unused")),
2988
+ sessionLister: lister,
2989
+ })
2990
+ }
2991
+
2992
+ it("advertises sessionCapabilities.list in initialize", async () => {
2993
+ const agent = makeAgent(async () => [])
2994
+ const init = await agent.initialize({
2995
+ protocolVersion: 1,
2996
+ clientCapabilities: {} as never,
2997
+ } as never)
2998
+ expect(init.agentCapabilities?.sessionCapabilities?.list).toEqual({})
2999
+ })
3000
+
3001
+ it("dispatches to SessionManager.list when cwd is provided", async () => {
3002
+ let received: { cwd?: string | null } = {}
3003
+ const agent = makeAgent(async (params) => {
3004
+ received = { cwd: params.cwd }
3005
+ return []
3006
+ })
3007
+ await agent.listSessions({ cwd: "/repo/foo", mcpServers: [] } as never)
3008
+ expect(received.cwd).toBe("/repo/foo")
3009
+ })
3010
+
3011
+ it("falls back to listAll when cwd is omitted", async () => {
3012
+ let cwdSeen: string | null | undefined = "sentinel"
3013
+ const agent = makeAgent(async (params) => {
3014
+ cwdSeen = params.cwd
3015
+ return []
3016
+ })
3017
+ await agent.listSessions({} as never)
3018
+ // Lister receives the original (undefined) cwd; the default lister maps
3019
+ // that to listAll(). Tests of the default lister itself live in pi.
3020
+ expect(cwdSeen).toBeUndefined()
3021
+ })
3022
+
3023
+ it("forwards additionalDirectories to the session lister", async () => {
3024
+ let received: ListSessionsRequest | undefined
3025
+ const agent = makeAgent(async (params) => {
3026
+ received = params
3027
+ return []
3028
+ })
3029
+ await agent.listSessions({
3030
+ cwd: "/repo/foo",
3031
+ additionalDirectories: ["/repo/bar", "/repo/baz"],
3032
+ } as never)
3033
+ expect(received?.additionalDirectories).toEqual(["/repo/bar", "/repo/baz"])
3034
+ })
3035
+
3036
+ it("dedupes sessions returned across multiple roots by id", async () => {
3037
+ // Custom lister stand-in for the multi-root default lister: returns the
3038
+ // same id from two roots; handler must surface it once.
3039
+ const dup = makePiSession({
3040
+ id: "shared",
3041
+ modified: new Date("2026-04-01T00:00:00Z"),
3042
+ name: "shared",
3043
+ })
3044
+ const uniq = makePiSession({
3045
+ id: "uniq",
3046
+ modified: new Date("2026-03-01T00:00:00Z"),
3047
+ name: "uniq",
3048
+ })
3049
+ const agent = makeAgent(async () => [dup, uniq, dup])
3050
+ const res = await agent.listSessions({ cwd: "/p" } as never)
3051
+ expect(res.sessions.map((s) => s.sessionId)).toEqual(["shared", "uniq"])
3052
+ })
3053
+
3054
+ it("returns empty array for a directory with no sessions", async () => {
3055
+ const agent = makeAgent(async () => [])
3056
+ const res = await agent.listSessions({ cwd: "/empty" } as never)
3057
+ expect(res.sessions).toEqual([])
3058
+ })
3059
+
3060
+ it("returns nextCursor: null to signal end-of-pagination", async () => {
3061
+ const agent = makeAgent(async () => [makePiSession({ id: "s" })])
3062
+ const res = await agent.listSessions({ cwd: "/p" } as never)
3063
+ expect(res.nextCursor).toBeNull()
3064
+ })
3065
+
3066
+ it("sorts sessions newest-first by updatedAt", async () => {
3067
+ const piSessions: PiSessionInfo[] = [
3068
+ makePiSession({
3069
+ id: "old",
3070
+ modified: new Date("2026-01-01T00:00:00Z"),
3071
+ name: "old",
3072
+ }),
3073
+ makePiSession({
3074
+ id: "new",
3075
+ modified: new Date("2026-05-09T00:00:00Z"),
3076
+ name: "new",
3077
+ }),
3078
+ makePiSession({
3079
+ id: "mid",
3080
+ modified: new Date("2026-03-01T00:00:00Z"),
3081
+ name: "mid",
3082
+ }),
3083
+ ]
3084
+ const agent = makeAgent(async () => piSessions)
3085
+ const res = await agent.listSessions({ cwd: "/p" } as never)
3086
+ expect(res.sessions.map((s) => s.sessionId)).toEqual(["new", "mid", "old"])
3087
+ })
3088
+
3089
+ it("uses truncated firstMessage as title when name is absent", async () => {
3090
+ const long = "z".repeat(120)
3091
+ const agent = makeAgent(async () => [makePiSession({ id: "s", firstMessage: long, name: undefined })])
3092
+ const res = await agent.listSessions({ cwd: "/p" } as never)
3093
+ expect(res.sessions[0].title).toBe(`${"z".repeat(80)}…`)
3094
+ })
3095
+ })
3096
+
3097
+ // Helpers for replay tests: build the SessionMessageEntry shape that
3098
+ // SessionManager.getBranch() returns. `userText` / `assistantText` produce the
3099
+ // minimal valid envelope — id/parentId/timestamp are not consulted by the
3100
+ // replay walker, so any non-empty placeholder is fine.
3101
+ function userTextEntry(text: string, id = "u1", parentId: string | null = null): unknown {
3102
+ return {
3103
+ type: "message",
3104
+ id,
3105
+ parentId,
3106
+ timestamp: "2026-05-09T00:00:00Z",
3107
+ message: { role: "user", content: text, timestamp: 0 },
3108
+ }
3109
+ }
3110
+ function assistantTextEntry(text: string, id = "a1", parentId: string | null = null): unknown {
3111
+ return assistantBlocksEntry([{ type: "text", text }], id, parentId)
3112
+ }
3113
+
3114
+ // Variant that builds an assistant entry from arbitrary content blocks (text,
3115
+ // thinking, toolCall). Used by replay tests to drop in mixed-block fixtures
3116
+ // without re-spelling the message envelope each time.
3117
+ function assistantBlocksEntry(content: unknown[], id = "a1", parentId: string | null = null): unknown {
3118
+ return {
3119
+ type: "message",
3120
+ id,
3121
+ parentId,
3122
+ timestamp: "2026-05-09T00:00:01Z",
3123
+ message: {
3124
+ role: "assistant",
3125
+ content,
3126
+ api: "anthropic-messages",
3127
+ provider: "anthropic",
3128
+ model: "claude",
3129
+ usage: {
3130
+ input: 0,
3131
+ output: 0,
3132
+ cacheRead: 0,
3133
+ cacheWrite: 0,
3134
+ totalTokens: 0,
3135
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
3136
+ },
3137
+ stopReason: "stop",
3138
+ timestamp: 0,
3139
+ },
3140
+ }
3141
+ }
3142
+
3143
+ function toolResultEntry(
3144
+ toolCallId: string,
3145
+ toolName: string,
3146
+ text: string,
3147
+ isError = false,
3148
+ id = `tr-${toolCallId}`,
3149
+ parentId: string | null = null,
3150
+ ): unknown {
3151
+ return {
3152
+ type: "message",
3153
+ id,
3154
+ parentId,
3155
+ timestamp: "2026-05-09T00:00:02Z",
3156
+ message: {
3157
+ role: "toolResult",
3158
+ toolCallId,
3159
+ toolName,
3160
+ content: [{ type: "text", text }],
3161
+ isError,
3162
+ timestamp: 0,
3163
+ },
3164
+ }
3165
+ }
3166
+
3167
+ function testEncodeCwdDir(cwd: string): string {
3168
+ return `--${cwd.replace(/^[/\\]/, "").replace(/[/\\:]/g, "-")}--`
3169
+ }
3170
+
3171
+ describe("IkieAcpAgent loadSession", () => {
3172
+ function makeAgent(loader: AcpSessionLoader, opts?: { conn?: AgentSideConnection }): IkieAcpAgent {
3173
+ return new IkieAcpAgent(opts?.conn ?? makeConn(), {
3174
+ extensionFactories: [],
3175
+ agentDir: "/tmp/fake-agent-dir",
3176
+ sessionFactory: async () => asSession(new FakeAgentSession("unused")),
3177
+ sessionLoader: loader,
3178
+ })
3179
+ }
3180
+
3181
+ it("advertises loadSession capability in initialize", async () => {
3182
+ const agent = makeAgent(async () => asSession(new FakeAgentSession("unused")))
3183
+ const init = await agent.initialize({
3184
+ protocolVersion: 1,
3185
+ clientCapabilities: {} as never,
3186
+ } as never)
3187
+ expect(init.agentCapabilities?.loadSession).toBe(true)
3188
+ expect(init.agentCapabilities?.sessionCapabilities?.close).toEqual({})
3189
+ })
3190
+
3191
+ it("rejects loadSession when mcpServers is non-empty (does not invoke loader)", async () => {
3192
+ const loaderCalls = { count: 0 }
3193
+ const loader: AcpSessionLoader = async () => {
3194
+ loaderCalls.count++
3195
+ return asSession(new FakeAgentSession("unused"))
3196
+ }
3197
+ const agent = makeAgent(loader)
3198
+ await expect(
3199
+ agent.loadSession({
3200
+ sessionId: "s1",
3201
+ cwd: "/tmp",
3202
+ // biome-ignore lint/suspicious/noExplicitAny: only the shape we care about
3203
+ mcpServers: [{ name: "x", command: "x", args: [] } as any],
3204
+ }),
3205
+ ).rejects.toMatchObject({ code: -32602 })
3206
+ expect(loaderCalls.count).toBe(0)
3207
+ })
3208
+
3209
+ it("replays and returns an already loaded session without reopening it", async () => {
3210
+ const loaderCalls = { count: 0 }
3211
+ const live = new FakeAgentSession("live-1")
3212
+ live.branch = [userTextEntry("already here", "u1", null)]
3213
+ const factory: AcpSessionFactory = async () => asSession(live)
3214
+ const loader: AcpSessionLoader = async () => {
3215
+ loaderCalls.count++
3216
+ return asSession(new FakeAgentSession("unused"))
3217
+ }
3218
+ const { conn, updates } = makeRecordingConn()
3219
+ const agent = new IkieAcpAgent(conn, {
3220
+ extensionFactories: [],
3221
+ agentDir: "/tmp/fake-agent-dir",
3222
+ sessionFactory: factory,
3223
+ sessionLoader: loader,
3224
+ })
3225
+ await agent.newSession({ cwd: "/tmp", mcpServers: [] })
3226
+
3227
+ const res = await agent.loadSession({
3228
+ sessionId: "live-1",
3229
+ cwd: "/tmp",
3230
+ mcpServers: [],
3231
+ })
3232
+
3233
+ expect(res.models).toMatchObject({
3234
+ currentModelId: "test/test-model",
3235
+ })
3236
+ expect(loaderCalls.count).toBe(0)
3237
+
3238
+ const replayUpdates = replayOnly(updates)
3239
+ // loadSession replay sends user_message_chunk
3240
+ expect(replayUpdates).toHaveLength(1)
3241
+ expect(replayUpdates[0].update).toMatchObject({
3242
+ sessionUpdate: "user_message_chunk",
3243
+ content: { type: "text", text: "already here" },
3244
+ })
3245
+ })
3246
+
3247
+ it("returns configOptions in loadSession response", async () => {
3248
+ const tmpDir = mkdtempSync(join(tmpdir(), "ikie-acp-load-config-"))
3249
+ try {
3250
+ const fake = new FakeAgentSession("test-load-session-config")
3251
+ const sessionFactory: AcpSessionFactory = async () => asSession(fake)
3252
+ const lister: AcpSessionLister = async () => [
3253
+ makePiSession({
3254
+ id: "test-load-session-config",
3255
+ cwd: tmpDir,
3256
+ path: join(tmpDir, "test-load-session-config.jsonl"),
3257
+ }),
3258
+ ]
3259
+ const loader: AcpSessionLoader = async () => {
3260
+ return asSession(fake)
3261
+ }
3262
+ const agent = new IkieAcpAgent(makeConn(), {
3263
+ extensionFactories: [],
3264
+ agentDir: tmpDir,
3265
+ sessionFactory,
3266
+ sessionLister: lister,
3267
+ sessionLoader: loader,
3268
+ })
3269
+
3270
+ // Create the session first
3271
+ await agent.newSession({ cwd: tmpDir, mcpServers: [] })
3272
+
3273
+ // Close it
3274
+ await agent.unstable_closeSession({
3275
+ sessionId: "test-load-session-config",
3276
+ })
3277
+
3278
+ // Load it back
3279
+ const res = await agent.loadSession({
3280
+ sessionId: "test-load-session-config",
3281
+ cwd: tmpDir,
3282
+ mcpServers: [],
3283
+ })
3284
+
3285
+ expect(res.configOptions).toBeDefined()
3286
+ expect(res.configOptions).toHaveLength(1)
3287
+ expect(res.configOptions?.[0].id).toBe("permissions-mode")
3288
+ } finally {
3289
+ rmSync(tmpDir, { recursive: true, force: true })
3290
+ }
3291
+ })
3292
+
3293
+ it("coalesces concurrent loadSession requests for the same sessionId", async () => {
3294
+ const fake = new FakeAgentSession("coalesce-1")
3295
+ let loaderCalls = 0
3296
+ let markLoaderStarted!: () => void
3297
+ let releaseLoader!: () => void
3298
+ const loaderStarted = new Promise<void>((resolve) => {
3299
+ markLoaderStarted = resolve
3300
+ })
3301
+ const release = new Promise<void>((resolve) => {
3302
+ releaseLoader = resolve
3303
+ })
3304
+ const loader: AcpSessionLoader = async () => {
3305
+ loaderCalls++
3306
+ markLoaderStarted()
3307
+ await release
3308
+ return asSession(fake)
3309
+ }
3310
+ const agent = makeAgent(loader)
3311
+ const first = agent.loadSession({
3312
+ sessionId: "coalesce-1",
3313
+ cwd: "/tmp",
3314
+ mcpServers: [],
3315
+ })
3316
+ await loaderStarted
3317
+ const second = agent.loadSession({
3318
+ sessionId: "coalesce-1",
3319
+ cwd: "/tmp",
3320
+ mcpServers: [],
3321
+ })
3322
+ releaseLoader()
3323
+
3324
+ await expect(Promise.all([first, second])).resolves.toHaveLength(2)
3325
+ expect(loaderCalls).toBe(1)
3326
+ })
3327
+
3328
+ it("propagates loader errors (e.g. missing file → invalidParams)", async () => {
3329
+ const agent = makeAgent(async () => {
3330
+ throw Object.assign(new Error("session not found"), { code: -32602 })
3331
+ })
3332
+ await expect(agent.loadSession({ sessionId: "missing", cwd: "/tmp", mcpServers: [] })).rejects.toThrow(
3333
+ /session not found/,
3334
+ )
3335
+ })
3336
+
3337
+ it("rejects default-loaded sessions whose header cwd disagrees before opening", async () => {
3338
+ const agentDir = mkdtempSync(join(tmpdir(), "ikie-acp-load-"))
3339
+ try {
3340
+ const sessionId = "cwd-mismatch"
3341
+ const requestedCwd = "/tmp/requested"
3342
+ const sessionDir = join(agentDir, "sessions", testEncodeCwdDir(requestedCwd))
3343
+ mkdirSync(sessionDir, { recursive: true })
3344
+ writeFileSync(
3345
+ join(sessionDir, `2026-05-09T00-00-00.000Z_${sessionId}.jsonl`),
3346
+ `${JSON.stringify({
3347
+ type: "session",
3348
+ version: 3,
3349
+ id: sessionId,
3350
+ timestamp: "2026-05-09T00:00:00Z",
3351
+ cwd: "/tmp/other",
3352
+ })}\n`,
3353
+ )
3354
+ const agent = new IkieAcpAgent(makeConn(), {
3355
+ extensionFactories: [],
3356
+ agentDir,
3357
+ sessionFactory: async () => asSession(new FakeAgentSession("unused")),
3358
+ })
3359
+
3360
+ await expect(agent.loadSession({ sessionId, cwd: requestedCwd, mcpServers: [] })).rejects.toThrow(
3361
+ /session cwd \/tmp\/other does not match requested cwd \/tmp\/requested/,
3362
+ )
3363
+ } finally {
3364
+ rmSync(agentDir, { recursive: true, force: true })
3365
+ }
3366
+ })
3367
+
3368
+ it("disposes the session if subscribe throws during loadSession", async () => {
3369
+ const leaky = new FakeAgentSession("leak-1")
3370
+ leaky.subscribe = () => {
3371
+ throw new Error("subscribe boom")
3372
+ }
3373
+ const agent = makeAgent(async () => asSession(leaky))
3374
+ await expect(agent.loadSession({ sessionId: "leak-1", cwd: "/tmp", mcpServers: [] })).rejects.toThrow(
3375
+ /subscribe boom/,
3376
+ )
3377
+ expect(leaky.disposed).toBe(true)
3378
+ })
3379
+
3380
+ it("unwinds registration and disposes the session if replay throws", async () => {
3381
+ // Pin the atomic-ownership invariant: a throw during replay must remove
3382
+ // the session from the registry AND dispose it, otherwise the id stays
3383
+ // "live" while loadSession rejects — blocking re-load with invalidRequest.
3384
+ const fake = new FakeAgentSession("replay-boom")
3385
+ fake.sessionManager = {
3386
+ getBranch: () => {
3387
+ throw new Error("branch read failed")
3388
+ },
3389
+ }
3390
+ const agent = makeAgent(async () => asSession(fake))
3391
+ await expect(
3392
+ agent.loadSession({
3393
+ sessionId: "replay-boom",
3394
+ cwd: "/tmp",
3395
+ mcpServers: [],
3396
+ }),
3397
+ ).rejects.toThrow(/branch read failed/)
3398
+ expect(fake.disposed).toBe(true)
3399
+ // Re-load must not see the failed session as already-live.
3400
+ fake.sessionManager = { getBranch: () => [] }
3401
+ fake.disposed = false
3402
+ await expect(
3403
+ agent.loadSession({
3404
+ sessionId: "replay-boom",
3405
+ cwd: "/tmp",
3406
+ mcpServers: [],
3407
+ }),
3408
+ ).resolves.toBeDefined()
3409
+ })
3410
+
3411
+ it("replays user/assistant text turns as session/update notifications before the response resolves", async () => {
3412
+ const fake = new FakeAgentSession("loaded-1")
3413
+ fake.model = { provider: "test", id: "test-model", name: "Test Model" }
3414
+ fake.modelRegistry = {
3415
+ getAvailable: () => [{ provider: "test", id: "test-model", name: "Test Model" }],
3416
+ }
3417
+ fake.branch = [
3418
+ userTextEntry("hello", "u1", null),
3419
+ assistantTextEntry("hi there", "a1", "u1"),
3420
+ userTextEntry("how are you?", "u2", "a1"),
3421
+ assistantTextEntry("doing well", "a2", "u2"),
3422
+ ]
3423
+ const { conn, updates } = makeRecordingConn()
3424
+ const agent = makeAgent(async () => asSession(fake), { conn })
3425
+
3426
+ // Capture the order: replay notifications must land BEFORE the response
3427
+ // resolves so Zed sees a coherent transcript on the load promise.
3428
+ const updatesAtResolve: (typeof updates)[number][] = []
3429
+ const original = (
3430
+ conn as unknown as {
3431
+ sessionUpdate: (p: SessionNotification) => Promise<void>
3432
+ }
3433
+ ).sessionUpdate
3434
+ ;(
3435
+ conn as unknown as {
3436
+ sessionUpdate: (p: SessionNotification) => Promise<void>
3437
+ }
3438
+ ).sessionUpdate = async (p: SessionNotification) => {
3439
+ await original(p)
3440
+ }
3441
+
3442
+ const res = await agent.loadSession({
3443
+ sessionId: "loaded-1",
3444
+ cwd: "/tmp",
3445
+ mcpServers: [],
3446
+ })
3447
+ // Snapshot updates seen at this point (ie. before any further awaits).
3448
+ // Drop the incidental available_commands_update so we can assert on
3449
+ // transcript shape without coupling to the command palette.
3450
+ updatesAtResolve.push(...replayOnly(updates))
3451
+
3452
+ expect(updatesAtResolve).toHaveLength(4)
3453
+ expect(updatesAtResolve[0].update).toMatchObject({
3454
+ sessionUpdate: "user_message_chunk",
3455
+ content: { type: "text", text: "hello" },
3456
+ })
3457
+ expect(updatesAtResolve[1].update).toMatchObject({
3458
+ sessionUpdate: "agent_message_chunk",
3459
+ content: { type: "text", text: "hi there" },
3460
+ })
3461
+ expect(updatesAtResolve[2].update).toMatchObject({
3462
+ sessionUpdate: "user_message_chunk",
3463
+ content: { type: "text", text: "how are you?" },
3464
+ })
3465
+ expect(updatesAtResolve[3].update).toMatchObject({
3466
+ sessionUpdate: "agent_message_chunk",
3467
+ content: { type: "text", text: "doing well" },
3468
+ })
3469
+ expect(res.models).toMatchObject({
3470
+ currentModelId: "test/test-model",
3471
+ availableModels: [{ modelId: "test/test-model", name: "Test Model" }],
3472
+ })
3473
+ })
3474
+
3475
+ // Replay walker: text + thinking + tool calls all surface as their own
3476
+ // session/update notifications; non-message entries (compaction,
3477
+ // branch_summary, model_change, custom) emit nothing. The block of tests
3478
+ // below exercises one fixture per kind plus a combined fixture.
3479
+
3480
+ it("rejects a load whose session-header id disagrees with the requested sessionId", async () => {
3481
+ // Defensive: pi reads sessionId from the JSONL header, not the file
3482
+ // name. A corrupt / hand-edited session whose header drifted from the
3483
+ // filename would otherwise land in `sessions` under a different key
3484
+ // than the client knows, and subsequent prompts would 404 even though
3485
+ // the file is held open.
3486
+ const fake = new FakeAgentSession("header-id")
3487
+ const loader: AcpSessionLoader = async () => asSession(fake)
3488
+ const agent = makeAgent(loader)
3489
+ await expect(
3490
+ agent.loadSession({
3491
+ sessionId: "requested-id",
3492
+ cwd: "/tmp",
3493
+ mcpServers: [],
3494
+ }),
3495
+ ).rejects.toMatchObject({
3496
+ code: -32602,
3497
+ })
3498
+ expect(fake.disposed).toBe(true)
3499
+ })
3500
+
3501
+ it("coalesces contiguous text blocks within an assistant message into one chunk", async () => {
3502
+ // Replay contract: emit the full message as a single chunk. Adjacent
3503
+ // text blocks (rare but legal) must merge into one agent_message_chunk;
3504
+ // structural blocks (thinking / toolCall) flush the buffer so ordering
3505
+ // stays faithful.
3506
+ const fake = new FakeAgentSession("loaded-coalesce")
3507
+ fake.branch = [
3508
+ userTextEntry("go", "u1", null),
3509
+ assistantBlocksEntry(
3510
+ [
3511
+ { type: "text", text: "first " },
3512
+ { type: "text", text: "second" },
3513
+ { type: "thinking", thinking: "pondering" },
3514
+ { type: "text", text: "third" },
3515
+ ],
3516
+ "a1",
3517
+ "u1",
3518
+ ),
3519
+ ]
3520
+ const { conn, updates } = makeRecordingConn()
3521
+ const agent = makeAgent(async () => asSession(fake), { conn })
3522
+ await agent.loadSession({
3523
+ sessionId: "loaded-coalesce",
3524
+ cwd: "/tmp",
3525
+ mcpServers: [],
3526
+ })
3527
+ const replay = replayOnly(updates)
3528
+ expect(replay.map((u) => u.update.sessionUpdate)).toEqual([
3529
+ "user_message_chunk",
3530
+ "agent_message_chunk",
3531
+ "agent_thought_chunk",
3532
+ "agent_message_chunk",
3533
+ ])
3534
+ expect((replay[1].update as { content: { text: string } }).content.text).toBe("first second")
3535
+ expect((replay[3].update as { content: { text: string } }).content.text).toBe("third")
3536
+ })
3537
+
3538
+ it("routes ANSI-dimmed replay text to thought chunks and strips remaining ANSI", async () => {
3539
+ // hide-thinking-aware models (DeepSeek, QwQ) plus hideThinkingBlock=false
3540
+ // persist text with ANSI dim escapes around inner <think> content. The
3541
+ // live TUI renders them as reasoning; ACP's text content type is
3542
+ // plaintext, so replay must preserve that semantic split explicitly.
3543
+ const dimmed = "before \x1b[2minner\x1b[22m after"
3544
+ const fake = new FakeAgentSession("loaded-ansi")
3545
+ fake.branch = [
3546
+ userTextEntry("go", "u1", null),
3547
+ assistantBlocksEntry(
3548
+ [
3549
+ { type: "text", text: dimmed },
3550
+ { type: "thinking", thinking: "raw \x1b[2mthought\x1b[22m" },
3551
+ ],
3552
+ "a1",
3553
+ "u1",
3554
+ ),
3555
+ ]
3556
+ const { conn, updates } = makeRecordingConn()
3557
+ const agent = makeAgent(async () => asSession(fake), { conn })
3558
+ await agent.loadSession({
3559
+ sessionId: "loaded-ansi",
3560
+ cwd: "/tmp",
3561
+ mcpServers: [],
3562
+ })
3563
+ const messageTexts = updates
3564
+ .filter((u) => u.update.sessionUpdate === "agent_message_chunk")
3565
+ .map((u) => (u.update as { content: { text: string } }).content.text)
3566
+ const thoughtTexts = updates
3567
+ .filter((u) => u.update.sessionUpdate === "agent_thought_chunk")
3568
+ .map((u) => (u.update as { content: { text: string } }).content.text)
3569
+ expect(messageTexts).toEqual(["before ", " after"])
3570
+ expect(thoughtTexts).toEqual(["inner", "raw thought"])
3571
+ })
3572
+
3573
+ it("drops ANSI-dimmed replay thinking when hideThinkingBlock is enabled", async () => {
3574
+ _setHideThinking(true)
3575
+ try {
3576
+ const fake = new FakeAgentSession("loaded-ansi-hidden")
3577
+ fake.branch = [
3578
+ userTextEntry("go", "u1", null),
3579
+ assistantBlocksEntry([{ type: "text", text: "before \x1b[2minner\x1b[22m after" }], "a1", "u1"),
3580
+ ]
3581
+ const { conn, updates } = makeRecordingConn()
3582
+ const agent = makeAgent(async () => asSession(fake), { conn })
3583
+ await agent.loadSession({
3584
+ sessionId: "loaded-ansi-hidden",
3585
+ cwd: "/tmp",
3586
+ mcpServers: [],
3587
+ })
3588
+ const messageTexts = updates
3589
+ .filter((u) => u.update.sessionUpdate === "agent_message_chunk")
3590
+ .map((u) => (u.update as { content: { text: string } }).content.text)
3591
+ expect(updates.find((u) => u.update.sessionUpdate === "agent_thought_chunk")).toBeUndefined()
3592
+ expect(messageTexts).toEqual(["before after"])
3593
+ } finally {
3594
+ _resetHideThinking()
3595
+ }
3596
+ })
3597
+
3598
+ it("treats a concurrent session/cancel during replay as a no-op (no turn active)", async () => {
3599
+ const fake = new FakeAgentSession("loaded-cancel")
3600
+ fake.branch = [userTextEntry("hi", "u1", null)]
3601
+ const agent = makeAgent(async () => asSession(fake))
3602
+ await agent.loadSession({
3603
+ sessionId: "loaded-cancel",
3604
+ cwd: "/tmp",
3605
+ mcpServers: [],
3606
+ })
3607
+ // No turn was created during loadSession, so cancel must not throw and
3608
+ // must not invoke abort with side effects beyond the no-op session.abort.
3609
+ await expect(agent.cancel({ sessionId: "loaded-cancel" })).resolves.toBeUndefined()
3610
+ })
3611
+
3612
+ it("rejects loaded sessions with no model", async () => {
3613
+ const fake = new FakeAgentSession("loaded-no-model")
3614
+ fake.model = undefined
3615
+ fake.branch = []
3616
+ const agent = makeAgent(async () => asSession(fake))
3617
+ await expect(
3618
+ agent.loadSession({
3619
+ sessionId: "loaded-no-model",
3620
+ cwd: "/tmp",
3621
+ mcpServers: [],
3622
+ }),
3623
+ ).rejects.toMatchObject({ code: -32000 })
3624
+ expect(fake.disposed).toBe(true)
3625
+ })
3626
+
3627
+ it("registers the loaded session so a follow-up prompt is accepted", async () => {
3628
+ const fake = new FakeAgentSession("loaded-prompt")
3629
+ fake.branch = [userTextEntry("prior", "u1", null)]
3630
+ const agent = makeAgent(async () => asSession(fake))
3631
+ await agent.loadSession({
3632
+ sessionId: "loaded-prompt",
3633
+ cwd: "/tmp",
3634
+ mcpServers: [],
3635
+ })
3636
+ // Drive a turn through the loaded session — short-circuit path is fine,
3637
+ // we just need to confirm prompt() doesn't reject with "unknown
3638
+ // sessionId" (which would mean the load registration failed).
3639
+ fake.promptImpl = async () => {}
3640
+ const res = await agent.prompt({
3641
+ sessionId: "loaded-prompt",
3642
+ prompt: [{ type: "text", text: "follow up" }],
3643
+ })
3644
+ expect(res.stopReason).toBe("end_turn")
3645
+ })
3646
+
3647
+ // Per ToolKind: replayed tool calls should produce the same shape as live
3648
+ // turns — an initial tool_call carrying the kind/title/locations, followed
3649
+ // by a single terminal tool_call_update that pins status + content. This
3650
+ // matrix locks in describeToolCall coverage on the replay path so a future
3651
+ // kind addition doesn't silently bypass replay.
3652
+ const toolKindMatrix: Array<{
3653
+ name: string
3654
+ toolName: string
3655
+ args: Record<string, unknown>
3656
+ result: { text: string; isError?: boolean }
3657
+ expect: {
3658
+ kind: string
3659
+ title: string
3660
+ status: string
3661
+ locations: Array<{ path: string }>
3662
+ }
3663
+ }> = [
3664
+ {
3665
+ name: "bash → execute",
3666
+ toolName: "bash",
3667
+ args: { command: "ls -la" },
3668
+ result: { text: "ok" },
3669
+ expect: {
3670
+ kind: "execute",
3671
+ title: "ls -la",
3672
+ status: "completed",
3673
+ locations: [],
3674
+ },
3675
+ },
3676
+ {
3677
+ name: "read → read with location",
3678
+ toolName: "read",
3679
+ args: { file_path: "/tmp/a.ts" },
3680
+ result: { text: "contents" },
3681
+ expect: {
3682
+ kind: "read",
3683
+ title: "/tmp/a.ts",
3684
+ status: "completed",
3685
+ locations: [{ path: "/tmp/a.ts" }],
3686
+ },
3687
+ },
3688
+ {
3689
+ name: "edit → edit with location",
3690
+ toolName: "edit",
3691
+ args: { file_path: "/tmp/b.ts" },
3692
+ result: { text: "edited" },
3693
+ expect: {
3694
+ kind: "edit",
3695
+ title: "/tmp/b.ts",
3696
+ status: "completed",
3697
+ locations: [{ path: "/tmp/b.ts" }],
3698
+ },
3699
+ },
3700
+ {
3701
+ name: "grep → search",
3702
+ toolName: "grep",
3703
+ args: { pattern: "foo" },
3704
+ result: { text: "match" },
3705
+ expect: {
3706
+ kind: "search",
3707
+ title: "foo",
3708
+ status: "completed",
3709
+ locations: [],
3710
+ },
3711
+ },
3712
+ {
3713
+ name: "ls → read",
3714
+ toolName: "ls",
3715
+ args: { path: "/tmp" },
3716
+ result: { text: "listing" },
3717
+ expect: {
3718
+ kind: "read",
3719
+ title: "/tmp",
3720
+ status: "completed",
3721
+ locations: [{ path: "/tmp" }],
3722
+ },
3723
+ },
3724
+ {
3725
+ name: "find → search",
3726
+ toolName: "find",
3727
+ args: { pattern: "*.ts" },
3728
+ result: { text: "found" },
3729
+ expect: {
3730
+ kind: "search",
3731
+ title: "*.ts",
3732
+ status: "completed",
3733
+ locations: [],
3734
+ },
3735
+ },
3736
+ {
3737
+ name: "web_fetch → fetch",
3738
+ toolName: "web_fetch",
3739
+ args: { url: "https://example.com" },
3740
+ result: { text: "html" },
3741
+ expect: {
3742
+ kind: "fetch",
3743
+ title: "web_fetch",
3744
+ status: "completed",
3745
+ locations: [],
3746
+ },
3747
+ },
3748
+ {
3749
+ name: "Agent → think",
3750
+ toolName: "Agent",
3751
+ args: { prompt: "go" },
3752
+ result: { text: "done" },
3753
+ expect: {
3754
+ kind: "think",
3755
+ title: "Agent",
3756
+ status: "completed",
3757
+ locations: [],
3758
+ },
3759
+ },
3760
+ {
3761
+ name: "unknown tool → other",
3762
+ toolName: "mcp__foo__bar",
3763
+ args: { arg: 1 },
3764
+ result: { text: "ok" },
3765
+ expect: {
3766
+ kind: "other",
3767
+ title: "mcp__foo__bar",
3768
+ status: "completed",
3769
+ locations: [],
3770
+ },
3771
+ },
3772
+ ]
3773
+ for (const c of toolKindMatrix) {
3774
+ it(`replays tool call (${c.name}) as tool_call + terminal tool_call_update`, async () => {
3775
+ const fake = new FakeAgentSession(`loaded-tool-${c.toolName}`)
3776
+ fake.branch = [
3777
+ userTextEntry("go", "u1", null),
3778
+ assistantBlocksEntry(
3779
+ [
3780
+ {
3781
+ type: "toolCall",
3782
+ id: "tc-1",
3783
+ name: c.toolName,
3784
+ arguments: c.args,
3785
+ },
3786
+ ],
3787
+ "a1",
3788
+ "u1",
3789
+ ),
3790
+ toolResultEntry("tc-1", c.toolName, c.result.text, c.result.isError ?? false, "tr1", "a1"),
3791
+ ]
3792
+ const { conn, updates } = makeRecordingConn()
3793
+ const agent = makeAgent(async () => asSession(fake), { conn })
3794
+ await agent.loadSession({
3795
+ sessionId: fake.sessionId,
3796
+ cwd: "/tmp",
3797
+ mcpServers: [],
3798
+ })
3799
+ const seq = replayOnly(updates).map((u) => u.update.sessionUpdate)
3800
+ expect(seq).toEqual(["user_message_chunk", "tool_call", "tool_call_update"])
3801
+
3802
+ const replay = replayOnly(updates)
3803
+ const toolCall = replay[1].update as Record<string, unknown>
3804
+ expect(toolCall).toMatchObject({
3805
+ sessionUpdate: "tool_call",
3806
+ toolCallId: "tc-1",
3807
+ kind: c.expect.kind,
3808
+ title: c.expect.title,
3809
+ status: c.expect.status,
3810
+ locations: c.expect.locations,
3811
+ rawInput: c.args,
3812
+ })
3813
+ const update = replay[2].update as Record<string, unknown>
3814
+ expect(update).toMatchObject({
3815
+ sessionUpdate: "tool_call_update",
3816
+ toolCallId: "tc-1",
3817
+ status: c.expect.status,
3818
+ })
3819
+ const content = (update as { content: Array<{ content: { text: string } }> }).content
3820
+ expect(content[0].content.text).toBe(c.result.text)
3821
+ })
3822
+ }
3823
+
3824
+ it("replays a denied/failed tool call with status failed and the persisted error content", async () => {
3825
+ const fake = new FakeAgentSession("loaded-tool-fail")
3826
+ fake.branch = [
3827
+ userTextEntry("go", "u1", null),
3828
+ assistantBlocksEntry(
3829
+ [
3830
+ {
3831
+ type: "toolCall",
3832
+ id: "tc-deny",
3833
+ name: "bash",
3834
+ arguments: { command: "rm -rf /" },
3835
+ },
3836
+ ],
3837
+ "a1",
3838
+ "u1",
3839
+ ),
3840
+ toolResultEntry("tc-deny", "bash", "permission denied", true, "tr1", "a1"),
3841
+ ]
3842
+ const { conn, updates } = makeRecordingConn()
3843
+ const agent = makeAgent(async () => asSession(fake), { conn })
3844
+ await agent.loadSession({
3845
+ sessionId: "loaded-tool-fail",
3846
+ cwd: "/tmp",
3847
+ mcpServers: [],
3848
+ })
3849
+ const replay = replayOnly(updates)
3850
+ const toolCall = replay[1].update as { status?: string }
3851
+ const update = replay[2].update as {
3852
+ status?: string
3853
+ content: Array<{ content: { text: string } }>
3854
+ }
3855
+ expect(toolCall.status).toBe("failed")
3856
+ expect(update.status).toBe("failed")
3857
+ expect(update.content[0].content.text).toBe("permission denied")
3858
+ })
3859
+
3860
+ it("replays an interrupted tool call (no persisted result) as failed with empty content", async () => {
3861
+ // Session was killed mid tool execution; the tool result never landed in
3862
+ // the JSONL. "failed" is the only honest terminal status we can synthesize
3863
+ // — leaving it in_progress would hang the client's spinner forever.
3864
+ const fake = new FakeAgentSession("loaded-tool-orphan")
3865
+ fake.branch = [
3866
+ userTextEntry("go", "u1", null),
3867
+ assistantBlocksEntry(
3868
+ [
3869
+ {
3870
+ type: "toolCall",
3871
+ id: "tc-orphan",
3872
+ name: "bash",
3873
+ arguments: { command: "sleep 100" },
3874
+ },
3875
+ ],
3876
+ "a1",
3877
+ "u1",
3878
+ ),
3879
+ ]
3880
+ const { conn, updates } = makeRecordingConn()
3881
+ const agent = makeAgent(async () => asSession(fake), { conn })
3882
+ await agent.loadSession({
3883
+ sessionId: "loaded-tool-orphan",
3884
+ cwd: "/tmp",
3885
+ mcpServers: [],
3886
+ })
3887
+ expect(replayOnly(updates).map((u) => u.update.sessionUpdate)).toEqual([
3888
+ "user_message_chunk",
3889
+ "tool_call",
3890
+ "tool_call_update",
3891
+ ])
3892
+ const replay = replayOnly(updates)
3893
+ const toolCall = replay[1].update as { status?: string }
3894
+ const update = replay[2].update as { status?: string; content: unknown[] }
3895
+ expect(toolCall.status).toBe("failed")
3896
+ expect(update.status).toBe("failed")
3897
+ expect(update.content).toEqual([])
3898
+ })
3899
+
3900
+ it("replays thinking blocks as agent_thought_chunk with raw text (no ANSI)", async () => {
3901
+ const fake = new FakeAgentSession("loaded-thinking")
3902
+ fake.branch = [
3903
+ userTextEntry("go", "u1", null),
3904
+ assistantBlocksEntry([{ type: "thinking", thinking: "considering options" }], "a1", "u1"),
3905
+ ]
3906
+ const { conn, updates } = makeRecordingConn()
3907
+ const agent = makeAgent(async () => asSession(fake), { conn })
3908
+ await agent.loadSession({
3909
+ sessionId: "loaded-thinking",
3910
+ cwd: "/tmp",
3911
+ mcpServers: [],
3912
+ })
3913
+ const thought = updates.find((u) => u.update.sessionUpdate === "agent_thought_chunk")
3914
+ expect(thought).toBeDefined()
3915
+ const content = (thought?.update as { content: { type: string; text: string } }).content
3916
+ expect(content.text).toBe("considering options")
3917
+ // No ANSI escape codes — filterThinkingForDisplay returns dimmed text
3918
+ // for live TUI rendering, but ACP clients can't render escapes. Replay
3919
+ // uses the helper as a yes/no predicate and emits the raw thinking.
3920
+ expect(content.text.includes("\x1b[")).toBe(false)
3921
+ })
3922
+
3923
+ it("skips thinking blocks when hideThinkingBlock is enabled (shared with hide-thinking extension)", async () => {
3924
+ // Same redaction rule the live TUI uses — verified by sharing
3925
+ // filterThinkingForDisplay across both code paths so a setting flip
3926
+ // doesn't drift between live and replay.
3927
+ _setHideThinking(true)
3928
+ try {
3929
+ const fake = new FakeAgentSession("loaded-thinking-hidden")
3930
+ fake.branch = [
3931
+ userTextEntry("go", "u1", null),
3932
+ assistantBlocksEntry([{ type: "thinking", thinking: "considering options" }], "a1", "u1"),
3933
+ ]
3934
+ const { conn, updates } = makeRecordingConn()
3935
+ const agent = makeAgent(async () => asSession(fake), { conn })
3936
+ await agent.loadSession({
3937
+ sessionId: "loaded-thinking-hidden",
3938
+ cwd: "/tmp",
3939
+ mcpServers: [],
3940
+ })
3941
+ expect(updates.find((u) => u.update.sessionUpdate === "agent_thought_chunk")).toBeUndefined()
3942
+ } finally {
3943
+ _resetHideThinking()
3944
+ }
3945
+ })
3946
+
3947
+ it("skips redacted thinking blocks even when hideThinkingBlock is off", async () => {
3948
+ // Redacted thinking has only an opaque encrypted payload (in
3949
+ // thinkingSignature) for multi-turn provider continuity — no plaintext
3950
+ // to surface to the user.
3951
+ const fake = new FakeAgentSession("loaded-thinking-redacted")
3952
+ fake.branch = [
3953
+ userTextEntry("go", "u1", null),
3954
+ assistantBlocksEntry(
3955
+ [
3956
+ {
3957
+ type: "thinking",
3958
+ thinking: "ignored",
3959
+ redacted: true,
3960
+ thinkingSignature: "opaque",
3961
+ },
3962
+ ],
3963
+ "a1",
3964
+ "u1",
3965
+ ),
3966
+ ]
3967
+ const { conn, updates } = makeRecordingConn()
3968
+ const agent = makeAgent(async () => asSession(fake), { conn })
3969
+ await agent.loadSession({
3970
+ sessionId: "loaded-thinking-redacted",
3971
+ cwd: "/tmp",
3972
+ mcpServers: [],
3973
+ })
3974
+ expect(updates.find((u) => u.update.sessionUpdate === "agent_thought_chunk")).toBeUndefined()
3975
+ })
3976
+
3977
+ it("emits zero notifications for compaction / branch_summary / model_change / custom entries", async () => {
3978
+ // Non-message entries are LLM-context artifacts (or, for model_change,
3979
+ // already conveyed via the load response's models field). Surfacing
3980
+ // them as session updates would make Zed's transcript UI churn through
3981
+ // historical state changes the user never saw the first time around.
3982
+ const fake = new FakeAgentSession("loaded-skip-only")
3983
+ fake.branch = [
3984
+ {
3985
+ type: "model_change",
3986
+ id: "mc1",
3987
+ parentId: null,
3988
+ timestamp: "x",
3989
+ provider: "p",
3990
+ modelId: "m",
3991
+ },
3992
+ {
3993
+ type: "compaction",
3994
+ id: "c1",
3995
+ parentId: "mc1",
3996
+ timestamp: "x",
3997
+ summary: "snip",
3998
+ firstKeptEntryId: "u1",
3999
+ tokensBefore: 0,
4000
+ },
4001
+ {
4002
+ type: "branch_summary",
4003
+ id: "bs1",
4004
+ parentId: "c1",
4005
+ timestamp: "x",
4006
+ summary: "branch",
4007
+ },
4008
+ {
4009
+ type: "custom",
4010
+ id: "cu1",
4011
+ parentId: "bs1",
4012
+ timestamp: "x",
4013
+ payload: { whatever: true },
4014
+ },
4015
+ ]
4016
+ const { conn, updates } = makeRecordingConn()
4017
+ const agent = makeAgent(async () => asSession(fake), { conn })
4018
+ await agent.loadSession({
4019
+ sessionId: "loaded-skip-only",
4020
+ cwd: "/tmp",
4021
+ mcpServers: [],
4022
+ })
4023
+
4024
+ // The only update expected here is a no-op surface commands update
4025
+ expect(updates).toHaveLength(1)
4026
+ expect(updates[0].update.sessionUpdate).toEqual("available_commands_update")
4027
+ })
4028
+
4029
+ it("replays a mixed transcript end-to-end (text, thinking, tool, skipped entries, follow-up text)", async () => {
4030
+ const fake = new FakeAgentSession("loaded-mixed")
4031
+ fake.branch = [
4032
+ userTextEntry("question", "u1", null),
4033
+ assistantBlocksEntry(
4034
+ [
4035
+ { type: "text", text: "let me check" },
4036
+ { type: "thinking", thinking: "weighing options" },
4037
+ {
4038
+ type: "toolCall",
4039
+ id: "tc-1",
4040
+ name: "bash",
4041
+ arguments: { command: "ls" },
4042
+ },
4043
+ ],
4044
+ "a1",
4045
+ "u1",
4046
+ ),
4047
+ toolResultEntry("tc-1", "bash", "file1\nfile2", false, "tr1", "a1"),
4048
+ // Skipped entries scattered through the branch must not break the walker.
4049
+ {
4050
+ type: "model_change",
4051
+ id: "mc1",
4052
+ parentId: "tr1",
4053
+ timestamp: "x",
4054
+ provider: "p",
4055
+ modelId: "m",
4056
+ },
4057
+ {
4058
+ type: "compaction",
4059
+ id: "c1",
4060
+ parentId: "mc1",
4061
+ timestamp: "x",
4062
+ summary: "snip",
4063
+ firstKeptEntryId: "u1",
4064
+ tokensBefore: 0,
4065
+ },
4066
+ assistantTextEntry("here is what I found", "a2", "c1"),
4067
+ ]
4068
+ const { conn, updates } = makeRecordingConn()
4069
+ const agent = makeAgent(async () => asSession(fake), { conn })
4070
+ await agent.loadSession({
4071
+ sessionId: "loaded-mixed",
4072
+ cwd: "/tmp",
4073
+ mcpServers: [],
4074
+ })
4075
+ // Order is significant: tool_call must precede tool_call_update, and
4076
+ // the post-skipped-entries assistant text must land last.
4077
+ expect(updates.map((u) => u.update.sessionUpdate)).toEqual([
4078
+ "user_message_chunk",
4079
+ "agent_message_chunk",
4080
+ "agent_thought_chunk",
4081
+ "tool_call",
4082
+ "tool_call_update",
4083
+ "agent_message_chunk",
4084
+ "available_commands_update",
4085
+ ])
4086
+ })
4087
+
4088
+ it("does not deliver synthetic agent_* events to session subscribers during replay", async () => {
4089
+ // Acceptance criterion from the plan: extensions registered on a loaded
4090
+ // session must not see the historical turns as if they were live —
4091
+ // otherwise telemetry/loop-guard/etc. would double-count. Replay sends
4092
+ // notifications straight to conn.sessionUpdate, never via emit().
4093
+ const fake = new FakeAgentSession("loaded-no-events")
4094
+ fake.branch = [
4095
+ userTextEntry("hi", "u1", null),
4096
+ assistantBlocksEntry(
4097
+ [
4098
+ { type: "text", text: "hello" },
4099
+ { type: "thinking", thinking: "thinking" },
4100
+ {
4101
+ type: "toolCall",
4102
+ id: "tc-1",
4103
+ name: "bash",
4104
+ arguments: { command: "ls" },
4105
+ },
4106
+ ],
4107
+ "a1",
4108
+ "u1",
4109
+ ),
4110
+ toolResultEntry("tc-1", "bash", "out", false, "tr1", "a1"),
4111
+ ]
4112
+ // Pre-subscribe a counter BEFORE loadSession so it sits alongside the
4113
+ // agent's own subscriber; if replay went through the event emitter we'd
4114
+ // see agent_start / message_update / tool_execution_* / agent_end here.
4115
+ let extensionEventCount = 0
4116
+ fake.subscribe(() => {
4117
+ extensionEventCount++
4118
+ })
4119
+ const agent = makeAgent(async () => asSession(fake))
4120
+ await agent.loadSession({
4121
+ sessionId: "loaded-no-events",
4122
+ cwd: "/tmp",
4123
+ mcpServers: [],
4124
+ })
4125
+ expect(extensionEventCount).toBe(0)
4126
+ })
4127
+
4128
+ it("replays a 200-turn session well within a generous bound (regression guard)", async () => {
4129
+ // Regression guard against quadratic walker behavior. The fake skips
4130
+ // disk I/O and JSON-RPC framing — what's actually under test is that
4131
+ // the walker stays O(N). Bound is loose (3s) because shared CI runners
4132
+ // are noisy; a real regression would blow past it by orders of
4133
+ // magnitude.
4134
+ const fake = new FakeAgentSession("loaded-perf")
4135
+ const branch: unknown[] = []
4136
+ for (let i = 0; i < 200; i++) {
4137
+ branch.push(userTextEntry(`q${i}`, `u${i}`, i === 0 ? null : `a${i - 1}`))
4138
+ branch.push(
4139
+ assistantBlocksEntry(
4140
+ [
4141
+ { type: "text", text: `a${i}` },
4142
+ {
4143
+ type: "toolCall",
4144
+ id: `tc-${i}`,
4145
+ name: "bash",
4146
+ arguments: { command: `echo ${i}` },
4147
+ },
4148
+ ],
4149
+ `a${i}`,
4150
+ `u${i}`,
4151
+ ),
4152
+ )
4153
+ branch.push(toolResultEntry(`tc-${i}`, "bash", `out${i}`, false, `tr-${i}`, `a${i}`))
4154
+ }
4155
+ fake.branch = branch
4156
+ const agent = makeAgent(async () => asSession(fake))
4157
+ const start = Date.now()
4158
+ await agent.loadSession({
4159
+ sessionId: "loaded-perf",
4160
+ cwd: "/tmp",
4161
+ mcpServers: [],
4162
+ })
4163
+ const elapsed = Date.now() - start
4164
+ expect(elapsed).toBeLessThan(3000)
4165
+ })
4166
+ })
4167
+
4168
+ // Ordering regression test: permission flag controller must be registered
4169
+ // BEFORE bindAcpExtensions is called. This ensures that when upstream
4170
+ // bindExtensions() emits session_start, the permissions extension already
4171
+ // has access to the shared controller and doesn't create a duplicate one.
4172
+ describe("permission flag controller registration ordering", () => {
4173
+ it("registers permission flag controller before bindAcpExtensions in newSession", async () => {
4174
+ const ordering: string[] = []
4175
+ const fake = new FakeAgentSession("session-ordering-test")
4176
+
4177
+ fake.bindExtensionsImpl = async () => {
4178
+ // At this point, the permission controller should already be registered
4179
+ const controller = getSessionPermissionFlagController("session-ordering-test")
4180
+ ordering.push(controller ? "controller-present" : "controller-missing")
4181
+ ordering.push("bindAcpExtensions-called")
4182
+ }
4183
+
4184
+ const factory: AcpSessionFactory = async () => asSession(fake)
4185
+ const agent = new IkieAcpAgent(makeConn(), {
4186
+ extensionFactories: [],
4187
+ agentDir: "/tmp/fake-agent-dir",
4188
+ sessionFactory: factory,
4189
+ })
4190
+
4191
+ await agent.newSession({ cwd: "/tmp", mcpServers: [] })
4192
+
4193
+ // The controller should be present when bindAcpExtensions is called
4194
+ expect(ordering).toEqual(["controller-present", "bindAcpExtensions-called"])
4195
+ // And should still be registered after newSession completes
4196
+ expect(getSessionPermissionFlagController("session-ordering-test")).toBeDefined()
4197
+
4198
+ await agent.shutdown()
4199
+ })
4200
+
4201
+ it("registers permission flag controller before bindAcpExtensions in loadSessionFresh", async () => {
4202
+ const ordering: string[] = []
4203
+ const fake = new FakeAgentSession("load-session-ordering")
4204
+ // Add a minimal branch for replay
4205
+ fake.branch = [
4206
+ {
4207
+ type: "message",
4208
+ message: { role: "user", content: "test" },
4209
+ timestamp: Date.now(),
4210
+ },
4211
+ ]
4212
+
4213
+ fake.bindExtensionsImpl = async () => {
4214
+ const controller = getSessionPermissionFlagController("load-session-ordering")
4215
+ ordering.push(controller ? "controller-present" : "controller-missing")
4216
+ ordering.push("bindAcpExtensions-called")
4217
+ }
4218
+
4219
+ let loaderCallCount = 0
4220
+ const loader: AcpSessionLoader = async () => {
4221
+ loaderCallCount++
4222
+ return asSession(fake)
4223
+ }
4224
+
4225
+ const agent = new IkieAcpAgent(makeConn(), {
4226
+ extensionFactories: [],
4227
+ agentDir: "/tmp/fake-agent-dir",
4228
+ sessionLoader: loader,
4229
+ })
4230
+
4231
+ await agent.loadSession({ sessionId: "load-session-ordering", cwd: "/tmp", mcpServers: [] })
4232
+
4233
+ expect(loaderCallCount).toBe(1)
4234
+ expect(ordering).toEqual(["controller-present", "bindAcpExtensions-called"])
4235
+ expect(getSessionPermissionFlagController("load-session-ordering")).toBeDefined()
4236
+
4237
+ await agent.shutdown()
4238
+ })
4239
+
4240
+ it("unregisters permission flag controller when bindAcpExtensions throws in newSession", async () => {
4241
+ const fake = new FakeAgentSession("session-bind-failure")
4242
+ // Verify controller is registered during the call (before bind fails)
4243
+ let controllerDuringBind: ReturnType<typeof getSessionPermissionFlagController>
4244
+ fake.bindExtensionsImpl = async () => {
4245
+ controllerDuringBind = getSessionPermissionFlagController("session-bind-failure")
4246
+ throw new Error("bindExtensions failed")
4247
+ }
4248
+
4249
+ const factory: AcpSessionFactory = async () => asSession(fake)
4250
+ const agent = new IkieAcpAgent(makeConn(), {
4251
+ extensionFactories: [],
4252
+ agentDir: "/tmp/fake-agent-dir",
4253
+ sessionFactory: factory,
4254
+ })
4255
+
4256
+ await expect(agent.newSession({ cwd: "/tmp", mcpServers: [] })).rejects.toThrow(/bindExtensions failed/)
4257
+
4258
+ // Controller should have been present during bind
4259
+ expect(controllerDuringBind).toBeDefined()
4260
+ // But should be unregistered after the catch block runs
4261
+ expect(getSessionPermissionFlagController("session-bind-failure")).toBeUndefined()
4262
+ expect(fake.disposed).toBe(true)
4263
+ })
4264
+
4265
+ it("unregisters permission flag controller when bindAcpExtensions throws in loadSession", async () => {
4266
+ const fake = new FakeAgentSession("load-bind-failure")
4267
+ fake.branch = [
4268
+ {
4269
+ type: "message",
4270
+ message: { role: "user", content: "test" },
4271
+ timestamp: Date.now(),
4272
+ },
4273
+ ]
4274
+ fake.bindExtensionsImpl = async () => {
4275
+ throw new Error("bindExtensions failed in load")
4276
+ }
4277
+
4278
+ const loader: AcpSessionLoader = async () => asSession(fake)
4279
+ const agent = new IkieAcpAgent(makeConn(), {
4280
+ extensionFactories: [],
4281
+ agentDir: "/tmp/fake-agent-dir",
4282
+ sessionLoader: loader,
4283
+ })
4284
+
4285
+ await expect(agent.loadSession({ sessionId: "load-bind-failure", cwd: "/tmp", mcpServers: [] })).rejects.toThrow(
4286
+ /bindExtensions failed in load/,
4287
+ )
4288
+
4289
+ expect(getSessionPermissionFlagController("load-bind-failure")).toBeUndefined()
4290
+ expect(fake.disposed).toBe(true)
4291
+ })
4292
+
4293
+ it("provides a working controller that can get and set mode during bindAcpExtensions", async () => {
4294
+ const fake = new FakeAgentSession("session-controller-functional")
4295
+ let capturedMode: { mode: string; source: string } | undefined
4296
+
4297
+ fake.bindExtensionsImpl = async () => {
4298
+ const controller = getSessionPermissionFlagController("session-controller-functional")
4299
+ if (controller) {
4300
+ // Verify the controller works - get initial mode
4301
+ capturedMode = controller.getMode()
4302
+ // Set a new mode
4303
+ controller.setMode("plan", "user")
4304
+ }
4305
+ }
4306
+
4307
+ const factory: AcpSessionFactory = async () => asSession(fake)
4308
+ const agent = new IkieAcpAgent(makeConn(), {
4309
+ extensionFactories: [],
4310
+ agentDir: "/tmp/fake-agent-dir",
4311
+ sessionFactory: factory,
4312
+ })
4313
+
4314
+ await agent.newSession({ cwd: "/tmp", mcpServers: [] })
4315
+
4316
+ // The controller should be present and functional during bindExtensions
4317
+ expect(capturedMode).toBeDefined()
4318
+ expect(capturedMode?.mode).toBeDefined()
4319
+ expect(capturedMode?.source).toBeDefined()
4320
+
4321
+ // After setMode in bindExtensions, the controller should have the new mode "plan"
4322
+ const finalController = getSessionPermissionFlagController("session-controller-functional")
4323
+ expect(finalController?.getMode()).toEqual({ mode: "plan", source: "user" })
4324
+
4325
+ await agent.shutdown()
4326
+ })
4327
+ })
4328
+
4329
+ describe("shouldEmitThinking", () => {
4330
+ it("returns true by default (hideThinkingBlock unset)", () => {
4331
+ _resetHideThinking()
4332
+ expect(shouldEmitThinking("anything")).toBe(true)
4333
+ })
4334
+ it("returns false when hideThinkingBlock is enabled", () => {
4335
+ _setHideThinking(true)
4336
+ try {
4337
+ expect(shouldEmitThinking("anything")).toBe(false)
4338
+ } finally {
4339
+ _resetHideThinking()
4340
+ }
4341
+ })
4342
+ it("does not break when the persisted thinking text contains a literal </think>", () => {
4343
+ // Regression: a previous version probed filterThinkingForDisplay with a
4344
+ // synthetic <think>${thinking}</think> wrapper. Models self-quoting
4345
+ // "</think>" closed the wrapper early and the inner text leaked, making
4346
+ // the predicate non-deterministic. Reading the setting directly avoids
4347
+ // the round-trip entirely.
4348
+ _resetHideThinking()
4349
+ const haunted = "I'll stop now. </think> trailing"
4350
+ expect(shouldEmitThinking(haunted)).toBe(true)
4351
+ _setHideThinking(true)
4352
+ try {
4353
+ expect(shouldEmitThinking(haunted)).toBe(false)
4354
+ } finally {
4355
+ _resetHideThinking()
4356
+ }
4357
+ })
4358
+ })
4359
+
4360
+ describe("stripAnsi", () => {
4361
+ it("returns unchanged text when no ANSI escapes are present", () => {
4362
+ expect(stripAnsi("plain text")).toBe("plain text")
4363
+ })
4364
+ it("removes CSI sequences (color, dim, reset) without touching surrounding text", () => {
4365
+ expect(stripAnsi("\x1b[2mfoo\x1b[22m bar")).toBe("foo bar")
4366
+ expect(stripAnsi("\x1b[31mred\x1b[0m and \x1b[1mbold\x1b[0m")).toBe("red and bold")
4367
+ })
4368
+ it("leaves a stray ESC byte (no full sequence) untouched", () => {
4369
+ // Conservative scrub: only `\x1b[…<letter>` is dropped. A bare ESC
4370
+ // without a CSI body isn't styling and shouldn't be mangled.
4371
+ expect(stripAnsi("plain\x1bbody")).toBe("plain\x1bbody")
4372
+ })
4373
+ })
4374
+
4375
+ describe("userMessageText", () => {
4376
+ it("returns string content unchanged for user messages", () => {
4377
+ expect(userMessageText("hello world")).toBe("hello world")
4378
+ })
4379
+ it("joins text blocks and skips images for user messages", () => {
4380
+ expect(
4381
+ userMessageText([
4382
+ { type: "text", text: "hi " },
4383
+ { type: "image", data: "x", mimeType: "image/png" },
4384
+ { type: "text", text: "there" },
4385
+ ]),
4386
+ ).toBe("hi there")
4387
+ })
4388
+ it("returns empty string for null / non-array user content", () => {
4389
+ expect(userMessageText(null)).toBe("")
4390
+ expect(userMessageText(42)).toBe("")
4391
+ })
4392
+ })