a02ed4e79f
Desktop Client Build / Resolve Build Metadata (push) Successful in 24s
Frontend CI / Frontend (push) Successful in 2m56s
Backend CI / Backend (push) Failing after 8m6s
Desktop Client Build / Build Desktop Client (push) Successful in 24m4s
Desktop Client Build / Publish Client Artifacts to NAS (push) Successful in 50s
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
984 lines
79 KiB
Markdown
984 lines
79 KiB
Markdown
# Progress Log
|
|
|
|
## Session: 2026-04-30
|
|
|
|
### Phase 37: k3s Deployment Foundation
|
|
- **Status:** complete
|
|
- Actions taken:
|
|
- Recovered the existing Docker Compose deployment topology and runtime command set.
|
|
- Added a self-contained `deploy/k3s` kustomize deployment with namespace, config, placeholder secrets, infra StatefulSets, app Deployments/Services, migration/minio-init Jobs, and Traefik Ingress.
|
|
- Included all server-side runtime services: `tenant-api`, `worker-generate`, `kol-assist-worker`, `scheduler`, `ops-api`, plus `frontend` and `ops-web`.
|
|
- Added `Dockerfile.ops-web` so the operations frontend can be built as a deployable nginx image.
|
|
- Updated the offline packaging script to build/save `ops-api`, `kol-assist-worker`, and `ops-web`, and to include the k3s directory in generated deploy packages.
|
|
- Updated the offline compose override and `.env.example` with the missing ops/security knobs.
|
|
- Files created/modified:
|
|
- `Dockerfile.ops-web` (created)
|
|
- `deploy/k3s/` (created)
|
|
- `deploy/docker-compose.yaml` (updated)
|
|
- `deploy/scripts/package.sh` (updated)
|
|
- `deploy/docker-compose.offline.yaml` (updated)
|
|
- `deploy/.env.example` (updated)
|
|
- `task_plan.md` / `findings.md` / `progress.md` (updated)
|
|
|
|
### Phase 38: k3s Verification
|
|
- **Status:** complete
|
|
- Verification:
|
|
- `kubectl kustomize deploy/k3s` rendered 30 Kubernetes objects.
|
|
- Local YAML parsing of the rendered manifest passed.
|
|
- `bash -n deploy/scripts/package.sh && bash -n deploy/scripts/load-and-start.sh` passed.
|
|
- `git diff --check` passed.
|
|
- `pnpm --filter ops-web build` passed.
|
|
- `pnpm --filter admin-web typecheck` passed.
|
|
- Notes:
|
|
- `kubectl apply --dry-run=client` could not complete locally because the configured kube-apiserver at `127.0.0.1:26443` is not running; run live API validation on the target k3s node.
|
|
|
|
## Session: 2026-04-20
|
|
|
|
### Phase 20: Tracking Collect-Now Repair
|
|
- **Status:** complete
|
|
- Actions taken:
|
|
- Re-read the `admin-web` tracking page, monitoring API client, and tenant monitoring handler/service chain to isolate why `立即采集` still depended on the removed browser-plugin runtime.
|
|
- Confirmed the frontend was still blocking on `monitoring-plugin` readiness and trying to kickoff a plugin cycle even though monitoring collection is now meant to run silently through `desktop-client`.
|
|
- Added monitoring dashboard runtime state so the page now knows whether the current logged-in user's own desktop client is online.
|
|
- Tightened `collect-now` server validation to only accept requests when the current actor has an online desktop client, instead of falling back to another online client in the same workspace.
|
|
- Updated `TrackingView.vue` to remove the plugin kickoff path, call only the backend `collect-now` endpoint, and disable the CTA with an explicit reason tooltip when brand/keyword/client-online requirements are not met.
|
|
- Added the missing `desktop_client_offline` frontend error mapping plus new i18n strings for the button gating reasons.
|
|
- Files created/modified:
|
|
- `task_plan.md` (updated)
|
|
- `findings.md` (updated)
|
|
- `progress.md` (updated)
|
|
- `apps/admin-web/src/views/TrackingView.vue` (updated)
|
|
- `apps/admin-web/src/i18n/messages/zh-CN.ts` (updated)
|
|
- `apps/admin-web/src/i18n/messages/en-US.ts` (updated)
|
|
- `apps/admin-web/src/lib/errors.ts` (updated)
|
|
- `packages/shared-types/src/index.ts` (updated)
|
|
- `server/internal/tenant/app/monitoring_service.go` (updated)
|
|
|
|
### Phase 15: Desktop Scheduler Design & Integration
|
|
- **Status:** complete
|
|
- Actions taken:
|
|
- Re-read the planning files and recovered the current desktop AI monitoring scope from the existing repo changes.
|
|
- Audited the desktop runtime controller, process metrics sampler, runtime snapshot, session registry, and monitor adapter surface.
|
|
- Confirmed the current desktop task executor is global-serial, monitor-task staleness dropping is already implemented, and no durable local queue/cache exists yet.
|
|
- Confirmed `playwright-core` is installed but `connectOverCDP()` is not wired, while hidden Electron execution already exists via `BrowserWindow` and `WebContentsView`.
|
|
- Added `monitor-scheduler.ts` as a durable file-backed local scheduler for monitor tasks, including same-day persistence, stale cross-day pruning, per-platform mutual exclusion, question-level cooldowns, and lease-miss backoff.
|
|
- Refactored `runtime-controller.ts` so publish tasks keep a conservative explicit queue while monitor tasks are selected through the local scheduler with adaptive max concurrency from Electron process metrics.
|
|
- Extended runtime diagnostics to surface the monitor scheduler snapshot and made the lease manager track multiple active leases instead of a single global lease placeholder.
|
|
- Files created/modified:
|
|
- `task_plan.md` (updated)
|
|
- `findings.md` (updated)
|
|
- `progress.md` (updated)
|
|
- `apps/desktop-client/src/main/monitor-scheduler.ts` (created)
|
|
- `apps/desktop-client/src/main/runtime-controller.ts` (updated)
|
|
- `apps/desktop-client/src/main/lease-manager.ts` (updated)
|
|
- `apps/desktop-client/src/main/runtime-snapshot.ts` (updated)
|
|
|
|
### Phase 16: Hidden Playwright CDP Execution Layer
|
|
- **Status:** complete
|
|
- Actions taken:
|
|
- Added `playwright-cdp.ts` as a reusable hidden-browser manager that launches hidden Electron `BrowserWindow` instances on account-bound sessions and attaches Playwright via `chromium.connectOverCDP()`.
|
|
- Enabled Electron remote debugging in bootstrap so the app exposes a CDP endpoint for local Playwright attachment.
|
|
- Extended adapter context with an optional Playwright `{ browser, page }` handle and wired the runtime controller to acquire/release hidden Playwright pages when an adapter declares `executionMode: "playwright"`.
|
|
- Kept the existing hidden `WebContentsView` path intact so current adapters like Doubao continue to work unchanged.
|
|
- Files created/modified:
|
|
- `apps/desktop-client/src/main/playwright-cdp.ts` (created)
|
|
- `apps/desktop-client/src/main/bootstrap.ts` (updated)
|
|
- `apps/desktop-client/src/main/adapters/base.ts` (updated)
|
|
- `apps/desktop-client/src/main/runtime-controller.ts` (updated)
|
|
|
|
### Phase 17: Verification & Delivery
|
|
- **Status:** in_progress
|
|
- Actions taken:
|
|
- Added optional scheduler metadata to desktop task events in shared types and server publishers so the local scheduler can make safer fan-out decisions before leasing.
|
|
- Ran `gofmt` on the modified Go files after the event metadata changes.
|
|
- Verified `pnpm --filter @geo/desktop-client typecheck` passes.
|
|
- Verified `pnpm --filter @geo/desktop-client build` passes.
|
|
- Verified `pnpm --filter admin-web typecheck` still passes after the shared-type event additions.
|
|
- Verified `go test ./internal/tenant/app/...` passes from `server/`.
|
|
- Files created/modified:
|
|
- `packages/shared-types/src/index.ts` (updated)
|
|
- `server/internal/tenant/app/desktop_task_events.go` (updated)
|
|
- `server/internal/tenant/app/desktop_task_service.go` (updated)
|
|
- `server/internal/tenant/app/publish_job_service.go` (updated)
|
|
|
|
### Phase 18: Qwen Adapter & Auth Relaxation
|
|
- **Status:** complete
|
|
- Actions taken:
|
|
- Ported the browser-extension `qwen` monitoring flow into a new desktop Playwright adapter that drives Tongyi's in-page managers via `page.evaluate()` and extracts answer/source data from `__qianwenChatAPI`.
|
|
- Registered the new `qwen` monitor adapter in the desktop runtime so monitor tasks can execute through the hidden Playwright CDP layer.
|
|
- Tightened generic AI auth fingerprinting to ignore CSRF-only cookies like `XSRF-TOKEN`, which Qwen sets even for anonymous visits.
|
|
- Added a Qwen-specific bind detector so the auth window can auto-close once a real session footprint is present, even if the page has not yet rendered an obvious avatar/name signal.
|
|
- Updated monitor preflight policy so only `yuanbao`, `kimi`, and `deepseek` require active login before execution; `qwen`, `doubao`, and `wenxin` are allowed to run anonymously when needed.
|
|
- Files created/modified:
|
|
- `task_plan.md` (updated)
|
|
- `findings.md` (updated)
|
|
- `progress.md` (updated)
|
|
- `apps/desktop-client/src/main/adapters/qwen.ts` (created)
|
|
- `apps/desktop-client/src/main/adapters/index.ts` (updated)
|
|
- `apps/desktop-client/src/main/runtime-controller.ts` (updated)
|
|
- `apps/desktop-client/src/main/account-binder.ts` (updated)
|
|
|
|
### Phase 19: Qwen Verification & Delivery
|
|
- **Status:** complete
|
|
- Actions taken:
|
|
- Verified `pnpm --filter @geo/desktop-client typecheck` passes after the Qwen adapter, bind-flow, and auth-policy updates.
|
|
- Verified `pnpm --filter @geo/desktop-client build` passes after the same changes.
|
|
- Followed up on a real Qwen bind stall reported by the user, inspected the machine's persisted `pending-qwen-*` partition, and confirmed logged-in cookies like `tongyi_sso_ticket`, `tongyi_sso_ticket_hash`, and `b-user-id` are present.
|
|
- Reworked Qwen account detection so bind/probe can succeed from those persisted auth cookies even when the page nickname/avatar heuristics do not trigger.
|
|
- Files created/modified:
|
|
- `task_plan.md` (updated)
|
|
- `findings.md` (updated)
|
|
- `progress.md` (updated)
|
|
|
|
## Session: 2026-04-04
|
|
|
|
### Phase 13: Prompt Centralization
|
|
- **Status:** complete
|
|
- Actions taken:
|
|
- Read the current planning files and reopened repository context for the new prompt-centralization request.
|
|
- Searched runtime and seed paths for all currently used hard-coded prompts instead of only matching the obvious template seed strings.
|
|
- Confirmed the prompt surface spans template seeds, template generation fallback prompts, template assist fallback prompts, prompt-rule generation supplements, and knowledge prompt injection.
|
|
- Added a dedicated `server/internal/tenant/prompts` package to centralize platform template seed prompts and runtime prompt fragments.
|
|
- Refactored `cmd/dev-seed`, `template_prompt.go`, `template_assist.go`, `prompt_generate_service.go`, and `knowledge_service.go` to read prompt text from the new package.
|
|
- Corrected invalid JSON quoting in the seed `custom_placeholder` fields while moving the template card-config blobs.
|
|
- Files created/modified:
|
|
- `task_plan.md` (updated)
|
|
- `findings.md` (updated)
|
|
- `progress.md` (updated)
|
|
- `server/internal/tenant/prompts/runtime.go` (created)
|
|
- `server/internal/tenant/prompts/template_seeds.go` (created)
|
|
- `server/cmd/dev-seed/main.go` (updated)
|
|
- `server/internal/tenant/app/template_prompt.go` (updated)
|
|
- `server/internal/tenant/app/template_assist.go` (updated)
|
|
- `server/internal/tenant/app/prompt_generate_service.go` (updated)
|
|
- `server/internal/tenant/app/knowledge_service.go` (updated)
|
|
|
|
### Phase 14: Prompt Verification & Delivery
|
|
- **Status:** complete
|
|
- Actions taken:
|
|
- Ran `gofmt` across all changed Go files after the prompt extraction.
|
|
- Re-scanned the runtime and seed callers to confirm the long prompt literals were removed from business functions and now only live under `server/internal/tenant/prompts`.
|
|
- Ran `go test ./internal/tenant/... ./cmd/dev-seed` from `server/` and confirmed the affected packages compile and tests pass.
|
|
- Files created/modified:
|
|
- `task_plan.md` (updated)
|
|
- `findings.md` (updated)
|
|
- `progress.md` (updated)
|
|
|
|
## Session: 2026-03-31
|
|
|
|
### Phase 10: Interface Coverage Audit & Visual Mapping
|
|
- **Status:** complete
|
|
- Actions taken:
|
|
- Re-read the backend router and transport/app layers to inventory every currently exposed tenant-facing HTTP interface.
|
|
- Confirmed the remaining frontend-backed API groups are `templates/articles` and `brands`, while `custom/media/tracking/knowledge` still lack matching backend routes in this repo.
|
|
- Recovered the reference screenshot layouts with position-aware OCR so the implementation can follow actual placement and grouping instead of just textual labels.
|
|
- Files created/modified:
|
|
- `task_plan.md` (updated)
|
|
- `findings.md` (updated)
|
|
- `progress.md` (updated)
|
|
|
|
### Phase 11: Admin-Web Full Interface Delivery
|
|
- **Status:** in_progress
|
|
- Actions taken:
|
|
- Added a minimal `vue-i18n` setup with `zh-CN` and `en-US` message bundles, locale persistence, and Ant Design locale switching.
|
|
- Reworked `LoginView`, `WorkspaceView`, `TemplatesView`, `ArticleDetailDrawer`, `TemplateGenerationDrawer`, `PageHero`, and `BrandsView` to stop using inline styles and to use component-local `<style>` blocks.
|
|
- Restored `AppShell.vue` to the user-preferred version and only moved its inline style attributes into named classes.
|
|
- Fixed the broken `pnpm dev:admin` startup path by adding the missing `BrandsView.vue`, running `pnpm install`, and re-running `pnpm typecheck:admin` plus `pnpm dev:admin`.
|
|
- Files created/modified:
|
|
- `apps/admin-web/package.json` (updated)
|
|
- `apps/admin-web/src/i18n/index.ts` (created)
|
|
- `apps/admin-web/src/i18n/messages/zh-CN.ts` (created)
|
|
- `apps/admin-web/src/i18n/messages/en-US.ts` (created)
|
|
- `apps/admin-web/src/main.ts` (updated)
|
|
- `apps/admin-web/src/App.vue` (updated)
|
|
- `apps/admin-web/src/router/meta.d.ts` (updated)
|
|
- `apps/admin-web/src/router/index.ts` (updated)
|
|
- `apps/admin-web/src/lib/api.ts` (updated)
|
|
- `apps/admin-web/src/lib/display.ts` (updated)
|
|
- `apps/admin-web/src/components/PageHero.vue` (created)
|
|
- `apps/admin-web/src/components/ArticleDetailDrawer.vue` (created)
|
|
- `apps/admin-web/src/components/TemplateGenerationDrawer.vue` (created)
|
|
- `apps/admin-web/src/views/LoginView.vue` (updated)
|
|
- `apps/admin-web/src/views/WorkspaceView.vue` (updated)
|
|
- `apps/admin-web/src/views/TemplatesView.vue` (created)
|
|
- `apps/admin-web/src/views/BrandsView.vue` (created)
|
|
- `apps/admin-web/src/views/FeatureStubView.vue` (updated)
|
|
- `apps/admin-web/src/layouts/AppShell.vue` (updated)
|
|
- `packages/shared-types/src/index.ts` (updated)
|
|
- `apps/admin-web/src/styles.css` (pending next cleanup pass)
|
|
- `task_plan.md` (updated)
|
|
- `findings.md` (updated)
|
|
- `progress.md` (updated)
|
|
|
|
### Phase 6: Frontend Scope Recovery
|
|
- **Status:** complete
|
|
- Actions taken:
|
|
- Read the planning files, Claude-side plan artifact, and architecture documents to recover the interrupted task context.
|
|
- Confirmed the backend chain is complete locally and the repository still has no `apps/` or `packages/` directories.
|
|
- Locked the next useful slice to a tenant-facing `admin-web` foundation rather than platform-side frontend work.
|
|
- Files created/modified:
|
|
- `task_plan.md` (updated)
|
|
- `findings.md` (updated)
|
|
- `progress.md` (updated)
|
|
|
|
### Phase 7: Frontend Foundation
|
|
- **Status:** complete
|
|
- Actions taken:
|
|
- Created the root pnpm workspace, root package scripts, and frontend-oriented `.gitignore`.
|
|
- Added shared frontend packages for TS config, API types, and an Axios-based client with auth refresh handling.
|
|
- Scaffolded `apps/admin-web` with Vite 8, Vue 3, TypeScript, Ant Design Vue, Pinia, Vue Router, and Vue Query.
|
|
- Files created/modified:
|
|
- `.gitignore` (created)
|
|
- `package.json` (created)
|
|
- `pnpm-workspace.yaml` (created)
|
|
- `packages/tsconfig/base.json` (created)
|
|
- `packages/shared-types/package.json` (created)
|
|
- `packages/shared-types/src/index.ts` (created)
|
|
- `packages/http-client/package.json` (created)
|
|
- `packages/http-client/src/index.ts` (created)
|
|
- `apps/admin-web/package.json` (created)
|
|
- `apps/admin-web/.env.example` (created)
|
|
- `apps/admin-web/index.html` (created)
|
|
- `apps/admin-web/tsconfig.json` (created)
|
|
- `apps/admin-web/vite.config.ts` (created)
|
|
|
|
### Phase 8: Admin-Web Initial Features
|
|
- **Status:** complete
|
|
- Actions taken:
|
|
- Implemented the app bootstrap, Ant Design locale wiring, session persistence helpers, and auth store.
|
|
- Implemented the login page with seeded local credentials and redirect-aware sign-in flow.
|
|
- Implemented the protected shell layout, navigation, quota teaser, workspace dashboard, and placeholder routes for the rest of the information architecture.
|
|
- Files created/modified:
|
|
- `apps/admin-web/src/App.vue` (created)
|
|
- `apps/admin-web/src/main.ts` (created)
|
|
- `apps/admin-web/src/styles.css` (created)
|
|
- `apps/admin-web/src/lib/session.ts` (created)
|
|
- `apps/admin-web/src/lib/errors.ts` (created)
|
|
- `apps/admin-web/src/lib/api.ts` (created)
|
|
- `apps/admin-web/src/stores/pinia.ts` (created)
|
|
- `apps/admin-web/src/stores/auth.ts` (created)
|
|
- `apps/admin-web/src/router/meta.d.ts` (created)
|
|
- `apps/admin-web/src/router/index.ts` (created)
|
|
- `apps/admin-web/src/layouts/AppShell.vue` (created)
|
|
- `apps/admin-web/src/views/LoginView.vue` (created)
|
|
- `apps/admin-web/src/views/WorkspaceView.vue` (created)
|
|
- `apps/admin-web/src/views/FeatureStubView.vue` (created)
|
|
|
|
### Phase 9: Frontend Verification & Delivery
|
|
- **Status:** complete
|
|
- Actions taken:
|
|
- Ran `pnpm install` for the new workspace and generated `pnpm-lock.yaml`.
|
|
- Fixed the initial frontend build errors related to Node typings and typed Axios wrapper method parameters.
|
|
- Switched Ant Design Vue registration from full-plugin mode to per-component registration to reduce the main bundle size.
|
|
- Ran `pnpm build:admin` successfully and confirmed production assets were emitted.
|
|
- Ran `pnpm --filter admin-web preview --host 127.0.0.1 --port 4173` and verified `/login` returned `HTTP/1.1 200 OK` with built asset references.
|
|
- Attempted browser automation verification, then fell back to HTTP verification after the local Playwright MCP environment failed on `/.playwright-mcp`.
|
|
- After Playwright became usable again, started the Vite dev server plus `tenant-api`, discovered the login CTA was not submitting on click, fixed the handler binding, and re-ran browser verification successfully with Playwright CLI.
|
|
- Files created/modified:
|
|
- `apps/admin-web/package.json` (updated)
|
|
- `apps/admin-web/tsconfig.json` (updated)
|
|
- `apps/admin-web/vite.config.ts` (updated)
|
|
- `apps/admin-web/src/main.ts` (updated)
|
|
- `apps/admin-web/src/views/LoginView.vue` (updated)
|
|
- `packages/http-client/src/index.ts` (updated)
|
|
- `pnpm-lock.yaml` (created)
|
|
- `task_plan.md` (updated)
|
|
- `findings.md` (updated)
|
|
- `progress.md` (updated)
|
|
|
|
### Phase 1: Progress Verification
|
|
- **Status:** complete
|
|
- **Started:** 2026-03-31
|
|
- Actions taken:
|
|
- Read the task-specific design document.
|
|
- Inspected top-level repository layout and backend directory tree.
|
|
- Read the planning-with-files skill instructions and initialized planning files.
|
|
- Inspected `server/Makefile`, `server/cmd/tenant-api/main.go`, and `server/internal/bootstrap/bootstrap.go`.
|
|
- Verified there are 19 migration files and inspected `cmd/dev-seed/main.go`.
|
|
- Inspected `sqlc.yaml`, repository directory contents, and current repository integration test placeholders.
|
|
- Inspected auth/workspace/template/article/brand services and route registration to compare actual implementation with the design doc.
|
|
- Files created/modified:
|
|
- `task_plan.md` (created)
|
|
- `findings.md` (created)
|
|
- `progress.md` (created)
|
|
|
|
### Phase 2: Gap Analysis and Scope Lock
|
|
- **Status:** complete
|
|
- Actions taken:
|
|
- Compared the repository contents against the design doc's expected `sqlc` and repository layout.
|
|
- Confirmed Step 4 is the earliest incomplete milestone because the generated code directory and repository wrappers are missing.
|
|
- Ran `make sqlc-generate` and observed a failing schema path in `sqlc.yaml`.
|
|
- Files created/modified:
|
|
- `task_plan.md` (updated)
|
|
- `findings.md` (updated)
|
|
- `progress.md` (updated)
|
|
|
|
### Phase 3: Implementation
|
|
- **Status:** complete
|
|
- Actions taken:
|
|
- Fixed `server/internal/tenant/repository/sqlc.yaml` and regenerated `sqlc` output under `server/internal/tenant/repository/generated/`.
|
|
- Added repository wrappers for auth, workspace, template, article, quota, and audit queries.
|
|
- Refactored auth/workspace/template services and handlers to use the new repository layer.
|
|
- Reworked template generation flow to use repository-backed transactional operations.
|
|
- Implemented atomic refresh token rotation in Redis and added `session_store` tests.
|
|
- Cleaned existing lint violations that were blocking local verification.
|
|
- Files created/modified:
|
|
- `server/internal/tenant/repository/sqlc.yaml` (updated)
|
|
- `server/internal/tenant/repository/generated/*` (generated)
|
|
- `server/internal/tenant/repository/common.go` (created)
|
|
- `server/internal/tenant/repository/auth_repo.go` (created)
|
|
- `server/internal/tenant/repository/workspace_repo.go` (created)
|
|
- `server/internal/tenant/repository/template_repo.go` (created)
|
|
- `server/internal/tenant/repository/article_repo.go` (created)
|
|
- `server/internal/tenant/repository/quota_repo.go` (created)
|
|
- `server/internal/tenant/repository/audit_repo.go` (created)
|
|
- `server/internal/tenant/app/auth_service.go` (updated)
|
|
- `server/internal/tenant/app/workspace_service.go` (updated)
|
|
- `server/internal/tenant/app/template_service.go` (updated)
|
|
- `server/internal/shared/auth/session_store.go` (updated)
|
|
- `server/internal/shared/auth/session_store_test.go` (created)
|
|
- `server/internal/tenant/transport/auth_handler.go` (updated)
|
|
- `server/internal/tenant/transport/workspace_handler.go` (updated)
|
|
- `server/internal/tenant/transport/template_handler.go` (updated)
|
|
|
|
### Phase 4: Testing & Verification
|
|
- **Status:** complete
|
|
- Actions taken:
|
|
- Re-ran `make sqlc-generate` after the final code state and confirmed generation succeeds.
|
|
- Ran `go test ./...`, then `make test`, and confirmed all tests pass.
|
|
- Ran `make lint`, fixed the reported warnings, and re-ran until it passed cleanly.
|
|
- Verified the tenant-scope guard script exists and checked for CI workflow files.
|
|
- Files created/modified:
|
|
- `server/internal/tenant/repository/tx.go` (updated)
|
|
- `server/cmd/dev-seed/main.go` (updated)
|
|
- `server/internal/shared/auth/middleware_test.go` (updated)
|
|
- `server/internal/tenant/app/article_service.go` (updated)
|
|
- `server/internal/tenant/app/brand_service.go` (updated)
|
|
- `task_plan.md` (updated)
|
|
- `findings.md` (updated)
|
|
- `progress.md` (updated)
|
|
|
|
### Phase 5: Delivery
|
|
- **Status:** complete
|
|
- Actions taken:
|
|
- Added backend CI workflow under `.github/workflows/`.
|
|
- Added `tenant-scope-guard` to the backend `Makefile` so CI and local verification use the same entrypoint.
|
|
- Re-ran `make tenant-scope-guard`, `make test`, and `make lint` after the CI-related edits.
|
|
- Updated the backend `Makefile` to run `golang-migrate` through `go run -tags postgres` instead of requiring a preinstalled `migrate` binary.
|
|
- Ran `make dev-init` successfully, including Docker startup, migrations, and seed data.
|
|
- Started `tenant-api` and verified health endpoints plus auth login/me/refresh/logout behavior with positive and negative checks.
|
|
- Files created/modified:
|
|
- `.github/workflows/backend-ci.yml` (created)
|
|
- `server/Makefile` (updated)
|
|
- `task_plan.md` (updated)
|
|
- `findings.md` (updated)
|
|
- `progress.md` (updated)
|
|
|
|
## Test Results
|
|
| Test | Input | Expected | Actual | Status |
|
|
|------|-------|----------|--------|--------|
|
|
| Repository inspection | `ls`, `rg --files`, `sed` | Establish current backend coverage | Backend skeleton, migrations, services, and transport files exist | pass |
|
|
| Migration count | `find server/migrations -name '*.up.sql' | wc -l` | 19 schema migrations | 19 | pass |
|
|
| SQLC generation | `make sqlc-generate` | Generate typed code | Passed after fixing `sqlc.yaml` schema path | pass |
|
|
| Go tests | `go test ./...` | All packages compile and tests pass | Passed | pass |
|
|
| Make tests | `make test` | Roadmap acceptance command passes | Passed | pass |
|
|
| Lint | `make lint` | Roadmap acceptance command passes | Passed after fixing errcheck/ineffassign warnings | pass |
|
|
| CI workflow presence | `find . -path '*/.github/workflows/*' -type f` | At least one CI workflow if Step 9 is complete | `.github/workflows/backend-ci.yml` exists | pass |
|
|
| Tenant scope guard | `make tenant-scope-guard` | Tenant SQL filter guard passes | Passed | pass |
|
|
| Dev init | `make dev-init` | Infra, migrations, and seed complete successfully | Passed after fixing Makefile-managed migrate driver tags | pass |
|
|
| Live health | `GET /api/health/live` | HTTP 200 with alive status | Returned `code=0`, `status=alive` | pass |
|
|
| Ready health | `GET /api/health/ready` | HTTP 200 with ready status | Returned `code=0`, `status=ready` | pass |
|
|
| Login | `POST /api/auth/login` with `admin@geo.local / Admin@123` | Receive access/refresh tokens and user info | Passed | pass |
|
|
| Me | `GET /api/auth/me` with fresh access token | Current user payload returned | Passed | pass |
|
|
| Refresh | `POST /api/auth/refresh` with original refresh token | Receive rotated access/refresh token pair | Passed | pass |
|
|
| Logout revoke | `POST /api/auth/logout`, then `GET /api/auth/me` with old access token | Old access token rejected | Returned `40103 token_revoked` | pass |
|
|
| Refresh rotate invalidate | Reuse old refresh token after refresh | Old refresh token rejected | Returned `40121 refresh_session_expired` | pass |
|
|
| Workspace overview | `GET /api/tenant/workspace/overview` | Aggregated stats return successfully | Returned `code=0`, article/brand counts present | pass |
|
|
| Workspace recent articles | `GET /api/tenant/workspace/recent-articles` | Recent list returns successfully | Returned `code=0` | pass |
|
|
| Workspace quota summary | `GET /api/tenant/workspace/quota-summary` | Quota summary returns successfully | Returned `code=0`, balance/total present | pass |
|
|
| Workspace template cards | `GET /api/tenant/workspace/template-cards` | Template cards return successfully | Returned `code=0`, count=4 | pass |
|
|
| Template generate flow | `POST /api/tenant/templates/{id}/generate` + article detail/version checks | Article generation completes end-to-end | Article `1` completed, versions count `1`, quota `100 -> 99` | pass |
|
|
| Brand soft delete and recreate | Create brand, delete, recreate same name | Recreate succeeds after soft delete | Original brand `1` deleted, recreated as brand `2` | pass |
|
|
| Question version history | Create question, update, list versions | Version history retained | Returned 2 versions, latest text updated | pass |
|
|
| Competitor CRUD basic flow | Create competitor then list | Competitor visible under brand | Returned count `1` | pass |
|
|
| Frontend workspace install | `pnpm install` | Workspace dependencies install cleanly | Passed | pass |
|
|
| Frontend build | `pnpm build:admin` | `admin-web` compiles and emits production assets | Passed | pass |
|
|
| Frontend preview login HTML | `curl -I http://127.0.0.1:4173/login` | Preview route returns `200 OK` | Returned `HTTP/1.1 200 OK` | pass |
|
|
| Frontend preview asset shell | `curl -s http://127.0.0.1:4173/login` | HTML references built CSS/JS assets | Returned built asset tags for `index-CtRpygQP.js` and `index-DFz5-Rsr.css` | pass |
|
|
| Frontend browser login flow | `pnpm dlx @playwright/test test .tmp-playwright/admin-web.spec.js --reporter=line` | Login succeeds and workspace renders | Passed after binding the login CTA directly to `handleSubmit` | pass |
|
|
|
|
## Error Log
|
|
| Timestamp | Error | Attempt | Resolution |
|
|
|-----------|-------|---------|------------|
|
|
| 2026-03-31 | None yet | 1 | N/A |
|
|
| 2026-03-31 | `make sqlc-generate` failed due to invalid schema path in `sqlc.yaml` | 1 | Fixed by changing schema path to `../../../migrations/` |
|
|
| 2026-03-31 | `make lint` failed on several existing warnings | 1 | Fixed all reported warnings and re-ran lint successfully |
|
|
| 2026-03-31 | `make dev-init` failed because go-run migrate lacked the postgres driver tag | 1 | Updated `MIGRATE_CMD` to `go run -tags postgres ...` and reran successfully |
|
|
| 2026-03-31 | Gemini CLI returned `429 MODEL_CAPACITY_EXHAUSTED` on `gemini-3.1-pro-preview` | 1 | Stopped pursuing Gemini once the user said not to use Gemini |
|
|
| 2026-03-31 | Initial frontend build failed on missing Node typings and implicit `any` parameters | 1 | Removed the Node type dependency from app TS config, simplified the Vite config, and typed the API client methods explicitly |
|
|
| 2026-03-31 | Playwright MCP browser open failed on `/.playwright-mcp` | 1 | Used preview HTTP verification instead of blocking on browser environment setup |
|
|
| 2026-03-31 | Browser click on the login CTA did not submit the form, so Playwright stayed on `/login` | 1 | Added an explicit `@click=\"handleSubmit\"` binding to the CTA and re-ran the E2E flow successfully |
|
|
|
|
### Phase 22: Monitoring Daily Collection Review
|
|
- **Status:** complete
|
|
- Actions taken:
|
|
- Read the existing planning files and restored context for the monitoring scheduler/runtime work.
|
|
- Inspected `cmd/scheduler`, the shared cron helper, `ScheduleDispatchWorker`, monitoring handlers, monitoring service, phase2 desktop task dispatch, migrations, and deployment config.
|
|
- Queried local Postgres/Monitoring Postgres containers for current task evidence.
|
|
- Verified the data-detail/dashboard read path with existing 2026-04-24 monitoring data.
|
|
- Findings so far:
|
|
- Current DB evidence shows 2026-04-24 monitoring collection tasks are `desktop/manual/plugin_standard`, not daily automatic tasks.
|
|
- `tenant_monitoring_quotas` is configured as `collect_frequency = daily`, but the inspected runtime does not contain a daily monitoring task generation worker.
|
|
|
|
### Phase 23: Monitoring Daily Task Generation Repair
|
|
- **Status:** complete
|
|
- Actions taken:
|
|
- Added `server/internal/tenant/app/monitoring_daily_task_worker.go`.
|
|
- Wired `MonitoringDailyTaskWorker` into `server/cmd/scheduler/main.go`.
|
|
- Added `server/internal/tenant/app/monitoring_daily_task_worker_test.go` for midnight-after materialization, existing-task idempotency, and deterministic plan ordering.
|
|
- Implemented stable jitter after midnight, global/plan/brand batch caps, daily hard-cap selection, and brand-level advisory locking.
|
|
- Implemented due desktop dispatch claim with `FOR UPDATE SKIP LOCKED`, `last_dispatched_at`, `dispatch_attempts`, and a retry cooldown.
|
|
- Kept automatic daily desktop tasks pending when no eligible desktop account/client is available; no legacy fallback is applied for this path.
|
|
- Fixed the P0 rollout-disabled case: daily generation now requires `desktop_tasks` rollout plus `primary_client_id`; otherwise it skips the plan and records `SkippedPlanCount` rather than creating orphan `automatic/legacy` rows.
|
|
- Removed Go runtime and dev-seed dependency on `tenant_monitoring_quotas`: daily plans now come from `desktop_clients`, dashboard/projection use default monitoring platforms, and primary client selection is derived from recent/registered desktop clients.
|
|
- Fixed the P0 RabbitMQ publish context issue in daily worker: `publishMonitorDesktopTaskAvailable` now receives a 5-second child context derived from the worker tick context instead of `context.Background()`.
|
|
- Verification:
|
|
- `go test ./internal/tenant/app -run 'Test.*MonitoringDaily|Test.*Monitoring|TestEncodeMonitoringProjectionRebuildEnvelope|TestBuildMonitoringRawPayload' -count=1` passed.
|
|
- `go test ./cmd/scheduler ./cmd/dev-seed ./internal/tenant/app -count=1` passed.
|
|
- `docker exec geo-monitoring-postgres psql ... EXPLAIN ...` passed for the new claim SQL.
|
|
|
|
### Phase 24: Monitoring Daily Observability Hardening
|
|
- **Status:** complete
|
|
- Actions taken:
|
|
- Completed the plan/brand scoped error-isolation path so transient failures increment summary failure counts and do not stop other tenants/brands in the same tick.
|
|
- Added `monitoring_daily_task_metrics.go` with atomic counters/gauges for worker runs, fatal and partial failures, plan/brand failures, skipped plans, task stage counts, last timestamps, duration, business date, and last fatal error code/message.
|
|
- Recorded metrics on every `runOnce` result, including zero-work ticks and fatal errors.
|
|
- Exposed `/metrics` in Prometheus text format and `/api/internal/metrics/monitoring/daily-tasks` as JSON.
|
|
- Started the scheduler's health/metrics HTTP server on `scheduler.http_port` default `8081`.
|
|
- Reworked daily hard-cap accounting so existing materialized tasks are counted from DB, full candidate horizons are preserved for de-duplication, and remaining capacity is decremented only by rows inserted in the current tick.
|
|
- Split daily materialization limit from desktop dispatch limit, so a full daily cap does not stop already-pending tasks from being dispatched.
|
|
- Replaced the hard-coded daily plan defaults with subscription/config-driven rules: active subscription required, max brands from plan/config, platforms from live bound desktop accounts, and per-brand task cap from configured active questions capped by `brand_library`.
|
|
- Changed dashboard and projection platform selection so unbound platforms are not silently shown or scheduled.
|
|
- Verification:
|
|
- `go test ./internal/tenant/app -run 'Test.*MonitoringDaily' -count=1` passed.
|
|
- `go test ./internal/tenant/app -run 'Test.*MonitoringDaily|TestReconcile|TestResolve|TestIntersect|TestFilter' -count=1` passed.
|
|
- `go test ./cmd/scheduler ./internal/bootstrap ./internal/shared/config -count=1` passed.
|
|
- `go test ./cmd/scheduler ./cmd/dev-seed ./internal/tenant/app -count=1` passed.
|
|
- `go test ./...` passed from `server/`.
|
|
- `git diff --check` passed.
|
|
|
|
### Phase 25: Heartbeat Primary Stability Hardening
|
|
- **Status:** complete
|
|
- Actions taken:
|
|
- Replaced heartbeat primary resolution with a per-tenant/per-workspace `desktop_client_primary_leases` lease row.
|
|
- The current primary renews the lease on heartbeat; other desktop clients are non-primary while the incumbent lease is live.
|
|
- Failover now happens only when the lease has expired or the recorded primary desktop client is unavailable/revoked.
|
|
- Updated daily monitoring plan selection to prefer the sticky lease primary before deterministic fallback.
|
|
- Removed `last_seen_at` ordering from the current-user registered-client lookup so UI platform selection is not heartbeat-driven.
|
|
- Added migration `20260424130000_add_desktop_primary_leases` with the lease table, backfill, and active desktop-client lookup indexes.
|
|
- Added a unit test for the lease-claim decision matrix.
|
|
- Verification:
|
|
- `go test ./internal/tenant/app -run 'TestShouldClaimHeartbeatPrimaryLease|Test.*MonitoringDaily|TestReconcile|TestResolve|TestIntersect|TestFilter' -count=1` passed.
|
|
- `go test ./...` passed from `server/`.
|
|
- `git diff --check` passed.
|
|
|
|
### Phase 26: Scheduler Metrics HTTP Hardening
|
|
- **Status:** complete
|
|
- Actions taken:
|
|
- Added `scheduler.http_host` with default `127.0.0.1`.
|
|
- Added `scheduler.internal_metrics_token`, with env overrides `SCHEDULER_INTERNAL_METRICS_TOKEN` / `SCHEDULER_METRICS_TOKEN`.
|
|
- Protected `/metrics` and `/api/internal/metrics/monitoring/daily-tasks` with token auth.
|
|
- Changed `scheduler.http_port < 0` to mean explicit HTTP disablement; `0` still defaults to `8081`.
|
|
- Replaced `app.Engine.Run(... Fatalf ...)` with `http.Server.ListenAndServe`, non-fatal error logging, and graceful `Shutdown`.
|
|
- Added scheduler HTTP auth/address tests and config normalization/env tests.
|
|
- Verification:
|
|
- `go test ./cmd/scheduler ./internal/shared/config -count=1` passed.
|
|
- `go test ./...` passed from `server/`.
|
|
- `git diff --check` passed.
|
|
|
|
### Phase 27: Scheduler Worker Graceful Shutdown
|
|
- **Status:** complete
|
|
- Actions taken:
|
|
- Added blocking `Run(ctx)` methods to scheduler workers while keeping existing `Start(ctx)` wrappers.
|
|
- Updated `cmd/scheduler` to create workers explicitly and run them under a `sync.WaitGroup`.
|
|
- On signal, scheduler now stops the metrics HTTP server, cancels worker loops, and waits up to 60 seconds for workers to finish.
|
|
- Changed scheduler worker loops so shutdown cancellation prevents the next tick but does not immediately cancel an active `runOnce`; active work still has the existing per-worker timeout.
|
|
- Added tests for worker wait completion and timeout behavior.
|
|
- Verification:
|
|
- `go test ./cmd/scheduler ./internal/scheduler ./internal/tenant/app -run 'TestScheduler|TestShouldClaimHeartbeatPrimaryLease|Test.*MonitoringDaily' -count=1` passed.
|
|
- `go test ./...` passed from `server/`.
|
|
- `git diff --check` passed.
|
|
|
|
### Phase 28: Monitoring Platform Authorization UI Contract
|
|
- **Status:** complete
|
|
- Actions taken:
|
|
- Added explicit monitoring platform authorization status to dashboard runtime and question-detail API responses.
|
|
- Added shared frontend type `MonitoringPlatformAuthorizationStatus`.
|
|
- Updated `TrackingView` to keep dashboard platform rows stable and disable collect-now for no-authorized or selected-unauthorized platform states without rendering a no-authorized dashboard alert.
|
|
- Updated `TrackingQuestionDetailView` to show an explicit unavailable state and suppress the platform tabs/detail grid when no platforms are authorized.
|
|
- Added i18n strings for the new no-desktop, no-authorized, and selected-unauthorized states.
|
|
- Added a Go unit test for the authorization-status decision matrix.
|
|
- Verification:
|
|
- `go test ./internal/tenant/app -run 'TestMonitoringPlatformAuthorizationStatus|TestReconcileEnabledMonitoringPlatforms|TestFilterMonitoringPlatforms|TestResolveDashboardDateWindowAt|TestParseDetailDateRangeAt' -count=1` passed.
|
|
- `pnpm typecheck:admin` passed.
|
|
- Browser regression against admin-web with `platform_authorization_status = no_authorized_platforms` passed for dashboard and question detail; dashboard does not show a no-authorized alert.
|
|
- `go test ./...` passed from `server/`.
|
|
- `pnpm build:admin` passed; it still reports existing bundle/CSS warnings unrelated to this change.
|
|
- `git diff --check` passed.
|
|
|
|
### Phase 29: Monitoring Six-Platform Display Contract
|
|
- **Status:** complete
|
|
- Actions taken:
|
|
- Changed `loadMonitoringProjectionPlatforms` to return the canonical six-platform catalog instead of deriving display rows from same-day task rows.
|
|
- Changed dashboard platform breakdown to use the same six-platform display catalog, so platforms with zero tasks/samples still appear.
|
|
- Added `authorized_monitoring_platform_ids` to dashboard runtime and shared frontend types.
|
|
- Updated `TrackingView` collect-now gating to use the explicit authorized platform ID list instead of inferring authorization from visible platform rows.
|
|
- Added unit coverage for the six-platform catalog copy and projection platform selection.
|
|
- Verification:
|
|
- `go test ./internal/tenant/app -run 'TestDefaultMonitoringPlatformMetadata|TestLoadMonitoringProjectionPlatforms|TestMonitoringPlatformAuthorizationStatus|TestReconcileEnabledMonitoringPlatforms|TestFilterMonitoringPlatforms' -count=1` passed.
|
|
- `pnpm typecheck:admin` passed.
|
|
- Browser regression confirmed a no-authorized-platform dashboard still renders all 6 platform names and keeps collect-now disabled.
|
|
- `go test ./...` passed from `server/`.
|
|
- `pnpm build:admin` passed; existing CSS/chunk warnings remain unrelated.
|
|
- `git diff --check` passed.
|
|
|
|
### Phase 30: Workspace Scope And Daily Config Visibility
|
|
- **Status:** complete
|
|
- Actions taken:
|
|
- Added current-workspace context helpers and a `WorkspaceScope` middleware with `X-Workspace-ID` support plus membership validation for non-primary workspace requests.
|
|
- Wired the tenant route group through `WorkspaceScope`.
|
|
- Updated monitoring dashboard, question detail, and collect-now paths to use the current request workspace for quota/client/platform-account/access-state resolution.
|
|
- Documented `findLatestRegisteredClientForUser` as created-at ordered and intentionally independent of online health.
|
|
- Changed daily worker platform JSON decoding to return errors instead of swallowing malformed JSON.
|
|
- Counted malformed daily platform config as a plan failure and logged it with tenant/workspace/business-date context.
|
|
- Added unit coverage for current workspace fallback/override, workspace-id parsing, and daily platform JSON decode failures.
|
|
- Verification:
|
|
- `go test ./internal/shared/auth ./internal/shared/middleware ./internal/tenant/app -run 'TestCurrentWorkspaceID|TestWorkspaceScope|TestRequestedWorkspaceID|TestDecodeDailyMonitoringEnabledPlatforms|Test.*MonitoringDaily|TestMonitoringPlatformAuthorizationStatus|TestDefaultMonitoringPlatformMetadata|TestLoadMonitoringProjectionPlatforms' -count=1` passed.
|
|
- `go test ./internal/tenant/transport -run TestProtectedRoutes -count=1` passed.
|
|
- `go test ./...` passed from `server/`.
|
|
- `git diff --check` passed.
|
|
|
|
### Phase 31: Heartbeat Primary Lease Scalability
|
|
- **Status:** complete
|
|
- Actions taken:
|
|
- Replaced per-heartbeat `BEGIN` / `SELECT ... FOR UPDATE` / `UPDATE` primary lease handling with read-mostly lease resolution.
|
|
- Normal primary heartbeats now return from a plain read unless the renew interval has elapsed.
|
|
- Non-primary heartbeats return from a plain read while the incumbent lease is live and available.
|
|
- Missing, expired, unavailable, and race cases use single-statement `INSERT` or CAS-style `UPDATE` writes instead of an explicit lock transaction.
|
|
- Added heartbeat primary lease metrics for hit/miss outcomes, DB writes, contention, errors, and duration.
|
|
- Added token-protected tenant-api internal metrics endpoints for heartbeat primary lease JSON and Prometheus output.
|
|
- Documented the renew throttle relative to the 25s desktop heartbeat and 90s TTL.
|
|
- Verification:
|
|
- `go test ./internal/tenant/app -run 'TestDecideHeartbeatPrimaryLease|TestMonitoringHeartbeatPrimaryLeaseMetrics|TestBuildMonitoringRawPayloadKimi' -count=1` passed.
|
|
- `go test ./internal/tenant/transport -run 'TestProtectedRoutes|TestPublicRoutes' -count=1` passed.
|
|
- `go test ./...` passed from `server/`.
|
|
- `git diff --check` passed.
|
|
|
|
### Phase 32: Monitoring Heartbeat Snapshot Scalability
|
|
- **Status:** complete
|
|
- Actions taken:
|
|
- Changed `MonitoringCallbackService.Heartbeat` to batch-load current access snapshot state before deciding whether a monitoring DB transaction is required.
|
|
- Stable unchanged platform access reports now skip snapshot upserts; unchanged rows refresh at most every 10 minutes.
|
|
- Primary-client inaccessible-platform reconciliation now first checks whether matching pending tasks exist, so stable inaccessible reports with no pending work do not open a write transaction.
|
|
- Added heartbeat snapshot metrics for platform reports, transaction opens, snapshot insert/update/refresh/skip counts, reconciled tasks, projection rebuilds, errors, and duration.
|
|
- Exposed heartbeat snapshot metrics through token-protected tenant-api internal JSON and Prometheus endpoints.
|
|
- Added a monitoring DB partial index for pending-platform reconciliation lookup.
|
|
- Verification:
|
|
- `go test ./internal/tenant/app -run 'TestDecideMonitoringHeartbeatSnapshot|TestMonitoringHeartbeatSnapshotMetrics|TestDecideHeartbeatPrimaryLease|TestMonitoringHeartbeatPrimaryLeaseMetrics' -count=1` passed.
|
|
- `go test ./internal/tenant/app -count=1` passed.
|
|
- `go test ./internal/tenant/transport -count=1` passed.
|
|
- `go test ./...` passed from `server/`.
|
|
- `git diff --check` passed.
|
|
|
|
### Phase 33: Prometheus Metrics Exposition Hardening
|
|
- **Status:** complete
|
|
- Actions taken:
|
|
- Added `prometheus/client_golang` and replaced custom hand-written Prometheus text builders with `prometheus.Collector` implementations plus `promhttp`.
|
|
- Kept existing JSON snapshot endpoints unchanged.
|
|
- Changed scheduler `/metrics` to serve a dedicated registry containing daily-task metrics plus Go runtime and process collectors.
|
|
- Changed tenant-api internal heartbeat Prometheus endpoints to serve through `promhttp` as well.
|
|
- Removed raw error-message labels from heartbeat snapshot Prometheus output; detailed messages remain available in JSON snapshots.
|
|
- Added explicit carriage-return normalization for label values before creating const metrics, because the local client_golang text path does not escape raw CR.
|
|
- Added tests covering scheduler runtime metrics and CR label normalization.
|
|
- Verification:
|
|
- `go test ./internal/tenant/app -run 'TestMonitoringDailyTaskMetrics|TestMonitoringDailyTaskPrometheus|TestMonitoringSchedulerMetricsPrometheusHandler|TestMonitoringHeartbeatPrimaryLeaseMetrics|TestMonitoringHeartbeatSnapshotMetrics' -count=1` passed.
|
|
- `go test ./cmd/scheduler ./internal/tenant/transport -run 'TestScheduler|TestProtectedRoutes|TestPublicRoutes|TestDesktopClientRoutes' -count=1` passed.
|
|
- `go test ./...` passed from `server/`.
|
|
- `git diff --check` passed.
|
|
|
|
### Phase 34: Daily Task Batch Materialization
|
|
- **Status:** complete
|
|
- Actions taken:
|
|
- Changed `ensureDailyMonitoringCollectTasks` from per-candidate `tx.Exec` to a single batched `INSERT ... SELECT FROM unnest(...)`.
|
|
- Batched arrays carry `question_id`, `question_hash`, `ai_platform_id`, and `dispatch_after`; tenant/brand/business date/collector/run mode/target client/shard key/execution owner remain constant per call.
|
|
- Kept `ON CONFLICT DO NOTHING`, so duplicate materialization still returns only the number of newly inserted rows via `RowsAffected`.
|
|
- Verification:
|
|
- `go test ./internal/tenant/app -run 'Test.*MonitoringDaily|TestMonitoringDailyTaskMetrics|TestMonitoringDailyTaskPrometheus|TestMonitoringSchedulerMetricsPrometheusHandler' -count=1` passed.
|
|
- `go test ./...` passed from `server/`.
|
|
- `git diff --check` passed.
|
|
|
|
### Phase 35: Daily Plan SQL Decomposition
|
|
- **Status:** complete
|
|
- Actions taken:
|
|
- Split `loadDailyMonitoringPlans` into `loadDailyMonitoringPrimaryClientPlans`, `loadDailyMonitoringPlanPlatformJSON`, and a pure assembly helper.
|
|
- Kept the first query focused on active subscription admission, lease-preferred primary client selection, workspace scoping, and subscription/config-derived brand/question limits.
|
|
- Moved authorized platform aggregation to a second batched query keyed by `(tenant_id, workspace_id, client_id)`.
|
|
- Added a helper test covering the race where a selected client loses its platform snapshot between the two reads; that candidate is skipped instead of becoming an empty executable plan.
|
|
- Verification:
|
|
- `go test ./internal/tenant/app -run 'TestBuildDailyMonitoringPlansFromSelectedClients|Test.*MonitoringDaily' -count=1` passed.
|
|
- `go test ./internal/tenant/app -run 'Test.*MonitoringDaily|TestMonitoringDailyTaskMetrics|TestMonitoringDailyTaskPrometheus|TestMonitoringSchedulerMetricsPrometheusHandler' -count=1` passed.
|
|
- `go test ./...` passed from `server/`.
|
|
- `git diff --check` passed.
|
|
|
|
### Phase 36: Monitoring Authorization And Detail Display Bug Fix
|
|
- **Status:** complete
|
|
- Actions taken:
|
|
- Changed monitoring platform authorization to mean a bound, non-deleted platform account on a supported AI platform; `platform_accounts.health` no longer has to be `live`.
|
|
- Removed `health = 'live'` from daily scheduled plan eligibility and platform aggregation, so daily automatic collection can materialize tasks for offline clients and non-live account states.
|
|
- Kept immediate collection gated by desktop-client online state, and made the online check target the same desktop client that owns the authorized platform accounts.
|
|
- Changed question detail to display the canonical platform history instead of hiding existing data behind current `platform_authorization_status`.
|
|
- Updated frontend date validation to use the monitoring business date, so today's date such as 2026-04-24 is not rejected by local/browser timezone drift.
|
|
- Verification:
|
|
- `go test ./internal/tenant/app -run 'Test.*MonitoringDaily|TestMonitoringPlatformAuthorizationStatus|TestReconcileEnabledMonitoringPlatforms|TestFilterMonitoringPlatforms|TestDefaultMonitoringPlatformMetadata|TestLoadMonitoringProjectionPlatforms' -count=1` passed.
|
|
- `pnpm --filter admin-web typecheck` passed.
|
|
- `go test ./...` passed from `server/`.
|
|
- `pnpm --filter admin-web build` passed.
|
|
- `git diff --check` passed.
|
|
|
|
### Phase 21: Foreground Publish Admission
|
|
- **Status:** complete
|
|
- Actions taken:
|
|
- Confirmed the current runtime only starts publish when `state.activeExecutions.size === 0`, so an already-running monitor can block media publish.
|
|
- Locked the implementation model: publish is foreground, monitor is background, publish receives reserved runtime capacity, and publish platform policy stays in a lightweight in-memory scheduler.
|
|
- Added `apps/desktop-client/src/main/publish-scheduler.ts` with in-memory queueing, same-platform active locks, and 3-6 second platform cooldowns.
|
|
- Refactored `runtime-controller.ts` so publish can start while monitor is running, monitor pauses behind any publish backlog, and lease-in-flight is tracked separately for publish vs. monitor.
|
|
- Added hardware/runtime adaptive total concurrency with `GEO_DESKTOP_MAX_TOTAL_CONCURRENCY` as an optional cap and a reserved publish slot for monitor budgeting.
|
|
- Exposed `publishScheduler` in the desktop runtime snapshot and added scheduler unit tests.
|
|
- Verification:
|
|
- `pnpm --filter @geo/desktop-client build` passed.
|
|
- `pnpm --filter @geo/desktop-client test` passed: 5 files, 26 tests.
|
|
- `git diff --check` passed.
|
|
- `pnpm --filter @geo/desktop-client typecheck` failed before checking runtime changes because `electron.vite.config.ts` has a Vite 5/8 plugin type mismatch.
|
|
|
|
### 2026-04-28 Dongchedi Publish Debug
|
|
- **Status:** in_progress
|
|
- Actions taken:
|
|
- Queried local `geo-postgres` through `docker exec` because `psql` is not installed on the host.
|
|
- Verified article `95` reconstructs to normal markdown through `repository.LoadArticleVersionContent`; removed the temporary inspection test after use.
|
|
- Updated `apps/desktop-client/src/main/adapters/dongchedi.ts` so body images first try Dongchedi `spice/image`; local/relative images use ImageX upload and then run through `spice/image` before replacement.
|
|
- Added redacted Dongchedi publish rejection diagnostics to the adapter error payload/logs.
|
|
- Added `apps/desktop-client/src/main/adapters/dongchedi-content.ts` and a unit test to downgrade table HTML to paragraph rows before Dongchedi submit.
|
|
- Followed up after another `server exception` retry where diagnostics showed no table tags, no local asset URL, and one body image.
|
|
- Removed ` ` entities from Dongchedi table-downgraded body HTML.
|
|
- Changed body image handling so ImageX-uploaded local images try Dongchedi `spice/image` through both session and page-context requests before replacement.
|
|
- After the platform returned `dongchedi_image_upload_failed:content_images_missing_1_of_1`, tried an ImageX direct URL fallback; the next retry still returned `server exception` with `content_image_upload_strategies = ['imagex_direct_fallback']`.
|
|
- Removed the direct ImageX正文图 fallback. Local正文图片 that cannot be converted to a Dongchedi `spice` URL are now removed from `content` instead of failing early or submitting a rejected ImageX URL.
|
|
- After a no-body-image retry still returned `server exception`, changed `extra.content_word_cnt` from the reference extension's hardcoded `267` to the actual text count of the final submitted HTML.
|
|
- Added `content_word_cnt` and `computed_text_count` to Dongchedi rejection diagnostics.
|
|
- Expanded rejection diagnostics with body image host summaries, body image upload strategies, tag/entity counts, content end excerpt, and cover upload dimensions/hosts.
|
|
- Verification:
|
|
- `pnpm --filter @geo/desktop-client typecheck` passed.
|
|
- `pnpm --filter @geo/desktop-client test -- dongchedi` passed.
|
|
- `pnpm --filter @geo/desktop-client test` passed.
|
|
- `pnpm --filter @geo/desktop-client build` passed and refreshed `out/main/bootstrap.cjs`.
|
|
- `git diff --check` passed.
|
|
|
|
## 5-Question Reboot Check
|
|
| Question | Answer |
|
|
|----------|--------|
|
|
| Where am I? | Phase 9 complete |
|
|
| Where am I going? | Next useful slice is turning the placeholder routes into real pages, starting with template creation and brand management |
|
|
| What's the goal? | Resume the interrupted task by adding the missing `admin-web` frontend foundation on top of the finished backend |
|
|
| What have I learned? | The tenant backend is stable enough to support a real login + dashboard frontend slice, and a real browser pass was valuable because it caught a submit wiring bug that static checks missed |
|
|
| What have I done? | Added the pnpm frontend workspace, built `apps/admin-web`, wired auth and dashboard data to `tenant-api`, reduced the bundle size, and passed install/build/preview plus browser login verification |
|
|
## 2026-05-01T06:43:58Z - Platform template seed deployment
|
|
|
|
- Investigated the "普通通用模版" cards shown in the screenshot.
|
|
- Confirmed the four platform templates are stored in `article_templates` and currently seeded by `server/cmd/dev-seed/main.go`.
|
|
- Confirmed production deployment jobs only run database migrations, so a fresh environment can miss the four template records unless dev seed is run manually.
|
|
- Decision: add a production-safe platform-template initializer and wire it into the migrate job/image instead of running the broad dev seed path.
|
|
|
|
## 2026-05-01T07:15:00Z - Gitea Registry CI/CD cleanup
|
|
|
|
- Kept `deploy-config-ci.yml` validation-only after the user clarified it should not own images.
|
|
- Scoped `frontend-ci.yml` to `admin-web` and `ops-web` plus shared packages/Dockerfiles; removed browser-extension typecheck from this workflow.
|
|
- Added Gitea Registry publishing to frontend/backend CI with commit8 tags and skip-if-tag-exists behavior through `deploy/scripts/gitea-registry-images.sh`.
|
|
- Added commit8 image verification to compose/k3s/offline deployment paths so CD fails if CI has not produced the required image.
|
|
- Changed offline package defaults to use commit8 instead of tag names and to pull business images from the Gitea Registry.
|
|
- Verification passed: workflow YAML parse, deploy script `bash -n`, and `sh -n` over all workflow run blocks.
|
|
|
|
## 2026-05-03T03:03:09Z - Stable PgBouncer Deployment
|
|
|
|
- Confirmed the existing repository topology uses application-side `pgxpool` and direct Postgres service names; no PgBouncer service/config existed before this change.
|
|
- Started Phase 40 to add stable PgBouncer deployment with session pooling, app runtime traffic through PgBouncer, and migration jobs remaining direct to Postgres.
|
|
- Added `pgbouncer` and `monitoring-pgbouncer` to production Docker Compose and k3s using `edoburu/pgbouncer:v1.24.1-p1`, `POOL_MODE=session`, and `AUTH_TYPE=scram-sha-256`.
|
|
- Changed runtime app configs to target PgBouncer while keeping Docker/k3s migration jobs direct to `postgres` / `monitoring-postgres`.
|
|
- Lowered application-side Postgres pools: tenant runtime uses 12 main / 8 monitoring connections per process; ops runtime uses 5 / 5.
|
|
- Made deployment passwords flow from `POSTGRES_PASSWORD` / `OPS_POSTGRES_PASSWORD` placeholders and changed `DatabaseConfig.DSN()` to URL-escape credentials for stronger production passwords.
|
|
- Included PgBouncer in offline packaging and docs.
|
|
- Verification passed:
|
|
- `docker compose -f deploy/docker-compose.yaml --env-file deploy/.env.example config`
|
|
- `kubectl kustomize deploy/k3s` plus local YAML parse
|
|
- `bash -n deploy/scripts/package.sh`
|
|
- `git diff --check`
|
|
- `go test ./internal/shared/config ./internal/shared/repository/postgres ./internal/ops/config`
|
|
- Temporary PgBouncer container attached to existing `server_default` network returned `SELECT 1` through PgBouncer, then was removed.
|
|
|
|
## 2026-05-04T20:51:36Z - Compliance Detection Implementation
|
|
|
|
- Started Phase 41 for the Revision 8 content compliance detection design.
|
|
- Re-read the design document sections covering data model, API contracts, publish gate ordering, manual-review lifecycle, ops pages, and test requirements.
|
|
- Confirmed the current code has no compliance module yet and that publish job creation currently bypasses content compliance entirely.
|
|
- Added Phase 41-43 to `task_plan.md` and recorded the initial backend/frontend integration findings.
|
|
|
|
## 2026-05-05T09:30:00+08:00 - Compliance backend integration
|
|
|
|
- Added tenant compliance HTTP APIs for runtime status, plain/article check, latest check, record-level ack, manual-review submit/latest/cancel, and tenant whitelist/blacklist terms.
|
|
- Wired `PublishJobService.Create()` through `GateForPublish`, including effective article version resolution, target platform aggregation, block/needs_ack errors with serialized check details, and transactional ack consumption.
|
|
- Exposed `ArticleDetailResponse.current_version_id` and extended desktop publish job creation with article/version compliance metadata.
|
|
- Added ops compliance service/handlers/routes for dictionaries, terms, policy, master switch, manual reviews, records, and stats.
|
|
- Verification passed: `go test ./internal/tenant/compliance ./internal/tenant/transport ./internal/tenant/app ./internal/tenant/repository ./internal/ops/app ./internal/ops/transport ./cmd/ops-api ./cmd/worker-generate`.
|
|
|
|
## 2026-05-05T10:45:00+08:00 - Compliance completion recovery
|
|
|
|
- Continued after the 429 interruption and completed the remaining compliance display/API gap.
|
|
- Added ops-web shared type aliases, content-safety navigation, and pages for policy, dictionaries, dictionary editing, manual reviews, manual-review detail, records, and stats.
|
|
- Added admin-web compliance publish/editing integration, including editor checks, violation grouping, locate/highlight support, whitelist creation, publish gate handling, acknowledgement flow, and manual-review submission/cancel paths.
|
|
- Added LLM review AI-point reservation/completion/refund handling in tenant compliance jobs and wired the review worker to the configured LLM provider.
|
|
- Extended desktop publish task listing with publish-job compliance block metadata and updated desktop Publish Management to show `合规阻断`, record id, intercepted time, and a readable reason summary.
|
|
- Added admin-web publish status mapping/i18n for `blocked_by_compliance`.
|
|
- Verification passed:
|
|
- `go test ./internal/tenant/compliance ./internal/tenant/transport ./internal/tenant/app ./internal/worker/generate ./cmd/worker-generate`
|
|
- `go test ./...`
|
|
- `pnpm --filter admin-web typecheck`
|
|
- `pnpm --filter ops-web typecheck`
|
|
- `pnpm --filter @geo/desktop-client typecheck`
|
|
- `pnpm --filter admin-web build`
|
|
- `pnpm --filter ops-web build`
|
|
- `pnpm --filter @geo/desktop-client build`
|
|
- `git diff --check`
|
|
- Notes:
|
|
- Admin-web and ops-web production builds still warn about large chunks from existing Ant Design / Milkdown bundles.
|
|
|
|
## 2026-05-05T20:09:10+08:00 - Remove tenant compliance policy overrides
|
|
|
|
- Removed the ops-web tenant override route, menu item, API helpers, and `ComplianceTenantOverridesView.vue`.
|
|
- Removed the ops-api tenant policy override routes, handlers, service methods, audit action, and tenant override resolver branch.
|
|
- Changed `ops.compliance_policies` to an `id=1` global singleton with no `scope` / `tenant_id` columns; seed migrations and tenant-api policy loading now read/update that singleton directly.
|
|
- Updated the current compliance design doc, the archived v1 design doc, and planning notes so tenant policy overrides are no longer documented as a supported feature.
|
|
- Verification passed:
|
|
- `pnpm --filter ops-web typecheck`
|
|
- `go test ./internal/ops/app ./internal/ops/transport ./internal/tenant/compliance ./cmd/ops-api`
|
|
|
|
## 2026-05-05T21:20:00+08:00 - Article generation reliability hardening
|
|
|
|
- Started Phase 44 after the user requested large-company style safeguards: structured logs, verifiable states, no swallowed errors, and automatic alerts.
|
|
- Confirmed the remaining weak points are in article body generation worker paths, not title/outline assist paths:
|
|
- Initial task `running` updates are ignored in template/custom/imitation generation execution.
|
|
- Failure cleanup logs status update errors but still swallows quota ledger/refund errors.
|
|
- Recovery requeue/finalization logs do not carry a consistent event/stage/anomaly schema yet.
|
|
- Scope locked to generation worker/app observability and state checks, avoiding unrelated deployment/compliance dirty files.
|
|
|
|
## 2026-05-05T23:45:00+08:00 - Article generation reliability verification
|
|
|
|
- Added structured article-generation task log context and counters for transitions, failures, cleanup failures, queue failures, recovery actions, state anomalies, and state-check failures.
|
|
- Added bounded scheduler-owned generation state consistency checks with configurable interval/timeout/batch/lookback and partial DB indexes; this is a low-frequency safety net, not a full-table polling loop.
|
|
- Added internal JSON/Prometheus metrics endpoints and Prometheus alert rules for cleanup failures, state anomalies, state-check failures, queue failures, failure spikes, and recovery finalization.
|
|
- Fixed compile/test follow-ups: matched the state-check DB interface to `pgx.Rows` and made the Prometheus label assertion order-independent.
|
|
- Verification passed:
|
|
- `cd server && go test ./internal/shared/config ./internal/tenant/app ./internal/tenant/transport ./internal/worker/generate ./cmd/scheduler ./cmd/worker-generate`
|
|
- `cd server && go test ./...`
|
|
- `git diff --check`
|
|
- `ruby -e 'require "yaml"; YAML.load_file("deploy/monitoring/article-generation-alerts.yml"); puts "ok"'`
|
|
|
|
## 2026-05-06T13:05:00+08:00 - Desktop client account isolation
|
|
|
|
- Fixed the desktop media account cross-device leak reported from Mac/Windows login:
|
|
- `/api/desktop/accounts` now lists accounts by the authenticated desktop `client_id`, not `workspace_id + user_id`.
|
|
- Desktop account identity lookup and upsert now use `(workspace_id, client_id, platform_id, platform_uid)`, preventing one machine from overwriting another machine's row for the same third-party UID.
|
|
- Desktop-side patch/delete and async health sink updates now also require matching `client_id`.
|
|
- Added migration `20260506120000_scope_platform_accounts_to_desktop_client` to update the active uniqueness index.
|
|
- Added MAC-address fingerprint fallback for desktop client ID generation while keeping OS machine ID as the preferred stable source.
|
|
- Verification passed:
|
|
- `cd server && make sqlc-generate`
|
|
- `cd server && go test ./internal/tenant/app ./internal/tenant/repository ./internal/tenant/transport -count=1`
|
|
- `pnpm --filter @geo/desktop-client typecheck`
|
|
- `pnpm --filter @geo/desktop-client exec vitest run src/main/device-id.test.ts`
|
|
- `git diff --check`
|
|
- Caveat:
|
|
- `pnpm --filter @geo/desktop-client test -- src/main/device-id.test.ts` ran unrelated existing tests and failed in `deepseek.test.ts` due to a pre-existing missing `electron/main` mock; the new device-id test passes when run directly with vitest.
|
|
|
|
## 2026-05-07T11:26:26+08:00 - Admin-web publish management start
|
|
|
|
- Started Phase 48/49 for the user's content-management "发文管理" request.
|
|
- Confirmed desktop-client already has a publish management table with the requested columns/actions, but admin-web needs tenant HTTP APIs because Electron IPC is unavailable in the browser.
|
|
|
|
## 2026-05-09T17:40:00+08:00 - Desktop publisher page.evaluate packaging fix
|
|
|
|
- Investigated `page.evaluate: ReferenceError: wO is not defined` reported for desktop-client Bilibili publishing and then confirmed dongchedi has the same risk pattern.
|
|
- Root cause: packaged desktop builds run `build:obf`; `scripts/obfuscate.cjs` obfuscated `out/main/*.cjs`, and Playwright `page.evaluate` callbacks then carried obfuscator helper names into the browser page context where those helpers do not exist.
|
|
- Updated `apps/desktop-client/scripts/obfuscate.cjs` so the Electron main bundle is left unobfuscated and only renderer assets are obfuscated. This aligns the post-build obfuscation step with the existing Vite main-process `minify: false` guard.
|
|
- Verification passed:
|
|
- `pnpm --filter @geo/desktop-client typecheck`
|
|
- `pnpm --filter @geo/desktop-client build:obf`
|
|
- `pnpm --filter @geo/desktop-client exec vitest run src/main/adapters/dongchedi.test.ts`
|
|
- `pnpm --filter @geo/desktop-client exec vitest run src/main/adapters/baijiahao.test.ts`
|
|
- Searched `apps/desktop-client/out/main/bootstrap.cjs` for `wO`, `_0x...`, `stringArray`, `javascript-obfuscator`, and `['evaluate']`; no obfuscator helper traces were present after `build:obf`.
|
|
- Scoped implementation to tenant publish task list/retry endpoints plus a new admin-web `/publish-management` page under 内容管理.
|
|
- Noted existing dirty files in i18n/Knowledge/TemplateWizard/config/swagger/knowledge service and will avoid reverting or overwriting unrelated changes.
|
|
|
|
## 2026-06-23T23:54:39+08:00 - Doubao thinking-reference fallback
|
|
|
|
- Investigated the Doubao monitor failure where the answer page showed "已完成思考 / 搜索 N 个关键词,参考 N 篇资料" links but the adapter returned `unknown`.
|
|
- Current Doubao behavior observed from user screenshots:
|
|
- citation/source links now live inside the thinking block rather than next to the final answer;
|
|
- one answer can contain multiple "搜索 X 个关键词,参考 Y 篇资料" groups;
|
|
- "已完成思考,参考 N 篇资料" is a broad thinking summary control, while the search groups hold the concrete blue source links;
|
|
- already-expanded groups may still show a chevron, so clicking blindly can collapse useful references.
|
|
- Updated `apps/desktop-client/src/main/adapters/doubao.ts` so `/chat/completion` and `text/event-stream` responses remain the preferred SSE source, while a high-quality page answer can be used when SSE has not finished.
|
|
- Strengthened page fallback to expand/reference-scan Doubao's thinking search groups, skip already-expanded nearby-link groups, merge multiple thinking reference groups, and filter favicon/asset CDN links.
|
|
- Added helper coverage in `doubao.test.ts` for unfinished SSE + usable page answer, finished SSE precedence, recoverable timeout with anchored page answer, and multi-group thinking references.
|
|
- Follow-up fix: the `unknown` message "未从正文或思维链兜底抓到可提交答案,仅抓到参考资料" still happened because the implementation only used `domAnswer` as the fallback answer and did not submit `domReasoning`. The adapter now allows a high-quality thinking-chain text fallback when SSE/page answer text is missing but references and anchored page context were captured.
|
|
- Local anonymous Playwright could open Doubao only to the logged-out/home page, so live account-specific MCP/page content was not directly readable in this session.
|
|
- Verification passed:
|
|
- `pnpm --filter @geo/desktop-client exec vitest run src/main/adapters/doubao.test.ts`
|
|
- `pnpm --filter @geo/desktop-client typecheck`
|
|
- `pnpm --filter @geo/desktop-client test`
|
|
- `git diff --check`
|
|
|
|
## 2026-06-24T01:20:00+08:00 - Doubao SSE capture and challenge handling
|
|
|
|
- Confirmed from the latest user screenshot that Doubao can trigger an official-site image captcha after a prompt is submitted. This is an account/platform challenge, not an answer parsing failure.
|
|
- Hardened `apps/desktop-client/src/main/adapters/doubao.ts`:
|
|
- capture Doubao `/chat/completion` SSE in-page through fetch/XHR stream cloning and keep SSE as the primary answer/source path;
|
|
- keep DOM/page extraction as fallback, including thinking/reference panels for `search_results` without promoting reference lists to `answer`;
|
|
- verify composer write/readback before sending, avoid selecting voice/microphone controls as send buttons, and add a Playwright keyboard/mouse submit fallback when the page does not observe the user question;
|
|
- detect Doubao captcha/risk-control surfaces such as image selection, drag-to-area, human verification, security verification, and frequent-access prompts;
|
|
- return `doubao_challenge_required` as failed/non-retryable AI platform authorization when a captcha is visible, so the desktop UI alerts the user instead of writing `unknown`.
|
|
- Updated `apps/desktop-client/src/main/platform-auth-adapters.ts` so `doubao_challenge_required` is classified as a challenge.
|
|
- Updated `apps/desktop-client/src/main/runtime-controller.ts` so Doubao challenge states show a specific user-facing activity: complete Doubao human verification in the desktop client before continuing collection.
|
|
- Verification passed:
|
|
- `pnpm --filter @geo/desktop-client exec vitest run src/main/adapters/doubao.test.ts src/main/platform-auth-adapters.test.ts`
|
|
- `pnpm --filter @geo/desktop-client typecheck`
|
|
- `git diff --check`
|
|
- `pnpm --filter @geo/desktop-client build`
|
|
- Remote SSH to `39.105.229.239` with the provided credentials failed with authentication failure, so remote logs/deployment could not be inspected in this pass.
|
|
|
|
## 2026-06-24T02:22:00+08:00 - Doubao captcha display, admission, and default mode
|
|
|
|
- Updated desktop HomeView issue aggregation so Doubao human-verification/account challenge failures collapse into one actionable item: "豆包需要人工验证"; the summary count now follows displayed issue rows instead of raw failed task rows.
|
|
- Added monitor admission filtering for blocked AI platforms:
|
|
- desktop runtime computes an eligible monitor platform whitelist from current local account health;
|
|
- Doubao `challenge_required`/expired/revoked states are excluded from local monitor selection, desktop-task monitor lease fallback, legacy monitoring lease fallback, and resume calls;
|
|
- other AI platforms remain eligible, so a Doubao captcha no longer blocks Qwen/Kimi/DeepSeek/etc. work.
|
|
- Extended `/api/desktop/tasks/lease` with optional `platform_ids` for monitor leases and filtered the server-side monitor candidate SQL by that whitelist.
|
|
- Changed Doubao execution to use the default visible mode directly:
|
|
- removed active in-page switching to "专家"/"思考" and removed deep-think selection parameters from Doubao query execution;
|
|
- `provider_model` now reports `doubao-web-fast` for default/fast and for any observed expert label, with no `doubao-web-expert` remaining.
|
|
- Verification passed:
|
|
- `pnpm --filter @geo/desktop-client exec vitest run src/main/adapters/doubao.test.ts src/main/platform-auth-adapters.test.ts`
|
|
- `pnpm --filter @geo/desktop-client typecheck`
|
|
- `pnpm --filter @geo/desktop-client build`
|
|
- `cd server && go test ./internal/tenant/app ./internal/tenant/transport`
|
|
- `git diff --check`
|
|
|
|
## 2026-06-24T02:29:25+08:00 - Doubao DOM source strictness
|
|
|
|
- Refined Doubao citation extraction after the user clarified that captcha/risk-control pages may legitimately have no reference sources.
|
|
- Kept SSE as the preferred and broad source path, including structured references that embed Doubao redirect URLs in source payloads.
|
|
- Tightened DOM/page fallback so `search_results` only comes from real link/card URLs and redirect URL attributes; gray search-query/explanatory text such as "search N keywords, reference N sources" is no longer converted into citation sources.
|
|
- Removed the page-side fallback that scraped arbitrary `http` URLs from element text, so expanded blue reference links are still captured while gray search keyword text is ignored.
|
|
- Verification passed:
|
|
- `pnpm --filter @geo/desktop-client exec vitest run src/main/adapters/doubao.test.ts src/main/platform-auth-adapters.test.ts`
|
|
- `pnpm --filter @geo/desktop-client typecheck`
|
|
- `pnpm --filter @geo/desktop-client build`
|
|
- `git diff --check`
|
|
|
|
## 2026-07-12T12:15:00+08:00 - Hunyuan SSE/search and Markdown diagnosis
|
|
|
|
- Started Phase 50 for the requested Hunyuan collection repair.
|
|
- Locked the desired execution order to official API SSE first, page RPA only when SSE is missing or unusable.
|
|
- Included explicit web-search enablement and end-to-end Markdown display repair in scope.
|
|
- Added an API-priority regression test at the final Yuanbao answer-selection boundary.
|
|
- Confirmed the test fails because the current quality score selects a longer DOM/tooling string over valid SSE Markdown.
|
|
## 2026-07-12T00:00:00+08:00 - Desktop Hunyuan/Yuanbao CDP diagnosis resumed
|
|
|
|
- Confirmed `npx` and `playwright-core` are available and connected Playwright to the running Electron CDP endpoint on port 9339.
|
|
- Located two authenticated Yuanbao chat pages and inspected the live composer/tool controls.
|
|
- Reproduced a web-search verification defect: the page had only `深度思考` active while `联网搜索` remained an unselected tools-menu item, but the adapter can optimistically return enabled when the menu item exposes no ARIA state.
|
|
- Captured `apps/desktop-client/output/playwright/yuanbao-tools.png` as local visual evidence.
|
|
- Existing API-vs-DOM priority regression test remains red pending the implementation fix.
|
|
- Submitted a short search-enabled query through the real desktop Yuanbao page over CDP and captured the safe request/response shape.
|
|
- Verified the official chat SSE endpoint, real search request flags, final `meta.endConv`, and the large ratio of `deepSearch` process frames to answer `text` frames.
|
|
- Added regression coverage for strict API priority, page fallback, current-chat SSE filtering, Markdown blank-line preservation, and exclusion of nested deep-search text from the final answer.
|
|
- Initial live-test attempt selected a stale hard-coded conversation ID and failed before adapter execution. The selector was corrected to any current Yuanbao chat page.
|
|
- One CDP probe called `browser.close()` and stopped the attached Electron Chromium. The existing `electron-vite` development process restarted Electron automatically; subsequent probes exit without sending a remote close command.
|
|
- Opened the bound Yuanbao account again through the desktop AI-platform card and ran the actual updated adapter through CDP.
|
|
- Live adapter verification passed: API SSE source selected, web search verified active, exactly one current chat SSE captured, and answer non-empty.
|
|
- Final verification passed:
|
|
- `pnpm --filter @geo/desktop-client exec vitest run src/main/adapters/yuanbao.test.ts` (16/16)
|
|
- `pnpm --filter @geo/desktop-client typecheck`
|
|
- `pnpm --filter admin-web typecheck`
|
|
- `pnpm --filter @geo/desktop-client build`
|
|
- `pnpm --filter admin-web build` (existing large-chunk warning only)
|
|
- targeted Prettier formatting and `git diff --check`
|
|
## 2026-07-12T13:30:00+08:00 - AI platform multi-account support started
|
|
|
|
- Added Phases 53-56 for storage/runtime audit, binding/UI changes, same-platform monitor failover, and verification.
|
|
- Initial hypothesis: server uniqueness already permits multiple platform UIDs per desktop client, while desktop projection/binding and monitor task targeting still enforce effective single-account behavior.
|
|
- Phase 53 audit completed. No server migration is needed; implementation is scoped to desktop dedupe/binding, platform-blocking, local account-pool failover, diagnostics, and the AI account-management UI.
|
|
- Added a tested monitor-account pool with preferred-first/LRU ordering, blocked/cooldown filtering, failover classification, and reason-specific cooldowns.
|
|
- Removed desktop AI platform-only deduplication and same-platform replacement cleanup; distinct platform UIDs now retain independent server rows and local session partitions.
|
|
- Added same-platform monitor attempts inside one leased task, final-result-only submission diagnostics, account health reporting, runtime switch activities, and per-account risk-control alerts.
|
|
- Rebuilt AI Platform Management as a media-account-style multi-account page and verified its desktop layout over Electron CDP.
|
|
|
|
## 2026-07-12T14:20:00+08:00 - AI platform multi-account server invariant
|
|
|
|
- Confirmed server monitor targeting remains one target per platform even when several same-platform accounts are bound.
|
|
- `uniqueMonitorDesktopTaskPlatformIDs()` de-duplicates requested platforms before account lookup, and `selectMonitorDesktopTaskTargetsWithOptions()` selects a single best target from each platform's account candidates.
|
|
- Added focused assertions covering duplicate platform specs and the one-target result for multiple same-platform accounts.
|
|
|
|
## 2026-07-12T14:35:00+08:00 - AI platform multi-account verification complete
|
|
|
|
- Focused server targeting tests passed, including duplicate platform de-duplication and one-target selection for multiple same-platform accounts.
|
|
- Focused desktop account-pool, account-health, scheduler, and Doubao tests passed: 3 files / 38 tests.
|
|
- Full desktop verification passed: 30 files / 206 tests, Vue typecheck, production Electron build, targeted Prettier check, and `git diff --check`.
|
|
- Electron CDP UI verification remains valid at 1420x960: six platform selectors, three separately managed AI accounts, add-account choices for all six platforms, working Doubao filtering, and no overflow or overlap.
|
|
- Residual live-test limitation: the UI was exercised with real bound accounts, but automatic failover could not be triggered against two simultaneously usable Doubao accounts in this environment. The selection, cooldown, error classification, and final-result-only behavior are covered by deterministic tests.
|
|
|
|
## 2026-07-12T14:50:00+08:00 - AI/media account UI alignment started
|
|
|
|
- Added Phases 57-58 after the user clarified that AI Platform Management must visually match Media Account Management, not only expose equivalent account-management functions.
|
|
- Audited both live Vue views and identified the mismatch: AI used compact selector cards plus a custom account table, while media uses larger authorization cards and a shared hero-card table shell.
|
|
- Locked the change to renderer composition and styles; multi-account runtime behavior and account actions remain unchanged.
|
|
- First Electron CDP comparison command failed because `playwright-core` is workspace-local and cannot be resolved from the repository root. The retry runs from `apps/desktop-client`, where the dependency is installed.
|
|
|
|
## 2026-07-12T15:15:00+08:00 - AI/media account UI alignment implemented
|
|
|
|
- Removed the global “添加 AI 账号” dropdown; platform cards are now the only binding entry, matching the media account workflow.
|
|
- Replaced compact AI selectors with the media page's large card geometry, status dot, bound/unbound treatment, and “新增账号 / 绑定账号” actions.
|
|
- Rebuilt the AI authorized-account list with the same hero-card shell, toolbar, filters, transparent table header, row spacing, avatar/platform cells, status tags, and three-action layout used by Media Account Management.
|
|
- Retained AI-specific multi-account counts, account health/session data, reauthorization/probe behavior, and row-level risk-control warnings.
|
|
- Electron CDP desktop and narrow-width comparisons passed with matching geometry and no page overflow.
|
|
|
|
## 2026-07-12T15:25:00+08:00 - Missing-citation failover diagnosis
|
|
|
|
- Confirmed the existing account-pool classifier returned success as soon as any non-empty answer existed, regardless of empty `citations` and `search_results` arrays.
|
|
- Added a red regression test proving a source-less successful answer previously returned no failover reason.
|
|
- Added `missing_citations` as a current-task failover reason. It has zero account cooldown because missing sources can be question-specific and should not mark the account unhealthy for later tasks.
|
|
|
|
## 2026-07-12T15:35:00+08:00 - AI account UI and missing-citation failover verified
|
|
|
|
- Full desktop tests passed: 30 files / 206 tests.
|
|
- Desktop Vue typecheck and production Electron build passed.
|
|
- Targeted Prettier checks and `git diff --check` passed.
|
|
- CDP confirmed AI and media platform cards have matching geometry at 1420x960; the AI page also passed 1024x800 responsive inspection with no page overflow.
|
|
- The live DOM contains only the hero actions “一键检测账号” and “刷新状态”; the removed global “添加 AI 账号” button is absent.
|
|
- Successful answers now require at least one item in `citations` or `search_results` to stop same-platform account failover. When every account lacks sources, the existing loop preserves and submits the final non-empty answer with attempt diagnostics.
|
|
|
|
## 2026-07-12T15:50:00+08:00 - Admin AI account management extraction started
|
|
|
|
- Added Phases 60-62 for a new tracking-side “AI 账号管理” menu after “外部文章标记”.
|
|
- Confirmed the existing tracking status panel collapses multiple accounts to the first account per platform even though the API returns every account.
|
|
- Confirmed account removal and delete-request APIs can be reused from Media Account Management; implementation needs no server migration.
|