mewkit 1.7.0 → 1.8.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 (264) hide show
  1. package/README.md +76 -0
  2. package/dist/commands/memory.js +3 -3
  3. package/dist/commands/memory.js.map +1 -1
  4. package/dist/commands/orchviz.d.ts +12 -0
  5. package/dist/commands/orchviz.d.ts.map +1 -0
  6. package/dist/commands/orchviz.js +160 -0
  7. package/dist/commands/orchviz.js.map +1 -0
  8. package/dist/commands/setup.d.ts.map +1 -1
  9. package/dist/commands/setup.js +7 -5
  10. package/dist/commands/setup.js.map +1 -1
  11. package/dist/core/skills-dependencies.js +2 -2
  12. package/dist/core/skills-dependencies.js.map +1 -1
  13. package/dist/index.js +50 -1
  14. package/dist/index.js.map +1 -1
  15. package/dist/migrate/__tests__/skill-id-utils.test.d.ts +2 -0
  16. package/dist/migrate/__tests__/skill-id-utils.test.d.ts.map +1 -0
  17. package/dist/migrate/__tests__/skill-id-utils.test.js +78 -0
  18. package/dist/migrate/__tests__/skill-id-utils.test.js.map +1 -0
  19. package/dist/migrate/discovery/skill-id-utils.d.ts +18 -0
  20. package/dist/migrate/discovery/skill-id-utils.d.ts.map +1 -0
  21. package/dist/migrate/discovery/skill-id-utils.js +45 -0
  22. package/dist/migrate/discovery/skill-id-utils.js.map +1 -0
  23. package/dist/migrate/discovery/skills-discovery.d.ts.map +1 -1
  24. package/dist/migrate/discovery/skills-discovery.js +5 -1
  25. package/dist/migrate/discovery/skills-discovery.js.map +1 -1
  26. package/dist/migrate/reconcile/portable-registry.d.ts +12 -12
  27. package/dist/migrate/types.d.ts +8 -6
  28. package/dist/migrate/types.d.ts.map +1 -1
  29. package/dist/migrate/types.js.map +1 -1
  30. package/dist/orchviz/constants.d.ts +53 -0
  31. package/dist/orchviz/constants.d.ts.map +1 -0
  32. package/dist/orchviz/constants.js +68 -0
  33. package/dist/orchviz/constants.js.map +1 -0
  34. package/dist/orchviz/fs-utils.d.ts +24 -0
  35. package/dist/orchviz/fs-utils.d.ts.map +1 -0
  36. package/dist/orchviz/fs-utils.js +49 -0
  37. package/dist/orchviz/fs-utils.js.map +1 -0
  38. package/dist/orchviz/index.d.ts +29 -0
  39. package/dist/orchviz/index.d.ts.map +1 -0
  40. package/dist/orchviz/index.js +28 -0
  41. package/dist/orchviz/index.js.map +1 -0
  42. package/dist/orchviz/log-persister.d.ts +22 -0
  43. package/dist/orchviz/log-persister.d.ts.map +1 -0
  44. package/dist/orchviz/log-persister.js +96 -0
  45. package/dist/orchviz/log-persister.js.map +1 -0
  46. package/dist/orchviz/logger.d.ts +13 -0
  47. package/dist/orchviz/logger.d.ts.map +1 -0
  48. package/dist/orchviz/logger.js +47 -0
  49. package/dist/orchviz/logger.js.map +1 -0
  50. package/dist/orchviz/open-url.d.ts +11 -0
  51. package/dist/orchviz/open-url.d.ts.map +1 -0
  52. package/dist/orchviz/open-url.js +28 -0
  53. package/dist/orchviz/open-url.js.map +1 -0
  54. package/dist/orchviz/overlay/collector.d.ts +29 -0
  55. package/dist/orchviz/overlay/collector.d.ts.map +1 -0
  56. package/dist/orchviz/overlay/collector.js +38 -0
  57. package/dist/orchviz/overlay/collector.js.map +1 -0
  58. package/dist/orchviz/overlay/gate-readers.d.ts +18 -0
  59. package/dist/orchviz/overlay/gate-readers.d.ts.map +1 -0
  60. package/dist/orchviz/overlay/gate-readers.js +111 -0
  61. package/dist/orchviz/overlay/gate-readers.js.map +1 -0
  62. package/dist/orchviz/overlay/session-state-readers.d.ts +18 -0
  63. package/dist/orchviz/overlay/session-state-readers.d.ts.map +1 -0
  64. package/dist/orchviz/overlay/session-state-readers.js +78 -0
  65. package/dist/orchviz/overlay/session-state-readers.js.map +1 -0
  66. package/dist/orchviz/parser/handle-progress.d.ts +9 -0
  67. package/dist/orchviz/parser/handle-progress.d.ts.map +1 -0
  68. package/dist/orchviz/parser/handle-progress.js +38 -0
  69. package/dist/orchviz/parser/handle-progress.js.map +1 -0
  70. package/dist/orchviz/parser/handle-text.d.ts +10 -0
  71. package/dist/orchviz/parser/handle-text.d.ts.map +1 -0
  72. package/dist/orchviz/parser/handle-text.js +38 -0
  73. package/dist/orchviz/parser/handle-text.js.map +1 -0
  74. package/dist/orchviz/parser/handle-thinking.d.ts +10 -0
  75. package/dist/orchviz/parser/handle-thinking.d.ts.map +1 -0
  76. package/dist/orchviz/parser/handle-thinking.js +35 -0
  77. package/dist/orchviz/parser/handle-thinking.js.map +1 -0
  78. package/dist/orchviz/parser/handle-tool-result.d.ts +10 -0
  79. package/dist/orchviz/parser/handle-tool-result.d.ts.map +1 -0
  80. package/dist/orchviz/parser/handle-tool-result.js +62 -0
  81. package/dist/orchviz/parser/handle-tool-result.js.map +1 -0
  82. package/dist/orchviz/parser/handle-tool-use.d.ts +11 -0
  83. package/dist/orchviz/parser/handle-tool-use.d.ts.map +1 -0
  84. package/dist/orchviz/parser/handle-tool-use.js +38 -0
  85. package/dist/orchviz/parser/handle-tool-use.js.map +1 -0
  86. package/dist/orchviz/parser/index.d.ts +38 -0
  87. package/dist/orchviz/parser/index.d.ts.map +1 -0
  88. package/dist/orchviz/parser/index.js +139 -0
  89. package/dist/orchviz/parser/index.js.map +1 -0
  90. package/dist/orchviz/parser/label-helpers.d.ts +9 -0
  91. package/dist/orchviz/parser/label-helpers.d.ts.map +1 -0
  92. package/dist/orchviz/parser/label-helpers.js +44 -0
  93. package/dist/orchviz/parser/label-helpers.js.map +1 -0
  94. package/dist/orchviz/parser/strip-ansi.d.ts +6 -0
  95. package/dist/orchviz/parser/strip-ansi.d.ts.map +1 -0
  96. package/dist/orchviz/parser/strip-ansi.js +14 -0
  97. package/dist/orchviz/parser/strip-ansi.js.map +1 -0
  98. package/dist/orchviz/parser/utils.d.ts +20 -0
  99. package/dist/orchviz/parser/utils.d.ts.map +1 -0
  100. package/dist/orchviz/parser/utils.js +56 -0
  101. package/dist/orchviz/parser/utils.js.map +1 -0
  102. package/dist/orchviz/permission-detection.d.ts +18 -0
  103. package/dist/orchviz/permission-detection.d.ts.map +1 -0
  104. package/dist/orchviz/permission-detection.js +50 -0
  105. package/dist/orchviz/permission-detection.js.map +1 -0
  106. package/dist/orchviz/plan/__tests__/apply-todo-toggle.test.d.ts +15 -0
  107. package/dist/orchviz/plan/__tests__/apply-todo-toggle.test.d.ts.map +1 -0
  108. package/dist/orchviz/plan/__tests__/apply-todo-toggle.test.js +165 -0
  109. package/dist/orchviz/plan/__tests__/apply-todo-toggle.test.js.map +1 -0
  110. package/dist/orchviz/plan/__tests__/atomic-write.test.d.ts +11 -0
  111. package/dist/orchviz/plan/__tests__/atomic-write.test.d.ts.map +1 -0
  112. package/dist/orchviz/plan/__tests__/atomic-write.test.js +89 -0
  113. package/dist/orchviz/plan/__tests__/atomic-write.test.js.map +1 -0
  114. package/dist/orchviz/plan/__tests__/end-to-end.test.d.ts +10 -0
  115. package/dist/orchviz/plan/__tests__/end-to-end.test.d.ts.map +1 -0
  116. package/dist/orchviz/plan/__tests__/end-to-end.test.js +132 -0
  117. package/dist/orchviz/plan/__tests__/end-to-end.test.js.map +1 -0
  118. package/dist/orchviz/plan/__tests__/etag.test.d.ts +11 -0
  119. package/dist/orchviz/plan/__tests__/etag.test.d.ts.map +1 -0
  120. package/dist/orchviz/plan/__tests__/etag.test.js +92 -0
  121. package/dist/orchviz/plan/__tests__/etag.test.js.map +1 -0
  122. package/dist/orchviz/plan/__tests__/list-plans.test.d.ts +14 -0
  123. package/dist/orchviz/plan/__tests__/list-plans.test.d.ts.map +1 -0
  124. package/dist/orchviz/plan/__tests__/list-plans.test.js +154 -0
  125. package/dist/orchviz/plan/__tests__/list-plans.test.js.map +1 -0
  126. package/dist/orchviz/plan/apply-todo-toggle.d.ts +29 -0
  127. package/dist/orchviz/plan/apply-todo-toggle.d.ts.map +1 -0
  128. package/dist/orchviz/plan/apply-todo-toggle.js +129 -0
  129. package/dist/orchviz/plan/apply-todo-toggle.js.map +1 -0
  130. package/dist/orchviz/plan/atomic-write.d.ts +25 -0
  131. package/dist/orchviz/plan/atomic-write.d.ts.map +1 -0
  132. package/dist/orchviz/plan/atomic-write.js +85 -0
  133. package/dist/orchviz/plan/atomic-write.js.map +1 -0
  134. package/dist/orchviz/plan/collector.d.ts +49 -0
  135. package/dist/orchviz/plan/collector.d.ts.map +1 -0
  136. package/dist/orchviz/plan/collector.js +173 -0
  137. package/dist/orchviz/plan/collector.js.map +1 -0
  138. package/dist/orchviz/plan/etag.d.ts +24 -0
  139. package/dist/orchviz/plan/etag.d.ts.map +1 -0
  140. package/dist/orchviz/plan/etag.js +58 -0
  141. package/dist/orchviz/plan/etag.js.map +1 -0
  142. package/dist/orchviz/plan/find-active-plan.d.ts +9 -0
  143. package/dist/orchviz/plan/find-active-plan.d.ts.map +1 -0
  144. package/dist/orchviz/plan/find-active-plan.js +90 -0
  145. package/dist/orchviz/plan/find-active-plan.js.map +1 -0
  146. package/dist/orchviz/plan/index.d.ts +23 -0
  147. package/dist/orchviz/plan/index.d.ts.map +1 -0
  148. package/dist/orchviz/plan/index.js +91 -0
  149. package/dist/orchviz/plan/index.js.map +1 -0
  150. package/dist/orchviz/plan/list-plans.d.ts +19 -0
  151. package/dist/orchviz/plan/list-plans.d.ts.map +1 -0
  152. package/dist/orchviz/plan/list-plans.js +148 -0
  153. package/dist/orchviz/plan/list-plans.js.map +1 -0
  154. package/dist/orchviz/plan/parse-phase-file.d.ts +13 -0
  155. package/dist/orchviz/plan/parse-phase-file.d.ts.map +1 -0
  156. package/dist/orchviz/plan/parse-phase-file.js +136 -0
  157. package/dist/orchviz/plan/parse-phase-file.js.map +1 -0
  158. package/dist/orchviz/plan/parse-plan-file.d.ts +19 -0
  159. package/dist/orchviz/plan/parse-plan-file.d.ts.map +1 -0
  160. package/dist/orchviz/plan/parse-plan-file.js +62 -0
  161. package/dist/orchviz/plan/parse-plan-file.js.map +1 -0
  162. package/dist/orchviz/plan/plan-constants.d.ts +17 -0
  163. package/dist/orchviz/plan/plan-constants.d.ts.map +1 -0
  164. package/dist/orchviz/plan/plan-constants.js +19 -0
  165. package/dist/orchviz/plan/plan-constants.js.map +1 -0
  166. package/dist/orchviz/plan/types.d.ts +46 -0
  167. package/dist/orchviz/plan/types.d.ts.map +1 -0
  168. package/dist/orchviz/plan/types.js +6 -0
  169. package/dist/orchviz/plan/types.js.map +1 -0
  170. package/dist/orchviz/protocol.d.ts +116 -0
  171. package/dist/orchviz/protocol.d.ts.map +1 -0
  172. package/dist/orchviz/protocol.js +23 -0
  173. package/dist/orchviz/protocol.js.map +1 -0
  174. package/dist/orchviz/redact.d.ts +10 -0
  175. package/dist/orchviz/redact.d.ts.map +1 -0
  176. package/dist/orchviz/redact.js +38 -0
  177. package/dist/orchviz/redact.js.map +1 -0
  178. package/dist/orchviz/sanitize.d.ts +11 -0
  179. package/dist/orchviz/sanitize.d.ts.map +1 -0
  180. package/dist/orchviz/sanitize.js +38 -0
  181. package/dist/orchviz/sanitize.js.map +1 -0
  182. package/dist/orchviz/server/__tests__/security-smoke.test.d.ts +13 -0
  183. package/dist/orchviz/server/__tests__/security-smoke.test.d.ts.map +1 -0
  184. package/dist/orchviz/server/__tests__/security-smoke.test.js +207 -0
  185. package/dist/orchviz/server/__tests__/security-smoke.test.js.map +1 -0
  186. package/dist/orchviz/server/__tests__/write-handlers.test.d.ts +24 -0
  187. package/dist/orchviz/server/__tests__/write-handlers.test.d.ts.map +1 -0
  188. package/dist/orchviz/server/__tests__/write-handlers.test.js +347 -0
  189. package/dist/orchviz/server/__tests__/write-handlers.test.js.map +1 -0
  190. package/dist/orchviz/server/api-handlers.d.ts +55 -0
  191. package/dist/orchviz/server/api-handlers.d.ts.map +1 -0
  192. package/dist/orchviz/server/api-handlers.js +112 -0
  193. package/dist/orchviz/server/api-handlers.js.map +1 -0
  194. package/dist/orchviz/server/index.d.ts +36 -0
  195. package/dist/orchviz/server/index.d.ts.map +1 -0
  196. package/dist/orchviz/server/index.js +147 -0
  197. package/dist/orchviz/server/index.js.map +1 -0
  198. package/dist/orchviz/server/sse-handler.d.ts +25 -0
  199. package/dist/orchviz/server/sse-handler.d.ts.map +1 -0
  200. package/dist/orchviz/server/sse-handler.js +128 -0
  201. package/dist/orchviz/server/sse-handler.js.map +1 -0
  202. package/dist/orchviz/server/static-handler.d.ts +9 -0
  203. package/dist/orchviz/server/static-handler.d.ts.map +1 -0
  204. package/dist/orchviz/server/static-handler.js +76 -0
  205. package/dist/orchviz/server/static-handler.js.map +1 -0
  206. package/dist/orchviz/server/write-handlers.d.ts +20 -0
  207. package/dist/orchviz/server/write-handlers.d.ts.map +1 -0
  208. package/dist/orchviz/server/write-handlers.js +167 -0
  209. package/dist/orchviz/server/write-handlers.js.map +1 -0
  210. package/dist/orchviz/server/write-utils.d.ts +59 -0
  211. package/dist/orchviz/server/write-utils.d.ts.map +1 -0
  212. package/dist/orchviz/server/write-utils.js +161 -0
  213. package/dist/orchviz/server/write-utils.js.map +1 -0
  214. package/dist/orchviz/session-discovery.d.ts +19 -0
  215. package/dist/orchviz/session-discovery.d.ts.map +1 -0
  216. package/dist/orchviz/session-discovery.js +104 -0
  217. package/dist/orchviz/session-discovery.js.map +1 -0
  218. package/dist/orchviz/session-manager.d.ts +17 -0
  219. package/dist/orchviz/session-manager.d.ts.map +1 -0
  220. package/dist/orchviz/session-manager.js +62 -0
  221. package/dist/orchviz/session-manager.js.map +1 -0
  222. package/dist/orchviz/session-runtime.d.ts +22 -0
  223. package/dist/orchviz/session-runtime.d.ts.map +1 -0
  224. package/dist/orchviz/session-runtime.js +135 -0
  225. package/dist/orchviz/session-runtime.js.map +1 -0
  226. package/dist/orchviz/session-watcher.d.ts +33 -0
  227. package/dist/orchviz/session-watcher.d.ts.map +1 -0
  228. package/dist/orchviz/session-watcher.js +135 -0
  229. package/dist/orchviz/session-watcher.js.map +1 -0
  230. package/dist/orchviz/subagent-meta.d.ts +8 -0
  231. package/dist/orchviz/subagent-meta.d.ts.map +1 -0
  232. package/dist/orchviz/subagent-meta.js +28 -0
  233. package/dist/orchviz/subagent-meta.js.map +1 -0
  234. package/dist/orchviz/subagent-scanner.d.ts +15 -0
  235. package/dist/orchviz/subagent-scanner.d.ts.map +1 -0
  236. package/dist/orchviz/subagent-scanner.js +27 -0
  237. package/dist/orchviz/subagent-scanner.js.map +1 -0
  238. package/dist/orchviz/subagent-watcher.d.ts +19 -0
  239. package/dist/orchviz/subagent-watcher.d.ts.map +1 -0
  240. package/dist/orchviz/subagent-watcher.js +147 -0
  241. package/dist/orchviz/subagent-watcher.js.map +1 -0
  242. package/dist/orchviz/test-server-boot.d.ts +28 -0
  243. package/dist/orchviz/test-server-boot.d.ts.map +1 -0
  244. package/dist/orchviz/test-server-boot.js +64 -0
  245. package/dist/orchviz/test-server-boot.js.map +1 -0
  246. package/dist/orchviz/token-estimator.d.ts +11 -0
  247. package/dist/orchviz/token-estimator.d.ts.map +1 -0
  248. package/dist/orchviz/token-estimator.js +38 -0
  249. package/dist/orchviz/token-estimator.js.map +1 -0
  250. package/dist/orchviz/tool-input-data.d.ts +11 -0
  251. package/dist/orchviz/tool-input-data.d.ts.map +1 -0
  252. package/dist/orchviz/tool-input-data.js +76 -0
  253. package/dist/orchviz/tool-input-data.js.map +1 -0
  254. package/dist/orchviz/tool-summarizer.d.ts +16 -0
  255. package/dist/orchviz/tool-summarizer.d.ts.map +1 -0
  256. package/dist/orchviz/tool-summarizer.js +131 -0
  257. package/dist/orchviz/tool-summarizer.js.map +1 -0
  258. package/dist/orchviz-web/index.css +1 -0
  259. package/dist/orchviz-web/index.html +18 -0
  260. package/dist/orchviz-web/index.js +51 -0
  261. package/package.json +18 -3
  262. package/dist/logger.d.ts +0 -26
  263. package/dist/logger.js +0 -70
  264. package/dist/logger.js.map +0 -1
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Agent event protocol — types describing live Claude Code session events.
3
+ *
4
+ * Ported (in part) from patoles/agent-flow @ 59ccf4e
5
+ * Original: extension/src/protocol.ts
6
+ * License: Apache-2.0 (see ../../NOTICE)
7
+ *
8
+ * Modifications: dropped VS Code extension/webview message types;
9
+ * replaced FSWatcher import path; pruned helper signatures unused server-side.
10
+ */
11
+ export function emitSubagentSpawn(emitter, parent, child, task, sessionId) {
12
+ emitter.emit({
13
+ time: emitter.elapsed(sessionId),
14
+ type: "subagent_dispatch",
15
+ payload: { parent, child, task },
16
+ }, sessionId);
17
+ emitter.emit({
18
+ time: emitter.elapsed(sessionId),
19
+ type: "agent_spawn",
20
+ payload: { name: child, parent, task },
21
+ }, sessionId);
22
+ }
23
+ //# sourceMappingURL=protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/orchviz/protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAmFH,MAAM,UAAU,iBAAiB,CAChC,OAA0B,EAC1B,MAAc,EACd,KAAa,EACb,IAAY,EACZ,SAAkB;IAElB,OAAO,CAAC,IAAI,CACX;QACC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC;QAChC,IAAI,EAAE,mBAAmB;QACzB,OAAO,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE;KAChC,EACD,SAAS,CACT,CAAC;IACF,OAAO,CAAC,IAAI,CACX;QACC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC;QAChC,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE;KACtC,EACD,SAAS,CACT,CAAC;AACH,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Strict-prefix credential redaction for terminal/log output.
3
+ *
4
+ * Per Q3 validation + red-team #13, redact only strings with high-confidence
5
+ * key prefixes (sk-, ghp_, AKIA, PEM blocks). Lexical "password=" / "token="
6
+ * patterns are NOT scrubbed — false-positive rate on user prompts is too high.
7
+ */
8
+ export declare function scrubSecrets(input: string): string;
9
+ export declare function scrubObject<T>(value: T): T;
10
+ //# sourceMappingURL=redact.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redact.d.ts","sourceRoot":"","sources":["../../src/orchviz/redact.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAYH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMlD;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAW1C"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Strict-prefix credential redaction for terminal/log output.
3
+ *
4
+ * Per Q3 validation + red-team #13, redact only strings with high-confidence
5
+ * key prefixes (sk-, ghp_, AKIA, PEM blocks). Lexical "password=" / "token="
6
+ * patterns are NOT scrubbed — false-positive rate on user prompts is too high.
7
+ */
8
+ const PATTERNS = [
9
+ { re: /sk-[a-zA-Z0-9_-]{20,}/g, replacement: "sk-***REDACTED***" },
10
+ { re: /ghp_[a-zA-Z0-9]{36}/g, replacement: "ghp_***REDACTED***" },
11
+ { re: /AKIA[0-9A-Z]{16}/g, replacement: "AKIA***REDACTED***" },
12
+ {
13
+ re: /-----BEGIN [A-Z ]+-----[\s\S]*?-----END [A-Z ]+-----/g,
14
+ replacement: "-----REDACTED-PEM-BLOCK-----",
15
+ },
16
+ ];
17
+ export function scrubSecrets(input) {
18
+ let out = input;
19
+ for (const { re, replacement } of PATTERNS) {
20
+ out = out.replace(re, replacement);
21
+ }
22
+ return out;
23
+ }
24
+ export function scrubObject(value) {
25
+ if (typeof value === "string")
26
+ return scrubSecrets(value);
27
+ if (Array.isArray(value))
28
+ return value.map((v) => scrubObject(v));
29
+ if (value && typeof value === "object") {
30
+ const out = {};
31
+ for (const [k, v] of Object.entries(value)) {
32
+ out[k] = scrubObject(v);
33
+ }
34
+ return out;
35
+ }
36
+ return value;
37
+ }
38
+ //# sourceMappingURL=redact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redact.js","sourceRoot":"","sources":["../../src/orchviz/redact.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,QAAQ,GAAuD;IACpE,EAAE,EAAE,EAAE,wBAAwB,EAAE,WAAW,EAAE,mBAAmB,EAAE;IAClE,EAAE,EAAE,EAAE,sBAAsB,EAAE,WAAW,EAAE,oBAAoB,EAAE;IACjE,EAAE,EAAE,EAAE,mBAAmB,EAAE,WAAW,EAAE,oBAAoB,EAAE;IAC9D;QACC,EAAE,EAAE,uDAAuD;QAC3D,WAAW,EAAE,8BAA8B;KAC3C;CACD,CAAC;AAEF,MAAM,UAAU,YAAY,CAAC,KAAa;IACzC,IAAI,GAAG,GAAG,KAAK,CAAC;IAChB,KAAK,MAAM,EAAE,EAAE,EAAE,WAAW,EAAE,IAAI,QAAQ,EAAE,CAAC;QAC5C,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;IACpC,CAAC;IACD,OAAO,GAAG,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,WAAW,CAAI,KAAQ;IACtC,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,YAAY,CAAC,KAAK,CAAiB,CAAC;IAC1E,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAiB,CAAC;IAClF,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACxC,MAAM,GAAG,GAA4B,EAAE,CAAC;QACxC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,EAAE,CAAC;YACvE,GAAG,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;QACzB,CAAC;QACD,OAAO,GAAmB,CAAC;IAC5B,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Combined sanitization for events leaving the server (SSE / API).
3
+ * - stripAnsi → defense vs ANSI-injection (red-team Critical #1)
4
+ * - scrubSecrets → defense vs key/PEM leak (red-team Medium #13 / Q3)
5
+ * - newline scrubbing → defense vs SSE frame injection (red-team RT2 #2)
6
+ *
7
+ * Recursive: walks every string in nested objects/arrays.
8
+ */
9
+ import type { AgentEvent } from "./protocol.js";
10
+ export declare function sanitizeEvent(event: AgentEvent): AgentEvent;
11
+ //# sourceMappingURL=sanitize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../src/orchviz/sanitize.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAuBhD,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,CAO3D"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Combined sanitization for events leaving the server (SSE / API).
3
+ * - stripAnsi → defense vs ANSI-injection (red-team Critical #1)
4
+ * - scrubSecrets → defense vs key/PEM leak (red-team Medium #13 / Q3)
5
+ * - newline scrubbing → defense vs SSE frame injection (red-team RT2 #2)
6
+ *
7
+ * Recursive: walks every string in nested objects/arrays.
8
+ */
9
+ import { stripAnsi } from "./parser/strip-ansi.js";
10
+ import { scrubSecrets } from "./redact.js";
11
+ function sanitizeString(s) {
12
+ // Strip ANSI, scrub secrets, then collapse \r\n / \n that would break SSE frames.
13
+ const cleaned = scrubSecrets(stripAnsi(s));
14
+ return cleaned.replace(/\r\n|\r|\n/g, " ");
15
+ }
16
+ function sanitizeValue(v) {
17
+ if (typeof v === "string")
18
+ return sanitizeString(v);
19
+ if (Array.isArray(v))
20
+ return v.map(sanitizeValue);
21
+ if (v && typeof v === "object") {
22
+ const out = {};
23
+ for (const [k, val] of Object.entries(v)) {
24
+ out[k] = sanitizeValue(val);
25
+ }
26
+ return out;
27
+ }
28
+ return v;
29
+ }
30
+ export function sanitizeEvent(event) {
31
+ return {
32
+ time: event.time,
33
+ type: event.type,
34
+ payload: sanitizeValue(event.payload),
35
+ ...(event.sessionId ? { sessionId: event.sessionId } : {}),
36
+ };
37
+ }
38
+ //# sourceMappingURL=sanitize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../../src/orchviz/sanitize.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,SAAS,cAAc,CAAC,CAAS;IAChC,kFAAkF;IAClF,MAAM,OAAO,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3C,OAAO,OAAO,CAAC,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,aAAa,CAAC,CAAU;IAChC,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,cAAc,CAAC,CAAC,CAAC,CAAC;IACpD,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAAE,OAAO,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAClD,IAAI,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;QAChC,MAAM,GAAG,GAA4B,EAAE,CAAC;QACxC,KAAK,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,CAA4B,CAAC,EAAE,CAAC;YACrE,GAAG,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;QAC7B,CAAC;QACD,OAAO,GAAG,CAAC;IACZ,CAAC;IACD,OAAO,CAAC,CAAC;AACV,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAiB;IAC9C,OAAO;QACN,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,OAAO,EAAE,aAAa,CAAC,KAAK,CAAC,OAAO,CAA4B;QAChE,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC1D,CAAC;AACH,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Security smoke tests — adversarial and regression cases for OrchvizServer.
3
+ *
4
+ * Adv-3 Symlink-out (M15): symlink inside planDir → 403; target unchanged
5
+ * Adv-4 Slow-loris (M11): body trickle triggers 5s timeout socket destroy
6
+ * R2-13 Orphaned .orchviz-tmp-* > 5min cleaned on next write
7
+ * V1-1 GET /api/plan most-recent works (no slug)
8
+ * V1-2 serveStatic 404 on unknown path
9
+ * V1-3 SSE /events responds with text/event-stream
10
+ * V1-4 Bad Host header → 403
11
+ */
12
+ export {};
13
+ //# sourceMappingURL=security-smoke.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security-smoke.test.d.ts","sourceRoot":"","sources":["../../../../src/orchviz/server/__tests__/security-smoke.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}
@@ -0,0 +1,207 @@
1
+ /**
2
+ * Security smoke tests — adversarial and regression cases for OrchvizServer.
3
+ *
4
+ * Adv-3 Symlink-out (M15): symlink inside planDir → 403; target unchanged
5
+ * Adv-4 Slow-loris (M11): body trickle triggers 5s timeout socket destroy
6
+ * R2-13 Orphaned .orchviz-tmp-* > 5min cleaned on next write
7
+ * V1-1 GET /api/plan most-recent works (no slug)
8
+ * V1-2 serveStatic 404 on unknown path
9
+ * V1-3 SSE /events responds with text/event-stream
10
+ * V1-4 Bad Host header → 403
11
+ */
12
+ import { describe, expect, it, beforeEach, afterEach } from "vitest";
13
+ import { EventEmitter } from "node:events";
14
+ import * as fs from "node:fs";
15
+ import * as os from "node:os";
16
+ import * as path from "node:path";
17
+ import * as http from "node:http";
18
+ import { OrchvizServer } from "../index.js";
19
+ import { PlanCollector } from "../../plan/collector.js";
20
+ import { computePhaseFileEtag } from "../../plan/etag.js";
21
+ import { resetPlansDirCache } from "../write-utils.js";
22
+ let active = null;
23
+ let tmpDir = null;
24
+ let serverUrl = "";
25
+ let serverPort = 0;
26
+ let currentSlug = "";
27
+ function makeProjectRoot() {
28
+ currentSlug = `260501-smoke-${Date.now()}`;
29
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "security-smoke-"));
30
+ const plansDir = path.join(tmpDir, "tasks", "plans", currentSlug);
31
+ fs.mkdirSync(plansDir, { recursive: true });
32
+ fs.writeFileSync(path.join(plansDir, "phase-01-smoke.md"), "# Phase 1\n\n## Todo List\n\n- [ ] Smoke task A\n- [ ] Smoke task B\n", "utf-8");
33
+ fs.writeFileSync(path.join(plansDir, "plan.md"), "---\ntitle: Smoke\nstatus: draft\n---\n# Smoke\n", "utf-8");
34
+ return tmpDir;
35
+ }
36
+ async function startServer(root) {
37
+ resetPlansDirCache();
38
+ const planCollector = new PlanCollector(root);
39
+ const ev = new EventEmitter();
40
+ active = new OrchvizServer({ staticDir: os.tmpdir(), eventSource: ev, projectRoot: root,
41
+ planCollector, planProvider: (slug) => planCollector.snapshot(slug) });
42
+ serverUrl = await active.start();
43
+ serverPort = active.port;
44
+ }
45
+ /** GET that resolves on headers (safe for SSE — doesn't wait for stream end). */
46
+ function headGet(urlPath, hdrs = {}) {
47
+ const u = new URL(serverUrl);
48
+ return new Promise((resolve, reject) => {
49
+ const req = http.request({ hostname: u.hostname, port: Number(u.port), path: urlPath, method: "GET",
50
+ headers: { Host: `${u.hostname}:${u.port}`, ...hdrs } }, (res) => {
51
+ const ct = typeof res.headers["content-type"] === "string" ? res.headers["content-type"] : "";
52
+ let body = "";
53
+ res.setEncoding("utf-8");
54
+ res.on("data", (c) => { body += c; });
55
+ res.on("end", () => resolve({ status: res.statusCode ?? 0, body, ct }));
56
+ // For SSE: destroy after first data or after 50ms so the stream doesn't hang
57
+ setTimeout(() => {
58
+ try {
59
+ res.destroy();
60
+ req.destroy();
61
+ }
62
+ catch { /* ok */ }
63
+ resolve({ status: res.statusCode ?? 0, body, ct });
64
+ }, 50);
65
+ res.on("error", (e) => {
66
+ if (e.code === "ECONNRESET" || e.code === "ERR_HTTP_SOCKET_CLOSED")
67
+ return;
68
+ reject(e);
69
+ });
70
+ });
71
+ req.on("error", (e) => {
72
+ if (e.code === "ECONNRESET")
73
+ return;
74
+ reject(e);
75
+ });
76
+ req.end();
77
+ });
78
+ }
79
+ function postTodo(body, extraHdrs = {}) {
80
+ const u = new URL(serverUrl);
81
+ const bodyStr = JSON.stringify(body);
82
+ return new Promise((resolve, reject) => {
83
+ const req = http.request({ hostname: u.hostname, port: Number(u.port), path: "/api/plan/todo", method: "POST",
84
+ headers: { Host: `${u.hostname}:${u.port}`, "Content-Type": "application/json",
85
+ Origin: `http://127.0.0.1:${serverPort}`, "Content-Length": String(Buffer.byteLength(bodyStr)), ...extraHdrs } }, (res) => {
86
+ let body = "";
87
+ res.setEncoding("utf-8");
88
+ res.on("data", (c) => { body += c; });
89
+ res.on("end", () => resolve({ status: res.statusCode ?? 0, body }));
90
+ res.on("error", reject);
91
+ });
92
+ req.on("error", reject);
93
+ req.write(bodyStr);
94
+ req.end();
95
+ });
96
+ }
97
+ beforeEach(async () => { delete process.env.MEOWKIT_ORCHVIZ_READONLY; await startServer(makeProjectRoot()); });
98
+ afterEach(async () => {
99
+ delete process.env.MEOWKIT_ORCHVIZ_READONLY;
100
+ if (active) {
101
+ await active.stop();
102
+ active = null;
103
+ }
104
+ if (tmpDir) {
105
+ fs.rmSync(tmpDir, { recursive: true, force: true });
106
+ tmpDir = null;
107
+ }
108
+ resetPlansDirCache();
109
+ });
110
+ describe("Adv-3: symlink-out (M15)", () => {
111
+ it("POST to symlinked phase outside planDir → 4xx; target unchanged", async () => {
112
+ const outsideTarget = path.join(os.tmpdir(), `orchviz-outside-${Date.now()}.md`);
113
+ fs.writeFileSync(outsideTarget, "sensitive data — must not be touched", "utf-8");
114
+ try {
115
+ const planDir = path.join(tmpDir, "tasks", "plans", currentSlug);
116
+ try {
117
+ fs.symlinkSync(outsideTarget, path.join(planDir, "phase-09-evil.md"));
118
+ }
119
+ catch {
120
+ fs.unlinkSync(outsideTarget);
121
+ return;
122
+ }
123
+ const etag = computePhaseFileEtag(path.join(planDir, "phase-01-smoke.md"));
124
+ const r = await postTodo({ slug: currentSlug, phase: 9, todoIdx: 0, checked: true, etag });
125
+ expect([400, 403]).toContain(r.status);
126
+ expect(JSON.parse(r.body).ok).toBeUndefined();
127
+ expect(fs.readFileSync(outsideTarget, "utf-8")).toBe("sensitive data — must not be touched");
128
+ }
129
+ finally {
130
+ try {
131
+ fs.unlinkSync(outsideTarget);
132
+ }
133
+ catch { /* ok */ }
134
+ }
135
+ });
136
+ });
137
+ describe("Adv-4: slow-loris (M11)", () => {
138
+ it("server destroys socket at 5s timeout", async () => {
139
+ const start = Date.now();
140
+ const result = await new Promise((resolve) => {
141
+ const u = new URL(serverUrl);
142
+ const req = http.request({ hostname: u.hostname, port: Number(u.port), path: "/api/plan/todo", method: "POST",
143
+ headers: { Host: `${u.hostname}:${u.port}`, "Content-Type": "application/json",
144
+ Origin: `http://127.0.0.1:${serverPort}`, "Transfer-Encoding": "chunked" } }, (res) => { res.resume(); resolve({ closed: true, elapsed: Date.now() - start }); });
145
+ req.on("error", (err) => {
146
+ const c = err.code;
147
+ resolve({ closed: c === "ECONNRESET" || c === "EPIPE" || c === "ECONNREFUSED", elapsed: Date.now() - start });
148
+ });
149
+ let sent = 0;
150
+ const tick = setInterval(() => {
151
+ sent++;
152
+ try {
153
+ req.write("{");
154
+ }
155
+ catch {
156
+ clearInterval(tick);
157
+ resolve({ closed: true, elapsed: Date.now() - start });
158
+ }
159
+ if (sent > 10) {
160
+ clearInterval(tick);
161
+ req.destroy();
162
+ resolve({ closed: false, elapsed: Date.now() - start });
163
+ }
164
+ }, 1000);
165
+ });
166
+ expect(result.closed).toBe(true);
167
+ expect(result.elapsed).toBeLessThan(6500);
168
+ }, 8000);
169
+ });
170
+ describe("R2-13: orphan tmp cleanup", () => {
171
+ it("orphaned .orchviz-tmp-* older than 5min removed on next write", async () => {
172
+ const planDir = path.join(tmpDir, "tasks", "plans", currentSlug);
173
+ const orphan1 = path.join(planDir, ".orchviz-tmp-fakeorphan1");
174
+ const orphan2 = path.join(planDir, ".orchviz-tmp-fakeorphan2");
175
+ fs.writeFileSync(orphan1, "o1");
176
+ fs.writeFileSync(orphan2, "o2");
177
+ const t = new Date(Date.now() - 6 * 60 * 1000);
178
+ fs.utimesSync(orphan1, t, t);
179
+ fs.utimesSync(orphan2, t, t);
180
+ const etag = computePhaseFileEtag(path.join(planDir, "phase-01-smoke.md"));
181
+ const r = await postTodo({ slug: currentSlug, phase: 1, todoIdx: 0, checked: true, etag });
182
+ expect(r.status).toBe(200);
183
+ expect(JSON.parse(r.body)).toMatchObject({ ok: true });
184
+ expect(fs.existsSync(orphan1)).toBe(false);
185
+ expect(fs.existsSync(orphan2)).toBe(false);
186
+ });
187
+ });
188
+ describe("V1.1 regression smokes", () => {
189
+ it("V1-1: GET /api/plan returns 200 with non-null plan", async () => {
190
+ const { status, body } = await headGet("/api/plan");
191
+ expect(status).toBe(200);
192
+ const json = JSON.parse(body);
193
+ expect(json.plan).not.toBeNull();
194
+ });
195
+ it("V1-2: GET /nonexistent → 404", async () => {
196
+ expect((await headGet("/nonexistent-path-xyz")).status).toBe(404);
197
+ });
198
+ it("V1-3: GET /events returns text/event-stream", async () => {
199
+ const { status, ct } = await headGet("/events");
200
+ expect(status).toBe(200);
201
+ expect(ct).toContain("text/event-stream");
202
+ });
203
+ it("V1-4: bad Host → 403", async () => {
204
+ expect((await headGet("/api/plan", { Host: "evil.example.com" })).status).toBe(403);
205
+ });
206
+ });
207
+ //# sourceMappingURL=security-smoke.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security-smoke.test.js","sourceRoot":"","sources":["../../../../src/orchviz/server/__tests__/security-smoke.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Integration tests for write-handlers.ts — POST /api/plan/todo.
3
+ *
4
+ * Each test spins up an ephemeral-port OrchvizServer with a temp fixture dir,
5
+ * makes HTTP requests, and verifies responses + on-disk state.
6
+ *
7
+ * Coverage (10+ cases):
8
+ * 1. 200 happy path — file mutated, ok:true, changed:true, new etag
9
+ * 2. 200 idempotent no-op — changed:false, mtime unchanged
10
+ * 3. 400 missing Origin header
11
+ * 4. 403 disallowed Origin header
12
+ * 5. 405 MEOWKIT_ORCHVIZ_READONLY=1
13
+ * 6. 409 stale etag — file unchanged
14
+ * 7. 413 body > 4KB
15
+ * 8. 415 wrong Content-Type
16
+ * 9. OPTIONS 204 — allowed origin
17
+ * 10. OPTIONS 403 — disallowed origin (no ACAO header emitted)
18
+ * 11. 400 invalid JSON
19
+ * 12. 400 zod validation failure (bad phase number)
20
+ * 13. POST to /api/plan (unrelated path) still returns 405 (v1.1 regression guard)
21
+ * 14. Phase zero-pad: POST {phase:1} matches phase-01-*.md
22
+ */
23
+ export {};
24
+ //# sourceMappingURL=write-handlers.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write-handlers.test.d.ts","sourceRoot":"","sources":["../../../../src/orchviz/server/__tests__/write-handlers.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG"}