Context
Discussions panel currently shows comments for a single document via useDiscussionsService({targetId}) → ListComments(targetAccount, targetPath) → exact WHERE iri = :iri match. Goal: when viewing an account doc, show comments from that doc AND all its children as a flat thread list sorted by latest activity.
Plan
Step 1: Backend — Add GLOB support to ListComments
File: backend/api/documents/v3alpha/comments.go
When target_path ends with *, use GLOB matching instead of exact IRI match:
In ListComments handler (line 152), detect wildcard: strings.HasSuffix(in.TargetPath, "*")
If wildcard:
Strip *, build IRI prefix manually: "hm://" + acc.String() + pathWithoutStar
Append * to create GLOB pattern: iriPattern = iriPrefix + "*"
Use new query qIterCommentsGlob instead of qIterComments
If no wildcard: keep existing exact-match behavior (zero regression risk)
New SQL query qIterCommentsGlob:
SELECT sb.id, b.codec, b.multihash, b.data, sb.extra_attrs->>'tsid' AS tsid
FROM (
SELECT sb.*, ROW_NUMBER() OVER (PARTITION BY sb.extra_attrs->>'tsid' ORDER BY sb.ts DESC) rn
FROM structural_blobs sb
WHERE sb.type = 'Comment'
AND sb.resource IN (SELECT id FROM resources WHERE iri GLOB :iri)
) sb
JOIN blobs b ON b.id = sb.id
WHERE sb.rn = 1
AND sb.extra_attrs->>'deleted' IS NULL
ORDER BY sb.ts
Key diff from qIterComments: = (SELECT id ...) → IN (SELECT id ... WHERE iri GLOB :iri)
Pattern follows existing GLOB usage in backend/api/activity/v1alpha/activity.go:609.
Step 2: Frontend — Pass wildcard target_path for account docs
File: frontend/packages/shared/src/models/comments-resolvers.ts
In createDiscussionsResolver (line 134), when the caller wants aggregated comments:
Accept a new optional includeChildren?: boolean parameter
When true, pass targetPath: hmIdPathToEntityQueryPath(id.path) + '*' (or just '*' for root docs with no path)
File: frontend/packages/shared/src/comments-service-provider.tsx
Extend HMListDiscussionsInput to include includeChildren?: boolean, pipe through to resolver.
File: frontend/packages/shared/src/api-comments.ts
Pass includeChildren from input to createDiscussionsResolver.
Step 3: Frontend — DiscussionsPanel passes includeChildren for account docs
File: frontend/apps/desktop/src/components/discussions-panel.tsx
When targetDocId is an account root doc (no path or empty path), pass includeChildren: true to the Discussions component.
File: frontend/packages/ui/src/comments.tsx
In Discussions component:
Accept new includeChildren?: boolean prop
Pass to useDiscussionsService({targetId, commentId, includeChildren})
Step 4: Grouping — reuse existing getCommentGroups
The existing getCommentGroups in frontend/packages/shared/src/comments.ts already:
Groups comments by reply chains (linearized threads)
Sorts by latest updateTime (newest first)
Counts branching replies as moreCommentsCount
Comments from different child docs will naturally form separate groups since they have different replyParent chains. No changes needed to the grouping algorithm.
Each HMComment already has targetAccount + targetPath fields, so the UI could optionally show which doc a comment belongs to if needed later.
Files to modify
Verification
Backend: write Go test or use grpcurl to call ListComments with target_path: "/*" or target_path: "*" and verify it returns comments from child docs
Frontend: open account root doc discussions panel, verify comments from child docs appear
Regression: open a regular doc discussions panel, verify exact-match behavior unchanged
Run: pnpm typecheck + pnpm -F @shm/shared test run + pnpm format:write