Skip to content

fix: dms window note counts direct messages the listing cannot show - #239

Open
rnavarro wants to merge 1 commit into
openclaw:mainfrom
rnavarro:fix/dms-window-note-counts-printable
Open

rnavarro wants to merge 1 commit into
openclaw:mainfrom
rnavarro:fix/dms-window-note-counts-printable

Conversation

@rnavarro

Copy link
Copy Markdown
Contributor

What Problem This Solves

Fixes: dms --days N reports messages in scope that dms without the window does not list, when a direct message's channel has no channels row.

User Impact

The window note now counts only conversations dms can return, so the command it recommends produces the rows the note named. On an archive whose only direct messages are uncatalogued, the note does not print.

Why This Change Was Made

store.DirectMessageConversations selects from channels and joins messages on channel id and guild id, so a direct message whose channel was never catalogued under its guild is in no dms listing at any window, while the count behind the note selects from messages and includes it. MessageScopeOptions gains CataloguedChannelsOnly and the dms window note sets it, so the count and the listing read one row set. Both tables carry a guild_id, so the correlated subquery is qualified on both sides and MessageScopeStats qualifies its scope clauses with the messages table: an unqualified outer reference inside the subquery resolves to the channels row and reduces the clause to "a channels row with this id exists".

Evidence

Scratch archive holding one catalogued conversation (newest 2020-03-01) and one direct message whose channel has no channels row (2020-07-01). Before:

$ discrawl dms --days 1
note: 2 messages in scope but none within the last 1 days (newest: 2020-07-01T00:00:00Z); try without --days
$ discrawl dms
CHANNEL           NAME   MESSAGES  AUTHORS  FIRST                 LAST
7777777777777777  Alice  1         1        2020-03-01T00:00:00Z  2020-03-01T00:00:00Z

After, running the command the note recommends, which returns the row it counted:

$ discrawl dms --days 1
note: 1 messages in scope but none within the last 1 days (newest: 2020-03-01T00:00:00Z); try without --days
$ discrawl dms
CHANNEL           NAME   MESSAGES  AUTHORS  FIRST                 LAST
7777777777777777  Alice  1         1        2020-03-01T00:00:00Z  2020-03-01T00:00:00Z

Three new tests. Two drive Run() over an archive holding an uncatalogued direct message and fail without the scope change. The store test adds a channels row carrying the orphan's id under a different guild, and fails if the guild half of the subquery is dropped or its outer reference is left unqualified.

make fmt, make lint, and make test-coverage (85.9%) pass. I found this by running each note's recommended command against a scratch archive.

https://claude.ai/code/session_019WpK9xb3Z2Zym1T9C7EGQH

…rint

`dms --days 1` over an archive whose only direct message has no channels row
printed "note: 1 messages in scope but none within the last 1 days; try without
--days", and `dms` without the window then listed no conversation. With a
catalogued conversation alongside, the note reported 2 messages and the newest
timestamp of the row `dms` cannot print.

store.DirectMessageConversations selects from channels and joins messages to it
on both channel id and guild id, so a direct message whose channel was never
catalogued under its guild is in that result at no window, while the count
behind the note selected from messages and included it. MessageScopeOptions
gains CataloguedChannelsOnly, the `dms` window note sets it, and the count is
now taken over the listing's own row set: zero prints nothing, and above zero
names rows that dropping the window returns.

The correlated subquery is qualified on both sides and MessageScopeStats now
qualifies its scope clauses with the messages table, because channels carries a
guild_id column of its own and an unqualified outer reference inside the
subquery resolves to the channels row. The store test pins that by adding a
channels row with the orphan's id under a different guild: the count stays 1.

Found by running every note's recommended command against a scratch archive.

Claude-Session: https://claude.ai/code/session_019WpK9xb3Z2Zym1T9C7EGQH
@clawsweeper

clawsweeper Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

ClawSweeper review complete

ClawSweeper finished reviewing this revision. The review result is being finalized.

View the workflow run.

@clawsweeper clawsweeper Bot added P2 Normal priority bug or improvement with limited blast radius. proof: sufficient Contributor real behavior proof is sufficient. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Sep 15, 2026
@clawsweeper

clawsweeper Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed September 15, 2026, 11:34 AM ET / 15:34 UTC.

ClawSweeper review

What this changes

The PR excludes uncatalogued direct messages from empty-result window notes, with regression tests and documentation explaining the count.

Merge readiness

Ready for maintainer review

This remains a useful, focused fix: current main and v0.15.1 still contain the diagnostic mismatch. No blocking defect was found, and the supplied before/after CLI transcript demonstrates the corrected behavior.

Priority: P2
Reviewed head: d7957d5a3d3c75e53dfd70e8e7cbcd83a5bb2114

Review scores

Measure Result What it means
Overall readiness 🐚 platinum hermit (4/6) A focused repair with relevant terminal proof, targeted regression coverage, and no blocking finding.
Proof confidence 🐚 platinum hermit (4/6) Sufficient (terminal): The captured terminal transcript exercises the real dms CLI against a scratch SQLite archive and shows the changed diagnostic count and timestamp matching the subsequent conversation listing; the three inspected tests supplement that proof.
Patch quality 🐚 platinum hermit (4/6) No actionable review findings were identified.

Verification

Check Result Evidence
Real behavior Verified Sufficient (terminal): The captured terminal transcript exercises the real dms CLI against a scratch SQLite archive and shows the changed diagnostic count and timestamp matching the subsequent conversation listing; the three inspected tests supplement that proof.
Evidence reviewed 7 items Current-main mismatch: Current main computes diagnostic scope over messages without requiring matching channel metadata. The DM command without time filters instead selects conversation summaries from channels, joined to messages on both guild and channel.
Focused production change: Only the DM window diagnostic enables the new restriction. The correlated EXISTS predicate matches channel and guild, and all shared scope-clause callers qualify their outer message columns. No schema, stored data, listing, or search behavior is changed.
Real CLI evidence: The captured PR body, sourceRevision 866dc827822c0fcf5197617d41b94f29ce236301ea2615a6915e02c536b1e9b2, supplies before/after terminal output from a scratch archive containing one catalogued conversation and one orphan DM. After the fix, the count changes from two to one, the newest timestamp changes from July to March, and the recommended unfiltered command lists the matching conversation.
Findings None None.
Security None None.

How this fits together

Discrawl reads locally archived Discord messages from SQLite. Its DM command switches between conversation summaries and filtered messages; empty-result notes help users choose a useful follow-up command.

flowchart TD
  A[Local Discord archive] --> B[DM command]
  B --> C[Filtered message query]
  B --> D[Conversation listing]
  C --> E[Empty result]
  E --> F[Count catalogued DM messages]
  F --> G[Window advice on stderr]
  D --> H[Conversation summaries]
Loading

Before merge

None.

Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Production and test delta production +31 net lines; tests +161; docs +2 Production growth implements the query-scope restriction; three regression tests cover missing and mismatched channel metadata.

Technical review

Best possible solution:

Keep diagnostic counts aligned with conversations the suggested command can display while preserving access to uncatalogued messages through existing message queries.

Do we have a high-confidence way to reproduce the issue?

Yes: an archive with an old catalogued DM and a newer uncatalogued DM exposes the mismatch through dms --days 1 followed by dms. Current source establishes the path; this review did not execute it.

Is this the best way to solve the issue?

Yes: the opt-in internal query restriction narrowly repairs the misleading advice without changing message retrieval or persistent storage.

AGENTS.md: not found in the target repository.

Codex review notes: model internal, reasoning medium; reviewed against b1ea76ebbb40.

Labels

Label changes:

  • add P2: Incorrect recovery advice affects a bounded local DM archive case without blocking message access.
  • add proof: sufficient: Contributor real behavior proof is sufficient. The captured terminal transcript exercises the real dms CLI against a scratch SQLite archive and shows the changed diagnostic count and timestamp matching the subsequent conversation listing; the three inspected tests supplement that proof.
  • add rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🐚 platinum hermit.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): The captured terminal transcript exercises the real dms CLI against a scratch SQLite archive and shows the changed diagnostic count and timestamp matching the subsequent conversation listing; the three inspected tests supplement that proof.

Label justifications:

  • P2: Incorrect recovery advice affects a bounded local DM archive case without blocking message access.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): The captured terminal transcript exercises the real dms CLI against a scratch SQLite archive and shows the changed diagnostic count and timestamp matching the subsequent conversation listing; the three inspected tests supplement that proof.
  • proof: sufficient: Contributor real behavior proof is sufficient. The captured terminal transcript exercises the real dms CLI against a scratch SQLite archive and shows the changed diagnostic count and timestamp matching the subsequent conversation listing; the three inspected tests supplement that proof.

Evidence

What I checked:

  • Current-main mismatch: Current main computes diagnostic scope over messages without requiring matching channel metadata. The DM command without time filters instead selects conversation summaries from channels, joined to messages on both guild and channel. (internal/store/query.go:129, b1ea76ebbb40)
  • Focused production change: Only the DM window diagnostic enables the new restriction. The correlated EXISTS predicate matches channel and guild, and all shared scope-clause callers qualify their outer message columns. No schema, stored data, listing, or search behavior is changed. (internal/store/query.go:135, d7957d5a3d3c)
  • Real CLI evidence: The captured PR body, sourceRevision 866dc827822c0fcf5197617d41b94f29ce236301ea2615a6915e02c536b1e9b2, supplies before/after terminal output from a scratch archive containing one catalogued conversation and one orphan DM. After the fix, the count changes from two to one, the newest timestamp changes from July to March, and the recommended unfiltered command lists the matching conversation. (d7957d5a3d3c)
  • Regression coverage: Two CLI tests cover mixed and orphan-only archives; one store test additionally verifies that a channel recorded under the wrong guild does not qualify. Tests were inspected, not executed during this read-only review. (internal/cli/zero_result_notes_test.go:1053, d7957d5a3d3c)
  • Merged diagnostic history: GitHub verifies fix(cli): explain empty search, messages, and dms results #233 as merged. Its raw-parent diff adds the existing DM diagnostic scope, establishing relevant prior merged work by rnavarro rather than routing solely from authorship of this proposal. (internal/cli/zero_result_notes.go:166, 7b78c2f1a8c8)
  • Release remains affected: The latest supplied release, v0.15.1, retains the unrestricted DM diagnostic scope. GitHub reports publication on 2026-09-14; it does not contain this fix. (internal/cli/zero_result_notes.go:158, ab58a5307dda)

Likely related people:

  • Robert Navarro: Raw commit 7b78c2f adds internal/cli/zero_result_notes.go:158 relative to its recorded parents. This identifies author metadata, not feature responsibility or a PR merger. (role: source-line author; confidence: high; commits: 7b78c2f1a8c8; files: internal/cli/zero_result_notes.go)

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Workflow

  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P2 Normal priority bug or improvement with limited blast radius. proof: sufficient Contributor real behavior proof is sufficient. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant