@cognisphere-sh/cognisphere-harness 0.0.0-stage → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/CHANGELOG.md +1970 -0
  2. package/bin/cognisphere.mjs +7 -0
  3. package/dist-web/assets/file-editor-CQSmlsy_.js +32 -0
  4. package/dist-web/assets/index-1Hg12QW0.js +336 -0
  5. package/dist-web/assets/index-BDa9M_Wt.css +2 -0
  6. package/dist-web/assets/markdown-sumxz7Eq.js +29 -0
  7. package/dist-web/assets/radix-DHW5y7jr.js +49 -0
  8. package/dist-web/assets/react-BIlrhC09.js +59 -0
  9. package/dist-web/index.html +28 -0
  10. package/home-template/CLAUDE.md +96 -0
  11. package/home-template/app/README.md +80 -0
  12. package/home-template/app/artifacts-routes/README.md +81 -0
  13. package/home-template/app/artifacts-routes/lib/artifacts.ts +87 -0
  14. package/home-template/app/artifacts-routes/private/artifacts/[slug]/ShareToggle.tsx +110 -0
  15. package/home-template/app/artifacts-routes/private/artifacts/[slug]/page.tsx +45 -0
  16. package/home-template/app/artifacts-routes/private/artifacts/[slug]/raw/route.ts +19 -0
  17. package/home-template/app/artifacts-routes/private/artifacts/[slug]/share/route.ts +33 -0
  18. package/home-template/app/artifacts-routes/public/artifacts/[slug]/route.ts +18 -0
  19. package/home-template/app/auth-routes/README.md +69 -0
  20. package/home-template/app/auth-routes/api/auth/login/route.ts +8 -0
  21. package/home-template/app/auth-routes/api/auth/logout/route.ts +5 -0
  22. package/home-template/app/auth-routes/api/auth/me/route.ts +5 -0
  23. package/home-template/app/auth-routes/lib/auth.ts +62 -0
  24. package/home-template/app/auth-routes/lib/harness.ts +16 -0
  25. package/home-template/app/auth-routes/login/page.tsx +28 -0
  26. package/home-template/config.example +56 -0
  27. package/home-template/docs/app/README.md +11 -0
  28. package/home-template/docs/base-harness/README.md +198 -0
  29. package/home-template/docs/base-harness/skills.md +97 -0
  30. package/home-template/docs/harness/README.md +21 -0
  31. package/home-template/scripts/app/README.md +33 -0
  32. package/home-template/scripts/aws/backup.sh +64 -0
  33. package/home-template/scripts/aws/config.example +18 -0
  34. package/home-template/scripts/aws/setup.sh +147 -0
  35. package/home-template/scripts/build.sh +26 -0
  36. package/home-template/scripts/contabo/config.example +24 -0
  37. package/home-template/scripts/contabo/setup.sh +141 -0
  38. package/home-template/scripts/lib/remote-bootstrap.sh +80 -0
  39. package/home-template/scripts/server.sh +189 -0
  40. package/home-template/scripts/setup-server.sh +262 -0
  41. package/package.json +51 -3
  42. package/skills/cognisphere-upgrade/CHANGELOG.md +37 -0
  43. package/skills/cognisphere-upgrade/SKILL.md +217 -0
  44. package/skills/create-plugin/CHANGELOG.md +30 -0
  45. package/skills/create-plugin/SKILL.md +214 -0
  46. package/skills/create-plugin/template/index.ts +47 -0
  47. package/skills/create-plugin/template/seed/scripts/hello/hello-cli +2 -0
  48. package/skills/create-plugin/template/seed/system_prompts/plugin-hello.md +4 -0
  49. package/skills/create-skill/CHANGELOG.md +26 -0
  50. package/skills/create-skill/SKILL.md +105 -0
  51. package/src/agents/base-agent/bootstrap/bootstrap.sh +152 -0
  52. package/src/agents/base-agent/bootstrap/requirements.txt +17 -0
  53. package/src/agents/base-agent/extensions/bash-guard.ts +36 -0
  54. package/src/agents/base-agent/extensions/context-meta.ts +184 -0
  55. package/src/agents/base-agent/extensions/harness-bridge.ts +63 -0
  56. package/src/agents/base-agent/extensions/skill-update-notice.ts +147 -0
  57. package/src/agents/base-agent/knowledge/index.md +10 -0
  58. package/src/agents/base-agent/knowledge/memory.md +24 -0
  59. package/src/agents/base-agent/scripts/agent/agent-browser +62 -0
  60. package/src/agents/base-agent/scripts/agent/ddgs +63 -0
  61. package/src/agents/base-agent/scripts/agent/markitdown +62 -0
  62. package/src/agents/base-agent/scripts/agent/session-reader +442 -0
  63. package/src/agents/base-agent/system_prompts/0-base_prompt.md +409 -0
  64. package/src/agents/base-agent/system_prompts/1-agent.md +17 -0
  65. package/src/agents/base-agent/workspace/index.md +13 -0
  66. package/src/agents/nova/system_prompts/1-agent.md +44 -0
  67. package/src/api/admin.ts +59 -0
  68. package/src/api/agents.ts +925 -0
  69. package/src/api/auth.ts +340 -0
  70. package/src/api/credentials.ts +42 -0
  71. package/src/api/files.ts +234 -0
  72. package/src/api/gws-oauth.ts +381 -0
  73. package/src/api/harness.ts +62 -0
  74. package/src/api/models.ts +288 -0
  75. package/src/api/secrets.ts +211 -0
  76. package/src/api/webhook.ts +66 -0
  77. package/src/cli/agent.ts +96 -0
  78. package/src/cli/index.ts +66 -0
  79. package/src/cli/init.ts +206 -0
  80. package/src/cli/plugin.ts +49 -0
  81. package/src/cli/run.ts +156 -0
  82. package/src/cli/upgrade.ts +134 -0
  83. package/src/cli/util.ts +176 -0
  84. package/src/core/agent-manager.ts +1127 -0
  85. package/src/core/config.ts +102 -0
  86. package/src/core/logger.ts +16 -0
  87. package/src/core/main.ts +225 -0
  88. package/src/core/models-catalog.ts +502 -0
  89. package/src/core/models-store.ts +97 -0
  90. package/src/core/oauth-logins.ts +303 -0
  91. package/src/core/pi-models-sync.ts +118 -0
  92. package/src/core/plugin-registry.ts +87 -0
  93. package/src/core/queue.ts +688 -0
  94. package/src/core/rpc.ts +374 -0
  95. package/src/core/runner.ts +958 -0
  96. package/src/core/secrets.ts +154 -0
  97. package/src/core/types.ts +257 -0
  98. package/src/plugins/admin/index.ts +49 -0
  99. package/src/plugins/admin/seed/system_prompts/plugin-admin.md +7 -0
  100. package/src/plugins/agent-messaging/index.ts +148 -0
  101. package/src/plugins/agent-messaging/seed/scripts/agent-msg/send +94 -0
  102. package/src/plugins/agent-messaging/seed/system_prompts/plugin-agent-messaging.md +31 -0
  103. package/src/plugins/artifacts/index.ts +271 -0
  104. package/src/plugins/artifacts/seed/scripts/artifacts/artifact +158 -0
  105. package/src/plugins/artifacts/seed/skills/artifacts/publish-artifact/CHANGELOG.md +26 -0
  106. package/src/plugins/artifacts/seed/skills/artifacts/publish-artifact/SKILL.md +145 -0
  107. package/src/plugins/artifacts/seed/skills/artifacts/publish-artifact/artifacts/template.html +59 -0
  108. package/src/plugins/artifacts/seed/system_prompts/plugin-artifacts.md +23 -0
  109. package/src/plugins/gws/index.ts +753 -0
  110. package/src/plugins/gws/seed/scripts/gws/email +386 -0
  111. package/src/plugins/gws/seed/scripts/gws/format-email-lib.d.mts +52 -0
  112. package/src/plugins/gws/seed/scripts/gws/format-email-lib.mjs +146 -0
  113. package/src/plugins/gws/seed/scripts/gws/routes +117 -0
  114. package/src/plugins/gws/seed/scripts/gws/settings +98 -0
  115. package/src/plugins/gws/seed/skills/gws/read-email/CHANGELOG.md +20 -0
  116. package/src/plugins/gws/seed/skills/gws/read-email/SKILL.md +86 -0
  117. package/src/plugins/gws/seed/skills/gws/route-email/CHANGELOG.md +14 -0
  118. package/src/plugins/gws/seed/skills/gws/route-email/SKILL.md +84 -0
  119. package/src/plugins/gws/seed/skills/gws/search-email/CHANGELOG.md +15 -0
  120. package/src/plugins/gws/seed/skills/gws/search-email/SKILL.md +100 -0
  121. package/src/plugins/gws/seed/system_prompts/plugin-gws.md +50 -0
  122. package/src/plugins/scheduler/index.ts +149 -0
  123. package/src/plugins/scheduler/seed/scripts/scheduler/cron-fires +248 -0
  124. package/src/plugins/scheduler/seed/scripts/scheduler/scheduler-cli +157 -0
  125. package/src/plugins/scheduler/seed/system_prompts/plugin-scheduler.md +41 -0
  126. package/src/plugins/telegram/index.ts +422 -0
  127. package/src/plugins/telegram/seed/scripts/telegram/routes +95 -0
  128. package/src/plugins/telegram/seed/scripts/telegram/telegram-cli +278 -0
  129. package/src/plugins/telegram/seed/skills/telegram/route-chats/CHANGELOG.md +7 -0
  130. package/src/plugins/telegram/seed/skills/telegram/route-chats/SKILL.md +63 -0
  131. package/src/plugins/telegram/seed/system_prompts/plugin-telegram.md +48 -0
  132. package/README.md +0 -3
package/CHANGELOG.md ADDED
@@ -0,0 +1,1970 @@
1
+ # Changelog
2
+
3
+ All notable changes to CogniSphere are recorded here, one section per version.
4
+
5
+ This file is the single source the **upgrade skill** reads to migrate a harness
6
+ from its current version to a target version. Each release that requires changes
7
+ to a harness's on-disk artifacts MUST include a `### Breaking changes` block
8
+ whose entries follow the form:
9
+
10
+ ```
11
+ - <what changed> [affects: <path glob in the harness dir>]
12
+ ```
13
+
14
+ The skill collects every section in `(current, target]`, proposes a diff against
15
+ the harness directory, and applies it after user approval. See
16
+ [`docs/distribution-and-deployment.md`](docs/distribution-and-deployment.md) §9.
17
+
18
+ The format is based on [Keep a Changelog](https://keepachangelog.com/) and this
19
+ project adheres to [Semantic Versioning](https://semver.org/).
20
+
21
+ ## [0.12.0]
22
+
23
+ ### Breaking changes
24
+
25
+ - **App→harness auth is now a bearer secret, not the operator login.**
26
+ `scripts/server.sh secrets` no longer writes `HARNESS_USER`/`HARNESS_PASS`
27
+ into `app/.env.local`; it writes the same pair as `APP_USER`/`APP_PASS`
28
+ (the app's *own* default sign-in), an `APP_SESSION_SECRET` for the app's
29
+ own cookie (generated once, reused from the previous `.env.local`), and
30
+ mints `harness/.secrets/app-secret` (hex, 0600, reused across restarts —
31
+ the harness also generates it on first boot if absent) written as
32
+ `HARNESS_APP_SECRET`. The app and the harness console mint independent
33
+ session tokens. New reference tree `app/auth-routes/` (refreshed on
34
+ upgrade like `artifacts-routes/`): config-credential login + `app_sid`
35
+ cookie, `lib/harness.ts` bearer client, and `getUser()` as the single
36
+ seam to swap in Clerk/Supabase/NextAuth. `/api/*`, `/admin/*` and
37
+ `GET /api/auth/me` accept `Authorization: Bearer <secret>` alongside the
38
+ `pi_sid` cookie; `X-App-User: <id>` (trusted only with a valid bearer)
39
+ sets the harness-side `user`, else `"app"`. Apps that logged in with
40
+ `HARNESS_USER`/`HARNESS_PASS` or forwarded the browser's `pi_sid`
41
+ cookie to the harness should switch to the bearer + own their user auth;
42
+ webhook plugins that verified a cookie via `/api/auth/me` verify the
43
+ bearer the same way by forwarding `authorization`/`x-app-user` instead.
44
+ Recipe in `app/auth-routes/README.md`.
45
+ [affects: scripts/server.sh, config.example, app/README.md, app/auth-routes/**, docs/base-harness/README.md, .claude/skills/cognisphere-upgrade/SKILL.md]
46
+
47
+ ### Changed
48
+
49
+ - `docs/api.md` §1/§3, `docs/server.md` §3 and
50
+ `docs/distribution-and-deployment.md` document the app bearer,
51
+ `.secrets/app-secret`, and the new `app/.env.local` keys. The upgrade
52
+ skill now refreshes `app/auth-routes/` and drift-checks the home's copies.
53
+
54
+ ## [0.11.1]
55
+
56
+ ### Breaking changes
57
+
58
+ - **`bootstrap.sh` pins the global `pi`.** It previously installed
59
+ `@earendil-works/pi-coding-agent` unpinned and only when `pi` was
60
+ missing, so deployed hosts ran whatever npm resolved at first boot.
61
+ It now compares `pi --version` to `PI_VERSION` (0.84.4) and installs
62
+ that exact version on mismatch, every agent start. Reseed from the
63
+ base agent; no operator action beyond that.
64
+ [affects: agents/*/bootstrap/bootstrap.sh]
65
+
66
+ ### Changed
67
+
68
+ - `home-template/docs/base-harness/README.md`: documents the pinned-`pi`
69
+ behaviour of `bootstrap.sh` (refreshed wholesale on upgrade).
70
+ - **pi upgraded to 0.84.4** (`@earendil-works/pi-ai` +
71
+ `@earendil-works/pi-coding-agent`, from 0.84.1). No harness code
72
+ changes were required: the `pi --mode rpc` flag set, the RPC events the
73
+ harness consumes, the session JSONL format (`CURRENT_SESSION_VERSION`
74
+ still 3), pi-ai's `KnownProvider` union (mirrored in
75
+ `core/models-catalog.ts`, verified identical) and the `ExtensionAPI` /
76
+ `ModelRuntime` / `readStoredCredential` / `getAgentDir` surfaces are all
77
+ unchanged. Verified `pi --mode rpc` on the bundled 0.84.3+ runtime still
78
+ loads the base agent's `.ts` extensions via `-e` (jiti is now
79
+ lazy-loaded). Relevant upstream behaviour changes, all favourable:
80
+ 0.84.2/0.84.4 fixed `pi.sendMessage(..., { triggerTurn: false })`
81
+ placement so `context-meta`'s mid-run checkpoints and
82
+ `skill-update-notice`'s notices land after the turn's tool results
83
+ instead of between a tool call and its result; 0.84.4 also runs
84
+ threshold auto-compaction between tool execution and the next LLM call
85
+ (so `compaction_start`/`compaction_end` can now arrive mid-run, not only
86
+ in prompt preflight — handled by the RPC client change below); 0.84.3
87
+ fixed threshold compaction being skipped when a provider omits usage.
88
+
89
+ ### Fixed
90
+
91
+ - **RPC prompt ack no longer times out during auto-compaction.** pi runs
92
+ threshold compaction in the prompt's preflight, before acking the prompt
93
+ frame, and summarizing a large session can take minutes — the harness's
94
+ 60 s ack timeout then failed the batch repeatedly. `PiRpcClient` now
95
+ suspends pending frame timeouts on `compaction_start` and re-arms them on
96
+ `compaction_end`, and logs both at info with `reason` and
97
+ `tokensBefore` / `estimatedTokensAfter` (`docs/server.md` §4.7).
98
+
99
+ ## [0.11.0]
100
+
101
+ ### Changed
102
+
103
+ - **gws sign-in moved to the agent's Settings tab.** Per-agent Google
104
+ sign-in/sign-out and the scope picker now live on the gws plugin card
105
+ in each agent's Settings tab (`GwsSignInBlock`); the console's
106
+ app-level Settings page keeps only the shared OAuth client id/secret.
107
+ The OAuth callback redirects back to `/agents/<agentId>/settings`.
108
+ - **Frontend apps can host the sign-in button.** The OAuth callback
109
+ (`GET /api/gws/oauth/callback`) is now mounted outside the auth wall —
110
+ the single-use `state` nonce issued by the authenticated start route is
111
+ the auth — and `POST /api/gws/oauth/:agentId/start` accepts an optional
112
+ `returnTo` for where the browser lands afterwards. Recipe (Next.js
113
+ route handler using `HARNESS_USER`/`HARNESS_PASS` + the `/api/*`
114
+ proxy) added to `home-template/app/README.md`; register the app
115
+ origin's `/api/gws/oauth/callback` as an extra redirect URI on the
116
+ Google client.
117
+ - **Gmail scope rationalized.** `gmail.modify` is always requested — it
118
+ is Google's read/write Gmail tier (read, drafts, send, labels,
119
+ mark-read; everything except permanent deletion) and the poll loop's
120
+ mark-read needs it; the narrower Gmail scopes (`readonly`, `compose`,
121
+ `send`, `labels`) are strict subsets of it, so no granular Gmail
122
+ choice is offered. Optional per-service scopes (Calendar, Drive, …)
123
+ unchanged, still stored in the gws config key `oauthScopes`.
124
+ - `home-template/app/README.md` and `docs/base-harness/README.md`
125
+ updated accordingly (both refreshed wholesale by the upgrade skill).
126
+
127
+ ### Removed
128
+
129
+ - **Legacy gws authentication.** The manual `gws auth login` +
130
+ `gws auth export` path is no longer supported or surfaced: the
131
+ `managed` field is gone from `GET /api/gws/oauth` (`signedIn` now
132
+ means "signed in via the web flow"), the "operator-managed
133
+ credentials file" labeling is gone from the console, and the plugin's
134
+ not-signed-in error points only at the web console. A hand-set
135
+ `GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE` secret still functions at the
136
+ plugin level but shows as not signed in.
137
+
138
+ ## [0.10.2]
139
+
140
+ ### Breaking changes
141
+
142
+ - Base prompt: main (non-task) threads are now coordinators, not workers —
143
+ they delegate skill-driven procedures, file reads, and sizable work to
144
+ task threads instead of doing it (or reading `SKILL.md`s) themselves;
145
+ the **Task threads** section carries the rule. Refreshed wholesale on
146
+ upgrade [affects: agents/*/system_prompts/0-base_prompt.md]
147
+ - Nova's persona prompt: the "delegate large code reads" working-style
148
+ bullet now defers to the base prompt's coordinator-not-worker rule
149
+ (code reads, searches, and implementation go to task threads). This
150
+ file is deployment-owned — apply the same edit to existing novas [affects: agents/nova/system_prompts/1-agent.md]
151
+
152
+ ## [0.10.1]
153
+
154
+ ### Breaking changes
155
+
156
+ - Skill description spec tightened (`create-skill` v1.3.0): "what's
157
+ included" is a brief sketch of the main procedures, not an exhaustive
158
+ contents list; partial applicability moves under "use when"; the whole
159
+ description stays under 1000 characters. During upgrade, audit every
160
+ skill and rephrase any description that doesn't conform, with a
161
+ patch bump and changelog entry per rephrased skill [affects: agents/*/skills/*/*/SKILL.md]
162
+
163
+ ### Changed
164
+
165
+ - `docs/base-harness/skills.md` and the `create-skill` skill restate the
166
+ new description spec (both refreshed wholesale by the upgrade skill).
167
+
168
+ ## [0.10.0]
169
+
170
+ ### Added
171
+
172
+ - **Web-based Google sign-in/sign-out for gws agents.** New Google
173
+ Workspace card on the console's Settings page and `/api/gws/oauth/*`
174
+ routes (`api/gws-oauth.ts`): the operator saves a "Web application"
175
+ OAuth client from their own GCP project once per harness
176
+ (`.secrets/gws/oauth-client.json`, redirect URI
177
+ `<console origin>/api/gws/oauth/callback`), then signs each
178
+ gws-enabled agent in with a browser consent flow. The callback writes
179
+ the standard `authorized_user` JSON (the shape
180
+ `gws auth export --unmasked` produces) to
181
+ `.secrets/gws/<agentId>/credentials.json`, points the agent's
182
+ `gws.GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE` secret at it, and
183
+ soft-reloads the agent — replacing the manual `gws auth login` +
184
+ `gws auth export` dance. Sign-out revokes the refresh token, deletes
185
+ the managed files, clears the secret, and reloads. Hand-set
186
+ credentials paths keep working and are labeled "operator-managed" in
187
+ the card.
188
+ - **Per-agent OAuth scope selection.** New optional gws plugin config
189
+ key `oauthScopes` (comma-separated scope URLs; read by the sign-in
190
+ flow, ignored by the plugin at runtime). The Settings card edits it
191
+ per agent as checkboxes grouped by service (Calendar, Drive, Docs,
192
+ Sheets, Slides, Contacts, Tasks — full and read-only variants);
193
+ `gmail.modify` + `openid email` are always requested. Granted scopes
194
+ are recorded at sign-in and shown per agent; changing the config
195
+ requires signing in again to take effect.
196
+
197
+ ## [0.9.2]
198
+
199
+ ### Fixed
200
+
201
+ - **Batch teardown now reaps the pi child's entire process tree.** Pi is
202
+ spawned in its own process group (`detached: true`) and, once it exits,
203
+ the group is SIGKILL-swept — so headless browsers, dev servers, and
204
+ anything else the agent's bash tool left running die with the batch
205
+ instead of accumulating on the server. The 5s no-exit escalation also
206
+ kills the group, not just pi.
207
+ - **/tmp no longer fills up.** A janitor sweeps known agent debris from the
208
+ OS temp dir at boot and every 6h (age > 24h): pi's `pi-bash-*.log`
209
+ output-spill files (pi writes them for any oversized command output and
210
+ never deletes them) and browser profile dirs
211
+ (`.org.chromium.*`, `puppeteer_dev_chrome_profile-*`, `playwright*`).
212
+
213
+ ### Changed
214
+
215
+ - **Agent-spawned processes are now strictly batch-scoped.** A background
216
+ process started during one turn no longer survives to the next — the
217
+ group sweep at batch end kills it. No shipped plugin or seed relied on
218
+ cross-batch daemons; if a future workload needs one, run it outside the
219
+ agent (e.g. a plugin) or ask for a skip-sweep flag.
220
+
221
+ ## [0.9.1]
222
+
223
+ ### Fixed
224
+
225
+ - **Memory leaks in the harness execution path.** Three long-running-process
226
+ leaks closed:
227
+ - The per-file session-cost cache (`api/agents.ts`) never evicted — entries
228
+ for deleted threads lived for the life of the process. A failed stat now
229
+ evicts, and past 4096 entries a sweep drops entries whose file is gone.
230
+ - The shared Ajv singleton pinned a compiled validator per agent restart
231
+ (its cache is keyed by schema object identity and `agent.json` is
232
+ re-parsed on every start). Validation now uses a throwaway Ajv per call.
233
+ - A wedged `pi` child that never acked its prompt frame held its worker
234
+ slot, batch state, and OS process forever. `sendPrompt` now times out
235
+ after 60 s; the batch fails and the child is torn down.
236
+ - **Async EPIPE on the pi child's stdin no longer crashes the server.** The
237
+ stdin stream had no `error` listener, so a child dying mid-write raised an
238
+ unhandled `'error'` event; it now logs at debug.
239
+
240
+ ## [0.9.0]
241
+
242
+ ### Added
243
+
244
+ - **The agent owns her gws notification settings.** New agent-writable overlay
245
+ `plugins/gws/state/settings.json`, managed by the seeded
246
+ `scripts/gws/settings` CLI (`show|set|reset`) and re-read by the plugin on
247
+ every poll tick — the same live-reload pattern as `routes.json`, so a change
248
+ applies within one poll. Per-key precedence: `settings.json` →
249
+ operator `config.json` → defaults. Overridable keys: `pollIntervalSec`,
250
+ `gmailQuery`, `allowedSenders`, `requireAgentInTo` (`firstOfThreadOnly`
251
+ stays operator-only).
252
+ - **Passive mailbox.** `pollIntervalSec: -1` disables polling entirely: no
253
+ notifications, nothing marked read — the agent reads mail only when she
254
+ chooses to search. While passive the loop still re-reads settings every
255
+ 60s, so setting a real interval again resumes within a minute (pending
256
+ unread arrives on the next poll).
257
+ - **Settings announced on start.** Each plugin start posts one `gws_settings`
258
+ message on the plugin's `main` channel — mailbox address, effective
259
+ settings, routing-rule count, and how to change them — so the agent can
260
+ re-assert her preferences after every harness restart.
261
+
262
+ ### Changed
263
+
264
+ - **gws defaults: notify on all unread inbox, poll every 15 minutes.**
265
+ `pollIntervalSec` 60 → 900 and `requireAgentInTo` true → false — by default
266
+ the latest message of *every* unread inbox thread now wakes the agent,
267
+ routed to its per-thread id as before; Cc/Bcc-only mail is skipped only
268
+ when `requireAgentInTo` is switched back on. Operators who want the old
269
+ behavior set both keys explicitly in `plugins/gws/config.json`.
270
+
271
+ ### Breaking changes
272
+
273
+ - New seeded `scripts/gws/settings` — the settings overlay's CLI. Plugin seeds
274
+ re-copy on the next agent start, so restarting each agent installs it
275
+ [affects: agents/*/scripts/gws/]
276
+ - `system_prompts/plugin-gws.md` rewritten (still 50 lines): new inbound
277
+ default, the Settings section, and the "ask to be kept in `To:`" outbound
278
+ rule dropped (it existed only for the old `requireAgentInTo: true` default);
279
+ it re-seeds on the next agent start
280
+ [affects: agents/*/system_prompts/plugin-gws.md]
281
+ - gws skills `read-email` (1.1.1), `search-email` (1.0.1), `route-email`
282
+ (1.0.1): wording that hardcoded the old you-in-`To` delivery rule now points
283
+ at the agent-owned settings; they re-seed on the next agent start
284
+ [affects: agents/*/skills/gws/]
285
+ - The default flip means an existing `plugins/gws/config.json` that never set
286
+ `pollIntervalSec` / `requireAgentInTo` changes behavior on upgrade — set
287
+ them explicitly to keep the old 60s / To-only behavior
288
+ [affects: agents/*/plugins/gws/config.json]
289
+
290
+ ## [0.8.25]
291
+
292
+ ### Changed
293
+
294
+ - **The web UI's thread list renders task threads as a tree.** A thread spawned
295
+ as a task (`<parent>-§-[TASK]-§-<slug>`) now nests under its parent to any
296
+ depth, so a task thread that itself spawns tasks shows up where it belongs
297
+ instead of as a top-level row. Each child is labeled by its task slug, rows
298
+ indent per level with a collapse chevron, and search keeps the matching
299
+ subtree. Replaces the flat two-level "tasks (n)" dropdown. Web-only — no
300
+ harness artifacts change.
301
+
302
+ ## [0.8.24]
303
+
304
+ ### Added
305
+
306
+ - **`scheduler-cli list` takes filters.** `--thread-id ID` narrows to the
307
+ schedules bound to one thread, `--active`/`--paused` split by state, and
308
+ `--from WHEN [--to WHEN]` keeps only the schedules that *fire* inside a
309
+ window, adding a `fires` array of the occurrences to each. `WHEN` is ISO
310
+ (`2026-08-17T09:00:00Z`) or bare (`2026-08-17`, `2026-08-17 09:00`); bare
311
+ means wall clock in the harness timezone, read from `harness.json`. Defaults
312
+ are `--from` now and `--to` +7 days, the window is capped at 366 days, and
313
+ `--max N` (default 50) caps the fires listed per schedule. Bare `list` is
314
+ unchanged. Until now an agent asking "what have I got scheduled this week?"
315
+ had to read every schedule and evaluate the crons in its head.
316
+ - **`scripts/scheduler/cron-fires`** — the fire-time evaluator behind
317
+ `--from`/`--to`, seeded alongside `scheduler-cli`. jq cannot evaluate cron and
318
+ `croner` is not resolvable from an agent dir (no `node_modules` of its own),
319
+ so it is a dependency-free minute scan: timezone-aware via
320
+ `Intl.formatToParts`, 5- and 6-field expressions, names/ranges/steps/lists,
321
+ and the cron dom+dow OR convention. Unparseable crons come back with an
322
+ `error` field and over-long fire lists with `"truncated": true`, so nothing
323
+ is dropped silently. `node scripts/scheduler/cron-fires --self-check` runs
324
+ its assertions.
325
+
326
+ ### Breaking changes
327
+
328
+ - New `scripts/scheduler/cron-fires` — `scheduler-cli list --from/--to` needs
329
+ it and exits non-zero without it. Plugin seeds re-copy on the next agent
330
+ start, so restarting each agent installs it
331
+ [affects: agents/*/scripts/scheduler/]
332
+ - `scripts/scheduler/scheduler-cli` gained the `list` flags; it re-seeds on the
333
+ next agent start [affects: agents/*/scripts/scheduler/scheduler-cli]
334
+ - `system_prompts/plugin-scheduler.md` documents the new `list` flags (34 → 41
335
+ lines, still inside the 50-line budget); it re-seeds on the next agent start
336
+ [affects: agents/*/system_prompts/plugin-scheduler.md]
337
+
338
+ ## [0.8.23]
339
+
340
+ ### Changed
341
+
342
+ - gws prompt fragment: the inbound section no longer explains *why* outbound
343
+ mail must ask to be kept in `To:` — the rule itself is unchanged under
344
+ **Rules**, and saying it twice spent two lines of a 50-line budget on one
345
+ instruction.
346
+
347
+ ### Breaking changes
348
+
349
+ - `system_prompts/plugin-gws.md` reworded; it re-seeds on the next agent start,
350
+ so restarting the gws agents is all that is required
351
+ [affects: agents/*/system_prompts/plugin-gws.md]
352
+
353
+ ## [0.8.22]
354
+
355
+ ### Added
356
+
357
+ - **`scripts/gws/email`** — the agent-facing Gmail CLI, seeded with the `gws`
358
+ plugin. `email read <messageId>` (full body, `--strip-quotes`,
359
+ `--attachments` → `plugins/gws/inbox/<messageId>/`), `email thread <threadId>`
360
+ (skim id/from/date/snippet, or `--full` for every body), `email search
361
+ '<gmail query>' [--max N]` (hits listed with subject/from/date/snippet — the
362
+ raw API returns bare ids), `email labels`, and `email label <id> --add NAME
363
+ --remove NAME --archive --read|--unread [--create] [--thread]`, which
364
+ resolves label names to Gmail's opaque label ids and refuses an unknown name
365
+ unless `--create`. It replaces the stdin-only `scripts/gws/format-email`.
366
+ - **Plugin-shipped skills for `gws` and `telegram`**, seeded under
367
+ `skills/<plugin-id>/<slug>/` like the `artifacts` plugin's: `read-email`
368
+ (full bodies, quoted history, thread skimming, attachments), `search-email`
369
+ (Gmail query syntax, filing with labels/archive/read, and the standing
370
+ `settings.filters` rules), `route-email` (thread-routing rules) and
371
+ `route-chats` (Telegram chat routing).
372
+
373
+ ### Changed
374
+
375
+ - **gws notifications are a preview, not the mail.** An `email_received` body
376
+ is now the `Subject/From/To/TimeStamp` header, the **first two lines** of the
377
+ sender's own text (quoted reply history stripped first), and the *names* of
378
+ any attachments. Attachments are no longer downloaded at poll time — the
379
+ agent fetches what it needs with `scripts/gws/email`, so a mailbox of long
380
+ quoted-history threads stops spending context on mail nobody reads.
381
+ - **Plugin prompt fragments are capped at 50 lines**, with every step-by-step
382
+ procedure moved into a plugin-owned skill: `plugin-gws.md` 204 → 50 lines,
383
+ `plugin-telegram.md` 75 → 48. A fragment costs every turn of every thread; a
384
+ skill costs one description line until an agent needs it.
385
+ - `docs/server.md`, `docs/base-harness/skills.md` and the `create-plugin` skill
386
+ (v1.3.0) document the 50-line budget and what belongs in a fragment
387
+ (identity, event shape, always-on rules) versus a skill. Both scaffold trees
388
+ are refreshed wholesale by the upgrade skill.
389
+
390
+ ### Breaking changes
391
+
392
+ - `scripts/gws/format-email` is replaced by `scripts/gws/email`. Plugin seeds
393
+ are overwritten on every agent start but never pruned, so the stale script
394
+ has to be deleted by hand [affects: agents/*/scripts/gws/format-email]
395
+ - Email notifications no longer carry the full body: any agent instruction or
396
+ knowledge note that assumes one — or that pipes `gws gmail users messages get
397
+ … | format-email` — must be reworded to call `scripts/gws/email read
398
+ <MessageId>` [affects: agents/*/system_prompts/1-*.md]
399
+ - The gws/telegram prompt fragments, the new `email` CLI and the four new
400
+ skills re-seed themselves on the next agent start; restarting the affected
401
+ agents is all that is required [affects: agents/*/skills/gws/]
402
+
403
+ ## [0.8.21]
404
+
405
+ ### Added
406
+
407
+ - **`artifacts` plugin** — agents publish self-contained static HTML (reports,
408
+ summaries, dashboards) and share a link on the app's own domain. Each
409
+ artifact carries a **public/private flag** that decides which of its two URLs
410
+ works: `<app>/public/artifacts/<slug>` for anyone, or
411
+ `<app>/private/artifacts/<slug>` behind the app's own login. **No URL carries
412
+ a token.** The plugin serves `public/<slug>` openly and `private/<slug>`,
413
+ `private/<slug>/meta`, `private/<slug>/share` only to callers presenting the
414
+ `ARTIFACTS_APP_SECRET` — which is what keeps private artifacts unreachable
415
+ from the open `/webhook/*` surface. Config: `appBaseUrl` (required). Catalog
416
+ scope, so it runs only on agents that opt in.
417
+ - **Artifact HTML is sandboxed and responsive by construction.** Every response
418
+ carries `Content-Security-Policy: sandbox` without `allow-same-origin` (agent
419
+ HTML on the app's origin can never touch its cookies or storage), plus
420
+ `Referrer-Policy: no-referrer`, `nosniff`, and an injected
421
+ `<meta name="viewport">` when the author omitted one.
422
+ - **`app/artifacts-routes/`** in the home template — drop-in Next.js routes for
423
+ the two paths above: a pass-through public route, and a protected page that
424
+ renders the artifact in a sandboxed iframe under the app's own public/private
425
+ toggle (the toggle is app chrome because a sandboxed page has an opaque
426
+ origin and could never authenticate). Includes `lib/artifacts.ts` with a
427
+ fail-closed `signedIn()` for the home to replace.
428
+ - **The `artifacts` seed ships a skill** — `publish-artifact` (authoring rules
429
+ for one self-contained, mobile-and-desktop-readable file; the starter
430
+ template; publishing, sharing, updating, taking down). First use of
431
+ `seed/skills/<plugin-id>/<slug>/`, now documented in `create-plugin`.
432
+
433
+ ### Changed
434
+
435
+ - **Deploy-time wiring for `artifacts`.** New `config` keys `ARTIFACTS_AGENT`
436
+ and `ARTIFACTS_SESSION_COOKIE` (both blank = feature off). When the agent is
437
+ set, `scripts/server.sh secrets` generates `ARTIFACTS_APP_SECRET` once and
438
+ writes it to **both** `harness/.secrets/secrets.json` and `app/.env.local`,
439
+ creates `agents/<agent>/plugins/artifacts/config.json` with
440
+ `appBaseUrl: https://$DOMAIN`, and thereby enables the plugin on that agent.
441
+ Existing homes get the refreshed `server.sh` + `config.example` from the
442
+ upgrade, but must add the keys to their own `config` for anything to happen.
443
+ - **`cognisphere-upgrade` 1.3.0** — `app/artifacts-routes/` joins the
444
+ harness-owned scaffold refresh (the one exception to "never refresh under
445
+ `app/`"), plus a new step 4b-i that diffs the home's *copies* of those routes
446
+ and reports drift instead of overwriting them.
447
+ - **`create-plugin` 1.2.0** — documents shipping a skill inside a plugin seed
448
+ (`seed/skills/<id>/<slug>/`), and its description now says when a plugin is
449
+ the right answer.
450
+ - **`create-skill` 1.2.0**, **`publish-harness` 1.1.0** — descriptions gained
451
+ situational triggers; `publish-harness` also covers the new-plugin case of
452
+ the shipped-artifact rule and deploy-time wiring notes.
453
+ - Docs: `docs/api.md` §10 (artifact routes + header contract),
454
+ `docs/server.md` (plugin list, plugin-shipped skills),
455
+ `docs/distribution-and-deployment.md` §5 (deploy-time wiring),
456
+ `docs/base-harness/README.md`, `app/README.md`.
457
+
458
+ ### Breaking changes
459
+
460
+ - New `artifacts` plugin — opt in per agent by creating the dir; it needs
461
+ `config.json` with `appBaseUrl` and the `ARTIFACTS_APP_SECRET` secret, or set
462
+ `ARTIFACTS_AGENT` in `config` and let `scripts/server.sh secrets` write all
463
+ three [affects: agents/*/plugins/artifacts/]
464
+ - Agents with the plugin enabled gain the seeded `scripts/artifacts/artifact`
465
+ CLI, the `plugin-artifacts.md` prompt fragment and the `publish-artifact`
466
+ skill on next start; all three are plugin-owned and must not be hand-edited
467
+ in the agent dir [affects: agents/*/scripts/artifacts/, agents/*/system_prompts/plugin-artifacts.md, agents/*/skills/artifacts/]
468
+
469
+ ## [0.8.20]
470
+
471
+ ### Changed
472
+
473
+ - **Memory is episodic; procedural guidance lives elsewhere.** The base
474
+ prompt's **Memory** section now states that `knowledge/memory.md` holds
475
+ events and facts only — a rule about *how to behave* belongs in
476
+ `system_prompts/1-agent.md` when it holds globally, or in the skill for the
477
+ procedure it governs when it only applies there. The seeded
478
+ `knowledge/memory.md` header carries the same rule.
479
+ - **`1-*` prompt files are the agent's to edit, with admin approval.**
480
+ Previously the base prompt routed every prompt change through the developer
481
+ agent (`nova`). Now only `0-*` and `plugin-<id>.md` files do; `1-*` files
482
+ the agent edits itself once the relevant admin has approved the change.
483
+
484
+ ### Breaking changes
485
+
486
+ - Memory section rewritten (episodic-only) and prompt-ownership rules changed
487
+ (`1-*` = self-edit with admin approval, not a `nova` request) [affects: agents/*/system_prompts/0-base_prompt.md]
488
+ - `knowledge/memory.md` header gained a "what belongs here" block — episodic
489
+ events and facts only, procedural rules go to `1-agent.md` or a skill [affects: agents/*/knowledge/memory.md]
490
+
491
+ ## [0.8.19]
492
+
493
+ ### Added
494
+
495
+ - **Chat pagination.** `GET /api/agents/:id/sessions/:threadId/:sessionId`
496
+ takes an optional `?limit=N` that returns only the newest N jsonl entries.
497
+ The file is tail-seeked — read backwards in 256 KiB chunks until N lines
498
+ are in hand — so opening a long-running thread costs the same as a short
499
+ one. The response gains `hasMore` (older rows exist above the window);
500
+ without `limit` the whole file is read and `hasMore` is `false`.
501
+ - **"Load 100 more" in the web chat.** Threads open at the newest 100
502
+ entries and page backwards on demand, preserving scroll position. The
503
+ window resets on thread/session switch, and a deep link
504
+ (`?thread=&session=&entry=`) drops the limit so the targeted entry is
505
+ always in range. The Raw JSONL tab shares the query and therefore shows
506
+ the same window.
507
+
508
+ ## [0.8.18]
509
+
510
+ ### Changed
511
+
512
+ - **Base prompt: reorganised, and workspace/memory layout reworked.**
513
+ `0-base_prompt.md` is reordered to follow the agent's actual reading path
514
+ (Cwd → System prompts → Plugins → Skills → Threads → Message metadata →
515
+ Communication model → Task threads → Workspace → Sessions → …), and the
516
+ `# Guidelines` grab-bag is gone — its content folded into **Workspace**
517
+ (persist immediately, daily notes) and **Communication model** (be
518
+ proactive).
519
+ - **New on-disk layout for notes, knowledge and memory:**
520
+
521
+ ```
522
+ workspace/
523
+ index.md
524
+ threads/<ThreadId>/{notes.md, files/, tasks/<task-slug>/notes.md}
525
+ daily_notes/YYYY-MM-DD.md
526
+ knowledge/
527
+ index.md, memory.md, files/
528
+ ```
529
+
530
+ - Task-thread notes moved from `workspace/taskThreads/<ThreadId>/tasks.md`
531
+ to `workspace/threads/<ThreadId>/tasks/<task-slug>/notes.md`; the parent
532
+ tracks its task threads in its own `notes.md → ## Tasks` section.
533
+ - Each thread dir gains a `files/` dir for files belonging to that thread.
534
+ - `workspace/memory/` is **removed**. Memory now lives in the cross-thread
535
+ `knowledge/` dir as a single `knowledge/memory.md`, with `knowledge/index.md`
536
+ indexing `knowledge/files/` (reference docs and long-term documents).
537
+ - **Memory is one grep-able file.** `knowledge/memory.md` holds sections
538
+ separated by `-----$-----$-----$-----`, each with `name`, `lastUpdated`
539
+ (`YYYY-MM-DD HH:MM:SS`) and a `description` covering what to remember, why,
540
+ where it came from, the reasoning, and how long it stays relevant. The agent
541
+ greps for the sections it needs and edits them in place instead of reading
542
+ the whole file.
543
+ - **Notes have a fixed shape.** Every `notes.md` (thread or task) is current
544
+ state, not a log: `## Context`, `## Tasks`, `## Decisions`, `## ToDos`,
545
+ `## Notes`, `## References` — every entry timestamped `YYYY-MM-DD HH:MM:SS`,
546
+ updated in place, with stale entries deleted.
547
+ - **Daily notes** now explicitly capture observations and learnings alongside
548
+ the situation/task/result summary.
549
+ - Base-agent seeds updated to match: new `knowledge/index.md` and
550
+ `knowledge/memory.md`, refreshed `workspace/index.md`.
551
+ - Docs updated: `docs/server.md` §3 on-disk tree and the shipped
552
+ `docs/base-harness/README.md` agent-anatomy list.
553
+
554
+ ### Breaking changes
555
+
556
+ Existing harnesses must migrate their agents' on-disk files to the new layout —
557
+ the prompt no longer describes the old paths, so anything left behind is
558
+ invisible to the agent. Per agent dir:
559
+
560
+ - `0-base_prompt.md` reordered; `# Guidelines` removed; Workspace/Task-threads
561
+ sections rewritten for the new layout. Replace each fork's copy with the new
562
+ seed (harness-owned). [affects: agents/*/system_prompts/0-base_prompt.md]
563
+ - Move `workspace/memory/**` into a single `knowledge/memory.md`, one section
564
+ per memory in the new `name` / `lastUpdated` / `description` format,
565
+ separated by `-----$-----$-----$-----`; delete `workspace/memory/`. [affects: agents/*/workspace/memory/**]
566
+ - Move `workspace/taskThreads/<ThreadId>/tasks.md` content into the parent
567
+ thread's `workspace/threads/<ThreadId>/notes.md` under `## Tasks`, and any
568
+ per-task notes to `workspace/threads/<ThreadId>/tasks/<task-slug>/notes.md`;
569
+ delete `workspace/taskThreads/`. [affects: agents/*/workspace/taskThreads/**]
570
+ - Rewrite each `workspace/threads/<ThreadId>/notes.md` into the fixed sections
571
+ (`## Context`, `## Tasks`, `## Decisions`, `## ToDos`, `## Notes`,
572
+ `## References`) with timestamped entries; drop `summary.md` by folding it
573
+ into `## Context`. [affects: agents/*/workspace/threads/**]
574
+ - Seed `knowledge/index.md` and `knowledge/memory.md` if absent, and move
575
+ existing cross-thread reference docs under `knowledge/files/`. [affects: agents/*/knowledge/**]
576
+ - Refresh `workspace/index.md` from the new seed (its `## Memory` section is
577
+ gone; knowledge is indexed in `knowledge/index.md`). [affects: agents/*/workspace/index.md]
578
+
579
+ ## [0.8.17]
580
+
581
+ ### Changed
582
+
583
+ - **Base prompt: aggressive task-thread delegation is now a rule.** The
584
+ Task threads section opens with "You must delegate aggressively" and a
585
+ "should a task thread do this?" default-yes framing, and the Guidelines
586
+ checklist gained a matching bullet (bulk reads, broad searches, research,
587
+ and self-contained multi-step work belong in task threads).
588
+ - **Web UI fixes.** Tool-call card arguments no longer overflow the card
589
+ (long unbroken tokens now wrap), and empty thinking segments are no
590
+ longer rendered as collapsible blocks.
591
+
592
+ ### Breaking changes
593
+
594
+ - `0-base_prompt.md`'s Task threads and Guidelines sections now mandate
595
+ aggressive delegation to task threads. Replace each fork's copy with the
596
+ new seed (harness-owned). [affects: agents/*/system_prompts/0-base_prompt.md]
597
+
598
+ ## [0.8.16]
599
+
600
+ ### Changed
601
+
602
+ - **Skill-update notices now fire on every unseen version change, reverts
603
+ included.** 0.8.15's dedupe was keyed per (skill, new version), so a
604
+ revert back to the version the agent had originally read stayed silent
605
+ (1.2 → 1.3 → 1.2 sent only the 1.3 notice), leaving the agent believing
606
+ the withdrawn version was current. `skill-update-notice.ts` now tracks a
607
+ single "aware" version per skill — the later of the agent's own
608
+ read/edit/write and the last notice sent — and fires whenever the file's
609
+ current version differs from it, upgrades and reverts alike. Sending a
610
+ notice marks that version as seen, so nothing re-fires while the file
611
+ stays put. 0.8.15 sessions replay into the new model unchanged (read +
612
+ sent entries replay chronologically, latest wins). The notice text now
613
+ reads "changed after you last read it or were notified".
614
+ - The base prompt's `SystemMessage` bullet and the shipped
615
+ `docs/base-harness/skills.md` describe the new upgrade-and-revert
616
+ semantics (upgrade refreshes the doc wholesale).
617
+
618
+ ### Breaking changes
619
+
620
+ - `skill-update-notice.ts` notification semantics changed (fires on any
621
+ unseen version change, reverts included) — replace each fork's copy with
622
+ the shipped version. [affects: agents/*/extensions/skill-update-notice.ts]
623
+ - `0-base_prompt.md`'s `SystemMessage` bullet was reworded for the new
624
+ semantics. Replace each fork's copy with the new seed
625
+ (harness-owned). [affects: agents/*/system_prompts/0-base_prompt.md]
626
+
627
+ ## [0.8.15]
628
+
629
+ ### Changed
630
+
631
+ - **Skill-update notices close the prompt-vs-read recency gap.**
632
+ `<available_skills>` is rebuilt at every spawn, so it always advertises
633
+ the current skill version — but it sits at position 0 of the context,
634
+ before any `SKILL.md` read in history; agents reasoned by context order,
635
+ trusted the (later) read, and concluded the prompt was stale instead of
636
+ re-reading the updated skill. Two-part fix: the base prompt's Skills
637
+ section now explains the recency inversion (the prompt is regenerated
638
+ per spawn, so on a mismatch the *file* changed after the read) and what
639
+ to do (act per the skill's `CHANGELOG.md`, or re-read `SKILL.md`); and a
640
+ new seeded pi extension `skill-update-notice.ts` records the frontmatter
641
+ version of every `SKILL.md` the agent reads (or edits/writes) as custom
642
+ session entries, and when the file's current version no longer matches,
643
+ injects a one-time-per-(skill, version) standalone `<harness-metadata>`
644
+ notice — `SystemMessage: Skill "<name>" changed after you last read it
645
+ (vX -> vY)` plus the newest changelog entry — checked at
646
+ `before_agent_start` (spawn-gap bumps, lands before the batch's first
647
+ LLM call) and each `turn_start` (mid-run bumps, next steer seam). State
648
+ replays from session entries, so the once-per-version dedupe survives
649
+ the fresh-pi-per-batch process model. The base prompt's Message metadata
650
+ section documents the new `SystemMessage` field: a notice from the
651
+ harness itself, to be acted on as platform instructions.
652
+ - **context-meta checkpoints are now indexed and pre-call.** One
653
+ standalone checkpoint message before *every* LLM call, after all of that
654
+ call's inputs are in place: `Checkpoint: <n>` (monotonic per-call
655
+ counter, seeded across process respawns from session replay) +
656
+ `CheckpointTokens: +<delta>` (context growth since the previous
657
+ checkpoint: the previous response, provider-reported and exact, plus the
658
+ new input after it — tool results / incoming message — estimated at
659
+ chars/4 and ~1200 tokens per image). Every checkpoint re-anchors on
660
+ provider-reported usage, so estimation error is bounded to one step and
661
+ spans sum accurately. Checkpoints are emitted only when the next call is
662
+ provably imminent (`before_agent_start` return for a run's first call;
663
+ the last expected toolResult's `message_end` as a steer mid-run), which
664
+ deletes the old deferred/`agent_settled` flush machinery and its
665
+ empty-LLM-loop hazard. `CheckpointTokens: reset` now marks any
666
+ unknowable delta (compaction, unknown fill). The ephemeral per-call
667
+ `Model`/`ContextUsage` injection is unchanged.
668
+ - **Daily notes: one entry per thread per day.** The base prompt's
669
+ end-of-task daily-note rule now says to extend the day's existing entry
670
+ for the ThreadId instead of appending a second one.
671
+ - Shipped `docs/base-harness/skills.md` documents the recency rule and the
672
+ skill-update notice mechanism (upgrade refreshes it wholesale).
673
+
674
+ ### Breaking changes
675
+
676
+ - New seeded agent extension `skill-update-notice.ts` — copy the shipped
677
+ file into each existing agent's `extensions/` dir. [affects: agents/*/extensions/skill-update-notice.ts]
678
+ - `context-meta.ts` was rewritten (per-call indexed checkpoints) — replace
679
+ each fork's copy with the shipped version. [affects: agents/*/extensions/context-meta.ts]
680
+ - `0-base_prompt.md` gained the skills recency guidance, the
681
+ `SystemMessage` metadata field, the rewritten Checkpoint-messages
682
+ bullet, and the one-entry-per-thread daily-notes rule. Replace each
683
+ fork's copy with the new seed (harness-owned). [affects: agents/*/system_prompts/0-base_prompt.md]
684
+
685
+ ## [0.8.14]
686
+
687
+ ### Changed
688
+
689
+ - **End-of-task daily-note summaries** — the base prompt's Guidelines now
690
+ require agents to append a brief summary to
691
+ `workspace/daily_notes/YYYY-MM-DD.md` at the end of each task, tagged with
692
+ the ThreadId: a few sentences covering the situation, the task, what was
693
+ done, the result, and any learnings — brief prose, no headed sections.
694
+
695
+ ### Breaking changes
696
+
697
+ - `0-base_prompt.md` Guidelines gained the end-of-task daily-notes summary
698
+ rule [affects: agents/*/system_prompts/0-base_prompt.md]
699
+
700
+ ## [0.8.13]
701
+
702
+ ### Changed
703
+
704
+ - **`create-skill` installed in every agent** — `agent new` now installs the
705
+ shipped `create-skill` skill into every agent's own `skills/agent/` dir
706
+ (previously dev-agent only; the dev agent still gets the full set). The
707
+ base prompt's "Maintaining skills" section now states the rule explicitly:
708
+ every piece of procedural memory must land as a skill — create a new one
709
+ or update an existing one — following the installed `create-skill` skill.
710
+ - **Skill description spec** — a skill's description must carry four parts:
711
+ summary, what's included (the procedures/topics/scripts/artifacts covered,
712
+ so an agent can spot a partially relevant skill), when to use it, and the
713
+ version; `metadata` carries `author` + `version`. Taught in the base
714
+ prompt, the shipped `docs/base-harness/skills.md`, and `create-skill`
715
+ (bumped to v1.1.0).
716
+
717
+ ### Breaking changes
718
+
719
+ - `0-base_prompt.md`'s "Maintaining skills" section was rewritten: procedural
720
+ memory must always land as a new or updated skill (via the installed
721
+ `create-skill` skill), and skill descriptions must carry summary +
722
+ what's-included + when-to-use + version. Replace each fork's copy with the
723
+ new base file (harness-owned). [affects: agents/*/system_prompts/0-base_prompt.md]
724
+ - Every agent now carries the `create-skill` skill. Copy the shipped
725
+ `create-skill` skill directory into each existing agent's
726
+ `skills/agent/create-skill/`. [affects: agents/*/skills/agent/create-skill/**]
727
+
728
+ ## [0.8.12]
729
+
730
+ ### Changed
731
+
732
+ - **Deployment-owned deploy hooks (`scripts/app/`)** — the scaffolded deploy
733
+ scripts are harness-owned and refreshed on upgrade, so app-specific deploy
734
+ logic no longer gets edited into them. Each script now sources an optional
735
+ deployment-owned hook: `server.sh` `gen_secrets` → `scripts/app/secrets.sh`
736
+ (after the stock secrets), `server.sh` → `scripts/app/server.sh` (after every
737
+ stock action except `harness`/`dev`/`logs`, same positional args — app
738
+ lifecycle work), `setup-server.sh` → `scripts/app/setup-server.sh`
739
+ (end, as root), `aws/setup.sh` → `scripts/app/aws-setup.sh` and
740
+ `contabo/setup.sh` → `scripts/app/contabo-setup.sh` (end of provisioning).
741
+ Hooks are sourced with the deploy `config` + the caller's resolved vars in
742
+ scope. Extra deploy params go in the deployment-owned root `config`,
743
+ documented in a deployment-owned `scripts/app/config.example` (the root
744
+ `config.example` stays harness-owned). Only `scripts/app/README.md` (the
745
+ contract) ships with the template. `cognisphere-upgrade` bumped to v1.2.0
746
+ to teach the scaffold refresh this ownership split.
747
+
748
+ - **pi upgraded to 0.84.1** (`@earendil-works/pi-ai` +
749
+ `@earendil-works/pi-coding-agent`, from 0.81.1). No harness code
750
+ changes were required: the RPC event contract the harness consumes
751
+ (`agent_start`, `agent_end`, `message_start`, extension `setStatus`
752
+ reports), the session JSONL format (`CURRENT_SESSION_VERSION` still
753
+ 3), the `pi --mode rpc` flag set, and the `ExtensionAPI` /
754
+ `ModelRuntime` surfaces the harness uses are all unchanged or
755
+ additive. pi 0.84.0's `message_update` breaking change (deltas only,
756
+ no cumulative `message`) does not affect us — the harness never reads
757
+ `message_update`. `ModelRuntime.reloadConfig()` was removed upstream;
758
+ the harness never called it.
759
+ - `core/models-catalog.ts`: refreshed the mirrored `KnownProvider` union
760
+ to pi-ai 0.84.1 (adds `baseten`, `qwen-token-plan-individual`, and the
761
+ `ant-ling` / `radius` / `nvidia` / `zai-coding-cn` / `qwen-token-plan`
762
+ / `qwen-token-plan-cn` ids that had drifted in since 0.81.1). Catalog
763
+ entries themselves are unchanged — new providers stay unlisted in the
764
+ Models page until an entry is added.
765
+ - **System-prompt file ownership is now an explicit contract**, taught in
766
+ the base prompt (new "System prompts" section) and documented in
767
+ `docs/server.md` §3 and the shipped `docs/base-harness/README.md`:
768
+ `0-*` files are harness-owned (replaced by the seed on upgrade;
769
+ `0.1-agent-directory.md` excepted), `plugin-<id>.md` is plugin-owned
770
+ (reseeded on every agent start — edits are clobbered), and `1-agent.md`
771
+ is deployment-owned: identity/persona/behaviour only. Any deliberate
772
+ override of a harness- or plugin-owned prompt file must be documented in
773
+ the home's `docs/harness/`; undocumented divergence is drift.
774
+ - **Skills are the agent's procedural memory, and are versioned.** The base
775
+ prompt's new "Skills" section tells agents to keep every step-by-step
776
+ procedure (SOP, runbook) as a skill — never inlined in prompt files,
777
+ `knowledge/`, or workspace notes — with the version stated in the skill's
778
+ description (the only metadata pi injects into the prompt) and in
779
+ `SKILL.md`'s `metadata.version`, plus a per-skill `CHANGELOG.md`. Skills
780
+ are self-contained — helper scripts in the skill's `scripts/`, supporting
781
+ files in `artifacts/`, referenced by skill-relative paths. Agents
782
+ re-read a skill whose advertised version differs from the copy they last
783
+ read, so version bumps propagate procedure changes to long-running
784
+ agents, and task-thread briefs name the skill (and version) to follow
785
+ instead of restating its steps. Shipped skills (`cognisphere-upgrade` v1.1.0, `create-plugin`
786
+ v1.1.0) follow the convention; the `cognisphere-upgrade` skill now also
787
+ migrates procedural content out of prompts/SOPs into versioned skills
788
+ when an upgrade window touches an agent's prompts.
789
+ - **New shipped skill `create-skill` (v1.0.0)** — the authoring/updating
790
+ procedure for versioned agent skills: scaffold `SKILL.md` + per-skill
791
+ `CHANGELOG.md` + `scripts/`/`artifacts/`, semver bump rules, SOP
792
+ migration, and pi's frontmatter constraints. Installed like the other
793
+ cognisphere skills — into the home's `.claude/skills/` + `.agents/skills/`
794
+ by `init`, and into the developer agent's own `skills/agent/` — so the
795
+ dev agent carries the skill-authoring procedure as a skill itself.
796
+ Existing homes pick it up via the upgrade's scaffold refresh; existing
797
+ dev agents by copying it into `agents/nova/skills/agent/create-skill/`.
798
+ - `cognisphere agent new` seeds a starter `system_prompts/1-agent.md`
799
+ (persona skeleton) so every agent dir carries the same prompt layout.
800
+
801
+ ### Breaking changes
802
+
803
+ - The developer-agent persona file was renamed for layout consistency:
804
+ `system_prompts/1-dev-agent.md` → `system_prompts/1-agent.md`. Rename the
805
+ fork's file (contents unchanged). [affects: agents/nova/system_prompts/*]
806
+ - `0-base_prompt.md` gained the "Skills" and "System prompts" sections and
807
+ moved procedures out of `knowledge/SOPs/`. Replace each fork's copy with
808
+ the new seed (local edits in a `0-*` file move to `1-agent.md`). [affects: agents/*/system_prompts/0-base_prompt.md]
809
+ - Procedural memory must live in versioned skills: for every agent, re-read
810
+ its `system_prompts/*.md` and `knowledge/` (incl. `knowledge/SOPs/`) and
811
+ migrate each step-by-step procedure into
812
+ `skills/agent/<slug>/SKILL.md` (version in description +
813
+ `metadata.version`, per-skill `CHANGELOG.md`, helper scripts in the
814
+ skill's `scripts/`, supporting files in `artifacts/`), updating
815
+ `1-agent.md` to reference the skill instead of restating it. [affects: agents/*]
816
+
817
+ ## [0.8.11]
818
+
819
+ ### Changed
820
+
821
+ - **Model overrides in `.secrets/models.json` now configure pi itself.**
822
+ New `core/pi-models-sync.ts` mirrors the store's `modelOverrides` into
823
+ pi's own models.json (`~/.pi/agent/models.json`, or
824
+ `$PI_CODING_AGENT_DIR/models.json`) at server boot, on every agent
825
+ start, and after `PUT /api/models` — so spawned pi children resolve the
826
+ overridden `contextWindow`/`maxTokens` natively (model registry,
827
+ in-context ContextUsage telemetry, and pi's compaction thresholds).
828
+ Ownership: for providers present in the harness store, the
829
+ `modelOverrides` key of pi's models.json is harness-owned (replaced
830
+ wholesale, removed when the store has none); all other fields and
831
+ providers in that file are preserved, and a corrupt file is skipped,
832
+ never clobbered.
833
+ - **Pi-as-configured is now the single source of truth for context
834
+ windows.** The API's reporting (`lastContext` in `/api/agents/usage`
835
+ and the threads list) resolves context windows via pi models.json
836
+ (`modelOverrides`, then custom model entries) with pi-ai's built-in
837
+ catalog as fallback, instead of consulting `.secrets/models.json`
838
+ directly — the dashboard and the agent's in-context telemetry can no
839
+ longer disagree, and hand-written custom providers in pi's models.json
840
+ now report correct context windows too.
841
+
842
+ ## [0.8.10]
843
+
844
+ ### Changed
845
+
846
+ - **`extensions/context-meta.ts`: turn-ending checkpoints now land right
847
+ after the final response.** Instead of deferring to the next inbound
848
+ message (which placed the checkpoint after the next user message), the
849
+ deferred emit fires on `agent_settled` — the agent is idle there, so
850
+ `sendMessage` appends the checkpoint directly to the session without
851
+ triggering a turn or an LLM call. Tool-use responses keep the immediate
852
+ steer emit (checkpoint after that response's tool results). Inbound-flush
853
+ and seed-time catch-up remain as fallbacks.
854
+
855
+ ### Breaking changes
856
+
857
+ - Seeded file `extensions/context-meta.ts` changed (turn-ending checkpoint
858
+ placement via agent_settled). Copy it from the new seed into existing
859
+ agents. [affects: agents/*/extensions/*]
860
+
861
+ ## [0.8.9]
862
+
863
+ ### Fixed
864
+
865
+ - **`extensions/context-meta.ts`: infinite invocation loop after
866
+ turn-ending responses (0.8.8 regression — upgrade off 0.8.8
867
+ immediately).** A checkpoint message queued via `sendMessage` lands in
868
+ pi's pending-message queue, and the agent loop keeps running while any
869
+ pending message exists — so a checkpoint emitted right after a response
870
+ with no tool calls kept provoking empty LLM calls forever, one paid call
871
+ per cycle. Checkpoints are now sent immediately only when the response
872
+ has tool calls (the loop continues anyway); for a turn-ending response
873
+ the emit is deferred to the next inbound message, with the existing
874
+ seed-time catch-up covering process exit. Per-step granularity and the
875
+ gapless trail are unchanged.
876
+
877
+ ### Breaking changes
878
+
879
+ - Seeded file `extensions/context-meta.ts` changed (checkpoint emission no
880
+ longer extends the agent loop). Copy it from the new seed into existing
881
+ agents. [affects: agents/*/extensions/*]
882
+
883
+ ## [0.8.8]
884
+
885
+ ### Changed
886
+
887
+ - **`extensions/context-meta.ts`: checkpoints are now standalone messages
888
+ instead of stamps on neighboring messages.** After each assistant
889
+ response the extension injects a custom message
890
+ (`customType: "context-meta.checkpoint"`) carrying
891
+ `CheckpointTokens: +<n>` and a self-describing `Covers:` line, delivered
892
+ at the first provider-legal seam (after the response's tool calls,
893
+ before the next LLM call). Standalone messages are prune-safe: a future
894
+ context cleaner can remove a span and its checkpoint by identity,
895
+ instead of stranding a stamp fused into a kept message that describes
896
+ deleted content. A checkpoint covers everything up through the nearest
897
+ assistant response above it; seeding emits a catch-up checkpoint on
898
+ spawn if the previous batch exited with one still queued, keeping the
899
+ trail gapless across batches. User messages and tool results are no
900
+ longer stamped.
901
+ - Base system prompt: `CheckpointTokens` moved out of the incoming-message
902
+ metadata fields into the telemetry section — documents the standalone
903
+ checkpoint messages, their coverage rule, and that they are informational
904
+ only (never act on or reply to them).
905
+
906
+ ### Breaking changes
907
+
908
+ - Seeded file `extensions/context-meta.ts` changed (standalone checkpoint
909
+ messages replace per-message stamps). Copy it from the new seed into
910
+ existing agents. [affects: agents/*/extensions/*]
911
+ - Message-metadata section of the seeded base system prompt changed
912
+ (checkpoint messages documented as standalone telemetry, FYI-only; field
913
+ removed from the block example). Graft into existing agents'
914
+ prompts. [affects: agents/*/system_prompts/0-base_prompt.md]
915
+
916
+ ## [0.8.7]
917
+
918
+ ### Changed
919
+
920
+ - **`extensions/context-meta.ts`: checkpoint stamps now span batch
921
+ boundaries.** On spawn the extension replays the stamping state machine
922
+ over the persisted session instead of only seeding a baseline, so a
923
+ batch that ended on an assistant response leaves its pending checkpoint
924
+ recoverable — the next batch's first message carries it (the previous
925
+ batch's final step). Only a thread's very first message has no
926
+ `CheckpointTokens` stamp.
927
+
928
+ ### Breaking changes
929
+
930
+ - Seeded file `extensions/context-meta.ts` changed (cross-batch checkpoint
931
+ seeding). Copy it from the new seed into existing agents. [affects: agents/*/extensions/*]
932
+
933
+ ## [0.8.6]
934
+
935
+ ### Added
936
+
937
+ - **New seeded pi extension `extensions/context-meta.ts`: context-window
938
+ telemetry for the agent.** Two signals:
939
+ - `CheckpointTokens: +<n>` — persistent per-step stamps. After each
940
+ assistant response, the first following user message / tool result is
941
+ stamped with the exact context growth of the completed step, computed
942
+ from consecutive provider-reported usage totals (no estimation).
943
+ Deltas are per-step, never cumulative, so the trail stays truthful
944
+ across compaction; a compaction stamps `CheckpointTokens: reset`.
945
+ Summing a span of stamps tells the agent what pruning that span would
946
+ free. Seeded from the session JSONL on spawn, so deltas stay exact
947
+ across batch boundaries.
948
+ - `Model:` + `ContextUsage: <tokens>/<context window>` — ephemeral,
949
+ injected into each LLM call's last outgoing message via the `context`
950
+ hook; never persisted, so exactly one fresh copy exists per call.
951
+
952
+ ### Changed
953
+
954
+ - Base system prompt: `<harness-metadata>` docs gain the `CheckpointTokens`
955
+ field and a note on the latest-message `Model`/`ContextUsage` telemetry,
956
+ with guidance to delegate/wrap up under context pressure.
957
+
958
+ ### Breaking changes
959
+
960
+ - New seeded file `extensions/context-meta.ts`. Copy it from the new seed
961
+ into existing agents. [affects: agents/*/extensions/*]
962
+ - Message-metadata section of the seeded base system prompt changed
963
+ (`CheckpointTokens` field, `Model`/`ContextUsage` telemetry note). Graft
964
+ into existing agents' prompts. [affects: agents/*/system_prompts/0-base_prompt.md]
965
+
966
+ ## [0.8.5]
967
+
968
+ ### Changed
969
+
970
+ - **Task-thread ids are now `<ThreadId>-§-[TASK]-§-<task-slug>`** (parent
971
+ thread id, literal `[TASK]` marker, kebab-case task slug, joined by
972
+ `-§-`) instead of the ambiguous `<ThreadId>-<task-slug>`. Prompts and
973
+ the session-reader help teach the new form; thread ids remain opaque to
974
+ the queue/runner, so no data migration — existing old-format task
975
+ threads keep working, they just render as ordinary threads in the UI.
976
+ - **The admin web UI groups task threads under their parent thread.** The
977
+ thread list no longer shows task threads as top-level rows; each parent
978
+ gets a `tasks (N)` dropdown listing them by task slug (select/delete),
979
+ the mobile picker indents them under the parent, and search matches a
980
+ parent by its task threads. Task threads with a missing parent fall
981
+ back to the top-level list.
982
+
983
+ ### Breaking changes
984
+
985
+ - Task-thread delegation section rewritten for the new
986
+ `<ThreadId>-§-[TASK]-§-<task-slug>` id format. [affects: agents/*/system_prompts/0-base_prompt.md]
987
+ - Task-thread spawn note updated to the new id format. [affects: agents/*/system_prompts/plugin-agent-messaging.md]
988
+ - `--help` text: task-thread session dir example updated to the new id
989
+ format. [affects: agents/*/scripts/agent/session-reader]
990
+
991
+ ## [0.8.4]
992
+
993
+ ### Changed
994
+
995
+ - **The upgrade skill's scaffold refresh now audits local edits first and
996
+ guarantees they survive.** Step 4 is audit → copy → re-apply: diff every
997
+ scaffold area against the installed package before copying, use the home's
998
+ git history to separate local edits from upstream changes, list every
999
+ local edit in the summary, then re-apply them on top of the fresh copies —
1000
+ so the approval diff shows upstream changes plus intact local edits. A
1001
+ local edit is dropped only with explicit operator approval; when a
1002
+ difference can't be classified, the skill stops and asks.
1003
+
1004
+ ## [0.8.3]
1005
+
1006
+ ### Changed
1007
+
1008
+ - **The upgrade skill now refreshes every harness-owned scaffold file on
1009
+ upgrade** — `scripts/`, `config.example`, `docs/base-harness/`, and
1010
+ `.claude/skills/` are re-copied wholesale from the installed package as
1011
+ part of the reviewed migration diff, so scaffold fixes reach existing
1012
+ homes even when a release didn't list them as breaking changes. User-owned
1013
+ files (`app/`, `docs/harness/`, `docs/app/`, `CLAUDE.md`, `config`, and
1014
+ the harness data dir) are never touched by the refresh.
1015
+ - **The publish preflight gates shipped-artifact changes.** Changes since the
1016
+ last release to files forked into agent dirs (`src/agents/**`,
1017
+ `src/plugins/*/seed/**`) fail preflight unless the version's CHANGELOG
1018
+ section carries a `### Breaking changes` block; changed scaffold/skill
1019
+ files are listed as a reminder to note them under `### Changed`.
1020
+ - Shipped docs updated to match (`docs/base-harness/skills.md`).
1021
+
1022
+ ## [0.8.2]
1023
+
1024
+ ### Fixed
1025
+
1026
+ - **The runner now exports `HARNESS_BASE_URL` (= `serverBaseUrl`) to every
1027
+ agent process.** The seeded `agent-msg/send` reads
1028
+ `${HARNESS_BASE_URL:-http://127.0.0.1:3142}`, but nothing ever set the
1029
+ variable — the runner didn't export it and the deploy scripts only define
1030
+ `HARNESS_PORT`, which the script never reads. So on any non-default port
1031
+ (`PORT` / `cognisphere serve --port`), agent-messaging silently posted to
1032
+ the wrong origin. The fallback in the seed is unchanged and now only
1033
+ covers running the script outside a runner-spawned process.
1034
+
1035
+ ## [0.8.1]
1036
+
1037
+ ### Fixed
1038
+
1039
+ - **Base prompt no longer tells agents to pass `-o json` to ddgs.** That flag
1040
+ doesn't print to stdout — it writes the results to a file in the cwd (e.g.
1041
+ `text_<query>_<timestamp>.json`), so piping to `jq` got empty input and
1042
+ agent dirs silently accumulated result files. The prompt now says to read
1043
+ the default stdout table directly and warns against `-o json`/`-o csv`.
1044
+ - **Plugin requests route to `nova`, not the operator.** The communication
1045
+ model section still said to ask the operator (via the admin plugin) to
1046
+ install or write missing plugins, contradicting 0.8.0's ownership model
1047
+ (§Platform code changes). It now forwards those requests to the developer
1048
+ agent via agent-messaging, keeping the operator for what genuinely needs
1049
+ them (secrets, harness restarts).
1050
+ - **`session-reader --help` documented a session layout 0.8.0 deleted.** The
1051
+ `sessions/<ThreadId>/subagents/<subAgentId>/` path example is now
1052
+ `sessions/<ThreadId>-<task-slug>/` — task-thread sessions are ordinary
1053
+ threads.
1054
+ - **Wrapper headers (`agent-browser`, `ddgs`, `markitdown`) no longer cite the
1055
+ removed `pi -p` sub-agent CLI** as their reason to exist. The wrappers stay
1056
+ (the PATH/venv rationale holds); the header comments and `--help` text now
1057
+ state it without referencing sub-agents.
1058
+
1059
+ ### Breaking changes
1060
+
1061
+ - Base prompt corrections (ddgs output flags, plugin-request routing) —
1062
+ replace the fork's copy with the new seed, re-applying any local
1063
+ edits. [affects: agents/*/system_prompts/0-base_prompt.md]
1064
+ - session-reader help updated for the task-thread session layout —
1065
+ re-seed. [affects: agents/*/scripts/agent/session-reader]
1066
+ - Wrapper rationale comments dropped the `pi -p` reference — re-seed (no
1067
+ behavior change). [affects: agents/*/scripts/agent/agent-browser, agents/*/scripts/agent/ddgs, agents/*/scripts/agent/markitdown]
1068
+
1069
+ ## [0.8.0]
1070
+
1071
+ ### Changed
1072
+
1073
+ - **Sub-agents are now task threads.** The `pi -p` sub-agent CLI is gone;
1074
+ delegation runs through the core agent-messaging plugin instead. An agent
1075
+ spawns a task by messaging **itself** on a new thread id
1076
+ `<parentThreadId>-<task-slug>`; the task thread runs with the full agent
1077
+ prompt in its own context window and **must report back** to the parent
1078
+ thread (named explicitly in the brief) via `scripts/agent-msg/send` when
1079
+ done. Delegation is asynchronous — the parent ends its turn and is woken by
1080
+ the report; follow-ups and status checks are messages to the same task
1081
+ thread. Task-thread status is declared **in the brief**, never inferred from
1082
+ the sender (self-messages also arrive for other reasons).
1083
+ - **One agent prompt.** `0-base_prompt.md` and `0.1-main-agent.md` merged into
1084
+ a single `0-base_prompt.md` covering identity, tools, workspace, threads,
1085
+ plugins, communication, task threads, app home, and the dev-agent hand-off.
1086
+ Ownership is now explicit: each agent owns its own agent dir (scripts,
1087
+ skills, workspace, knowledge); platform code **and software installs** go to
1088
+ the developer agent.
1089
+ - **agent-messaging is a core plugin** (`CORE_PLUGIN_IDS`) — auto-installed
1090
+ and seeded on every agent alongside admin and scheduler; `cognisphere
1091
+ plugin add agent-messaging` is refused. Messaging a thread id that doesn't
1092
+ exist yet starts a fresh thread (that's how task threads spawn).
1093
+ - **The developer agent is always `nova`.** `cognisphere init` creates it
1094
+ under that fixed id (`--dev-agent` flag removed), `agent new` refuses the
1095
+ name for any other agent, and the prompt templates reference `nova`
1096
+ literally — the `{{DevAgentId}}`/`{{DevAgentName}}` baking (and the
1097
+ `bakeDevAgentName`/`findDevAgentId` CLI machinery) is gone. Telegram is no
1098
+ longer auto-enabled on it; human channels are opt-in (other agents reach it
1099
+ via agent-messaging).
1100
+ - **Web console:** agent messages are hyperlinked — an incoming
1101
+ `agent_message` links to the sender's thread (`From`/`FromThread`), and an
1102
+ `agent-msg/send` tool call links to the destination agent thread
1103
+ (`$PI_AGENT_ID` resolves to the current agent). Thread-only deep links
1104
+ (`?thread=`) now work without a session id.
1105
+ - Base template and dev overlay moved to `src/agents/base-agent/` and
1106
+ `src/agents/nova/` inside the package (was `src/base-agent/`,
1107
+ `src/dev-agent/`). No harness-side effect; `files` already ships `src/`.
1108
+
1109
+ ### Removed
1110
+
1111
+ - `subagentModel` from `agent.json` and the `PI_SUBAGENT_PROVIDER` /
1112
+ `PI_SUBAGENT_MODEL` / `PI_SUBAGENT_THINKING` env vars — task threads run on
1113
+ the agent's own model (per-thread overrides still apply).
1114
+ - The `subagents` array from `GET /api/agents/:id/sessions/:threadId/usage`
1115
+ (and the legacy `sessions/<threadId>/subagents/*/` scanning behind it). The
1116
+ response is now `{ threadId, main }`; task-thread usage shows up as
1117
+ ordinary threads.
1118
+
1119
+ ### Breaking changes
1120
+
1121
+ - Sub-agent CLI removed — delete the seeded wrapper and role prompt from every
1122
+ agent fork. [affects: agents/*/scripts/agent/subagent]
1123
+ - Sub-agent role prompt removed with it. [affects: agents/*/scripts/agent/sub-agent-prompt.md]
1124
+ - `0.1-main-agent.md` merged into `0-base_prompt.md` — replace the fork's
1125
+ `0-base_prompt.md` with the new seed (re-apply any local edits) and delete
1126
+ `0.1-main-agent.md`. [affects: agents/*/system_prompts/]
1127
+ - Agent-directory roster renamed — rename the file to
1128
+ `0.1-agent-directory.md` (contents unchanged; the manager only regenerates
1129
+ the new name when absent, so an un-renamed copy would duplicate the
1130
+ roster). [affects: agents/*/system_prompts/0.3-agent-directory.md]
1131
+ - `subagentModel` no longer read — remove the key where present. [affects: agents/*/agent.json]
1132
+ - agent-messaging became a core plugin — the per-agent enable dir is
1133
+ redundant (remove), and a forked copy now shadows the bundled core plugin
1134
+ (remove unless the fork is intentional). [affects: agents/*/plugins/agent-messaging, plugins/agent-messaging]
1135
+ - Developer agent id frozen to `nova` — rename the existing dev agent's dir
1136
+ (the one whose `agent.json` has `devAgent: true`, e.g. `dory`) to `nova`,
1137
+ and update any references to the old id (other agents' roster fragments,
1138
+ `allowMessageFrom` lists, workspace notes). New prompt seeds address the
1139
+ dev agent as `nova` literally. [affects: agents/*]
1140
+
1141
+ ## [0.7.2]
1142
+
1143
+ ### Fixed
1144
+
1145
+ - **`spawn E2BIG` on every batch once `system_prompts/` crossed 128 KiB.** The
1146
+ runner passed the whole assembled system prompt as a single `--system-prompt`
1147
+ argv value. Linux caps **one** argv/env string at `MAX_ARG_STRLEN` = 131 072
1148
+ bytes — a per-string limit, independent of the ~2 MB `ARG_MAX` total — so a
1149
+ prompt tree that grew past 128 KiB killed `spawn("pi", …)` outright. Because
1150
+ `assembleSystemPrompt` hands every thread the same files, this took *all* of
1151
+ an agent's threads down at once, with `E2BIG` and no partial failure to
1152
+ narrow it down.
1153
+
1154
+ The runner now writes the assembled prompt to
1155
+ `sessions/<threadId>/.system-prompt.md` (rewritten on every spawn) and passes
1156
+ **that path** to `--system-prompt`. pi's `resolvePromptInput` already reads a
1157
+ flag value as a file when it names an existing path, so this needs no pi-side
1158
+ change, and files have no length ceiling. An env var would not have worked —
1159
+ same per-string cap.
1160
+
1161
+ `scripts/agent/subagent` had the identical exposure (it concatenated
1162
+ `0-base_prompt.md` + `sub-agent-prompt.md` into one `--system-prompt` string,
1163
+ so sub-agents were on course to fail the same way at the same threshold). It
1164
+ now passes the two files as paths — `--system-prompt <base>
1165
+ --append-system-prompt <role>` — which pi composes as
1166
+ `<system-prompt>\n\n<append>`, byte-identical to the concatenation it
1167
+ replaces.
1168
+
1169
+ ### Changed
1170
+
1171
+ - **The developer agent now gets the `agent-messaging` plugin by default**, on
1172
+ top of telegram. It owns the home's platform code and every other agent's
1173
+ prompt tells it to route code and doc changes there — but until now nothing
1174
+ gave those agents a way to actually send it one; the request had to go
1175
+ through a human on Telegram. `cognisphere init` and
1176
+ `cognisphere agent new <name> --dev` both enable it. The inbox default is
1177
+ unchanged (`allowMessageFrom: ["*"]`, i.e. any in-harness agent).
1178
+
1179
+ ### Breaking changes
1180
+
1181
+ - Existing developer agents don't have the `agent-messaging` plugin enabled;
1182
+ create the (empty) plugin dir to install the bundled copy with its default
1183
+ config. [affects: agents/*/plugins/agent-messaging/]
1184
+ - `scripts/agent/subagent` passes the sub-agent system prompt as two file
1185
+ paths instead of one concatenated string (operator edits survive — merge
1186
+ rather than overwrite). [affects: agents/*/scripts/agent/subagent]
1187
+
1188
+ ## [0.7.1]
1189
+
1190
+ ### Added
1191
+
1192
+ - **gws routing on the Gmail thread id** — `scripts/gws/routes add` takes a
1193
+ new `--gmail-thread-id RE` (rule field `gmailThreadId`), matched as an
1194
+ **anchored**, case-insensitive regex against the raw Gmail thread id — a
1195
+ plain id is an exact match, `a|b` a set. This is the precise way to park
1196
+ replies: a reply always stays in the Gmail thread of the message it
1197
+ answers, so routing on that id captures the follow-ups to one mail and
1198
+ nothing else, where `--from`/`--subject` also catch unrelated mail. A rule
1199
+ still needs at least one of `--from` / `--subject` / `--gmail-thread-id`,
1200
+ and when several are given all must match; first matching rule wins.
1201
+
1202
+ ### Breaking changes
1203
+
1204
+ *(Nothing breaks — rules without `gmailThreadId` behave exactly as before.)*
1205
+
1206
+ - `scripts/gws/routes` gained the `--gmail-thread-id` flag, and
1207
+ `system_prompts/plugin-gws.md`'s "Routing rules" section documents it
1208
+ (operator edits survive — merge rather than overwrite). [affects: agents/*/scripts/gws/routes, agents/*/system_prompts/plugin-gws.md]
1209
+
1210
+ ## [0.7.0]
1211
+
1212
+ ### Added
1213
+
1214
+ - **Telegram thread-routing rules** — `plugins/telegram/state/routes.json`,
1215
+ managed by the seeded `scripts/telegram/routes` CLI (`add | list |
1216
+ remove`), mirrors the gws routing added in 0.6.0. A rule maps a chat id to
1217
+ a thread id of the agent's choosing, overriding the agent's
1218
+ `threadIdStrategy`: `routes add --name ops --thread-id ops-room --chat
1219
+ '-100.*'`. `--chat` is an **anchored**, case-insensitive regex matched
1220
+ against the chat id — a plain id is an exact match, `.*` is a wildcard,
1221
+ `123|456` a set. First matching rule wins; the plugin re-reads the file on
1222
+ every batch of updates, so a new rule takes effect immediately. `/reset`
1223
+ in a routed chat resets the routed thread.
1224
+
1225
+ ### Changed
1226
+
1227
+ - **`PluginInstanceContext.resetThread` takes an optional second argument**
1228
+ — `resetThread(channelId, threadIdOverride?)`. Plugins that route a
1229
+ channel to a custom thread pass the same override they gave `notify`, so
1230
+ the reset hits the thread the messages actually landed in. Omitted → the
1231
+ previous `threadIdStrategy` mapping, unchanged.
1232
+
1233
+ ### Breaking changes
1234
+
1235
+ *(Nothing breaks — the routing CLI is a new on-disk artifact an existing
1236
+ home syncs to adopt; agents without `routes.json` behave exactly as before.)*
1237
+
1238
+ - New seeded script `scripts/telegram/routes` and a "Routing rules" section
1239
+ in `system_prompts/plugin-telegram.md` (operator edits survive — merge
1240
+ rather than overwrite). [affects: agents/*/scripts/telegram/routes, agents/*/system_prompts/plugin-telegram.md]
1241
+
1242
+ ## [0.6.2]
1243
+
1244
+ ### Changed
1245
+
1246
+ - **Base agent knows about the app home.** `0.1-main-agent.md` gained a
1247
+ `# The app home` section pointing every agent at the repo above its agent
1248
+ dir: `../../../app/` (the user-facing frontend users see in a browser),
1249
+ `../../../docs/` (`base-harness/` platform reference, `harness/` this
1250
+ deployment's agents/plugins, `app/` the frontend), plus `harness/` and
1251
+ `scripts/`. The `# Platform code changes` hand-off now covers the app and
1252
+ the docs explicitly — read freely, route every change to the developer
1253
+ agent, report stale docs there.
1254
+ - **Developer agent's `agent.json.description`** (what the agent-directory
1255
+ roster shows other agents) now names the frontend app and the docs duty:
1256
+ "…owns and modifies this deployment's platform code — agent
1257
+ prompts/scripts, forked plugins, the user-facing frontend app, deploy
1258
+ scripts — and keeps docs/harness + docs/app current."
1259
+
1260
+ ### Breaking changes
1261
+
1262
+ *(Nothing breaks — both are on-disk artifacts an existing home must sync to
1263
+ adopt; old copies keep working untouched.)*
1264
+
1265
+ - `system_prompts/0.1-main-agent.md` gained the app-home + docs sections
1266
+ (operator edits survive — merge rather than overwrite; `{{DevAgentId}}` /
1267
+ `{{DevAgentName}}` are baked at fork time, so substitute the dev agent's
1268
+ actual id when hand-merging). [affects: agents/*/system_prompts/0.1-main-agent.md]
1269
+ - The developer agent's `agent.json.description` is only written at
1270
+ `agent new --dev` time; existing homes keep the old one-liner until
1271
+ edited. [affects: agents/*/agent.json]
1272
+
1273
+ ## [0.6.1]
1274
+
1275
+ ### Changed
1276
+
1277
+ - **Default HTTP port is now `3142`** (was `7331`) — `PORT` / `cognisphere
1278
+ serve --port` still override it. Updated everywhere the old default was
1279
+ baked in: `config.ts`, the CLI's `DEFAULT_PORT`, the web dev-server proxy
1280
+ target, the scaffold's `HARNESS_PORT` default, the seeded `agent-msg/send`
1281
+ fallback base URL, and the docs.
1282
+
1283
+ ### Breaking changes
1284
+
1285
+ - Existing homes pin `HARNESS_PORT=7331` in their `config`, so they keep
1286
+ serving on 7331 — but the re-seeded `scripts/agent-msg/send` now falls back
1287
+ to `127.0.0.1:3142`, which breaks agent-to-agent messaging. Either set
1288
+ `HARNESS_PORT=3142` in `config` (then re-run `scripts/setup-server.sh` to
1289
+ regenerate the systemd unit + nginx vhost, and restart), or keep 7331 and
1290
+ export `HARNESS_BASE_URL=http://127.0.0.1:7331` into the harness
1291
+ environment. [affects: config, scripts/setup-server.sh]
1292
+
1293
+ ## [0.6.0]
1294
+
1295
+ ### Added
1296
+
1297
+ - **gws thread routing.** The `gws` plugin now reads routing rules from
1298
+ `plugins/gws/state/routes.json` on every poll; the first rule whose
1299
+ `from` / `subject` patterns match an inbound thread replaces the default
1300
+ harness thread id (`<Subject>[<gmailThreadId>]`) with the rule's own
1301
+ `threadId`. Patterns are case-insensitive, unanchored regexes, so a plain
1302
+ string is a substring match. Lets an agent mail someone from a thread and
1303
+ have the reply land back in that same thread instead of opening a new one.
1304
+ - **`scripts/gws/routes` CLI** (seeded with the plugin): `add|list|remove`,
1305
+ atomic writes, rules take effect within one poll interval. A rule with
1306
+ neither `--from` nor `--subject` is rejected — it would capture every
1307
+ inbound email. Documented in the plugin's system prompt; existing homes
1308
+ pick both up automatically (the gws seed is re-copied on plugin start).
1309
+
1310
+ ## [0.5.1]
1311
+
1312
+ ### Added
1313
+
1314
+ - **Per-unit restart.** `scripts/server.sh` `start`/`stop`/`restart` now take an
1315
+ optional `app`|`harness` target to bounce a single systemd unit; omit it for
1316
+ both (the deploy loop is unchanged). `restart app` builds and restarts only
1317
+ the app unit — applying an app-only change without touching the harness.
1318
+ - **Developer agent ships app changes itself.** The dev-agent prompt now tells
1319
+ it to apply `app/` changes live via `sudo ./scripts/server.sh restart app`
1320
+ (its own session survives, since the app is a separate unit), and to leave
1321
+ harness restarts to the operator — restarting the harness would kill its own
1322
+ turn mid-run; the interrupted turn is requeued and swept back in on boot.
1323
+
1324
+ ### Breaking changes
1325
+
1326
+ *(No behavior breaks — both entries are on-disk artifacts an existing home must
1327
+ sync to adopt the feature; old copies keep working untouched.)*
1328
+
1329
+ - `scripts/server.sh` gained the optional `app`|`harness` restart target. [affects: scripts/server.sh]
1330
+ - The developer agent's `1-dev-agent.md` prompt gained the app-restart
1331
+ instructions (operator edits survive — re-seed or merge if customised). [affects: agents/*/system_prompts/1-dev-agent.md]
1332
+
1333
+ ## [0.5.0]
1334
+
1335
+ ### Added
1336
+
1337
+ - **Agent directory**: each agent now carries an `agent.json.description`
1338
+ (one-line role blurb). On start the harness seeds
1339
+ `system_prompts/0.3-agent-directory.md` — a roster of the *other* agents
1340
+ (id + description, how to message them) — if the file is absent, so operator
1341
+ edits survive. Single-agent harnesses skip it until a second agent exists.
1342
+ - **`PI_THREAD_ID`** is exported to the pi child's env (alongside
1343
+ `PI_AGENT_ID`), so seeded scripts know the current thread without being told.
1344
+
1345
+ ### Changed
1346
+
1347
+ - **agent-messaging identity is env-sourced, not caller-supplied.** The seeded
1348
+ `agent-msg/send` CLI now fills `from_agent`/`from_thread_id` from
1349
+ `$PI_AGENT_ID`/`$PI_THREAD_ID` — the `--from-agent`/`--from-thread-id` flags
1350
+ are gone. Agents can no longer typo or spoof their own reply address.
1351
+ - **agent-messaging inbox now authenticates.** `POST /webhook/<agent>/agent-messaging/api/send`
1352
+ requires the shared `COGNISPHERE_WEBHOOK_SECRET` (generated at boot unless
1353
+ pinned via env; inherited by every agent's env) as an `X-Webhook-Secret`
1354
+ header (`401` otherwise). Sender authorisation moved to a per-inbox
1355
+ `allowMessageFrom` plugin config (default `["*"]`; a sender not listed gets
1356
+ `403`), replacing the `PluginInstanceContext.allowsMessageFrom` method.
1357
+
1358
+ ### Breaking changes
1359
+
1360
+ - `agent.json.devAgentAccess` removed. It is now ignored; the `0.2-dev-agent.md`
1361
+ hand-off fragment is included for **every** agent, and messaging permission
1362
+ to the developer agent is governed solely by the dev agent's
1363
+ `allowMessageFrom`. Agents previously set to `devAgentAccess: false` will now
1364
+ see the dev-agent fragment and (unless restricted via `allowMessageFrom`) be
1365
+ able to message the developer agent. Remove the dead field; to restrict the
1366
+ dev inbox, set `allowMessageFrom` on its `agent-messaging` config. [affects: agents/*/agent.json, agents/*/plugins/agent-messaging/config.json]
1367
+ - Add a `description` to each `agent.json` so the agent-directory roster reads
1368
+ well (optional but recommended; absent ⇒ the agent is listed id-only). [affects: agents/*/agent.json]
1369
+
1370
+ ## [0.4.4]
1371
+
1372
+ ### Added
1373
+
1374
+ - **Developer agent**: `packages/harness/src/dev-agent/` is a persona
1375
+ overlay on the base template. `cognisphere agent new <name> --dev` forks the
1376
+ base + overlay, installs the cognisphere skills (`cognisphere-upgrade`,
1377
+ `create-plugin`) into the agent's own `skills/agent/`, and enables the
1378
+ telegram plugin (the dev agent's only channel); `cognisphere init`
1379
+ pre-creates the developer agent in every home (`--dev-agent <name>`,
1380
+ default `dory`). The chosen name is baked at create time into the
1381
+ `{{DevAgentId}}`/`{{DevAgentName}}` placeholders of `0.2-dev-agent.md`
1382
+ (every fork) and `1-dev-agent.md` (the dev fork). The developer agent
1383
+ owns and modifies the home's code (agents, user plugins, the app — never
1384
+ the installed harness library) and keeps `docs/harness/` + `docs/app/`
1385
+ current.
1386
+ - **Plugin-driven thread reset**: `PluginInstanceContext.resetThread(channelId)`
1387
+ deletes the thread's queue rows, session binding, and session files (refusing
1388
+ while a batch is in-flight), so the next message starts a fresh pi session.
1389
+ The telegram plugin intercepts a `/reset` message (never delivered to the
1390
+ agent) and calls it, replying with a confirmation.
1391
+ - **App-home docs + guidelines**: `home-template/` now ships `CLAUDE.md`
1392
+ (init copies it to `AGENT.md` too) and a `docs/` tree —
1393
+ `docs/base-harness/` (shipped user reference for the harness library +
1394
+ `skills.md`; init copies the package `CHANGELOG.md` in; refreshed by the
1395
+ upgrade skill), `docs/harness/` and `docs/app/` (deployment-owned, updated
1396
+ by the developer agent after every code change).
1397
+ - Base template: new `system_prompts/0.2-dev-agent.md` fragment — a
1398
+ **Platform code changes** section telling every non-developer agent to pass
1399
+ code-change requests to `dory`.
1400
+ - **Per-agent developer-agent access**: `agent.json.devAgentAccess` (default
1401
+ true). When false, the `0.2-dev-agent.md` fragment is omitted from the
1402
+ agent's system prompt and the developer agent's agent-messaging inbox
1403
+ rejects that agent's messages (403). `agent new --dev` stamps
1404
+ `devAgent: true` so the agent-messaging plugin knows which inbox to guard.
1405
+
1406
+ ### Changed
1407
+
1408
+ - Web build fix: dropped stale `manualChunks` entries (`framer-motion`,
1409
+ `remark-breaks`) left behind after those deps were removed — they broke
1410
+ `vite build` (and therefore `prepack`) under current Rollup.
1411
+ - Internal refactors, no intended behavior change: provider-credential
1412
+ handling extracted to `src/api/credentials.ts`; the AWS/Contabo setup
1413
+ scripts now share `scripts/lib/remote-bootstrap.sh`; assorted CLI, logger,
1414
+ and web-console cleanups.
1415
+
1416
+ ### Breaking changes
1417
+
1418
+ - base template: new system_prompts/0.2-dev-agent.md fragment (route code-change requests to the developer agent; omitted when agent.json devAgentAccess=false) — copy it into each agent and replace the `{{DevAgentId}}`/`{{DevAgentName}}` placeholders with the dev agent's id/name [affects: agents/*]
1419
+ - app home: new CLAUDE.md + AGENT.md + docs/{base-harness,harness,app}/ — copy from the package's home-template/, then copy the package CHANGELOG.md to docs/base-harness/CHANGELOG.md [affects: <home root>]
1420
+ - app home: create the developer agent with `cognisphere agent new <name> --dev` (conventional name: dory), then set secrets.json → <name>.telegram.TELEGRAM_BOT_TOKEN and a model provider [affects: agents/]
1421
+
1422
+ ## [0.4.3]
1423
+
1424
+ ### Changed
1425
+
1426
+ - **pi upgraded to 0.81.1** (`@earendil-works/pi-ai` +
1427
+ `@earendil-works/pi-coding-agent`, from 0.80.6). pi 0.80.8 removed the
1428
+ `AuthStorage` export the harness used for OAuth subscription login; the
1429
+ harness now drives login/logout through pi-coding-agent's `ModelRuntime`
1430
+ (one shared lazy instance) and reads stored credentials via
1431
+ `readStoredCredential`. Behavior parity: same routes, same polled
1432
+ status shapes, tokens still in pi's own `<piAgentDir>/auth.json`.
1433
+ Internally the login interaction moved to pi-ai's `AuthInteraction`
1434
+ (`prompt`/`notify`): select cancellation now rejects the prompt, and
1435
+ per-prompt abort signals (manual-code paste raced against the callback
1436
+ server) clear the pending waiter state.
1437
+
1438
+ ## [0.4.2]
1439
+
1440
+ ### Added
1441
+
1442
+ - **Contabo deploy target**: `scripts/contabo/setup.sh` + `config.example`
1443
+ (`cntb`-driven provision: object storage + backup bucket, SSH-key secret,
1444
+ Cloud VPS, `~/.ssh/config` entry, `ufw` in the remote bootstrap since
1445
+ Contabo has no security groups). Re-runnable; the first run places a paid
1446
+ monthly order. Prints the four `BACKUP_*` values for the root `config`.
1447
+ - `scripts/aws/backup.sh` now works against any S3-compatible store: new
1448
+ `BACKUP_S3_ENDPOINT` / `BACKUP_S3_ACCESS_KEY` / `BACKUP_S3_SECRET_KEY` keys
1449
+ in the root `config.example` (blank = AWS CLI chain / IAM role, as before).
1450
+
1451
+ ### Changed
1452
+
1453
+ - `scripts/server.sh start` is now the same as `restart` (secrets + build +
1454
+ `systemctl restart`, which also starts stopped units) — previously `start`
1455
+ on a running server was a silent no-op.
1456
+ - `scripts/setup-server.sh` retires units/nginx site/backup cron left behind
1457
+ by a previous `APP_NAME` (matched by `WorkingDirectory`) before writing the
1458
+ new ones, so renaming the app can't leave two instances fighting over the
1459
+ ports.
1460
+ - The `[0.4.0]` section below gained a breaking-change entry documenting the
1461
+ session-cwd migration gap (pi session JSONLs store the absolute harness
1462
+ path) and its rewrite recipe.
1463
+
1464
+ ### Breaking changes
1465
+
1466
+ - The scaffolded lifecycle scripts changed (`server.sh`, `setup-server.sh`,
1467
+ `aws/backup.sh`, root `config.example`). Existing app homes keep their
1468
+ copies; re-copy `scripts/` and graft the new `BACKUP_S3_*` keys into
1469
+ `config` to pick up the fixes. [affects: the app home's scripts/ + config.example (not the harness data dir)]
1470
+
1471
+ ## [0.4.1]
1472
+
1473
+ ### Changed
1474
+
1475
+ - The `Timestamp` field in every `<harness-metadata>` block now includes the
1476
+ day of week (e.g. `Fri 2026-04-17 14:30:05 IST`), for both incoming
1477
+ messages and continuation nudges. Base main-agent prompt example updated.
1478
+
1479
+ ### Breaking changes
1480
+
1481
+ - Seeded base main-agent prompt changed (`Timestamp` example now shows the
1482
+ weekday). Existing agents keep their provisioned copies; re-copy or graft
1483
+ from the new seed. [affects: agents/*/system_prompts/0.1-main-agent.md]
1484
+
1485
+ ## [0.4.0]
1486
+
1487
+ ### Changed
1488
+
1489
+ - **`cognisphere init <name>` now scaffolds an app home**, not a bare harness
1490
+ data dir: a pnpm workspace with the harness data dir at `harness/`, a
1491
+ user-facing app placeholder at `app/`, lifecycle scripts under `scripts/`
1492
+ (`setup-server.sh`, `server.sh`, `build.sh`), per-platform provisioning +
1493
+ backup under `scripts/<platform>/` (`scripts/aws/setup.sh`,
1494
+ `scripts/aws/backup.sh`, `scripts/aws/config.example`), and
1495
+ `config.example` at the root. AWS is
1496
+ the only supported deploy target for now (GWS and similar later). The agent
1497
+ skills are copied into the home root's `.claude/skills/` + `.agents/skills/`
1498
+ (not into `harness/`).
1499
+ - The CLI accepts either the harness data dir or the app home as cwd
1500
+ (`./harness` is resolved automatically).
1501
+ - The scaffolded `.npmrc` no longer embeds the `_authToken` line — pnpm
1502
+ refuses env-var credentials from a committed project `.npmrc`; the token
1503
+ belongs in the user's `~/.npmrc` (`scripts/setup-server.sh` writes it on a
1504
+ deployed box).
1505
+
1506
+ ### Removed
1507
+
1508
+ - **`cognisphere up` / `logs` / `status`** (the `cognisphere@<id>` systemd
1509
+ user service). Deployment is the scaffolded `scripts/` now:
1510
+ `sudo ./scripts/setup-server.sh` once, then
1511
+ `git pull && sudo ./scripts/server.sh restart`.
1512
+ - The `cognisphere-deploy` agent skill (superseded by the scaffolded deploy
1513
+ scripts).
1514
+
1515
+ ### Breaking changes
1516
+
1517
+ - Existing harness data dirs keep working as-is (the runtime layout is
1518
+ unchanged), but deployments that used `cognisphere up` must move to the
1519
+ scripted model: create a new app home with `cognisphere init`, move the old
1520
+ harness dir's contents into its `harness/`, then `cp config.example config`,
1521
+ edit, and run `sudo ./scripts/setup-server.sh`. Remove the old
1522
+ `cognisphere@<id>` systemd user unit. [affects: the whole harness dir]
1523
+ - **Moving/renaming the harness dir breaks resumption of existing pi
1524
+ sessions.** Every pi session JSONL records the absolute working directory
1525
+ it was created in (`"cwd": …` in its header line); on resume pi validates
1526
+ that path and exits 1 if it no longer exists (`Stored session working
1527
+ directory does not exist`), so every pre-migration thread fails on its next
1528
+ message while new threads work fine. After moving the old harness contents
1529
+ to the new path, rewrite the stored cwd in place (stop the harness first):
1530
+
1531
+ ```
1532
+ grep -rl '"cwd":"<OLD_HARNESS_PATH>' harness/agents/*/sessions/ \
1533
+ | xargs sed -i 's#<OLD_HARNESS_PATH>#<NEW_HARNESS_PATH>#g'
1534
+ ```
1535
+
1536
+ where the paths are the absolute old/new locations of the harness data dir
1537
+ (e.g. `/home/ubuntu/myapp/lps-harness` → `/home/ubuntu/myapp/harness`). [affects: agents/*/sessions/**/*.jsonl]
1538
+
1539
+ ## [0.3.16]
1540
+
1541
+ ### Added
1542
+
1543
+ - Every `<harness-metadata>` block now carries a `ThreadId` common field
1544
+ (after `Channel`), so agents can pass the routing id to plugin CLIs
1545
+ (`--thread-id`) without guessing it. `ThreadId` joined the reserved
1546
+ metadata keys — plugin-contributed values under that key are dropped.
1547
+ - Base main-agent prompt documents `ThreadId`: what it is, that it equals
1548
+ `{{ThreadId}}`, and that it is distinct from plugin-side ids (Telegram
1549
+ chat id, Gmail thread id).
1550
+
1551
+ ### Changed
1552
+
1553
+ - **agent-messaging: `POST …/api/send` now rejects requests missing
1554
+ `from_agent` or `from_thread_id` (400).** The seeded `agent-msg/send` CLI
1555
+ already required both, so only direct HTTP callers are affected.
1556
+ - agent-messaging: the `[AGENT MESSAGE] from …` header prepended to the
1557
+ delivered text is gone — the text is now the sender's message verbatim.
1558
+ Sender identity travels only in metadata (`From`, `FromThread`, optional
1559
+ `Subject`); the redundant `EventType`, `to`, and `thread` metadata keys
1560
+ were dropped. The seed prompt documents the metadata fields and the
1561
+ reply recipe.
1562
+ - telegram: dropped the redundant `ChatId` metadata key (always identical
1563
+ to the common `Channel` field). Seed prompt now points at `Channel`.
1564
+ - gws: dropped the redundant `GmailThreadId` (identical to `Channel`) and
1565
+ `ReceivedAtUtc` (same instant as `ReceivedAt`) metadata keys. Seed
1566
+ prompt updated accordingly, including its stale `ThreadId` bullet.
1567
+ - `create-plugin` agent skill: new "Event & metadata conventions" section
1568
+ (reserved/common fields, PascalCase rendering, when to emit `EventType`,
1569
+ identity-in-metadata vs content-in-text, seed-prompt sync rule) and a
1570
+ pnpm ≥ 10 `allowBuilds`/`better-sqlite3` gotcha.
1571
+
1572
+ ### Breaking changes
1573
+
1574
+ - Seeded base main-agent prompt changed (`ThreadId` documented in the
1575
+ message-metadata section). Existing agents keep their provisioned
1576
+ copies; re-copy or graft from the new seed. [affects: agents/*/system_prompts/0.1-main-agent.md]
1577
+
1578
+ ## [0.3.15]
1579
+
1580
+ ### Added
1581
+
1582
+ - New `create-plugin` agent skill: guides authoring a user-scope plugin in a
1583
+ harness's `plugins/<id>/` (contract, seed layout, per-agent enable/config,
1584
+ secrets, verification), with a tested hello-plugin template.
1585
+ - The package now bundles the harness-facing agent skills
1586
+ (`cognisphere-deploy`, `cognisphere-upgrade`, `create-plugin`) under
1587
+ `skills/` (prepack), and `cognisphere init` copies them into the new
1588
+ harness dir's `.claude/skills/` and `.agents/skills/` so agents working
1589
+ inside the harness discover them.
1590
+
1591
+ ### Breaking changes
1592
+
1593
+ - Existing harness dirs predate the bundled agent skills; copy them in: `cp -R node_modules/@cognisphere-sh/cognisphere-harness/skills/. .claude/skills/ && cp -R node_modules/@cognisphere-sh/cognisphere-harness/skills/. .agents/skills/` [affects: .claude/skills/]
1594
+
1595
+ ## [0.3.14]
1596
+
1597
+ ### Fixed
1598
+
1599
+ - gws and telegram seed prompts moved from `seed/system_prompt.md` (copied
1600
+ to the agent dir root, where `assembleSystemPrompt` never reads) to
1601
+ `seed/system_prompts/plugin-<id>.md` — the layout every other plugin uses.
1602
+ Until now, neither plugin's system-prompt fragment was ever included in
1603
+ the agent's assembled prompt. The fragments load automatically on next
1604
+ agent start (seeds are re-copied every start).
1605
+ - gws helper files (`format-email.ts`, `format-email-lib.mjs`,
1606
+ `format-email-lib.d.mts`) moved from loose `seed/scripts/` into the
1607
+ namespaced `seed/scripts/gws/`; the seeded `scripts/gws/format-email` CLI
1608
+ now imports the lib from its own directory.
1609
+
1610
+ ### Breaking changes
1611
+
1612
+ - gws/telegram seed prompt renamed `system_prompt.md` → `system_prompts/plugin-<id>.md`; delete the stale, never-read `system_prompt.md` at the agent dir root [affects: agents/*/system_prompt.md]
1613
+ - gws helper lib namespaced under `scripts/gws/`; delete the stale loose copies `format-email.ts`, `format-email-lib.mjs`, `format-email-lib.d.mts` directly under `scripts/` [affects: agents/*/scripts/format-email*]
1614
+
1615
+ ## [0.3.13]
1616
+
1617
+ ### Added
1618
+
1619
+ - New seeded pi extension `extensions/bash-guard.ts`: every agent `bash`
1620
+ command now runs under `set -u`, so a `$...` inside double quotes (e.g.
1621
+ `--text "costs $100"`, where bash silently expanded `$1` to nothing and
1622
+ sent "costs 00") fails loudly with an `unbound variable` error instead of
1623
+ silently corrupting CLI arguments. On that error, a quoting hint is
1624
+ appended to the tool result so the agent self-corrects. Agents can opt
1625
+ out per-command with `set +u`.
1626
+
1627
+ ### Changed
1628
+
1629
+ - Base system prompt: bash tool guidelines now tell agents to single-quote
1630
+ literal text arguments (or use a file / quoted heredoc `<<'EOF'`), and
1631
+ document that commands run under `set -u`.
1632
+
1633
+ ### Breaking changes
1634
+
1635
+ - New seeded file `extensions/bash-guard.ts`. Copy it from the new seed
1636
+ into existing agents. [affects: agents/*/extensions/*]
1637
+ - Bash tool guidelines section of the seeded base system prompt changed
1638
+ (single-quoting rule, `set -u` note). Graft into existing agents'
1639
+ `system_prompt.md`. [affects: agents/*/system_prompt.md]
1640
+
1641
+ ## [0.3.12]
1642
+
1643
+ ### Changed
1644
+
1645
+ - `telegram/telegram-cli`: `send-message`, `edit-message`, and `send-file`
1646
+ captions now auto-convert standard markdown (`**bold**`, `*italic*`,
1647
+ `` `code` ``, ``` blocks, links, headers, bullets) to Telegram HTML when
1648
+ no `--parse-mode` is passed; markdown tables render as column-aligned
1649
+ monospace `<pre>` blocks (Telegram has no table markup). If Telegram
1650
+ rejects the generated HTML, the message is automatically resent as plain
1651
+ text, so formatting can never drop a message. Explicit `--parse-mode`
1652
+ keeps the previous raw behavior.
1653
+ - Telegram seed prompt: agents are told to write plain markdown and not
1654
+ pass `--parse-mode`; removed the stale `--parse-mode Markdown` example.
1655
+
1656
+ ### Breaking changes
1657
+
1658
+ - Seeded `scripts/telegram/telegram-cli` changed (markdown→HTML
1659
+ auto-formatting). Existing agents keep their provisioned copies; re-copy
1660
+ from the new seed to pick it up. [affects: agents/*/scripts/telegram/*]
1661
+ - Telegram section of seeded system prompts changed (markdown guidance,
1662
+ removed `--parse-mode Markdown` example). Graft into existing agents'
1663
+ `system_prompt.md`. [affects: agents/*/system_prompt.md]
1664
+
1665
+ ## [0.3.11]
1666
+
1667
+ ### Changed
1668
+
1669
+ - Every seeded script now answers `-h`/`--help`: base-agent
1670
+ `scripts/agent/{subagent,agent-browser,ddgs,markitdown}` and plugin seeds
1671
+ `scheduler/scheduler-cli` (also bare `help`), `telegram/telegram-cli`
1672
+ (also bare `help`), and `agent-msg/send`. The three thin wrappers print a
1673
+ wrapper note (what they resolve, env knobs) and then forward to the
1674
+ underlying CLI's own help; `--help` exits 0 even when the underlying
1675
+ binary isn't installed yet. `session-reader` and `gws/format-email`
1676
+ already had `--help` and are unchanged.
1677
+ - Fixed: `scheduler-cli --help` (or any invocation from outside the agent
1678
+ dir) no longer aborts before printing — the state-file init ran before
1679
+ command parsing and `set -e` killed the script when
1680
+ `plugins/scheduler/state/` didn't exist.
1681
+
1682
+ ### Breaking changes
1683
+
1684
+ - Seeded scripts under `scripts/` changed (`--help` support). Existing
1685
+ agents keep their provisioned copies; graft the edits or re-copy from the
1686
+ new seeds to pick them up. [affects: agents/*/scripts/*]
1687
+
1688
+ ## [0.3.10]
1689
+
1690
+ ### Added
1691
+
1692
+ - Optional per-provider `modelOverrides` in `.secrets/models.json`
1693
+ (`{ "<modelId>": { "contextWindow"?, "maxTokens"? } }`), layered over
1694
+ pi-ai's built-in catalog and used for context-window reporting
1695
+ (`lastContext.contextWindow` in the threads-list and usage endpoints —
1696
+ an override wins over the registry). Accepted and returned by
1697
+ `PUT/GET /api/models` (`null` per model deletes the entry). Existing
1698
+ configs without the field are unchanged.
1699
+
1700
+ ## [0.3.9]
1701
+
1702
+ ### Changed
1703
+
1704
+ - Base-agent template prompts: per-thread notes move to
1705
+ `workspace/threads/<ThreadId>/` (bare ThreadId as dir name), new
1706
+ `workspace/daily_notes/YYYY-MM-DD.md` convention, cross-thread knowledge
1707
+ relocated from `workspace/knowledge/` to agent-root `knowledge/`, and
1708
+ `session-reader` documented as directly executable (invoking it via `bash`
1709
+ fails — it's a Node script).
1710
+
1711
+ ### Breaking changes
1712
+
1713
+ - Base template `system_prompts/0-base_prompt.md` and `0.1-main-agent.md`
1714
+ changed (workspace layout + knowledge dir + session-reader invocation).
1715
+ Existing agents keep their forked copies; graft the edits if you want the
1716
+ new conventions. [affects: agents/*/system_prompts/*]
1717
+
1718
+ ## [0.3.8]
1719
+
1720
+ ### Added
1721
+
1722
+ - New built-in `agent-messaging` plugin (opt-in): inter-/intra-agent messaging.
1723
+ Each enabled agent gets an HTTP inbox at
1724
+ `/webhook/<agent>/agent-messaging/api/send` and a seeded
1725
+ `scripts/agent-msg/send` CLI; a received note wakes the target agent on the
1726
+ target thread (`silent` delivers for awareness only).
1727
+
1728
+ ### Changed
1729
+
1730
+ - Upgraded `@earendil-works/pi-ai` and `@earendil-works/pi-coding-agent` from
1731
+ `^0.78.0` to `^0.80.6` (switched the static catalog read to
1732
+ `getBuiltinModel` from `@earendil-works/pi-ai/providers/all`).
1733
+ - Plugin seed provisioning now re-asserts `chmod 755` on every file under the
1734
+ agent's `scripts/` after copying a plugin's `seed/` tree. Seeds land after
1735
+ `bootstrap.sh`'s exec-bit repair pass, so a seeded script that lost its exec
1736
+ bit would otherwise stay broken until the next restart.
1737
+
1738
+ ## [0.3.6]
1739
+
1740
+ ### Changed
1741
+
1742
+ - gws plugin: `requireAgentInTo: false` now delivers messages the agent isn't
1743
+ addressed to (Cc/Bcc/none) **in full and wakes the agent**, instead of the
1744
+ previous header-only silent delivery. Backlog mode is unaffected.
1745
+
1746
+ ## [0.3.5]
1747
+
1748
+ ### Fixed
1749
+
1750
+ - Agents were missing tools at runtime because the per-agent bootstrap silently
1751
+ failed to install its dependencies. `bootstrap.sh` now:
1752
+ - re-asserts `+x` on every shebang script under `scripts/` (a dropped exec bit
1753
+ otherwise surfaces as a bare "Permission denied" mid-task);
1754
+ - prechecks `ensurepip` and recreates an incomplete `.venv` (Ubuntu 26.04 /
1755
+ Python 3.14 ships without `python3-venv`, so `python -m venv` left a
1756
+ pip-less venv and `markitdown`/`ddgs` never installed);
1757
+ - points the npm global prefix at `~/.npm-global` so `npm install -g` of `pi`
1758
+ and `agent-browser` doesn't `EACCES` when bootstrap runs as the non-root app
1759
+ user, and downloads the Chrome build `agent-browser` drives.
1760
+ - `bootstrap/requirements.txt`: pin `markitdown` to the document/audio backends
1761
+ (`[pdf,docx,pptx,xlsx,xls,outlook,audio-transcription]`) instead of `[all]`,
1762
+ which is uninstallable on Python 3.14 (it hard-pins `youtube-transcript-api`).
1763
+ - `scripts/agent/agent-browser`: default `AGENT_BROWSER_ARGS=--no-sandbox`
1764
+ (overridable) so Chrome starts on hosts where unprivileged user namespaces are
1765
+ restricted (Ubuntu 23.10+ AppArmor default, containers, VMs).
1766
+
1767
+ ### Breaking changes
1768
+
1769
+ - Bootstrap rewritten for reliable dependency install (exec-bit repair, venv
1770
+ ensurepip precheck + recreate, user-writable npm prefix, agent-browser Chrome
1771
+ download). [affects: agents/*/bootstrap/bootstrap.sh]
1772
+ - `markitdown` extras pinned instead of `[all]` for Python 3.14 compatibility.
1773
+ [affects: agents/*/bootstrap/requirements.txt]
1774
+ - `agent-browser` wrapper defaults to `--no-sandbox`.
1775
+ [affects: agents/*/scripts/agent/agent-browser]
1776
+
1777
+ ## [0.3.4]
1778
+
1779
+ ### Added
1780
+
1781
+ - gws plugin: new `requireAgentInTo` config flag (default `true`, the previous
1782
+ behavior). When `false`, the latest message of a matching thread is delivered
1783
+ even when the agent's address is not in its `To` header — silently (no wake)
1784
+ unless the agent is in `To`. Ignored in backlog mode.
1785
+ - gws seeded CLI `scripts/gws/format-email`: new `--strip-quotes` flag drops
1786
+ quoted reply history from a body (most clients quote the whole conversation
1787
+ below each reply), printing only the message's own text.
1788
+ - gws seeded CLI: new `--list` mode accepts a Gmail *Thread* JSON (from
1789
+ `gws gmail users threads get`, `format: "metadata"` suffices) and prints
1790
+ per-message metadata (id, from, date, snippet) so agents can skim a thread
1791
+ cheaply and then fetch only the messages they need. The seeded
1792
+ `system_prompt.md` documents the explore-then-fetch workflow.
1793
+
1794
+ ### Changed
1795
+
1796
+ - gws plugin: the ingestion filter no longer re-checks the `UNREAD` label on a
1797
+ thread's latest message — unread filtering is delegated entirely to the
1798
+ configured `gmailQuery` (default `is:unread in:inbox`).
1799
+ - gws plugin: Gmail message decoding (body extraction, quote stripping,
1800
+ attachment fetch, timestamp formatting) is deduplicated into a single shared
1801
+ module, `seed/scripts/format-email-lib.mjs`, imported by both the plugin
1802
+ runtime and the seeded `scripts/gws/format-email` CLI (which previously
1803
+ carried its own copy of the logic).
1804
+
1805
+ ### Fixed
1806
+
1807
+ - gws seeded CLI: the documented `--timezone` flag was parsed but never used —
1808
+ the header block now includes the `TimeStamp:` line, matching the shape of
1809
+ `email_received` notifications as documented.
1810
+
1811
+ ## [0.3.3]
1812
+
1813
+ ### Fixed
1814
+
1815
+ - Sub-agents could receive a single task brief as dozens of phantom one-word
1816
+ messages. The `subagent` wrapper passed the brief as a positional argv entry,
1817
+ and `pi -p` treats every positional as a separate user turn. A literal
1818
+ unescaped quote inside the brief (e.g. a pasted email body like
1819
+ `Message: "Hi Chris, ..."`) let the shell word-split the single intended arg
1820
+ into many argv entries, each replayed as its own message. The wrapper now
1821
+ routes the brief to `pi` on **stdin** (`pi -p` reads its prompt from stdin
1822
+ when no positional message is given), so quoting inside the brief can no
1823
+ longer fan out into phantom turns. Flags still pass through argv verbatim and
1824
+ the caller interface is unchanged (`subagent "<brief>" --flags`).
1825
+
1826
+ ### Changed
1827
+
1828
+ - Base prompt now tells agents to keep `workspace/` for what must persist:
1829
+ write intermediate/throwaway files under `/tmp` (or delete them), and don't
1830
+ copy plugin inbox input files into `workspace/` unless they genuinely need to
1831
+ outlive the inbox.
1832
+
1833
+ ### Breaking changes
1834
+
1835
+ - `subagent` wrapper now passes the task brief to `pi` on stdin instead of as a
1836
+ positional argument. [affects: agents/*/scripts/agent/subagent]
1837
+ - Base prompt adds workspace-hygiene guidance (intermediate files to `/tmp`;
1838
+ don't copy inbox inputs into `workspace/` unless persisting).
1839
+ [affects: agents/*/system_prompts/0-base_prompt.md]
1840
+
1841
+ ## [0.3.2]
1842
+
1843
+ ### Fixed
1844
+
1845
+ - Sub-agents lost their system prompt on resume (`-c`/`--continue`). The
1846
+ `subagent` wrapper skipped re-injecting the base + sub-agent-role prompt on
1847
+ continue, assuming pi had persisted it — but pi never writes the system
1848
+ prompt to the session JSONL, so resumed sub-agents fell back to pi's default
1849
+ identity. The wrapper now concatenates `0-base_prompt.md` +
1850
+ `sub-agent-prompt.md` into a single `--system-prompt` value (replace, not
1851
+ `--append-system-prompt`, so pi's default doesn't leak in) and sets it on
1852
+ every call including `-c`. The task-specific brief now goes in the **message**
1853
+ (positional arg) instead of `--system-prompt`, so it lives in session history
1854
+ and survives re-invocation. The main-agent prompt was updated to match.
1855
+
1856
+ ### Breaking changes
1857
+
1858
+ - `subagent` wrapper rewrites system-prompt handling: concatenates base +
1859
+ sub-agent role into one `--system-prompt`, set on every call (incl. `-c`).
1860
+ [affects: agents/*/scripts/agent/subagent]
1861
+ - Main-agent prompt now instructs putting the sub-agent task brief in the
1862
+ message, never passing `--system-prompt`.
1863
+ [affects: agents/*/system_prompts/0.1-main-agent.md]
1864
+
1865
+ ## [0.3.1]
1866
+
1867
+ ### Added
1868
+
1869
+ - On first start the server prompts for an admin username/password when
1870
+ `.secrets/users.json` is missing or still holds the `admin/changeme`
1871
+ placeholder and stdin is a TTY, writing the file `0600`. Under systemd (no
1872
+ TTY) it logs a warning and falls back to the placeholder so boot still
1873
+ succeeds. (`ensureCredentials` in `api/auth.ts`, wired in `core/main.ts`.)
1874
+
1875
+ ## [0.3.0]
1876
+
1877
+ ### Changed
1878
+
1879
+ - **Base-agent system prompt split into three role-scoped parts** to remove the
1880
+ duplication that arose when sub-agents were handed a hand-copied harness
1881
+ prompt:
1882
+ - `0-base_prompt.md` is now the **shared base** — the operating manual (tools,
1883
+ files, workspace, sessions, web, browser) common to every agent. It no
1884
+ longer carries agent identity or main-agent-only framing.
1885
+ - `0.1-main-agent.md` (new) holds the **main-agent-only** role: threads,
1886
+ plugins, message metadata, the communication model, and the guide on how to
1887
+ spawn sub-agents (merged in from the old `0.1-subagents.md`).
1888
+ - `scripts/agent/sub-agent-prompt.md` (new) holds the **sub-agent-only** role
1889
+ ("stdout is your return value", include all relevant info, ask when the
1890
+ brief is ambiguous, stay scoped). It lives outside `system_prompts/` so it
1891
+ never leaks into the main agent's concatenated prompt.
1892
+ - The `scripts/agent/subagent` wrapper now appends the base prompt + sub-agent
1893
+ prompt to every fresh sub-agent via `--append-system-prompt` (skipped on
1894
+ `-c`/`--continue`). Sub-agents get the same harness context as the main agent
1895
+ on top of the parent's task brief, so the parent's `--system-prompt` only
1896
+ needs to carry the task-specific brief.
1897
+ - Agent identity (`AgentId`, `AgentName`) moved out of the base prompt into the
1898
+ hand-written `1-agent.md` persona. The only remaining sed-baked `{{var}}`
1899
+ (`Timezone`) is now baked into `0.1-main-agent.md`.
1900
+
1901
+ ### Breaking changes
1902
+
1903
+ - Base prompt repurposed and identity removed: `0-base_prompt.md` is now the
1904
+ shared base context only; agent identity moves to the `1-agent.md` persona.
1905
+ [affects: agents/*/system_prompts/0-base_prompt.md, agents/*/system_prompts/1-agent.md]
1906
+ - New main-agent-only prompt; `0.1-subagents.md` removed (its content merged in).
1907
+ [affects: agents/*/system_prompts/0.1-main-agent.md, agents/*/system_prompts/0.1-subagents.md]
1908
+ - New sub-agent-only role prompt, appended to sub-agents by the wrapper.
1909
+ [affects: agents/*/scripts/agent/sub-agent-prompt.md]
1910
+ - `subagent` wrapper updated to append the base + sub-agent prompts on fresh spawns.
1911
+ [affects: agents/*/scripts/agent/subagent]
1912
+
1913
+ ## [0.2.1]
1914
+
1915
+ ### Fixed
1916
+
1917
+ - Core plugins (`admin`, `scheduler`) are now always started on every agent,
1918
+ unioned with any user-installed plugins — previously a freshly scaffolded
1919
+ agent loaded no plugins at all (the operator-chat `admin` channel included),
1920
+ since the base-agent template ships no `plugins/` dir. Single source of truth
1921
+ is `CORE_PLUGIN_IDS` in `core/plugin-registry.ts`.
1922
+ - `bootstrap.sh` now runs automatically on every agent start (`runBootstrap`
1923
+ in `startAgent`, before the runner spawns) — provisions system deps + the
1924
+ per-agent `.venv` so the runner can activate it. Idempotent, awaited, and
1925
+ failure-tolerant (logged, never sinks the agent); no-op when the agent ships
1926
+ no `bootstrap/bootstrap.sh`. Cost: first boot blocks on `pip install`.
1927
+ - Plugin `seed/` provisioning: on plugin start, a plugin's `seed/` tree is
1928
+ recursively copied into the agent dir (mirrors the agent layout —
1929
+ `system_prompts/plugin-<id>.md`, `scripts/<id>/…`), so the agent actually
1930
+ receives each plugin's system-prompt fragment and helper CLIs (e.g. the
1931
+ scheduler's `scheduler-cli`). Previously the seed content was never copied,
1932
+ so those prompts/scripts never reached the agent.
1933
+ - `cognisphere init` now pre-approves `better-sqlite3` in the scaffolded
1934
+ `package.json` (`pnpm.onlyBuiltDependencies`), so `pnpm install` builds its
1935
+ native addon instead of silently skipping it (which crashed agent boot with
1936
+ "Could not locate the bindings file").
1937
+
1938
+ ## [0.2.0]
1939
+
1940
+ ### Added
1941
+
1942
+ - **`cognisphere` CLI** (`packages/harness/src/cli/`, bin shim `bin/cognisphere.mjs`):
1943
+ `init`, `agent new`, `plugin add`, `dev`, `serve`, `up`/`logs`/`status`
1944
+ (systemd user services), and `upgrade`. `dev` runs the backend (watch) and,
1945
+ in the monorepo, the Vite dev server (HMR) together (`--port`/`--web-port`/
1946
+ `--no-web`); `serve` takes `--port` and `--headless` (mount no web UI —
1947
+ backend-only deploy, via `COGNISPHERE_HEADLESS`). See
1948
+ [`docs/distribution-and-deployment.md`](docs/distribution-and-deployment.md) §10.
1949
+ - **Publishable package.** `@cognisphere-sh/cognisphere-harness` ships a `bin`, a
1950
+ `files` allowlist, `publishConfig` (GitHub Packages), and a `prepack` step that
1951
+ bundles the built web UI (`dist-web/`) and the root `CHANGELOG.md` into the
1952
+ package. `tsx` is now a runtime dependency.
1953
+ - **`harness.json.version`** — the data/migration version stamp, written by
1954
+ `cognisphere init` and surfaced over `GET /api/harness`. Additive and optional;
1955
+ existing harnesses read it as `""`.
1956
+ - **Upgrade & deploy skills** (`.claude/skills/cognisphere-{upgrade,deploy}/`).
1957
+
1958
+ ### Changed
1959
+
1960
+ - Repository restructured into a pnpm workspace with two packages:
1961
+ `packages/harness` (`@cognisphere-sh/cognisphere-harness` — backend; all
1962
+ TypeScript source under `src/` (`core/`, `api/`, `cli/`, `plugins/`,
1963
+ `base-agent/`), with `bin/` + `scripts/` at the package root) and
1964
+ `packages/web` (the React UI). Tooling moved to pnpm; `pnpm check` runs
1965
+ typecheck + lint across both packages. No on-disk harness artifacts are
1966
+ affected — this is a source-layout change only.
1967
+
1968
+ ## [0.1.0]
1969
+
1970
+ - Initial version.