chore: update chat history archive + design-tokens tarball

This commit is contained in:
saravanakumardb1 2026-03-31 01:42:31 -07:00
parent 23d5ef44f3
commit de13a08a98
7 changed files with 690 additions and 6 deletions

View File

@ -1,9 +1,9 @@
Last refresh: 2026-03-29T06:00:06Z (2026-03-28 23:00:06 PDT) Last refresh: 2026-03-31T06:00:05Z (2026-03-30 23:00:05 PDT)
Cascade conversations: 50 (424M) Cascade conversations: 50 (366M)
Memories: 104 Memories: 106
Implicit context: 20 Implicit context: 20
Code tracker dirs: 77 Code tracker dirs: 43
File edit history: 3881 entries File edit history: 4014 entries
Workspace storage: 34 workspaces Workspace storage: 34 workspaces
Repo docs: 7 files across 2 repos Repo docs: 7 files across 2 repos
Repo workflows: 49 files across 11 repos Repo workflows: 54 files across 12 repos

View File

@ -0,0 +1,9 @@
# Effo Rise AI — Windsurf Workflows
This directory contains Windsurf workflow definitions for the Effo Rise AI project.
## Available Workflows
| Workflow | Description |
| ----------------------- | ----------------------------------------- |
| `/refresh-chat-history` | Refresh the Windsurf chat history archive |

View File

@ -0,0 +1,17 @@
---
description: Refresh the Windsurf chat history archive
---
# Refresh Chat History
This workflow is a placeholder for the Effo Rise AI project. Since this repo does not currently have a chat-history archive directory, this workflow is minimal.
## Steps
1. Confirm the repo is clean or commit pending changes first.
```bash
cd /Users/sd9235/code/mygh/learning_ai_efforise && git status --short
```
2. No chat-history symlinks or archives to refresh for this repo at this time.

View File

@ -0,0 +1,125 @@
---
description: 'Window 1: Phase 0 scaffolding + Manus cleanup (RUN FIRST — other windows depend on this)'
---
# Window 1: Phase 0 Scaffolding + Manus Cleanup
> **MUST complete before starting Window 2 or Window 3.**
> **Scope:** Root files, `shared/`, `vite.config.ts`, config files. Do NOT create `backend/` or `mobile/`.
> **Reference:** `docs/ECOSYSTEM_ADAPTATION_ROADMAP.md` Sections 4 (Phase 0), 5, and 6.
## Context
This repo (`learning_ai_efforise`) is a Vite + React 19 SPA built by Manus.computer. It needs ecosystem scaffolding before any feature work. The product is **EffoRise** — an identity-based habit tracker. Product ID: `efforise`, backend port: 4020, web port: 3080.
## Step 1: Create Product Identity
Create `shared/product.json` following the ecosystem pattern. Use NoteLett (`../learning_ai_notes/shared/product.json`) or ActionTrail (`../learning_ai_trails/shared/product.json`) as reference. Key fields:
```json
{
"productId": "efforise",
"productName": "EffoRise",
"displayName": "EffoRise",
"description": "Identity-based habit tracker — rise with efforts",
"domain": "efforise.app",
"version": "0.1.0",
"ports": {
"backend": 4020,
"web": 3080
},
"bundleIds": {
"ios": "com.saravana.efforise",
"android": "com.saravana.efforise"
},
"platforms": ["web", "mobile"],
"tokenPrefix": "--er-",
"ecosystem": "bytelyst"
}
```
## Step 2: Create Agent Config Files (8 files)
Create all 8 agent config files matching ecosystem standard. Copy structure from `../learning_ai_notes/` or `../learning_ai_trails/`:
1. `AGENTS.md` — AI agent onboarding guide (customize for efforise: Vite SPA + Fastify backend, productId efforise, port 4020, --er-\* tokens)
2. `CLAUDE.md` — Claude Code instructions (short version pointing to AGENTS.md)
3. `.windsurfrules` — Windsurf rules (short version pointing to AGENTS.md)
4. `.cursorrules` — Cursor rules (short version pointing to AGENTS.md)
5. `.clinerules` — Cline rules (short version pointing to AGENTS.md)
6. `.aider.conf.yml` — Aider config
7. `.editorconfig` — Copy from any ecosystem repo
8. `.github/copilot-instructions.md` — GitHub Copilot rules
## Step 3: Create Root Config Files
1. Add `.nvmrc` with content `22`
2. Update `packageManager` in `package.json` to `"pnpm@10.6.5"`
3. Add `.npmrc` — copy from `../learning_ai_notes/.npmrc` (Gitea registry config)
4. Add `.npmrc.docker` — copy from `../learning_ai_notes/.npmrc.docker`
5. Add `pnpm-workspace.yaml`:
```yaml
packages:
- backend
```
6. Add `.husky/pre-commit` and `.husky/pre-push` — copy from `../learning_ai_notes/.husky/`
7. Add `scripts/secret-scan-repo.sh` and `scripts/secret-scan-staged.sh` — copy from `../learning_ai_notes/scripts/`
8. Add `.dockerignore` — copy from `../learning_ai_notes/.dockerignore`
9. Add `eslint.config.js` at root — ESLint 9 flat config
## Step 4: Manus Artifact Cleanup
### 4a. Clean `vite.config.ts`
- Remove `vite-plugin-manus-runtime` plugin
- Remove `vite-plugin-manus-debug-collector` plugin + all LOG_DIR code
- Remove `@builder.io/vite-plugin-jsx-loc` plugin
- Replace `allowedHosts: [".manuspre.computer", ...]` with `allowedHosts: ["localhost"]`
### 4b. Delete Manus Files
- Delete `client/src/components/ManusDialog.tsx`
- Delete `client/src/components/Map.tsx` (Google Maps boilerplate, 156 lines)
- Delete `client/public/__manus__/` directory (contains `debug-collector.js`)
- Delete `client/public/images/` (empty dir, referenced `identity-tree.png` never existed)
- Delete `report.txt` (root — Manus project report)
- Delete `server/` directory entirely (Express static server — replaced by backend/ in Phase 1)
- Delete `shared/const.ts` (Manus OAuth constants — `COOKIE_NAME`, `ONE_YEAR_MS`)
- Delete `patches/wouter@3.7.1.patch` (evaluate first — remove if not critical)
### 4c. Clean `client/index.html`
- Remove `VITE_ANALYTICS_ENDPOINT` / `VITE_ANALYTICS_WEBSITE_ID` script references
### 4d. Dependency Cleanup in `package.json`
- **Downgrade** `zod` from `^4.1.12``^3.24.2` (CRITICAL — Zod 4 breaks @bytelyst/\* integration)
- **Upgrade** `typescript` from `5.6.3``^5.7.3`
- **Remove:** `streamdown`, `cmdk`, `add` (devDep), `@types/google.maps` (devDep), `next-themes`
- **Remove:** `express`, `@types/express` (server/ is deleted)
- **Remove** Manus vite plugins from devDeps: `vite-plugin-manus-runtime`, `@builder.io/vite-plugin-jsx-loc`
### 4e. Move Files
- Move `ideas.md``docs/ideas.md`
## Step 5: Create README.md
Write a proper README.md with:
- Product name + description
- Tech stack (Vite + React 19 SPA, Fastify 5 backend planned)
- Setup instructions (`pnpm install`, `pnpm dev`)
- Port assignments (backend: 4020, web: 3080)
- Link to `docs/ECOSYSTEM_ADAPTATION_ROADMAP.md`
## Step 6: Verify
- Run `pnpm install` to verify lock file generates cleanly
- Run `pnpm dev` to verify the Vite SPA still works after cleanup
- Commit: `chore(scaffold): Phase 0 product identity + ecosystem scaffolding`
- Commit: `chore(cleanup): remove Manus artifacts and fix dependencies`
## Done Signal
When complete, tell the user: **"Window 1 complete. You can now start Window 2 (backend) and Window 3 (web) in parallel."**

View File

@ -0,0 +1,255 @@
---
description: 'Window 2: Backend scaffold + domain modules (Phase 1 + Phase 3 — start AFTER Window 1 completes)'
---
# Window 2: Backend Scaffold + Domain Modules
> **Prerequisites:** Window 1 must be complete (product identity, pnpm-workspace, .npmrc exist).
> **Scope:** `backend/` directory ONLY. Do NOT modify `client/`, `mobile/`, root config files, or `shared/`.
> **Reference:** `docs/ECOSYSTEM_ADAPTATION_ROADMAP.md` Sections 4 (Phase 1, Phase 3).
> **Scaffold reference repos:** `../learning_ai_notes/backend/`, `../learning_ai_trails/backend/`, `../learning_ai_flowmonk/backend/`
## Context
EffoRise is an identity-based habit tracker. Product ID: `efforise`, backend port: 4020. The backend follows the standard ByteLyst product-backend pattern: Fastify 5 + TypeScript ESM + `@bytelyst/*` shared packages + Zod validation.
All `@bytelyst/*` packages come from the Gitea npm registry (configured in root `.npmrc`). Use `@bytelyst/datastore` with `DB_PROVIDER=memory` for local dev (no Cosmos needed).
---
## Phase 1: Backend Scaffold
### Step 1: Create `backend/package.json`
Copy structure from `../learning_ai_notes/backend/package.json`. Key deps:
**dependencies:**
- `@bytelyst/fastify-core`, `@bytelyst/config`, `@bytelyst/errors`, `@bytelyst/datastore`
- `@bytelyst/cosmos`, `@bytelyst/auth`, `@bytelyst/fastify-auth`, `@bytelyst/backend-config`
- `@bytelyst/backend-telemetry`, `@bytelyst/backend-flags`, `@bytelyst/field-encrypt`
- `@bytelyst/logger`, `fastify`, `zod` (^3.24.2), `jose`
**devDependencies:**
- `typescript` (^5.7.3), `tsx`, `vitest`, `eslint` (^9.0.0), `@bytelyst/testing`
**scripts:**
- `"dev": "tsx watch src/server.ts"`
- `"build": "tsc"`
- `"typecheck": "tsc --noEmit"`
- `"test": "vitest run"`
- `"start": "node dist/server.js"`
### Step 2: Create `backend/tsconfig.json`
Extend `../../tsconfig.base.json` if available, otherwise use ecosystem standard:
```json
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"outDir": "dist",
"rootDir": "src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"declaration": true,
"resolveJsonModule": true
},
"include": ["src/**/*.ts"],
"exclude": ["src/**/*.test.ts", "dist"]
}
```
### Step 3: Create `backend/src/lib/` Files
Create these standard lib files (copy patterns from `../learning_ai_notes/backend/src/lib/`):
1. **`product-config.ts`** — Read `../../shared/product.json`, export `productConfig`, `PRODUCT_ID`
2. **`config.ts`** — Zod env schema (PORT=4020, HOST, NODE_ENV, DB_PROVIDER, JWT_SECRET, CORS_ORIGIN, COSMOS_ENDPOINT, COSMOS_KEY, COSMOS_DATABASE)
3. **`auth.ts`** — Re-export JWT extraction from `@bytelyst/auth` or `@bytelyst/fastify-auth`
4. **`request-context.ts`** — `getUserId(req)`, `getRequestProductId(req)` helpers
5. **`errors.ts`** — Re-export from `@bytelyst/errors`
6. **`datastore.ts`** — `@bytelyst/datastore` provider init (Cosmos or memory via `DB_PROVIDER`)
7. **`cosmos-init.ts`** — Register all Cosmos containers on startup (effo_identities, effo_efforts, effo_habits, effo_streaks, effo_insights)
8. **`field-encrypt.ts`** — Field encryption singleton from `@bytelyst/field-encrypt`
9. **`telemetry.ts`** — Telemetry event buffer stub from `@bytelyst/backend-telemetry`
10. **`feature-flags.ts`** — Feature flag registry stub from `@bytelyst/backend-flags`
### Step 4: Create `backend/src/server.ts`
Fastify entrypoint using `createServiceApp()` from `@bytelyst/fastify-core`:
- Register CORS, auth, health endpoint
- Register cosmos-init on startup
- Register route modules (added in Phase 3)
- `startService()` on port 4020
### Step 5: Create `backend/src/diagnostics.test.ts`
Standard diagnostic health-check test (copy from any ecosystem backend).
### Step 6: Create Config Files
- `backend/.env.example` — All env vars with defaults
- `backend/.gitignore``dist/`, `node_modules/`, `.env`
- `backend/eslint.config.js` — ESLint 9 flat config (copy from `../learning_ai_notes/backend/`)
- `backend/vitest.config.ts` — Vitest config
- `backend/Dockerfile` — Multi-stage Fastify build (copy from `../learning_ai_notes/backend/Dockerfile`)
### Step 7: Add Vite Proxy
Add to `vite.config.ts` (in the root, this is the ONE root file you may touch):
```ts
server: {
proxy: {
'/api': 'http://localhost:4020'
}
}
```
### Step 8: Verify Phase 1
```bash
cd backend && pnpm install && pnpm run typecheck && pnpm run build && pnpm test
```
Commit: `feat(backend): Phase 1 backend scaffold with Fastify 5 + @bytelyst/* packages`
---
## Phase 3: Domain Modules
### Module Pattern
Each module lives in `backend/src/modules/<name>/` with three files:
- `types.ts` — Zod schemas + TypeScript types, Cosmos doc shape
- `repository.ts` — CRUD operations via `@bytelyst/datastore` `getCollection()`
- `routes.ts` — Fastify route handlers with Zod validation
- `routes.test.ts` — Vitest tests using `buildTestApp()` pattern
Every Cosmos document MUST include `productId: "efforise"`.
### Module 1: `identities`
Container: `effo_identities`, partition: `/userId`
| Field | Type | Description |
| ----------- | ---------- | ------------------------- |
| id | string | UUID |
| userId | string | Owner |
| productId | "efforise" | Required |
| name | string | "Writer", "Athlete", etc. |
| parentId | string? | For tree structure |
| description | string | What this identity means |
| color | string | Accent color |
| icon | string | Emoji or icon key |
| order | number | Sort order |
| createdAt | string | ISO timestamp |
| updatedAt | string | ISO timestamp |
Routes: GET /api/identities, POST /api/identities, GET /api/identities/:id, PATCH /api/identities/:id, DELETE /api/identities/:id, PATCH /api/identities/:id/reorder
### Module 2: `efforts`
Container: `effo_efforts`, partition: `/userId`
| Field | Type | Description |
| --------------- | ----------------------------- | ----------------------------------- |
| id | string | UUID |
| userId | string | Owner |
| productId | "efforise" | Required |
| identityId | string | Which identity this effort supports |
| habitId | string? | Optional link to habit |
| type | "micro" \| "medium" \| "deep" | Effort depth |
| description | string | What was done |
| durationMinutes | number? | Optional duration |
| loggedAt | string | When the effort happened |
| createdAt | string | ISO timestamp |
Routes: GET /api/efforts, POST /api/efforts, GET /api/efforts/:id, PATCH /api/efforts/:id, DELETE /api/efforts/:id, GET /api/efforts/stats (aggregation)
### Module 3: `habits`
Container: `effo_habits`, partition: `/userId`
| Field | Type | Description |
| ------------ | ------------------------------- | ------------------------------------- |
| id | string | UUID |
| userId | string | Owner |
| productId | "efforise" | Required |
| identityId | string | Which identity this habit supports |
| name | string | "Write 500 words", "Run 3 miles" |
| frequency | "daily" \| "weekly" \| "custom" | How often |
| customDays | number[]? | If frequency=custom, which days (0-6) |
| targetCount | number | Times per period |
| reminderTime | string? | HH:MM for push notification |
| isActive | boolean | Can be paused |
| createdAt | string | ISO timestamp |
| updatedAt | string | ISO timestamp |
Routes: GET /api/habits, POST /api/habits, GET /api/habits/:id, PATCH /api/habits/:id, DELETE /api/habits/:id
### Module 4: `streaks`
Container: `effo_streaks`, partition: `/userId`
| Field | Type | Description |
| ---------------- | ---------- | ------------------------ |
| id | string | UUID |
| userId | string | Owner |
| productId | "efforise" | Required |
| habitId | string | Which habit |
| currentStreak | number | Current consecutive days |
| longestStreak | number | All-time record |
| lastLogDate | string | YYYY-MM-DD |
| totalCompletions | number | All-time count |
| updatedAt | string | ISO timestamp |
Routes: GET /api/streaks, GET /api/streaks/:habitId, POST /api/streaks/:habitId/log (increment)
### Module 5: `insights`
Container: `effo_insights`, partition: `/userId`
| Field | Type | Description |
| ------------------ | --------------------------------------------- | -------------------------- |
| id | string | UUID |
| userId | string | Owner |
| productId | "efforise" | Required |
| type | "weekly_summary" \| "coaching" \| "milestone" | Insight type |
| title | string | Display title |
| body | string | Insight content (markdown) |
| relatedIdentityIds | string[] | Referenced identities |
| generatedAt | string | ISO timestamp |
| dismissedAt | string? | If user dismissed |
Routes: GET /api/insights, GET /api/insights/:id, POST /api/insights/:id/dismiss
### Step: Register All Modules
Update `server.ts` to register all 5 route modules. Update `cosmos-init.ts` to register all 5 containers.
### Step: Create `backend/src/test-helpers.ts`
Standard `buildTestApp()` helper for Vitest (copy pattern from `../learning_ai_notes/backend/src/test-helpers.ts`).
### Verify Phase 3
```bash
cd backend && pnpm run typecheck && pnpm test && pnpm run build
```
Commit: `feat(backend): Phase 3 domain modules — identities, efforts, habits, streaks, insights`
---
## Done Signal
When complete, tell the user: **"Window 2 complete. Backend with 5 domain modules is ready. Window 3 can now build web screens against these APIs. Window 5 (mobile) can also start."**

View File

@ -0,0 +1,278 @@
---
description: 'Window 3: Web frontend + design tokens + platform integration + DevOps (Phase 2 + 4 + 5 + 6 — start AFTER Window 1 completes)'
---
# Window 3: Web Frontend + DevOps
> **Prerequisites:** Window 1 must be complete (Manus artifacts removed, deps cleaned, scaffolding in place).
> **Scope:** `client/` directory, root DevOps files (`Dockerfile`, `docker-compose.yml`, `.gitea/`, `scripts/docker-prep.sh`). Do NOT modify `backend/` or `mobile/`.
> **Reference:** `docs/ECOSYSTEM_ADAPTATION_ROADMAP.md` Sections 4 (Phase 2, 4, 5, 6).
> **Scaffold reference repos:** `../learning_ai_fastgap/web/` (NomGap), `../learning_ai_notes/web/` (NoteLett)
## Context
EffoRise is an identity-based habit tracker. The web frontend is a Vite + React 19 SPA in `client/`. Currently only a landing page exists (`client/src/pages/Home.tsx`). The backend (Window 2) exposes APIs on port 4020. Vite proxy is configured to forward `/api``http://localhost:4020`.
Product design direction: "Modern Gradient Minimalism" with emerald green branding and glassmorphic UI elements (see `docs/ideas.md`). CSS token prefix: `--er-*`.
---
## Phase 2: Design Token Alignment
### Step 1: Define `--er-*` CSS Custom Properties
Update `client/src/index.css` to use `--er-*` prefixed tokens. Map existing unprefixed vars to the new namespace:
```css
:root {
/* EffoRise design tokens (--er-* namespace) */
--er-bg-primary: #ffffff;
--er-bg-secondary: #f8fafc;
--er-bg-surface: #ffffff;
--er-text-primary: #0f172a;
--er-text-secondary: #475569;
--er-text-muted: #94a3b8;
--er-accent-primary: #059669; /* emerald-600 */
--er-accent-secondary: #0d9488; /* teal-600 */
--er-accent-gradient: linear-gradient(to right, #059669, #0d9488);
--er-border-default: #e2e8f0;
--er-border-subtle: #f1f5f9;
--er-radius-sm: 0.375rem;
--er-radius-md: 0.5rem;
--er-radius-lg: 0.75rem;
--er-radius-xl: 1rem;
/* ... dark mode overrides in .dark {} */
}
```
Keep the existing shadcn/ui CSS variable layer (--background, --foreground, etc.) but wire them to reference `--er-*` tokens underneath so the app can gradually migrate.
### Step 2: Integrate `@bytelyst/design-tokens`
Add `@bytelyst/design-tokens` to root `package.json` (devDep). This provides the canonical token source. The `--er-*` tokens should align with the generated values where possible.
### Step 3: Wire `@bytelyst/ui` Components
Add `@bytelyst/ui` to root `package.json`. Audit existing `client/src/components/ui/` — replace local shadcn copies where `@bytelyst/ui` equivalents exist (Button, Card, Badge, Toast, etc.). Keep app-specific components local.
Commit: `feat(web): Phase 2 design tokens — --er-* namespace + @bytelyst/design-tokens`
---
## Phase 4: Web App Screens
### Step 1: Create App Layout
Create a sidebar-based app layout (matching ecosystem pattern). Reference `../learning_ai_fastgap/web/src/components/Sidebar.tsx`.
The app should have two modes:
- **Marketing:** Landing page at `/` (existing `Home.tsx`)
- **App:** Sidebar layout at `/app/*` routes (new)
For Vite SPA with wouter:
- `/` → Landing page (existing)
- `/app` → Dashboard
- `/app/identity` → Identity tree builder
- `/app/log` → Effort logging
- `/app/insights` → Progress charts
- `/app/settings` → Account settings
### Step 2: Create API Client
Create `client/src/lib/api-client.ts` — typed fetch wrapper for backend API:
```typescript
const API_BASE = '/api'; // Vite proxy handles forwarding to :4020
export async function fetchApi<T>(path: string, options?: RequestInit): Promise<T> {
const res = await fetch(`${API_BASE}${path}`, {
headers: { 'Content-Type': 'application/json', ...options?.headers },
...options,
});
if (!res.ok) throw new Error(`API error: ${res.status}`);
return res.json();
}
```
Create typed clients: `identity-client.ts`, `effort-client.ts`, `habit-client.ts`, `streak-client.ts`, `insight-client.ts`.
### Step 3: Create Zustand Store
Create `client/src/lib/store.ts` — app state store:
```typescript
import { create } from 'zustand';
// Identity, effort, habit, streak state + actions
// Wire to API clients for fetch/create/update/delete
```
### Step 4: Build Screens
Build each screen as a component in `client/src/pages/app/`:
1. **Dashboard** (`Dashboard.tsx`)
- Identity tree summary cards
- Today's habits checklist
- Current streaks display
- Quick-log effort button
- Recent insights
2. **Identity Builder** (`Identity.tsx`)
- Tree view of identities (parent/child)
- Create/edit identity modal
- Drag-and-drop reorder
- Color + icon picker
3. **Effort Logger** (`Log.tsx`)
- Quick-tap effort buttons (micro/medium/deep)
- Select identity + optional habit
- Description + duration
- Recent efforts timeline
4. **Insights** (`Insights.tsx`)
- Weekly effort chart (Recharts)
- Streak leaderboard
- AI coaching cards
- Milestone celebrations
5. **Settings** (`Settings.tsx`)
- Account info (placeholder until auth)
- Theme toggle (already exists via ThemeContext)
- Notification preferences (placeholder)
- Data export
### Step 5: Verify Phase 4
- All screens render without errors
- API calls work through Vite proxy to backend (if Window 2 is running)
- Navigation works between all routes
Commit: `feat(web): Phase 4 app screens — dashboard, identity, log, insights, settings`
---
## Phase 5: Platform Integration
### Step 1: Add Platform Client Packages
Add to root `package.json`:
- `@bytelyst/react-auth` — Auth context + provider
- `@bytelyst/api-client` — Typed fetch wrapper (can replace manual api-client.ts)
- `@bytelyst/telemetry-client` — Browser telemetry
- `@bytelyst/diagnostics-client` — Diagnostic reporter
- `@bytelyst/feature-flag-client` — Feature flags
- `@bytelyst/kill-switch-client` — Kill switch
- `@bytelyst/platform-client` — Platform service client
### Step 2: Wire Auth
Create `client/src/lib/auth.ts`:
```typescript
import { createAuthContext } from '@bytelyst/react-auth';
export const { AuthProvider, useAuth } = createAuthContext({
platformUrl: 'http://localhost:4003',
productId: 'efforise',
});
```
Wrap app in `<AuthProvider>` in `App.tsx`.
### Step 3: Wire Telemetry + Diagnostics
Create `client/src/lib/telemetry.ts` and `client/src/lib/diagnostics.ts`. Initialize in app root.
### Step 4: Wire Feature Flags + Kill Switch
Create `client/src/lib/feature-flags.ts` and `client/src/lib/kill-switch.ts`. Use for gating unreleased features.
### Step 5: Create Product Config
Create `client/src/lib/product-config.ts`:
```typescript
import productJson from '../../../shared/product.json';
export const PRODUCT_ID = productJson.productId;
export const PRODUCT_NAME = productJson.productName;
// etc.
```
Commit: `feat(web): Phase 5 platform integration — auth, telemetry, flags, kill switch`
---
## Phase 6: DevOps
### Step 1: Docker
- Create `client/Dockerfile` — multi-stage Vite build (or copy from NomGap `../learning_ai_fastgap/web/Dockerfile` and adapt for Vite)
- Create `docker-compose.yml` at root:
```yaml
services:
backend:
build: ./backend
ports: ['4020:4020']
env_file: backend/.env
web:
build: ./client
ports: ['3080:3080']
```
- Create `scripts/docker-prep.sh` — Pack @bytelyst/\* tarballs for Docker builds (copy from `../learning_ai_notes/scripts/docker-prep.sh`)
### Step 2: CI
Create `.gitea/workflows/ci.yml`:
```yaml
name: CI
on: [push, pull_request]
jobs:
backend:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with: { node-version: 22 }
- run: pnpm install --frozen-lockfile
- run: cd backend && pnpm run typecheck
- run: cd backend && pnpm test
- run: cd backend && pnpm run build
web:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with: { node-version: 22 }
- run: pnpm install --frozen-lockfile
- run: cd client && npx tsc --noEmit
- run: pnpm run build
```
### Step 3: Playwright E2E
Create `client/e2e/` directory with:
- `playwright.config.ts` — config targeting `http://localhost:3080`
- `accessibility.spec.ts` — axe-core accessibility checks on all pages
- `navigation.spec.ts` — verify all routes load
### Step 4: Register in Ecosystem
Tell user to add to `../learning_ai_common_plat/`:
- `docker-compose.ecosystem.yml`: efforise-backend :4020, efforise-web :3080
- `.env.ecosystem.example`: Effo Rise env vars
- `products/efforise/product.json`: Product registry entry
Commit: `chore(devops): Phase 6 — Docker, CI, Playwright E2E, docker-prep`
---
## Done Signal
When complete, tell the user: **"Window 3 complete. Web app with 5 screens, platform integration, Docker, CI, and Playwright E2E are ready."**