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,200 @@
|
|
|
1
|
+
# Decisions: Mercury WhatsApp Bot — Context, Identity & Command Hardening
|
|
2
|
+
|
|
3
|
+
**Goal**: [whatsapp-bot-hardening](goal.md)
|
|
4
|
+
|
|
5
|
+
## D-001: Run the live bot from the git checkout, not the npm global install
|
|
6
|
+
- **Category:** architecture
|
|
7
|
+
- **Decided:** `npm link` from `~/mercury-src`, reinstall the systemd user unit
|
|
8
|
+
via `mercury service install --user`, keep the npm-installed 0.8.12 in place
|
|
9
|
+
as a <1-minute rollback (`npm unlink` + restore old unit).
|
|
10
|
+
- **Alternatives considered:** keep patching the globally installed package
|
|
11
|
+
(0.8.12) in place; publish a private build.
|
|
12
|
+
- **Reasoning:** fixes become version-controlled, testing is edit→restart, and
|
|
13
|
+
`npm i -g` upgrades can no longer silently revert hand-patches (which already
|
|
14
|
+
happened with the pinchtab fixes).
|
|
15
|
+
- **Revisit if:** the checkout diverges so far from upstream that rebasing costs
|
|
16
|
+
more than maintaining patches.
|
|
17
|
+
- **Used by:** run-from-source-switchover
|
|
18
|
+
|
|
19
|
+
## D-002: Message authorship goes in the DB schema (`author_id` / `author_name` columns)
|
|
20
|
+
- **Category:** architecture
|
|
21
|
+
- **Decided:** migrate the `messages` table to carry author id + display name;
|
|
22
|
+
render `<user name="…" id="…">` in history XML; back the in-memory
|
|
23
|
+
`pushNames` map with `space_roles.display_name`.
|
|
24
|
+
- **Alternatives considered:** prefix names into the content string (as ambient
|
|
25
|
+
already does at `runtime.ts:604`); a separate authors join table.
|
|
26
|
+
- **Reasoning:** the identity data already exists clean in
|
|
27
|
+
`space_roles.display_name`; columns make it queryable and render-safe, and a
|
|
28
|
+
prefix-in-content hack would be unparseable later. Existing rows backfill as
|
|
29
|
+
NULL and still render.
|
|
30
|
+
- **Revisit if:** upstream lands its own attribution schema first — then adopt
|
|
31
|
+
theirs in the rebase.
|
|
32
|
+
- **Used by:** message-author-attribution, ambient-group-context, member-memory
|
|
33
|
+
|
|
34
|
+
## D-003: Ambient context gets its own bounded query + retention TTL before it is enabled
|
|
35
|
+
- **Category:** trade-off
|
|
36
|
+
- **Decided:** `recordAmbient` ships only together with a dedicated bounded
|
|
37
|
+
ambient query (not sharing `getRecentTurns`' `turnCount * 5` window) and an
|
|
38
|
+
ambient TTL in `storage-cleanup.ts`.
|
|
39
|
+
- **Alternatives considered:** enable ambient first, tune the budget later.
|
|
40
|
+
- **Reasoning:** once ambient actually flows, every group message becomes a row;
|
|
41
|
+
unbounded it crowds real user/assistant turns out of the context window and
|
|
42
|
+
grows the DB forever. HANDOFF is explicit: do not ship the handler fix
|
|
43
|
+
without the cap.
|
|
44
|
+
- **Revisit if:** measured ambient volume in `greece2026` is trivially small.
|
|
45
|
+
- **Used by:** ambient-group-context
|
|
46
|
+
|
|
47
|
+
## D-004: Media cap raised to 64 MB; every dropped attachment produces a promptNote
|
|
48
|
+
- **Category:** scope
|
|
49
|
+
- **Decided:** `media.max_size_mb: 64` in `mercury.yaml` (verified
|
|
50
|
+
`MERCURY_MEDIA_MAX_SIZE_MB` is unset so YAML takes effect), plus an
|
|
51
|
+
unconditional system note on any dropped attachment, copying the existing
|
|
52
|
+
`media-gate.ts` promptNote pattern.
|
|
53
|
+
- **Alternatives considered:** 32 MB; download-extract-discard for oversize
|
|
54
|
+
documents (deferred as optional follow-up).
|
|
55
|
+
- **Reasoning:** the observed real files were 49–56 MB; the silence was the
|
|
56
|
+
worse half of the bug — the agent invented a wrong explanation because it was
|
|
57
|
+
told nothing.
|
|
58
|
+
- **Revisit if:** disk or bandwidth pressure appears in practice.
|
|
59
|
+
- **Used by:** media-size-and-silent-drop
|
|
60
|
+
|
|
61
|
+
## D-005: Document creation is a new `docs` extension modeled on the `pdf` extension
|
|
62
|
+
- **Category:** tech-stack
|
|
63
|
+
- **Decided:** extension with `install` string adding `pandoc` +
|
|
64
|
+
`python-docx openpyxl odfpy` to the derived image, a `SKILL.md` teaching
|
|
65
|
+
docx-to-`outbox/`, `defaultRoles: ["admin", "member"]`.
|
|
66
|
+
- **Alternatives considered:** Google Docs/Workspace integration (real links).
|
|
67
|
+
- **Reasoning:** egress already works (HTML attachments prove it); only
|
|
68
|
+
production of `.docx` is missing. Workspace OAuth is a separate project.
|
|
69
|
+
- **Revisit if:** users specifically need collaborative Google Docs links.
|
|
70
|
+
- **Used by:** docs-extension
|
|
71
|
+
|
|
72
|
+
## D-006: `mrctl spaces delete` rejects arguments loudly; the API keeps `/current` only
|
|
73
|
+
- **Category:** architecture
|
|
74
|
+
- **Decided:** error out when `mrctl spaces delete` receives an argument,
|
|
75
|
+
pointing to the chat command `/spaces delete <id>`; do **not** add a
|
|
76
|
+
`DELETE /api/spaces/:id` route.
|
|
77
|
+
- **Alternatives considered:** make mrctl honor the id via a new API route.
|
|
78
|
+
- **Reasoning:** the `/current`-only API is a deliberate security boundary
|
|
79
|
+
(`core/routes/spaces.ts` scopes every mutation to the caller's space).
|
|
80
|
+
Silently ignoring the argument is what actually destroyed the baduk space.
|
|
81
|
+
- **Revisit if:** never — widening this API is out of scope by design.
|
|
82
|
+
- **Used by:** destructive-command-guards
|
|
83
|
+
|
|
84
|
+
## D-007: Slash commands work without the trigger word in groups
|
|
85
|
+
- **Category:** pattern
|
|
86
|
+
- **Decided:** honor `/`-prefixed known commands in groups without the trigger
|
|
87
|
+
word; unknown `/foo` still falls through to ambient.
|
|
88
|
+
- **Alternatives considered:** delete the dead `isCommand` bypass and document
|
|
89
|
+
that commands require the trigger.
|
|
90
|
+
- **Reasoning:** matches the handler's evident intent (the bypass exists, it
|
|
91
|
+
just accomplishes nothing today), and matches what users already type — the
|
|
92
|
+
two live ambient rows are exactly such stranded commands.
|
|
93
|
+
- **Revisit if:** command-name collisions with normal chat starting with `/`.
|
|
94
|
+
- **Used by:** command-routing-consistency
|
|
95
|
+
|
|
96
|
+
## D-008: Chat stays seeded-admin-only for `/spaces`; `spaces.delete` leaves the blanket admin grant
|
|
97
|
+
- **Category:** trade-off
|
|
98
|
+
- **Decided:** align the divergent gates by tightening the CLI/API side — lift
|
|
99
|
+
`spaces.delete` out of `getDefaultPermissions`' blanket space-admin grant so
|
|
100
|
+
it matches the chat surface's seeded-admin gate.
|
|
101
|
+
- **Alternatives considered:** loosen chat to any space admin.
|
|
102
|
+
- **Reasoning:** the tighter gate is the intended one; today a promoted space
|
|
103
|
+
admin who is denied in chat can destroy the current space via `mrctl` — a
|
|
104
|
+
bypass, not a feature.
|
|
105
|
+
- **Revisit if:** multi-admin spaces become a real use case.
|
|
106
|
+
- **Used by:** command-routing-consistency
|
|
107
|
+
|
|
108
|
+
## D-009: `/spaces unlink` is removed from chat; `/model active` is dropped; `/compact` vs `/clear` get honest help text, not a merge
|
|
109
|
+
- **Category:** scope
|
|
110
|
+
- **Decided:** remove the unrecoverable one-way door (6c) from the chat surface
|
|
111
|
+
entirely (dashboard/API keep the capability); drop the redundant
|
|
112
|
+
`/model active`; keep both `/compact` and `/clear` but rewrite their help to
|
|
113
|
+
state the actual `session_boundary` vs `clear_boundary` difference.
|
|
114
|
+
- **Alternatives considered:** make unlink recoverable in chat; merge
|
|
115
|
+
compact/clear blind.
|
|
116
|
+
- **Reasoning:** unlink's advertised recovery path (`/spaces switch`) is
|
|
117
|
+
provably unreachable after unlinking; re-link-on-rejoin still ships so the
|
|
118
|
+
group-removal path self-heals. Merging compact/clear without first
|
|
119
|
+
documenting the real difference risks destroying a distinction users need.
|
|
120
|
+
- **Revisit if:** a safe recovery UX for unlink is designed later.
|
|
121
|
+
- **Used by:** command-routing-consistency, destructive-command-guards
|
|
122
|
+
|
|
123
|
+
## D-010: Member memory = hard identity from DB + soft notes as workspace files
|
|
124
|
+
- **Category:** architecture
|
|
125
|
+
- **Decided:** a `<members>` block generated from `space_roles` (id → name,
|
|
126
|
+
not guessable) plus per-space `knowledge/members/<id>.md` notes written by
|
|
127
|
+
the agent with its existing `write` tool, injected like `<active_episodes>`.
|
|
128
|
+
- **Alternatives considered:** a new DB table for member profiles.
|
|
129
|
+
- **Reasoning:** reuses existing episodic plumbing, needs no migration for the
|
|
130
|
+
notes half, and keeps identity facts (who is who) separate from accumulated
|
|
131
|
+
observations (what they're like).
|
|
132
|
+
- **Revisit if:** notes need querying/aggregation across spaces.
|
|
133
|
+
- **Used by:** member-memory
|
|
134
|
+
|
|
135
|
+
## D-011: `allowedDomains "*"` stays for this PR, called out as a security trade-off
|
|
136
|
+
- **Category:** trade-off
|
|
137
|
+
- **Decided:** keep the wildcard pinchtab allowlist (the injection guard is
|
|
138
|
+
verified still active); the PR describes it as a deliberate widening of
|
|
139
|
+
attack surface, not a plain bugfix. Tightening to a curated list is deferred.
|
|
140
|
+
- **Alternatives considered:** curated domain list now.
|
|
141
|
+
- **Reasoning:** out of scope for this PR; honesty in the PR description is the
|
|
142
|
+
cheap mitigation available now.
|
|
143
|
+
- **Revisit if:** always — this is queued as a follow-up idea.
|
|
144
|
+
- **Used by:** (PR prep — see roadmap Completion section)
|
|
145
|
+
|
|
146
|
+
## D-012: One PR at the end, not a PR per story
|
|
147
|
+
- **Category:** scope
|
|
148
|
+
- **Decided:** single PR `fix/whatsapp-context-identity-and-docs` → `main`
|
|
149
|
+
with a section per change, including the four already-merged pinchtab
|
|
150
|
+
commits (framed as upstreaming a live hotfix), the uncommitted
|
|
151
|
+
`.dockerignore` fix, the schema migration, and the explicit list of
|
|
152
|
+
command-surface behaviour changes.
|
|
153
|
+
- **Alternatives considered:** stacked PRs per milestone.
|
|
154
|
+
- **Reasoning:** the branch already carries the pinchtab commits; the fixes are
|
|
155
|
+
interdependent (attribution ↔ ambient); and the repo has a single upstream
|
|
156
|
+
reviewer. The per-section PR body keeps it reviewable.
|
|
157
|
+
- **Revisit if:** upstream asks for it to be split.
|
|
158
|
+
- **Used by:** all stories
|
|
159
|
+
|
|
160
|
+
## D-013: The D:-clone's `fix/pinchtab-browser-startup` branch is superseded, not pushed
|
|
161
|
+
- **Category:** scope
|
|
162
|
+
- **Decided:** leave the branch in the stale Windows clone
|
|
163
|
+
(`D:\Projects\whatsapp-bot\mercury`) untouched and unpushed; the four pinchtab
|
|
164
|
+
commits reach `main` through `fix/whatsapp-context-identity-and-docs` instead.
|
|
165
|
+
- **Alternatives considered:** push it as its own PR and merge it before the
|
|
166
|
+
hardening PR; delete the branch.
|
|
167
|
+
- **Reasoning:** verified equivalent, not assumed — the combined patch of the
|
|
168
|
+
four commits is byte-identical in both repos (md5 `83aa486e…` over the
|
|
169
|
+
index-line-stripped diff, same three files, 56 insertions / 12 deletions).
|
|
170
|
+
The clone's copy (`3c5d56f..17c92c6`) sits on a base three commits behind
|
|
171
|
+
`origin/main`; the `mercury-src` copy (`bfe5a33..b12d7c0`) is current with
|
|
172
|
+
`origin/main` at `70a5ce3`. Pushing both would put the same change on `main`
|
|
173
|
+
twice. The branch is left in place rather than deleted because it costs
|
|
174
|
+
nothing and is the only copy of those commit hashes.
|
|
175
|
+
- **Revisit if:** the hardening PR is rejected or split, in which case the
|
|
176
|
+
pinchtab commits should be re-proposed on their own from `mercury-src`.
|
|
177
|
+
- **Used by:** (PR prep — see roadmap Completion section)
|
|
178
|
+
|
|
179
|
+
## D-014: One instruction, one layer — never state the same rule twice
|
|
180
|
+
- **Category:** pattern
|
|
181
|
+
- **Decided:** each voice/behaviour rule lives in exactly **one** of the five
|
|
182
|
+
prompt layers, chosen by scope: global default → `project_config.character`;
|
|
183
|
+
per-space override → `space_preferences`; per-space long-form structure
|
|
184
|
+
(role, workflow, honesty rules) → `.mercury/spaces/<id>/AGENTS.md`.
|
|
185
|
+
`space_config.system_prompt` is treated as unavailable (no setter exists).
|
|
186
|
+
Quantities are written as **countable** rules, never adjectives.
|
|
187
|
+
- **Alternatives considered:** rely on layer precedence to override — e.g. put
|
|
188
|
+
the permissive default in the character and a stricter rule in preferences,
|
|
189
|
+
expecting the more specific layer to win.
|
|
190
|
+
- **Reasoning:** measured, not assumed. On the throwaway `prompttest` space a
|
|
191
|
+
direct `system_prompt`-vs-`preferences` conflict went 8/10 to `system_prompt`
|
|
192
|
+
— but a swapped-language control produced the **opposite** winner, and
|
|
193
|
+
repeating one fixed config gave different winners across runs. Precedence is
|
|
194
|
+
not reliable, so a conflict is a coin flip and must be designed out rather
|
|
195
|
+
than resolved by placement. The countable-rule half is from the emoji data:
|
|
196
|
+
"none at all" → 0%, "minimal" → 33%, "here and there when it fits" → 73%.
|
|
197
|
+
The layer decides *scope*; the wording decides *compliance*.
|
|
198
|
+
- **Revisit if:** upstream introduces explicit, documented precedence between
|
|
199
|
+
the layers — then placement becomes a usable tool again.
|
|
200
|
+
- **Used by:** (prompt/voice work — see open-threads.md §A)
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Mercury WhatsApp Bot — Context, Identity & Command Hardening
|
|
2
|
+
|
|
3
|
+
**Status**: Active — all 4 milestones shipped; open items in [open-threads.md](open-threads.md)
|
|
4
|
+
**Slug**: whatsapp-bot-hardening
|
|
5
|
+
**Created**: 2026-08-09
|
|
6
|
+
**Last updated**: 2026-08-10
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Goal Statement
|
|
11
|
+
|
|
12
|
+
Fix the six verified defect families documented in the handoff
|
|
13
|
+
(`docs/goals/whatsapp-bot-hardening/archive/handoff-2026-08-09.md`) — ambient group
|
|
14
|
+
context dead code, sender misidentification, silent large-media rejection, no
|
|
15
|
+
document creation, destructive/broken command surface) and add member memory —
|
|
16
|
+
then land everything as one upstream PR from
|
|
17
|
+
`fix/whatsapp-context-identity-and-docs`, with the live bot running the fixed
|
|
18
|
+
code from the git checkout.
|
|
19
|
+
|
|
20
|
+
## Constraints
|
|
21
|
+
|
|
22
|
+
- All code work happens in **`~/mercury-src` inside WSL** (branch
|
|
23
|
+
`fix/whatsapp-context-identity-and-docs`, based on v0.9.0). The Windows clone
|
|
24
|
+
at `D:\Projects\whatsapp-bot\mercury` is stale reference only — never edit it.
|
|
25
|
+
- The bot is **live** for real family/friends groups. Data-loss bugs (the baduk
|
|
26
|
+
incident) already happened once; every migration must be preceded by a DB
|
|
27
|
+
backup, and destructive-command fixes ship before anything that increases
|
|
28
|
+
message volume is enabled for long.
|
|
29
|
+
- Never read `~/whatsapp-bot/.env` (live API keys). Never run `mercury run`
|
|
30
|
+
directly; restart only via `systemctl --user restart mercury`.
|
|
31
|
+
- Check gate for every story: `cd ~/mercury-src && bun run check`
|
|
32
|
+
(typecheck + lint + tests), run inside WSL with the PATH fix
|
|
33
|
+
(`export PATH=$HOME/.nvm/versions/node/v24.19.0/bin:$HOME/.bun/bin:$PATH`).
|
|
34
|
+
- Debug logging (`log_level: debug`) may be enabled for verification windows
|
|
35
|
+
only and **must** be reverted — it writes chat-content previews to journald.
|
|
36
|
+
|
|
37
|
+
## Preferences
|
|
38
|
+
|
|
39
|
+
- Follow the fix designs already verified in the archived handoff §4 (required) —
|
|
40
|
+
root causes were confirmed against running code and live data; do not re-derive them.
|
|
41
|
+
- Reuse existing plumbing over new subsystems (required) — e.g. member notes as
|
|
42
|
+
workspace files like episodes, promptNote pattern from `media-gate.ts`.
|
|
43
|
+
- One PR at the end covering all changes, with explicit sections per change and
|
|
44
|
+
the behaviour-change list for the command surface (required).
|
|
45
|
+
- Suggested implementation order from the archived handoff §7 (preferred).
|
|
46
|
+
|
|
47
|
+
## Target Users
|
|
48
|
+
|
|
49
|
+
- **The owner/admin (Sahar)** — runs the bot, admins the spaces, is the one who
|
|
50
|
+
typed the command that destroyed the baduk space.
|
|
51
|
+
- **Family/friends group members** — talk in groups the bot is linked to; they
|
|
52
|
+
expect the bot to know who said what and to read files they send.
|
|
53
|
+
- **Future upstream users of Mercury** — the PR upstreams fixes for bugs that
|
|
54
|
+
exist verbatim on `origin/main`.
|
|
55
|
+
|
|
56
|
+
## Success Criteria
|
|
57
|
+
|
|
58
|
+
- Untagged group messages are recorded: `SELECT space_id, role, COUNT(*) FROM
|
|
59
|
+
messages GROUP BY space_id, role` shows `ambient` rows for `greece2026`
|
|
60
|
+
growing, and the bot can answer "what was just said?" after being tagged.
|
|
61
|
+
- Two people talk in a group; a third asks "who said X?" and attribution is
|
|
62
|
+
correct — including quoted replies after a service restart.
|
|
63
|
+
- `mrctl spaces delete <id>` with an argument exits non-zero with an
|
|
64
|
+
explanatory error and issues **no** HTTP request; replying "yes" (as a
|
|
65
|
+
WhatsApp reply) to a `/spaces delete <id>` confirmation deletes the *named*
|
|
66
|
+
space, not the current one.
|
|
67
|
+
- `/stop` aborts a running agent instead of queueing another model run; a bare
|
|
68
|
+
`/spaces list` works untagged in a group; an unlinked group can re-link
|
|
69
|
+
itself from chat.
|
|
70
|
+
- A ~50 MB docx sent to a space is downloaded and readable; an over-limit file
|
|
71
|
+
produces an explicit "too large" note to the agent instead of silence.
|
|
72
|
+
- "Make me a doc" produces a real `.docx` delivered over WhatsApp.
|
|
73
|
+
- `bun run check` is green, the live service runs from `~/mercury-src`, and one
|
|
74
|
+
PR containing all changes (including the four pinchtab commits and the
|
|
75
|
+
`.dockerignore` fix) is open against `main`.
|