Conversation
There was a problem hiding this comment.
🟡 Changes recommended
A confirmed NullPointerException risk exists in SiteService.normalizeMusicManifestUrl() (host null handling), and it should be addressed before merging.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR introduces the Stage 5 “knowledge garden” vertical slice: a new public /api/v1/public/garden endpoint (with caching/ETag), corresponding OpenAPI + generated TS client updates, and a Nuxt /garden page that renders an SSR-first timeline with an optional desktop-only Canvas force graph. It also expands site experience feature flags (music + home 3D) end-to-end (DB → API → Studio settings → public site response) and updates Compose/env/docs accordingly.
Changes:
- Add
/api/v1/public/gardencontract + backend graph builder with deterministic truncation (200 nodes / 600 edges) and conditional 304 semantics. - Add web
/gardenpage with SSR timeline fallback and a client-only, constrainedd3-forceCanvas renderer; add E2E/unit tests. - Add site experience flags (
musicEnabled,threeDEnabled) andHAOBLOG_MUSIC_MANIFEST_URLconfig validation + migrations + Studio UI.
File summaries
| File | Description |
|---|---|
| pnpm-lock.yaml | Locks new d3-force and its types for the garden Canvas renderer. |
| packages/api-client/src/generated.ts | Regenerated client types for new garden endpoint + new site flags/fields. |
| infra/compose/compose.prod.yml | Adds HAOBLOG_MUSIC_MANIFEST_URL to prod API container env. |
| infra/compose/compose.dev.yml | Adds HAOBLOG_MUSIC_MANIFEST_URL to dev API container env. |
| infra/compose/.env.ci.example | Documents HAOBLOG_MUSIC_MANIFEST_URL in CI env template. |
| docs/本地启动指南.md | Documents Stage 5 music manifest env var semantics and constraints. |
| docs/taget/阶段五准入清单.md | Adds Stage 5 admission checklist and recorded local verification results. |
| docs/taget/第五阶段目标任务.md | Adds Stage 5 goals/tasks doc including garden/music/flags boundaries. |
| docs/openapi/public-api.yaml | Adds /api/v1/public/garden + garden schemas; extends site schemas with flags/manifest URL. |
| apps/web/test/public-garden.test.ts | Unit test for deterministic SSR/browser ordering in garden timeline sorting. |
| apps/web/package.json | Adds d3-force dependency and @types/d3-force. |
| apps/web/nuxt.config.ts | Removes noindex override for /garden route metadata policy. |
| apps/web/e2e/stage5.spec.ts | E2E coverage for SSR/no-JS constrained paths + desktop canvas + tools query locate. |
| apps/web/app/utils/publicSite.ts | Extends default public site model with new experience flags + manifest URL. |
| apps/web/app/utils/publicGarden.ts | Adds shared garden graph types + sorting/label/date helpers for SSR timeline. |
| apps/web/app/pages/tools.vue | Supports ?tool= deep-linking by expanding and scrolling to a tool entry. |
| apps/web/app/pages/studio/settings.vue | Adds Studio toggles for musicEnabled and threeDEnabled with optimistic-lock save. |
| apps/web/app/pages/garden.vue | Implements /garden SSR-first timeline + conditional Canvas graph mounting logic. |
| apps/web/app/components/garden/GardenCanvas.client.vue | Client-only Canvas force graph with lazy d3-force import and input/viewport gating. |
| apps/api/src/test/java/io/haoblog/site/application/SiteServiceTest.java | Adds tests for manifest URL normalization and safe public flag behavior when missing. |
| apps/api/src/test/java/io/haoblog/site/application/PublicFeedServiceTest.java | Updates sitemap test expectations after adding /garden. |
| apps/api/src/test/java/io/haoblog/site/application/GardenGraphServiceTest.java | Unit tests for deterministic graph build, clipping, weights, and internal href safety. |
| apps/api/src/test/java/io/haoblog/PublicApiTest.java | Adds MVC test coverage for /api/v1/public/garden and 304 behavior. |
| apps/api/src/test/java/io/haoblog/PublicApiIT.java | Updates sitemap integration test expectations after adding /garden. |
| apps/api/src/test/java/io/haoblog/GardenGraphIT.java | Integration test ensuring only public snapshots/active tools are exposed and ETag works. |
| apps/api/src/test/java/io/haoblog/ContentModelIT.java | Updates Flyway migration count for new V16 migration. |
| apps/api/src/test/java/io/haoblog/AdminCommentIT.java | Updates seed SQL for new site_setting columns; adds experience-flag + manifest requirement tests. |
| apps/api/src/main/resources/db/migration/V16__site_experience_flags.sql | Adds music_enabled + three_d_enabled columns to site_setting. |
| apps/api/src/main/resources/application.yml | Adds haoblog.site.music-manifest-url wiring. |
| apps/api/src/main/resources/application-prod.yml | Adds prod wiring for haoblog.site.music-manifest-url. |
| apps/api/src/main/java/io/haoblog/toolbox/application/ToolManagementService.java | Adds public garden tool read-model query + GardenTool record. |
| apps/api/src/main/java/io/haoblog/site/web/PublicSiteController.java | Extends public site response DTO with new flags + manifest URL field. |
| apps/api/src/main/java/io/haoblog/site/web/PublicGardenController.java | New controller exposing /api/v1/public/garden with ETag/304 and cache headers. |
| apps/api/src/main/java/io/haoblog/site/web/AdminSiteController.java | Extends admin update request/response to include experience flags. |
| apps/api/src/main/java/io/haoblog/site/domain/SiteSetting.java | Adds persisted fields for musicEnabled and threeDEnabled. |
| apps/api/src/main/java/io/haoblog/site/application/SiteService.java | Adds manifest URL normalization/validation and flag enforcement (incl. “must configure manifest before enabling music”). |
| apps/api/src/main/java/io/haoblog/site/application/PublicFeedService.java | Includes /garden in sitemap static URLs. |
| apps/api/src/main/java/io/haoblog/site/application/GardenGraphService.java | New service building deterministic, bounded garden graph from public article snapshots + active tools. |
| apps/api/src/main/java/io/haoblog/content/persistence/ArticleRevisionRepository.java | Adds native query projection to fetch public garden rows (article + taxonomy snapshots). |
| apps/api/src/main/java/io/haoblog/content/application/ArticleService.java | Adds public garden article list assembly/grouping for graph building. |
| .env.example | Documents HAOBLOG_MUSIC_MANIFEST_URL for local configuration. |
Review details
Files not reviewed (1)
- pnpm-lock.yaml: Generated file
- Files reviewed: 40/41 changed files
- Comments generated: 2
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| function scheduleDraw() { | ||
| if (frame || disposed) return | ||
| frame = requestAnimationFrame(() => { | ||
| frame = 0 | ||
| draw() | ||
| }) | ||
| } | ||
|
|
||
| function draw() { | ||
| if (!context || !canvas.value) return | ||
| const { width, height } = measure() | ||
| context.clearRect(0, 0, width, height) | ||
| const styles = getComputedStyle(canvas.value) | ||
| const accent = styles.getPropertyValue('--garden-accent') || '#a8ff60' | ||
| const line = styles.getPropertyValue('--garden-line') || 'rgba(168,255,96,.2)' |
变更
验证