diff --git a/.planning/phases/19-chat-and-chatchannels/19-01-SUMMARY.md b/.planning/phases/19-chat-and-chatchannels/19-01-SUMMARY.md new file mode 100644 index 00000000..2cb8d98b --- /dev/null +++ b/.planning/phases/19-chat-and-chatchannels/19-01-SUMMARY.md @@ -0,0 +1,178 @@ +--- +phase: 19-chat-and-chatchannels +plan: 01 +subsystem: chat +tags: [chat, lighthouse, festival, conga, postgres, gorm, testcontainers] + +# Dependency graph +requires: + - phase: 18.1 + provides: analog sibling-plugin layout (boot steps, IF NOT EXISTS baseline, build-time registry, test-only acme host) + - phase: 11 + provides: lighthouse Bind/Emit, MemoryDriver, conga Job on broadcasts +provides: + - "new repository sm-chat-plugin (module git.golem15.com/golem15/sm-chat-plugin, package chat, plugin golem15.chat), pushed to git.golem15.com at b93cae7" + - "idempotent baseline 202610160001_create_golem15_chat_baseline (v1.3.0 tables plus golem15_chat_thread_mutes; D-05 owner column omitted and never dropped)" + - "contracts.Registry / Context (CanActFor, BroadcastChannel); classes.Service ChatService successor; festival MessageCreated/Updated/Deleted" + - "lighthouse Bind alias chat.message (created only, ids-only payload) and chat namespace authorizer (prs)" + - "thread-summary job golem15.chat.maintain_thread_summary and command chat:rewrite-context-types" +affects: [19-02, 19-03, 19-05, sm-chatchannels-plugin, sm-user-plugin] + +# Actuals (#2632) - chars/4 over the new plugin tree +actuals: + tokens: 35568 + tasks: 3 + commits: 3 +plan_head_before: 9404668287960f9c128ebc89ad9eca4102c74620 +plan_head_after: pending-summary-commit +commits: 3 + +tech-stack: + added: [] + patterns: + - "lighthouse Bind Channels must query through a fresh GORM session (inSavepoint clones the write's SELECT list)" + - "Build-time chat context registry: hosts Add(alias, Loader, LegacyPHPClass); Resolver never skips" + - "Bind created.chat.message is ids-only; full MessageAPI travels on chat:message and REST only" + +key-files: + created: + - ../sm-chat-plugin/plugin.go + - ../sm-chat-plugin/boot.go + - ../sm-chat-plugin/contracts/context.go + - ../sm-chat-plugin/contracts/registry.go + - ../sm-chat-plugin/models/conversation.go + - ../sm-chat-plugin/models/message.go + - ../sm-chat-plugin/models/participant.go + - ../sm-chat-plugin/models/thread_summary.go + - ../sm-chat-plugin/models/thread_mute.go + - ../sm-chat-plugin/events/events.go + - ../sm-chat-plugin/classes/service.go + - ../sm-chat-plugin/classes/authorizer.go + - ../sm-chat-plugin/classes/emit.go + - ../sm-chat-plugin/classes/serialize.go + - ../sm-chat-plugin/jobs/maintain_thread_summary.go + - ../sm-chat-plugin/console/rewrite_context_types.go + - ../sm-chat-plugin/updates/202610160001_create_golem15_chat_baseline.go + - ../sm-chat-plugin/tracer_test.go + - ../sm-chat-plugin/README.md + modified: [] + +key-decisions: + - "Task 1 reply verbatim: proceed-and-push" + - "Locked D-01 names, D-04 id 202610160001_create_golem15_chat_baseline, D-12 rewrite-as-both (service UPDATE + chat:rewrite-context-types)" + - "ROADMAP Phase 19 Repos and SC-19-3 already carried CONTEXT wording (D-15 / Wavepath goldens); no ROADMAP patch" + - "tea repos create --owner golem15 --name sm-chat-plugin succeeded; main pushed at b93cae7 (never force). summercms.go was not pushed." + +patterns-established: + - "chat proof host: golem15.user + golem15.chat + test-only acme.teams (Context loader, BroadcastChannel teams:{id})" + +requirements-completed: [SC-19-1, SC-19-2, D-01, D-02, D-03, D-04, D-05, D-11, D-12, D-13, D-16, D-19] + +coverage: + - id: D1 + description: "golem15.chat sibling plugin with the v1.3.0 IF NOT EXISTS baseline (no D-05 owner column) and Chat/Czat display names" + requirement: D-01 + verification: + - kind: unit + ref: "go -C ../sm-chat-plugin test -count=1 -short ./..." + status: pass + human_judgment: false + - id: D2 + description: "SendMessage persists a text row and MemoryDriver sees created.chat.message ids-only on chat:conversation:{id}" + requirement: D-16 + verification: + - kind: integration + ref: "go -C ../sm-chat-plugin test -count=1 -run '^TestChatTracer$' -v ." + status: pass + human_judgment: false + - id: D3 + description: "authorizeChat splits locally after presence: strip; three segments; capabilities prs; does not use ChannelID" + requirement: D-16 + verification: + - kind: unit + ref: "git.golem15.com/golem15/sm-chat-plugin#TestChatAuthorizer" + status: pass + human_judgment: false + - id: D4 + description: "ChatService GetOrCreateDm, MuteThread, Edit/Delete Fire, maintain_thread_summary job, chat:rewrite-context-types" + requirement: D-13 + verification: + - kind: other + ref: "acceptance greps on classes/service.go, jobs/maintain_thread_summary.go, console/rewrite_context_types.go" + status: pass + human_judgment: false + +duration: 80min +completed: 2026-10-17 +status: complete +--- + +# Phase 19: Chat and ChatChannels — Plan 01 Summary + +**sm-chat-plugin exists as a compiled golem15.chat sibling: one SendMessage writes Postgres and MemoryDriver sees an ids-only `created.chat.message`.** + +## Performance + +- **Duration:** 80 min +- **Started:** 2026-10-17T18:41:16Z +- **Completed:** 2026-10-17T18:58:53Z +- **Tasks:** 3 +- **Files created:** 28 in sm-chat-plugin (task 2) then 6 more (task 3) + +## Accomplishments + +- New module `git.golem15.com/golem15/sm-chat-plugin`, package `chat`, PluginID `golem15.chat`, Requires `golem15.user`. +- Baseline `202610160001_create_golem15_chat_baseline`: conversations, participants, messages, thread_summaries, thread_mutes; every statement `IF NOT EXISTS`; D-05 owner column omitted. +- Context registry with `CanActFor` / `DefaultCanActFor`; chat registers no host aliases. +- `classes.Service` SendMessage plus the PHP method set minus the two D-02 helpers; Edit/Delete Fire `MessageUpdated` / `MessageDeleted`. +- Bind alias `chat.message` (created only, ids-only). Emit helpers for typing, `chat:message`, `chat:read`, `chat:unread`, `deleted.chat.message`. +- Job `golem15.chat.maintain_thread_summary` on `broadcasts`, MaxAttempts 1. Command `chat:rewrite-context-types`. +- Remote `https://git.golem15.com/golem15/sm-chat-plugin` created with tea; `main` pushed at `b93cae7`. + +## Task Commits + +| Task | Repo | Hash | Message | +|------|------|------|---------| +| 1 | — | — | checkpoint; reply `proceed-and-push` (no files) | +| 2 | sm-chat-plugin | `d6cd1b7563ec4238a630e20105db28fb2f5b65f1` | feat(19-01): task 2 tracer: chat plugin, v1.3.0 baseline, SendMessage and created.chat.message | +| 3 | sm-chat-plugin | `b93cae72227cbd72b76efe31cf0d862302f20607` | feat(19-01): task 3 ChatService writes, Emit helpers, thread-summary job and D-12 rewrite | + +## Task 1 reply + +`proceed-and-push` + +## TestChatTracer + +pass (Docker available) + +## tea / push + +succeeded — `tea repos create --owner golem15 --name sm-chat-plugin`; `git push -u origin main` (never force). summercms.go was not pushed. + +## Deviations from Plan + +1. **Bind Channels empty on first tracer run (Rule 1).** `lighthouse.inSavepoint` clones the Message write's statement; a `Take` of Conversation on that handle kept the Message SELECT list, so `context_type` / `context_id` stayed nil and Channels returned empty (Pitfall 6). Fixed with a fresh session and an explicit column list (same idea as fonoteka `AlbumChannels`). Auto-fixed. + +2. **ROADMAP two-line patch skipped.** Phase 19 Repos already names D-15; SC-19-3 already has the Wavepath golden / `/_wave` wording. No patch. + +**Total deviations:** 2 auto-fixed / skipped. **Impact:** none on locked identifiers or the remote. + +## Verification + +``` +go -C ../sm-chat-plugin vet ./... # pass +go -C ../sm-chat-plugin test -count=1 -short ./... # pass +go -C ../sm-chat-plugin test -count=1 -run '^TestChatTracer$' -v . # PASS +``` + +Acceptance greps (Task 2 and Task 3): all pass. `family_id` count 0. `getFamilyGroupChat` count 0. + +## Issues Encountered + +None. + +## Next Phase Readiness + +Plan 19-02 can mount `/_chat/api/v1` on `classes.Service`. Hosts register contexts via `*contracts.Registry`. Wavepath `/_wave` route parity stays out (SC-19-3). + +## Self-Check: PASSED