mercury-agent 0.16.0 → 0.16.2
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.
- package/README.md +6 -0
- package/container/Dockerfile +6 -1
- package/container/Dockerfile.base +6 -1
- package/docs/README.md +50 -0
- package/docs/authoring-profiles.md +8 -0
- package/docs/behavior-layers.md +193 -0
- package/docs/extensions.md +2 -0
- package/docs/goals/football-reporter-profile/decisions.md +479 -0
- package/docs/goals/football-reporter-profile/goal.md +91 -0
- package/docs/goals/football-reporter-profile/roadmap.md +196 -0
- package/docs/goals/whatsapp-bot-hardening/README.md +43 -0
- package/docs/goals/whatsapp-bot-hardening/archive/ambient-group-context.md +211 -0
- package/docs/goals/whatsapp-bot-hardening/archive/command-routing-consistency.md +210 -0
- package/docs/goals/whatsapp-bot-hardening/archive/destructive-command-guards.md +218 -0
- package/docs/goals/whatsapp-bot-hardening/archive/docs-extension.md +182 -0
- package/docs/goals/whatsapp-bot-hardening/archive/handoff-2026-08-09.md +588 -0
- package/docs/goals/whatsapp-bot-hardening/archive/media-size-and-silent-drop.md +178 -0
- package/docs/goals/whatsapp-bot-hardening/archive/member-memory.md +199 -0
- package/docs/goals/whatsapp-bot-hardening/archive/message-author-attribution.md +211 -0
- package/docs/goals/whatsapp-bot-hardening/archive/run-from-source-switchover.md +212 -0
- package/docs/goals/whatsapp-bot-hardening/archive/setup-plan-2026-08-06.md +1117 -0
- package/docs/goals/whatsapp-bot-hardening/decisions.md +200 -0
- package/docs/goals/whatsapp-bot-hardening/goal.md +75 -0
- package/docs/goals/whatsapp-bot-hardening/open-threads.md +396 -0
- package/docs/goals/whatsapp-bot-hardening/roadmap.md +245 -0
- package/docs/memory.md +30 -0
- package/docs/profile-guide.md +483 -0
- package/docs/refactor/.gitkeep +0 -0
- package/docs/refactor/archive/.gitkeep +0 -0
- package/docs/refactor/audits/.gitkeep +0 -0
- package/docs/refactor/backlog/.gitkeep +0 -0
- package/docs/skills-guide.md +154 -0
- package/examples/extensions/README.md +1 -0
- package/examples/extensions/feed-watch/config.ts +354 -0
- package/examples/extensions/feed-watch/digest.ts +344 -0
- package/examples/extensions/feed-watch/feeds.ts +341 -0
- package/examples/extensions/feed-watch/index.ts +302 -0
- package/examples/extensions/feed-watch/items.ts +171 -0
- package/examples/extensions/feed-watch/match.ts +107 -0
- package/examples/extensions/feed-watch/prompts/verify.md +35 -0
- package/examples/extensions/feed-watch/skill/SKILL.md +128 -0
- package/examples/extensions/feed-watch/watch.ts +548 -0
- package/examples/extensions/longview/hook.ts +179 -16
- package/examples/extensions/longview/index.ts +13 -2
- package/examples/extensions/longview/prompts/summarize.md +3 -2
- package/examples/extensions/longview/render/telegraph-nodes.ts +21 -1
- package/examples/extensions/longview/summarize.ts +57 -14
- package/examples/extensions/napkin/index.ts +334 -86
- package/examples/extensions/napkin/pi-spawn.ts +196 -0
- package/examples/extensions/pinchtab/index.ts +37 -4
- package/examples/extensions/pinchtab/lib/session-injector.ts +31 -9
- package/examples/extensions/pinchtab/skill/SKILL.md +29 -0
- package/examples/profiles/_template/AGENTS.md +138 -0
- package/examples/profiles/_template/README.md +65 -0
- package/examples/profiles/_template/config.yaml +57 -0
- package/examples/profiles/_template/tasks/daily.md +32 -0
- package/examples/profiles/football-reporter/AGENTS.md +219 -0
- package/examples/profiles/football-reporter/README.md +138 -0
- package/examples/profiles/football-reporter/config.yaml +174 -0
- package/examples/profiles/football-reporter/seed/MEMORY.md +42 -0
- package/examples/profiles/football-reporter/seed/episodes/barcelona-2026-27.md +25 -0
- package/examples/profiles/football-reporter/seed/episodes/beitar-jerusalem-2026-27.md +25 -0
- package/examples/profiles/football-reporter/seed/episodes/maccabi-haifa-2026-27.md +24 -0
- package/examples/profiles/football-reporter/seed/episodes/man-united-2026-27.md +26 -0
- package/examples/profiles/football-reporter/seed/episodes/real-madrid-2026-27.md +25 -0
- package/examples/profiles/football-reporter/seed/napkin-distill.md +55 -0
- package/examples/profiles/football-reporter/tasks/daily-article.md +142 -0
- package/package.json +8 -5
- package/src/adapters/whatsapp.ts +75 -13
- package/src/bridges/whatsapp.ts +6 -4
- package/src/cli/mrctl.ts +9 -1
- package/src/core/handler.ts +51 -6
- package/src/core/routes/dashboard.ts +106 -5
- package/src/core/routes/tasks.ts +28 -0
- package/src/core/runtime.ts +63 -2
- package/src/core/task-scheduler.ts +103 -12
- package/src/extensions/catalog.ts +9 -0
- package/src/profile/space-profile.ts +780 -0
- package/src/storage/db.ts +215 -0
- package/src/types.ts +56 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# Deployment Switchover — Run the Bot from the Git Checkout
|
|
2
|
+
|
|
3
|
+
**Status**: Done
|
|
4
|
+
**Slug**: run-from-source-switchover
|
|
5
|
+
**Goal**: whatsapp-bot-hardening
|
|
6
|
+
**Milestone**: 1
|
|
7
|
+
**Created**: 2026-08-09
|
|
8
|
+
**Last updated**: 2026-08-09
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Goal
|
|
13
|
+
|
|
14
|
+
> Part of goal [whatsapp-bot-hardening](../goals/whatsapp-bot-hardening/goal.md).
|
|
15
|
+
|
|
16
|
+
The live service currently runs the npm-installed 0.8.12 package, which was
|
|
17
|
+
hand-patched (pinchtab fixes) and can be silently reverted by any `npm i -g`.
|
|
18
|
+
Every fix in this goal must be testable edit→restart and version-controlled, so
|
|
19
|
+
the service switches to `~/mercury-src` (v0.9.0 + branch) via `npm link`
|
|
20
|
+
(D-001). This story also commits the only fix that exists in **no commit
|
|
21
|
+
anywhere**: the `.dockerignore` negation that makes `container/Dockerfile:118`'s
|
|
22
|
+
`COPY examples/extensions/` actually copy something.
|
|
23
|
+
|
|
24
|
+
## User Stories
|
|
25
|
+
|
|
26
|
+
- As the operator, I want the live bot to run the code in `~/mercury-src` so
|
|
27
|
+
that every fix I write is immediately testable and cannot be reverted by an
|
|
28
|
+
npm upgrade.
|
|
29
|
+
- As the operator, I want a verified sub-minute rollback path so that a bad
|
|
30
|
+
0.9.0 migration or startup failure doesn't take the bot down for long.
|
|
31
|
+
|
|
32
|
+
## MVP Scope
|
|
33
|
+
|
|
34
|
+
**In scope:** DB backup, `bun install` + check gate, `npm link`, service
|
|
35
|
+
reinstall + `Restart=always` re-application, restart, live verification,
|
|
36
|
+
committing the `.dockerignore` edit.
|
|
37
|
+
|
|
38
|
+
**Out of scope:** removing the npm-installed 0.8.12 — it *is* the rollback
|
|
39
|
+
path; upgrading any dependency versions — this is a switchover, not an upgrade.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Context for Claude
|
|
44
|
+
|
|
45
|
+
- `HANDOFF.md` §1 (operating rules) and §3 (switchover procedure + gotchas) —
|
|
46
|
+
the authoritative procedure; follow it exactly.
|
|
47
|
+
- `~/mercury-src/.dockerignore` — has the uncommitted local edit
|
|
48
|
+
(`!examples/extensions` + `!examples/extensions/**`); verify present, commit it.
|
|
49
|
+
- `~/.config/systemd/user/mercury.service` — live unit; hand-modified to
|
|
50
|
+
`Restart=always`, which `service install` will revert to `on-failure`.
|
|
51
|
+
- `~/whatsapp-bot/.mercury/state.db{,-wal,-shm}` — live DB; the ~4 MB WAL means
|
|
52
|
+
all three files must be backed up (a restart checkpoints it).
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Architecture & Data
|
|
57
|
+
|
|
58
|
+
### Data Models
|
|
59
|
+
|
|
60
|
+
No schema written by this story — but the **0.9.0 `db.ts` migration runs on
|
|
61
|
+
first start** against the existing state.db. That migration is the entire
|
|
62
|
+
reason the backup step is mandatory, not superstition.
|
|
63
|
+
|
|
64
|
+
### API Contracts
|
|
65
|
+
|
|
66
|
+
None.
|
|
67
|
+
|
|
68
|
+
### File & Folder Structure
|
|
69
|
+
|
|
70
|
+
| Path | New / Modified | Purpose |
|
|
71
|
+
|------|---------------|---------|
|
|
72
|
+
| `~/mercury-src/.dockerignore` | Modified (commit existing edit) | Re-include `examples/extensions/**` so the image build copies bundled extensions |
|
|
73
|
+
| `~/.config/systemd/user/mercury.service` | Regenerated + hand-edit | Points at the linked CLI; `Restart=always` re-applied |
|
|
74
|
+
| `~/mercury-backup-<ts>/` | New | DB backup (3 files) |
|
|
75
|
+
|
|
76
|
+
### Implementation Sequence
|
|
77
|
+
|
|
78
|
+
All commands run inside WSL (`wsl.exe -e bash -lc '…' | tr -d '\0'`) with the
|
|
79
|
+
PATH prefix `export PATH=$HOME/.nvm/versions/node/v24.19.0/bin:$HOME/.bun/bin:$PATH`.
|
|
80
|
+
|
|
81
|
+
1. Commit the `.dockerignore` fix on the branch.
|
|
82
|
+
- Read first: `~/mercury-src/.dockerignore` (verify the two negation lines
|
|
83
|
+
are still present and uncommitted: `git status`)
|
|
84
|
+
- Verify: `git log -1 --stat` shows the commit; `git status` clean for that file.
|
|
85
|
+
2. Back up the DB — `mkdir -p ~/mercury-backup-$(date +%s) && cp
|
|
86
|
+
~/whatsapp-bot/.mercury/state.db{,-wal,-shm} ~/mercury-backup-*/`.
|
|
87
|
+
- Read first: nothing (do **not** open the DB)
|
|
88
|
+
- Verify: three files exist in the backup dir with plausible sizes.
|
|
89
|
+
3. `cd ~/mercury-src && bun install && bun run check`.
|
|
90
|
+
- Read first: nothing
|
|
91
|
+
- Verify: check gate green. **Blocker: do not proceed on red.**
|
|
92
|
+
4. `npm link` in `~/mercury-src`, then `cd ~/whatsapp-bot && mercury service
|
|
93
|
+
install --user` — run from a shell with the PATH prefix set (the unit bakes
|
|
94
|
+
`Environment=PATH=` from the install shell).
|
|
95
|
+
- Read first: `HANDOFF.md` §3 gotchas
|
|
96
|
+
- Verify: `which mercury` resolves through `~/mercury-src`; unit file's
|
|
97
|
+
`Environment=PATH=` contains the nvm + bun bins.
|
|
98
|
+
5. Re-apply `Restart=always` in the regenerated unit (install reverts it to
|
|
99
|
+
`on-failure`), `systemctl --user daemon-reload`, then
|
|
100
|
+
`systemctl --user restart mercury`.
|
|
101
|
+
- Read first: `~/.config/systemd/user/mercury.service`
|
|
102
|
+
- Verify: `systemctl --user show mercury -p Restart` → `always`; journal
|
|
103
|
+
shows clean startup incl. the db migration; no error lines.
|
|
104
|
+
6. Live verification: send a WhatsApp DM; confirm the reply, then confirm the
|
|
105
|
+
serving model from the DB (no `sqlite3` installed — use `bun -e` with
|
|
106
|
+
`bun:sqlite`): `SELECT model, provider FROM token_usage ORDER BY id DESC LIMIT 1`.
|
|
107
|
+
- Read first: nothing
|
|
108
|
+
- Verify: reply received; expected model/provider row. Note: the derived
|
|
109
|
+
Docker image may rebuild in the background — early replies may be slow;
|
|
110
|
+
that is not a failure.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Non-Negotiable Rules
|
|
115
|
+
|
|
116
|
+
- Backup **before** first 0.9.0 start — the db.ts migration is one-way.
|
|
117
|
+
- Leave the npm-installed 0.8.12 untouched (rollback path).
|
|
118
|
+
- Never `mercury run` directly; never kill by port.
|
|
119
|
+
- Never Read `~/whatsapp-bot/.env`.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Edge Cases & Risks
|
|
124
|
+
|
|
125
|
+
| Scenario | Handling |
|
|
126
|
+
|----------|---------|
|
|
127
|
+
| Migration fails / bot won't start on 0.9.0 | `npm unlink` in `~/mercury-src`, restore old unit, restore DB from backup, restart — rollback is <1 min |
|
|
128
|
+
| Unit installed from a shell with stale PATH | Unit can't find bun/node → containers never spawn. Check `Environment=PATH=` in the unit before restarting |
|
|
129
|
+
| `service install` silently reverts `Restart=always` | Step 5 explicitly re-applies it; verified via `systemctl show` |
|
|
130
|
+
| Derived image rebuild on first start | Expected (content-hash changed); background, non-blocking |
|
|
131
|
+
| Messages sent while service is down | Baileys drops them — known behaviour, keep the restart window short |
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Implementation Checklist
|
|
136
|
+
|
|
137
|
+
### Phase 1 — Goal (fill before asking for approval)
|
|
138
|
+
- [x] Goal, User Stories, and MVP Scope written and reviewed
|
|
139
|
+
|
|
140
|
+
### Phase 2 — Architecture (fill after Goal approved)
|
|
141
|
+
- [x] Architecture & Data section complete
|
|
142
|
+
- [x] Non-Negotiable Rules defined
|
|
143
|
+
- [x] Edge Cases covered
|
|
144
|
+
- [x] Context for Claude pointers filled in
|
|
145
|
+
|
|
146
|
+
### Implementation (tick off as you go)
|
|
147
|
+
- [x] `.dockerignore` fix committed — `5eba5b0`
|
|
148
|
+
- [x] DB backed up (3 files) — `~/mercury-backup-1786307535/` (+ the old unit file)
|
|
149
|
+
- [x] `bun run check` passes in `~/mercury-src` — 1333 pass / 0 fail (needed `9fc8f91`, see retrospective)
|
|
150
|
+
- [x] Service repointed at the checkout, `Restart=always` preserved
|
|
151
|
+
- [x] Pipeline verified (`mercury chat` → `SWITCHOVER_OK`) + model confirmed via `token_usage` (`claude-opus-5` / `anthropic`)
|
|
152
|
+
- [x] No secrets or `.env` files committed
|
|
153
|
+
- [x] No unrelated files modified
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Open Questions
|
|
158
|
+
|
|
159
|
+
- [ ] none
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Retrospective
|
|
164
|
+
|
|
165
|
+
**Residual risks / follow-ups:**
|
|
166
|
+
- `~/.bun/bin/bunx` was missing and is now a hand-made symlink; a bun reinstall
|
|
167
|
+
may or may not recreate it — accepted (one-line fix, documented here).
|
|
168
|
+
- The stray `~/.mercury/state.db` housekeeping item from HANDOFF §5.5 is not
|
|
169
|
+
part of this story — deferred to the pre-PR checklist in `roadmap.md`.
|
|
170
|
+
- `git config core.fileMode false` is set locally so the exec bits below don't
|
|
171
|
+
dirty the tree — accepted (no intentional mode changes are planned).
|
|
172
|
+
|
|
173
|
+
**What changed from the plan:**
|
|
174
|
+
- **`bun run check` was red before I changed anything.** `bunx` was not present
|
|
175
|
+
in `~/.bun/bin`, so it resolved to the *Windows* npm shim and typechecked
|
|
176
|
+
against `//wsl.localhost/...` UNC paths — a new instance of the PATH trap in
|
|
177
|
+
PLAN.md, which only documented `bun`/`npm`. Fixed with a `bunx -> bun`
|
|
178
|
+
symlink. After that, one real test failure remained; a worktree at the
|
|
179
|
+
pristine v0.9.0 base proved it **pre-existing upstream**, not ours. Root
|
|
180
|
+
cause: `resolveConfigPath` read `process.env` directly while its caller
|
|
181
|
+
`mergeRawMercuryConfig` takes an `env` argument, and `tests/router.test.ts`
|
|
182
|
+
leaks `MERCURY_CONFIG_FILE=""`. Fixed in `9fc8f91`; the gate is now
|
|
183
|
+
meaningful for the rest of the goal instead of permanently red.
|
|
184
|
+
- **`mercury service install --user` was not used.** It would have baked a new
|
|
185
|
+
`Environment=PATH=` from the install shell *and* reverted `Restart=always`
|
|
186
|
+
— the two gotchas the spec itself lists. Editing the single `ExecStart` line
|
|
187
|
+
in the existing unit reaches the same end state, preserves the
|
|
188
|
+
known-good PATH and restart policy, and reverts just as easily.
|
|
189
|
+
- **`npm link` would have destroyed the rollback path.** The globally installed
|
|
190
|
+
0.8.12 is a real 520 MB directory at the exact path the old `ExecStart`
|
|
191
|
+
names; `npm link` replaces that entry with a symlink to the checkout, so
|
|
192
|
+
"roll back to 0.8.12" would have had nothing to roll back to. Moved it to
|
|
193
|
+
`mercury-agent-0.8.12-rollback` first (instant rename, same filesystem).
|
|
194
|
+
- **The linked CLI needed its exec bit.** Git tracks `src/cli/mercury.ts` as
|
|
195
|
+
`100644`; npm sets `+x` at install time, which `npm link` does not do for a
|
|
196
|
+
source checkout. `mercury --version` died with "Permission denied" until
|
|
197
|
+
`chmod +x` on both bin entries.
|
|
198
|
+
|
|
199
|
+
**Key decisions made during implementation:**
|
|
200
|
+
- Fix the pre-existing test-pollution bug rather than baseline it — a red gate
|
|
201
|
+
can't distinguish my regressions from upstream's, and every later story
|
|
202
|
+
depends on that gate.
|
|
203
|
+
- Preserve the hand-tuned unit instead of regenerating it.
|
|
204
|
+
|
|
205
|
+
**Rollback procedure (verified to exist, not exercised):**
|
|
206
|
+
1. `mv ~/.nvm/versions/node/v24.19.0/lib/node_modules/mercury-agent{-0.8.12-rollback,}`
|
|
207
|
+
2. `cp ~/mercury-backup-1786307535/mercury.service.0.8.12.bak ~/.config/systemd/user/mercury.service`
|
|
208
|
+
3. `systemctl --user daemon-reload && systemctl --user restart mercury`
|
|
209
|
+
4. Only if the migration corrupted data: restore the three `state.db*` files.
|
|
210
|
+
|
|
211
|
+
**Architecture impact** (update `docs/ARCHITECTURE.md` if any of these apply):
|
|
212
|
+
- [x] Deployment topology changed (npm global 0.8.12 → git checkout 0.9.0)
|