@rubytech/create-maxy-code 0.1.461 → 0.1.463

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 (186) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/lib/graph-mcp/dist/index.d.ts +2 -1
  3. package/payload/platform/lib/graph-mcp/dist/index.d.ts.map +1 -1
  4. package/payload/platform/lib/graph-mcp/dist/index.js +14 -22
  5. package/payload/platform/lib/graph-mcp/dist/index.js.map +1 -1
  6. package/payload/platform/lib/graph-mcp/src/index.ts +15 -22
  7. package/payload/platform/lib/mcp-spawn-tee/dist/index.d.ts +8 -7
  8. package/payload/platform/lib/mcp-spawn-tee/dist/index.d.ts.map +1 -1
  9. package/payload/platform/lib/mcp-spawn-tee/dist/index.js +19 -19
  10. package/payload/platform/lib/mcp-spawn-tee/dist/index.js.map +1 -1
  11. package/payload/platform/lib/mcp-spawn-tee/src/__tests__/spawn-tee.test.ts +34 -5
  12. package/payload/platform/lib/mcp-spawn-tee/src/index.ts +22 -19
  13. package/payload/platform/lib/mcp-stderr-tee/dist/index.d.ts +35 -17
  14. package/payload/platform/lib/mcp-stderr-tee/dist/index.d.ts.map +1 -1
  15. package/payload/platform/lib/mcp-stderr-tee/dist/index.js +41 -48
  16. package/payload/platform/lib/mcp-stderr-tee/dist/index.js.map +1 -1
  17. package/payload/platform/lib/mcp-stderr-tee/src/index.ts +42 -51
  18. package/payload/platform/lib/storage-broker/dist/__tests__/audit.test.js +27 -0
  19. package/payload/platform/lib/storage-broker/dist/__tests__/audit.test.js.map +1 -1
  20. package/payload/platform/lib/storage-broker/dist/__tests__/cf-exec.test.js +49 -0
  21. package/payload/platform/lib/storage-broker/dist/__tests__/cf-exec.test.js.map +1 -1
  22. package/payload/platform/lib/storage-broker/dist/audit.d.ts +11 -0
  23. package/payload/platform/lib/storage-broker/dist/audit.d.ts.map +1 -1
  24. package/payload/platform/lib/storage-broker/dist/audit.js +16 -0
  25. package/payload/platform/lib/storage-broker/dist/audit.js.map +1 -1
  26. package/payload/platform/lib/storage-broker/dist/cf-exec.d.ts +18 -0
  27. package/payload/platform/lib/storage-broker/dist/cf-exec.d.ts.map +1 -1
  28. package/payload/platform/lib/storage-broker/dist/cf-exec.js +77 -0
  29. package/payload/platform/lib/storage-broker/dist/cf-exec.js.map +1 -1
  30. package/payload/platform/lib/storage-broker/dist/house-scoped-token.js +3 -0
  31. package/payload/platform/lib/storage-broker/dist/house-scoped-token.js.map +1 -1
  32. package/payload/platform/lib/storage-broker/dist/registry.d.ts +1 -1
  33. package/payload/platform/lib/storage-broker/dist/registry.d.ts.map +1 -1
  34. package/payload/platform/lib/storage-broker/dist/registry.js.map +1 -1
  35. package/payload/platform/lib/storage-broker/src/__tests__/audit.test.ts +32 -1
  36. package/payload/platform/lib/storage-broker/src/__tests__/cf-exec.test.ts +61 -0
  37. package/payload/platform/lib/storage-broker/src/audit.ts +45 -0
  38. package/payload/platform/lib/storage-broker/src/cf-exec.ts +91 -0
  39. package/payload/platform/lib/storage-broker/src/house-scoped-token.ts +3 -0
  40. package/payload/platform/lib/storage-broker/src/registry.ts +5 -1
  41. package/payload/platform/plugins/admin/lib/mcp-spawn-tee/index.js +19 -19
  42. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +23 -12
  43. package/payload/platform/plugins/aeo/lib/mcp-spawn-tee/index.js +19 -19
  44. package/payload/platform/plugins/browser/lib/mcp-spawn-tee/index.js +19 -19
  45. package/payload/platform/plugins/cloudflare/PLUGIN.md +1 -1
  46. package/payload/platform/plugins/cloudflare/mcp/dist/index.js +5 -5
  47. package/payload/platform/plugins/cloudflare/mcp/dist/index.js.map +1 -1
  48. package/payload/platform/plugins/cloudflare/references/hosting-sites.md +2 -0
  49. package/payload/platform/plugins/cloudflare/skills/calendar-site/SKILL.md +1 -1
  50. package/payload/platform/plugins/cloudflare/skills/site-deploy/SKILL.md +2 -0
  51. package/payload/platform/plugins/connector/lib/mcp-spawn-tee/index.js +19 -19
  52. package/payload/platform/plugins/contacts/lib/mcp-spawn-tee/index.js +19 -19
  53. package/payload/platform/plugins/docs/references/admin-session.md +3 -3
  54. package/payload/platform/plugins/docs/references/cloudflare.md +2 -0
  55. package/payload/platform/plugins/docs/references/internals.md +1 -1
  56. package/payload/platform/plugins/docs/references/outlook-guide.md +11 -4
  57. package/payload/platform/plugins/docs/references/plugins-guide.md +8 -6
  58. package/payload/platform/plugins/email/lib/mcp-spawn-tee/index.js +19 -19
  59. package/payload/platform/plugins/filesystem/lib/mcp-spawn-tee/index.js +19 -19
  60. package/payload/platform/plugins/graph-viewer/lib/mcp-spawn-tee/index.js +19 -19
  61. package/payload/platform/plugins/memory/PLUGIN.md +1 -1
  62. package/payload/platform/plugins/memory/lib/mcp-spawn-tee/index.js +19 -19
  63. package/payload/platform/plugins/memory/mcp/dist/lib/log-ingest.js +2 -2
  64. package/payload/platform/plugins/memory/mcp/dist/lib/log-ingest.js.map +1 -1
  65. package/payload/platform/plugins/outlook/.claude-plugin/plugin.json +1 -1
  66. package/payload/platform/plugins/outlook/PLUGIN.md +2 -2
  67. package/payload/platform/plugins/outlook/lib/mcp-spawn-tee/index.js +19 -19
  68. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-threaded.test.d.ts +2 -0
  69. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-threaded.test.d.ts.map +1 -0
  70. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-threaded.test.js +238 -0
  71. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-threaded.test.js.map +1 -0
  72. package/payload/platform/plugins/outlook/mcp/dist/index.js +9 -5
  73. package/payload/platform/plugins/outlook/mcp/dist/index.js.map +1 -1
  74. package/payload/platform/plugins/outlook/mcp/dist/lib/message.d.ts +1 -6
  75. package/payload/platform/plugins/outlook/mcp/dist/lib/message.d.ts.map +1 -1
  76. package/payload/platform/plugins/outlook/mcp/dist/lib/message.js +9 -17
  77. package/payload/platform/plugins/outlook/mcp/dist/lib/message.js.map +1 -1
  78. package/payload/platform/plugins/outlook/mcp/dist/lib/recipients.d.ts +56 -0
  79. package/payload/platform/plugins/outlook/mcp/dist/lib/recipients.d.ts.map +1 -0
  80. package/payload/platform/plugins/outlook/mcp/dist/lib/recipients.js +40 -0
  81. package/payload/platform/plugins/outlook/mcp/dist/lib/recipients.js.map +1 -0
  82. package/payload/platform/plugins/outlook/mcp/dist/tools/draft-edit.d.ts.map +1 -1
  83. package/payload/platform/plugins/outlook/mcp/dist/tools/draft-edit.js +1 -3
  84. package/payload/platform/plugins/outlook/mcp/dist/tools/draft-edit.js.map +1 -1
  85. package/payload/platform/plugins/outlook/mcp/dist/tools/draft.d.ts +58 -9
  86. package/payload/platform/plugins/outlook/mcp/dist/tools/draft.d.ts.map +1 -1
  87. package/payload/platform/plugins/outlook/mcp/dist/tools/draft.js +97 -18
  88. package/payload/platform/plugins/outlook/mcp/dist/tools/draft.js.map +1 -1
  89. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-fetch-body.d.ts.map +1 -1
  90. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-fetch-body.js +1 -3
  91. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-fetch-body.js.map +1 -1
  92. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-reply.d.ts.map +1 -1
  93. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-reply.js +3 -18
  94. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-reply.js.map +1 -1
  95. package/payload/platform/plugins/outlook/skills/outlook/SKILL.md +5 -2
  96. package/payload/platform/plugins/quickbooks/lib/mcp-spawn-tee/index.js +19 -19
  97. package/payload/platform/plugins/replicate/lib/mcp-spawn-tee/index.js +19 -19
  98. package/payload/platform/plugins/scheduling/lib/mcp-spawn-tee/index.js +19 -19
  99. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/agent-turn-dispatch.test.js +6 -32
  100. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/agent-turn-dispatch.test.js.map +1 -1
  101. package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts.map +1 -1
  102. package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js +10 -30
  103. package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js.map +1 -1
  104. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-cancel.test.js +24 -21
  105. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-cancel.test.js.map +1 -1
  106. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-cancel.d.ts +27 -18
  107. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-cancel.d.ts.map +1 -1
  108. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-cancel.js +31 -27
  109. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-cancel.js.map +1 -1
  110. package/payload/platform/plugins/storage-broker/PLUGIN.md +9 -1
  111. package/payload/platform/plugins/storage-broker/lib/mcp-spawn-tee/index.js +19 -19
  112. package/payload/platform/plugins/storage-broker/mcp/dist/confine-path.d.ts.map +1 -1
  113. package/payload/platform/plugins/storage-broker/mcp/dist/confine-path.js +16 -5
  114. package/payload/platform/plugins/storage-broker/mcp/dist/confine-path.js.map +1 -1
  115. package/payload/platform/plugins/storage-broker/mcp/dist/index.js +49 -0
  116. package/payload/platform/plugins/storage-broker/mcp/dist/index.js.map +1 -1
  117. package/payload/platform/plugins/telegram/lib/mcp-spawn-tee/index.js +19 -19
  118. package/payload/platform/plugins/url-get/lib/mcp-spawn-tee/index.js +19 -19
  119. package/payload/platform/plugins/voice-mirror/lib/mcp-spawn-tee/index.js +19 -19
  120. package/payload/platform/plugins/web-designer/PLUGIN.md +1 -1
  121. package/payload/platform/plugins/web-designer/commands/website.md +6 -0
  122. package/payload/platform/plugins/web-designer/skills/web-design/references/deploy.md +12 -0
  123. package/payload/platform/plugins/whatsapp/lib/mcp-spawn-tee/index.js +19 -19
  124. package/payload/platform/plugins/work/lib/mcp-spawn-tee/index.js +19 -19
  125. package/payload/platform/plugins/workflows/lib/mcp-spawn-tee/index.js +19 -19
  126. package/payload/platform/scripts/__tests__/logs-rotate.test.sh +24 -20
  127. package/payload/platform/scripts/logs-read.sh +31 -0
  128. package/payload/platform/scripts/logs-rotate.sh +21 -18
  129. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
  130. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +2 -0
  131. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
  132. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
  133. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +37 -0
  134. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
  135. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts +5 -3
  136. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts.map +1 -1
  137. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
  138. package/payload/platform/services/telegram-channel/dist/server.d.ts.map +1 -1
  139. package/payload/platform/services/telegram-channel/dist/server.js +0 -4
  140. package/payload/platform/services/telegram-channel/dist/server.js.map +1 -1
  141. package/payload/platform/services/webchat-channel/dist/server.d.ts.map +1 -1
  142. package/payload/platform/services/webchat-channel/dist/server.js +0 -4
  143. package/payload/platform/services/webchat-channel/dist/server.js.map +1 -1
  144. package/payload/platform/services/whatsapp-channel/dist/server.d.ts.map +1 -1
  145. package/payload/platform/services/whatsapp-channel/dist/server.js +0 -4
  146. package/payload/platform/services/whatsapp-channel/dist/server.js.map +1 -1
  147. package/payload/server/{chunk-JXWFVE5X.js → chunk-BBSPFN45.js} +65 -0
  148. package/payload/server/public/assets/{AdminLoginScreens-BFbpkEUS.js → AdminLoginScreens-Bed8SDxY.js} +1 -1
  149. package/payload/server/public/assets/{AdminShell-CdOGObaZ.js → AdminShell-BLh9O6dn.js} +1 -1
  150. package/payload/server/public/assets/{Checkbox-RFD_F0c0.js → Checkbox-BC_KSbpS.js} +1 -1
  151. package/payload/server/public/assets/{admin-CYGdL-1O.js → admin-DfWgJVI3.js} +1 -1
  152. package/payload/server/public/assets/{browser-DVfa_plj.js → browser-C0vkv-hH.js} +1 -1
  153. package/payload/server/public/assets/{calendar-JC_Dxa4n.js → calendar-_pfHw0Hp.js} +1 -1
  154. package/payload/server/public/assets/chat-DYT5H81o.js +1 -0
  155. package/payload/server/public/assets/chevron-left-BnpVBu51.js +1 -0
  156. package/payload/server/public/assets/data-CR-fbPWr.js +1 -0
  157. package/payload/server/public/assets/{graph-hBUrRSkr.js → graph-BZiudUGr.js} +1 -1
  158. package/payload/server/public/assets/{graph-labels-CHh6zs8t.js → graph-labels-BzmmJwCR.js} +1 -1
  159. package/payload/server/public/assets/{maximize-2-DjxE4rm9.js → maximize-2-Bhdsv0U-.js} +1 -1
  160. package/payload/server/public/assets/{operator-BqU9SQuu.js → operator-gm2eP4r6.js} +1 -1
  161. package/payload/server/public/assets/{page-DiQhU6lD.js → page-8AB3jUa_.js} +1 -1
  162. package/payload/server/public/assets/page-BoPorLg-.js +32 -0
  163. package/payload/server/public/assets/{public-Cu_eALgY.js → public-DqJk6qgW.js} +1 -1
  164. package/payload/server/public/assets/{rotate-ccw-F9DsSTSJ.js → rotate-ccw-D_5cETGt.js} +1 -1
  165. package/payload/server/public/assets/{tasks-CE-D0f50.js → tasks-EyKLXINi.js} +1 -1
  166. package/payload/server/public/assets/{time-entry-format-D2rsWhov.js → time-entry-format-DAwmmR3i.js} +1 -1
  167. package/payload/server/public/assets/{useCopyFeedback-QxOmoobV.js → useCopyFeedback-rOWd_lzl.js} +1 -1
  168. package/payload/server/public/assets/{useSelectionMode-RIzNqFjV.js → useSelectionMode-DDmLmPph.js} +1 -1
  169. package/payload/server/public/assets/{useSubAccountSwitcher-BW_fK1Nt.css → useSubAccountSwitcher-pu0jjLCz.css} +1 -1
  170. package/payload/server/public/assets/{useVoiceRecorder-WrWurSYI.js → useVoiceRecorder-azG8zSUI.js} +1 -1
  171. package/payload/server/public/browser.html +5 -5
  172. package/payload/server/public/calendar.html +6 -6
  173. package/payload/server/public/chat.html +12 -12
  174. package/payload/server/public/data.html +10 -10
  175. package/payload/server/public/graph.html +11 -11
  176. package/payload/server/public/index.html +13 -13
  177. package/payload/server/public/operator.html +14 -14
  178. package/payload/server/public/public.html +12 -12
  179. package/payload/server/public/tasks.html +5 -5
  180. package/payload/server/server.js +596 -235
  181. package/payload/server/{src-4F37OHLK.js → src-YLGAZY36.js} +5 -1
  182. package/payload/server/public/assets/chat-Yf8Nkop8.js +0 -1
  183. package/payload/server/public/assets/chevron-left-CAiAUBxO.js +0 -1
  184. package/payload/server/public/assets/data-hqdYXaEn.js +0 -1
  185. package/payload/server/public/assets/page-B4c4_4HP.js +0 -32
  186. /package/payload/server/public/assets/{useSubAccountSwitcher-wo_qGW-I.js → useSubAccountSwitcher-CU-lOxTd.js} +0 -0
@@ -1,10 +1,17 @@
1
1
  /**
2
- * MCP server stderr tee — dual-destination log capture.
2
+ * MCP server stderr tee — per-conversation stream-log capture.
3
3
  *
4
4
  * Claude Code spawns MCP servers as child processes and consumes their stderr
5
5
  * internally. The platform cannot intercept at the spawn level. Each server
6
6
  * must tee its own stderr so diagnostic output is retrievable.
7
7
  *
8
+ * This module owns ONE destination: the per-conversation stream log. The raw
9
+ * per-server sink belongs to mcp-spawn-tee (`mcp-<name>-<SESSION_ID>.log`),
10
+ * which is every spawned caller's real parent and writes with appendFileSync.
11
+ * Task 1721 retired this module's own raw file: it was date-named after the
12
+ * process's boot day, no reader parsed that date, and mcp-spawn-tee wrote the
13
+ * same path, so every line landed twice.
14
+ *
8
15
  * ┌─────────────────────────┐
9
16
  * │ MCP server process │
10
17
  * │ │
@@ -15,18 +22,25 @@
15
22
  * │ │ │
16
23
  * │ ├──► original stderr (consumed by Claude Code — opaque)
17
24
  * │ │
18
- * │ ├──► mcp-{name}-stderr-{YYYY-MM-DD}.log (raw chunks, per-plugin)
19
- * │ │
20
25
  * │ └──► $STREAM_LOG_PATH (per-line, prefixed)
21
26
  * │ "[<iso>] [mcp:{name}] <line>"
22
27
  * └─────────────────────────┘
23
28
  *
24
- * $STREAM_LOG_PATH is set by the spawner (`getMcpServers` in `claude-agent.ts`)
25
- * to the per-conversation stream log file. The MCP server code itself knows
26
- * nothing about conversations — it just trusts the spawner's path. This is
27
- * the scope boundary introduced: the tee is attached per spawn,
28
- * not per MCP-server process lifetime. Servers spawned for conversation A
29
- * write to conversation A's file; servers for B write to B's file.
29
+ * $STREAM_LOG_PATH is meant to be set by the spawner to the per-conversation
30
+ * stream log file. The MCP server code itself knows nothing about
31
+ * conversations — it just trusts the spawner's path. This is the scope
32
+ * boundary intended: the tee is attached per spawn, not per MCP-server process
33
+ * lifetime. Servers spawned for conversation A write to conversation A's file;
34
+ * servers for B write to B's file.
35
+ *
36
+ * NOTE: no spawner actually sets it. `pty-spawner.ts` and `rc-daemon.ts`'s
37
+ * `buildRcChildEnv` stamp LOG_DIR and SESSION_ID but not STREAM_LOG_PATH, and
38
+ * the only assignment in the repo is `plugins/memory/mcp/scripts/boot-smoke.sh`
39
+ * (a smoke harness). So in production this module takes its skip path and
40
+ * patches nothing. The raw bytes are not lost — mcp-spawn-tee writes them to
41
+ * the per-session sink regardless. Whether to wire this up or retire the module
42
+ * is Task 1736. Do not read the paragraph above as a description of live
43
+ * behaviour until that lands.
30
44
  *
31
45
  * Every decision is logged via `[mcp-tee-*]` markers on both the target file
32
46
  * and the original stderr so an investigator can confirm from the stream log
@@ -34,16 +48,20 @@
34
48
  */
35
49
  /**
36
50
  * Patch process.stderr.write to tee to:
37
- * 1. Per-server raw log (`mcp-<serverName>-stderr-<date>.log` under LOG_DIR).
38
- * 2. The per-conversation stream log at `STREAM_LOG_PATH`per-line, prefixed.
39
- * 3. The original stderr (consumed by Claude Code) — always preserved.
40
- *
41
- * LOG_DIR absent skip per-server raw file (dev mode / tool discovery).
42
- * STREAM_LOG_PATH absent skip stream-log destination (older spawner or
43
- * standalone invocation). In both absent cases, stderr works unchanged —
44
- * a `[mcp-tee-skip]` marker is written to original stderr so the skip is
51
+ * 1. The per-conversation stream log at `STREAM_LOG_PATH` per-line, prefixed.
52
+ * 2. The original stderr (consumed by Claude Code) always preserved.
53
+ *
54
+ * STREAM_LOG_PATH absent → skip the stream-log destination (older spawner or
55
+ * standalone invocation) and leave stderr entirely unpatched. A
56
+ * `[mcp-tee-skip]` marker is written to original stderr so the skip is
45
57
  * visible to journalctl-level readers.
46
58
  *
59
+ * This module writes NO raw per-server file and holds NO write stream. Task
60
+ * 1721 moved the raw sink to mcp-spawn-tee, which is every spawned caller's
61
+ * real parent: the two modules were writing the same per-date file, so every
62
+ * line landed twice, and the held stream was the sole reason Task 1706 could
63
+ * not age-purge these logs.
64
+ *
47
65
  * Safe to call once at MCP server module load. Refused on second call to
48
66
  * prevent stacking patches.
49
67
  */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAeH;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CA8ItD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AAeH;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAmHtD"}
@@ -1,11 +1,18 @@
1
1
  "use strict";
2
2
  /**
3
- * MCP server stderr tee — dual-destination log capture.
3
+ * MCP server stderr tee — per-conversation stream-log capture.
4
4
  *
5
5
  * Claude Code spawns MCP servers as child processes and consumes their stderr
6
6
  * internally. The platform cannot intercept at the spawn level. Each server
7
7
  * must tee its own stderr so diagnostic output is retrievable.
8
8
  *
9
+ * This module owns ONE destination: the per-conversation stream log. The raw
10
+ * per-server sink belongs to mcp-spawn-tee (`mcp-<name>-<SESSION_ID>.log`),
11
+ * which is every spawned caller's real parent and writes with appendFileSync.
12
+ * Task 1721 retired this module's own raw file: it was date-named after the
13
+ * process's boot day, no reader parsed that date, and mcp-spawn-tee wrote the
14
+ * same path, so every line landed twice.
15
+ *
9
16
  * ┌─────────────────────────┐
10
17
  * │ MCP server process │
11
18
  * │ │
@@ -16,18 +23,25 @@
16
23
  * │ │ │
17
24
  * │ ├──► original stderr (consumed by Claude Code — opaque)
18
25
  * │ │
19
- * │ ├──► mcp-{name}-stderr-{YYYY-MM-DD}.log (raw chunks, per-plugin)
20
- * │ │
21
26
  * │ └──► $STREAM_LOG_PATH (per-line, prefixed)
22
27
  * │ "[<iso>] [mcp:{name}] <line>"
23
28
  * └─────────────────────────┘
24
29
  *
25
- * $STREAM_LOG_PATH is set by the spawner (`getMcpServers` in `claude-agent.ts`)
26
- * to the per-conversation stream log file. The MCP server code itself knows
27
- * nothing about conversations — it just trusts the spawner's path. This is
28
- * the scope boundary introduced: the tee is attached per spawn,
29
- * not per MCP-server process lifetime. Servers spawned for conversation A
30
- * write to conversation A's file; servers for B write to B's file.
30
+ * $STREAM_LOG_PATH is meant to be set by the spawner to the per-conversation
31
+ * stream log file. The MCP server code itself knows nothing about
32
+ * conversations — it just trusts the spawner's path. This is the scope
33
+ * boundary intended: the tee is attached per spawn, not per MCP-server process
34
+ * lifetime. Servers spawned for conversation A write to conversation A's file;
35
+ * servers for B write to B's file.
36
+ *
37
+ * NOTE: no spawner actually sets it. `pty-spawner.ts` and `rc-daemon.ts`'s
38
+ * `buildRcChildEnv` stamp LOG_DIR and SESSION_ID but not STREAM_LOG_PATH, and
39
+ * the only assignment in the repo is `plugins/memory/mcp/scripts/boot-smoke.sh`
40
+ * (a smoke harness). So in production this module takes its skip path and
41
+ * patches nothing. The raw bytes are not lost — mcp-spawn-tee writes them to
42
+ * the per-session sink regardless. Whether to wire this up or retire the module
43
+ * is Task 1736. Do not read the paragraph above as a description of live
44
+ * behaviour until that lands.
31
45
  *
32
46
  * Every decision is logged via `[mcp-tee-*]` markers on both the target file
33
47
  * and the original stderr so an investigator can confirm from the stream log
@@ -44,21 +58,24 @@ const node_string_decoder_1 = require("node:string_decoder");
44
58
  const INIT_MARKER = Symbol.for("maxy.mcpStderrTee.installed");
45
59
  /**
46
60
  * Patch process.stderr.write to tee to:
47
- * 1. Per-server raw log (`mcp-<serverName>-stderr-<date>.log` under LOG_DIR).
48
- * 2. The per-conversation stream log at `STREAM_LOG_PATH`per-line, prefixed.
49
- * 3. The original stderr (consumed by Claude Code) — always preserved.
61
+ * 1. The per-conversation stream log at `STREAM_LOG_PATH` per-line, prefixed.
62
+ * 2. The original stderr (consumed by Claude Code) always preserved.
50
63
  *
51
- * LOG_DIR absent → skip per-server raw file (dev mode / tool discovery).
52
- * STREAM_LOG_PATH absent skip stream-log destination (older spawner or
53
- * standalone invocation). In both absent cases, stderr works unchanged
54
- * a `[mcp-tee-skip]` marker is written to original stderr so the skip is
64
+ * STREAM_LOG_PATH absent → skip the stream-log destination (older spawner or
65
+ * standalone invocation) and leave stderr entirely unpatched. A
66
+ * `[mcp-tee-skip]` marker is written to original stderr so the skip is
55
67
  * visible to journalctl-level readers.
56
68
  *
69
+ * This module writes NO raw per-server file and holds NO write stream. Task
70
+ * 1721 moved the raw sink to mcp-spawn-tee, which is every spawned caller's
71
+ * real parent: the two modules were writing the same per-date file, so every
72
+ * line landed twice, and the held stream was the sole reason Task 1706 could
73
+ * not age-purge these logs.
74
+ *
57
75
  * Safe to call once at MCP server module load. Refused on second call to
58
76
  * prevent stacking patches.
59
77
  */
60
78
  function initStderrTee(serverName) {
61
- const logDir = process.env.LOG_DIR;
62
79
  const streamLogPath = process.env.STREAM_LOG_PATH;
63
80
  // Refuse repeat patches — stacking them would double-log every chunk
64
81
  // and corrupt the re-entrancy guard (originalWrite would capture the
@@ -73,27 +90,7 @@ function initStderrTee(serverName) {
73
90
  const skipTee = (reason, destination) => {
74
91
  originalWrite(`${tsPrefix()} [platform] [mcp-tee-skip] server=${serverName} destination=${destination} reason=${JSON.stringify(reason)}\n`);
75
92
  };
76
- // --- Destination 1: per-server raw file (optional, existing behaviour)
77
- let perServerStream;
78
- if (logDir) {
79
- try {
80
- (0, node_fs_1.mkdirSync)(logDir, { recursive: true });
81
- const date = new Date().toISOString().slice(0, 10);
82
- perServerStream = (0, node_fs_1.createWriteStream)((0, node_path_1.resolve)(logDir, `mcp-${serverName}-stderr-${date}.log`), { flags: "a" });
83
- perServerStream.on("error", (err) => {
84
- originalWrite(`${tsPrefix()} [platform] [mcp-tee-error] server=${serverName} destination=per-server reason=${JSON.stringify(err.message)}\n`);
85
- });
86
- }
87
- catch (err) {
88
- const msg = err instanceof Error ? err.message : String(err);
89
- skipTee(msg, "per-server");
90
- perServerStream = undefined;
91
- }
92
- }
93
- else {
94
- skipTee("LOG_DIR not set", "per-server");
95
- }
96
- // --- Destination 2: per-conversation stream log
93
+ // --- Destination: per-conversation stream log
97
94
  let streamLogStream;
98
95
  if (streamLogPath) {
99
96
  try {
@@ -116,10 +113,10 @@ function initStderrTee(serverName) {
116
113
  else {
117
114
  skipTee("STREAM_LOG_PATH not set", "stream-log");
118
115
  }
119
- // If neither tee target is available, leave stderr untouched patching
120
- // the writer to a no-op tee would still consume event-loop cycles on
121
- // every write for zero observability gain.
122
- if (!perServerStream && !streamLogStream) {
116
+ // No stream-log target leave stderr untouched. Patching the writer to a
117
+ // no-op tee would still consume event-loop cycles on every write for zero
118
+ // observability gain.
119
+ if (!streamLogStream) {
123
120
  return;
124
121
  }
125
122
  // Line buffer — accumulates characters written to stderr so complete
@@ -149,11 +146,7 @@ function initStderrTee(serverName) {
149
146
  }
150
147
  };
151
148
  process.stderr.write = (chunk, ...args) => {
152
- // 1. Per-server raw file behaviour (no prefix).
153
- if (perServerStream && !perServerStream.destroyed) {
154
- perServerStream.write(chunk);
155
- }
156
- // 2. Stream log — per-line, prefixed.
149
+ // 1. Stream logper-line, prefixed.
157
150
  if (streamLogStream) {
158
151
  try {
159
152
  const text = typeof chunk === "string"
@@ -166,7 +159,7 @@ function initStderrTee(serverName) {
166
159
  originalWrite(`${tsPrefix()} [platform] [mcp-tee-emit-error] server=${serverName} reason=${JSON.stringify(msg)}\n`);
167
160
  }
168
161
  }
169
- // 3. Original stderr — Claude Code still gets what it's always got.
162
+ // 2. Original stderr — Claude Code still gets what it's always got.
170
163
  return originalWrite(chunk, ...args);
171
164
  };
172
165
  // Mark the patch so a second initStderrTee() call is refused at the top.
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -1,10 +1,17 @@
1
1
  /**
2
- * MCP server stderr tee — dual-destination log capture.
2
+ * MCP server stderr tee — per-conversation stream-log capture.
3
3
  *
4
4
  * Claude Code spawns MCP servers as child processes and consumes their stderr
5
5
  * internally. The platform cannot intercept at the spawn level. Each server
6
6
  * must tee its own stderr so diagnostic output is retrievable.
7
7
  *
8
+ * This module owns ONE destination: the per-conversation stream log. The raw
9
+ * per-server sink belongs to mcp-spawn-tee (`mcp-<name>-<SESSION_ID>.log`),
10
+ * which is every spawned caller's real parent and writes with appendFileSync.
11
+ * Task 1721 retired this module's own raw file: it was date-named after the
12
+ * process's boot day, no reader parsed that date, and mcp-spawn-tee wrote the
13
+ * same path, so every line landed twice.
14
+ *
8
15
  * ┌─────────────────────────┐
9
16
  * │ MCP server process │
10
17
  * │ │
@@ -15,18 +22,25 @@
15
22
  * │ │ │
16
23
  * │ ├──► original stderr (consumed by Claude Code — opaque)
17
24
  * │ │
18
- * │ ├──► mcp-{name}-stderr-{YYYY-MM-DD}.log (raw chunks, per-plugin)
19
- * │ │
20
25
  * │ └──► $STREAM_LOG_PATH (per-line, prefixed)
21
26
  * │ "[<iso>] [mcp:{name}] <line>"
22
27
  * └─────────────────────────┘
23
28
  *
24
- * $STREAM_LOG_PATH is set by the spawner (`getMcpServers` in `claude-agent.ts`)
25
- * to the per-conversation stream log file. The MCP server code itself knows
26
- * nothing about conversations — it just trusts the spawner's path. This is
27
- * the scope boundary introduced: the tee is attached per spawn,
28
- * not per MCP-server process lifetime. Servers spawned for conversation A
29
- * write to conversation A's file; servers for B write to B's file.
29
+ * $STREAM_LOG_PATH is meant to be set by the spawner to the per-conversation
30
+ * stream log file. The MCP server code itself knows nothing about
31
+ * conversations — it just trusts the spawner's path. This is the scope
32
+ * boundary intended: the tee is attached per spawn, not per MCP-server process
33
+ * lifetime. Servers spawned for conversation A write to conversation A's file;
34
+ * servers for B write to B's file.
35
+ *
36
+ * NOTE: no spawner actually sets it. `pty-spawner.ts` and `rc-daemon.ts`'s
37
+ * `buildRcChildEnv` stamp LOG_DIR and SESSION_ID but not STREAM_LOG_PATH, and
38
+ * the only assignment in the repo is `plugins/memory/mcp/scripts/boot-smoke.sh`
39
+ * (a smoke harness). So in production this module takes its skip path and
40
+ * patches nothing. The raw bytes are not lost — mcp-spawn-tee writes them to
41
+ * the per-session sink regardless. Whether to wire this up or retire the module
42
+ * is Task 1736. Do not read the paragraph above as a description of live
43
+ * behaviour until that lands.
30
44
  *
31
45
  * Every decision is logged via `[mcp-tee-*]` markers on both the target file
32
46
  * and the original stderr so an investigator can confirm from the stream log
@@ -38,7 +52,7 @@ import {
38
52
  createWriteStream,
39
53
  type WriteStream,
40
54
  } from "node:fs";
41
- import { resolve, dirname } from "node:path";
55
+ import { dirname } from "node:path";
42
56
  import { StringDecoder } from "node:string_decoder";
43
57
 
44
58
  // Marker on process.stderr.write so repeat calls to initStderrTee() are
@@ -48,21 +62,24 @@ const INIT_MARKER = Symbol.for("maxy.mcpStderrTee.installed");
48
62
 
49
63
  /**
50
64
  * Patch process.stderr.write to tee to:
51
- * 1. Per-server raw log (`mcp-<serverName>-stderr-<date>.log` under LOG_DIR).
52
- * 2. The per-conversation stream log at `STREAM_LOG_PATH`per-line, prefixed.
53
- * 3. The original stderr (consumed by Claude Code) — always preserved.
65
+ * 1. The per-conversation stream log at `STREAM_LOG_PATH` per-line, prefixed.
66
+ * 2. The original stderr (consumed by Claude Code) always preserved.
54
67
  *
55
- * LOG_DIR absent → skip per-server raw file (dev mode / tool discovery).
56
- * STREAM_LOG_PATH absent skip stream-log destination (older spawner or
57
- * standalone invocation). In both absent cases, stderr works unchanged
58
- * a `[mcp-tee-skip]` marker is written to original stderr so the skip is
68
+ * STREAM_LOG_PATH absent → skip the stream-log destination (older spawner or
69
+ * standalone invocation) and leave stderr entirely unpatched. A
70
+ * `[mcp-tee-skip]` marker is written to original stderr so the skip is
59
71
  * visible to journalctl-level readers.
60
72
  *
73
+ * This module writes NO raw per-server file and holds NO write stream. Task
74
+ * 1721 moved the raw sink to mcp-spawn-tee, which is every spawned caller's
75
+ * real parent: the two modules were writing the same per-date file, so every
76
+ * line landed twice, and the held stream was the sole reason Task 1706 could
77
+ * not age-purge these logs.
78
+ *
61
79
  * Safe to call once at MCP server module load. Refused on second call to
62
80
  * prevent stacking patches.
63
81
  */
64
82
  export function initStderrTee(serverName: string): void {
65
- const logDir = process.env.LOG_DIR;
66
83
  const streamLogPath = process.env.STREAM_LOG_PATH;
67
84
 
68
85
  // Refuse repeat patches — stacking them would double-log every chunk
@@ -80,29 +97,7 @@ export function initStderrTee(serverName: string): void {
80
97
  originalWrite(`${tsPrefix()} [platform] [mcp-tee-skip] server=${serverName} destination=${destination} reason=${JSON.stringify(reason)}\n`);
81
98
  };
82
99
 
83
- // --- Destination 1: per-server raw file (optional, existing behaviour)
84
- let perServerStream: WriteStream | undefined;
85
- if (logDir) {
86
- try {
87
- mkdirSync(logDir, { recursive: true });
88
- const date = new Date().toISOString().slice(0, 10);
89
- perServerStream = createWriteStream(
90
- resolve(logDir, `mcp-${serverName}-stderr-${date}.log`),
91
- { flags: "a" },
92
- );
93
- perServerStream.on("error", (err) => {
94
- originalWrite(`${tsPrefix()} [platform] [mcp-tee-error] server=${serverName} destination=per-server reason=${JSON.stringify(err.message)}\n`);
95
- });
96
- } catch (err) {
97
- const msg = err instanceof Error ? err.message : String(err);
98
- skipTee(msg, "per-server");
99
- perServerStream = undefined;
100
- }
101
- } else {
102
- skipTee("LOG_DIR not set", "per-server");
103
- }
104
-
105
- // --- Destination 2: per-conversation stream log
100
+ // --- Destination: per-conversation stream log
106
101
  let streamLogStream: WriteStream | undefined;
107
102
  if (streamLogPath) {
108
103
  try {
@@ -124,10 +119,10 @@ export function initStderrTee(serverName: string): void {
124
119
  skipTee("STREAM_LOG_PATH not set", "stream-log");
125
120
  }
126
121
 
127
- // If neither tee target is available, leave stderr untouched patching
128
- // the writer to a no-op tee would still consume event-loop cycles on
129
- // every write for zero observability gain.
130
- if (!perServerStream && !streamLogStream) {
122
+ // No stream-log target leave stderr untouched. Patching the writer to a
123
+ // no-op tee would still consume event-loop cycles on every write for zero
124
+ // observability gain.
125
+ if (!streamLogStream) {
131
126
  return;
132
127
  }
133
128
 
@@ -161,11 +156,7 @@ export function initStderrTee(serverName: string): void {
161
156
  chunk: string | Uint8Array,
162
157
  ...args: unknown[]
163
158
  ): boolean => {
164
- // 1. Per-server raw file behaviour (no prefix).
165
- if (perServerStream && !perServerStream.destroyed) {
166
- perServerStream.write(chunk);
167
- }
168
- // 2. Stream log — per-line, prefixed.
159
+ // 1. Stream logper-line, prefixed.
169
160
  if (streamLogStream) {
170
161
  try {
171
162
  const text = typeof chunk === "string"
@@ -177,7 +168,7 @@ export function initStderrTee(serverName: string): void {
177
168
  originalWrite(`${tsPrefix()} [platform] [mcp-tee-emit-error] server=${serverName} reason=${JSON.stringify(msg)}\n`);
178
169
  }
179
170
  }
180
- // 3. Original stderr — Claude Code still gets what it's always got.
171
+ // 2. Original stderr — Claude Code still gets what it's always got.
181
172
  return (originalWrite as (chunk: string | Uint8Array, ...a: unknown[]) => boolean)(chunk, ...args);
182
173
  };
183
174
  // Mark the patch so a second initStderrTee() call is refused at the top.
@@ -43,4 +43,31 @@ const clean = {
43
43
  });
44
44
  strict_1.default.ok(strays.some((s) => s.kind === "account-wide-token" && s.detail === "acc-b:CLOUDFLARE_API_TOKEN"));
45
45
  });
46
+ // --- Task 1728: Pages ownership reconcile --------------------------------
47
+ (0, node_test_1.default)("reconcilePages reports a live project with no owner as an orphan", async () => {
48
+ const r = await (0, audit_js_1.reconcilePages)({
49
+ cfProjects: async () => ["glsmithandsons", "ac-electrical"],
50
+ registeredProjects: async () => ["ac-electrical"],
51
+ });
52
+ strict_1.default.deepEqual(r.orphans, ["glsmithandsons"]);
53
+ strict_1.default.deepEqual(r.phantoms, []);
54
+ strict_1.default.equal(r.projects, 2);
55
+ strict_1.default.equal(r.registered, 1);
56
+ });
57
+ (0, node_test_1.default)("reconcilePages reports a registered project Cloudflare does not have as a phantom", async () => {
58
+ const r = await (0, audit_js_1.reconcilePages)({
59
+ cfProjects: async () => ["ac-electrical"],
60
+ registeredProjects: async () => ["ac-electrical", "deleted-site"],
61
+ });
62
+ strict_1.default.deepEqual(r.orphans, []);
63
+ strict_1.default.deepEqual(r.phantoms, ["deleted-site"]);
64
+ });
65
+ (0, node_test_1.default)("reconcilePages is clean when every live project has exactly one owner", async () => {
66
+ const r = await (0, audit_js_1.reconcilePages)({
67
+ cfProjects: async () => ["a", "b"],
68
+ registeredProjects: async () => ["b", "a"],
69
+ });
70
+ strict_1.default.deepEqual(r.orphans, []);
71
+ strict_1.default.deepEqual(r.phantoms, []);
72
+ });
46
73
  //# sourceMappingURL=audit.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"audit.test.js","sourceRoot":"","sources":["../../src/__tests__/audit.test.ts"],"names":[],"mappings":";;;;;AAAA,0DAA6B;AAC7B,gEAAwC;AACxC,0CAA+D;AAE/D,MAAM,KAAK,GAAc;IACvB,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,WAAW,CAAC;IAC/B,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,EAAE;IACpB,eAAe,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/D,mBAAmB,EAAE,KAAK,IAAI,EAAE,CAAC;QAC/B,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,2CAA2C,EAAE;KAC1F;CACF,CAAC;AAEF,IAAA,mBAAI,EAAC,mCAAmC,EAAE,KAAK,IAAI,EAAE;IACnD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAA,2BAAgB,EAAC,KAAK,CAAC,CAAC;IACjD,gBAAM,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAC/B,CAAC,CAAC,CAAC;AAEH,IAAA,mBAAI,EAAC,mCAAmC,EAAE,KAAK,IAAI,EAAE;IACnD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAA,2BAAgB,EAAC;QACxC,GAAG,KAAK;QACR,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,kBAAkB,CAAC;KACpD,CAAC,CAAC;IACH,gBAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,iBAAiB,IAAI,CAAC,CAAC,MAAM,KAAK,kBAAkB,CAAC,CAAC,CAAC;AACjG,CAAC,CAAC,CAAC;AAEH,IAAA,mBAAI,EAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;IACtD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAA,2BAAgB,EAAC;QACxC,GAAG,KAAK;QACR,mBAAmB,EAAE,KAAK,IAAI,EAAE,CAAC;YAC/B,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,+BAA+B,EAAE;SAC9E;KACF,CAAC,CAAC;IACH,gBAAM,CAAC,EAAE,CACP,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,oBAAoB,IAAI,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAClF,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,IAAA,mBAAI,EAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;IAChD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAA,2BAAgB,EAAC;QACxC,GAAG,KAAK;QACR,mBAAmB,EAAE,KAAK,IAAI,EAAE,CAAC;YAC/B,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,oCAAoC,EAAE;SACnF;KACF,CAAC,CAAC;IACH,gBAAM,CAAC,EAAE,CACP,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,oBAAoB,IAAI,CAAC,CAAC,MAAM,KAAK,4BAA4B,CAAC,CACjG,CAAC;AACJ,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"audit.test.js","sourceRoot":"","sources":["../../src/__tests__/audit.test.ts"],"names":[],"mappings":"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"}
@@ -599,4 +599,53 @@ function objectPage(keys, opts = {}) {
599
599
  const found = await cf.r2ObjectFind("b", "k");
600
600
  strict_1.default.equal(found?.size, 4);
601
601
  });
602
+ // --- Task 1728: house-run Pages publishing -------------------------------
603
+ function projectPage(names, cursor) {
604
+ return JSON.stringify({
605
+ success: true,
606
+ errors: [],
607
+ messages: [],
608
+ result: names.map((name) => ({ name, subdomain: `${name}.pages.dev` })),
609
+ result_info: cursor === undefined ? {} : { cursor, per_page: 20 },
610
+ });
611
+ }
612
+ (0, node_test_1.default)("pagesDeploy shells npx wrangler (never bare) and returns the deployment url", async () => {
613
+ const { run, calls } = recordingRun("Uploading... (2/2)\n✨ Deployment complete! Take a peek over at https://abc123.glsmithandsons.pages.dev\n");
614
+ const cf = (0, cf_exec_js_1.makeCfExec)(cred, run);
615
+ const { url } = await cf.pagesDeploy("/acct/sites/gls", "glsmithandsons", "main");
616
+ strict_1.default.equal(url, "https://abc123.glsmithandsons.pages.dev");
617
+ strict_1.default.equal(calls[0].cmd, "npx");
618
+ strict_1.default.deepEqual(calls[0].args, [
619
+ "wrangler", "pages", "deploy", "/acct/sites/gls",
620
+ "--project-name", "glsmithandsons", "--branch", "main",
621
+ ]);
622
+ strict_1.default.equal(calls[0].env.CLOUDFLARE_API_TOKEN, "cfat_x");
623
+ });
624
+ (0, node_test_1.default)("pagesDeploy omits --branch when no branch is given", async () => {
625
+ const { run, calls } = recordingRun("✨ Deployment complete! Take a peek over at https://x.y.pages.dev\n");
626
+ const cf = (0, cf_exec_js_1.makeCfExec)(cred, run);
627
+ await cf.pagesDeploy("/acct/sites/gls", "glsmithandsons");
628
+ strict_1.default.deepEqual(calls[0].args, [
629
+ "wrangler", "pages", "deploy", "/acct/sites/gls", "--project-name", "glsmithandsons",
630
+ ]);
631
+ });
632
+ (0, node_test_1.default)("pagesDeploy throws with the body when wrangler prints no deployment url", async () => {
633
+ const { run } = recordingRun("Uploading... (0/0)\nsomething went sideways\n");
634
+ const cf = (0, cf_exec_js_1.makeCfExec)(cred, run);
635
+ await strict_1.default.rejects(() => cf.pagesDeploy("/acct/sites/gls", "glsmithandsons"), /something went sideways/, "a url-less wrangler run must surface its output, never report a silent success");
636
+ });
637
+ (0, node_test_1.default)("pagesProjectList follows the pagination cursor to exhaustion via the API, never wrangler", async () => {
638
+ const { fetchFn, calls } = sequenceFetch([
639
+ { ok: true, status: 200, body: projectPage(["glsmithandsons"], "c1") },
640
+ { ok: true, status: 200, body: projectPage(["ac-electrical"]) },
641
+ ]);
642
+ const cf = (0, cf_exec_js_1.makeCfExec)(cred, throwingRun, fetchFn);
643
+ strict_1.default.deepEqual(await cf.pagesProjectList(), [
644
+ { name: "glsmithandsons" },
645
+ { name: "ac-electrical" },
646
+ ]);
647
+ strict_1.default.equal(calls.length, 2);
648
+ strict_1.default.ok(!calls[0].url.includes("per_page"), "per_page is never sent (its max is unconfirmed)");
649
+ strict_1.default.ok(calls[1].url.includes("cursor=c1"), "the second request carries the cursor");
650
+ });
602
651
  //# sourceMappingURL=cf-exec.test.js.map