@code-yeongyu/senpi 2026.7.30 → 2026.7.31

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 (204) hide show
  1. package/CHANGELOG.md +98 -0
  2. package/README.md +3 -0
  3. package/dist/core/agent-session.d.ts +7 -0
  4. package/dist/core/agent-session.d.ts.map +1 -1
  5. package/dist/core/agent-session.js +31 -3
  6. package/dist/core/agent-session.js.map +1 -1
  7. package/dist/core/compaction/compaction.d.ts +1 -0
  8. package/dist/core/compaction/compaction.d.ts.map +1 -1
  9. package/dist/core/compaction/compaction.js +1 -0
  10. package/dist/core/compaction/compaction.js.map +1 -1
  11. package/dist/core/extensions/builtin/compaction/idle.d.ts +16 -0
  12. package/dist/core/extensions/builtin/compaction/idle.d.ts.map +1 -0
  13. package/dist/core/extensions/builtin/compaction/idle.js +21 -0
  14. package/dist/core/extensions/builtin/compaction/idle.js.map +1 -0
  15. package/dist/core/extensions/builtin/compaction/index.d.ts.map +1 -1
  16. package/dist/core/extensions/builtin/compaction/index.js +18 -1
  17. package/dist/core/extensions/builtin/compaction/index.js.map +1 -1
  18. package/dist/core/extensions/builtin/compaction/log.d.ts +1 -1
  19. package/dist/core/extensions/builtin/compaction/log.d.ts.map +1 -1
  20. package/dist/core/extensions/builtin/compaction/log.js.map +1 -1
  21. package/dist/core/extensions/builtin/compaction/openai-remote.d.ts +3 -0
  22. package/dist/core/extensions/builtin/compaction/openai-remote.d.ts.map +1 -1
  23. package/dist/core/extensions/builtin/compaction/openai-remote.js +15 -4
  24. package/dist/core/extensions/builtin/compaction/openai-remote.js.map +1 -1
  25. package/dist/core/extensions/builtin/compaction/speculative.d.ts.map +1 -1
  26. package/dist/core/extensions/builtin/compaction/speculative.js +18 -4
  27. package/dist/core/extensions/builtin/compaction/speculative.js.map +1 -1
  28. package/dist/core/extensions/builtin/goal/continuation.d.ts +2 -0
  29. package/dist/core/extensions/builtin/goal/continuation.d.ts.map +1 -1
  30. package/dist/core/extensions/builtin/goal/continuation.js +12 -0
  31. package/dist/core/extensions/builtin/goal/continuation.js.map +1 -1
  32. package/dist/core/extensions/builtin/goal/index.d.ts.map +1 -1
  33. package/dist/core/extensions/builtin/goal/index.js +4 -1
  34. package/dist/core/extensions/builtin/goal/index.js.map +1 -1
  35. package/dist/core/extensions/builtin/goal/monitor-continuation.d.ts.map +1 -1
  36. package/dist/core/extensions/builtin/goal/monitor-continuation.js +22 -18
  37. package/dist/core/extensions/builtin/goal/monitor-continuation.js.map +1 -1
  38. package/dist/core/extensions/builtin/gpt-apply-patch/apply.d.ts +1 -1
  39. package/dist/core/extensions/builtin/gpt-apply-patch/apply.d.ts.map +1 -1
  40. package/dist/core/extensions/builtin/gpt-apply-patch/apply.js +67 -66
  41. package/dist/core/extensions/builtin/gpt-apply-patch/apply.js.map +1 -1
  42. package/dist/core/extensions/builtin/gpt-apply-patch/recovery.d.ts +4 -0
  43. package/dist/core/extensions/builtin/gpt-apply-patch/recovery.d.ts.map +1 -0
  44. package/dist/core/extensions/builtin/gpt-apply-patch/recovery.js +35 -0
  45. package/dist/core/extensions/builtin/gpt-apply-patch/recovery.js.map +1 -0
  46. package/dist/core/extensions/builtin/gpt-apply-patch/tool.d.ts.map +1 -1
  47. package/dist/core/extensions/builtin/gpt-apply-patch/tool.js +0 -5
  48. package/dist/core/extensions/builtin/gpt-apply-patch/tool.js.map +1 -1
  49. package/dist/core/extensions/builtin/gpt-apply-patch/types.d.ts +2 -0
  50. package/dist/core/extensions/builtin/gpt-apply-patch/types.d.ts.map +1 -1
  51. package/dist/core/extensions/builtin/gpt-apply-patch/types.js.map +1 -1
  52. package/dist/core/high-reasoning-warning.d.ts +10 -0
  53. package/dist/core/high-reasoning-warning.d.ts.map +1 -0
  54. package/dist/core/high-reasoning-warning.js +28 -0
  55. package/dist/core/high-reasoning-warning.js.map +1 -0
  56. package/dist/core/model-runtime.d.ts.map +1 -1
  57. package/dist/core/model-runtime.js +3 -11
  58. package/dist/core/model-runtime.js.map +1 -1
  59. package/dist/core/settings-manager.d.ts +2 -0
  60. package/dist/core/settings-manager.d.ts.map +1 -1
  61. package/dist/core/settings-manager.js +1 -0
  62. package/dist/core/settings-manager.js.map +1 -1
  63. package/dist/modes/interactive/interactive-mode.d.ts +8 -1
  64. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  65. package/dist/modes/interactive/interactive-mode.js +59 -13
  66. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  67. package/dist/modes/interactive/risky-main-model-warning.d.ts +5 -0
  68. package/dist/modes/interactive/risky-main-model-warning.d.ts.map +1 -0
  69. package/dist/modes/interactive/risky-main-model-warning.js +8 -0
  70. package/dist/modes/interactive/risky-main-model-warning.js.map +1 -0
  71. package/dist/modes/interactive/tips/catalog/subagent-tips.d.ts.map +1 -1
  72. package/dist/modes/interactive/tips/catalog/subagent-tips.js +30 -0
  73. package/dist/modes/interactive/tips/catalog/subagent-tips.js.map +1 -1
  74. package/dist/modes/rpc/rpc-types.d.ts +6 -0
  75. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  76. package/dist/modes/rpc/rpc-types.js.map +1 -1
  77. package/dist/utils/version-check.d.ts.map +1 -1
  78. package/dist/utils/version-check.js +22 -2
  79. package/dist/utils/version-check.js.map +1 -1
  80. package/docs/docs.json +4 -0
  81. package/docs/quickstart.md +3 -0
  82. package/docs/release-guide.md +636 -0
  83. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +24 -0
  84. package/node_modules/@code-yeongyu/senpi-codemode/package.json +3 -3
  85. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js +2 -2
  86. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js.map +1 -1
  87. package/node_modules/@earendil-works/pi-agent-core/dist/empty-assistant-recovery.d.ts +4 -0
  88. package/node_modules/@earendil-works/pi-agent-core/dist/empty-assistant-recovery.d.ts.map +1 -0
  89. package/node_modules/@earendil-works/pi-agent-core/dist/empty-assistant-recovery.js +106 -0
  90. package/node_modules/@earendil-works/pi-agent-core/dist/empty-assistant-recovery.js.map +1 -0
  91. package/node_modules/@earendil-works/pi-agent-core/dist/stream-fn.d.ts +1 -0
  92. package/node_modules/@earendil-works/pi-agent-core/dist/stream-fn.d.ts.map +1 -1
  93. package/node_modules/@earendil-works/pi-agent-core/dist/stream-fn.js +1 -0
  94. package/node_modules/@earendil-works/pi-agent-core/dist/stream-fn.js.map +1 -1
  95. package/node_modules/@earendil-works/pi-agent-core/package.json +2 -2
  96. package/node_modules/@earendil-works/pi-ai/dist/index.d.ts +1 -1
  97. package/node_modules/@earendil-works/pi-ai/dist/index.d.ts.map +1 -1
  98. package/node_modules/@earendil-works/pi-ai/dist/index.js +1 -1
  99. package/node_modules/@earendil-works/pi-ai/dist/index.js.map +1 -1
  100. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  101. package/node_modules/@earendil-works/pi-ai/dist/providers/data/huggingface.json +1 -1
  102. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  103. package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
  104. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/index.d.ts +2 -1
  105. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/index.d.ts.map +1 -1
  106. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/index.js +13 -0
  107. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/index.js.map +1 -1
  108. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/kimi-xtml/recovery-stream.js +2 -2
  109. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/kimi-xtml/recovery-stream.js.map +1 -1
  110. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/kimi-xtml/thinking-recovery-stream.d.ts +3 -0
  111. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/kimi-xtml/thinking-recovery-stream.d.ts.map +1 -0
  112. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/kimi-xtml/thinking-recovery-stream.js +29 -0
  113. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/kimi-xtml/thinking-recovery-stream.js.map +1 -0
  114. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/kimi-xtml/thinking-recovery.d.ts +3 -0
  115. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/kimi-xtml/thinking-recovery.d.ts.map +1 -0
  116. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/kimi-xtml/thinking-recovery.js +82 -0
  117. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/kimi-xtml/thinking-recovery.js.map +1 -0
  118. package/node_modules/@earendil-works/pi-ai/package.json +1 -1
  119. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  120. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  121. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/index.d.ts.map +1 -1
  122. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/index.js +1 -12
  123. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/index.js.map +1 -1
  124. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/stdio.d.ts +7 -0
  125. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/stdio.d.ts.map +1 -1
  126. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/stdio.js +9 -3
  127. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/stdio.js.map +1 -1
  128. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/streamableHttp.d.ts.map +1 -1
  129. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/streamableHttp.js +5 -3
  130. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/streamableHttp.js.map +1 -1
  131. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/index.d.ts.map +1 -1
  132. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/index.js +1 -12
  133. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/index.js.map +1 -1
  134. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/sseKeepAlive.d.ts +5 -0
  135. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/sseKeepAlive.d.ts.map +1 -0
  136. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/sseKeepAlive.js +17 -0
  137. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/sseKeepAlive.js.map +1 -0
  138. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/stdio.d.ts +9 -1
  139. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/stdio.d.ts.map +1 -1
  140. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/stdio.js +10 -4
  141. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/stdio.js.map +1 -1
  142. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/webStandardStreamableHttp.d.ts +21 -0
  143. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/webStandardStreamableHttp.d.ts.map +1 -1
  144. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/webStandardStreamableHttp.js +239 -41
  145. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/webStandardStreamableHttp.js.map +1 -1
  146. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/zod-compat.d.ts.map +1 -1
  147. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/zod-compat.js +25 -6
  148. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/zod-compat.js.map +1 -1
  149. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/shared/mediaType.d.ts +32 -0
  150. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/shared/mediaType.d.ts.map +1 -0
  151. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/shared/mediaType.js +64 -0
  152. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/shared/mediaType.js.map +1 -0
  153. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/shared/stdio.d.ts +5 -0
  154. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/shared/stdio.d.ts.map +1 -1
  155. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/shared/stdio.js +10 -1
  156. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/shared/stdio.js.map +1 -1
  157. package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/index.d.ts.map +1 -1
  158. package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/index.js +2 -13
  159. package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/index.js.map +1 -1
  160. package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/stdio.d.ts +7 -0
  161. package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/stdio.d.ts.map +1 -1
  162. package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/stdio.js +9 -3
  163. package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/stdio.js.map +1 -1
  164. package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/streamableHttp.d.ts.map +1 -1
  165. package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/streamableHttp.js +5 -3
  166. package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/streamableHttp.js.map +1 -1
  167. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.d.ts.map +1 -1
  168. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js +2 -13
  169. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js.map +1 -1
  170. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/sseKeepAlive.d.ts +5 -0
  171. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/sseKeepAlive.d.ts.map +1 -0
  172. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/sseKeepAlive.js +13 -0
  173. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/sseKeepAlive.js.map +1 -0
  174. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.d.ts +9 -1
  175. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.d.ts.map +1 -1
  176. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js +10 -4
  177. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js.map +1 -1
  178. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/webStandardStreamableHttp.d.ts +21 -0
  179. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/webStandardStreamableHttp.d.ts.map +1 -1
  180. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/webStandardStreamableHttp.js +239 -41
  181. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/webStandardStreamableHttp.js.map +1 -1
  182. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.d.ts.map +1 -1
  183. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.js +25 -6
  184. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.js.map +1 -1
  185. package/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/mediaType.d.ts +32 -0
  186. package/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/mediaType.d.ts.map +1 -0
  187. package/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/mediaType.js +57 -0
  188. package/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/mediaType.js.map +1 -0
  189. package/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.d.ts +5 -0
  190. package/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.d.ts.map +1 -1
  191. package/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js +9 -0
  192. package/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js.map +1 -1
  193. package/node_modules/@modelcontextprotocol/sdk/package.json +4 -3
  194. package/node_modules/brace-expansion/README.md +12 -0
  195. package/node_modules/brace-expansion/dist/commonjs/index.d.ts +2 -0
  196. package/node_modules/brace-expansion/dist/commonjs/index.d.ts.map +1 -1
  197. package/node_modules/brace-expansion/dist/commonjs/index.js +138 -86
  198. package/node_modules/brace-expansion/dist/commonjs/index.js.map +1 -1
  199. package/node_modules/brace-expansion/dist/esm/index.d.ts +2 -0
  200. package/node_modules/brace-expansion/dist/esm/index.d.ts.map +1 -1
  201. package/node_modules/brace-expansion/dist/esm/index.js +137 -85
  202. package/node_modules/brace-expansion/dist/esm/index.js.map +1 -1
  203. package/node_modules/brace-expansion/package.json +2 -2
  204. package/package.json +7 -7
@@ -0,0 +1,636 @@
1
+ # Senpi 2026.7.30-2 Release and Installation Guide
2
+
3
+ This guide is the authoritative procedure for building, installing, and verifying Senpi
4
+ `2026.7.30-2` on:
5
+
6
+ - `mengmotaMac` — the local Apple Silicon development machine
7
+ - `mengmotaHost` / Jobdori — the remote Apple Silicon machine
8
+
9
+ The procedure deliberately does **not** publish to npm, create a Git tag, create a commit,
10
+ push a branch, or modify Senpi configuration. Both machines receive the same locally built
11
+ npm tarball, verified by SHA-256 before installation.
12
+
13
+ ## Release summary
14
+
15
+ Senpi `2026.7.30-2` packages the post-`v2026.7.30` runtime work and updates the bundled MCP
16
+ SDK integration:
17
+
18
+ - recovers Kimi XML thinking channels and retries one empty assistant response
19
+ - reuses the active runtime API key for automatic session titles
20
+ - compacts proactively when an agent becomes idle above the configured threshold
21
+ - starts a freshly created durable goal immediately while preserving user grace for side questions on existing goals
22
+ - serializes multi-file apply-patch mutations and reports concrete failure reasons
23
+ - warns when high-reasoning and risky main-model selections are likely to waste capacity
24
+ - expands OMO workflow tips in interactive sessions
25
+ - updates `@modelcontextprotocol/sdk` from `1.29.0` to `1.30.0`
26
+ - updates `brace-expansion` from vulnerable `5.0.7` to patched `5.0.8`
27
+ - preserves every bundled extension registration and the separate hooks plugin loader
28
+
29
+ Read the package changelogs for the complete package-by-package breakdown.
30
+
31
+ ## Non-negotiable config rule
32
+
33
+ Do not run release QA against the real Senpi agent directory.
34
+
35
+ The real directory is normally:
36
+
37
+ ```text
38
+ ~/.senpi/agent/
39
+ ```
40
+
41
+ Every runtime command in this guide uses a disposable `HOME` and
42
+ `SENPI_CODING_AGENT_DIR`. Global npm installation changes the executable and package files
43
+ only; it does not need to read or write Senpi settings, credentials, sessions, extensions,
44
+ models, provider state, or authentication data.
45
+
46
+ Do not use these commands during this release procedure:
47
+
48
+ ```bash
49
+ senpi install ...
50
+ senpi remove ...
51
+ senpi update
52
+ senpi --no-extensions
53
+ ```
54
+
55
+ Package-management commands can change configured extension resources or use the normal
56
+ agent directory. They are unnecessary for verifying the bundled release.
57
+
58
+ ## Prerequisites
59
+
60
+ Both machines must have:
61
+
62
+ - macOS on `arm64`
63
+ - Node.js `>=24`
64
+ - npm
65
+ - a working `senpi` global bin directory on `PATH`
66
+
67
+ The source machine additionally needs:
68
+
69
+ - the Senpi repository checkout
70
+ - Bun
71
+ - Git
72
+ - the repository dependencies
73
+ - `tmux` for the POSIX TUI smoke channel
74
+
75
+ Verify the local toolchain:
76
+
77
+ ```bash
78
+ cd /Users/yeongyu/local-workspaces/senpi
79
+ uname -m
80
+ node --version
81
+ npm --version
82
+ bun --version
83
+ git status --short --branch
84
+ ```
85
+
86
+ Verify Jobdori without entering its shared Senpi checkout:
87
+
88
+ ```bash
89
+ ssh mengmotaHost 'uname -m; node --version; npm --version; command -v senpi'
90
+ ```
91
+
92
+ Expected architecture on both machines is `arm64`.
93
+
94
+ ## Release identity
95
+
96
+ This release uses CalVer:
97
+
98
+ ```text
99
+ 2026.7.30-2
100
+ ```
101
+
102
+ The eight lockstep package manifests are:
103
+
104
+ - `packages/ai/package.json`
105
+ - `packages/agent/package.json`
106
+ - `packages/coding-agent/package.json`
107
+ - `packages/server/package.json`
108
+ - `packages/pty/package.json`
109
+ - `packages/senpi-codemode/package.json`
110
+ - `packages/tui/package.json`
111
+ - `packages/web-ui/package.json`
112
+
113
+ `@earendil-works/pi-storage-sqlite-node` remains on its independent semver line and is not
114
+ part of the CalVer bump.
115
+
116
+ Confirm the source CLI identity without using real configuration:
117
+
118
+ ```bash
119
+ QA_ROOT="$(mktemp -d)"
120
+ HOME="$QA_ROOT/home" \
121
+ SENPI_CODING_AGENT_DIR="$QA_ROOT/agent" \
122
+ PI_OFFLINE=1 \
123
+ node --import tsx packages/coding-agent/src/cli.ts --version
124
+ rm -rf "$QA_ROOT"
125
+ ```
126
+
127
+ Expected output:
128
+
129
+ ```text
130
+ 2026.7.30-2
131
+ ```
132
+
133
+ ## Plugin and extension status
134
+
135
+ Senpi has several extension surfaces. They must not be conflated.
136
+
137
+ ### Ordered builtins
138
+
139
+ The authoritative `builtinExtensions` registration order contains 31 extensions:
140
+
141
+ 1. `hooks`
142
+ 2. `permission-system`
143
+ 3. `gpt-apply-patch`
144
+ 4. `prompt-preset`
145
+ 5. `todowrite`
146
+ 6. `redraws`
147
+ 7. `anthropic-web-search`
148
+ 8. `anthropic-bash`
149
+ 9. `openai-web-search`
150
+ 10. `service-tier`
151
+ 11. `model-fallback`
152
+ 12. `recommended-models`
153
+ 13. `bash-timeout`
154
+ 14. `terminal`
155
+ 15. `tool-pair-guard`
156
+ 16. `compaction`
157
+ 17. `history-search`
158
+ 18. `help`
159
+ 19. `import-repro`
160
+ 20. `websearch`
161
+ 21. `webfetch`
162
+ 22. `video-in`
163
+ 23. `look-at`
164
+ 24. `nested-agents-md`
165
+ 25. `rules`
166
+ 26. `goal`
167
+ 27. `ttsr`
168
+ 28. `btw`
169
+ 29. `claude-agent-sdk`
170
+ 30. `config-reload`
171
+ 31. `mcp`
172
+
173
+ `mcp` remains last because its load order is intentional and load-bearing.
174
+
175
+ ### Global defaults
176
+
177
+ Four global default extension factories load separately:
178
+
179
+ - `diff`
180
+ - `files`
181
+ - `prompt-url-widget`
182
+ - `tps`
183
+
184
+ ### Other bundled surfaces
185
+
186
+ - `codemode` is bundled as `@code-yeongyu/senpi-codemode`.
187
+ - `llama.cpp` is a hidden inline extension.
188
+ - `.codex-plugin/plugin.json` belongs to the hooks plugin-manifest loader. Runtime-discovered
189
+ hook plugins are user resources; no hook plugin is bundled by this repository.
190
+
191
+ ### Version status
192
+
193
+ | Surface | Release status |
194
+ |---|---|
195
+ | `@modelcontextprotocol/sdk` | updated from exact `1.29.0` to exact `1.30.0` |
196
+ | `brace-expansion` | updated from vulnerable exact `5.0.7` to patched exact `5.0.8` |
197
+ | `@anthropic-ai/claude-agent-sdk` | current at exact `0.3.220` |
198
+ | `@code-yeongyu/senpi-codemode` | lockstep `2026.7.30-2` |
199
+ | eight vendored builtin snapshots | preserved from `external-versions.json` |
200
+
201
+ The vendored snapshot sources are mostly unpublished on npm. The configured sibling
202
+ `../pi-extensions` checkout and an accessible `code-yeongyu/pi-extensions` GitHub repository
203
+ were unavailable during this release. Their checked-in source plus
204
+ `external-versions.json` therefore remain authoritative; no version was guessed or fabricated.
205
+
206
+ ### Known packaging warning
207
+
208
+ The isolated Bun package installation on the release machine reports
209
+ `incorrect peer dependency "@anthropic-ai/sdk@0.91.1"`. The source and packed manifests both
210
+ pin that exact SDK version, while the isolated npm installation, npm audit, standalone Bun
211
+ binary, and npm/Bun package CLIs all pass. Treat this as a Bun resolver warning; it does not
212
+ change the supported Node/npm installation path or require a configuration migration.
213
+
214
+ `release:local` stages the publish manifest and bundled package tree inside the source checkout
215
+ while packing. Run it from a clean, dedicated release checkout rather than a shared dirty
216
+ worktree. After packing, verify `packages/coding-agent/package.json` still has only the five
217
+ intentional internal bundle entries and run `npm install --ignore-scripts` before resuming
218
+ development so workspace dependency resolution is restored. Do not use destructive Git cleanup
219
+ when other work is present.
220
+
221
+ ## Build and static verification
222
+
223
+ Run from the repository root:
224
+
225
+ ```bash
226
+ npm run check
227
+ npm run build
228
+ CI=1 npm test
229
+ npm audit --omit=dev
230
+ ```
231
+
232
+ The release-script checks are:
233
+
234
+ ```bash
235
+ node scripts/generate-coding-agent-shrinkwrap.mjs --check
236
+ node scripts/generate-coding-agent-install-lock.mjs --check
237
+ node scripts/upstream-release-worthy.mjs
238
+ npm run release -- --dry-run
239
+ node scripts/release-notes.mjs extract \
240
+ --version 2026.7.30-2 \
241
+ --tag v2026.7.30-2
242
+ ```
243
+
244
+ `npm run release -- --dry-run` is safe for this workflow. Do not run the live release command:
245
+ the live path commits, tags, and pushes.
246
+
247
+ ## Plugin verification
248
+
249
+ Run the focused extension suites:
250
+
251
+ ```bash
252
+ npm --prefix packages/coding-agent exec vitest -- \
253
+ --run \
254
+ test/suite/builtin-extension-sync.test.ts \
255
+ test/suite/vendored-builtins.test.ts \
256
+ test/extensions/loader-concurrency.test.ts \
257
+ test/mcp/ \
258
+ test/suite/claude-agent-sdk-extension.test.ts \
259
+ test/suite/terminal-extension.test.ts \
260
+ test/compaction/ \
261
+ test/ttsr/
262
+ ```
263
+
264
+ The tests import the extension registry or use temporary fixtures. They do not discover
265
+ extensions from the real Senpi agent directory.
266
+
267
+ ## Mandatory local QA
268
+
269
+ The repository QA harness creates isolated homes, sets offline mode, and guards real
270
+ authentication state.
271
+
272
+ Run:
273
+
274
+ ```bash
275
+ node .agents/skills/senpi-qa/scripts/lib/common.mjs --self-check
276
+ node .agents/skills/senpi-qa/scripts/cli-smoke.mjs --self-test
277
+ node .agents/skills/senpi-qa/scripts/rpc-drive.mjs --self-test
278
+ node .agents/skills/senpi-qa/scripts/rpc-drive.mjs --state
279
+ node .agents/skills/senpi-qa/scripts/mock-loop.mjs --self-test
280
+ node .agents/skills/senpi-qa/scripts/mock-loop.mjs \
281
+ --with-tool \
282
+ --api openai-responses
283
+ node .agents/skills/senpi-qa/scripts/tui-smoke.mjs \
284
+ --self-test \
285
+ --driver tmux \
286
+ --evidence senpi-2026.7.30-2-tui
287
+ node .agents/skills/senpi-qa/scripts/pty-drive.mjs \
288
+ --self-test \
289
+ --evidence senpi-2026.7.30-2-pty
290
+ ```
291
+
292
+ Evidence belongs under:
293
+
294
+ ```text
295
+ local-ignore/qa-evidence/20260730-senpi-release-2026-7-30-2/
296
+ ```
297
+
298
+ ## Build the canonical release artifact
299
+
300
+ Choose one durable output directory outside the repository:
301
+
302
+ ```bash
303
+ cd /Users/yeongyu/local-workspaces/senpi
304
+ ARTIFACT_ROOT="$HOME/.local/share/senpi-releases/2026.7.30-2"
305
+ npm run release:local -- --force --out "$ARTIFACT_ROOT"
306
+ ```
307
+
308
+ The canonical npm tarball is:
309
+
310
+ ```text
311
+ ~/.local/share/senpi-releases/2026.7.30-2/tarballs/code-yeongyu-senpi-2026.7.30-2.tgz
312
+ ```
313
+
314
+ Set variables and calculate its checksum:
315
+
316
+ ```bash
317
+ ARTIFACT_ROOT="$HOME/.local/share/senpi-releases/2026.7.30-2"
318
+ TARBALL="$ARTIFACT_ROOT/tarballs/code-yeongyu-senpi-2026.7.30-2.tgz"
319
+ shasum -a 256 "$TARBALL"
320
+ ```
321
+
322
+ Retain the checksum with the QA evidence. Jobdori must receive this exact file.
323
+
324
+ ## Upgrade an existing installation
325
+
326
+ An upgrade uses the same checksum-verified tarball as a first installation. It replaces package
327
+ files only; Senpi settings, credentials, providers, models, permissions, sessions, and plugin
328
+ enablement files do not need a migration.
329
+
330
+ Record executable discovery before upgrading:
331
+
332
+ ```bash
333
+ command -v senpi
334
+ senpi --version
335
+ npm prefix -g
336
+ ```
337
+
338
+ Install the verified tarball through npm without lifecycle scripts, then refresh the shell’s
339
+ command cache:
340
+
341
+ ```bash
342
+ npm install -g --ignore-scripts "$TARBALL"
343
+ hash -r
344
+ command -v senpi
345
+ senpi --version
346
+ ```
347
+
348
+ The final version must be `2026.7.30-2`. If `command -v senpi` still points at another package
349
+ manager’s prefix, inspect that manager’s global package list and remove only its stale
350
+ `@code-yeongyu/senpi` package. Do not edit shell startup files or Senpi configuration merely to
351
+ change executable precedence. Re-run the isolated verification commands below after every
352
+ upgrade.
353
+
354
+ ## Install on mengmotaMac
355
+
356
+ Install the verified tarball:
357
+
358
+ ```bash
359
+ npm install -g --ignore-scripts "$TARBALL"
360
+ ```
361
+
362
+ Create an isolated runtime home:
363
+
364
+ ```bash
365
+ LOCAL_QA="$(mktemp -d)"
366
+ mkdir -p "$LOCAL_QA/home" "$LOCAL_QA/agent"
367
+ ```
368
+
369
+ Exercise the installed CLI:
370
+
371
+ ```bash
372
+ HOME="$LOCAL_QA/home" \
373
+ SENPI_CODING_AGENT_DIR="$LOCAL_QA/agent" \
374
+ PI_OFFLINE=1 \
375
+ senpi --version
376
+
377
+ HOME="$LOCAL_QA/home" \
378
+ SENPI_CODING_AGENT_DIR="$LOCAL_QA/agent" \
379
+ PI_OFFLINE=1 \
380
+ senpi --help
381
+
382
+ HOME="$LOCAL_QA/home" \
383
+ SENPI_CODING_AGENT_DIR="$LOCAL_QA/agent" \
384
+ PI_OFFLINE=1 \
385
+ senpi --list-models
386
+ ```
387
+
388
+ The malformed-input scenario must fail:
389
+
390
+ ```bash
391
+ HOME="$LOCAL_QA/home" \
392
+ SENPI_CODING_AGENT_DIR="$LOCAL_QA/agent" \
393
+ PI_OFFLINE=1 \
394
+ senpi --definitely-invalid
395
+ ```
396
+
397
+ Expected results:
398
+
399
+ - `--version` prints exactly `2026.7.30-2`
400
+ - `--help` exits 0 and shows usage
401
+ - `--list-models` exits 0 offline and prints at least one model
402
+ - the invalid option exits nonzero and identifies the option as unknown
403
+
404
+ Remove the isolated runtime home after evidence is captured:
405
+
406
+ ```bash
407
+ rm -rf "$LOCAL_QA"
408
+ ```
409
+
410
+ ## Transfer to Jobdori
411
+
412
+ Do not use or clean Jobdori’s shared Senpi source checkout.
413
+
414
+ Create a remote transfer directory and copy the tarball:
415
+
416
+ ```bash
417
+ ssh mengmotaHost 'mkdir -p /tmp/senpi-2026.7.30-2'
418
+ scp "$TARBALL" \
419
+ mengmotaHost:/tmp/senpi-2026.7.30-2/code-yeongyu-senpi-2026.7.30-2.tgz
420
+ ```
421
+
422
+ Compare checksums:
423
+
424
+ ```bash
425
+ shasum -a 256 "$TARBALL"
426
+ ssh mengmotaHost \
427
+ 'shasum -a 256 /tmp/senpi-2026.7.30-2/code-yeongyu-senpi-2026.7.30-2.tgz'
428
+ ```
429
+
430
+ Do not install unless the two hashes are identical.
431
+
432
+ ## Install on Jobdori
433
+
434
+ Install the transferred artifact:
435
+
436
+ ```bash
437
+ ssh mengmotaHost \
438
+ 'npm install -g --ignore-scripts \
439
+ /tmp/senpi-2026.7.30-2/code-yeongyu-senpi-2026.7.30-2.tgz'
440
+ ```
441
+
442
+ Exercise the remote CLI inside an isolated home:
443
+
444
+ ```bash
445
+ ssh mengmotaHost '
446
+ REMOTE_QA=$(mktemp -d)
447
+ mkdir -p "$REMOTE_QA/home" "$REMOTE_QA/agent"
448
+
449
+ HOME="$REMOTE_QA/home" \
450
+ SENPI_CODING_AGENT_DIR="$REMOTE_QA/agent" \
451
+ PI_OFFLINE=1 \
452
+ senpi --version
453
+
454
+ HOME="$REMOTE_QA/home" \
455
+ SENPI_CODING_AGENT_DIR="$REMOTE_QA/agent" \
456
+ PI_OFFLINE=1 \
457
+ senpi --help
458
+
459
+ HOME="$REMOTE_QA/home" \
460
+ SENPI_CODING_AGENT_DIR="$REMOTE_QA/agent" \
461
+ PI_OFFLINE=1 \
462
+ senpi --list-models
463
+
464
+ if HOME="$REMOTE_QA/home" \
465
+ SENPI_CODING_AGENT_DIR="$REMOTE_QA/agent" \
466
+ PI_OFFLINE=1 \
467
+ senpi --definitely-invalid
468
+ then
469
+ echo "invalid option unexpectedly succeeded" >&2
470
+ rm -rf "$REMOTE_QA"
471
+ exit 1
472
+ fi
473
+
474
+ rm -rf "$REMOTE_QA"
475
+ '
476
+ ```
477
+
478
+ The expected observables are identical to the local installation.
479
+
480
+ ## Configuration integrity proof
481
+
482
+ Before installation, calculate one composite digest for every regular file under the real
483
+ agent directory. Do not print individual file names, file contents, or per-file hashes.
484
+
485
+ Local:
486
+
487
+ ```bash
488
+ CONFIG_DIR="$HOME/.senpi/agent"
489
+ find "$CONFIG_DIR" -type f -print0 |
490
+ sort -z |
491
+ xargs -0 shasum -a 256 |
492
+ shasum -a 256
493
+ ```
494
+
495
+ Jobdori:
496
+
497
+ ```bash
498
+ ssh mengmotaHost '
499
+ CONFIG_DIR="$HOME/.senpi/agent"
500
+ find "$CONFIG_DIR" -type f -print0 |
501
+ sort -z |
502
+ xargs -0 shasum -a 256 |
503
+ shasum -a 256
504
+ '
505
+ ```
506
+
507
+ Repeat after all installation and QA steps. The before and after composite digests and file
508
+ counts must match exactly on each machine.
509
+
510
+ ## Troubleshooting
511
+
512
+ ### The source CLI reports the old version
513
+
514
+ Re-run version synchronization and lock generation:
515
+
516
+ ```bash
517
+ node scripts/sync-versions.js
518
+ PI_ALLOW_LOCKFILE_CHANGE=1 npm install --package-lock-only --ignore-scripts
519
+ node scripts/generate-coding-agent-shrinkwrap.mjs
520
+ node scripts/generate-coding-agent-install-lock.mjs
521
+ ```
522
+
523
+ Then rebuild before packaging.
524
+
525
+ ### The installed CLI reports the old version
526
+
527
+ Confirm the tarball name and inspect npm’s global package:
528
+
529
+ ```bash
530
+ npm list -g @code-yeongyu/senpi
531
+ command -v senpi
532
+ senpi --version
533
+ ```
534
+
535
+ Reinstall the exact local tarball, not the registry’s `latest` tag.
536
+
537
+ ### Jobdori’s checksum differs
538
+
539
+ Delete only the remote transfer file, copy it again, and re-run both hashes:
540
+
541
+ ```bash
542
+ ssh mengmotaHost \
543
+ 'rm -f /tmp/senpi-2026.7.30-2/code-yeongyu-senpi-2026.7.30-2.tgz'
544
+ scp "$TARBALL" \
545
+ mengmotaHost:/tmp/senpi-2026.7.30-2/code-yeongyu-senpi-2026.7.30-2.tgz
546
+ ```
547
+
548
+ Do not install a mismatched artifact.
549
+
550
+ ### A QA command tries to use real credentials
551
+
552
+ Stop immediately. Confirm the command sets:
553
+
554
+ ```text
555
+ HOME=<temporary directory>
556
+ SENPI_CODING_AGENT_DIR=<temporary directory>/agent
557
+ PI_OFFLINE=1
558
+ ```
559
+
560
+ The repository QA harness sets its own isolation variables. Do not override them with real
561
+ configuration paths.
562
+
563
+ ### MCP tests fail after the SDK update
564
+
565
+ Run the MCP suite directly:
566
+
567
+ ```bash
568
+ npm --prefix packages/coding-agent exec vitest -- --run test/mcp/
569
+ ```
570
+
571
+ Make only compatibility changes required by a reproduced failure. Do not add fallback logic
572
+ for unsupported scenarios.
573
+
574
+ ## Rollback and recovery
575
+
576
+ Rollback changes the executable package only. It does not remove or modify
577
+ `~/.senpi/agent/`.
578
+
579
+ Reinstall the prior published version:
580
+
581
+ ```bash
582
+ npm install -g @code-yeongyu/senpi@2026.7.30
583
+ ```
584
+
585
+ Verify rollback from an isolated home:
586
+
587
+ ```bash
588
+ ROLLBACK_QA="$(mktemp -d)"
589
+ HOME="$ROLLBACK_QA/home" \
590
+ SENPI_CODING_AGENT_DIR="$ROLLBACK_QA/agent" \
591
+ PI_OFFLINE=1 \
592
+ senpi --version
593
+ rm -rf "$ROLLBACK_QA"
594
+ ```
595
+
596
+ If only Jobdori must be rolled back, run the same install and isolated verification through
597
+ `ssh mengmotaHost`.
598
+
599
+ ## Cleanup
600
+
601
+ After Jobdori is installed and verified:
602
+
603
+ ```bash
604
+ ssh mengmotaHost 'rm -rf /tmp/senpi-2026.7.30-2'
605
+ ```
606
+
607
+ Remove every temporary QA home. Keep:
608
+
609
+ - the installed `2026.7.30-2` package on both machines
610
+ - the canonical tarball
611
+ - its checksum
612
+ - the release notes
613
+ - the QA evidence directory
614
+
615
+ Do not remove the real Senpi agent directory.
616
+
617
+ ## Maintenance checklist
618
+
619
+ For the next release:
620
+
621
+ 1. Start from a clean, current `main`.
622
+ 2. Audit every commit since the latest tag.
623
+ 3. Update all affected package `[Unreleased]` sections.
624
+ 4. Duplicate user-facing AI, agent, and TUI changes into the coding-agent changelog.
625
+ 5. Query registry-verifiable plugin dependencies for newer exact versions.
626
+ 6. Preserve vendored snapshots when no authoritative upstream source is available.
627
+ 7. Update the eight lockstep package versions.
628
+ 8. Regenerate package-lock, publish-deps lock, and install lock.
629
+ 9. Run focused plugin tests.
630
+ 10. Run `check`, `build`, and the full test suite.
631
+ 11. Run the real Senpi QA channels.
632
+ 12. Build one canonical local tarball.
633
+ 13. Install that same checksum-identical tarball on every target machine.
634
+ 14. Verify through isolated runtime homes.
635
+ 15. Prove real Senpi configuration stayed unchanged.
636
+ 16. Publish, tag, commit, or push only when separately authorized.
@@ -12,6 +12,30 @@
12
12
 
13
13
  ### Removed
14
14
 
15
+ ## [2026.7.31] - 2026-07-31
16
+
17
+ ### Breaking Changes
18
+
19
+ ### Added
20
+
21
+ ### Changed
22
+
23
+ ### Fixed
24
+
25
+ ### Removed
26
+
27
+ ## [2026.7.30-2] - 2026-07-30
28
+
29
+ ### Breaking Changes
30
+
31
+ ### Added
32
+
33
+ ### Changed
34
+
35
+ ### Fixed
36
+
37
+ ### Removed
38
+
15
39
  ## [2026.7.30] - 2026-07-30
16
40
 
17
41
  ### Breaking Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-yeongyu/senpi-codemode",
3
- "version": "2026.7.30",
3
+ "version": "2026.7.31",
4
4
  "description": "Source-only senpi extension package for codemode evaluation tools",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -30,14 +30,14 @@
30
30
  },
31
31
  "dependencies": {
32
32
  "@babel/parser": "8.0.4",
33
- "@earendil-works/pi-ai": "^2026.7.30",
33
+ "@earendil-works/pi-ai": "^2026.7.31",
34
34
  "typebox": "1.3.8"
35
35
  },
36
36
  "peerDependencies": {
37
37
  "@code-yeongyu/senpi": "*"
38
38
  },
39
39
  "devDependencies": {
40
- "@code-yeongyu/senpi": "2026.7.30"
40
+ "@code-yeongyu/senpi": "2026.7.31"
41
41
  },
42
42
  "keywords": [
43
43
  "senpi",
@@ -4,7 +4,7 @@
4
4
  */
5
5
  import { EventStream, validateToolArguments, } from "@earendil-works/pi-ai";
6
6
  import { createTerminalFailureAssistantMessage, normalizeTerminalAssistantMessage, shouldTerminateAssistantTurn, } from "./assistant-terminal-state.js";
7
- import { getDefaultStreamFn } from "./stream-fn.js";
7
+ import { getDefaultStreamFn, withEmptyAssistantRecovery } from "./stream-fn.js";
8
8
  /**
9
9
  * Start an agent loop with a new prompt message.
10
10
  * The prompt is added to the context and events are emitted for it.
@@ -153,7 +153,7 @@ async function runLoop(initialContext, newMessages, initialConfig, signal, emit,
153
153
  }
154
154
  : config;
155
155
  const streamIdleTimeoutMs = isInitialProviderRequest ? config.timeoutMs : requestConfig.timeoutMs;
156
- const message = await streamAssistantResponse(currentContext, requestConfig, signal, emit, streamFunction, streamIdleTimeoutMs);
156
+ const message = await streamAssistantResponse(currentContext, requestConfig, signal, emit, withEmptyAssistantRecovery(requestConfig.model, streamFunction), streamIdleTimeoutMs);
157
157
  newMessages.push(message);
158
158
  if (shouldTerminateAssistantTurn(message)) {
159
159
  await emit({ type: "turn_end", message, toolResults: [] });