Files
LexAI/docs/HANDOFF.md
john kevin asprec c2ca659a2b
All checks were successful
CI — Test & Build / Test & Build (push) Successful in 1m15s
feat: Enhance project memory and skills documentation; add memory-sync skill for knowledge consolidation
2026-07-15 16:01:13 +08:00

29 lines
8.3 KiB
Markdown

# Handoff — LexAI
## Current state
- **Outcome:** Phase 1 complete (7 workitems, 2026-03-06). Codebase reviewed 2026-07-13 (`RECOMMENDATIONS.md`). Operating-system docs + agent roster aligned to the template 2026-07-15.
- **Delivered:** working MV3 extension — selection detection (textarea/input/contenteditable), floating toolbar, background LLM proxy with OpenAI/Anthropic/Groq/OpenRouter, Options page, result modal with Replace/Copy. Build ~166 KB.
- **Verified (Phase 1):** `npm run build` clean. Note: unit tests currently exercise the storage mock, not the real handlers; e2e has `[EXTENSION_ID]` placeholders and won't pass as-is.
- **Verified (2026-07-15 finalize/build):** `npm run typecheck` clean, `npm test -- --run` 46/46 passing (actions, messaging, crypto, providers), `npm run build` clean → `.output/chrome-mv3/` (265.82 kB) ready for load-unpacked testing. Recent refactor series (crypto consolidation, provider adapter table, context-menu registry, dev-gated debug logs) all pass gates; real-page Replace verification still pending on the user's load-unpacked check.
- **Fix (2026-07-15):** OpenAI adapter now sends `max_completion_tokens` instead of the legacy `max_tokens` (newer OpenAI models reject it) and omits `temperature` for reasoning models (`o*`/`gpt-5*`, which only accept the default). Groq/OpenRouter unchanged (they still expect `max_tokens`). Pinned tests updated + new reasoning-model test; typecheck/47 tests/build all green; rebuilt `.output/chrome-mv3/`.
- **Feature (2026-07-15):** Options form reordered to Provider → API Key → Model (model list is fetched with the key). New `prompt` action ("Make Prompt", prompt-engineer): added to `ACTIONS`/labels (context menus follow automatically), prompt-engineer system prompt in `getSystemPrompt` with a prompt-directed style modifier, toolbar button (🪄 Prompt) in content.ts, popup button. Tests updated (registry count now derived; new getSystemPrompt cases); typecheck/48 tests/build green.
- **Feature (2026-07-15, Prompt Builder):** dedicated popup section for the `prompt` action with its own parameters — Prompt Style (Auto/Instructional/Role-play/Step-by-step/Few-shot/Structured), Persona (presets + Custom free text + None), Output Format (Auto/Plain/Markdown/Bulleted/Numbered/JSON/Table). Constants in `src/lib/actions.ts`, `PromptParams` added to `AnalyzePayload` (both message shapes still supported), composed into the system prompt by `promptParamModifiers` in providers.ts (prompt action only; 'Auto' = no-op). Params persist in `chrome.storage.local`. Toolbar 🪄 Prompt keeps Auto defaults. typecheck/49 tests/build green.
- **Feature (2026-07-15, popup tabs + model picker):** popup restructured into two tabs — "✍ Writing" (style + fix/rephrase/shorten/expand) and "🪄 Prompt Builder" (prompt params + Make Prompt). Prompt Builder gained a Model picker: fetched via `LIST_MODELS` on first tab open, '' = configured default; selection sent as new optional `model` override on `AnalyzePayload` (both message shapes), applied in background's `handleAnalyzeText`. Tab + model persist in storage. typecheck/49 tests/build green.
- **Tweak (2026-07-15):** model picker's "Default (model)" label → plain "Default" (badge already shows the model). Toolbar/context-menu `prompt` requests now inherit the saved Prompt Builder settings: background's `handleAnalyzeText` loads `promptStyle/promptPersona/customPersona/promptFormat/promptModel` from storage when the payload has no `promptParams` (popup still sends explicit ones); persona resolution shared via `resolvePromptPersona` in actions.ts. typecheck/49 tests/build green.
- **Feature (2026-07-15, in-page Prompt Builder dialog):** toolbar 🪄 Prompt and context-menu "Make Prompt" now open an on-page dialog (content.ts `showPromptBuilderDialog`) with the popup's parameters (Style/Persona+custom/Format/Model); selections persist to the shared storage keys, then the request runs without explicit params (background applies saved). Context menu: prompt is now a single item (no style children — registry excludes it; tests updated). `LIST_MODELS` resolves provider from storage when omitted. Toolbar re-clamps position using its real width so the last buttons stay on-screen. typecheck/49 tests/build green. Needs a real-page check (dialog + replace are DOM-timing-sensitive).
- **Fix (2026-07-15, prompt UX chain):** Make Prompt no longer closes the dialog silently — the dialog becomes a "⟳ Building your prompt…" spinner and `runAction` closes it (`closePromptBuilder`) at every completion path (success, error, invalidated-context). Prompt result modal is prompt-specific: "🪄 Engineered Prompt" title, and the writing-style selector row is replaced by "✎ Edit Parameters" (reopens the builder dialog) + Regenerate (re-runs with saved builder params). typecheck/49 tests/build green.
- **Security/perf pass (2026-07-15, goal-driven audit):** reviewed key safety, user-text privacy, and content-script performance; fixed:
- `src/lib/crypto.ts` — new `migratePlaintextApiKey()`: background auto-encrypts a legacy plaintext `apiKey` on worker start and removes the plaintext (write-and-await key material before delete; verify-decrypt before dropping plaintext when an encrypted key already exists; re-check for a concurrent Options save before writing). Read-path plaintext fallback in `resolveApiKey` retained per invariant.
- `entrypoints/background.ts` — calls the migration on startup; `sender.id !== chrome.runtime.id` guard on `onMessage` (defense-in-depth; internal senders unaffected).
- `entrypoints/content.ts` — fixed unbounded document-listener leak: `showToolbar` added `click`/`scroll` listeners per selection and never removed them; now unregistered in `hideToolbar` (also closes an orphaned More-menu). Error toast gained `data-lexai`; mouseup threshold now uses `MIN_SELECTION_LENGTH` (was hardcoded `<= 10`, which ate exactly-10-char selections); same sender guard on its listener.
- `src/lib/providers.ts``callProvider` guards `res.json()` so non-JSON gateway errors (HTML 502) surface as `"<Provider> error: HTTP <status>"` instead of a raw SyntaxError.
- Verified: typecheck clean, 54/54 tests (6 new: 4 migration, 1 non-JSON error, plus existing), build clean (280.3 kB). `security-auditor` reviewed the key-path diff: PASS; its two P3 hardening notes (await encKey persistence, concurrent-save re-check) were implemented and re-gated. User-text privacy audited clean: no persistence of analyzed text, debug logs dev-gated, key/text travel only to the chosen provider. Real-page load-unpacked check of toolbar/replace still recommended (DOM-timing paths untouched except listener cleanup).
- **CI fix + workflow hardening (2026-07-15):** CI typecheck failed on push (`content.ts(10,31) TS2339: Property 'env' does not exist on type 'ImportMeta'`) because `.wxt/types/` (which types `import.meta.env`) is generated by `wxt prepare`, which CI never ran — locally it existed as a side effect of `wxt build`/`dev`. Reproduced locally by deleting `.wxt/`. Fixes: `postinstall: wxt prepare` in package.json (root fix — every fresh install regenerates types); explicit "Prepare WXT types" step in both workflows (survives a future `--ignore-scripts`); `deploy-chrome.yml` now runs **typecheck** before tests (release previously gated less than CI); fixed `head -1``sed '$d'` body extraction in both curl-response checks (body is all-but-last-line, not first line); added `timeout-minutes` (15 CI / 20 deploy). Verified: fresh install regenerates `.wxt`, then typecheck + 54/54 tests + build all green. CLAUDE.md Commands section documents the gotcha.
- **Changed paths (this alignment):** added `docs/` (brief, architecture, decisions, tasks, evals, lessons, handoff, self-model, attacksurface), ported `.claude/agents/*` roster + `.claude/skills/*`, kept `lexai-extension-dev`, updated `.claude/AGENTS.md`. `CLAUDE.md` restructured to the operating-system format (all original LexAI rules preserved).
- **Open risks (ranked):**
1. `<all_urls>` host permission — privacy surface + CWS review blocker (TASKS #1).
2. Key "encryption" is obfuscation (`encKey` co-located) — TASKS #2.
3. Tests don't cover real code paths (TASKS #8) or DOM replace (TASKS #10).
- **Next smallest action:** run the quick wins in order — T-03 (gate debug logs), then T-06/T-09/T-15/T-16 — each is small and independent. Do T-01/T-02 before any Chrome Web Store push.