Files
geo/progress.md
T
root 4174aafcbc docs: record Phase 21 foreground publish admission
Log the decision to implement publish priority through admission control
and reserved capacity rather than queue sort order, and capture the
preexisting electron.vite.config.ts typecheck mismatch that blocked a
clean desktop-client typecheck run.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 09:44:15 +08:00

28 KiB

Progress Log

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
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 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.

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