@geminixiang/mikan 1.0.0-beta.94 → 1.0.0-beta.96

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 (198) hide show
  1. package/CHANGELOG.md +432 -378
  2. package/README.md +31 -40
  3. package/dist/adapters/commands/login.js +1 -1
  4. package/dist/adapters/commands/login.js.map +1 -1
  5. package/dist/adapters/commands/registry.d.ts +1 -1
  6. package/dist/adapters/commands/registry.d.ts.map +1 -1
  7. package/dist/adapters/commands/registry.js +1 -2
  8. package/dist/adapters/commands/registry.js.map +1 -1
  9. package/dist/adapters/commands/types.d.ts +2 -4
  10. package/dist/adapters/commands/types.d.ts.map +1 -1
  11. package/dist/adapters/commands/types.js.map +1 -1
  12. package/dist/adapters/github/bot.js +1 -1
  13. package/dist/adapters/github/bot.js.map +1 -1
  14. package/dist/adapters/github/policy.d.ts +2 -9
  15. package/dist/adapters/github/policy.d.ts.map +1 -1
  16. package/dist/adapters/github/policy.js +18 -26
  17. package/dist/adapters/github/policy.js.map +1 -1
  18. package/dist/adapters/slack/bot.d.ts +2 -4
  19. package/dist/adapters/slack/bot.d.ts.map +1 -1
  20. package/dist/adapters/slack/bot.js +28 -56
  21. package/dist/adapters/slack/bot.js.map +1 -1
  22. package/dist/adapters/slack/socket-agent.d.ts +9 -0
  23. package/dist/adapters/slack/socket-agent.d.ts.map +1 -0
  24. package/dist/adapters/slack/socket-agent.js +17 -0
  25. package/dist/adapters/slack/socket-agent.js.map +1 -0
  26. package/dist/adapters/telegram/bot.d.ts +1 -0
  27. package/dist/adapters/telegram/bot.d.ts.map +1 -1
  28. package/dist/adapters/telegram/bot.js +6 -1
  29. package/dist/adapters/telegram/bot.js.map +1 -1
  30. package/dist/adapters/telegram/types.d.ts +1 -0
  31. package/dist/adapters/telegram/types.d.ts.map +1 -1
  32. package/dist/adapters/telegram/types.js.map +1 -1
  33. package/dist/adapters/web/admin/portal.d.ts.map +1 -1
  34. package/dist/adapters/web/admin/portal.js +92 -173
  35. package/dist/adapters/web/admin/portal.js.map +1 -1
  36. package/dist/adapters/web/admin/types.d.ts +3 -8
  37. package/dist/adapters/web/admin/types.d.ts.map +1 -1
  38. package/dist/adapters/web/admin/types.js.map +1 -1
  39. package/dist/adapters/web/server.d.ts +1 -1
  40. package/dist/adapters/web/server.d.ts.map +1 -1
  41. package/dist/adapters/web/server.js.map +1 -1
  42. package/dist/cli/arg-grammar.d.ts +1 -3
  43. package/dist/cli/arg-grammar.d.ts.map +1 -1
  44. package/dist/cli/arg-grammar.js +2 -20
  45. package/dist/cli/arg-grammar.js.map +1 -1
  46. package/dist/cli/boot.d.ts.map +1 -1
  47. package/dist/cli/boot.js +5 -11
  48. package/dist/cli/boot.js.map +1 -1
  49. package/dist/cli/migrate.d.ts.map +1 -1
  50. package/dist/cli/migrate.js +22 -7
  51. package/dist/cli/migrate.js.map +1 -1
  52. package/dist/cli/office.d.ts.map +1 -1
  53. package/dist/cli/office.js +3 -5
  54. package/dist/cli/office.js.map +1 -1
  55. package/dist/cli/onboard.js +18 -20
  56. package/dist/cli/onboard.js.map +1 -1
  57. package/dist/cli/types.d.ts +1 -2
  58. package/dist/cli/types.d.ts.map +1 -1
  59. package/dist/cli/types.js.map +1 -1
  60. package/dist/env-manifest.d.ts +2 -1
  61. package/dist/env-manifest.d.ts.map +1 -1
  62. package/dist/env-manifest.js +76 -47
  63. package/dist/env-manifest.js.map +1 -1
  64. package/dist/events/index.d.ts +5 -5
  65. package/dist/events/index.d.ts.map +1 -1
  66. package/dist/events/index.js +1 -7
  67. package/dist/events/index.js.map +1 -1
  68. package/dist/file-guards.d.ts +1 -0
  69. package/dist/file-guards.d.ts.map +1 -1
  70. package/dist/file-guards.js +4 -1
  71. package/dist/file-guards.js.map +1 -1
  72. package/dist/harness/execution-resolver.d.ts.map +1 -1
  73. package/dist/harness/execution-resolver.js +2 -8
  74. package/dist/harness/execution-resolver.js.map +1 -1
  75. package/dist/harness/http.d.ts +1 -2
  76. package/dist/harness/http.d.ts.map +1 -1
  77. package/dist/harness/http.js +3 -16
  78. package/dist/harness/http.js.map +1 -1
  79. package/dist/harness/jev.d.ts +2 -1
  80. package/dist/harness/jev.d.ts.map +1 -1
  81. package/dist/harness/jev.js.map +1 -1
  82. package/dist/harness/models.d.ts +2 -2
  83. package/dist/harness/models.d.ts.map +1 -1
  84. package/dist/harness/models.js +4 -6
  85. package/dist/harness/models.js.map +1 -1
  86. package/dist/harness/prompt.d.ts.map +1 -1
  87. package/dist/harness/prompt.js +0 -6
  88. package/dist/harness/prompt.js.map +1 -1
  89. package/dist/harness/runner.js +1 -2
  90. package/dist/harness/runner.js.map +1 -1
  91. package/dist/harness/session.d.ts +2 -9
  92. package/dist/harness/session.d.ts.map +1 -1
  93. package/dist/harness/session.js +3 -3
  94. package/dist/harness/session.js.map +1 -1
  95. package/dist/harness/tools/event.d.ts +0 -1
  96. package/dist/harness/tools/event.d.ts.map +1 -1
  97. package/dist/harness/tools/event.js +1 -7
  98. package/dist/harness/tools/event.js.map +1 -1
  99. package/dist/harness/types.d.ts +4 -4
  100. package/dist/harness/types.d.ts.map +1 -1
  101. package/dist/harness/types.js.map +1 -1
  102. package/dist/index.d.ts +8 -31
  103. package/dist/index.d.ts.map +1 -1
  104. package/dist/index.js +3 -15
  105. package/dist/index.js.map +1 -1
  106. package/dist/main.js +29 -41
  107. package/dist/main.js.map +1 -1
  108. package/dist/migrations/index.d.ts +0 -1
  109. package/dist/migrations/index.d.ts.map +1 -1
  110. package/dist/migrations/index.js +4 -10
  111. package/dist/migrations/index.js.map +1 -1
  112. package/dist/migrations/legacy-office-files.d.ts +3 -0
  113. package/dist/migrations/legacy-office-files.d.ts.map +1 -0
  114. package/dist/migrations/legacy-office-files.js +29 -0
  115. package/dist/migrations/legacy-office-files.js.map +1 -0
  116. package/dist/migrations/session-v3.d.ts +57 -0
  117. package/dist/migrations/session-v3.d.ts.map +1 -0
  118. package/dist/migrations/session-v3.js +93 -0
  119. package/dist/migrations/session-v3.js.map +1 -0
  120. package/dist/migrations/sessions-sqlite.d.ts.map +1 -1
  121. package/dist/migrations/sessions-sqlite.js +98 -54
  122. package/dist/migrations/sessions-sqlite.js.map +1 -1
  123. package/dist/observability/instrument.js +2 -5
  124. package/dist/observability/instrument.js.map +1 -1
  125. package/dist/observability/sentry.js +1 -1
  126. package/dist/observability/sentry.js.map +1 -1
  127. package/dist/office/projection.js +2 -2
  128. package/dist/office/projection.js.map +1 -1
  129. package/dist/runtime/conversation-runtime.js +9 -14
  130. package/dist/runtime/conversation-runtime.js.map +1 -1
  131. package/dist/runtime/types.d.ts +2 -7
  132. package/dist/runtime/types.d.ts.map +1 -1
  133. package/dist/runtime/types.js.map +1 -1
  134. package/dist/sandbox/identity.d.ts +0 -1
  135. package/dist/sandbox/identity.d.ts.map +1 -1
  136. package/dist/sandbox/identity.js +0 -3
  137. package/dist/sandbox/identity.js.map +1 -1
  138. package/dist/sandbox/registry.d.ts +1 -5
  139. package/dist/sandbox/registry.d.ts.map +1 -1
  140. package/dist/sandbox/registry.js +4 -13
  141. package/dist/sandbox/registry.js.map +1 -1
  142. package/dist/sandbox/types.d.ts +1 -5
  143. package/dist/sandbox/types.d.ts.map +1 -1
  144. package/dist/sandbox/types.js.map +1 -1
  145. package/dist/sessions/types.d.ts +1 -1
  146. package/dist/sessions/types.d.ts.map +1 -1
  147. package/dist/sessions/types.js.map +1 -1
  148. package/dist/settings/apply.d.ts +1 -1
  149. package/dist/settings/apply.d.ts.map +1 -1
  150. package/dist/settings/apply.js +4 -5
  151. package/dist/settings/apply.js.map +1 -1
  152. package/dist/settings/index.d.ts +59 -5
  153. package/dist/settings/index.d.ts.map +1 -1
  154. package/dist/settings/index.js +75 -54
  155. package/dist/settings/index.js.map +1 -1
  156. package/dist/types.d.ts +3 -28
  157. package/dist/types.d.ts.map +1 -1
  158. package/dist/types.js.map +1 -1
  159. package/dist/vault/index.d.ts.map +1 -1
  160. package/dist/vault/index.js +2 -15
  161. package/dist/vault/index.js.map +1 -1
  162. package/package.json +4 -17
  163. package/dist/cli/download.d.ts +0 -2
  164. package/dist/cli/download.d.ts.map +0 -1
  165. package/dist/cli/download.js +0 -84
  166. package/dist/cli/download.js.map +0 -1
  167. package/dist/harness/index.d.ts +0 -20
  168. package/dist/harness/index.d.ts.map +0 -1
  169. package/dist/harness/index.js +0 -14
  170. package/dist/harness/index.js.map +0 -1
  171. package/dist/migrations/dream-checkpoints.d.ts +0 -3
  172. package/dist/migrations/dream-checkpoints.d.ts.map +0 -1
  173. package/dist/migrations/dream-checkpoints.js +0 -23
  174. package/dist/migrations/dream-checkpoints.js.map +0 -1
  175. package/dist/migrations/private-office-dirs.d.ts +0 -3
  176. package/dist/migrations/private-office-dirs.d.ts.map +0 -1
  177. package/dist/migrations/private-office-dirs.js +0 -24
  178. package/dist/migrations/private-office-dirs.js.map +0 -1
  179. package/dist/migrations/session-files.d.ts +0 -28
  180. package/dist/migrations/session-files.d.ts.map +0 -1
  181. package/dist/migrations/session-files.js +0 -80
  182. package/dist/migrations/session-files.js.map +0 -1
  183. package/dist/migrations/session-v4.d.ts +0 -77
  184. package/dist/migrations/session-v4.d.ts.map +0 -1
  185. package/dist/migrations/session-v4.js +0 -177
  186. package/dist/migrations/session-v4.js.map +0 -1
  187. package/dist/migrations/sessions-v3.d.ts +0 -8
  188. package/dist/migrations/sessions-v3.d.ts.map +0 -1
  189. package/dist/migrations/sessions-v3.js +0 -350
  190. package/dist/migrations/sessions-v3.js.map +0 -1
  191. package/dist/sandbox/cloudflare.d.ts +0 -17
  192. package/dist/sandbox/cloudflare.d.ts.map +0 -1
  193. package/dist/sandbox/cloudflare.js +0 -142
  194. package/dist/sandbox/cloudflare.js.map +0 -1
  195. package/dist/sandbox/index.d.ts +0 -7
  196. package/dist/sandbox/index.d.ts.map +0 -1
  197. package/dist/sandbox/index.js +0 -6
  198. package/dist/sandbox/index.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -4,686 +4,740 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  The format is loosely based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html)
7
- once it leaves the 0.x line. While on `0.2.0-beta.*`, breaking changes may land in
8
- any release.
7
+ from 1.0.0 on. The package interface is the root export of `@geminixiang/mikan`; the
8
+ CLI, `settings.json`, `mikan.env`, and the state layout under `~/.mikan` are covered too.
9
9
 
10
10
  ## [Unreleased]
11
11
 
12
- ## [1.0.0-beta.94]
12
+ 1.0.0 is the first stable release. It replaces the 0.5.3 runtime, which ran on
13
+ `pi-coding-agent`, with mikan's own harness on `pi-durable` and `pi-ai`, and gives every
14
+ conversation its own office. The 97 `1.0.0-beta.*` prereleases are summarized here; their
15
+ individual notes remain in the [GitHub releases](https://github.com/geminixiang/mikan/releases).
13
16
 
14
- ### Changed
15
-
16
- - Pi dependencies (`pi-durable`, `pi-ai`, `pi-agent-core`, `chord`) are pinned to 1.0.2.
17
+ ### Upgrading from 0.5.3
17
18
 
18
- ### Fixed
19
+ `mikan migrate` upgrades a 0.5.3 install in place; it is the only supported upgrade path, and
20
+ formats that existed only in 1.0.0 prereleases are not converted. The daemon refuses to start
21
+ while migrations are pending and prints the exact command to run. Follow
22
+ [Upgrading from 0.5.3](https://mikan.geminixiang.com/deployment/#upgrading-from-053) in the
23
+ deployment guide, which lists what migrates, what does not, and what to check afterwards.
19
24
 
20
- - Chat-history sync no longer drops a new human message because an earlier message has the same text. Each synced history line keeps its platform message ID, and the message that started a run counts as handled only once Pi has admitted it, so repeated confirmations and identical messages from different people reach the model, including after a session reset or in a forked thread, and a request that failed before admission (for example, missing credentials) stays in history. A history batch and its sync cursor are written in one Pi commit. Previously omitted history is not automatically restored.
21
- - Provider requests are routed to their conversation by Pi's own provider session ID instead of by message-object identity: compaction now counts against its own conversation's budget rather than the most recently started run's, and a request with no matching conversation fails instead of borrowing another conversation's models. Provider prompt caches key on Pi's persisted session ID; conversations without one get it once on their next run.
22
- - The system prompt's channel table no longer lists every channel and direct message the bot belongs to in every conversation: it names only the conversation itself and the public channels whose offices the conversation can read, so the names of private channels and the people who direct-message the bot no longer reach other conversations, as office visibility promises. On a deployment with 279 such conversations the table drops from 8.9k to 6.2k characters.
23
- - The usage summary, the `agent.run.*` metrics, and the run span's usage attributes now count the spend of subagents a run delegates to and of compaction during the run, matching the total the run budget enforces; they previously counted only the main agent's own model calls, so a run whose subagent wrote about 2,000 output tokens reported 21.
25
+ ### Added
24
26
 
25
- ## [1.0.0-beta.93]
27
+ - **Conversation offices.** Each conversation gets its own directory, sandbox runtime, vault,
28
+ settings, sessions, and scheduled events, named by an office key
29
+ (`v1-<platform>-<readable-id>-<hash>`) so two platforms never collide on one raw id. Offices
30
+ are public or private, following the Slack conversation type, and `image:*` sandboxes enforce
31
+ it: a private office sees only itself plus shared knowledge. `mikan office list` prints them.
32
+ - **GitHub adapter.** A regular GitHub account, bound with a fine-grained token and an
33
+ organization webhook, answers mentions, assignments, and review requests; each issue or pull
34
+ request is one conversation.
35
+ - **Durable sessions.** Each office keeps its sessions in one SQLite database (`sessions.db`)
36
+ through `pi-durable`. Sessions survive restarts, a channel's top-level session stays current
37
+ until `/new` with Pi compacting old context, and threads keep their own sessions. The agent's
38
+ `history` tool reads the conversation's earlier sessions.
39
+ - **MCP servers and codemode.** `mcpServers` in `settings.json` connects MCP servers; the agent
40
+ reaches their tools through Pi's codemode and searches large tool lists on demand.
41
+ OpenConnector can provision a per-conversation MCP token.
42
+ - **Subagents.** The agent delegates bounded work, in parallel or as a dependency graph, to
43
+ subagents with role profiles, their own tools, and token, cost, and time budgets.
44
+ - **Admin portal and session viewer.** `/admin` opens a 30-minute portal for model, sandbox
45
+ limits, office visibility, reply mode, MCP servers, and skills; `session` opens a read-only view
46
+ of the current session.
47
+ - **Memory capture.** After each human-triggered run, durable facts go to the office's
48
+ `MEMORY.md`.
49
+ - **Jev.** A small model answers yes/no decisions, such as whether a Slack message addresses the
50
+ bot in `/pi-auto-reply jev` mode, and drives the `jev_browser` tool.
51
+ - **Platform rendering.** Slack answers stream into native markdown and table blocks, with the
52
+ `slack_blockkit` tool for interactive messages; Discord uses Components V2; Telegram uses rich
53
+ formatting. Long answers continue in the thread instead of failing.
54
+ - **CLI.** `mikan onboard` writes `settings.json` and `mikan.env` from a few questions, `mikan env`
55
+ lists every environment variable and which are set, and `mikan migrate` applies state
56
+ migrations with `--dry-run`.
57
+ - **Observability.** Standard OTLP export through the `OTEL_*` variables, alongside Sentry.
58
+
59
+ ### Changed
60
+
61
+ - Node.js 24.15.0 or newer is required.
62
+ - `mikan.env` holds secrets and deployment addresses; `settings.json` holds behavior. The
63
+ Sentry DSN is read only from `SENTRY_DSN`, so a `sentry.dsn` setting is ignored, and the GitHub
64
+ adapter's repositories and trigger rules live under `github` in `settings.json`. At startup the
65
+ daemon logs each environment variable it no longer reads, with what replaces it.
66
+ - State lives in `~/.mikan` only: `settings.json`, `mikan.env`, `models.json`, vaults, and the
67
+ host-only per-conversation directories under `conversations/`. Per-conversation settings,
68
+ sessions, and scheduled events moved out of the workspace, where sandboxes could read them.
69
+ - The workspace argument is optional and defaults to `~/.mikan/workspace`.
70
+ - Inside a sandbox, an office's files are at `/workspace/<office-key>` instead of
71
+ `/workspace/<conversation-id>`. Paths quoted in sessions from before the upgrade point at the
72
+ old location.
73
+ - `image:<image>` provisions one managed container and one vault per office, recreated from the
74
+ current image when missing; `/pi-sandbox boost` raises its limits until it stops.
75
+ - Vault directories use hashed keys instead of raw user and container names.
76
+ - Only `session` and `stop` work without a leading slash; `new`, `model`, and `auto-reply` need
77
+ their slash forms (`/new`, `/pi-new`, …).
78
+ - Auto-reply is Slack-only and takes `on`, `off`, or `jev`. A 0.5.3 channel with auto-reply
79
+ rules replies to every top-level message; the rules are ignored.
80
+ - The link server for the portal and credential links listens on `127.0.0.1` unless
81
+ configured otherwise.
82
+ - The package exports only what an embedder needs: `createConversationRuntime`,
83
+ `createWorkspace`, `createOfficeAddress`, `officeKey`, `createConversationEvent`,
84
+ `createConversationMessage`, `defaultCommandHandlers`, `MikanModels`, and the types they use.
85
+ The `@geminixiang/mikan/harness` and `@geminixiang/mikan/sandbox` entry points are gone.
26
86
 
27
- ### Added
87
+ ### Removed
28
88
 
29
- - Skills can be turned off and on per workspace and per conversation with Pi's resource rules: `skills` in the global or conversation settings takes `!glob`, `+path`, and `-path` entries over each skill's directory, every skill stays listed by default, and an excluded skill is left out of the system prompt. The admin portal's Skills pages list every skill the agent loads, including nested ones such as `bundle/vendors/<skill>` that they previously missed, grouped by directory with a filter, and toggle them: the workspace page writes the global entries, and a conversation page cycles a skill between inherited, `+`, and `-` and shows how many skills and characters the prompt lists.
89
+ - The `pi-coding-agent` runtime and its extension loading; mikan loads no third-party code into
90
+ its process (ADR 0006). Skills in `skills/` directories remain.
91
+ - The `firecracker:*` and `cloudflare:*` sandboxes.
92
+ - `--state-dir` and the `STATE_DIR` / `MIKAN_STATE_DIR` variables, and `--download`.
93
+ - Auto-reply on Discord and Telegram, and auto-reply rules.
94
+ - `SENTRY_ENABLED` (leave `SENTRY_DSN` unset to turn Sentry off) and `HTTP_IDLE_TIMEOUT`
95
+ (outbound HTTP streams time out after five minutes).
96
+ - Provider keys in `~/.pi/mikan/auth.json`; put them in `~/.mikan/mikan.env` or `models.json`.
30
97
 
31
- ## [1.0.0-beta.92]
98
+ ### Fixed
32
99
 
33
- ### Changed
100
+ - Slack startup and reconnects no longer hang without a log line when Slack accepts the
101
+ connection and never answers; a socket silent for 30 seconds is dropped and retried, and the
102
+ daemon logs `Slack connection lost; reconnecting` and `Slack reconnected after Ns`.
103
+ - Stopping the daemon while it is still connecting to Slack ends in a graceful shutdown.
104
+ - When Telegram ends long polling because the token was revoked (401) or another process polls
105
+ the same bot (409), the daemon logs the reason and exits with code 1 for the process manager
106
+ to restart, instead of running on without receiving messages.
107
+ - A Slack message whose acknowledgement was lost during a reconnect runs once, not twice.
34
108
 
35
- - Codemode guides the model to discover every tool a task needs in one script and to parse MCP results and emit only the fields the answer needs, because everything a script emits is sent again on every later model call. `searchTools()` and `tool_search` rank with BM25 over names, descriptions, argument schemas, and the MCP server name, splitting camelCase like Pi, so a query such as `OpenConnector` finds `mcp__open-connector__*` tools; the default limit is 8.
109
+ ## [1.0.0-beta.96]
36
110
 
37
- ## [1.0.0-beta.91]
111
+ The last prerelease before 1.0.0. Installs on 1.0.0-beta.95 run one migration,
112
+ `0012-legacy-office-files`, before the daemon starts.
38
113
 
39
- ### Changed
114
+ ### Removed
40
115
 
41
- - MCP follows Pi's codemode design. MCP tools are reached from `codemode` scripts by default and `tool_search` exists only for servers configured with `"exposure": "deferred"`. A script receives each MCP tool's complete `CallToolResult` (`content`, `structuredContent`, `isError`) instead of the bounded view the model gets, so it can filter large results before they enter the context, and an MCP error resolves with `isError: true` instead of rejecting. The `codemode` description no longer repeats the declarations of tools already declared to the model; each of those tools' descriptions says what a script call resolves to. Server instructions are no longer copied into the system prompt: an `mcp_servers` section lists each server once with the first line of its new optional `description` or its instructions, and scripts read the rest with the new `describeNamespace()`. On a local request these changes cut the tool declarations from 38,274 to 26,538 characters and the codemode description from 14,232 to 2,803.
42
- - A direct MCP call that the server marks `isError` returns an error result instead of throwing, keeping the server's message.
116
+ - `--state-dir` and the `STATE_DIR` / `MIKAN_STATE_DIR` variables: state always lives in
117
+ `~/.mikan`, and passing `--state-dir` is an error.
118
+ - The experimental `cloudflare:<sandbox-id>` sandbox with `CLOUDFLARE_SANDBOX_URL` and
119
+ `CLOUDFLARE_SANDBOX_TOKEN`, and `mikan --download`.
120
+ - The `@geminixiang/mikan/harness` and `@geminixiang/mikan/sandbox` entry points and every root
121
+ export an embedder does not need; the root keeps `createConversationRuntime`,
122
+ `createWorkspace`, `createOfficeAddress`, `officeKey`, `createConversationEvent`,
123
+ `createConversationMessage`, `defaultCommandHandlers`, `MikanModels`, and the types they use.
124
+ `MessagingBot` drops the optional `addReaction`, `uploadFile`, `openDirectConversation`,
125
+ `fetchHistory`, and `listUsers`.
126
+ - `SENTRY_ENABLED` and `HTTP_IDLE_TIMEOUT`, and the `sentry.dsn` setting: the DSN comes only from
127
+ `SENTRY_DSN`, and Sentry runs exactly when it is set.
128
+ - The `event` tool's `scope` parameter, and `channelId` in place of `conversationId` in event files.
129
+
130
+ ### Changed
131
+
132
+ - The GitHub adapter's repositories and trigger rules move from `GITHUB_REPOS`,
133
+ `GITHUB_PUBLIC_REPOS`, `GITHUB_USERS`, `GITHUB_MIN_PERMISSION`, `GITHUB_TRIGGERS`, and
134
+ `GITHUB_CAPABILITIES` to the `github` block of `settings.json`, as JSON lists.
135
+ - At startup the daemon logs each `settings.json` key and each environment variable it no longer
136
+ reads, with what replaces it.
137
+ - `mikan onboard` asks fewer questions and lists only the variables it set; `mikan env` folds the
138
+ 19 `OTEL_*` variables into one line and lists every variable mikan reads.
139
+ - `0012-legacy-office-files` removes the `last_prompt.jsonl` and `auto-reply.disabled` files 0.5.3
140
+ left in office directories.
141
+ - `@earendil-works/pi-codemode` and `@earendil-works/pi-mcp` are pinned to 1.0.0.
43
142
 
44
- ## [1.0.0-beta.90]
143
+ ### Fixed
45
144
 
46
- ### Changed
145
+ - Slack startup and reconnects give up a connection that stays silent for 30 seconds and retry,
146
+ instead of hanging without a log line; the daemon logs lost connections and reconnection time.
147
+ - Stopping the daemon while it connects to Slack ends in a graceful shutdown instead of
148
+ `Failed to start bot undefined` and exit code 1.
149
+ - When Telegram ends long polling on 401 or 409, the daemon logs why and exits for the process
150
+ manager to restart it, instead of running on without messages.
151
+ - `mikan migrate` refuses to run when the state directory or workspace is not a mikan install,
152
+ instead of recording every step as applied.
153
+ - Office state directories are created with mode `0700`.
154
+ - The startup log reports the HTTP idle timeout actually applied.
155
+ - A Slack App Home Force Stop button without a session key stops nothing.
47
156
 
48
- - Run `mikan migrate` before starting this version. It deletes each office's `dream.json`, the checkpoint of the Dream maintenance removed in [ADR 0012](docs/adr/0012-remove-dream.md) that nothing reads, and makes every directory under `<state-dir>/conversations/` readable only by its owner (mode 700); links are not followed.
157
+ ## [0.5.3] - 2026-06-30
49
158
 
50
- ### Security
159
+ ### Added
51
160
 
52
- - An office's `events/` directory is created readable only by its owner (mode 700) instead of following the process umask.
161
+ - Append a session-view link to event-triggered attribution messages.
162
+ - Show raw cached token counts and cache-hit rate in usage summaries.
53
163
 
54
- ## [1.0.0-beta.89]
164
+ ### Changed
55
165
 
56
- ### Breaking
166
+ - Use a stable, low-noise usage summary layout with token units and fixed cost breakdowns.
167
+ - Mark the auto-reply command as deprecated.
57
168
 
58
- - **Pi is upgraded to 1.0, and conversations now run on `@earendil-works/pi-durable`.** Pi 1.0 removed the harness, sessions, compaction, and coding tools from `pi-agent-core`; pi-durable is their first-party successor (see [ADR 0017](docs/adr/0017-pi-durable-harness.md)). Each office now keeps all its sessions in one SQLite storage, `sessions.db` in its State dir (see [ADR 0018](docs/adr/0018-one-durable-storage-per-office.md)); this needs Node 24.15 or later, whose built-in `node:sqlite` prints an experimental warning on load. Run `mikan migrate` before starting this version: it imports each office's v4 session files into that storage, the current main session as the top-level session and earlier main sessions and threads beside it, and moves the office's `sessions/` directory to `sessions-v4/`. An imported session keeps what the model could still see (the newest compaction summary and everything after it), its name, ID, and mikan's bookkeeping; history an earlier compaction had already hidden stays only in the archived files. Every office must be in `office-registry.json`. A tool call that was still running at upgrade is closed with an error result instead of being retried, and a run left unfinished is not resumed.
59
- - `/new` resets the session in place: the model starts from an empty context, and the earlier history stays readable to the `history` tool and the session view instead of moving to a new session file.
60
- - Library API: `createManagedSessionFile`, `createManagedSessionFileAtPath`, `createNewSessionFile`, `extractSessionSuffix`, `extractSessionUuid`, `getThreadSessionFile`, `openManagedSession`, `resolveManagedSessionFile`, `resolveSessionFile`, `tryResolveCurrentSession`, `tryResolveThreadSession`, `isPlatformHistorySession`, `CURRENT_SESSION_VERSION`, `MikanSessionHeader`, and `ChatSyncReport` are removed with session files; `SessionHeader` holds only `id`, `createdAt`, and `parentSessionId`; `registerThreadSession` and `hasMaterializedChatSession` are asynchronous, and `ResolvedSessionScope` no longer has `contextFile`.
61
- - Library API: `SessionEntry` is mikan's own union of `message`, `custom`, and `compaction` entries, with IDs qualified by the session ID; `BranchSummaryEntry`, `CompactionEntry`, and `CustomEntry` are no longer exported. `SessionStore.createHarness` is replaced by `bindHarness`; `appendCustomMessageEntry`, the tree-era `getBranch`, `getLeafId`, `getEntry`, and `isPersisted`, and `SessionEntry.parentId` are removed; `SessionStore.getContextEntries()` returns the entries still in the model's context; and `MikanAgentSession.compactWhenNearLimit`/`cancelIdleCompaction`/`foldExternalUsage` are gone. `HarnessEvent` no longer mirrors pi-agent-core's `AgentEvent`: it drops `agent_start`/`agent_end`/`turn_start`/`turn_end`, replaces `message_update` with `text_delta`, and tool events carry `details` and a `{ content, details }` result. `MikanAgentSession.messages` and `reloadFromSession` are removed: the session keeps no transcript copy, so read the context through `SessionStore`, and a run's own messages through `lastRunMessages`. Harness tools use pi-durable's `execute(args, api, context)`; plain `AgentTool`s are still adapted.
169
+ ### Fixed
62
170
 
63
- ### Added
171
+ - Harden state file writes to avoid readers seeing partial state.
172
+ - Reject malformed OAuth configuration during login setup.
64
173
 
65
- - Slack and Discord mark a message with ⏳ when it waits behind a task that is still running, so a queued message no longer looks ignored.
66
- - The agent gets a `history` tool, in every conversation, that lists the conversation's sessions (earlier ones replaced by `/new` and its threads), searches or reads them including tool calls and their output that `log.jsonl` does not keep, and searches the chat log; a query matches entries containing all of its words, and a Chinese or Japanese word also matches when most of its character pairs appear, so `暫時代號` finds `暫時註記:代號`. The system prompt tells the agent to answer from its own context when it can, and to look up a result its context lacks, such as a command's output from another session, instead of guessing or rerunning the command. It never reaches another conversation.
67
- - `SENTRY_TRACES_SAMPLE_RATE` (0 to 1, default 1) sets how many traces go to Sentry when OTLP traces are not configured; an invalid value stops startup.
174
+ ### Tests
68
175
 
69
- ### Changed
176
+ - Add unit coverage for utility and tool modules.
177
+ - Expand Slack end-to-end coverage and make CI Slack artifacts more reliable.
70
178
 
71
- - A new thread starts from what caused it. A thread under a channel answer, or under the message that triggered it, forks that run, so it carries the run's context up to its end, including tool calls and their output: asked what a command printed, the agent reads it instead of guessing or running it again. Any other thread starts from its root and its own replies, instead of ten earlier top-level messages copied from the chat log. Each run records the message that started it, and the chat log records each run answer with that message and its session.
72
- - Chat history never appears as the agent's own turn: synced messages from other people, other bots, and mikan's notices enter a session as attributed chat lines, and an answer a run posted is left to its own session, so a Discord or Telegram reply answered in another session no longer leaks into the channel session.
73
- - Compaction is Pi's: it runs in the background as the context grows and blocks the next request only near the limit, so mikan no longer starts its own compaction after a reply. Compaction summary requests now count toward a run's LLM-call and token budgets, and a request over the LLM-call budget is never sent.
74
- - A run left unfinished by a crash or restart is aborted before the next message in that conversation instead of answering first.
75
- - A thread session is named after the first line of its root message, cut to 80 characters, instead of the whole message; existing thread sessions take the short name on their next run.
179
+ ## [0.5.2] - 2026-06-26
76
180
 
77
- ### Fixed
181
+ ### Added
78
182
 
79
- - A one-shot event whose time passed while mikan was restarting or stopped now fires when mikan starts, instead of being deleted without running.
80
- - Tool results that report `isError` reach the model as errors, so a failing codemode script is no longer recorded as a success.
81
- - A run stopped before the model wrote anything no longer stores a made-up aborted answer, and its reply is never taken from the previous run.
82
- - Compaction entries in the session view and subagent parent context show the summary itself, without Pi's wrapper text, and a subagent's parent context keeps the messages Pi retained after compaction.
83
- - A run Pi settles with a model error is recorded as failed instead of completed.
84
- - The usage summary's context size follows Pi's rule, the newest successful answer after the latest compaction, so it no longer reports the pre-compaction size, and it is omitted until a new answer measures it.
183
+ - Show the top 20 pi sessions by token usage in the admin portal, including channel labels and raw input, output, cache read, cache write, total, and cost columns.
85
184
 
86
- ## [1.0.0-beta.88]
185
+ ## [0.5.1] - 2026-06-26
87
186
 
88
187
  ### Added
89
188
 
90
- - `tool_search` discovers authorized MCP tools and loads matching schemas for the next model call. MCP connections still start as before, but tools are no longer all declared upfront. Loaded tools survive later prompts and session reopen, subject to current grants. Codemode gains `searchTools()` and omits MCP schemas from its inline description.
91
- - `codemode` runs JavaScript through Pi's official QuickJS sandbox to combine authorized tools and filter results before returning them to the model. Existing direct tools remain available; nested calls honor per-run grants, loop guards and cancellation, and appear in progress and tool-call counts. Sessions without tools stay tool-less.
189
+ - Render markdown as Slack Block Kit.
190
+ - Show live tool progress during agent runs.
92
191
 
93
- ### Fixed
192
+ ## [0.5.0] - 2026-06-25
94
193
 
95
- - Codemode follows Pi's model-facing helper guidance and generates asynchronous global declarations from the same definitions used by the official sandbox. `searchTools` and `describeTool` are explicitly global functions called with `await`; their complete declarations remain available even when the nested tool catalog exceeds its inline budget. Discovery uses Pi-generated tool samples with declared output schemas and its text-result default, so scripts can distinguish JSON text from structured values.
194
+ ### Added
96
195
 
97
- ## [1.0.0-beta.87]
196
+ - Add the Starlight documentation site with localized docs for English, Japanese, Simplified Chinese, and Traditional Chinese.
197
+ - Add platform adapter guides for Slack, Discord, and Telegram.
198
+ - Add a web agent-events portal for streaming agent events.
98
199
 
99
- ### Fixed
200
+ ### Changed
100
201
 
101
- - `mikan migrate` moves the per-thread session directories that early versions left inside `sessions/` to the state directory intact, instead of stopping with `Unexpected entry in sessions directory`. Links inside them are moved as links and never followed.
202
+ - Align adapter, runtime, and session naming around conversation terminology for clearer contributor navigation.
203
+ - Update project dependencies and bundled pi packages.
102
204
 
103
- ## [1.0.0-beta.86]
205
+ ### Fixed
104
206
 
105
- ### Breaking
207
+ - Preserve custom Starlight theme component overrides.
208
+ - Keep the docs dev server from restarting when settings cleanup runs.
209
+ - Tighten Sentry event sanitization.
106
210
 
107
- - **The GitHub adapter now runs as a bound GitHub account driven by webhooks, and no longer uses a GitHub App or polling.** People mention it with autocomplete, assign it issues and pull requests, and request its review. Set `GITHUB_AGENT_TOKEN` (a fine-grained PAT of that account), `GITHUB_WEBHOOK_SECRET` (an organization or App webhook to `<LINK_URL>/github/webhook`), and `GITHUB_REPOS` (now required: `owner/repo` or `owner/*`); the link server must run. `GITHUB_APP_ID`, `GITHUB_INSTALLATION_ID`, `GITHUB_APP_PRIVATE_KEY`, `GITHUB_APP_PRIVATE_KEY_PATH`, and `GITHUB_POLL_INTERVAL` are removed, `@<app-slug>` no longer triggers, and `<state-dir>/github-sync.json` is no longer read and can be deleted. Deliveries are best effort: events sent while mikan is down are not replayed. See [ADR 0015](docs/adr/0015-github-agent-account-and-webhooks.md) and [Make mikan a GitHub teammate](src/content/docs/github-teammate-guide.md).
108
- - **The GitHub adapter is restricted by default.** It answers only in private repositories listed in `GITHUB_REPOS`, only to people with write permission, and only comments and reads. `GITHUB_CAPABILITIES=triage,push` restores label and assignee management and pull requests; `GITHUB_PUBLIC_REPOS`, `GITHUB_USERS`, `GITHUB_MIN_PERMISSION`, and `GITHUB_TRIGGERS` narrow or widen who can trigger it and how.
109
- - `github_checks` reads GitHub Actions jobs and commit statuses instead of check runs, because fine-grained PATs have no Checks permission. Check runs from third-party CI apps are no longer visible.
110
- - **mikan no longer runs git for GitHub conversations.** Nothing is cloned into `<office>/repo`, and `github_sync` is removed. The agent clones, commits, and pushes inside its sandbox with the sandbox's GitHub credentials, and `github_pr` only opens a pull request for a branch the agent already pushed. What the agent can push is now bounded by that token, the account's repository role, and branch protection instead of mikan's `pi/*` rule; protect the default branch. GitHub conversations now trust `membership`, because only collaborators with write access can trigger them, so they receive `sandbox.defaultSharedVault` and settings-declared MCP servers like Slack conversations.
111
- - **Session files move from `<workspace>/<office-key>/sessions/` to `<state-dir>/conversations/<office-key>/sessions/`, and sandboxes no longer see them.** Run `mikan migrate` before starting this version. The agent searches earlier history in `log.jsonl`, which stays in the office directory. See [ADR 0016](docs/adr/0016-host-sandbox-trust-boundary.md).
112
- - Library API: `officeSessionsDir` and `resolveChannelSessionFile` are removed; use `office.sessionsDir` and `tryResolveCurrentSession(office.sessionsDir)`. `getThreadSessionFile` and `resolveParentSessionForThread` take the sessions directory, and the `ChatHistorySync` options and `registerThreadSession`/`hasMaterializedChatSession` take `office` instead of `conversationDir`.
113
- - `jev_browser` no longer takes a `session` parameter. Each conversation thread has one browser that stays open across calls until `close: true`; a later `url` opens a new tab, and opening past three tabs closes the oldest inactive tabs and reports them in `closedOldTabs`. Model-named sessions each started another Chrome, and a few of them exhausted a 1 GB sandbox until every page load timed out.
211
+ ## [0.4.8] - 2026-06-22
114
212
 
115
213
  ### Changed
116
214
 
117
- - Pi is upgraded from 0.87 to 0.99 (`pi-agent-core`, `pi-ai`).
118
- - MCP servers now connect through Pi's `@earendil-works/pi-mcp` client instead of the official `@modelcontextprotocol/sdk`, which is removed along with `zod`. Stdio servers still receive only a minimal inherited environment plus their configured `env`. When an HTTP server rejects the connection, the error now carries the status and the start of the server's response body.
215
+ - Update bundled pi packages to the 0.79.9 line.
119
216
 
120
- ### Added
121
-
122
- - GitHub issue and pull request conversations receive the default OpenConnector runtime token like Slack conversations, named `mikan:github:<conversation-id>`.
217
+ ## [0.4.7] - 2026-06-22
123
218
 
124
219
  ### Fixed
125
220
 
126
- - `models.json` follows `--state-dir` / `STATE_DIR` like `settings.json`; the daemon, `mikan migrate`, and `mikan onboard` no longer read or write `~/.mikan/models.json` for another state directory.
127
- - A daemon adopts at startup only the sandbox containers that mount its own workspace, so two mikan instances sharing one Docker engine no longer stop each other's containers.
128
- - The sandbox image now ships CJK fonts (`fonts-noto-cjk`, about 170 MB). Without them, `jev_browser` screenshots showed Chinese and Japanese text as blank space, and charts drawn in the sandbox could not use Chinese labels.
129
- - Python packages in the sandbox go through uv. The system pip still refuses installs, but its message now names the uv commands to use (`uv run --with <package>`), so the agent recovers after one attempt instead of trying pip, venvs, and apt in turn. The docs no longer claim that `pip install --user` works.
130
- - Creating or updating a periodic event now reports its next three runs in the event's timezone, so the agent no longer computes weekdays itself (it once announced a Monday reminder for a Tuesday). An invalid cron `schedule` or `timezone` is rejected before the event file is written instead of being saved and then skipped by the scheduler.
131
- - `apt-get install` works inside managed sandbox containers again. The containers drop all capabilities, so apt's download sandbox user could not switch groups and every install failed; the image now runs apt downloads as root, and the image smoke test installs a package under the same hardening.
132
- - Asking "好了嗎" at the moment a background task finishes no longer answers "還在處理" right beside the completion notice. Task status now trusts the recorded end of the run over the runtime's still-settling state.
133
- - A Slack message whose acknowledgement was lost during a socket reconnect no longer runs twice. Slack redelivers such events; mikan now recognizes a message or mention it has already taken and ignores the copy. A failed acknowledgement is logged instead of surfacing as an unhandled promise rejection.
134
- - A Slack app that is not an agent app no longer calls `assistant.threads.setSuggestedPrompts` and logs `not_agent_app` every time someone opens its DM; after the first refusal the call is skipped until restart.
135
- - A long Slack answer that outgrew the native stream no longer shows up twice. The partial streamed message is deleted before the full answer is posted, and the notification text sent with it is capped at the 4,000 bytes `chat.update` accepts, so the edit no longer fails with `msg_too_long`.
136
- - A long Slack answer with many headings no longer fails with `invalid_blocks` and an `Error:` line. Slack expands each heading of a markdown block into its own block and rejects a message with more than 50; when an answer would exceed that, its headings are sent as bold lines instead.
137
- - MCP tools ask the model for a progress label like every built-in tool, so the Slack checklist shows a readable step (for example "確認 GitHub 連線") instead of `mcp__server__tool`. The label is not forwarded to the MCP server, and a tool that already has its own `label` argument is left unchanged.
221
+ - Apply the recent-days and max-messages history window when syncing existing chat sessions so resuming a session no longer replays unbounded older log history.
138
222
 
139
- ## [1.0.0-beta.85]
223
+ ### Changed
140
224
 
141
- ### Breaking
225
+ - Always report a usage summary whenever token usage is available.
142
226
 
143
- - **State migrations run only through `mikan migrate`.** The daemon now refuses to start while a migration is pending, and prints the exact command to run. It no longer moves anything at startup or on first read. After installing a new version, run `mikan migrate --sandbox=<the daemon's --sandbox> --dry-run`; if anything is pending, stop the daemon, run the same command without `--dry-run`, then start it. Applied migrations are recorded in `<state-dir>/migrations.json`, and `mikan onboard` marks a new state directory as fully migrated. See [ADR 0014](docs/adr/0014-versioned-state-migrations.md).
144
- - **Removed commands:** `mikan office claim`, `mikan office migrate-openconnector`, `mikan office migrate-events`, `mikan office migrate-door-policy`, `mikan sessions migrate`, and `mikan sandbox status|diff|migrate`. `mikan office list` remains and now prints each office key with its platform and conversation id.
145
- - **Upgrades are supported only from 0.5.3.** Formats that existed only in 1.0.0 prereleases are no longer converted: OpenConnector `open-connector-runtime-token.json` files, door-policy settings, Pi 0.84 session files, `<state-dir>/conversations/<raw-id>` directories, and the hashed legacy vault keys. A prerelease install that already ran those conversions is unaffected.
146
- - **Sandbox containers are disposable.** A managed container has no home volume. When its image or mounts change, it is replaced once it is stopped, and only the workspace and vault mounts carry over. Anything else, including `/root`, installed packages, and caches, starts empty. Existing `mikan-home-*` volumes and `mikan-migrate:*` images are no longer used, and operators may delete them.
147
- - **Host and container vaults use hashed keys only.** The runtime no longer falls back to vault directories named by raw user id (`host`) or `container-<name>` (`container:*`). `mikan migrate` renames them.
148
- - The public API no longer exports `findV3SessionFiles`, `isV3SessionFile`, or `migrateSessionFile`.
227
+ ### Tests
149
228
 
150
- ### Changed
229
+ - Add coverage for capping existing chat history sync to the recent history window.
151
230
 
152
- - When a scheduled run hits its budget, the stop notice now says how long it ran, how many model and tool calls it made, the slowest steps with their durations, and which step was still running. Slow queries can be found from the notice alone.
231
+ ## [0.4.6] - 2026-06-18
153
232
 
154
233
  ### Fixed
155
234
 
156
- - Multi-line error notices in Slack are italicized line by line, because Slack emphasis does not span line breaks.
157
- - Upgrading a 0.5.3 install keeps each conversation's credentials. The old startup migration looked for a vault name that 0.5.3 never wrote, so 0.5.3 conversation vaults were silently left behind; `mikan migrate` moves them to their office keys.
158
- - Upgrading a 0.5.3 install removes its sandbox containers instead of recreating them from snapshots under their old names next to the new ones.
235
+ - Store Slack streamed responses as a single finalized bot log entry instead of per-delta fragments.
236
+ - Coalesce legacy Slack bot log fragments when bootstrapping chat sessions so platform history is not filled with partial words.
159
237
 
160
- ## [1.0.0-beta.84]
238
+ ### Tests
161
239
 
162
- ### Performance
240
+ - Add coverage for coalescing streamed bot history and logging only finalized Slack responses.
163
241
 
164
- - Shorten the `jev_browser` tool definition from about 7,000 to 2,800 characters sent on every turn: its description and parameters no longer repeat each other or explain rules the tool already enforces with its own error messages.
165
- - List skills in the prompt one line each under their directory instead of an XML block with a full path per skill; a path appears only when a skill's directory differs from its name. A workspace with 68 skills drops from about 31,000 to 22,000 characters of prompt per turn with the same names and descriptions.
242
+ ## [0.4.5] - 2026-06-17
166
243
 
167
- ## [1.0.0-beta.83]
244
+ ### Added
168
245
 
169
- ### Fixed
246
+ - Rotate shared top-level channel sessions on biweekly Sunday boundaries while keeping thread sessions fixed.
170
247
 
171
- - Stop copying each mikan reply back into the session a second time: chat history sync compared the posted reply, which carries the `_Triggered by …_` signature, against the model's unsigned text, missed the match, and appended the signed copy. Context held every answer twice and taught the model to keep writing the signature. Imported bot messages are now compared and stored without the signature, and a posted reply that opens with the tool checklist is matched to the model's answer it ends with.
248
+ ### Changed
172
249
 
173
- ## [1.0.0-beta.82]
250
+ - Bootstrap rotated shared channel sessions from the recent two-week chat log window and prevent older log history from being resynced into the active session.
251
+ - Harden managed Docker sandboxes with dropped capabilities, no-new-privileges, and a PID limit.
174
252
 
175
- ### Changed
253
+ ### Fixed
176
254
 
177
- - mikan reacts `saluting_face` (eyes on GitHub) itself when a run starts its first work tool, instead of the model spending a separate round on the reaction; the model's `react` tool is left for background checks with nothing to report.
178
- - mikan owns the `_Triggered by …_` signature on chat responses and replaces any signature line the model wrote, so user messages no longer carry a per-turn attribution instruction. The model is still asked to sign GitHub text it writes itself.
179
- - The model reads the current time from each message's send time instead of running `date`.
255
+ - Report usage summaries when token usage is available even if provider pricing data is missing.
180
256
 
181
- ## [1.0.0-beta.81]
257
+ ### Tests
182
258
 
183
- ### Added
259
+ - Add coverage for session rotation, thread bootstrap watermarks, sandbox hardening flags, and usage summaries without cost data.
184
260
 
185
- - Stream every run of a session live in Session View: a run started from Slack or another chat platform now appears on an open page as it happens (user message, tool results, the streaming answer), then the timeline reloads. Page-sent messages use the same stream; thinking text and errors appear after the timeline reloads.
186
- - Guard tool loops: repeating the same tool call with identical arguments earns a notice from the third call, is blocked from the fifth, and stops the run at the tenth; short repeating cycles of calls also earn a notice.
187
- - Compact a session in the background after a successful run when its context nears the compaction threshold, so the next message does not wait for compaction.
261
+ ## [0.4.4] - 2026-06-12
188
262
 
189
263
  ### Fixed
190
264
 
191
- - Undo Slack's HTML escaping on incoming text: the model and the office log saw `&amp;&amp;`, `&lt;`, and `&gt;` where the user typed `&&`, `<`, and `>`.
192
- - Keep the tool checklist visible while the final answer streams; it used to disappear until the answer finished.
193
- - Stop an open Session View page from holding shutdown open; open live streams now close after a five-second grace, so a restart no longer waits for the process manager's kill timeout.
194
- - Report a GitHub API request that returns an empty body where a resource is required with its method, path, and status, instead of failing later on a null value.
265
+ - Require exact provider model ID matches when grouping verified admin model availability.
195
266
 
196
- ### Security
267
+ ## [0.4.3] - 2026-06-12
268
+
269
+ ### Added
197
270
 
198
- - **Breaking (deploy):** The link server (Admin, Session View, and credential links) now listens on `127.0.0.1` even when `LINK_URL` is set; it used to listen on every interface, so portal tokens could travel in plain HTTP straight to `LINK_PORT` around the TLS reverse proxy. A reverse proxy on the same host (`reverse_proxy 127.0.0.1:8181`) keeps working unchanged. Set the new `LINK_HOST` (for example `0.0.0.0`) when the proxy runs on another host or in a separate network namespace.
271
+ - Group admin model selectors by verified availability for OpenAI and Anthropic keys.
272
+ - Log the active provider and model when each agent run starts to simplify server-side debugging.
199
273
 
200
- ## [1.0.0-beta.80]
274
+ ## [0.4.2] - 2026-06-11
201
275
 
202
276
  ### Fixed
203
277
 
204
- - Post no Slack usage summary for a `[SILENT]` response: the reply and its thread were deleted, so the summary for a quiet recurring event landed at the top level of the channel on every run.
205
- - Stop warning `Could not remove snapshot image mikan-migrate:...` for every migrated container on each startup; the startup sweep now leaves a snapshot alone while its container still runs from it, and still reclaims snapshots no container uses.
278
+ - Resolve custom providers through pi's model registry so conversation settings can select models from `models.json`.
279
+ - Resolve attached file paths from the sandbox runtime workspace so image sandboxes upload generated files from the correct host path.
206
280
 
207
- ## [1.0.0-beta.79]
281
+ ## [0.4.1] - 2026-06-08
208
282
 
209
283
  ### Changed
210
284
 
211
- - Load the Discord adapter and `discord.js` only when Discord is active, saving about 38 MB of memory and 90 ms of startup in processes that do not run Discord.
212
- - Use pi's `typebox` 1.3.27 for tool and settings schemas instead of the incompatible `@sinclair/typebox` 0.34; platform tool packs now share pi's `AgentTool` schema types. Schema validation errors retain field paths but use typebox 1's wording.
213
- - **Breaking (SDK):** `new ChatHistorySync()` now requires `{ isCommandText }`, so sessions no longer import the command inventory from the adapters. Pass the newly exported `isCommandText` to keep filtering command messages out of synced history.
214
-
215
- ### Security
216
-
217
- - Only send the Slack bot token to `https://*.slack.com` file URLs, and stream incoming attachments to disk with a 100 MiB limit instead of buffering whole files in memory; a download over the limit is rejected, not retried, and leaves no partial file.
285
+ - Update bundled pi packages to the 0.78.1 line.
218
286
 
219
287
  ### Fixed
220
288
 
221
- - Reject missing sandbox helper executables as ordinary `ENOENT` errors instead of emitting an unhandled child-process error.
222
- - Accept `thinking: max` in subagent profiles; they kept their own level list without `max`, while settings and `/pi-model` accepted it.
223
- - Spill oversized MCP JSON results as indented JSON so `read` and `grep` can inspect them; the compact single-line spill exceeded `read`'s per-line limit.
224
- - Record a Discord channel without a name (such as a DM) under its channel id instead of a `null` name.
289
+ - Stream Slack responses with delta-only appends to avoid duplicated message segments and streaming state conflicts.
290
+ - Include Slack streaming recipient metadata so threaded streamed replies work in Slack E2E and production workspaces.
225
291
 
226
292
  ### Tests
227
293
 
228
- - Type-check tests, E2E code, and the embedder example in pre-commit and CI, and remove every `any` and double assertion from tests.
229
- - Run tests in random order and print the seed, so order-dependent tests fail visibly and can be reproduced.
294
+ - Add Slack streaming E2E coverage for delta appends without duplicate text.
230
295
 
231
- ## [1.0.0-beta.78]
296
+ ## [0.4.0] - 2026-06-07
232
297
 
233
298
  ### Added
234
299
 
235
- - Capture durable knowledge after each settled human run: Jev gates the exchange, and the conversation's model adds or updates stamped lines under `## Captured knowledge` in the conversation `MEMORY.md`; configured secrets are redacted from captured entries (ADR 0011).
236
- - Give each new managed image container a per-office home volume (`mikan-home-<key>`) at `/root`. A stopped container whose image or mounts are stale is recreated from the current image with the same volume, so `/root` survives image upgrades; running containers are never interrupted (ADR 0009).
237
- - Add `mikan sandbox status|diff|migrate` to inspect managed containers and move legacy containers onto a home volume with the daemon stopped.
300
+ - Add streamed response deltas across adapters so replies can update progressively.
301
+ - Add Slack reply mode configuration in the admin portal.
302
+ - Add event tool CRUD support for listing, reading, updating, and deleting scheduled events, with conversation-scoped listing by default and explicit all-event listing.
238
303
 
239
304
  ### Changed
240
305
 
241
- - Bound MCP tool results like `bash`: JSON is re-serialized compactly, oversized results become a structural digest (keys, counts, and pagination kept) within Pi's 50KB/2000-line limit, and the full result is spilled to `.mikan/mcp-output/` in the runtime workspace. `structuredContent` is used when `content` is empty, binary resources are no longer inlined, error text is bounded, and MCP results pass through secret redaction.
242
- - Shared top-level channel sessions no longer rotate every two weeks; they stay current until `/new`, and Pi's automatic compaction bounds the model context (ADR 0010).
243
- - The sandbox image installs its runtime outside `/root` and is published only with mikan releases.
244
- - Document the Vault as the store for development credentials that sandbox programs read directly; OpenConnector is the path for third-party service access (ADR 0013).
306
+ - Reorganize source modules and centralize shared type definitions for clearer contributor navigation.
307
+ - Centralize adapter conversation intake and reduce wrapper indirection across runtime, adapters, commands, config, and web modules.
308
+ - Attribute agent Sentry traces with platform and conversation context for clearer operator debugging.
245
309
 
246
- ### Removed
310
+ ### Fixed
247
311
 
248
- - Remove scheduled Dream memory maintenance. Conversation `MEMORY.md` is written only by the agent and by post-run memory capture; existing `dream.json` checkpoints are no longer read (ADR 0012).
312
+ - Persist global settings overrides correctly.
313
+ - Warn when invalid custom OAuth service definitions are skipped instead of silently dropping them.
249
314
 
250
- ## [1.0.0-beta.77]
315
+ ## [0.4.0-beta.0]
251
316
 
252
317
  ### Added
253
318
 
254
- - Provision the standard sandbox image with Node.js 24, Chromium, ffmpeg, pinned `agent-browser` 0.38.1, and a checksummed Google Workspace CLI so `jev_browser` and capture workflows work without runtime installation and current-page recording preserves hydrated browser state.
319
+ - Add streamed response deltas across adapters so replies can update progressively.
320
+ - Add Slack reply mode configuration in the admin portal.
321
+ - Add event tool CRUD support for listing, reading, updating, and deleting scheduled events, with conversation-scoped listing by default and explicit all-event listing.
255
322
 
256
323
  ### Changed
257
324
 
258
- - Run every `jev_browser` command through the conversation-authorized sandbox executor, preserve native snapshots, refs, frames, tabs, screenshots, HAR, and recording, serialize calls per runner, and make named-session continuity and close-only operations explicit.
259
- - Bound autonomous browser failures and repeated action cycles, refresh current page evidence before reporting completion, and refuse to silently resurrect an explicitly closed named session as `about:blank`.
260
- - Delegate persisted session behavior to public Pi session and harness APIs instead of maintaining duplicate storage semantics.
325
+ - Reorganize source modules and centralize shared type definitions for clearer contributor navigation.
326
+ - Centralize adapter conversation intake and reduce wrapper indirection across runtime, adapters, commands, config, and web modules.
261
327
 
262
328
  ### Fixed
263
329
 
264
- - Log LLM cancellation reasons and Pi run ids only while provider transport is active, avoiding false abort logs during authentication, payload hooks, retry waits, tool execution, or after structural requests finish.
265
-
266
- ### Security
267
-
268
- - Harden state and credential ownership by preserving explicit vault mount targets outside secret directories, rejecting migration collisions, keeping private file writes atomic, and deriving session operations from authorized conversation identities.
330
+ - Persist global settings overrides correctly.
269
331
 
270
- ## [1.0.0-beta.76]
332
+ ## [0.3.2] - 2026-06-02
271
333
 
272
- ### Changed
334
+ ### Fixed
273
335
 
274
- - Update `@earendil-works/pi-agent-core` and `@earendil-works/pi-ai` to 0.87.0, including their aligned telemetry and harness dependencies.
336
+ - Preserve trigger attribution in streamed agent responses so tool-written GitHub comments include the triggering user.
275
337
 
276
- ## [1.0.0-beta.75]
338
+ ## [0.3.1] - 2026-06-02
277
339
 
278
340
  ### Added
279
341
 
280
- - `jev_browser` agent tool: drives a real Chrome browser toward a natural-language goal, deciding each step (click, type, select, scroll, wait) itself using a Jev decision per step against ref-indexed accessibility snapshots — the same architecture as [`browser-use/jev-ultrafast`](https://github.com/browser-use/jev-ultrafast). A `commands` mode forwards raw [`agent-browser`](https://github.com/vercel-labs/agent-browser) CLI argument arrays directly, covering screenshot, video recording, HAR capture, cookies, and any other agent-browser capability beyond the click/type/select loop. A named `session` spans multiple calls against the same browser (start a recording, run a goal, stop the recording, screenshot the result) and stays open by default; every result reports `browserContinuity` in plain language so a caller can tell whether the browser it just used was actually the same one a prior call left open. Tool progress lines are prefixed `jev_browser ·`, matching the existing `jev ·` treatment. Requires the `agent-browser` CLI installed on the host (not a mikan dependency); host sandbox only.
281
- - Jev decision cost (from the `jev` tool, `jev_browser`'s decision loop, Slack auto-reply gating, and task-intent classification) is now reported to Sentry/OpenTelemetry as `agent.jev.cost`, `agent.jev.duration`, and `agent.jev.calls`, tagged by which feature made the call. Previously this spend was invisible next to the primary chat model's per-run cost — it only ever appeared inside a tool call's raw JSON text.
282
-
283
- ### Changed
342
+ - Add Slack Block Kit response support and document Block Kit implementation lessons.
284
343
 
285
- - Every agent tool now requires the `label` parameter the system prompt already promises for every tool call, so its progress line always shows a real description instead of silently falling back to the raw tool name.
344
+ ### Fixed
286
345
 
287
- ## [1.0.0-beta.74]
346
+ - Require explicit mentions before Slack thread replies trigger the bot.
288
347
 
289
- ### Security
348
+ ### Tests
290
349
 
291
- - Host sandbox tool output (bash, read, and every other agent tool) is now scrubbed of any configured secret env var's value before it reaches the model or the durable session transcript. Host sandbox mode does not isolate environment variables, so a command like `echo $OPENROUTER_API_KEY` previously returned the key in plain text with no defense beyond the model choosing not to repeat it; it is now replaced with a `[SECRET:VAR_NAME]` placeholder using mikan's existing secret env var inventory.
350
+ - Enforce phase-one strict checks and unused export checks.
292
351
 
293
- ### Fixed
352
+ ## [0.3.0] - 2026-06-01
294
353
 
295
- - Stop and shutdown-restart notices ("Stopping…", "Stopped.", the restart notice) are now recorded in the conversation's `log.jsonl`, matching every other agent reply. Previously these control messages reached the platform but left no trace in the human-readable history the agent (and operators) grep, so a stopped run looked, on later review, like it had never been interrupted.
354
+ ### Added
296
355
 
297
- ## [1.0.0-beta.73]
356
+ - Add source directory README guides for contributors navigating adapters, commands, runtime, sessions, sandbox, tools, login, admin, and session-view code.
298
357
 
299
358
  ### Changed
300
359
 
301
- - Admin: redesigned the page around a persistent icon sidebar and a single active settings pane (Claude/ChatGPT settings-app style), replacing the pill-tab-plus-accordion layout. Conversation and workspace scope each get their own rail; every pane shares one quiet header (title, one-line description, actions) instead of a stack of bordered cards. Widened the page from 960px to 1180px so the sidebar-plus-pane layout has room to breathe.
302
-
303
- ## [1.0.0-beta.72]
360
+ - Centralize chat session bootstrapping through `ChatSessionManager` so Slack top-level and thread sessions share the same log-based history sync path.
361
+ - Rename Slack branch/fork terminology to thread/anchor terminology across the adapter, session viewer, and documentation.
362
+ - Model session-view related sessions as parent/thread relationships, including fixed-path thread sessions without legacy parent metadata.
363
+ - Remove legacy thread fork and snapshot helpers from session storage.
304
364
 
305
- ### Added
365
+ ### Fixed
306
366
 
307
- - Admin: the Skills panel (conversation and global) can now create, edit, and delete skills directly, not just list and preview them. Saving writes `SKILL.md` straight into the workspace skills tree the harness loader reads, so a new or edited skill is available on the conversation's next turn.
367
+ - Anchor session-view thread links on the root turn instead of earlier bootstrapped context messages.
308
368
 
309
- ## [1.0.0-beta.71]
369
+ ## [0.3.0-beta.0]
310
370
 
311
371
  ### Changed
312
372
 
313
- - Built-in subagents now use the full 100-turn / $10 allowance, and the model-facing `subagent` tool can only request a larger token allowance instead of accidentally shrinking turn, cost, or duration budgets (for example, to $0.30).
373
+ - Centralize chat session bootstrapping through `ChatSessionManager` so Slack top-level and thread sessions share the same log-based history sync path.
374
+ - Rename Slack branch/fork terminology to thread/anchor terminology across the adapter, session viewer, and documentation.
375
+ - Model session-view related sessions as parent/thread relationships, including fixed-path thread sessions without legacy parent metadata.
376
+ - Remove legacy thread fork and snapshot helpers from session storage.
314
377
 
315
378
  ### Fixed
316
379
 
317
- - Shared-memory guidance now keeps personal, project-specific, and tool-specific knowledge in its proper scope, prevents memory from overriding system mechanisms, and removes the obsolete shared `SYSTEM.md` environment log.
318
- - Console usage summaries now show cache-read tokens alongside fresh input tokens.
319
- - Sandbox provisioning no longer logs `Container … already running` on every readiness check; creation, restart, drift, and failure messages remain visible.
380
+ - Anchor session-view thread links on the root turn instead of earlier bootstrapped context messages.
320
381
 
321
- ## [1.0.0-beta.70]
382
+ ## [0.2.4] - 2026-06-01
322
383
 
323
384
  ### Fixed
324
385
 
325
- - Sandbox: a container migrated to the office-key mount layout (or recreated after its mount configuration drifted) no longer re-migrates on every subsequent restart. The one-time bridging snapshot image is now removed once the new container is confirmed up, instead of being kept forever on the mistaken assumption that the container would eventually run from the base image again. In production this had pinned dozens of containers to increasingly stale snapshots and left their images unreclaimed, consuming disk space on every restart.
326
-
327
- ## [1.0.0-beta.69]
328
-
329
- ### Changed
330
-
331
- - `harness/jev.ts` is now backed by [`@geminixiang/jev`](https://github.com/geminixiang/jev), a standalone SDK shaped like pi-ai (providers own auth, a model catalog, and a wire implementation) instead of a hand-rolled OpenRouter fetch client. `evaluateWithJev`'s signature, types, and error classes are unchanged, so the auto-reply gate, DM task-intent classification, and the `jev` tool are unaffected. The swap adds request retries and timeouts, neither of which existed before, and a path to other Jev backends (TypeSafe, Vercel AI Gateway, Cloudflare Workers AI) without touching call sites.
386
+ - Make Slack bot-rooted thread session seeds loadable by storing platform-history assistant metadata.
332
387
 
333
- ## [1.0.0-beta.68]
388
+ ## [0.2.3] - 2026-06-01
334
389
 
335
390
  ### Added
336
391
 
337
- - `jev` agent tool: the model can now call Jev directly with a `state` (text or JSON) and any number of boolean / choice / score `questions`, mirroring the decisions API one-to-one — structured instructions and criteria, per-option probabilities, confidence, and score legends all pass through. Available to the main agent and to the `worker`, `software-engineer`, `data-scientist`, and `summarizer` subagent profiles. A missing `OPENROUTER_API_KEY` is reported as a tool error so the model judges for itself.
338
- - Slack: DM messages in a task thread (and top-level DMs while a task is running) are classified by Jev as `status`, `steer`, or `request` before spending a model turn. Status questions are answered from recorded task state; steering is delivered into the running task; anything else starts a normal run. The regex status matcher remains as the fallback.
339
- - `task_status` reports `queued` for tasks that were admitted but have not started executing yet.
392
+ - Add a sandbox resource limit tool for checking and temporarily updating managed sandbox CPU and memory limits.
340
393
 
341
- ### Changed
394
+ ### Fixed
342
395
 
343
- - `harness/jev.ts` accepts structured JSON for state, instructions, and criteria, and returns `confidence` and `legend` on choice / score answers.
344
- - Jev auto-reply and task-intent state renders `<@U…>` mentions as `@Name` (the bot as `@mikan`) so Jev can tell a message addressed to someone else from one addressed to mikan.
345
- - Tool progress lines for `jev` calls are prefixed with `jev ·` so users can see which steps came from a calibrated judgment.
396
+ - Isolate Slack sessions rooted at bot messages so thread replies do not inherit unrelated channel history.
346
397
 
347
- ## [1.0.0-beta.67]
398
+ ## [0.2.2] - 2026-05-30
348
399
 
349
- ### Changed
350
-
351
- - Slack: unaddressed thread replies in shared channels now pass through the same `/pi-auto-reply` gate as top-level messages instead of being dropped unconditionally. In `jev` mode, Jev scores the message together with its surrounding scope (the channel's recent top-level messages, or the thread's messages plus whether mikan has already replied there), so bare follow-ups like "then roll it back" are judged in context. `off` still requires a mention; `on` now admits thread replies too.
352
- - Deploy docs: `/pi-auto-reply` slash command description lists `on | off | jev`.
400
+ ### Added
353
401
 
354
- ## [1.0.0-beta.66]
402
+ - Add `/admin` portal with token-protected access via `/admin` and `/pi-admin` commands.
403
+ - Add admin APIs and UI for conversation settings, global settings, workspace preview, skills, events, session links, and login/vault links.
404
+ - Add model selection in the admin portal using `ModelRegistry.getAvailable()` instead of free-text fields.
405
+ - Share portal shell chrome across admin, session-view, and login/vault pages.
406
+ - Document admin, login, and session token boundaries in `docs/portal-auth-model.md`.
355
407
 
356
- ### Added
408
+ ### Changed
357
409
 
358
- - `/pi-auto-reply` gains a third state, `jev`: alongside manual `on`/`off`, a Slack channel can now delegate the "does this unaddressed message address mikan" decision to Jev (`typesafe/jev`), a fast typed-decision model, on a per-message basis. Any evaluation failure (including a missing `OPENROUTER_API_KEY`) fails closed to "not addressed" so a misconfiguration cannot make the bot noisy in a shared channel.
359
- - `harness/jev.ts`: a standalone `evaluateWithJev` client for Jev, reached through OpenRouter's `/api/alpha/decisions` REST API using the same `OPENROUTER_API_KEY` pi-ai's `openrouter` chat provider reads. Jev returns typed decisions (boolean probability, choice, score) instead of generated text, so it is a plain function call sites use directly rather than a selectable chat provider in `models.ts`'s catalog.
360
- - Jev-mode auto-reply decisions (channel, probability, addressed, truncated message text) are logged at info level for observability.
410
+ - Normalize slash-command feedback into muted compact summaries.
411
+ - Align desktop layout widths across all portal surfaces.
361
412
 
362
- ## [1.0.0-beta.65]
413
+ ## [0.2.1] - 2026-05-27
363
414
 
364
415
  ### Added
365
416
 
366
- - Slack: when a run resolves to exactly one completed subagent profile with a known persona, the final answer posts as a fresh message under that profile's own username/icon (`Data Scientist`, `Software Engineer`, `DevOps Engineer`, `Account Manager`, `Business Development`, `Creative Producer`, `Ad Operations Specialist`) instead of mikan's own identity. Mixed-profile or partially-failed runs keep mikan's identity, since `chat.update`/`chat.appendStream` cannot carry a Slack identity and there is no single "who answered this" to attribute.
367
- - The `react` tool (add an emoji reaction to the triggering message) is now documented in the system prompt with two unconditional triggers tied to `start_task`'s existing bar: react before starting any multi-step investigation, change/test, or long wait, and react instead of writing "nothing to report" on a periodic/background check with nothing to report.
368
- - Discord and Telegram now wire the `react` tool into their responders (previously Slack/GitHub-only despite the tool being granted everywhere); a shared short-name-to-Unicode translation covers what the prompt recommends for platforms whose reaction API takes a Unicode character rather than a name.
369
- - `creative-producer` subagent profile gains the `generate_image` tool grant, matching its image-deliverable description.
417
+ - Add expanded command, configuration, deployment, development, session, and skill documentation.
418
+ - Add README hero and architecture diagrams.
419
+ - Add project agent development rules and Karpathy coding guidelines.
370
420
 
371
421
  ### Changed
372
422
 
373
- - Built-in subagent profile `maxTokens` raised from 100,000 to 1,000,000: the old cap was a common budget-exceeded trip for ordinary investigative tasks (e.g. a repo-wide architecture review), not just runaway loops.
374
- - The `analysis-only` subagent profile is renamed `summarizer`: it is a DAG synthesis node over upstream dependency output, not a mid-task advisor.
375
- - Office data policy for non-Slack platforms is now an explicit rule (ADR 0008): only Slack conversations can be public, and Telegram/Discord/GitHub offices always resolve to private rather than falling through an "unknown" branch by omission.
376
- - The Admin office visibility card now states the effective outcome in plain words instead of the internal policy model; public Slack channels get one "Hide the files in this channel from other offices" checkbox, other conversation kinds show the fixed Hidden state with no control.
377
- - `settings.json` ownership (schema, scope merge, readers, writers, one-time migrations) is gathered under `src/settings/`.
423
+ - Simplify the README overview and clarify sandbox runtime architecture documentation.
424
+ - Simplify file guards and retry helpers.
378
425
 
379
- ### Docs and maintenance
426
+ ### Fixed
380
427
 
381
- - Describe mikan as an organization-wide, per-conversation-isolated agent.
382
- - Move the three remaining top-level source files into their owning modules (`adapters/messages.ts`, `adapters/index.ts`, `cli/process-lifecycle.ts`); pure move, no behavior change.
428
+ - Retry attachment downloads.
429
+ - Skip retry sleep on the final attempt and clarify retry naming.
383
430
 
384
- ## [1.0.0-beta.64]
431
+ ## [0.2.0] - 2026-05-23
385
432
 
386
433
  ### Changed
387
434
 
388
- - The retired door-policy keys (`sandbox.image.workspaceMount`, `sandbox.workspace`) are dropped at load time and no longer appear in the resolved sandbox settings or the Admin office view.
435
+ - Renamed the project, CLI, npm package, GitHub repository, documentation, release skill, and sandbox image references to mikan.
436
+ - Changed platform credentials to unprefixed env vars (`SLACK_APP_TOKEN`, `SLACK_BOT_TOKEN`, `TELEGRAM_BOT_TOKEN`, `DISCORD_BOT_TOKEN`) while keeping `MIKAN_*` aliases as fallbacks.
437
+ - Changed runtime env vars such as `LINK_URL`, `LINK_PORT`, `STATE_DIR`, OAuth scope overrides, and Cloudflare sandbox settings to prefer unprefixed names with `MIKAN_*` fallbacks.
438
+ - Raised the minimum supported Node.js version to `>=22.19.0`.
439
+ - Updated internal variable, function, type, Docker label, sandbox image, and generated resource names to use mikan naming.
440
+ - Added manual dispatch support to the CI workflow.
389
441
 
390
- ### Added
391
-
392
- - `mikan office migrate-door-policy` removes the retired keys from the global and every registered office settings file, preserving all other settings and leaving files without them untouched. Only an explicit shared-support `private` visibility is carried into `office.visibility`; `full`, `isolated`, and legacy `private` are removed without deriving any grant.
393
-
394
- ## [1.0.0-beta.63]
442
+ ## [0.2.0-beta.25] - 2026-05-23
395
443
 
396
444
  ### Changed
397
445
 
398
- - Office data policy is now a single **visibility** derived from the Slack conversation type (ADR 0008): public channels are public offices; private channels, DMs, group DMs, externally shared channels, and unknown kinds are private. Every office receives the same projection — its own directory read-write, every other public office read-only under `/workspace/public/<office key>`, and shared `MEMORY.md`/`skills/` read-write for public offices or read-only for private ones. Nothing mounts the workspace root.
399
- - The five-way door policy (`isolated`, `trusted/shared-support`, `trusted/full`, …) is retired. Legacy settings still parse but no longer change the projection; offices that still declare `full` are reported once per process. The Admin "door policy" control and `/pi-sandbox door` are replaced by one switch that can narrow a public channel to private (`/pi-sandbox visibility <private|default>`); nothing can widen beyond what Slack allows.
400
- - Backends without a managed projection (`host`, `container:*`, `cloudflare:*`) now serve private offices with a one-time logged warning instead of refusing, since they are trusted deployments by definition.
446
+ - Grouped session modules under a single directory.
447
+ - Centralized command parsing across adapters.
448
+ - Removed explicit `any` usage across the type surface.
449
+ - Cleaned unused dependencies.
401
450
 
402
- ### Added
451
+ ### Tests
403
452
 
404
- - The Slack adapter records channel kinds for every registered office from the channel list loaded at startup, so offices created before kinds were recorded keep their public status without waiting for a new message.
453
+ - CI now enforces coverage thresholds.
454
+
455
+ ## [0.2.0-beta.24]
405
456
 
406
457
  ### Fixed
407
458
 
408
- - Recreating a sandbox container after a visibility change removes empty `/workspace/public/<key>` mountpoints that `docker commit` carried over from the previous mount set.
459
+ - Session history writes now emit valid assistant messages.
409
460
 
410
- ## [1.0.0-beta.62]
461
+ ## [0.2.0-beta.23]
411
462
 
412
- ### Changed
463
+ ### Fixed
413
464
 
414
- - Scheduled events now live in host-only per-office state (`<state dir>/conversations/<office key>/events/`) and are never mounted into a sandbox. The `event` tool and the Admin portal are the only writers, both confined to the current office; `create` never overwrites, deleting a record cancels its timer or cron immediately, and the Slack App Home lists only the opener's DM office schedules. The filesystem watcher is gone: hand-edited records take effect on the next start.
415
- - OpenConnector is an ordinary MCP server with a deployment default. When a Slack conversation has not declared `open-connector`, mikan mints that conversation's runtime token with `OPENCONNECTOR_ADMIN_TOKEN` and saves a normal `mcpServers` entry in its settings; conversations may override it with a self-hosted server or disable it like any other MCP entry. The loader no longer fills `connectionName`; connection selection belongs to OpenConnector.
465
+ - Refresh stale channel history before forking a thread.
466
+ - Separate history seeds from live sessions to prevent cross-contamination.
467
+ - Materialize channel history when the first thread is created.
416
468
 
417
469
  ### Added
418
470
 
419
- - `mikan office migrate-events` moves legacy `<workspace>/events/*.json` records into the owning office's state and reports records it cannot attribute.
420
- - `mikan office migrate-openconnector` converts legacy `open-connector-runtime-token.json` files into conversation MCP entries.
471
+ - Scripts to migrate session history and repair orphan thread sessions.
472
+
473
+ ## [0.2.0-beta.22]
421
474
 
422
475
  ### Fixed
423
476
 
424
- - The agent `event` tool can no longer list, read, update, or delete another office's events, and `scope=all` is rejected.
477
+ - Slack: fork bot response threads from the channel session so replies inherit context.
478
+ - Vault: preserve failures when the default shared vault cannot be applied.
425
479
 
426
- ### Docs and maintenance
480
+ ## [0.2.0-beta.21]
427
481
 
428
- - Redraw the architecture diagram as a single rounded page and refresh the README image.
429
- - Support local Slack E2E runs, capture intake and session markers on failure, and schedule E2E events through the `event` tool instead of writing files.
430
- - Record the Office isolation policy, storage inventory, and OpenConnector history audit under `docs/`.
482
+ ### Added
483
+
484
+ - Vault: seed new sandboxes from a shared profile (`sandbox.defaultSharedVault`).
431
485
 
432
- ## [1.0.0-beta.61]
486
+ ## [0.2.0-beta.20]
433
487
 
434
488
  ### Added
435
489
 
436
- - Ground Slack DM progress replies in runtime/v4 task observations; common task-thread status queries no longer steer work, and ordinary followups do not repeat completion mentions.
437
- - Slack DM task handoff: independent task threads keep the main conversation free, with text steering in active task threads and continuation after stopping.
490
+ - Sentry: report user-facing failures.
491
+ - Auto-reply: surface configured rules in the status command.
438
492
 
439
493
  ### Fixed
440
494
 
441
- - Keep thread stop acknowledgements in the source thread, including shared-channel unmentioned stop controls.
442
- - Notify Slack DM task requesters with a fresh in-thread mention after normal completion.
443
- - Finalize stop acknowledgements that arrive after the cancelled run has already settled.
444
- - Propagate final response delivery failures so rejected updates do not trigger completion notifications.
445
- - Honor stop during runner preparation and keep older active tasks visible in status queries.
446
- - Report task admission, asynchronous startup, and status inspection failures through the existing Sentry/OTLP observability path.
495
+ - Slack: anchor event-fork sessions correctly (#61).
496
+ - Slack: keep session ephemerals scoped to threads.
497
+ - Agent: require history search before answering unknown replies.
498
+ - Agent: keep quiet tool errors out of chat.
447
499
 
448
500
  ### Changed
449
501
 
450
- - Publish the already built and verified npm package without rerunning build and repository setup lifecycle scripts.
451
- - Keep the documented and CI coverage commands as stable entry points while maintaining their shared Vitest invocation in one place.
452
- - Validate debug Session View selections from their path and header, leaving full parsing to consumers that load session content instead of inspecting the same file twice.
502
+ - Removed cloud-logging config — log to stdout/stderr and route via your process manager.
453
503
 
454
- ## [1.0.0-beta.60]
504
+ ## [0.2.0-beta.19]
455
505
 
456
506
  ### Fixed
457
507
 
458
- - Separate CJK-adjacent bold dollar amounts for Slack's Markdown parser while preserving code and link destinations.
459
- - Validate Session View selections through read-only inspection so active and repeatedly selected historical sessions do not conflict with writer ownership or appear corrupted.
508
+ - Sandbox: bootstrap `gh` git credentials inside managed containers.
460
509
 
461
- ## [1.0.0-beta.59]
510
+ ## [0.2.0-beta.18]
462
511
 
463
512
  ### Fixed
464
513
 
465
- - Keep Slack's working indicator in its own paragraph so progressive heading and table updates can replace existing rich-text messages without `block_mismatch`.
466
- - Pace failed progressive redraws as well as successful ones, retaining accumulated text for recovery instead of retrying on every delta.
467
-
468
- ### Changed
469
-
470
- - Use Commander for CLI option parsing, subcommand validation, and generated help.
471
- - Guide interactive onboarding with arrow-key selections, masked credentials, and a final confirmation before saving. Cancel without writing settings.
472
- - Refuse custom-provider onboarding when models.json already exists, without printing credentials or writing partial settings.
514
+ - Sandbox: update memory swap when applying CPU/memory limits.
515
+ - Slack: preserve long replies posted in threads.
473
516
 
474
- ## [1.0.0-beta.58]
517
+ ## [0.2.0-beta.17]
475
518
 
476
519
  ### Added
477
520
 
478
- - Restore Slack `/pi-auto-reply on|off` with the original per-conversation marker files, without judge models or rules.
479
- - Expose the admin portal command on Discord and Telegram.
521
+ - Sentry: store env values and write a `sentry-cli` config for richer error reports.
480
522
 
481
523
  ### Changed
482
524
 
483
- - Collapse conversation sections in the Admin portal, load their data only when opened, remember their open state, and open Vault and Session View links in new tabs.
525
+ - Bumped `@earendil-works/pi-*` packages.
484
526
 
485
- ## [1.0.0-beta.57]
527
+ ## [0.2.0-beta.16]
486
528
 
487
- ### Changed
488
-
489
- - Export raw platform conversation, channel, session, thread, message, and user identifiers so Sentry traces can be mapped directly back to their source while continuing to exclude human-readable names and conversation or tool content.
490
-
491
- ### Removed
529
+ ### Performance
492
530
 
493
- - Remove telemetry identifier hashing and the `TELEMETRY_HASH_KEY` deployment setting.
531
+ - Slack: unblock startup while backfill is running.
494
532
 
495
- ## [1.0.0-beta.56]
533
+ ## [0.2.0-beta.15]
496
534
 
497
535
  ### Added
498
536
 
499
- - Add content-free agent diagnostics for actual model IDs, token and cost totals, first-token latency, context utilization, message and attachment counts, payload sizes, tool categories and status, and retry, compaction, and budget summaries.
537
+ - Config: validate JSON files with TypeBox schemas.
538
+ - Agent: attribute the trigger (mention/direct/auto-reply/…) in responses.
500
539
 
501
- ### Security
540
+ ## [0.2.0-beta.14]
502
541
 
503
- - Replace raw conversation, session, message, thread, and user telemetry identifiers with stable opaque values, support deployment-specific HMACs through `TELEMETRY_HASH_KEY`, and stop sending usernames to Sentry.
542
+ ### Fixed
504
543
 
505
- ## [1.0.0-beta.55]
544
+ - Login: refresh the sandbox after copying a shared profile.
506
545
 
507
- ### Added
546
+ ### Changed
508
547
 
509
- - Export explicitly configured, content-free traces and metrics over standard OTLP HTTP/protobuf, including GenAI and OpenInference attribution for Arize Phoenix. Sentry remains available for sanitized issues and legacy metric fallback without duplicate spans; zero configuration remains network-free.
510
- - Add a guided Admin dialog for configuring MCP servers, with structured fields or pasted standard `mcpServers` JSON and card-based installed-server management.
548
+ - Simplified command dispatch, token stores, and re-exports (#60).
511
549
 
512
- ### Changed
550
+ ## [0.2.0-beta.13]
513
551
 
514
- - Delegate the agent run loop, retries, compaction, persistence, cancellation, and the native `read`, `write`, `edit`, and `bash` tools to Pi's `AgentHarness` and execution-tool implementations. mikan retains budgets, platform presentation, authorization, and sandbox-backed execution routing.
515
- - Upgrade `pi-agent-core` and `pi-ai` to 0.85.1, including GPT-6 Astra catalog entries and the 30-minute prompt-cache TTL for GPT-5.6+ Responses models.
516
- - Consolidate harness, office, session, sandbox, web-adapter, and shared-command ownership without changing the published root exports.
552
+ ### Added
517
553
 
518
- ### Removed
554
+ - Login: gcloud OAuth support.
519
555
 
520
- - Remove managed skill packages and their Admin/package materialization surfaces. Workspace and conversation skills remain supported.
521
- - Remove the auto-reply judge, command, configuration, and UI; explicit platform triggers remain supported.
522
- - Remove the unused `/api/agent-events/stream` SSE mirror, its token setting, and supporting event types. The authenticated session viewer continues to use `/session/stream`.
556
+ ## [0.2.0-beta.12]
523
557
 
524
558
  ### Fixed
525
559
 
526
- - Preserve Pi's native optional tool schemas, require an explicit authorized execution environment for native file/shell tools, and keep container working directories inside the guest instead of applying them to the host Docker process.
560
+ - Auto-reply: persist the resolved session key.
527
561
 
528
- ## [1.0.0-beta.54]
562
+ ## [0.2.0-beta.11]
529
563
 
530
- ### Changed
531
-
532
- - Admin portal: MCP servers are added by pasting the server's standard `mcpServers` JSON (Claude Desktop / Cursor shape), stored as-is; the old name / target / `KEY=value` form is gone. Every add and preset install is followed by a real connection check, and the response shows the tool count or the server's own error; a per-server **Test** button re-checks an installed entry. Query-string values in listed URLs are redacted. stdio entries now run their command on the host at save time.
564
+ ### Fixed
533
565
 
534
- ## [1.0.0-beta.53]
566
+ - Login: make Slack login ephemeral and refresh vault mounts after credentials change.
535
567
 
536
568
  ### Changed
537
569
 
538
- - Graceful shutdown drains in-flight runs for up to five minutes (was 30 seconds) after stopping intake; runs still open at the deadline are aborted and their conversations receive a restart notice instead of silence. The pm2 template `kill_timeout` is now six minutes; update your `ecosystem.config.cjs` to match. Shutdown failures now log every nested step error.
570
+ - Sandbox: update base image and tags.
571
+
572
+ ## [0.2.0-beta.10]
539
573
 
540
574
  ### Added
541
575
 
542
- - Send the run user (id and username) with Sentry events instead of stripping it, so Conversations show who sent each message; email and IP stay dropped.
543
- - Set the Sentry conversation id to the session key on every agent run so Agent Monitoring groups gen_ai spans per thread.
544
- - Report subagent outcomes to Sentry from the subagent tool: `agent.subagent.runs` / `agent.subagent.duration` metrics and a lifecycle breadcrumb for every status; a Sentry error under `error_domain=subagent` for `failed` and `invalid_output` (fingerprinted by error class) and for launch failures. `budget_exceeded`, `timeout`, `cancelled`, and `skipped` stay metrics-only. Reports carry run metrics, never task text or labels.
576
+ - Auto-reply: channel trigger rules and a configurable judge model (`llm.autoReply`).
577
+ - Slack: native E2E smoke workflow under `e2e/`.
545
578
 
546
- ## [1.0.0-beta.52]
579
+ ### Fixed
547
580
 
548
- ### Removed
581
+ - Auto-reply: use mom-compatible marker files; judge policy never throws and always logs.
582
+ - Events: validate one-shot times before scheduling; simplify fresh follow-up sessions.
549
583
 
550
- - Remove the subagent `requiredTools` / `required_tools` mechanism: the post-run "every listed tool was invoked" check was a proxy for evidence that never held and failed only after the budget was spent. Callers that want evidence can read `toolCallCounts`.
584
+ ### Changed
551
585
 
552
- ## [1.0.0-beta.51]
586
+ - Onboard: default model is `claude-sonnet-4-6`.
587
+ - Separated runtime and control-plane paths.
553
588
 
554
- ### Fixed
589
+ ## [0.2.0-beta.9]
555
590
 
556
- - Drop `requiredTools` from built-in subagent profiles; requiring both `read` and `bash` discarded finished answers from tasks that needed only one of them.
557
- - Keep a caller's `requiredTools` when the request also names a profile.
558
- - Stop dropping the retained assistant message when an overflow retry rebuilds context from the store.
591
+ ### Added
559
592
 
560
- ### Changed
593
+ - Session view: floating composer and per-message copy button.
594
+ - Docker sandbox: add `rg` and `fd` to the image.
561
595
 
562
- - Read mikan session metadata through Pi's `session.getValue` in `open`/`inspect`; compare `fstat` fields instead of hashing the file for pending-session materialization.
596
+ ### Fixed
563
597
 
564
- ## [1.0.0-beta.50]
598
+ - Session view: ignore Enter during IME composition; preserve code-block contrast.
565
599
 
566
- ### Fixed
600
+ ## [0.2.0-beta.8]
567
601
 
568
- - Tolerate byte-identical duplicate Dream session files while rejecting divergent same-ID files.
602
+ ### Added
569
603
 
570
- ## [1.0.0-beta.49]
604
+ - Login: shared vault profiles.
605
+ - Session view: improved interactive chat console.
606
+ - Slack: harden socket connection and label the platform in the connect log.
607
+ - Agent: `ThinkingLevel` type on session parameters.
571
608
 
572
609
  ### Changed
573
610
 
574
- - Configure OpenConnector only at startup with `OPENCONNECTOR_ENDPOINT` and `OPENCONNECTOR_ADMIN_TOKEN`; ignore settings overrides of the reserved server, and reduce the Admin MCP Marketplace to the Metabase preset.
611
+ - Sandbox: store the image workspace mount in settings.
612
+ - Dropped `vault.json` metadata — directories are the only source of truth.
613
+ - Refactored agent runner orchestration into smaller modules.
575
614
 
576
- ## [1.0.0-beta.48]
615
+ ### Removed
616
+
617
+ - `UserBindingStore` and `bindings.json` plumbing.
618
+ - Log-to-session backfill.
619
+
620
+ ## [0.2.0-beta.7]
577
621
 
578
622
  ### Added
579
623
 
580
- - Add an offline session migration for Pi 0.84-generation v4 JSONL files, with verified atomic replacement and preserved `*.pi-084.bak` originals.
624
+ - Sandbox: temporary `boost` command for one-off CPU/memory bumps.
625
+ - Slack: mute command summaries.
581
626
 
582
627
  ### Changed
583
628
 
584
- - Upgrade `pi-agent-core` and `pi-ai` to 0.85.0 and persist sessions with the current `v: 4`, `storageVersion: 1` schema.
585
- - Extend `mikan sessions migrate` to convert both legacy mikan v3 and Pi 0.84-generation v4 sessions while the daemon is stopped.
629
+ - Migrated `pi-*` packages to the `@earendil-works/` namespace.
586
630
 
587
- ## [1.0.0-beta.47]
631
+ ### Fixed
632
+
633
+ - Slack: log messages from external apps; hide bash tool diagnostics.
634
+ - Session: ignore history written before a reset.
635
+ - Agent: clarify runtime workspace paths in the system prompt.
636
+
637
+ ## [0.2.0-beta.6]
588
638
 
589
639
  ### Added
590
640
 
591
- - Integrate OpenConnector as a host-side MCP gateway: Slack Conversation offices receive scoped runtime identities, while provider OAuth connections remain in the gateway and execution audit stays attributable to the originating conversation.
592
- - Preserve operating guidance supplied during MCP initialization and present it to the agent with explicit system-prompt and user-intent boundaries.
593
- - Add automatic selection of a sole OpenConnector provider connection when an action omits `connectionName`; retain explicit selection when multiple accounts exist.
641
+ - Commands: conversation model switch (`/pi-model …`) with `:thinking` shorthand.
642
+ - Config: onboarding flow for global settings (`mikan --onboard`).
643
+ - Docs: PM2 ecosystem config and production deploy guide.
594
644
 
595
645
  ### Changed
596
646
 
597
- - Gate MCP tools by the platform trust model and enforce the untrusted package boundary.
598
- - Make platform shutdown cleanup bounded and strengthen runner/session lifecycle rollback handling.
647
+ - Config: nest settings schema; align chat platform commands.
599
648
 
600
649
  ### Fixed
601
650
 
602
- - Isolate Slack DM and thread E2E context and bound event-delivery waits.
651
+ - Slack: strip only the bot's own mention from message text.
603
652
 
604
- ### Tests
653
+ ## [0.2.0-beta.5]
654
+
655
+ ### Added
605
656
 
606
- - Add coverage for OpenConnector token provisioning, MCP instruction propagation, connection selection, trust gating, lifecycle cleanup, and Slack isolation.
657
+ - Sandbox: Cloudflare sandbox bridge (experimental).
658
+ - Tests: unit coverage for `CommandRegistry` and command handlers.
607
659
 
608
- ## [1.0.0-beta.46]
660
+ ### Changed
609
661
 
610
- ### Added
662
+ - Env: renamed `MOM_*` env vars to `MIKAN_*` (breaking).
663
+ - Vault: conversation vault directories are now the source of truth; dropped platform prefix from the conversation vault key.
664
+ - Config: `--state-dir` is the single source for settings.
665
+ - Tightened command/runtime types and added a `postPrivate` capability.
611
666
 
612
- - Add an interactive `mikan onboard` wizard that configures one chat adapter, an LLM provider, and the sandbox, writing private environment and settings files while retaining non-interactive template generation.
613
- - Derive shared workspace visibility from platform channel privacy: Slack public channels can update shared memory, private channels receive it read-only, and DMs, external channels, unknown kinds, and other platforms stay isolated unless explicitly overridden.
614
- - Schedule Dream maintenance for Conversation-office memory with durable evidence checkpoints.
615
- - Add an Admin MCP Marketplace with reviewed GitHub, Context7, Playwright, Sequential Thinking, and Metabase presets; Metabase installations accept an instance endpoint and API key.
667
+ ## [0.2.0-beta.4]
616
668
 
617
669
  ### Changed
618
670
 
619
- - Remove the executable extension system and its CLI/chat management surfaces; packages remain the supported path for deploying read-only skills.
620
- - Remove the harness `auth.json` credential store; configure provider credentials through environment variables, onboarding, or the conversation vault.
621
- - Remove Gondolin, Firecracker, and GitHub Cloud Build log integrations from the supported runtime surface.
622
- - Fail closed when a sandbox backend cannot enforce an isolated office or read-only shared workspace memory; use `image:*` or explicitly select a trusted read-write projection.
623
- - Consolidate runtime, session, adapter, web, and configuration ownership to reduce duplicate lifecycle and parsing rules.
671
+ - Hardened core writes; unified adapter retry and log helpers.
672
+ - Eliminated duplication across adapters, vault, and Slack command factories (#53).
673
+ - Session forks now anchor to raw split points.
674
+ - Adapter-specific stop logic stays in adapters.
624
675
 
625
676
  ### Fixed
626
677
 
627
- - Preserve streamed UTF-8 output when host sandbox chunks split multi-byte characters.
628
- - Re-aim migrated session lanes at the nearest surviving ancestor when the newest v3 entry contains facts but no v4 message.
678
+ - Slack: tighten thread reply triggers.
629
679
 
630
- ### Tests
680
+ ## [0.2.0-beta.3]
631
681
 
632
- - Move CI action runtimes to Node 24 and strengthen runtime, presenter, workspace-projection, MCP marketplace, and session migration coverage.
682
+ ### Added
633
683
 
634
- ## [1.0.0-beta.45]
684
+ - Session view: Slack-aware session viewer with branching (#51).
685
+ - Login: built-in credential presets and a redesigned credential portal.
686
+ - Sandbox: image-mode container CPU/memory limits (#50), bridge network isolation, `ffmpeg` in the tools image.
635
687
 
636
688
  ### Fixed
637
689
 
638
- - Session migration now collapses crash-duplicated v3 lines (a retried append writing the same header and entry twice) the way the v3 reader did, instead of failing v4 verification on the duplicate id. Found rehearsing the migration against 5,446 production session files; after the fix all migrate and reopen cleanly.
690
+ - Discord: normalize thread sessions; queue follow-up messages; persistent channel sessions; hide usage summary by default.
691
+ - Events: restore Slack synthetic notifications (#52).
692
+ - Attachments: wait for downloads before the agent accesses them.
639
693
 
640
- ## [1.0.0-beta.44]
694
+ ## [0.2.0-beta.2]
641
695
 
642
696
  ### Added
643
697
 
644
- - Connect MCP (Model Context Protocol) servers via `mcpServers` settings and expose their tools to the agent as `mcp__<server>__<tool>`; stdio and streamable-HTTP transports, per-server failures isolated, credentials held host-side in server config out of the model's reach.
645
- - Manage MCP servers from the admin portal: per-conversation and global panels with add, enable/disable, and remove; credential values are redacted to key names in the UI.
646
- - Migrate sessions to pi's v4 format with a `mikan sessions migrate` CLI; pi upgraded to 0.84.3.
647
- - Extensions can declare required host capabilities in `package.json` (`mikan.requires`); activation checks them before importing the module and `mikan ext validate` reports them.
698
+ - Per-user vault system for actor-scoped credential isolation (#24).
699
+ - Managed image sandbox (`--sandbox=image:<image>`) (#47).
700
+ - Login flow wired into the runtime; credential onboarding server (#32, #34).
701
+ - Slack: `/pi-new` and `/pi-login` DM commands.
702
+ - Events: actor-aware scheduling tool (#36, #39).
648
703
 
649
704
  ### Changed
650
705
 
651
- - Split the agent module into five authority modules (catalog, prompt, runner, subagent-runner, types); the runtime now owns session rotation decisions and per-event chat-history sync.
652
- - Derive all platform command registration and routing from the single command manifest.
653
- - Adopt pi-ai's retryable-error classifier instead of a local copy.
654
- - Conversation runtimes are keyed by office key, fixing cross-conversation runner reuse after ID changes.
706
+ - Internal contracts unified around "conversation" naming across adapter, store, config, log, and UI layers (#38, #41, #42, #43, #44, #46).
655
707
 
656
708
  ### Fixed
657
709
 
658
- - Session files enforce single-writer ownership, surviving inode reuse and stale writer claims.
659
- - Failed extension activations roll back cleanly; duplicate tool names are rejected.
660
- - Slack slash commands in threads carry the thread session key instead of falling back to the top-level session.
661
- - GitHub first-contact stop no longer creates participation state.
662
- - Subagent deadlines are enforced by a single wall-clock timer; `before_agent_start` hooks run before auth and pre-turn compaction.
663
- - Sandbox container removal failures no longer clear ownership, preventing orphaned containers.
664
- - Run outcomes settle from the final message and run state is released on throw.
710
+ - Telegram: handle bare `stop` in shared chats; escape unsupported HTML entities.
711
+ - Slack: queue follow-up messages per session.
665
712
 
666
- ## [1.0.0-beta.43]
713
+ ## [0.2.0-beta.1]
667
714
 
668
715
  ### Added
669
716
 
670
- - Add an optional authenticated GitHub webhook endpoint that wakes polling immediately for lower-latency issue and pull-request handling.
671
- - Add a machine-readable architecture index and generated system architecture documentation for repository-wide module boundaries and flows.
717
+ - File-backed credential vault (#31) and per-user vault routing (#33).
718
+ - OAuth: GitHub redirect flow, scope parity with `gh` CLI, gcloud OAuth.
719
+ - Sandbox: separate `stateDir` from `workspaceDir` to keep secrets out of sandboxes.
672
720
 
673
- ### Changed
721
+ ### Security
674
722
 
675
- - Run manual and automatic Session Dreams in the background while preserving session rotation and conversation maintenance boundaries.
723
+ - Hardened vault writes, file permissions, and login flow.
724
+ - Stopped leaking secrets in `docker exec` args.
725
+ - Enforced vault sandbox isolation policy.
676
726
 
677
- ### Fixed
727
+ ### Changed
678
728
 
679
- - Wait for final Slack thread responses in isolation coverage instead of accepting provisional native-stream text.
729
+ - Renamed `docker` sandbox mode to `container` (breaking).
730
+ - Replaced `DockerProvisioner` with `DockerContainerManager` + idle stop.
680
731
 
681
- ### Tests
732
+ ## [0.2.0-beta.0]
682
733
 
683
- - Add regression coverage for GitHub webhook authentication and dispatch, background Session Dream lifecycle behavior, and final Slack stream settlement.
734
+ ### Added
684
735
 
685
- ## [1.0.0-beta.42]
736
+ - Sentry integration for error monitoring, tracing, and metrics (#21).
737
+ - Persistent session management with in-thread replies (#18).
738
+ - Telegram: native slash commands; private-chat session fix (#15).
739
+ - `pi-coding-agent` extension loading (#12).
686
740
 
687
- ### Changed
741
+ ## Earlier releases
688
742
 
689
- [Showing lines 1-614 of 1985 (50.0KB limit). Use offset=615 to continue.]
743
+ For releases prior to `0.2.0-beta.0` (i.e. the `0.1.x` line), see the [git tag history](https://github.com/geminixiang/mikan/tags).