m's feedback on 5i (verbatim): "It's not really what I wanted. It
should like the paliad custom views, not of the existing views a
variant but individually created views."
5i modelled views as overlays on existing pages (?view=<uuid>). m wants
the paliad model: views are first-class URLs (/views/{slug}), each one
its own page. System defaults (dashboard, calendar, timeline, ...)
share the route shape with reserved slugs; user-created views land
beside them.
Plan covers: schema redesign (slug as URL key, drop is_default_for +
pinned, add icon + sort_order + show_count + last_used_at), four-route
table (landing with MRU redirect, render, editor blank/edit), system-
view shape (hybrid alias recommendation under Q1), editor surface
(dedicated pages, not modal), migration path from 5i (drop table +
delete overlay code; keep view_type enum and per-view_type renderers),
seven-slice implementation chain (A schema → B routes → C system views
→ D editor → E sidebar → F cleanup → G polish).
11 open questions batched in §9 — head delegation pending. NO chip-
picker without head's explicit re-grant (5i permission was one-time).
No code changes; this branch ships docs only. Coder shifts wait on m's
sign-off via head's relay.
m answered every open question directly via AskUserQuestion (greenlit
for inventor 2026-05-26 13:12). New §8.5 captures the picks + slice
implications. Inventor picks held on 6 of 9; m differed on Q5 (project
filter descendants) — wants an include-descendants toggle on the chip
rather than always-on, so Slice A grows an `IncludeDescendants` field
on TreeFilter + a toggle on the picker chip.
view_type enum locks at 5 (card/list/calendar/kanban/timeline). All
four out-of-scope items stay parked. No other slice changes.
Phase A (design) of Phase 5i — project filter dim, view-type as a
parameter, saved views, and per-page bindings. Five-slice implementation
plan (A: project filter → B: view-type URL → D: saved-views schema → C:
kanban → E: defaults). Nine open questions for m batched in §9 ready
for head delegation.
No code changes; this branch ships docs only. Coder shifts wait on m's
sign-off via head.
Phase 5c slice A. Pulls the structural rules out of the Postgres
triggers into a Go-side validator. The trigger stays as defence in
depth; the validator is the human-facing error path.
- docs/plans/itemwrite-validation.md enumerates every rule the
triggers in 0001 + 0010 enforce, with the ValidationError.Kind
callers will see for each. Eleven rules total (two SQL-only safety
rails kept untranslated).
- internal/itemwrite/itemwrite.go: ValidationError + Input + Reader
interface + ValidateFormat (pure: missing fields, slug format,
status whitelist, self-parent) + ValidateAgainstStore (DB-aware:
unknown-parent, slug-collision under any common parent, cycle via
ancestor-closure DFS capped at 64 hops to mirror the trigger).
- Eight kind constants exported: missing-required, invalid-slug-format,
invalid-status, slug-collision, cycle, self-parent, unknown-parent,
unresolvable-path.
Tests cover every kind on both happy and reject paths: missing /
whitespace fields, slug containing dot / upper / whitespace, invalid
status enum, self-parent guard, unknown parent id, root slug collision,
sibling slug collision under common parent, cycle on ancestor closure,
and the "Reader returns ListAll error → validator returns nil" path
(callers see the infra error later, validator doesn't mask it).
No caller migrates yet. Same Go-linker DCE caveat as 5a/5b slice A:
`strings <binary> | grep internal/itemwrite` returns 0 until slice B
imports.
Task: t-projax-5c-itemwrite
Phase 5a slice A: a new package that concentrates the "fan out across
linked items" pattern web/dashboard.go, web/timeline.go and mcp/tools.go
each had separate copies of. No callers touch it yet — slices B/C/D
migrate them in turn.
- Aggregator with five methods (Todos/Events/Issues/Docs/Creations) plus
All convenience for the MCP timeline. Each method takes a *store.Item
slice and (optionally) a Window, returns typed Row slices.
- Row types embed the underlying caldav.Todo / caldav.Event / gitea.Issue
so existing html/template field accesses (.Todo.UID, .Event.Summary,
…) keep resolving via Go field promotion in slices B/C.
- TimelineRow sum-type wrapper (with pointer slots per Kind) plus the
flat template-friendly fields. Lifted-but-untouched from web/.
- BuildTimelineDays + SortTimelineRows + EventStartLabel +
EventDurationHint lifted near-verbatim from web/timeline.go.
- CalDAV/Gitea/Store interfaces in the aggregator so unit tests stub IO
cleanly. Real *caldav.Client / *gitea.Client / *store.Store satisfy
by method set.
- Per-source error handling preserved: log at WARN + skip the bad
fetch, return surviving rows.
Tests cover empty inputs, fan-out call counts, per-source error
recovery, window narrowing for todos, issue-cache hit path, doc/creation
allow-list filtering, BuildTimelineDays asc/desc order, sticky pills,
far-future fade, within-day sort.
Plan doc captures the slicing strategy + design decisions:
docs/plans/aggregator-refactor.md.
Task: t-projax-5a-aggregator
Phase A of the 4c task brief. Survey found the integration already
exists and ships (mAi#228, 2026-05-15) — the question is which slice
deepens it next.
Plan covers:
- Otto-PWA structural notes (Go backend + Bun/TS frontend in m/mAi, not
m/otto — ADR-006 moved PWA code into mAi)
- Existing MCP-consumption pattern (Bearer-token JSON-RPC bridge,
graceful 501 degradation, 4 endpoints registered, frontend shells +
client TS, live at https://otto.msbls.de/projax/)
- 3 deepening slices: (S1) timeline surface, (S2) CalDAV writeback,
(S3) dated docs quick-add
- Recommendation: ship (S1) first — Phase 4a just landed /timeline
in projax web, the data + aggregation logic exist, exposing via MCP
is a clean wrap with no schema or auth model change
- Impl plan if greenlit: 3 slices across projax + mAi with cross-repo
deploy verification
Out of scope until head greenlights: writing any code in m/mAi.
Per docs/plans/mgmt-teardown.md §4 steps 5 + 6.
Step 5: deploy/dokploy.yaml — stale "federated with mgmt.msbls.de" line
in the header comment replaced with the current host-scoped /login cookie
model. The mgmt federation never happened in projax anyway (projax
cookies are host-scoped, no Domain attribute).
Step 6: append a "DONE 2026-05-16" section to docs/plans/mgmt-teardown.md
recording every step's commit hash across both repos, the head-approved
deviation from §4 step 1 (SvelteKit-side redirect instead of Dokploy
Traefik labels — Dokploy config is UI-only), verification curls, and the
post-teardown janitorial that's out of scope for the worker (env-var
cleanup in Dokploy, DNS at m's leisure).
m/msbls.de side merged separately (86bfa61) — three commits:
2941dc4 (redirect), <previous step's commit covers the rest>.
Research-only output: audit of every /mgmt/* route + auth shell + server
libs in m/msbls.de, mapping to projax equivalents, gap list, migration
sequence, risk register.
Headline:
- 4 mgmt routes audited (root, /login, /self redirect, /mgmt/* guard)
- 3 already at parity on projax (login, auth guard, CalDAV VTODOs)
- 1 small gap (VEVENTs on dashboard) is the only blocker — Phase 3l candidate
- 2 further "gaps" (mWorkRepo cards, mBrian topic cards) recommended
park-forever; mgmt never shipped them either
- Cross-repo grep confirms ZERO external dependencies on /mgmt/* — only
one stale comment in projax/deploy/dokploy.yaml
No code touched. m reads the plan + decides go/no-go on Gap 1 + migration
sequence (§4) before any teardown work.