Files
geo/findings.md
T
root 446f865cdf feat: add knowledge management functionality with CRUD operations and database schema
- Implemented KnowledgeHandler for managing knowledge groups and items, including listing, creating, updating, and deleting operations.
- Added database migration scripts to create necessary tables for knowledge management, including knowledge_groups, knowledge_items, knowledge_parse_tasks, and knowledge_chunks_meta.
- Introduced prompt_rule_knowledge_groups table to associate prompt rules with knowledge groups.
2026-04-05 17:14:13 +08:00

110 lines
15 KiB
Markdown

# Findings & Decisions
## Requirements
- Verify the repository against the 9-step implementation plan provided by the user.
- Use `/Users/liangxu/Documents/test/geo-rankly/docs/superpowers/specs/2026-03-31-admin-web-backend-core-design.md` as the source of truth for the next development slice.
- Continue development immediately after identifying the earliest unfinished step.
## Research Findings
- The repository already contains core backend scaffolding under `server/`, including `cmd/tenant-api`, `internal/bootstrap`, `shared`, `tenant`, `migrations`, and SQL query files.
- `server/Makefile` already defines `dev-init`, `dev-api`, `migrate-up`, `sqlc-generate`, `seed`, `lint`, and `test`.
- The bootstrap layer already exposes `/api/health/live` and `/api/health/ready`.
- The design doc defines a sequential 9-step delivery plan and expects `sqlc` generated code under `internal/tenant/repository/generated/`, plus repository wrappers around it.
- The repository has 19 migration `.up.sql` files, matching the plan's schema count, and `cmd/dev-seed` seeds `admin@geo.local` plus plan/quota/template data.
- `internal/tenant/repository/` currently contains only query SQL, `sqlc.yaml`, `tx.go`, and placeholder integration tests; there is no `generated/` directory and no repository wrapper implementations.
- `auth_service.go`, `workspace_service.go`, `template_service.go`, `article_service.go`, and `brand_service.go` still issue SQL directly against `pgxpool.Pool`, which contradicts the design doc's Step 4 target.
- Running `make sqlc-generate` currently fails because `server/internal/tenant/repository/sqlc.yaml` sets `schema: "../../migrations/"`, which resolves to a non-existent path. The correct repository-relative path should point to `server/migrations`.
- After fixing `sqlc.yaml`, `make sqlc-generate` succeeds and produces typed code in `server/internal/tenant/repository/generated/`.
- Repository wrappers now exist for auth, workspace, template, article, quota, and audit queries, and the auth/workspace/template services consume them on the main code path.
- Refresh token rotation is now atomic in Redis via a Lua script in `session_store.go`, with tests covering successful rotation and hash mismatch rejection.
- `make test` and `make lint` both pass locally after cleaning up existing lint violations.
- A GitHub Actions workflow now exists at `.github/workflows/backend-ci.yml`; it runs `sqlc` generation, verifies generated code is committed, executes the tenant SQL scope guard, runs tests, and runs `golangci-lint`.
- The `server/Makefile` now exposes `tenant-scope-guard`, so the tenant filter check is available both locally and in CI.
- The `server/Makefile` no longer depends on a preinstalled `migrate` binary; it now runs `golang-migrate` via `go run -tags postgres`, which allowed `make dev-init` to run successfully on this machine.
- `make dev-init` now completes end-to-end: Docker services start, all 19 migrations apply, and seed data creates tenant/user/plan/template records.
- Runtime verification succeeded for `/api/health/live`, `/api/health/ready`, `POST /api/auth/login`, `GET /api/auth/me`, `POST /api/auth/refresh`, and `POST /api/auth/logout`.
- Negative auth checks also passed at runtime: the old access token returns `40103 token_revoked` after logout, and the old refresh token returns `40121 refresh_session_expired` after rotation.
- Workspace runtime verification passed for all four first-screen endpoints: `overview`, `recent-articles`, `quota-summary`, and `template-cards`.
- Template generation runtime verification passed end-to-end: creating a generation task produced an article, article detail returned `generate_status=completed`, article versions returned one version, and quota balance decreased from 100 to 99.
- Brand runtime verification passed for create keyword/question/competitor flows, question version history returned two versions after update, and soft-deleted brands can be recreated with the same name.
- The repository still has no `apps/` or `packages/` directories, so neither `admin-web` nor `ops-admin-web` has been started.
- The frontend architecture doc recommends `pnpm workspace + Vue 3 + TypeScript + ant-design-vue + Vite`, with shared packages for UI, shared DTOs, HTTP client, and TS config.
- The current backend already exposes enough stable endpoints for a first `admin-web` slice: `POST /api/auth/login`, `GET /api/auth/me`, and the four workspace endpoints under `/api/tenant/workspace/*`.
- Backend responses use a consistent envelope: `code`, `message`, `data`, and `request_id`, which makes a shared frontend API client straightforward.
- Local toolchain support for the frontend is present on this machine: `node v22.20.0`, `npm 10.9.3`, and `pnpm 10.28.2`.
- A new pnpm workspace now exists at the repo root, with `apps/admin-web` plus shared packages under `packages/shared-types`, `packages/http-client`, and `packages/tsconfig`.
- `apps/admin-web` is now a working Vue 3 + TypeScript + Vite 8 app with Ant Design Vue, Pinia, Vue Router, and Vue Query wired in.
- The frontend implements a persistent auth session store, login flow, route guard, auto-refresh-capable API client, and a tenant-facing application shell.
- The workspace page is wired to live backend data through the four dashboard endpoints and renders template cards, stats, quota, and recent articles.
- Placeholder routes now exist for template creation, custom generation, optimization, media, brands, tracking, and knowledge so the navigation shell is ready for incremental page delivery.
- `pnpm build:admin` passes successfully, producing a production build under `apps/admin-web/dist/`.
- Static preview verification passed via `vite preview` and HTTP checks against `http://127.0.0.1:4173/login`, which returned `HTTP/1.1 200 OK` plus the built asset references.
- Gemini CLI was tested but then abandoned for this turn: `gemini-3.1-pro-preview` consistently returned `429 MODEL_CAPACITY_EXHAUSTED`, and the user explicitly requested not to use Gemini afterward.
- After the user indicated Playwright was fixed, browser-level verification succeeded through the Playwright CLI path rather than the broken MCP path.
- Browser testing exposed one real frontend bug: the login CTA rendered correctly but did not submit the form on click until it was explicitly bound to `handleSubmit`.
- After the login-button fix, a Playwright end-to-end flow successfully loaded `/login`, signed in with the seeded account, reached `/workspace`, and verified the presence of the workspace heading plus the template and recent-content sections.
- The production bundle size improved substantially after switching Ant Design Vue registration from full-plugin mode to per-component registration; the main JS chunk dropped from roughly `1.4 MB` to about `747 kB` before gzip.
- The currently exposed tenant-facing backend interfaces fall into four frontend-covered groups: auth, workspace, templates/articles, and brands.
- The reference screenshots were re-read using position-aware OCR extraction, which made the layout intent clear beyond the raw text labels.
- `docs/refer/工作台.png` places the main content in a left-heavy column with template cards above recent articles, while the right side holds the compact stats cluster; the quota/plan card sits in the left sidebar footer rather than the main canvas.
- `docs/refer/模板创作.png` uses a top page hero, a horizontal filter/action strip, an article table below it, and a separate template-selection layer before entering a 3-step generation flow.
- `docs/refer/文擎GEO/模版创作-新建模版-创建topx文章-步骤一.png` and `...步骤二.png` show the generation flow as a wizard: step 1 basic info plus brand/keyword/competitor context, step 2 title and structure selection, step 3 generation.
- `docs/refer/品牌词库.png` uses a top brand card rail, then a split content area with keyword navigation on the left and question management on the right; the competitor library lives under a sibling tab.
- `docs/refer/媒体管理.png` confirms the overall visual system: page hero under the content header, three-step guide card near the top, and white cards on a cool gray background with the same left navigation shell.
- The user explicitly asked for i18n and styling discipline during implementation: text should move behind translation keys, and component styles should live in `<style>` blocks rather than inline attributes.
- `pnpm dev:admin` regressed temporarily after the route graph referenced a missing `BrandsView.vue`; adding the missing view, installing the new frontend dependency set, and rerunning checks restored the Vite startup path.
- `pnpm typecheck:admin` now passes after introducing the i18n scaffold, restoring `AppShell.vue` to the user's preferred version, and removing inline styles from the Vue SFC templates.
- The currently used hard-coded prompts are concentrated in four runtime areas: `cmd/dev-seed` platform template seeds, `template_prompt.go` generation fallback sections, `template_assist.go` analyze/title/outline fallback prompts, and `prompt_generate_service.go` plus `knowledge_service.go` prompt supplements.
- The seed path stores four full article prompt templates plus twelve wizard prompt templates inside large inline JSON blobs, which makes prompt iteration awkward and easy to miss during later tuning.
- Runtime prompt assembly still embeds section titles, writing rules, output requirements, output examples, and knowledge-reference instructions directly inside application functions.
- A dedicated prompt hub now exists under `server/internal/tenant/prompts/`: `template_seeds.go` owns the four platform template seeds and their wizard prompt templates, while `runtime.go` owns generation fallback prompts, assist fallback prompts, prompt-rule supplements, and knowledge prompt instructions.
- `cmd/dev-seed` now reads platform templates from `prompts.PlatformTemplateSeeds()` instead of carrying 400+ lines of inline prompt/card-config text in the command itself.
- `template_prompt.go`, `template_assist.go`, `prompt_generate_service.go`, and `knowledge_service.go` now assemble prompts from the centralized prompt package, so runtime business logic no longer embeds the long prompt text directly.
- The prompt centralization also corrected invalid JSON quoting in the seed card config `custom_placeholder` fields, which previously contained unescaped inner quotes.
- Targeted verification passed with `go test ./internal/tenant/... ./cmd/dev-seed` from `server/`, confirming the refactor compiles cleanly across the affected runtime and seed paths.
## Technical Decisions
| Decision | Rationale |
|----------|-----------|
| Verify by code inspection first, then run targeted commands | Faster way to establish step coverage before making changes |
| Use the design doc as the acceptance reference when repository behavior is ambiguous | User explicitly pointed to this document for next-step development |
| Treat Step 4 as the current development target unless command verification disproves it | Earlier steps have visible artifacts, but repository/sqlc acceptance is not yet met |
| Fix `sqlc` generation and introduce repository wrappers before touching later roadmap items | This is the first broken acceptance gate and an architectural dependency for the service layer |
| Close Step 9 by adding repository-scoped CI rather than a repo-wide generic pipeline | The remaining missing acceptance item was backend CI plus the tenant scope guard |
| Resume into `admin-web` instead of `ops-admin-web` | Only tenant-facing APIs exist in the repository today, so this is the only frontend slice that can be meaningfully wired end to end |
| Keep the initial frontend page set broad in navigation but shallow in implementation | This gives the repo a usable admin shell now without inventing missing backend modules for later pages |
| Use templates/articles and brands as the primary implementation targets for this turn | They are the remaining backend-backed pages still missing real frontend coverage |
| Use screenshot-derived spatial structure as an implementation constraint | Needed to satisfy the user's requirement to follow layout and placement, not just labels |
| Introduce a minimal `vue-i18n` foundation now instead of leaving hard-coded strings in new pages | The user explicitly called out the current i18n approach as non-standard |
| Keep `AppShell.vue` on the user-preferred version and avoid structural/style rewrites there | The user said that file is managed elsewhere and only allowed inline-style cleanup |
| Create a dedicated `internal/tenant/prompts` package for prompt text and seed definitions | This keeps prompt tuning in one place while minimizing refactor risk in the current dirty worktree |
## Issues Encountered
| Issue | Resolution |
|-------|------------|
| Repository is fully untracked in git status output | Avoid relying on git history; verify via filesystem and test commands instead |
| `make sqlc-generate` fails before any code is generated | Repair the `sqlc.yaml` schema path and then build repository wrappers around generated queries |
| `go run` migrate initially failed with `unknown driver postgres` | Added `-tags postgres` to the Makefile-managed migrate command |
| Playwright MCP could not open a browser session locally because it tried to create `/.playwright-mcp` | Use `vite preview` plus `curl` verification for this turn instead of spending time on browser tool plumbing |
## Resources
- `/Users/liangxu/Documents/test/geo-rankly/docs/superpowers/specs/2026-03-31-admin-web-backend-core-design.md`
- `/Users/liangxu/Documents/test/geo-rankly/server/Makefile`
- `/Users/liangxu/Documents/test/geo-rankly/server/cmd/tenant-api/main.go`
- `/Users/liangxu/Documents/test/geo-rankly/server/internal/bootstrap/bootstrap.go`
- `/Users/liangxu/Documents/test/geo-rankly/server/internal/shared/auth/session_store.go`
- `/Users/liangxu/Documents/test/geo-rankly/server/internal/tenant/repository/sqlc.yaml`
- `/Users/liangxu/Documents/test/geo-rankly/server/scripts/check_tenant_scope.sh`
- `/Users/liangxu/Documents/test/geo-rankly/.github/workflows/backend-ci.yml`
- `/Users/liangxu/Documents/test/geo-rankly/server/docker-compose.yaml`
- `/Users/liangxu/Documents/test/geo-rankly/apps/admin-web`
- `/Users/liangxu/Documents/test/geo-rankly/packages/shared-types/src/index.ts`
- `/Users/liangxu/Documents/test/geo-rankly/packages/http-client/src/index.ts`
## Visual/Browser Findings
- Reviewed the reference screenshots for `工作台.png` and `模板创作.png` and matched the new UI to the same left-nav plus airy card/table composition.
- Browser automation verification was attempted but blocked by the local Playwright MCP directory error; preview HTTP verification succeeded instead.
- Later browser verification succeeded with Playwright CLI, and the captured login/workspace screenshots matched the intended layout and data density.
- Position-aware OCR of the reference images confirmed the sidebar navigation occupies roughly the left 10-12% of the frame, with content titles aligned at the upper-left of the main canvas and most action buttons aligned to the right edge of page headers.
- The workspace screenshot places stats on the upper-right and the recent-articles table directly beneath the template card block, so the existing all-grid treatment should be tightened into a more asymmetric two-column composition.