Distinguish HEY World posts from email - #185
Conversation
There was a problem hiding this comment.
Pull request overview
Distinguishes HEY World posts from email across the CLI and TUI, preventing inappropriate email actions and adding a dedicated deletion command.
Changes:
- Preserves posting kinds and reports separate email and World-post counts.
- Blocks email-only actions for
world/postitems. - Adds confirmed HEY World deletion through the SDK.
Tip
If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.
Reviewed changes
Copilot reviewed 22 out of 22 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
.surface |
Registers new commands and flags. |
API-COVERAGE.md |
Documents the World deletion endpoint. |
README.md |
Documents posting kinds and World deletion. |
skills/hey/SKILL.md |
Adds agent guidance for World posts. |
internal/cmd/box.go |
Counts and summarizes posting kinds. |
internal/cmd/box_test.go |
Tests mixed-kind JSON output and counts. |
internal/cmd/help.go |
Adds World commands to help. |
internal/cmd/help_test.go |
Updates help expectations. |
internal/cmd/ignore.go |
Adds World-post validation. |
internal/cmd/move.go |
Adds World-post validation. |
internal/cmd/posting_kind.go |
Implements shared kind validation. |
internal/cmd/posting_kind_test.go |
Tests rejection across email actions. |
internal/cmd/root.go |
Registers the World command. |
internal/cmd/seen.go |
Adds validation to seen/unseen. |
internal/cmd/spam.go |
Adds World-post validation. |
internal/cmd/stop_ignoring.go |
Adds World-post validation. |
internal/cmd/trash.go |
Adds World-post validation. |
internal/cmd/trash_test.go |
Tests trash/spam rejection. |
internal/cmd/world.go |
Implements confirmed World deletion. |
internal/cmd/world_test.go |
Tests confirmation and endpoint routing. |
internal/tui/mail.go |
Blocks email actions on World posts. |
internal/tui/mail_test.go |
Tests TUI action rejection. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
dc5cfeb to
35c0f8c
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 25 out of 25 changed files in this pull request and generated no new comments.
Suppressed comments (2)
internal/cmd/help.go:20
worldis still rendered under theEMAILheading even though this change establishes that HEY World posts are published content and that their actions are separate from email. Put this command in a non-email/HEY World category so root help communicates the same boundary as the command validation.
names: []string{"boxes", "box", "search", "contacts", "threads", "attachments", "compose", "reply", "forward", "drafts", "seen", "unseen", "move", "trash", "spam", "ignore", "stop-ignoring", "world"},
internal/cmd/box.go:30
- The detailed description now says this command returns both email and World items, but its
Shorttext and--limithelp still call every result a thread. Those strings drive root/subcommand help and preserve the misleading email-only description this PR is intended to remove; update them to use “items” or explicitly mention both kinds, along with the help expectation.
Long: "List email threads and HEY World posts in a box. Each kind is counted separately. Accepts a box name (imbox, feedbox, etc.) or numeric ID.",
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 25 out of 25 changed files in this pull request and generated no new comments.
Suppressed comments (1)
internal/cmd/box.go:137
- The new
Itemcolumn still rendersresolvePostingTopicID(posting), so email rows show the topic ID while World rows fall back to the box item ID. These IDs can differ, and the newly documentedseen/move/trashcommands require the box item ID, so copying an email's displayed “Item” value can target the wrong resource. Renderposting.Idconsistently and expose the topic ID in a separately labeled column if the read workflow still needs it.
fmt.Sprintf("%d", resolvePostingTopicID(posting)),
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 25 out of 25 changed files in this pull request and generated no new comments.
Suppressed comments (7)
internal/cmd/seen.go:77
- The new guard only works when
--kindis supplied, but the built-inunseenhelp examples still omit it. Update these examples so copied commands preserve the item-kind boundary.
"agent_notes": "Accepts one or more box item IDs from hey box output. Pass --kind exactly as returned by hey box --json. HEY World posts are rejected before any email action is requested. Marks each email thread as unseen/unread.",
internal/cmd/seen.go:23
- The new guard only works when
--kindis supplied, but the built-inseenhelp examples still demonstrate calls without it. This can lead users to copy the compatibility form and bypass the World-post boundary; align these examples with the README by passing--kind topic.
This issue also appears on line 77 of the same file.
"agent_notes": "Accepts one or more box item IDs from hey box output. Pass --kind exactly as returned by hey box --json. HEY World posts are rejected before any email action is requested. Marks each email thread as seen/read.",
internal/cmd/trash.go:23
- The new guard only works when
--kindis supplied, buthey trash --helpstill demonstrates commands without it. Add--kind topicso the built-in examples do not teach callers to bypass the World-post check.
"agent_notes": "Accepts one or more box item IDs from hey box output. Pass --kind exactly as returned by hey box --json. HEY World posts are rejected before any email action is requested. Shared threads lose your access rather than being deleted for everyone.",
internal/cmd/spam.go:23
- The new guard only works when
--kindis supplied, buthey spam --helpstill demonstrates commands without it. Add--kind topicso copied examples enforce the World-post boundary.
"agent_notes": "Accepts one or more box item IDs from hey box output. Pass --kind exactly as returned by hey box --json. HEY World posts are rejected before any email action is requested. Marks each thread as spam and removes it from the current box.",
internal/cmd/ignore.go:23
- The new guard only works when
--kindis supplied, buthey ignore --helpstill demonstrates commands without it. Add--kind topicso copied examples enforce the World-post boundary.
"agent_notes": "Accepts one or more box item IDs from hey box output. Pass --kind exactly as returned by hey box --json. HEY World posts are rejected before any email action is requested. Ignored threads remain in their box and can be restored with hey stop-ignoring.",
internal/cmd/stop_ignoring.go:23
- The new guard only works when
--kindis supplied, buthey stop-ignoring --helpstill demonstrates commands without it. Add--kind topicso copied examples enforce the World-post boundary.
"agent_notes": "Accepts one or more box item IDs from hey box output. Pass --kind exactly as returned by hey box --json. HEY World posts are rejected before any email action is requested. Reverses hey ignore for each thread.",
internal/cmd/move.go:33
- The built-in move examples still omit
--kind, even though this new annotation says callers should preserve it and the README examples now do so. Since omission bypasses the World-post guard, include--kind topicin all three help examples.
"agent_notes": "Accepts box item IDs from hey box output. Pass --kind exactly as returned by hey box --json. HEY World posts are rejected before any email action is requested. --to accepts a box name, kind, or ID. Use HEY's scheduled Bubble Up flow for Bubble Up.",
248d8db to
934ce67
Compare
What changed
HEY box responses can mix email topics with published HEY World posts. The CLI treated every item as an email, which made counts misleading and made email actions look valid for published content.
This change:
2,944 emails and 21 HEY World posts--kindto email organization commands and rejectsworld/postbefore authentication or any HTTP requesthey world delete <token> --confirmcommand using the SDK World endpointExisting command calls without
--kindremain compatible. Callers that read fromhey box --jsonshould pass the returned kind so the CLI can enforce the boundary. The TUI already has that context and enforces it automatically.World deletion requires the post token, not the box item ID, and explicit confirmation. No existing HEY World posts were deleted while developing or testing this change.
Tests
make checkworld/postwithout making a request/world/posts/{token}, never/postings/trashSummary by cubic
Distinguishes HEY World posts from email, separates box item IDs from email topic IDs, and blocks email actions on published content. Previously every box item was treated as email and IDs were conflated; now the CLI/TUI preserve kind, show accurate counts, and route HEY World deletions through a dedicated command.
hey boxpreserves per-itemkind, shows Item/Kind/Topic columns (World posts have no Topic), prints mixed summaries (e.g., “2,944 emails and 21 HEY World posts”), and adds JSON metadata:posting_count,email_count,world_post_count.seen,unseen,move,trash,spam,ignore,stop-ignoring) accept--kind, act on boxid(nottopic_id), and rejectworld/postlocally before auth or any request.world/post, shows a notice, and makes no requests.hey world delete <token> --confirmusing/world/posts/{token}(separate from email Trash); help includes a new HEY WORLD section and updates email action examples to include--kind topic.Migration
--kind. If you parsehey box --json, passid+--kind topicfor email actions and usetopic_idfor reading/replying/forwarding; do not assumeid == topic_id.world/postnow fail locally with guidance and make no requests.hey world delete <token> --confirmwith the post token (not the box item ID).Written for commit 934ce67. Summary will update on new commits.