8.3 KiB
8.3 KiB
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 buildclean. 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 typecheckclean,npm test -- --run46/46 passing (actions, messaging, crypto, providers),npm run buildclean →.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_tokensinstead of the legacymax_tokens(newer OpenAI models reject it) and omitstemperaturefor reasoning models (o*/gpt-5*, which only accept the default). Groq/OpenRouter unchanged (they still expectmax_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
promptaction ("Make Prompt", prompt-engineer): added toACTIONS/labels (context menus follow automatically), prompt-engineer system prompt ingetSystemPromptwith 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
promptaction 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 insrc/lib/actions.ts,PromptParamsadded toAnalyzePayload(both message shapes still supported), composed into the system prompt bypromptParamModifiersin providers.ts (prompt action only; 'Auto' = no-op). Params persist inchrome.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_MODELSon first tab open, '' = configured default; selection sent as new optionalmodeloverride onAnalyzePayload(both message shapes), applied in background'shandleAnalyzeText. 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
promptrequests now inherit the saved Prompt Builder settings: background'shandleAnalyzeTextloadspromptStyle/promptPersona/customPersona/promptFormat/promptModelfrom storage when the payload has nopromptParams(popup still sends explicit ones); persona resolution shared viaresolvePromptPersonain 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_MODELSresolves 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
runActioncloses 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— newmigratePlaintextApiKey(): background auto-encrypts a legacy plaintextapiKeyon 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 inresolveApiKeyretained per invariant.entrypoints/background.ts— calls the migration on startup;sender.id !== chrome.runtime.idguard ononMessage(defense-in-depth; internal senders unaffected).entrypoints/content.ts— fixed unbounded document-listener leak:showToolbaraddedclick/scrolllisteners per selection and never removed them; now unregistered inhideToolbar(also closes an orphaned More-menu). Error toast gaineddata-lexai; mouseup threshold now usesMIN_SELECTION_LENGTH(was hardcoded<= 10, which ate exactly-10-char selections); same sender guard on its listener.src/lib/providers.ts—callProviderguardsres.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-auditorreviewed 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 typesimport.meta.env) is generated bywxt prepare, which CI never ran — locally it existed as a side effect ofwxt build/dev. Reproduced locally by deleting.wxt/. Fixes:postinstall: wxt preparein package.json (root fix — every fresh install regenerates types); explicit "Prepare WXT types" step in both workflows (survives a future--ignore-scripts);deploy-chrome.ymlnow runs typecheck before tests (release previously gated less than CI); fixedhead -1→sed '$d'body extraction in both curl-response checks (body is all-but-last-line, not first line); addedtimeout-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/*, keptlexai-extension-dev, updated.claude/AGENTS.md.CLAUDE.mdrestructured to the operating-system format (all original LexAI rules preserved). - Open risks (ranked):
<all_urls>host permission — privacy surface + CWS review blocker (TASKS #1).- Key "encryption" is obfuscation (
encKeyco-located) — TASKS #2. - 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.