supipowers 1.5.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (340) hide show
  1. package/README.md +14 -8
  2. package/bin/install.mjs +20 -5
  3. package/bin/install.ts +95 -0
  4. package/package.json +8 -4
  5. package/skills/context-mode/SKILL.md +17 -10
  6. package/skills/harness/SKILL.md +94 -0
  7. package/skills/ui-design/SKILL.md +63 -0
  8. package/skills/ui-design/sub-agent-templates/component-builder.md +29 -0
  9. package/skills/ui-design/sub-agent-templates/design-critic.md +46 -0
  10. package/skills/ui-design/sub-agent-templates/pencil/component-builder.md +29 -0
  11. package/skills/ui-design/sub-agent-templates/pencil/design-critic.md +42 -0
  12. package/skills/ui-design/sub-agent-templates/pencil/section-assembler.md +27 -0
  13. package/skills/ui-design/sub-agent-templates/section-assembler.md +27 -0
  14. package/skills/ultraplan-discover/SKILL.md +96 -0
  15. package/skills/ultraplan-intake/SKILL.md +89 -0
  16. package/skills/ultraplan-research/SKILL.md +129 -0
  17. package/skills/ultraplan-review/SKILL.md +86 -0
  18. package/skills/ultraplan-review-scope/SKILL.md +111 -0
  19. package/skills/ultraplan-review-structure/SKILL.md +120 -0
  20. package/skills/ultraplan-review-tdd/SKILL.md +142 -0
  21. package/skills/ultraplan-scout/SKILL.md +110 -0
  22. package/skills/ultraplan-synthesize/SKILL.md +124 -0
  23. package/src/{quality/ai-session.ts → ai/final-message.ts} +27 -0
  24. package/src/ai/schema-text.ts +129 -0
  25. package/src/ai/structured-output.ts +274 -0
  26. package/src/ai/template.ts +27 -0
  27. package/src/bootstrap.ts +63 -28
  28. package/src/commands/agents.ts +149 -45
  29. package/src/commands/ai-review.ts +251 -30
  30. package/src/commands/clear.ts +434 -0
  31. package/src/commands/commit.ts +1 -0
  32. package/src/commands/config.ts +242 -44
  33. package/src/commands/context.ts +55 -28
  34. package/src/commands/doctor.ts +234 -6
  35. package/src/commands/fix-pr.ts +306 -131
  36. package/src/commands/generate.ts +111 -21
  37. package/src/commands/memory.ts +192 -0
  38. package/src/commands/model-picker.ts +28 -21
  39. package/src/commands/model.ts +19 -9
  40. package/src/commands/optimize-context.ts +408 -29
  41. package/src/commands/plan.ts +2 -0
  42. package/src/commands/qa.ts +312 -137
  43. package/src/commands/release.ts +259 -76
  44. package/src/commands/review.ts +293 -59
  45. package/src/commands/status.ts +200 -13
  46. package/src/commands/supi.ts +3 -35
  47. package/src/commands/ui-design.ts +394 -0
  48. package/src/commands/ultraplan.ts +1518 -0
  49. package/src/commands/update.ts +86 -0
  50. package/src/config/defaults.ts +62 -0
  51. package/src/config/loader.ts +448 -60
  52. package/src/config/schema.ts +108 -2
  53. package/src/context/optimizer.ts +25 -33
  54. package/src/context/rule-renderer.ts +223 -0
  55. package/src/context/savings.ts +258 -0
  56. package/src/context/startup-check.ts +380 -0
  57. package/src/context/startup-optimizer.ts +355 -0
  58. package/src/context/tokenignore.ts +146 -0
  59. package/src/context-mode/cache-handle.ts +49 -0
  60. package/src/context-mode/cache-preview.ts +71 -0
  61. package/src/context-mode/cache-store.ts +738 -0
  62. package/src/context-mode/compressor.ts +131 -26
  63. package/src/context-mode/dedup.ts +108 -0
  64. package/src/context-mode/detector.ts +35 -4
  65. package/src/context-mode/event-extractor.ts +14 -12
  66. package/src/context-mode/event-store.ts +91 -36
  67. package/src/context-mode/hooks.ts +798 -56
  68. package/src/context-mode/knowledge/store.ts +255 -11
  69. package/src/context-mode/memory-store.ts +325 -0
  70. package/src/context-mode/metrics-recorder.ts +158 -0
  71. package/src/context-mode/metrics-store.ts +765 -0
  72. package/src/context-mode/model.ts +24 -0
  73. package/src/context-mode/processor-keys.ts +29 -0
  74. package/src/context-mode/processors/build.ts +66 -0
  75. package/src/context-mode/processors/docker.ts +57 -0
  76. package/src/context-mode/processors/git.ts +111 -0
  77. package/src/context-mode/processors/json.ts +112 -0
  78. package/src/context-mode/processors/k8s.ts +67 -0
  79. package/src/context-mode/processors/lint.ts +67 -0
  80. package/src/context-mode/processors/log.ts +86 -0
  81. package/src/context-mode/processors/registry.ts +116 -0
  82. package/src/context-mode/processors/test-runner.ts +102 -0
  83. package/src/context-mode/processors/types.ts +20 -0
  84. package/src/context-mode/repomap.ts +400 -0
  85. package/src/context-mode/routing.ts +97 -24
  86. package/src/context-mode/sandbox/runners.ts +5 -1
  87. package/src/context-mode/snapshot-builder.ts +106 -11
  88. package/src/context-mode/source-hash.ts +173 -0
  89. package/src/context-mode/tool-name.ts +11 -0
  90. package/src/context-mode/tools.ts +654 -22
  91. package/src/context-mode/web/fetcher.ts +31 -12
  92. package/src/debug/logger.ts +2 -1
  93. package/src/deps/registry.ts +1 -1
  94. package/src/discipline/failure-summarizer.ts +170 -0
  95. package/src/discipline/failure-taxonomy.ts +131 -0
  96. package/src/discipline/workflow-invariants.ts +125 -0
  97. package/src/discovery/index.ts +31 -0
  98. package/src/discovery/lsp.ts +87 -0
  99. package/src/discovery/rank.ts +144 -0
  100. package/src/discovery/sources.ts +89 -0
  101. package/src/discovery/workflow.ts +87 -0
  102. package/src/docs/contracts.ts +39 -0
  103. package/src/docs/drift.ts +117 -87
  104. package/src/fix-pr/assessment.ts +200 -0
  105. package/src/fix-pr/contracts.ts +47 -0
  106. package/src/fix-pr/fetch-comments.ts +80 -0
  107. package/src/fix-pr/prompt-builder.ts +58 -40
  108. package/src/fix-pr/scripts/exec.ts +34 -0
  109. package/src/fix-pr/scripts/trigger-review.ts +106 -0
  110. package/src/fix-pr/scripts/wait-and-check.ts +108 -0
  111. package/src/fix-pr/types.ts +4 -0
  112. package/src/git/branch-finish.ts +5 -0
  113. package/src/git/commit-contract.ts +83 -0
  114. package/src/git/commit.ts +121 -184
  115. package/src/git/status.ts +62 -8
  116. package/src/harness/anti_slop/architecture-parser.ts +210 -0
  117. package/src/harness/anti_slop/backend-factory.ts +30 -0
  118. package/src/harness/anti_slop/backend.ts +140 -0
  119. package/src/harness/anti_slop/desloppify-adapter.ts +319 -0
  120. package/src/harness/anti_slop/fallow-adapter.ts +305 -0
  121. package/src/harness/anti_slop/installer.ts +227 -0
  122. package/src/harness/anti_slop/queue.ts +216 -0
  123. package/src/harness/anti_slop/recommend.ts +84 -0
  124. package/src/harness/anti_slop/score.ts +180 -0
  125. package/src/harness/anti_slop/synthetic-edit-test.ts +128 -0
  126. package/src/harness/artifacts/agents-md.ts +88 -0
  127. package/src/harness/artifacts/checks-wiring.ts +57 -0
  128. package/src/harness/artifacts/docs-tree.ts +79 -0
  129. package/src/harness/artifacts/lint-configs.ts +136 -0
  130. package/src/harness/artifacts/review-agents.ts +67 -0
  131. package/src/harness/bare-entry.ts +108 -0
  132. package/src/harness/command.ts +1010 -0
  133. package/src/harness/default-agents/design.md +23 -0
  134. package/src/harness/default-agents/discover.md +18 -0
  135. package/src/harness/default-agents/implement.md +24 -0
  136. package/src/harness/default-agents/plan.md +19 -0
  137. package/src/harness/default-agents/research.md +21 -0
  138. package/src/harness/default-agents/validate.md +22 -0
  139. package/src/harness/gc/reporter.ts +28 -0
  140. package/src/harness/gc/runner.ts +136 -0
  141. package/src/harness/hooks/layer-context-inject.ts +155 -0
  142. package/src/harness/hooks/post-session-sweep.ts +130 -0
  143. package/src/harness/hooks/pre-edit-dupe-probe.ts +224 -0
  144. package/src/harness/hooks/register.ts +118 -0
  145. package/src/harness/model.ts +117 -0
  146. package/src/harness/pipeline.ts +348 -0
  147. package/src/harness/project-paths.ts +235 -0
  148. package/src/harness/stage-runner.ts +107 -0
  149. package/src/harness/stages/design.ts +386 -0
  150. package/src/harness/stages/discover.ts +454 -0
  151. package/src/harness/stages/implement.ts +162 -0
  152. package/src/harness/stages/plan.ts +335 -0
  153. package/src/harness/stages/research.ts +263 -0
  154. package/src/harness/stages/validate.ts +684 -0
  155. package/src/harness/storage.ts +467 -0
  156. package/src/harness/tools.ts +426 -0
  157. package/src/lsp/bridge.ts +56 -95
  158. package/src/lsp/capabilities.ts +108 -0
  159. package/src/lsp/contracts.ts +35 -0
  160. package/src/lsp/detector.ts +8 -12
  161. package/src/markdown-frontmatter.ts +68 -0
  162. package/src/mempalace/bridge.ts +129 -0
  163. package/src/mempalace/config.ts +75 -0
  164. package/src/mempalace/format.ts +163 -0
  165. package/src/mempalace/hooks.ts +370 -0
  166. package/src/mempalace/installer-helper.ts +194 -0
  167. package/src/mempalace/python/mempalace_bridge.py +440 -0
  168. package/src/mempalace/runtime.ts +565 -0
  169. package/src/mempalace/schema.ts +264 -0
  170. package/src/mempalace/session-summary.ts +198 -0
  171. package/src/mempalace/tool.ts +186 -0
  172. package/src/mempalace/uv.ts +256 -0
  173. package/src/migrate/runner.ts +354 -0
  174. package/src/planning/approval-flow.ts +206 -9
  175. package/src/planning/plan-writer-prompt.ts +4 -3
  176. package/src/planning/planning-ask-tool.ts +39 -0
  177. package/src/planning/render-markdown.ts +74 -0
  178. package/src/planning/spec.ts +42 -0
  179. package/src/planning/system-prompt.ts +11 -8
  180. package/src/planning/validate.ts +84 -0
  181. package/src/platform/omp.ts +15 -2
  182. package/src/platform/system-prompt.ts +37 -0
  183. package/src/platform/test-utils.ts +3 -0
  184. package/src/platform/types.ts +6 -1
  185. package/src/qa/config.ts +12 -6
  186. package/src/qa/detect-app-type.ts +13 -6
  187. package/src/qa/matrix.ts +12 -6
  188. package/src/qa/prompt-builder.ts +28 -30
  189. package/src/qa/scripts/dev-server-utils.ts +72 -0
  190. package/src/qa/scripts/run-e2e-tests.ts +226 -0
  191. package/src/qa/scripts/start-dev-server.ts +138 -0
  192. package/src/qa/scripts/stop-dev-server.ts +77 -0
  193. package/src/qa/session.ts +13 -7
  194. package/src/quality/ai-setup.ts +27 -25
  195. package/src/quality/contracts.ts +34 -0
  196. package/src/quality/gates/ai-review.ts +20 -58
  197. package/src/quality/gates/command.ts +249 -46
  198. package/src/quality/review-gates.ts +18 -2
  199. package/src/quality/runner.ts +63 -22
  200. package/src/quality/schemas.ts +37 -2
  201. package/src/quality/setup.ts +96 -16
  202. package/src/release/changelog.ts +1 -1
  203. package/src/release/channels/custom.ts +13 -3
  204. package/src/release/channels/types.ts +5 -0
  205. package/src/release/contracts.ts +90 -0
  206. package/src/release/executor.ts +122 -45
  207. package/src/release/prompt.ts +18 -2
  208. package/src/release/targets.ts +86 -0
  209. package/src/release/version.ts +96 -71
  210. package/src/review/agent-loader.ts +298 -127
  211. package/src/review/fixer.ts +10 -6
  212. package/src/review/multi-agent-runner.ts +115 -14
  213. package/src/review/output.ts +12 -139
  214. package/src/review/runner.ts +12 -6
  215. package/src/review/scope.ts +144 -24
  216. package/src/review/types.ts +11 -20
  217. package/src/review/validator.ts +12 -6
  218. package/src/storage/fix-pr-sessions.ts +21 -14
  219. package/src/storage/plans.ts +14 -5
  220. package/src/storage/qa-sessions.ts +25 -19
  221. package/src/storage/reliability-metrics.ts +180 -0
  222. package/src/storage/reports.ts +8 -7
  223. package/src/storage/review-sessions.ts +55 -20
  224. package/src/tool-catalog/active-tool-controller.ts +164 -0
  225. package/src/tool-catalog/active-tool-planner.ts +212 -0
  226. package/src/tool-catalog/tool-groups.ts +102 -0
  227. package/src/types.ts +1401 -5
  228. package/src/ui-design/backend-adapter.ts +78 -0
  229. package/src/ui-design/backends/local-html.ts +82 -0
  230. package/src/ui-design/backends/pencil-mcp.ts +111 -0
  231. package/src/ui-design/components-scanner.ts +124 -0
  232. package/src/ui-design/config.ts +55 -0
  233. package/src/ui-design/pen-scanner.ts +95 -0
  234. package/src/ui-design/pen-selector.ts +72 -0
  235. package/src/ui-design/prompt-builder.ts +73 -0
  236. package/src/ui-design/scanner.ts +136 -0
  237. package/src/ui-design/session.ts +974 -0
  238. package/src/ui-design/system-prompt.ts +312 -0
  239. package/src/ui-design/tokens-scanner.ts +181 -0
  240. package/src/ui-design/types.ts +96 -0
  241. package/src/ultraplan/agent-catalog.ts +522 -0
  242. package/src/ultraplan/authoring/agent-catalog.ts +310 -0
  243. package/src/ultraplan/authoring/authoring-tools.ts +552 -0
  244. package/src/ultraplan/authoring/command-handlers.ts +339 -0
  245. package/src/ultraplan/authoring/markdown.ts +510 -0
  246. package/src/ultraplan/authoring/model.ts +162 -0
  247. package/src/ultraplan/authoring/pipeline.ts +319 -0
  248. package/src/ultraplan/authoring/stage-runner.ts +141 -0
  249. package/src/ultraplan/authoring/stages/approve.ts +249 -0
  250. package/src/ultraplan/authoring/stages/discover.ts +289 -0
  251. package/src/ultraplan/authoring/stages/intake.ts +203 -0
  252. package/src/ultraplan/authoring/stages/research.ts +399 -0
  253. package/src/ultraplan/authoring/stages/review.ts +333 -0
  254. package/src/ultraplan/authoring/stages/scout.ts +188 -0
  255. package/src/ultraplan/authoring/stages/synthesize.ts +348 -0
  256. package/src/ultraplan/authoring/storage.ts +594 -0
  257. package/src/ultraplan/authoring/synth-gate.ts +165 -0
  258. package/src/ultraplan/authoring-draft.ts +653 -0
  259. package/src/ultraplan/authoring-persist.ts +180 -0
  260. package/src/ultraplan/authoring-tool.ts +608 -0
  261. package/src/ultraplan/authoring-wizard.ts +587 -0
  262. package/src/ultraplan/batch/merge.ts +98 -0
  263. package/src/ultraplan/batch/planner.ts +150 -0
  264. package/src/ultraplan/batch/presenter.ts +97 -0
  265. package/src/ultraplan/batch/storage.ts +420 -0
  266. package/src/ultraplan/batch/supervisor.ts +317 -0
  267. package/src/ultraplan/batch/worker.ts +26 -0
  268. package/src/ultraplan/batch/worktree.ts +110 -0
  269. package/src/ultraplan/contracts.ts +1593 -0
  270. package/src/ultraplan/default-agents/authoring/discoverer.md +12 -0
  271. package/src/ultraplan/default-agents/authoring/intake.md +12 -0
  272. package/src/ultraplan/default-agents/authoring/planner.md +12 -0
  273. package/src/ultraplan/default-agents/authoring/researcher.md +12 -0
  274. package/src/ultraplan/default-agents/authoring/scope-checker.md +12 -0
  275. package/src/ultraplan/default-agents/authoring/scout.md +12 -0
  276. package/src/ultraplan/default-agents/authoring/structure-checker.md +12 -0
  277. package/src/ultraplan/default-agents/authoring/tdd-checker.md +12 -0
  278. package/src/ultraplan/default-agents/backend-domain-reviewer.md +10 -0
  279. package/src/ultraplan/default-agents/backend-executor.md +10 -0
  280. package/src/ultraplan/default-agents/backend-stack-reviewer.md +10 -0
  281. package/src/ultraplan/default-agents/backend-tester.md +10 -0
  282. package/src/ultraplan/default-agents/frontend-domain-reviewer.md +10 -0
  283. package/src/ultraplan/default-agents/frontend-executor.md +10 -0
  284. package/src/ultraplan/default-agents/frontend-stack-reviewer.md +10 -0
  285. package/src/ultraplan/default-agents/frontend-tester.md +10 -0
  286. package/src/ultraplan/default-agents/infrastructure-domain-reviewer.md +10 -0
  287. package/src/ultraplan/default-agents/infrastructure-executor.md +10 -0
  288. package/src/ultraplan/default-agents/infrastructure-stack-reviewer.md +10 -0
  289. package/src/ultraplan/default-agents/infrastructure-tester.md +10 -0
  290. package/src/ultraplan/execution/contract.ts +71 -0
  291. package/src/ultraplan/execution/policy.ts +217 -0
  292. package/src/ultraplan/execution/runtime-tools.ts +107 -0
  293. package/src/ultraplan/execution/session-runner.ts +281 -0
  294. package/src/ultraplan/next-router.ts +85 -0
  295. package/src/ultraplan/presenter.ts +359 -0
  296. package/src/ultraplan/project-paths.ts +342 -0
  297. package/src/ultraplan/runtime/active-execution.ts +72 -0
  298. package/src/ultraplan/runtime/apply-mutation.ts +416 -0
  299. package/src/ultraplan/runtime/blockers.ts +243 -0
  300. package/src/ultraplan/runtime/hook-bridge.ts +486 -0
  301. package/src/ultraplan/runtime/launch-context.ts +207 -0
  302. package/src/ultraplan/runtime/migration.ts +524 -0
  303. package/src/ultraplan/runtime/normalize.ts +281 -0
  304. package/src/ultraplan/runtime/proof.ts +260 -0
  305. package/src/ultraplan/runtime/reducer.ts +416 -0
  306. package/src/ultraplan/runtime/repair.ts +251 -0
  307. package/src/ultraplan/runtime/tracker-storage.ts +368 -0
  308. package/src/ultraplan/session-selection.ts +291 -0
  309. package/src/ultraplan/storage.ts +374 -0
  310. package/src/utils/editor.ts +38 -0
  311. package/src/utils/executable.ts +80 -0
  312. package/src/utils/paths.ts +1 -20
  313. package/src/utils/shell.ts +31 -0
  314. package/src/visual/companion.ts +2 -1
  315. package/src/visual/scripts/frame-template.html +60 -0
  316. package/src/visual/scripts/index.js +59 -13
  317. package/src/visual/scripts/package.json +3 -0
  318. package/src/visual/start-server.ts +2 -1
  319. package/src/workspace/git-scope.ts +64 -0
  320. package/src/workspace/locks.ts +23 -0
  321. package/src/workspace/package-manager.ts +117 -0
  322. package/src/workspace/path-mapping.ts +75 -0
  323. package/src/workspace/project-slug.ts +92 -0
  324. package/src/workspace/repo-root.ts +137 -0
  325. package/src/workspace/selector.ts +115 -0
  326. package/src/workspace/state-paths.ts +118 -0
  327. package/src/workspace/targets.ts +313 -0
  328. package/src/fix-pr/scripts/diff-comments.sh +0 -33
  329. package/src/fix-pr/scripts/fetch-pr-comments.sh +0 -25
  330. package/src/fix-pr/scripts/trigger-review.sh +0 -36
  331. package/src/fix-pr/scripts/wait-and-check.sh +0 -37
  332. package/src/qa/scripts/detect-app-type.sh +0 -68
  333. package/src/qa/scripts/discover-routes.sh +0 -143
  334. package/src/qa/scripts/run-e2e-tests.sh +0 -131
  335. package/src/qa/scripts/start-dev-server.sh +0 -46
  336. package/src/qa/scripts/stop-dev-server.sh +0 -36
  337. package/src/review/prompts/fix-output-schema.md +0 -18
  338. package/src/review/prompts/review-output-schema.md +0 -38
  339. package/src/review/template.ts +0 -15
  340. /package/src/{review → ai}/prompts/invalid-output-retry.md +0 -0
@@ -0,0 +1,264 @@
1
+ export const MEMPALACE_ACTIONS = [
2
+ "status",
3
+ "list_wings",
4
+ "list_rooms",
5
+ "get_taxonomy",
6
+ "search",
7
+ "check_duplicate",
8
+ "get_aaak_spec",
9
+ "get_drawer",
10
+ "list_drawers",
11
+ "add_drawer",
12
+ "update_drawer",
13
+ "delete_drawer",
14
+ "kg_query",
15
+ "kg_add",
16
+ "kg_invalidate",
17
+ "kg_timeline",
18
+ "kg_stats",
19
+ "traverse",
20
+ "find_tunnels",
21
+ "graph_stats",
22
+ "create_tunnel",
23
+ "list_tunnels",
24
+ "delete_tunnel",
25
+ "follow_tunnels",
26
+ "diary_write",
27
+ "diary_read",
28
+ "hook_settings",
29
+ "memories_filed_away",
30
+ "reconnect",
31
+ "setup",
32
+ "version",
33
+ "init",
34
+ "mine",
35
+ "split",
36
+ "repair",
37
+ "wake_up",
38
+ ] as const;
39
+
40
+ export type MempalaceAction = typeof MEMPALACE_ACTIONS[number];
41
+
42
+ export interface MempalaceParams {
43
+ action: MempalaceAction;
44
+ palace?: string;
45
+ wing?: string;
46
+ room?: string;
47
+ query?: string;
48
+ limit?: number;
49
+ offset?: number;
50
+ drawer_id?: string;
51
+ content?: string;
52
+ source_file?: string;
53
+ added_by?: string;
54
+ subject?: string;
55
+ predicate?: string;
56
+ object?: string;
57
+ valid_from?: string;
58
+ valid_to?: string;
59
+ ended?: boolean;
60
+ as_of?: string;
61
+ direction?: string;
62
+ start_room?: string;
63
+ max_hops?: number;
64
+ source_wing?: string;
65
+ source_room?: string;
66
+ target_wing?: string;
67
+ target_room?: string;
68
+ label?: string;
69
+ tunnel_id?: string;
70
+ agent_name?: string;
71
+ entry?: string;
72
+ topic?: string;
73
+ dir?: string;
74
+ mode?: string;
75
+ extract?: boolean;
76
+ dry_run?: boolean;
77
+ include_ignored?: boolean;
78
+ no_gitignore?: boolean;
79
+ yes?: boolean;
80
+ timeout?: number;
81
+ }
82
+
83
+ export interface MempalaceValidationResult {
84
+ valid: boolean;
85
+ errors: string[];
86
+ params?: MempalaceParams;
87
+ }
88
+
89
+ const STRING_FIELDS = [
90
+ "palace",
91
+ "wing",
92
+ "room",
93
+ "query",
94
+ "drawer_id",
95
+ "content",
96
+ "source_file",
97
+ "added_by",
98
+ "subject",
99
+ "predicate",
100
+ "object",
101
+ "valid_from",
102
+ "valid_to",
103
+ "as_of",
104
+ "direction",
105
+ "start_room",
106
+ "source_wing",
107
+ "source_room",
108
+ "target_wing",
109
+ "target_room",
110
+ "label",
111
+ "tunnel_id",
112
+ "agent_name",
113
+ "entry",
114
+ "topic",
115
+ "dir",
116
+ "mode",
117
+ ] as const;
118
+
119
+ const POSITIVE_INTEGER_FIELDS = ["limit", "max_hops", "timeout"] as const;
120
+ const NON_NEGATIVE_INTEGER_FIELDS = ["offset"] as const;
121
+ const BOOLEAN_FIELDS = ["ended", "extract", "dry_run", "include_ignored", "no_gitignore", "yes"] as const;
122
+
123
+ const REQUIRED_FIELDS: Partial<Record<MempalaceAction, readonly (keyof MempalaceParams)[]>> = {
124
+ search: ["query"],
125
+ check_duplicate: ["content"],
126
+ get_drawer: ["drawer_id"],
127
+ list_drawers: ["wing"],
128
+ add_drawer: ["content"],
129
+ update_drawer: ["drawer_id", "content"],
130
+ delete_drawer: ["drawer_id"],
131
+ kg_query: ["subject"],
132
+ kg_add: ["subject", "predicate", "object"],
133
+ kg_invalidate: ["subject", "predicate"],
134
+ kg_timeline: ["subject"],
135
+ traverse: ["start_room"],
136
+ find_tunnels: ["source_wing", "source_room"],
137
+ create_tunnel: ["source_wing", "source_room", "target_wing", "target_room", "label"],
138
+ delete_tunnel: ["tunnel_id"],
139
+ follow_tunnels: ["source_wing", "source_room"],
140
+ diary_write: ["entry"],
141
+ init: ["dir"],
142
+ mine: ["dir"],
143
+ split: ["source_file"],
144
+ repair: ["dir"],
145
+ };
146
+
147
+ function isRecord(value: unknown): value is Record<string, unknown> {
148
+ return typeof value === "object" && value !== null && !Array.isArray(value);
149
+ }
150
+
151
+ export function isMempalaceAction(action: unknown): action is MempalaceAction {
152
+ return typeof action === "string" && (MEMPALACE_ACTIONS as readonly string[]).includes(action);
153
+ }
154
+
155
+ function isNonEmptyString(value: unknown): value is string {
156
+ return typeof value === "string" && value.trim().length > 0;
157
+ }
158
+
159
+ export const mempalaceToolParameters = {
160
+ type: "object",
161
+ additionalProperties: false,
162
+ properties: {
163
+ action: {
164
+ type: "string",
165
+ enum: MEMPALACE_ACTIONS,
166
+ description: "Action to dispatch.",
167
+ },
168
+ palace: { type: "string" },
169
+ wing: { type: "string" },
170
+ room: { type: "string" },
171
+ query: { type: "string" },
172
+ limit: { type: "integer", minimum: 1 },
173
+ offset: { type: "integer", minimum: 0 },
174
+ drawer_id: { type: "string" },
175
+ content: { type: "string" },
176
+ source_file: { type: "string" },
177
+ added_by: { type: "string" },
178
+ subject: { type: "string" },
179
+ predicate: { type: "string" },
180
+ object: { type: "string" },
181
+ valid_from: { type: "string" },
182
+ valid_to: { type: "string" },
183
+ ended: { type: "boolean" },
184
+ as_of: { type: "string" },
185
+ direction: { type: "string" },
186
+ start_room: { type: "string" },
187
+ max_hops: { type: "integer", minimum: 1 },
188
+ source_wing: { type: "string" },
189
+ source_room: { type: "string" },
190
+ target_wing: { type: "string" },
191
+ target_room: { type: "string" },
192
+ label: { type: "string" },
193
+ tunnel_id: { type: "string" },
194
+ agent_name: { type: "string" },
195
+ entry: { type: "string" },
196
+ topic: { type: "string" },
197
+ dir: { type: "string" },
198
+ mode: { type: "string" },
199
+ extract: { type: "boolean" },
200
+ dry_run: { type: "boolean" },
201
+ include_ignored: { type: "boolean" },
202
+ no_gitignore: { type: "boolean" },
203
+ yes: { type: "boolean" },
204
+ timeout: { type: "integer", minimum: 1 },
205
+ },
206
+ required: ["action"],
207
+ } as const;
208
+
209
+ export function validateMempalaceParams(params: unknown): MempalaceValidationResult {
210
+ if (!isRecord(params)) {
211
+ return { valid: false, errors: ["params must be an object"] };
212
+ }
213
+
214
+ const errors: string[] = [];
215
+ const action = params.action;
216
+ if (!isMempalaceAction(action)) {
217
+ errors.push(
218
+ action === undefined
219
+ ? "action is required"
220
+ : "action must be one of the supported MemPalace actions",
221
+ );
222
+ return { valid: false, errors };
223
+ }
224
+
225
+ for (const field of STRING_FIELDS) {
226
+ const value = params[field];
227
+ if (value !== undefined && typeof value !== "string") {
228
+ errors.push(`${field} must be a string`);
229
+ }
230
+ }
231
+
232
+ for (const field of BOOLEAN_FIELDS) {
233
+ const value = params[field];
234
+ if (value !== undefined && typeof value !== "boolean") {
235
+ errors.push(`${field} must be a boolean`);
236
+ }
237
+ }
238
+
239
+ for (const field of POSITIVE_INTEGER_FIELDS) {
240
+ const value = params[field];
241
+ if (value !== undefined && (typeof value !== "number" || !Number.isInteger(value) || value < 1)) {
242
+ errors.push(`${field} must be a positive integer`);
243
+ }
244
+ }
245
+
246
+ for (const field of NON_NEGATIVE_INTEGER_FIELDS) {
247
+ const value = params[field];
248
+ if (value !== undefined && (typeof value !== "number" || !Number.isInteger(value) || value < 0)) {
249
+ errors.push(`${field} must be a non-negative integer`);
250
+ }
251
+ }
252
+
253
+ for (const field of REQUIRED_FIELDS[action] ?? []) {
254
+ if (!isNonEmptyString(params[field])) {
255
+ errors.push(`${field} is required for action ${action}`);
256
+ }
257
+ }
258
+
259
+ if (errors.length > 0) {
260
+ return { valid: false, errors };
261
+ }
262
+
263
+ return { valid: true, errors: [], params: params as unknown as MempalaceParams };
264
+ }
@@ -0,0 +1,198 @@
1
+ import type { EventStore, TrackedEvent } from "../context-mode/event-store.js";
2
+ import { buildResumeSnapshot } from "../context-mode/snapshot-builder.js";
3
+
4
+ export interface SessionSummaryOptions {
5
+ cwd: string;
6
+ sessionId: string;
7
+ wing: string;
8
+ defaultAgentName: string;
9
+ now?: string;
10
+ eventStore?: Pick<EventStore, "getEventCounts" | "getEvents"> | null;
11
+ sessionManager?: { getBranch?: () => unknown[] } | null;
12
+ maxChars?: number;
13
+ }
14
+
15
+ export interface CompactionCheckpoint {
16
+ content: string;
17
+ metadata: {
18
+ wing: string;
19
+ room: "compaction-checkpoints";
20
+ added_by: string;
21
+ source_file: string;
22
+ };
23
+ }
24
+
25
+ export interface ShutdownDiary {
26
+ entry: string;
27
+ metadata: {
28
+ agent_name: string;
29
+ wing: string;
30
+ topic: "shutdown";
31
+ timestamp: string;
32
+ source_file: string;
33
+ };
34
+ }
35
+
36
+ const DEFAULT_MAX_CHARS = 8000;
37
+ const EVENT_CATEGORIES = ["decision", "task", "intent", "rule"] as const;
38
+
39
+ function truncate(text: string, maxChars: number): string {
40
+ return text.length <= maxChars ? text : `${text.slice(0, Math.max(0, maxChars - 1)).trimEnd()}…`;
41
+ }
42
+
43
+ function safeParse(data: string): Record<string, unknown> | null {
44
+ try {
45
+ const parsed = JSON.parse(data);
46
+ return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed as Record<string, unknown> : null;
47
+ } catch {
48
+ return null;
49
+ }
50
+ }
51
+
52
+ function summarizeTask(data: Record<string, unknown>): string | null {
53
+ const input = data.input as Record<string, unknown> | undefined;
54
+ const ops = Array.isArray(input?.ops) ? input.ops as Array<Record<string, unknown>> : [];
55
+ const parts = ops.map((op) => {
56
+ const verb = typeof op.op === "string" ? op.op : "";
57
+ const target = typeof op.task === "string" ? op.task : typeof op.phase === "string" ? op.phase : "";
58
+ return [verb, target].filter(Boolean).join(": ");
59
+ }).filter(Boolean);
60
+ return parts.length > 0 ? parts.join("; ") : JSON.stringify(data).slice(0, 240);
61
+ }
62
+
63
+ function summarizeEvent(event: TrackedEvent): string | null {
64
+ const data = safeParse(event.data);
65
+ if (!data) return null;
66
+ if (event.category === "decision") {
67
+ const prompt = typeof data.prompt === "string" ? data.prompt.trim() : "";
68
+ return prompt ? `decision: ${prompt}` : null;
69
+ }
70
+ if (event.category === "task") {
71
+ const summary = summarizeTask(data);
72
+ return summary ? `task: ${summary}` : null;
73
+ }
74
+ if (event.category === "intent") {
75
+ const intent = typeof data.intent === "string" ? data.intent : "intent";
76
+ const prompt = typeof data.prompt === "string" ? data.prompt : "";
77
+ return `intent ${intent}: ${prompt}`.trim();
78
+ }
79
+ if (event.category === "rule") {
80
+ const path = typeof data.path === "string" ? data.path : typeof data.file === "string" ? data.file : "";
81
+ return path ? `rule loaded: ${path}` : null;
82
+ }
83
+ return null;
84
+ }
85
+
86
+ function eventStoreSection(options: SessionSummaryOptions): string | null {
87
+ const eventStore = options.eventStore;
88
+ if (!eventStore) return null;
89
+
90
+ let snapshot = "";
91
+ try {
92
+ snapshot = buildResumeSnapshot(eventStore as EventStore, options.sessionId);
93
+ } catch {
94
+ snapshot = "";
95
+ }
96
+
97
+ const lines: string[] = [];
98
+ try {
99
+ const events = eventStore.getEvents(options.sessionId, { categories: [...EVENT_CATEGORIES], limit: 40 });
100
+ for (const event of events) {
101
+ const summary = summarizeEvent(event as TrackedEvent);
102
+ if (summary) lines.push(`- ${summary}`);
103
+ }
104
+ } catch {
105
+ // fall through to snapshot-only or later fallbacks
106
+ }
107
+
108
+ if (!snapshot && lines.length === 0) return null;
109
+ return [
110
+ "Event-store summary",
111
+ snapshot,
112
+ ...lines,
113
+ ].filter(Boolean).join("\n");
114
+ }
115
+
116
+ function branchText(entry: unknown): string | null {
117
+ if (typeof entry === "string") return entry;
118
+ if (typeof entry !== "object" || entry === null) return null;
119
+ const record = entry as Record<string, unknown>;
120
+ const role = typeof record.role === "string" ? record.role : "entry";
121
+ const content = record.content;
122
+ let text = "";
123
+ if (typeof content === "string") {
124
+ text = content;
125
+ } else if (Array.isArray(content)) {
126
+ text = content
127
+ .map((part) => typeof part === "object" && part !== null && typeof (part as { text?: unknown }).text === "string" ? (part as { text: string }).text : "")
128
+ .filter(Boolean)
129
+ .join("\n");
130
+ }
131
+ return text ? `${role}: ${text}` : null;
132
+ }
133
+
134
+ function sessionManagerSection(options: SessionSummaryOptions): string | null {
135
+ try {
136
+ const branch = options.sessionManager?.getBranch?.();
137
+ if (!Array.isArray(branch) || branch.length === 0) return null;
138
+ const lines = branch.map(branchText).filter((line): line is string => Boolean(line)).slice(-10);
139
+ return lines.length > 0 ? ["Session branch fallback", ...lines.map((line) => `- ${line}`)].join("\n") : null;
140
+ } catch {
141
+ return null;
142
+ }
143
+ }
144
+
145
+ function fallbackSection(reason: "compaction" | "shutdown", options: SessionSummaryOptions, now: string): string {
146
+ return [
147
+ `timestamp: ${now}`,
148
+ `cwd: ${options.cwd}`,
149
+ `wing: ${options.wing}`,
150
+ `session: ${options.sessionId}`,
151
+ `reason: ${reason}`,
152
+ "Structured session data unavailable.",
153
+ ].join("\n");
154
+ }
155
+
156
+ function buildBody(title: string, reason: "compaction" | "shutdown", options: SessionSummaryOptions): { body: string; now: string } {
157
+ const now = options.now ?? new Date().toISOString();
158
+ const source = eventStoreSection(options)
159
+ ?? sessionManagerSection(options)
160
+ ?? fallbackSection(reason, options, now);
161
+ const body = [
162
+ `# ${title}`,
163
+ `generated_at: ${now}`,
164
+ `cwd: ${options.cwd}`,
165
+ `wing: ${options.wing}`,
166
+ `session_id: ${options.sessionId}`,
167
+ "",
168
+ source,
169
+ ].join("\n");
170
+ return { body: truncate(body, options.maxChars ?? DEFAULT_MAX_CHARS), now };
171
+ }
172
+
173
+ export function buildCompactionCheckpoint(options: SessionSummaryOptions): CompactionCheckpoint {
174
+ const { body, now } = buildBody("MemPalace compaction checkpoint", "compaction", options);
175
+ return {
176
+ content: body,
177
+ metadata: {
178
+ wing: options.wing,
179
+ room: "compaction-checkpoints",
180
+ added_by: options.defaultAgentName,
181
+ source_file: `omp-session:${options.sessionId}:compaction:${now}`,
182
+ },
183
+ };
184
+ }
185
+
186
+ export function buildShutdownDiary(options: SessionSummaryOptions): ShutdownDiary {
187
+ const { body, now } = buildBody("MemPalace shutdown diary", "shutdown", options);
188
+ return {
189
+ entry: body,
190
+ metadata: {
191
+ agent_name: options.defaultAgentName,
192
+ wing: options.wing,
193
+ topic: "shutdown",
194
+ timestamp: now,
195
+ source_file: `omp-session:${options.sessionId}:shutdown:${now}`,
196
+ },
197
+ };
198
+ }
@@ -0,0 +1,186 @@
1
+ import type { Platform } from "../platform/types.js";
2
+ import type { SupipowersConfig } from "../types.js";
3
+ import { createMempalaceBridge, type MempalaceBridgeFacade } from "./bridge.js";
4
+ import { resolveMempalaceConfig, type ResolvedMempalaceConfig } from "./config.js";
5
+ import { formatMempalaceError, formatMempalaceResult } from "./format.js";
6
+ import { mempalaceToolParameters, validateMempalaceParams, type MempalaceParams } from "./schema.js";
7
+ import {
8
+ resolveBridgeScriptPath,
9
+ setupMempalaceRuntime,
10
+ type BridgePathResult,
11
+ type SetupMempalaceRuntimeOptions,
12
+ type SetupMempalaceRuntimeResult,
13
+ } from "./runtime.js";
14
+ import {
15
+ snapshotMempalaceInstall,
16
+ type MempalaceInstallSnapshot,
17
+ } from "./installer-helper.js";
18
+
19
+ export interface MempalaceToolDeps {
20
+ createBridge?: (config: ResolvedMempalaceConfig, cwd: string) => MempalaceBridgeFacade;
21
+ resolveBridgeScriptPath?: () => BridgePathResult;
22
+ setupRuntime?: (options: SetupMempalaceRuntimeOptions) => Promise<SetupMempalaceRuntimeResult>;
23
+ /**
24
+ * Installation readiness probe. Default reads the filesystem; tests can inject
25
+ * a stub. The tool is registered only when this returns `ready: true`.
26
+ */
27
+ snapshotInstall?: (config: SupipowersConfig, cwd: string) => MempalaceInstallSnapshot;
28
+ }
29
+
30
+ function toolResult(text: string, details: Record<string, unknown>): { content: Array<{ type: "text"; text: string }>; details: Record<string, unknown> } {
31
+ return { content: [{ type: "text", text }], details };
32
+ }
33
+
34
+ function readCwd(toolCtx: unknown): string {
35
+ if (typeof toolCtx === "object" && toolCtx !== null && typeof (toolCtx as { cwd?: unknown }).cwd === "string") {
36
+ return (toolCtx as { cwd: string }).cwd;
37
+ }
38
+ return process.cwd();
39
+ }
40
+
41
+ function emitProgress(onUpdate: unknown, text: string): void {
42
+ if (typeof onUpdate !== "function") return;
43
+ // OMP's tool runtime treats the value passed to onUpdate as a partial tool
44
+ // result. It iterates `partialResult.content.map(...)`, so we must pass a
45
+ // shape that mirrors the final `{ content: [...] }` return.
46
+ try {
47
+ onUpdate({ content: [{ type: "text", text }] });
48
+ } catch {
49
+ // best effort — never let a progress notification kill the tool call
50
+ }
51
+ }
52
+
53
+ async function executeSetup(
54
+ params: MempalaceParams,
55
+ resolved: ResolvedMempalaceConfig,
56
+ cwd: string,
57
+ managedBinDir: string,
58
+ deps: MempalaceToolDeps,
59
+ onUpdate: unknown,
60
+ ): Promise<{ content: Array<{ type: "text"; text: string }>; details: Record<string, unknown> }> {
61
+ const bridgePath = (deps.resolveBridgeScriptPath ?? resolveBridgeScriptPath)();
62
+ if (!bridgePath.ok) {
63
+ const formatted = formatMempalaceError(bridgePath.error, {
64
+ ok: false,
65
+ action: params.action,
66
+ bridgeScriptPath: bridgePath.path,
67
+ });
68
+ return toolResult(formatted.text, formatted.details as Record<string, unknown>);
69
+ }
70
+
71
+ const setup = await (deps.setupRuntime ?? setupMempalaceRuntime)({
72
+ cwd,
73
+ config: resolved,
74
+ bridgeScriptPath: bridgePath.path,
75
+ managedBinDir,
76
+ onProgress: (message) => emitProgress(onUpdate, message),
77
+ });
78
+
79
+ if (!setup.ok) {
80
+ const formatted = formatMempalaceError(setup.error, {
81
+ ok: false,
82
+ action: "setup",
83
+ stderrTail: setup.stderrTail,
84
+ });
85
+ return toolResult(formatted.text, formatted.details as Record<string, unknown>);
86
+ }
87
+
88
+ const formatted = formatMempalaceResult(
89
+ "setup",
90
+ { message: "setup complete", ...setup.details },
91
+ resolved.budgets,
92
+ );
93
+ return toolResult(formatted.text, {
94
+ ok: true,
95
+ action: "setup",
96
+ setup: setup.details,
97
+ });
98
+ }
99
+
100
+ export function registerMempalaceTool(
101
+ platform: Platform,
102
+ config: SupipowersConfig,
103
+ deps: MempalaceToolDeps = {},
104
+ ): void {
105
+ if (!config.mempalace.enabled) return;
106
+ if (typeof platform.registerTool !== "function") return;
107
+
108
+ // Gate exposure on installation readiness. Without uv + the managed venv +
109
+ // the Python bridge script all present, every action fails — surfacing a
110
+ // dead tool in the agent's catalog only invites broken tool calls. Setup is
111
+ // driven explicitly by `/supi:memory setup`, so this gate is recoverable.
112
+ const snapshotFn = deps.snapshotInstall ?? ((cfg, cwd) => snapshotMempalaceInstall(platform.paths, cwd, cfg));
113
+ let snapshot: MempalaceInstallSnapshot;
114
+ try {
115
+ snapshot = snapshotFn(config, process.cwd());
116
+ } catch (error) {
117
+ (platform as { logger?: { warn?: (message: string, error?: unknown) => void } }).logger?.warn?.(
118
+ "supi-mempalace: install snapshot failed; tool will not be registered",
119
+ error,
120
+ );
121
+ return;
122
+ }
123
+ if (!snapshot.ready) return;
124
+
125
+ platform.registerTool({
126
+ name: "mempalace",
127
+ label: "MemPalace",
128
+ description:
129
+ "MemPalace memory dispatcher. **MUST** call `search` before answering past-fact questions; write only on explicit user request.",
130
+ parameters: mempalaceToolParameters,
131
+ async execute(_toolCallId: string, rawParams: unknown, _signal: AbortSignal, onUpdate: unknown, toolCtx: unknown) {
132
+ try {
133
+ const validation = validateMempalaceParams(rawParams);
134
+ if (!validation.valid || !validation.params) {
135
+ return toolResult(`MemPalace validation failed:\n${validation.errors.map((error) => `- ${error}`).join("\n")}`, {
136
+ ok: false,
137
+ errors: validation.errors,
138
+ });
139
+ }
140
+
141
+ const cwd = readCwd(toolCtx);
142
+ const resolved = resolveMempalaceConfig(config, cwd, platform.paths);
143
+ const params = validation.params;
144
+
145
+ if (params.action === "setup") {
146
+ return await executeSetup(params, resolved, cwd, platform.paths.global("bin"), deps, onUpdate);
147
+ }
148
+
149
+ const bridge = deps.createBridge
150
+ ? deps.createBridge(resolved, cwd)
151
+ : createMempalaceBridge({ cwd, config: resolved });
152
+ const result = await bridge.execute(params);
153
+
154
+ if (!result.ok) {
155
+ const formatted = formatMempalaceError(result.error, {
156
+ ok: false,
157
+ action: result.action,
158
+ diagnostics: result.diagnostics,
159
+ });
160
+ return toolResult(formatted.text, {
161
+ ok: false,
162
+ action: result.action,
163
+ error: result.error,
164
+ diagnostics: result.diagnostics,
165
+ });
166
+ }
167
+
168
+ const formatted = formatMempalaceResult(result.action, result.result, resolved.budgets);
169
+ return toolResult(formatted.text, {
170
+ ok: true,
171
+ action: result.action,
172
+ result: result.result,
173
+ diagnostics: result.diagnostics,
174
+ formattedDetails: formatted.details,
175
+ });
176
+ } catch (error) {
177
+ const message = error instanceof Error ? error.message : String(error);
178
+ const stack = error instanceof Error ? error.stack : undefined;
179
+ return toolResult(
180
+ `MemPalace tool crashed: ${message}`,
181
+ { ok: false, error: { code: "tool_crash", message, stack } },
182
+ );
183
+ }
184
+ },
185
+ });
186
+ }