← Galaxy / notesorg-wide / engineering-docs-operations-simplify-backlog

Simplify backlog

engineering-docs-operations-simplify-backlog · in engineering/docs/operations · org-wide · updated 2026-06-01 10:19

Frontmatter

lang
en
imported_at
2026-06-01T10:19:43.442Z
source_path
productgalaxy/docs/operations/SIMPLIFY-BACKLOG.md
source_repo
productgalaxy

Simplify backlog

Deferred from the first /simplify pass (2026-05-25). Each item is a real find from one of the 3 review agents. We landed the 5 highest-leverage fixes inline + parked the bigger refactors here because they touch many files at once.

Reports lived at /tmp/simplify-{reuse,quality,efficiency}.md — re-spawn the agents to regenerate.

Landed in commit <simplify pass 1>

  1. BUG apps/app/src/api/v1/audit-issues.ts:83or(eq(x, b), eq(x, b))or(eq(x, b), isNull(x)). Silently missed global taxonomies for audit_issues.
  2. BUG packages/db/src/schema/entity_links.ts — added 'embed' to entityLinkRelation enum (referenced in notes.ts wikilink resolver but missing → runtime error on Obsidian ![[note]] embeds).
  3. DUPE deleted apps/mcp/src/lib/jcs.ts; rewired the 2 import sites to @galaxy/db/jcs (which was already exported but the local copy lingered with a TODO).
  4. PERF apps/app/src/api/middleware/business-scope.ts — added in-memory TTL cache (5 min) for slug→id. Was a DB roundtrip per request before; now ~1 roundtrip per slug per 5 min.
  5. LEAK apps/app/src/api/middleware/idempotency.ts — added hourly setInterval GC (unref'd). Was only GC'd lazily on each request, so low-traffic memory grew unbounded.

Deferred — high leverage but multi-file (do in dedicated PRs)

A. Route-list factory (~600 LOC saved) — STILL DEFERRED

Every v1 GET list endpoint (audits, pm-tasks, pm-pipeline, abtests, comments, comment-insights, notes, tags, businesses, taxonomies) has the same skeleton:

  • decode cursor → (date,id) tuple
  • build WHERE from optional query filters
  • ORDER BY (date, id) DESC + LIMIT N+1
  • map rows → response shape via rowToX(r, businessSlug)
  • envelope as CursorPage<T>

Proposal: extract apps/app/src/api/middleware/list-factory.ts exporting a registerList({ router, path, table, rowMap, filters }) helper. Each list endpoint collapses from ~40 LOC to ~10.

Why still deferred: 60+ @ts-expect-error suppressions sit at .openapi(...) boundaries in close proximity to these routes (see §S). Re-positioning them risks invalidating dozens at once. Wait for upstream @hono/zod-openapi 1.5+ Handler-type fix before tackling.

B. ✅ DONE in 068d1ad — FK resolvers lifted to @galaxy/db/resolvers

loadBusinesses, resolveBusinessId, loadTaxonomies (now takes onRow callback), resolveTaxonomyId*, rememberTaxonomy, findMissingBusinessSlugs, tryResolveBusinessId, clearSharedResolverCaches live in packages/db/src/resolvers.ts. Each importer re-exports + adds LocalCaches for domain-specific state (audits: page/team/issue, pm: taxonomyByNameFa + team-by-name + pm_task/pm_pipeline, comments: issueBySlug).

C. ✅ DONE in 068d1ad — display-IDs lifted to @galaxy/db/display-ids

BIZ_PREFIX_MAP + bizPrefix() + pad3() consolidated. Fixed long-standing drift: 6 inline slug.slice(0,3).toUpperCase() shims (4 in apps/app + 2 in apps/mcp) used to yield TEL for televika while importers used TVK. Now both paths agree.

D. ✅ DONE in fb4455esummaryAudit() shipped

summaryAudit({domain, entityId, after}) in @galaxy/db/audited-write; 18 importer phase-tail sites migrated. SummaryDomain closed union catches typos like audit_isssues.

E. ✅ DONE in d0d7d6b — Persian byte utilities lifted

countZWNJ, assertEnIsAscii, emptyToNull, slugify, parseDateUTC available from @galaxy/db/bilingual.

F. ✅ DONE in <this commit>Limit const + CursorString adopted

packages/shared/src/common.ts exports CursorString + Limit + PaginationQuery + BusinessQuery. 13 inline 5-line limit: z.union(...).transform(...).pipe(...).default(50) declarations across 5 domain schemas collapsed to limit: Limit. Two outliers (notes' max(50) curated lists, comments' max(5000) ingest) intentionally inline.

G. ✅ DONE in 068d1ademitFieldAuditDeltas() shipped

6 PATCH/subtask handlers' 18-line for ... auditedWrite(...) ladders replaced. keyAliases covers FK-vs-slug remaps (phase_slug → phase_id); skipFields covers non-column fields (commit_message on notes).

H. ✅ DONE in <this commit>entityLinkRelation type derived

notes.ts:1123-1124 + :1177-1179 hand-rolled 'wikilink' | 'embed' | … unions replaced with type EntityLinkRelation = (typeof schema.entityLinkRelation.enumValues)[number]. Adding a new variant in entity_links.ts now propagates automatically.

I. ✅ DONE — N+1 batched on all 3 list endpoints

  • notes.ts: shipped in ad1e490 (hydrateLinkedEntitiesBatch)
  • audit-issues.ts: already batched at lines 199-234 (inArray joins)
  • pm-tasks.ts: shipped in <this commit> — new loadJoinMaps() + joinTaskRowWithMaps() collapse ~140 round-trips per page to 3 IN(...) queries.

J. ✅ DONE in <this commit> — importer INSERT batching

  • importers/audits/src/issues.ts: 159 audit_issues + N audit_issue_pages went from per-row INSERTs to 2 batched calls (one for issues, one for the M:N junction). Uses Postgres excluded.* for the conflict SET clause.
  • importers/pm/src/master.ts: upsertPmTask replaced with batched upsertPmTasks(inputs); each phase (stories/tasks/tombstones) accumulates inputs and flushes once. Team auto-provisioning still inline (ordering-dependent).
  • ~460 importer round-trips collapsed to 4. @galaxy/importer-comments was already batched (500-row chunks).

K. ✅ DONE in fb4455eextractBearer canonicalized

Single source in packages/auth/src/middleware.ts; apps/mcp/src/lib/jwt.ts re-exports as a back-compat shim. Follow-up: migrate the 2 callers off the shim and delete it.

L. ✅ DONE in <this commit>createPgClient() factory shipped

packages/db/src/client.ts exports createPgClient({ mode }) with 4 modes (app / migrator / eval / script) covering all 4 callsites: client.ts, migrate.ts, scripts/eval/_eval-utils.ts, tools/issue-admin-jwt.ts. Argon2 params already lifted to @galaxy/db/argon2-params in d0d7d6b.

Deferred — low value (skip unless follow-on changes force it)

M. Trim narrating top-of-file comments — DEFERRED (judged not worth pursuing)

Re-reviewed in <this commit>: most "narrating" comments in routes are actually route-table summaries (e.g. notes.ts opens with a list of every endpoint + its idempotency/audit semantics) that serve as navigation aids in 1k+-line files. Trimming them risks information loss for marginal LOC savings. Future cleanup should be selective per-file rather than a blanket pass.

N. ✅ DONE — void inArray; void KIND_MAP; workarounds already removed

Grep finds zero hits. Cleaned up in earlier sprints.

O. <Card>/<CardHeader> wrapper noise in apps/app/src/app/admin/notes/page.tsx

Reviewed previously and judged not applicable — those Cards provide real visual structure (border, hover-affordance), not redundant nesting.

P. ✅ DONE — defensive rows.rows dance no longer present

Grep across apps/app/src + apps/mcp/src returns zero hits for Array.isArray.*rows.*rows or rows.rows. Cleaned up incrementally in earlier sprints.

Q. Hand-rolled error handling in notes-vault.ts

Reviewed previously and judged not applicable — the catch + problemJson(...) blocks return semantic per-call detail messages (not generic 500s); centralizing them would lose error context.

R. ✅ DONE in <this commit>exactOptionalPropertyTypes: true enabled globally

Root tsconfig.json now has exactOptionalPropertyTypes: true. Required edits to keep typecheck clean across all 11 packages:

  • importers/comments/src/insights.ts: drop source_comment_legacy_id: undefined (omit instead).
  • importers/pm/src/relations.ts: type the relatedItems?: RelatedItem[] | undefined array entry explicitly.
  • apps/mcp/src/index.ts: 2 as never casts on the SDK's StreamableHTTPServerTransport({ sessionIdGenerator: undefined, … }) ctor + server.connect(transport) (SDK type signature gap).
  • apps/app/src/lib/api-client.ts + 5 admin-UI prop interfaces: widen ?: T to ?: T | undefined where callers pass already-extracted string | undefined values.

S. Suppressions now down to 52 (was 76) — Handler-type drift remains

After <this commit>:

  • Removed 22 noUncheckedIndexedAccess + .returning() suppressions in apps/app/src/api/v1/{pm-tasks,notes}.ts via firstRow() helper.
  • 52 @hono/zod-openapi 1.x Handler-type drift suppressions remain. Verified upstream: @hono/zod-openapi 1.4.0 is the latest release; the type bug persists. Drop blocked until 1.5+ ships.
  • 2 new as never markers on the MCP SDK transport (see R). Different class — SDK type gap, not a missing column-type narrowing.

T. ✅ DONE — apps/mcp Vitest 80/80 passing

Test helper rewired through the SDK's public discovery API. Verified in <this commit> + every recent commit.

How to revisit

Re-run /simplify periodically (or via the pre-commit hook). Each item above includes the file:line refs so the next pass can verify what's still outstanding.

Outbound links (0)

This note doesn't reference any other entity.

Version history (1)

  • v12026-06-01 10:19"galaxy-docs importer: initial import"