{"owner":"Floorp-Projects","repo":"Floorp","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["CLAUDE.md","AGENTS.md",".cursorrules",".github/copilot-instructions.md"],"skills":{"CLAUDE.md":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\nFloorp is a Firefox-based web browser (\"Noraneko\") built on top of the Gecko engine. This repo contains the custom browser features that overlay Firefox — not the Firefox source itself.\n\n## Commands\n\n```bash\ndeno install                        # Install dependencies\ndeno task feles-build dev           # Dev mode with HMR (ports 5173–5186)\ndeno task feles-build build         # Production build (two-phase: --phase before-mach / --phase after-mach)\ndeno task feles-build stage         # Staging build\ndeno task feles-build test          # Launch browser with Marionette for automated testing\ndeno task feles-build misc patch    # Manage Firefox source patches (apply/create/init)\ndeno task test                      # Run unit tests (browser-integrated, uses colocated test runner)\ndeno task test -- --near <path>     # Run tests near a specific file/directory\ndeno task test -- --layer chrome    # Run only chrome-layer tests (also: esm, pages, all)\ndeno task test:host                 # Run tool tests (Deno native)\ndeno task test:smoke                # Smoke tests\ndeno task dev-tool                  # Development utility CLI\n```\n\n## Architecture (5 Layers)\n\n```notes\nFirefox Base  ← patched Gecko, pref overrides (static/gecko/pref/override.ini)\n     ↓\nESM Modules   ← .sys.mts files with direct Firefox API access, Window Actors\n     ↓\nBridge        ← startup scripts that load features from Vite dev servers (HTTP) or chrome://noraneko/ (prod)\n     ↓\nChrome UI     ← SolidJS → XUL via custom solid-xul renderer, auto-discovered by import.meta.glob\n     ↓\nPages         ← React + Tailwind full-page UIs (settings, new tab, welcome, notes, etc.)\n```\n\nThe bridge (`bridge/startup/src/chrome_root.ts`) is the bootstrap: in dev/test mode it loads from `http://localhost:5181/loader/index.ts` with retry logic; in production it loads `chrome://noraneko/content/core.js`.\n\n## Tech Stack\n\n- **Runtime**: Deno 2.x (primary), Node.js 22 (some pages)\n- **Browser Chrome UI**: SolidJS + `@nora/solid-xul` (custom renderer that uses `document.createXULElement()` via `solid-js/universal`'s `createRenderer`)\n- **Settings/Pages UI**: React + Tailwind CSS\n- **Build**: Vite via custom `feles-build` system (`tools/feles-build.ts`)\n- **Language**: TypeScript (strict)\n\n## Path Aliases (deno.json)\n\n```typescript\n#i18n/              → ./i18n/\n#chrome/            → ./chrome/\n#libs/              → ./libs/\n#features-chrome/   → ./browser-features/chrome/\n#modules/           → ./browser-features/modules/\n#ui/                → ./src/ui/\n#themes/            → ./src/themes/\n```\n\n## Coding Conventions\n\n### File Placement\n\n| What               | Where                                                         | Framework   |\n| ------------------ | ------------------------------------------------------------- | ----------- |\n| Browser UI feature | `browser-features/chrome/common/{name}/`                      | SolidJS     |\n| Firefox API module | `browser-features/modules/modules/{name}.sys.mts`             | Firefox ESM |\n| Settings page      | `browser-features/pages-settings/src/app/{name}/`             | React       |\n| Actor (IPC)        | `browser-features/modules/actors/{Name}Parent\\|Child.sys.mts` | Firefox ESM |\n\n### Feature Auto-Discovery\n\n`browser-features/chrome/common/mod.ts` uses `import.meta.glob(\"./*/index.ts\")` — adding a directory with an `index.ts` under `common/` is sufficient. No manual registration needed.\n\nActor registration is manual: add entries to the `JS_WINDOW_ACTORS` object in `browser-features/modules/modules/BrowserGlue.sys.mts`.\n\n### Type Definitions\n\nSeparate types into dedicated `types.ts` files. Exception: `.sys.mts` files may include inline types.\n\n### No `any`\n\nNever use `any`. Use explicit types or `unknown`.\n\n### SolidJS Pattern (Browser Chrome)\n\n```typescript\nimport { noraComponent, NoraComponentBase } from \"#features-chrome/utils/base\";\nimport { render } from \"@nora/solid-xul\";\nimport { createSignal } from \"solid-js\";\n\n@noraComponent(import.meta.hot)\nexport default class MyFeature extends NoraComponentBase {\n  init(): void {\n    /* ... */\n  }\n}\n```\n\n- Always use `@noraComponent(import.meta.hot)` decorator for HMR support\n- Use `createSignal` / `createMemo` for reactive state — never mutate variables directly\n\n### Firefox ESM Modules (.sys.mts)\n\n```typescript\nconst { SomeService } = ChromeUtils.importESModule(\n  \"resource://floorp/lib/SomeService.sys.mjs\",\n);\n```\n\n### React Pattern (Settings Pages)\n\n```typescript\nexport default function MyPage() {\n  const [value, setValue] = useState(\"\");\n  return <div className=\"p-4\">...</div>;\n}\n```\n\n### i18n\n\nTranslations use i18next-style `{{variable}}` interpolation and `_plural` suffix keys. Add strings to at least `i18n/en-US/` and `i18n/ja-JP/`. Organized by feature namespace in `browser-chrome.json`.\n\n### Error Handling\n\nUse try/catch with `console.error(\"[FeatureName]\", ...)` prefix for log messages.\n\n## Testing\n\nTests run **inside the actual Firefox browser**, not in Deno/Node. They are plain TypeScript functions with a custom harness (`test_harness.ts` providing `assert`, `assertEquals`, `TestCase`), not `Deno.test()`.\n\n```typescript\n// @colocated-env browser\nimport { type TestCase, assert } from \"../../../test/utils/test_harness.ts\";\n\nfunction testSomething(): void {\n  assert(condition, \"message\");\n}\n\nexport function runAllTests(): void {\n  const tests: TestCase[] = [{ name: \"something works\", fn: testSomething }];\n  // ...run and collect failures\n}\n```\n\nColocated in `test/` directories next to source. The runner discovers them automatically.\n\n## Dev Server Ports\n\n- 5173: Main features\n- 5174–5177: Other pages\n- 5178: Settings pages\n- 5181: Feature loader (bridge)\n- 5186: New tab page\n\n## dev-tool — Browser Inspection CLI\n\n`deno task dev-tool` communicates with a running Floorp instance via the **Marionette protocol** (Firefox's TCP-based WebDriver). All browser commands require the browser to be running (started via `dev-tool start` or `feles-build dev`).\n\n### Process Management\n\n```bash\ndeno task dev-tool start      # Start dev server + browser in background (waits for Marionette ready)\ndeno task dev-tool stop       # Kill all dev processes (deno, vite, floorp) cleanly\ndeno task dev-tool restart    # Stop then start\ndeno task dev-tool rebuild    # Rebuild startup + modules + inject XHTML without restarting browser (HMR handles loader-features)\n```\n\n### Browser Commands\n\n```bash\ndeno task dev-tool status                                      # Check connection: shows page title, URL, tab count, active tab\ndeno task dev-tool eval \"JSON.stringify(Services.prefs.getStringPref('floorp.some.pref'))\"  # Execute JS in browser (returns result)\ndeno task dev-tool console                                     # Last 50 console messages (via Services.console)\ndeno task dev-tool console -l 100 -f \"workspace\" -l error      # Filtered: 100 messages, text filter \"workspace\", errors only\ndeno task dev-tool console --level error                       # Level filter: error/warn/info/debug/all\ndeno task dev-tool screenshot                                  # Full-page screenshot → _dist/screenshot.png\ndeno task dev-tool screenshot -s \"#tabbrowser-tabs\" -o out.png # Element screenshot by CSS selector\ndeno task dev-tool navigate about:preferences                  # Navigate browser to URL\ndeno task dev-tool dom \"#sidebar-box\"                          # Inspect DOM: tag, id, class, text, attributes, child count\ndeno task dev-tool title                                       # Get current page title\n```\n\n### Context Flag (`--context` / `-c`)\n\nAll browser commands accept `--context` to choose the JS execution context:\n\n- `chrome` (default) — browser chrome scope. Access `Services`, `gBrowser`, XUL elements, Firefox internals, prefs\n- `content` — web content scope. Interact with loaded page DOM as a normal web page\n\n```bash\ndeno task dev-tool eval \"gBrowser.tabs.length\" -c chrome    # Count open tabs (chrome context)\ndeno task dev-tool eval \"document.title\" -c content         # Get page title from content context\n```\n\n### Typical LLM Workflow\n\n1. `deno task dev-tool start` — launch browser\n2. Edit source files (HMR updates chrome UI automatically)\n3. `deno task dev-tool console --level error` — check for runtime errors\n4. `deno task dev-tool eval \"...\"` — inspect live state (prefs, DOM, services)\n5. `deno task dev-tool screenshot` — visually verify UI changes\n6. `deno task dev-tool rebuild` — if HMR didn't pick up changes (modules/startup only)\n7. `deno task dev-tool stop` — shut down when done\n\n## Debugging\n\n- Browser Console: `Ctrl+Shift+J` / `Cmd+Option+J`\n- DevTools: `Ctrl+Shift+I` / `Cmd+Option+I`\n- Log convention: `console.log(\"[FeatureName]\", ...)`\n\n## Further Reading\n\n- `docs/llm/project-overview.md` — Full project overview\n- `docs/llm/architecture-deep-dive.md` — 5-layer architecture, Window Actor patterns, build system internals\n- `docs/llm/development-notes.md` — Setup requirements, .sys.mts vs .ts decision matrix, dev-tool CLI\n","AGENTS.md":"# AGENTS.md\n\nFloorp is a Firefox-based web browser (\"Noraneko\") built on top of the Gecko engine. This repo contains the custom browser features that overlay Firefox — not the Firefox source itself.\n\n## Commands\n\n```bash\ndeno install                        # Install dependencies\ndeno task feles-build dev           # Dev mode with HMR (ports 5173–5186)\ndeno task feles-build build         # Production build (two-phase: --phase before-mach / --phase after-mach)\ndeno task feles-build stage         # Staging build\ndeno task feles-build test          # Launch browser with Marionette for automated testing\ndeno task feles-build misc patch    # Manage Firefox source patches (apply/create/init)\ndeno task test                      # Run unit tests (browser-integrated, uses colocated test runner)\ndeno task test -- --near <path>     # Run tests near a specific file/directory\ndeno task test -- --layer chrome    # Run only chrome-layer tests (also: esm, pages, all)\ndeno task test:host                 # Run tool tests (Deno native)\ndeno task test:smoke                # Smoke tests\ndeno task dev-tool                  # Development utility CLI\n```\n\n## Architecture (5 Layers)\n\n```text\nFirefox Base  <- patched Gecko, pref overrides (static/gecko/pref/override.ini)\n     |\nESM Modules   <- .sys.mts files with direct Firefox API access, Window Actors\n     |\nBridge        <- startup scripts that load features from Vite dev servers (HTTP) or chrome://noraneko/ (prod)\n     |\nChrome UI     <- SolidJS -> XUL via custom solid-xul renderer, auto-discovered by import.meta.glob\n     |\nPages         <- React + Tailwind full-page UIs (settings, new tab, welcome, notes, etc.)\n```\n\nThe bridge (`bridge/startup/src/chrome_root.ts`) is the bootstrap: in dev/test mode it loads from `http://localhost:5181/loader/index.ts` with retry logic; in production it loads `chrome://noraneko/content/core.js`.\n\n## Tech Stack\n\n- **Runtime**: Deno 2.x (primary), Node.js 22 (some pages)\n- **Browser Chrome UI**: SolidJS + `@nora/solid-xul` (custom renderer that uses `document.createXULElement()` via `solid-js/universal`'s `createRenderer`)\n- **Settings/Pages UI**: React + Tailwind CSS\n- **Build**: Vite via custom `feles-build` system (`tools/feles-build.ts`)\n- **Language**: TypeScript (strict)\n\n## Path Aliases (deno.json)\n\n```typescript\n#i18n/              -> ./i18n/\n#chrome/            -> ./chrome/\n#libs/              -> ./libs/\n#features-chrome/   -> ./browser-features/chrome/\n#modules/           -> ./browser-features/modules/\n#ui/                -> ./src/ui/\n#themes/            -> ./src/themes/\n```\n\n## Coding Conventions\n\n### File Placement\n\n| What               | Where                                                         | Framework   |\n| ------------------ | ------------------------------------------------------------- | ----------- |\n| Browser UI feature | `browser-features/chrome/common/{name}/`                      | SolidJS     |\n| Firefox API module | `browser-features/modules/modules/{name}.sys.mts`             | Firefox ESM |\n| Settings page      | `browser-features/pages-settings/src/app/{name}/`             | React       |\n| Actor (IPC)        | `browser-features/modules/actors/{Name}Parent\\|Child.sys.mts` | Firefox ESM |\n\n### Feature Auto-Discovery\n\n`browser-features/chrome/common/mod.ts` uses `import.meta.glob(\"./*/index.ts\")` -- adding a directory with an `index.ts` under `common/` is sufficient. No manual registration needed.\n\nActor registration is manual: add entries to the `JS_WINDOW_ACTORS` object in `browser-features/modules/modules/BrowserGlue.sys.mts`.\n\n### Type Definitions\n\nSeparate types into dedicated `types.ts` files. Exception: `.sys.mts` files may include inline types.\n\n### No `any`\n\nNever use `any`. Use explicit types or `unknown`.\n\n### SolidJS Pattern (Browser Chrome)\n\n```typescript\nimport { noraComponent, NoraComponentBase } from \"#features-chrome/utils/base\";\nimport { render } from \"@nora/solid-xul\";\nimport { createSignal } from \"solid-js\";\n\n@noraComponent(import.meta.hot)\nexport default class MyFeature extends NoraComponentBase {\n  init(): void {\n    /* ... */\n  }\n}\n```\n\n- Always use `@noraComponent(import.meta.hot)` decorator for HMR support\n- Use `createSignal` / `createMemo` for reactive state -- never mutate variables directly\n\n### Firefox ESM Modules (.sys.mts)\n\n```typescript\nconst { SomeService } = ChromeUtils.importESModule(\n  \"resource://floorp/lib/SomeService.sys.mjs\",\n);\n```\n\n### React Pattern (Settings Pages)\n\n```typescript\nexport default function MyPage() {\n  const [value, setValue] = useState(\"\");\n  return <div className=\"p-4\">...</div>;\n}\n```\n\n### i18n\n\nTranslations use i18next-style `{{variable}}` interpolation and `_plural` suffix keys. Add strings to at least `i18n/en-US/` and `i18n/ja-JP/`. Organized by feature namespace in `browser-chrome.json`.\n\n### Error Handling\n\nUse try/catch with `console.error(\"[FeatureName]\", ...)` prefix for log messages.\n\n## Testing\n\nTests run **inside the actual Firefox browser**, not in Deno/Node. They are plain TypeScript functions with a custom harness (`test_harness.ts` providing `assert`, `assertEquals`, `TestCase`), not `Deno.test()`.\n\n```typescript\n// @colocated-env browser\nimport { type TestCase, assert } from \"../../../test/utils/test_harness.ts\";\n\nfunction testSomething(): void {\n  assert(condition, \"message\");\n}\n\nexport function runAllTests(): void {\n  const tests: TestCase[] = [{ name: \"something works\", fn: testSomething }];\n  // ...run and collect failures\n}\n```\n\nColocated in `test/` directories next to source. The runner discovers them automatically.\n\n## Dev Server Ports\n\n- 5173: Main features\n- 5174-5177: Other pages\n- 5178: Settings pages\n- 5181: Feature loader (bridge)\n- 5186: New tab page\n\n## dev-tool -- Browser Inspection CLI\n\n`deno task dev-tool` communicates with a running Floorp instance via the **Marionette protocol** (Firefox's TCP-based WebDriver). All browser commands require the browser to be running (started via `dev-tool start` or `feles-build dev`).\n\n### Process Management\n\n```bash\ndeno task dev-tool start      # Start dev server + browser in background (waits for Marionette ready)\ndeno task dev-tool stop       # Kill all dev processes (deno, vite, floorp) cleanly\ndeno task dev-tool restart    # Stop then start\ndeno task dev-tool rebuild    # Rebuild startup + modules + inject XHTML without restarting browser (HMR handles loader-features)\n```\n\n### Browser Commands\n\n```bash\ndeno task dev-tool status                                      # Check connection: shows page title, URL, tab count, active tab\ndeno task dev-tool eval \"JSON.stringify(Services.prefs.getStringPref('floorp.some.pref'))\"  # Execute JS in browser (returns result)\ndeno task dev-tool console                                     # Last 50 console messages (via Services.console)\ndeno task dev-tool console -l 100 -f \"workspace\" -l error      # Filtered: 100 messages, text filter \"workspace\", errors only\ndeno task dev-tool console --level error                       # Level filter: error/warn/info/debug/all\ndeno task dev-tool screenshot                                  # Full-page screenshot -> _dist/screenshot.png\ndeno task dev-tool screenshot -s \"#tabbrowser-tabs\" -o out.png # Element screenshot by CSS selector\ndeno task dev-tool navigate about:preferences                  # Navigate browser to URL\ndeno task dev-tool dom \"#sidebar-box\"                          # Inspect DOM: tag, id, class, text, attributes, child count\ndeno task dev-tool title                                       # Get current page title\n```\n\n### Context Flag (`--context` / `-c`)\n\nAll browser commands accept `--context` to choose the JS execution context:\n\n- `chrome` (default) -- browser chrome scope. Access `Services`, `gBrowser`, XUL elements, Firefox internals, prefs\n- `content` -- web content scope. Interact with loaded page DOM as a normal web page\n\n```bash\ndeno task dev-tool eval \"gBrowser.tabs.length\" -c chrome    # Count open tabs (chrome context)\ndeno task dev-tool eval \"document.title\" -c content         # Get page title from content context\n```\n\n### Typical LLM Workflow\n\n1. `deno task dev-tool start` -- launch browser\n2. Edit source files (HMR updates chrome UI automatically)\n3. `deno task dev-tool console --level error` -- check for runtime errors\n4. `deno task dev-tool eval \"...\"` -- inspect live state (prefs, DOM, services)\n5. `deno task dev-tool screenshot` -- visually verify UI changes\n6. `deno task dev-tool rebuild` -- if HMR didn't pick up changes (modules/startup only)\n7. `deno task dev-tool stop` -- shut down when done\n\n## Debugging\n\n- Browser Console: `Ctrl+Shift+J` / `Cmd+Option+J`\n- DevTools: `Ctrl+Shift+I` / `Cmd+Option+I`\n- Log convention: `console.log(\"[FeatureName]\", ...)`\n\n## Further Reading\n\n- `docs/llm/project-overview.md` -- Full project overview\n- `docs/llm/architecture-deep-dive.md` -- 5-layer architecture, Window Actor patterns, build system internals\n- `docs/llm/development-notes.md` -- Setup requirements, .sys.mts vs .ts decision matrix, dev-tool CLI\n",".cursorrules":"# Floorp プロジェクトルール\n\nこのプロジェクトは Mozilla Firefox をベースにした Web ブラウザ \"Floorp\" です。\n\n## 必読ドキュメント\n\nコーディング前に以下のドキュメントを参照してください：\n\n- `docs/llm/README.md` - LLM 向けドキュメントの索引\n- `docs/llm/project-overview.md` - プロジェクト全体の概要\n- `docs/llm/development-notes.md` - 開発ガイドとベストプラクティス\n- `docs/llm/architecture-deep-dive.md` - アーキテクチャ詳細\n- `.claude/context.md` - クイックリファレンス\n\n## 技術スタック\n\n- **ランタイム**: Deno 2.x (メイン), Node.js 22 (一部)\n- **UI**: SolidJS (ブラウザクローム), React (設定ページ)\n- **ビルド**: Vite, feles-build\n- **言語**: TypeScript\n- **CSS**: Tailwind CSS\n\n## コーディング規約\n\n### 型定義\n\n**重要**: 型定義は可能な限り別ファイルに分離してください。\n\n```typescript\n// Good: 型定義を types.ts に分離\n// types.ts\nexport interface Config {\n  enabled: boolean;\n  timeout: number;\n}\n\n// index.ts\nimport type { Config } from \"./types.ts\";\n\n// Bad: 実装と型を混在させる\nexport interface Config { /* ... */ }\nexport class Feature { /* ... */ }\n```\n\n**例外**: `.sys.mts` ファイルでは Firefox API との統合のため、型定義を同じファイルに書いても構いません。\n\n### TypeScript\n\n- `any` 型は避ける\n- 明確な型定義を使用\n- 型推論を活用\n- null/undefined のチェックを忘れずに\n\n```typescript\n// Good\ninterface User {\n  id: number;\n  name: string;\n}\n\nfunction getUser(id: number): User | null {\n  // ...\n}\n\n// Bad\nfunction getUser(id: any): any {\n  // ...\n}\n```\n\n### SolidJS (ブラウザクローム機能)\n\n- リアクティブな状態管理には `createSignal` を使用\n- 直接変数を変更しない\n- HMR サポートのために `@noraComponent(import.meta.hot)` デコレーターを使用\n\n```typescript\n// Good\nimport { createSignal } from \"solid-js\";\nconst [count, setCount] = createSignal(0);\nsetCount(c => c + 1);\n\n// Bad\nlet count = 0;\ncount++; // 動作しない\n```\n\n### React (設定ページ)\n\n- 関数コンポーネントを使用\n- Hooks を適切に使用\n- Tailwind CSS でスタイリング\n\n```typescript\n// Good\nexport default function SettingsPage() {\n  const [value, setValue] = useState(\"\");\n  return <div className=\"p-4\">...</div>;\n}\n```\n\n### ファイル配置\n\n- **ブラウザ UI 機能**: `browser-features/chrome/common/{feature-name}/`\n- **Firefox API モジュール**: `browser-features/modules/modules/{module-name}.sys.mts`\n- **設定ページ**: `browser-features/pages-settings/src/pages/`\n- **型定義**: 各機能の `types.ts` ファイル（`.sys.mts` を除く）\n\n### エラーハンドリング\n\n常に適切なエラーハンドリングを実装してください。\n\n```typescript\n// Good\ntry {\n  const data = await fetchData(url);\n  return data;\n} catch (error) {\n  console.error(\"[FeatureName] Failed to fetch:\", error);\n  return null; // フォールバック\n}\n\n// Bad\nconst data = await fetchData(url); // エラーが伝播\n```\n\n### コメント\n\n- 複雑なロジックには日本語または英語でコメントを追加\n- 関数の目的は JSDoc で説明\n- TODO コメントには担当者を明記\n\n```typescript\n/**\n * ユーザー設定を取得します\n * @param userId ユーザー ID\n * @returns ユーザー設定オブジェクト、存在しない場合は null\n */\nfunction getUserConfig(userId: string): UserConfig | null {\n  // TODO(@username): キャッシュ機構を実装\n  return null;\n}\n```\n\n## 新機能追加のチェックリスト\n\n1. **適切な場所に配置**\n   - ブラウザ UI → `browser-features/chrome/common/`\n   - システムモジュール → `browser-features/modules/modules/`\n   - 設定ページ → `browser-features/pages-settings/`\n\n2. **型定義を別ファイルに**\n   - `types.ts` を作成（`.sys.mts` 以外）\n   - インターフェースと型を定義\n\n3. **HMR サポートを追加**（ブラウザクローム機能のみ）\n   ```typescript\n   @noraComponent(import.meta.hot)\n   export default class MyFeature extends NoraComponentBase {\n     init(): void { /* ... */ }\n   }\n   ```\n\n4. **機能を登録**\n   - `browser-features/chrome/common/mod.ts` に追加\n\n5. **翻訳を追加**\n   - 少なくとも `i18n/en-US/` と `i18n/ja-JP/` に追加\n\n6. **必要に応じて Actor を追加**（マルチプロセス通信が必要な場合）\n   - Parent: `browser-features/modules/actors/{Name}Parent.sys.mts`\n   - Child: `browser-features/modules/actors/{Name}Child.sys.mts`\n   - 登録: `browser-features/modules/modules/BrowserGlue.sys.mts`\n\n## 開発コマンド\n\n```bash\n# 開発モード（HMR 付き）\ndeno task feles-build dev\n\n# 本番ビルド\ndeno task feles-build build\n\n# ステージングビルド\ndeno task feles-build stage\n\n# 依存関係のインストール\ndeno install\n```\n\n## モジュールパスエイリアス\n\n```typescript\nimport { foo } from \"#i18n/utils\";           // i18n/\nimport { bar } from \"#chrome/common/tab\";    // chrome/\nimport { baz } from \"#libs/shared\";          // libs/\nimport { qux } from \"#modules/experiments\";  // browser-features/modules/\n```\n\n## よくある問題\n\n### HMR が動作しない\n- `@noraComponent(import.meta.hot)` デコレーターが付いているか確認\n- `NoraComponentBase` を継承しているか確認\n\n### Firefox API にアクセスできない\n- `.sys.mts` ファイルから ChromeUtils.importESModule() を使用\n\n### 型エラー\n- 型定義を別ファイル（`types.ts`）に分離\n- `any` 型を使用していないか確認\n\n## パフォーマンス\n\n- `init()` メソッドで重い処理を避ける\n- 遅延初期化を活用\n- イベントリスナーを適切にクリーンアップ\n- メモリリークに注意\n\n## テスト\n\n- 新機能には可能な限りテストを追加\n- テストは `browser-features/chrome/test/unit/` に配置\n- Deno のテストフレームワークを使用\n\n## Git コミット\n\n- 意味のあるコミットメッセージ\n- 1 コミット = 1 つの論理的な変更\n- コミット前に `deno fmt` で整形\n\n## 参考リンク\n\n- プロジェクトドキュメント: `docs/llm/`\n- Deno: https://docs.deno.com/\n- SolidJS: https://www.solidjs.com/\n- React: https://react.dev/\n- Firefox Source: https://firefox-source-docs.mozilla.org/\n\n---\n\nこれらのルールに従って、一貫性のある高品質なコードを書いてください。\n",".github/copilot-instructions.md":"# AI Coding Agent Instructions\n\nThis workspace contains multiple interconnected projects: **Floorp** (Firefox-based browser), **Sapphillon** (workflow automation backend), **Floorp-OS-Automator-Frontend**, and **web-store**.\n\n## Project Overview\n\n### Floorp (`floorp/`)\nFirefox-based browser built with Deno 2.x, SolidJS, and React. Custom browser features overlay Firefox's Gecko engine.\n\n### Sapphillon Backend (`Floorp-OS-Automator-Backend/`)\nRust-based workflow automation backend using gRPC (tonic), SeaORM, and Deno runtime for executing JavaScript workflows.\n\n### Frontend Projects\n- **Floorp-OS-Automator-Frontend**: React + TypeScript + Vite UI for workflow management\n- **web-store**: Plugin marketplace with React + Vite\n\n---\n\n## Cross-Project Integration\n\nThis workspace contains interconnected projects. Understanding data flow and integration points is crucial for full-stack development.\n\n### Data Flow Architecture\n\n```\n┌──────────────────────────────────────────────────────────────┐\n│                    Floorp Browser                        │\n│              (Mozilla Firefox + Custom Features)           │\n│  Location: /Users/user/dev-source/floorp-dev/floorp/     │\n│  Dev: deno task dev (ports: 5173-5186)              │\n└───────────────────────────┬────────────────────────────────┘\n                          │\n                          │ Floorp OS API (OpenAPI)\n                          │ openapi.yaml:\n                          │ Floorp-OS-Automator-Backend/plugins/floorp/\n                          │\n                          ▼\n┌──────────────────────────────────────────────────────────────┐\n│              Sapphillon Backend (Rust)                │\n│  Location: ../Floorp-OS-Automator-Backend/          │\n│  Dev: make run (gRPC on localhost:50051)            │\n│  - Plugin system (floorp, fetch, filesystem, etc.)    │\n│  - Workflow engine (Deno Core runtime)                 │\n└───────────────────────────┬────────────────────────────────┘\n                          │\n                          │ gRPC (tonic + prost)\n                          │ protobuf in:\n                          │ Floorp-OS-Automator-Frontend/vender/Sapphillon_API/\n                          │\n                          ▼\n┌──────────────────────────────────────────────────────────────┐\n│         Floorp-OS-Automator-Frontend (React)          │\n│  Location: ../Floorp-OS-Automator-Frontend/          │\n│  Dev: pnpm dev (port 8081)                          │\n│  - gRPC-Web client (@connectrpc/connect-web)           │\n│  - Workflow management UI                                │\n└───────────────────────────┬────────────────────────────────┘\n                          │\n                          │ (optional, disabled)\n                          │ PostMessage to Floorp\n                          │ Progress Window\n                          ▼\n                   ┌────────────────┐\n                   │  Floorp       │\n                   │  Progress     │\n                   │  Window       │\n                   └────────────────┘\n\n                          ▲\n                          │\n                ┌─────────┴──────────┐\n                │                    │\n┌───────────────┐      ┌────────────────┐\n│  Web Store    │      │  External     │\n│  (Plugin      │      │  Plugins     │\n│   Marketplace)│      │              │\n└───────────────┘      └────────────────┘\n```\n\n### Integration Points\n\n**1. Floorp → Sapphillon** (Browser Automation):\n- Floorp exposes browser automation via OpenAPI spec at `Floorp-OS-Automator-Backend/plugins/floorp/api-spec/openapi.yaml`\n- Sapphillon's `floorp` plugin consumes this API to control browser tabs, navigation, etc.\n- Workflows can automate browser interactions (open tabs, navigate, fill forms)\n\n**2. Sapphillon → Frontend** (Workflow Management):\n- gRPC communication using `tonic` (server) and `@connectrpc/connect-web` (client)\n- Protobuf definitions in `Floorp-OS-Automator-Frontend/vender/Sapphillon_API/proto/`\n- Frontend generates TypeScript clients from `.proto` files\n- Services: Workflow, Plugin, Version, Model, Provider\n\n**3. Frontend → Floorp** (Progress Tracking):\n- Disabled by default (see `lib/workflow-progress.ts`)\n- Uses `window.OSAutomotor?.sendWorkflowProgress()` for real-time updates\n- Would show workflow progress in Floorp's native progress window\n\n**4. Web Store → Sapphillon** (Plugin Distribution):\n- Plugin marketplace at `../web-store/`\n- Plugins installed via Sapphillon's plugin installer\n- External plugins run in separate processes with gRPC communication\n\n### Development Setup for Full Stack\n\n**Recommended workflow for full-stack development**:\n```bash\n# Terminal 1: Start Floorp Browser\ncd /Users/user/dev-source/floorp-dev/floorp\ndeno task dev\n\n# Terminal 2: Start Sapphillon Backend\ncd /Users/user/dev-source/sapphillon-dev/Floorp-OS-Automator-Backend\nmake run  # Starts gRPC server on localhost:50051\n\n# Terminal 3: Start Frontend (production mode)\ncd /Users/user/dev-source/sapphillon-dev/Floorp-OS-Automator-Frontend\npnpm dev:prod  # Connects to localhost:50051\n```\n\n**Frontend-only development** (no backend needed):\n```bash\ncd /Users/user/dev-source/sapphillon-dev/Floorp-OS-Automator-Frontend\npnpm dev:mock  # Mock gRPC on port 50099, Vite on 5199\n```\n\n---\n\n## Floorp Development Patterns\n\n### Build System\n- **Primary**: `deno task dev` - Runs custom feles-build system\n- **Build orchestration**: `tools/feles-build.ts` orchestrates patches, symlinks, Vite dev servers\n- **Dev server ports**: 5173 (main), 5178 (settings), 5186 (newtab), 5174-5177 (other pages)\n\n### Code Organization\n\n**Type Definitions**: Always separate types into dedicated files (`types.ts`), not mixed with implementation.\n```typescript\n// Good: types.ts\nexport interface Config { enabled: boolean; }\n\n// index.ts\nimport type { Config } from \"./types.ts\";\n```\n**Exception**: `.sys.mts` files can include types with Firefox API integration.\n\n**File Extensions**:\n- `.ts` - General TypeScript\n- `.sys.mts` - Firefox ESM modules (loaded via `ChromeUtils.importESModule()`)\n- `.jsx` - React components in pages-*/ directories\n\n### UI Framework Usage\n\n**SolidJS** (`browser-features/chrome/`):\n- Use `createSignal` for reactive state (never mutate directly)\n- `@noraComponent(import.meta.hot)` decorator for HMR support\n- Import from `@nora/solid-xul` for rendering:\n```typescript\nimport { render, createSignal } from \"@nora/solid-xul\";\nconst [count, setCount] = createSignal(0);\nsetCount(c => c + 1);\n```\n\n**React** (`browser-features/pages-*/`):\n- Functional components with hooks\n- Tailwind CSS for styling\n- `import { createRootHMR } from \"@nora/solid-xul\"` for i18n integration\n\n### Firefox API Integration\nAccess Firefox APIs via ESM modules in `.sys.mts` files:\n```typescript\nconst { I18nUtils } = ChromeUtils.importESModule(\"resource://floorp/lib/I18nUtils.sys.mjs\");\n```\n\n---\n\n## Sapphillon Backend Patterns\n\n### Architecture\n- **gRPC Service Layer**: `src/services/` - Tonic-based services (workflow, plugin, model, version, provider)\n- **Plugin System**: Modular plugins in `plugins/` (fetch, filesystem, floorp, vscode, git, finder, etc.)\n- **Database**: SeaORM with SQLite, migrations in `migration/`, entities in `entity/`\n- **Workflow Engine**: Deno Core runtime executes JavaScript workflows with plugin permissions\n\n### Common Commands\n```bash\nmake rust_test          # Run all workspace tests\nmake rust_build         # Build entire workspace\nmake migrate            # Run SeaORM migrations\nmake entity_generate    # Generate entities from DB\nmake run                # Run with debug DB at ./debug/sqlite.db\nmake grpcui            # Launch gRPC UI on localhost:50051\n```\n\n### Testing\n- Unit tests: `cargo test --lib`\n- External plugin tests: `cargo test --test external_plugin`\n- Ignored tests: `cargo test --lib external_plugin -- --ignored`\n\n### Plugin Development\nEach plugin crate exposes Deno-compatible functions. See `plugins/floorp/` for OpenAPI-based Floorp browser control.\n\n**Debug Workflows**: Place JS files in `debug_workflow/` directory - auto-registered every 10s in debug builds with full permissions (`[DEBUG]` prefix).\n\n### gRPC & Protocol Buffers\n- Uses `tonic` for server, `prost` for code generation\n- `buf.yaml` and `buf.gen.yaml` configuration\n- Generate with `buf generate`\n\n---\n\n## Frontend Patterns (Both Projects)\n\n### Build Commands\n```bash\nnpm run dev              # Vite dev server\nnpm run build            # TypeScript check + Vite build\nnpm run test             # Vitest\nnpm run lint             # ESLint\n```\n\n### Component Patterns\n- **Chakra UI**: Primary component library\n- **i18next**: Internationalization via `src/i18n/config.ts`\n- **React Router**: Routing in `src/routes/`\n- **Type Definitions**: Export from `src/types/`, not inline\n\n### gRPC Communication\n- `@connectrpc/connect-web` for browser-based gRPC\n- `@connectrpc/connect` for Node-based\n- Generated clients in `src/gen/` from proto definitions\n\n---\n\n## Cross-Project Integration\n\n### Floorp OS API\nFloorp exposes browser automation via OpenAPI spec in `Floorp-OS-Automator-Backend/plugins/floorp/api-spec/openapi.yaml`. The Sapphillon floorp plugin consumes this for workflow automation.\n\n### Data Flow\n```\nFloorp Browser\n    ↓ (Floorp OS API)\nSapphillon Backend (floorp plugin)\n    ↓ (gRPC)\nFloorp-OS-Automator-Frontend\n```\n\n### Plugin System\nWorkflows in Sapphillon can invoke plugins including:\n- **floorp**: Control Floorp browser (tabs, navigation, etc.)\n- **fetch**: HTTP requests\n- **filesystem**: File operations\n- **vscode**: VS Code control\n- **finder**: macOS Finder automation\n- And more in `plugins/`\n\n---\n\n## Key Conventions\n\n### Error Handling\n- **Floorp**: Use `Result<T, E>` from fp-ts for type-safe error handling\n- **Sapphillon**: `anyhow::Result<T>` and `tonic::Status` for gRPC errors\n\n### State Management\n- **SolidJS**: `createSignal` - never mutate directly\n- **React**: `useState`, `useContext` for global state\n\n### Database Operations\n- Use SeaORM `Entity::find().all(db).await?` pattern\n- Migrations: `sea-orm-cli migrate generate <name>`\n- Entities are auto-generated - don't edit manually\n\n### Permissions\nSapphillon uses wildcard `*` plugin_function_id to grant workflows full access. Used for trusted workflows and testing.\n\n---\n\n## Language-Specific Notes\n\n### Rust\n- Edition 2024, workspace resolver \"3\"\n- Async/await with tokio runtime\n- `#[tonic::async_trait]` for gRPC service implementations\n\n### TypeScript/Deno\n- No `any` types - use explicit types or `unknown`\n- Null/undefined checks required\n- Deno permissions: `--allow-all` often needed for build scripts\n\n### React\n- Functional components only\n- Hooks over class components\n- Tailwind CSS classes (e.g., `className=\"p-4\"`)\n\n---\n\n## Critical Files Reference\n\n| Purpose | File |\n|---------|------|\n| Floorp build system | `floorp/tools/feles-build.ts` |\n| Floorp dev config | `floorp/deno.json` |\n| Sapphillon main entry | `Floorp-OS-Automator-Backend/src/main.rs` |\n| Sapphillon workflow service | `Floorp-OS-Automator-Backend/src/services/workflow.rs` |\n| Frontend Vite config | `Floorp-OS-Automator-Frontend/vite.config.ts` |\n| Floorp SolidJS renderer | `floorp/libs/solid-xul/index.ts` |\n| Plugin permissions | `Floorp-OS-Automator-Backend/src/services/workflow.rs:make_plugin_permission()` |\n"},"files":{"CLAUDE.md":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\nFloorp is a Firefox-based web browser (\"Noraneko\") built on top of the Gecko engine. This repo contains the custom browser features that overlay Firefox — not the Firefox source itself.\n\n## Commands\n\n```bash\ndeno install                        # Install dependencies\ndeno task feles-build dev           # Dev mode with HMR (ports 5173–5186)\ndeno task feles-build build         # Production build (two-phase: --phase before-mach / --phase after-mach)\ndeno task feles-build stage         # Staging build\ndeno task feles-build test          # Launch browser with Marionette for automated testing\ndeno task feles-build misc patch    # Manage Firefox source patches (apply/create/init)\ndeno task test                      # Run unit tests (browser-integrated, uses colocated test runner)\ndeno task test -- --near <path>     # Run tests near a specific file/directory\ndeno task test -- --layer chrome    # Run only chrome-layer tests (also: esm, pages, all)\ndeno task test:host                 # Run tool tests (Deno native)\ndeno task test:smoke                # Smoke tests\ndeno task dev-tool                  # Development utility CLI\n```\n\n## Architecture (5 Layers)\n\n```notes\nFirefox Base  ← patched Gecko, pref overrides (static/gecko/pref/override.ini)\n     ↓\nESM Modules   ← .sys.mts files with direct Firefox API access, Window Actors\n     ↓\nBridge        ← startup scripts that load features from Vite dev servers (HTTP) or chrome://noraneko/ (prod)\n     ↓\nChrome UI     ← SolidJS → XUL via custom solid-xul renderer, auto-discovered by import.meta.glob\n     ↓\nPages         ← React + Tailwind full-page UIs (settings, new tab, welcome, notes, etc.)\n```\n\nThe bridge (`bridge/startup/src/chrome_root.ts`) is the bootstrap: in dev/test mode it loads from `http://localhost:5181/loader/index.ts` with retry logic; in production it loads `chrome://noraneko/content/core.js`.\n\n## Tech Stack\n\n- **Runtime**: Deno 2.x (primary), Node.js 22 (some pages)\n- **Browser Chrome UI**: SolidJS + `@nora/solid-xul` (custom renderer that uses `document.createXULElement()` via `solid-js/universal`'s `createRenderer`)\n- **Settings/Pages UI**: React + Tailwind CSS\n- **Build**: Vite via custom `feles-build` system (`tools/feles-build.ts`)\n- **Language**: TypeScript (strict)\n\n## Path Aliases (deno.json)\n\n```typescript\n#i18n/              → ./i18n/\n#chrome/            → ./chrome/\n#libs/              → ./libs/\n#features-chrome/   → ./browser-features/chrome/\n#modules/           → ./browser-features/modules/\n#ui/                → ./src/ui/\n#themes/            → ./src/themes/\n```\n\n## Coding Conventions\n\n### File Placement\n\n| What               | Where                                                         | Framework   |\n| ------------------ | ------------------------------------------------------------- | ----------- |\n| Browser UI feature | `browser-features/chrome/common/{name}/`                      | SolidJS     |\n| Firefox API module | `browser-features/modules/modules/{name}.sys.mts`             | Firefox ESM |\n| Settings page      | `browser-features/pages-settings/src/app/{name}/`             | React       |\n| Actor (IPC)        | `browser-features/modules/actors/{Name}Parent\\|Child.sys.mts` | Firefox ESM |\n\n### Feature Auto-Discovery\n\n`browser-features/chrome/common/mod.ts` uses `import.meta.glob(\"./*/index.ts\")` — adding a directory with an `index.ts` under `common/` is sufficient. No manual registration needed.\n\nActor registration is manual: add entries to the `JS_WINDOW_ACTORS` object in `browser-features/modules/modules/BrowserGlue.sys.mts`.\n\n### Type Definitions\n\nSeparate types into dedicated `types.ts` files. Exception: `.sys.mts` files may include inline types.\n\n### No `any`\n\nNever use `any`. Use explicit types or `unknown`.\n\n### SolidJS Pattern (Browser Chrome)\n\n```typescript\nimport { noraComponent, NoraComponentBase } from \"#features-chrome/utils/base\";\nimport { render } from \"@nora/solid-xul\";\nimport { createSignal } from \"solid-js\";\n\n@noraComponent(import.meta.hot)\nexport default class MyFeature extends NoraComponentBase {\n  init(): void {\n    /* ... */\n  }\n}\n```\n\n- Always use `@noraComponent(import.meta.hot)` decorator for HMR support\n- Use `createSignal` / `createMemo` for reactive state — never mutate variables directly\n\n### Firefox ESM Modules (.sys.mts)\n\n```typescript\nconst { SomeService } = ChromeUtils.importESModule(\n  \"resource://floorp/lib/SomeService.sys.mjs\",\n);\n```\n\n### React Pattern (Settings Pages)\n\n```typescript\nexport default function MyPage() {\n  const [value, setValue] = useState(\"\");\n  return <div className=\"p-4\">...</div>;\n}\n```\n\n### i18n\n\nTranslations use i18next-style `{{variable}}` interpolation and `_plural` suffix keys. Add strings to at least `i18n/en-US/` and `i18n/ja-JP/`. Organized by feature namespace in `browser-chrome.json`.\n\n### Error Handling\n\nUse try/catch with `console.error(\"[FeatureName]\", ...)` prefix for log messages.\n\n## Testing\n\nTests run **inside the actual Firefox browser**, not in Deno/Node. They are plain TypeScript functions with a custom harness (`test_harness.ts` providing `assert`, `assertEquals`, `TestCase`), not `Deno.test()`.\n\n```typescript\n// @colocated-env browser\nimport { type TestCase, assert } from \"../../../test/utils/test_harness.ts\";\n\nfunction testSomething(): void {\n  assert(condition, \"message\");\n}\n\nexport function runAllTests(): void {\n  const tests: TestCase[] = [{ name: \"something works\", fn: testSomething }];\n  // ...run and collect failures\n}\n```\n\nColocated in `test/` directories next to source. The runner discovers them automatically.\n\n## Dev Server Ports\n\n- 5173: Main features\n- 5174–5177: Other pages\n- 5178: Settings pages\n- 5181: Feature loader (bridge)\n- 5186: New tab page\n\n## dev-tool — Browser Inspection CLI\n\n`deno task dev-tool` communicates with a running Floorp instance via the **Marionette protocol** (Firefox's TCP-based WebDriver). All browser commands require the browser to be running (started via `dev-tool start` or `feles-build dev`).\n\n### Process Management\n\n```bash\ndeno task dev-tool start      # Start dev server + browser in background (waits for Marionette ready)\ndeno task dev-tool stop       # Kill all dev processes (deno, vite, floorp) cleanly\ndeno task dev-tool restart    # Stop then start\ndeno task dev-tool rebuild    # Rebuild startup + modules + inject XHTML without restarting browser (HMR handles loader-features)\n```\n\n### Browser Commands\n\n```bash\ndeno task dev-tool status                                      # Check connection: shows page title, URL, tab count, active tab\ndeno task dev-tool eval \"JSON.stringify(Services.prefs.getStringPref('floorp.some.pref'))\"  # Execute JS in browser (returns result)\ndeno task dev-tool console                                     # Last 50 console messages (via Services.console)\ndeno task dev-tool console -l 100 -f \"workspace\" -l error      # Filtered: 100 messages, text filter \"workspace\", errors only\ndeno task dev-tool console --level error                       # Level filter: error/warn/info/debug/all\ndeno task dev-tool screenshot                                  # Full-page screenshot → _dist/screenshot.png\ndeno task dev-tool screenshot -s \"#tabbrowser-tabs\" -o out.png # Element screenshot by CSS selector\ndeno task dev-tool navigate about:preferences                  # Navigate browser to URL\ndeno task dev-tool dom \"#sidebar-box\"                          # Inspect DOM: tag, id, class, text, attributes, child count\ndeno task dev-tool title                                       # Get current page title\n```\n\n### Context Flag (`--context` / `-c`)\n\nAll browser commands accept `--context` to choose the JS execution context:\n\n- `chrome` (default) — browser chrome scope. Access `Services`, `gBrowser`, XUL elements, Firefox internals, prefs\n- `content` — web content scope. Interact with loaded page DOM as a normal web page\n\n```bash\ndeno task dev-tool eval \"gBrowser.tabs.length\" -c chrome    # Count open tabs (chrome context)\ndeno task dev-tool eval \"document.title\" -c content         # Get page title from content context\n```\n\n### Typical LLM Workflow\n\n1. `deno task dev-tool start` — launch browser\n2. Edit source files (HMR updates chrome UI automatically)\n3. `deno task dev-tool console --level error` — check for runtime errors\n4. `deno task dev-tool eval \"...\"` — inspect live state (prefs, DOM, services)\n5. `deno task dev-tool screenshot` — visually verify UI changes\n6. `deno task dev-tool rebuild` — if HMR didn't pick up changes (modules/startup only)\n7. `deno task dev-tool stop` — shut down when done\n\n## Debugging\n\n- Browser Console: `Ctrl+Shift+J` / `Cmd+Option+J`\n- DevTools: `Ctrl+Shift+I` / `Cmd+Option+I`\n- Log convention: `console.log(\"[FeatureName]\", ...)`\n\n## Further Reading\n\n- `docs/llm/project-overview.md` — Full project overview\n- `docs/llm/architecture-deep-dive.md` — 5-layer architecture, Window Actor patterns, build system internals\n- `docs/llm/development-notes.md` — Setup requirements, .sys.mts vs .ts decision matrix, dev-tool CLI\n","AGENTS.md":"# AGENTS.md\n\nFloorp is a Firefox-based web browser (\"Noraneko\") built on top of the Gecko engine. This repo contains the custom browser features that overlay Firefox — not the Firefox source itself.\n\n## Commands\n\n```bash\ndeno install                        # Install dependencies\ndeno task feles-build dev           # Dev mode with HMR (ports 5173–5186)\ndeno task feles-build build         # Production build (two-phase: --phase before-mach / --phase after-mach)\ndeno task feles-build stage         # Staging build\ndeno task feles-build test          # Launch browser with Marionette for automated testing\ndeno task feles-build misc patch    # Manage Firefox source patches (apply/create/init)\ndeno task test                      # Run unit tests (browser-integrated, uses colocated test runner)\ndeno task test -- --near <path>     # Run tests near a specific file/directory\ndeno task test -- --layer chrome    # Run only chrome-layer tests (also: esm, pages, all)\ndeno task test:host                 # Run tool tests (Deno native)\ndeno task test:smoke                # Smoke tests\ndeno task dev-tool                  # Development utility CLI\n```\n\n## Architecture (5 Layers)\n\n```text\nFirefox Base  <- patched Gecko, pref overrides (static/gecko/pref/override.ini)\n     |\nESM Modules   <- .sys.mts files with direct Firefox API access, Window Actors\n     |\nBridge        <- startup scripts that load features from Vite dev servers (HTTP) or chrome://noraneko/ (prod)\n     |\nChrome UI     <- SolidJS -> XUL via custom solid-xul renderer, auto-discovered by import.meta.glob\n     |\nPages         <- React + Tailwind full-page UIs (settings, new tab, welcome, notes, etc.)\n```\n\nThe bridge (`bridge/startup/src/chrome_root.ts`) is the bootstrap: in dev/test mode it loads from `http://localhost:5181/loader/index.ts` with retry logic; in production it loads `chrome://noraneko/content/core.js`.\n\n## Tech Stack\n\n- **Runtime**: Deno 2.x (primary), Node.js 22 (some pages)\n- **Browser Chrome UI**: SolidJS + `@nora/solid-xul` (custom renderer that uses `document.createXULElement()` via `solid-js/universal`'s `createRenderer`)\n- **Settings/Pages UI**: React + Tailwind CSS\n- **Build**: Vite via custom `feles-build` system (`tools/feles-build.ts`)\n- **Language**: TypeScript (strict)\n\n## Path Aliases (deno.json)\n\n```typescript\n#i18n/              -> ./i18n/\n#chrome/            -> ./chrome/\n#libs/              -> ./libs/\n#features-chrome/   -> ./browser-features/chrome/\n#modules/           -> ./browser-features/modules/\n#ui/                -> ./src/ui/\n#themes/            -> ./src/themes/\n```\n\n## Coding Conventions\n\n### File Placement\n\n| What               | Where                                                         | Framework   |\n| ------------------ | ------------------------------------------------------------- | ----------- |\n| Browser UI feature | `browser-features/chrome/common/{name}/`                      | SolidJS     |\n| Firefox API module | `browser-features/modules/modules/{name}.sys.mts`             | Firefox ESM |\n| Settings page      | `browser-features/pages-settings/src/app/{name}/`             | React       |\n| Actor (IPC)        | `browser-features/modules/actors/{Name}Parent\\|Child.sys.mts` | Firefox ESM |\n\n### Feature Auto-Discovery\n\n`browser-features/chrome/common/mod.ts` uses `import.meta.glob(\"./*/index.ts\")` -- adding a directory with an `index.ts` under `common/` is sufficient. No manual registration needed.\n\nActor registration is manual: add entries to the `JS_WINDOW_ACTORS` object in `browser-features/modules/modules/BrowserGlue.sys.mts`.\n\n### Type Definitions\n\nSeparate types into dedicated `types.ts` files. Exception: `.sys.mts` files may include inline types.\n\n### No `any`\n\nNever use `any`. Use explicit types or `unknown`.\n\n### SolidJS Pattern (Browser Chrome)\n\n```typescript\nimport { noraComponent, NoraComponentBase } from \"#features-chrome/utils/base\";\nimport { render } from \"@nora/solid-xul\";\nimport { createSignal } from \"solid-js\";\n\n@noraComponent(import.meta.hot)\nexport default class MyFeature extends NoraComponentBase {\n  init(): void {\n    /* ... */\n  }\n}\n```\n\n- Always use `@noraComponent(import.meta.hot)` decorator for HMR support\n- Use `createSignal` / `createMemo` for reactive state -- never mutate variables directly\n\n### Firefox ESM Modules (.sys.mts)\n\n```typescript\nconst { SomeService } = ChromeUtils.importESModule(\n  \"resource://floorp/lib/SomeService.sys.mjs\",\n);\n```\n\n### React Pattern (Settings Pages)\n\n```typescript\nexport default function MyPage() {\n  const [value, setValue] = useState(\"\");\n  return <div className=\"p-4\">...</div>;\n}\n```\n\n### i18n\n\nTranslations use i18next-style `{{variable}}` interpolation and `_plural` suffix keys. Add strings to at least `i18n/en-US/` and `i18n/ja-JP/`. Organized by feature namespace in `browser-chrome.json`.\n\n### Error Handling\n\nUse try/catch with `console.error(\"[FeatureName]\", ...)` prefix for log messages.\n\n## Testing\n\nTests run **inside the actual Firefox browser**, not in Deno/Node. They are plain TypeScript functions with a custom harness (`test_harness.ts` providing `assert`, `assertEquals`, `TestCase`), not `Deno.test()`.\n\n```typescript\n// @colocated-env browser\nimport { type TestCase, assert } from \"../../../test/utils/test_harness.ts\";\n\nfunction testSomething(): void {\n  assert(condition, \"message\");\n}\n\nexport function runAllTests(): void {\n  const tests: TestCase[] = [{ name: \"something works\", fn: testSomething }];\n  // ...run and collect failures\n}\n```\n\nColocated in `test/` directories next to source. The runner discovers them automatically.\n\n## Dev Server Ports\n\n- 5173: Main features\n- 5174-5177: Other pages\n- 5178: Settings pages\n- 5181: Feature loader (bridge)\n- 5186: New tab page\n\n## dev-tool -- Browser Inspection CLI\n\n`deno task dev-tool` communicates with a running Floorp instance via the **Marionette protocol** (Firefox's TCP-based WebDriver). All browser commands require the browser to be running (started via `dev-tool start` or `feles-build dev`).\n\n### Process Management\n\n```bash\ndeno task dev-tool start      # Start dev server + browser in background (waits for Marionette ready)\ndeno task dev-tool stop       # Kill all dev processes (deno, vite, floorp) cleanly\ndeno task dev-tool restart    # Stop then start\ndeno task dev-tool rebuild    # Rebuild startup + modules + inject XHTML without restarting browser (HMR handles loader-features)\n```\n\n### Browser Commands\n\n```bash\ndeno task dev-tool status                                      # Check connection: shows page title, URL, tab count, active tab\ndeno task dev-tool eval \"JSON.stringify(Services.prefs.getStringPref('floorp.some.pref'))\"  # Execute JS in browser (returns result)\ndeno task dev-tool console                                     # Last 50 console messages (via Services.console)\ndeno task dev-tool console -l 100 -f \"workspace\" -l error      # Filtered: 100 messages, text filter \"workspace\", errors only\ndeno task dev-tool console --level error                       # Level filter: error/warn/info/debug/all\ndeno task dev-tool screenshot                                  # Full-page screenshot -> _dist/screenshot.png\ndeno task dev-tool screenshot -s \"#tabbrowser-tabs\" -o out.png # Element screenshot by CSS selector\ndeno task dev-tool navigate about:preferences                  # Navigate browser to URL\ndeno task dev-tool dom \"#sidebar-box\"                          # Inspect DOM: tag, id, class, text, attributes, child count\ndeno task dev-tool title                                       # Get current page title\n```\n\n### Context Flag (`--context` / `-c`)\n\nAll browser commands accept `--context` to choose the JS execution context:\n\n- `chrome` (default) -- browser chrome scope. Access `Services`, `gBrowser`, XUL elements, Firefox internals, prefs\n- `content` -- web content scope. Interact with loaded page DOM as a normal web page\n\n```bash\ndeno task dev-tool eval \"gBrowser.tabs.length\" -c chrome    # Count open tabs (chrome context)\ndeno task dev-tool eval \"document.title\" -c content         # Get page title from content context\n```\n\n### Typical LLM Workflow\n\n1. `deno task dev-tool start` -- launch browser\n2. Edit source files (HMR updates chrome UI automatically)\n3. `deno task dev-tool console --level error` -- check for runtime errors\n4. `deno task dev-tool eval \"...\"` -- inspect live state (prefs, DOM, services)\n5. `deno task dev-tool screenshot` -- visually verify UI changes\n6. `deno task dev-tool rebuild` -- if HMR didn't pick up changes (modules/startup only)\n7. `deno task dev-tool stop` -- shut down when done\n\n## Debugging\n\n- Browser Console: `Ctrl+Shift+J` / `Cmd+Option+J`\n- DevTools: `Ctrl+Shift+I` / `Cmd+Option+I`\n- Log convention: `console.log(\"[FeatureName]\", ...)`\n\n## Further Reading\n\n- `docs/llm/project-overview.md` -- Full project overview\n- `docs/llm/architecture-deep-dive.md` -- 5-layer architecture, Window Actor patterns, build system internals\n- `docs/llm/development-notes.md` -- Setup requirements, .sys.mts vs .ts decision matrix, dev-tool CLI\n",".cursorrules":"# Floorp プロジェクトルール\n\nこのプロジェクトは Mozilla Firefox をベースにした Web ブラウザ \"Floorp\" です。\n\n## 必読ドキュメント\n\nコーディング前に以下のドキュメントを参照してください：\n\n- `docs/llm/README.md` - LLM 向けドキュメントの索引\n- `docs/llm/project-overview.md` - プロジェクト全体の概要\n- `docs/llm/development-notes.md` - 開発ガイドとベストプラクティス\n- `docs/llm/architecture-deep-dive.md` - アーキテクチャ詳細\n- `.claude/context.md` - クイックリファレンス\n\n## 技術スタック\n\n- **ランタイム**: Deno 2.x (メイン), Node.js 22 (一部)\n- **UI**: SolidJS (ブラウザクローム), React (設定ページ)\n- **ビルド**: Vite, feles-build\n- **言語**: TypeScript\n- **CSS**: Tailwind CSS\n\n## コーディング規約\n\n### 型定義\n\n**重要**: 型定義は可能な限り別ファイルに分離してください。\n\n```typescript\n// Good: 型定義を types.ts に分離\n// types.ts\nexport interface Config {\n  enabled: boolean;\n  timeout: number;\n}\n\n// index.ts\nimport type { Config } from \"./types.ts\";\n\n// Bad: 実装と型を混在させる\nexport interface Config { /* ... */ }\nexport class Feature { /* ... */ }\n```\n\n**例外**: `.sys.mts` ファイルでは Firefox API との統合のため、型定義を同じファイルに書いても構いません。\n\n### TypeScript\n\n- `any` 型は避ける\n- 明確な型定義を使用\n- 型推論を活用\n- null/undefined のチェックを忘れずに\n\n```typescript\n// Good\ninterface User {\n  id: number;\n  name: string;\n}\n\nfunction getUser(id: number): User | null {\n  // ...\n}\n\n// Bad\nfunction getUser(id: any): any {\n  // ...\n}\n```\n\n### SolidJS (ブラウザクローム機能)\n\n- リアクティブな状態管理には `createSignal` を使用\n- 直接変数を変更しない\n- HMR サポートのために `@noraComponent(import.meta.hot)` デコレーターを使用\n\n```typescript\n// Good\nimport { createSignal } from \"solid-js\";\nconst [count, setCount] = createSignal(0);\nsetCount(c => c + 1);\n\n// Bad\nlet count = 0;\ncount++; // 動作しない\n```\n\n### React (設定ページ)\n\n- 関数コンポーネントを使用\n- Hooks を適切に使用\n- Tailwind CSS でスタイリング\n\n```typescript\n// Good\nexport default function SettingsPage() {\n  const [value, setValue] = useState(\"\");\n  return <div className=\"p-4\">...</div>;\n}\n```\n\n### ファイル配置\n\n- **ブラウザ UI 機能**: `browser-features/chrome/common/{feature-name}/`\n- **Firefox API モジュール**: `browser-features/modules/modules/{module-name}.sys.mts`\n- **設定ページ**: `browser-features/pages-settings/src/pages/`\n- **型定義**: 各機能の `types.ts` ファイル（`.sys.mts` を除く）\n\n### エラーハンドリング\n\n常に適切なエラーハンドリングを実装してください。\n\n```typescript\n// Good\ntry {\n  const data = await fetchData(url);\n  return data;\n} catch (error) {\n  console.error(\"[FeatureName] Failed to fetch:\", error);\n  return null; // フォールバック\n}\n\n// Bad\nconst data = await fetchData(url); // エラーが伝播\n```\n\n### コメント\n\n- 複雑なロジックには日本語または英語でコメントを追加\n- 関数の目的は JSDoc で説明\n- TODO コメントには担当者を明記\n\n```typescript\n/**\n * ユーザー設定を取得します\n * @param userId ユーザー ID\n * @returns ユーザー設定オブジェクト、存在しない場合は null\n */\nfunction getUserConfig(userId: string): UserConfig | null {\n  // TODO(@username): キャッシュ機構を実装\n  return null;\n}\n```\n\n## 新機能追加のチェックリスト\n\n1. **適切な場所に配置**\n   - ブラウザ UI → `browser-features/chrome/common/`\n   - システムモジュール → `browser-features/modules/modules/`\n   - 設定ページ → `browser-features/pages-settings/`\n\n2. **型定義を別ファイルに**\n   - `types.ts` を作成（`.sys.mts` 以外）\n   - インターフェースと型を定義\n\n3. **HMR サポートを追加**（ブラウザクローム機能のみ）\n   ```typescript\n   @noraComponent(import.meta.hot)\n   export default class MyFeature extends NoraComponentBase {\n     init(): void { /* ... */ }\n   }\n   ```\n\n4. **機能を登録**\n   - `browser-features/chrome/common/mod.ts` に追加\n\n5. **翻訳を追加**\n   - 少なくとも `i18n/en-US/` と `i18n/ja-JP/` に追加\n\n6. **必要に応じて Actor を追加**（マルチプロセス通信が必要な場合）\n   - Parent: `browser-features/modules/actors/{Name}Parent.sys.mts`\n   - Child: `browser-features/modules/actors/{Name}Child.sys.mts`\n   - 登録: `browser-features/modules/modules/BrowserGlue.sys.mts`\n\n## 開発コマンド\n\n```bash\n# 開発モード（HMR 付き）\ndeno task feles-build dev\n\n# 本番ビルド\ndeno task feles-build build\n\n# ステージングビルド\ndeno task feles-build stage\n\n# 依存関係のインストール\ndeno install\n```\n\n## モジュールパスエイリアス\n\n```typescript\nimport { foo } from \"#i18n/utils\";           // i18n/\nimport { bar } from \"#chrome/common/tab\";    // chrome/\nimport { baz } from \"#libs/shared\";          // libs/\nimport { qux } from \"#modules/experiments\";  // browser-features/modules/\n```\n\n## よくある問題\n\n### HMR が動作しない\n- `@noraComponent(import.meta.hot)` デコレーターが付いているか確認\n- `NoraComponentBase` を継承しているか確認\n\n### Firefox API にアクセスできない\n- `.sys.mts` ファイルから ChromeUtils.importESModule() を使用\n\n### 型エラー\n- 型定義を別ファイル（`types.ts`）に分離\n- `any` 型を使用していないか確認\n\n## パフォーマンス\n\n- `init()` メソッドで重い処理を避ける\n- 遅延初期化を活用\n- イベントリスナーを適切にクリーンアップ\n- メモリリークに注意\n\n## テスト\n\n- 新機能には可能な限りテストを追加\n- テストは `browser-features/chrome/test/unit/` に配置\n- Deno のテストフレームワークを使用\n\n## Git コミット\n\n- 意味のあるコミットメッセージ\n- 1 コミット = 1 つの論理的な変更\n- コミット前に `deno fmt` で整形\n\n## 参考リンク\n\n- プロジェクトドキュメント: `docs/llm/`\n- Deno: https://docs.deno.com/\n- SolidJS: https://www.solidjs.com/\n- React: https://react.dev/\n- Firefox Source: https://firefox-source-docs.mozilla.org/\n\n---\n\nこれらのルールに従って、一貫性のある高品質なコードを書いてください。\n",".github/copilot-instructions.md":"# AI Coding Agent Instructions\n\nThis workspace contains multiple interconnected projects: **Floorp** (Firefox-based browser), **Sapphillon** (workflow automation backend), **Floorp-OS-Automator-Frontend**, and **web-store**.\n\n## Project Overview\n\n### Floorp (`floorp/`)\nFirefox-based browser built with Deno 2.x, SolidJS, and React. Custom browser features overlay Firefox's Gecko engine.\n\n### Sapphillon Backend (`Floorp-OS-Automator-Backend/`)\nRust-based workflow automation backend using gRPC (tonic), SeaORM, and Deno runtime for executing JavaScript workflows.\n\n### Frontend Projects\n- **Floorp-OS-Automator-Frontend**: React + TypeScript + Vite UI for workflow management\n- **web-store**: Plugin marketplace with React + Vite\n\n---\n\n## Cross-Project Integration\n\nThis workspace contains interconnected projects. Understanding data flow and integration points is crucial for full-stack development.\n\n### Data Flow Architecture\n\n```\n┌──────────────────────────────────────────────────────────────┐\n│                    Floorp Browser                        │\n│              (Mozilla Firefox + Custom Features)           │\n│  Location: /Users/user/dev-source/floorp-dev/floorp/     │\n│  Dev: deno task dev (ports: 5173-5186)              │\n└───────────────────────────┬────────────────────────────────┘\n                          │\n                          │ Floorp OS API (OpenAPI)\n                          │ openapi.yaml:\n                          │ Floorp-OS-Automator-Backend/plugins/floorp/\n                          │\n                          ▼\n┌──────────────────────────────────────────────────────────────┐\n│              Sapphillon Backend (Rust)                │\n│  Location: ../Floorp-OS-Automator-Backend/          │\n│  Dev: make run (gRPC on localhost:50051)            │\n│  - Plugin system (floorp, fetch, filesystem, etc.)    │\n│  - Workflow engine (Deno Core runtime)                 │\n└───────────────────────────┬────────────────────────────────┘\n                          │\n                          │ gRPC (tonic + prost)\n                          │ protobuf in:\n                          │ Floorp-OS-Automator-Frontend/vender/Sapphillon_API/\n                          │\n                          ▼\n┌──────────────────────────────────────────────────────────────┐\n│         Floorp-OS-Automator-Frontend (React)          │\n│  Location: ../Floorp-OS-Automator-Frontend/          │\n│  Dev: pnpm dev (port 8081)                          │\n│  - gRPC-Web client (@connectrpc/connect-web)           │\n│  - Workflow management UI                                │\n└───────────────────────────┬────────────────────────────────┘\n                          │\n                          │ (optional, disabled)\n                          │ PostMessage to Floorp\n                          │ Progress Window\n                          ▼\n                   ┌────────────────┐\n                   │  Floorp       │\n                   │  Progress     │\n                   │  Window       │\n                   └────────────────┘\n\n                          ▲\n                          │\n                ┌─────────┴──────────┐\n                │                    │\n┌───────────────┐      ┌────────────────┐\n│  Web Store    │      │  External     │\n│  (Plugin      │      │  Plugins     │\n│   Marketplace)│      │              │\n└───────────────┘      └────────────────┘\n```\n\n### Integration Points\n\n**1. Floorp → Sapphillon** (Browser Automation):\n- Floorp exposes browser automation via OpenAPI spec at `Floorp-OS-Automator-Backend/plugins/floorp/api-spec/openapi.yaml`\n- Sapphillon's `floorp` plugin consumes this API to control browser tabs, navigation, etc.\n- Workflows can automate browser interactions (open tabs, navigate, fill forms)\n\n**2. Sapphillon → Frontend** (Workflow Management):\n- gRPC communication using `tonic` (server) and `@connectrpc/connect-web` (client)\n- Protobuf definitions in `Floorp-OS-Automator-Frontend/vender/Sapphillon_API/proto/`\n- Frontend generates TypeScript clients from `.proto` files\n- Services: Workflow, Plugin, Version, Model, Provider\n\n**3. Frontend → Floorp** (Progress Tracking):\n- Disabled by default (see `lib/workflow-progress.ts`)\n- Uses `window.OSAutomotor?.sendWorkflowProgress()` for real-time updates\n- Would show workflow progress in Floorp's native progress window\n\n**4. Web Store → Sapphillon** (Plugin Distribution):\n- Plugin marketplace at `../web-store/`\n- Plugins installed via Sapphillon's plugin installer\n- External plugins run in separate processes with gRPC communication\n\n### Development Setup for Full Stack\n\n**Recommended workflow for full-stack development**:\n```bash\n# Terminal 1: Start Floorp Browser\ncd /Users/user/dev-source/floorp-dev/floorp\ndeno task dev\n\n# Terminal 2: Start Sapphillon Backend\ncd /Users/user/dev-source/sapphillon-dev/Floorp-OS-Automator-Backend\nmake run  # Starts gRPC server on localhost:50051\n\n# Terminal 3: Start Frontend (production mode)\ncd /Users/user/dev-source/sapphillon-dev/Floorp-OS-Automator-Frontend\npnpm dev:prod  # Connects to localhost:50051\n```\n\n**Frontend-only development** (no backend needed):\n```bash\ncd /Users/user/dev-source/sapphillon-dev/Floorp-OS-Automator-Frontend\npnpm dev:mock  # Mock gRPC on port 50099, Vite on 5199\n```\n\n---\n\n## Floorp Development Patterns\n\n### Build System\n- **Primary**: `deno task dev` - Runs custom feles-build system\n- **Build orchestration**: `tools/feles-build.ts` orchestrates patches, symlinks, Vite dev servers\n- **Dev server ports**: 5173 (main), 5178 (settings), 5186 (newtab), 5174-5177 (other pages)\n\n### Code Organization\n\n**Type Definitions**: Always separate types into dedicated files (`types.ts`), not mixed with implementation.\n```typescript\n// Good: types.ts\nexport interface Config { enabled: boolean; }\n\n// index.ts\nimport type { Config } from \"./types.ts\";\n```\n**Exception**: `.sys.mts` files can include types with Firefox API integration.\n\n**File Extensions**:\n- `.ts` - General TypeScript\n- `.sys.mts` - Firefox ESM modules (loaded via `ChromeUtils.importESModule()`)\n- `.jsx` - React components in pages-*/ directories\n\n### UI Framework Usage\n\n**SolidJS** (`browser-features/chrome/`):\n- Use `createSignal` for reactive state (never mutate directly)\n- `@noraComponent(import.meta.hot)` decorator for HMR support\n- Import from `@nora/solid-xul` for rendering:\n```typescript\nimport { render, createSignal } from \"@nora/solid-xul\";\nconst [count, setCount] = createSignal(0);\nsetCount(c => c + 1);\n```\n\n**React** (`browser-features/pages-*/`):\n- Functional components with hooks\n- Tailwind CSS for styling\n- `import { createRootHMR } from \"@nora/solid-xul\"` for i18n integration\n\n### Firefox API Integration\nAccess Firefox APIs via ESM modules in `.sys.mts` files:\n```typescript\nconst { I18nUtils } = ChromeUtils.importESModule(\"resource://floorp/lib/I18nUtils.sys.mjs\");\n```\n\n---\n\n## Sapphillon Backend Patterns\n\n### Architecture\n- **gRPC Service Layer**: `src/services/` - Tonic-based services (workflow, plugin, model, version, provider)\n- **Plugin System**: Modular plugins in `plugins/` (fetch, filesystem, floorp, vscode, git, finder, etc.)\n- **Database**: SeaORM with SQLite, migrations in `migration/`, entities in `entity/`\n- **Workflow Engine**: Deno Core runtime executes JavaScript workflows with plugin permissions\n\n### Common Commands\n```bash\nmake rust_test          # Run all workspace tests\nmake rust_build         # Build entire workspace\nmake migrate            # Run SeaORM migrations\nmake entity_generate    # Generate entities from DB\nmake run                # Run with debug DB at ./debug/sqlite.db\nmake grpcui            # Launch gRPC UI on localhost:50051\n```\n\n### Testing\n- Unit tests: `cargo test --lib`\n- External plugin tests: `cargo test --test external_plugin`\n- Ignored tests: `cargo test --lib external_plugin -- --ignored`\n\n### Plugin Development\nEach plugin crate exposes Deno-compatible functions. See `plugins/floorp/` for OpenAPI-based Floorp browser control.\n\n**Debug Workflows**: Place JS files in `debug_workflow/` directory - auto-registered every 10s in debug builds with full permissions (`[DEBUG]` prefix).\n\n### gRPC & Protocol Buffers\n- Uses `tonic` for server, `prost` for code generation\n- `buf.yaml` and `buf.gen.yaml` configuration\n- Generate with `buf generate`\n\n---\n\n## Frontend Patterns (Both Projects)\n\n### Build Commands\n```bash\nnpm run dev              # Vite dev server\nnpm run build            # TypeScript check + Vite build\nnpm run test             # Vitest\nnpm run lint             # ESLint\n```\n\n### Component Patterns\n- **Chakra UI**: Primary component library\n- **i18next**: Internationalization via `src/i18n/config.ts`\n- **React Router**: Routing in `src/routes/`\n- **Type Definitions**: Export from `src/types/`, not inline\n\n### gRPC Communication\n- `@connectrpc/connect-web` for browser-based gRPC\n- `@connectrpc/connect` for Node-based\n- Generated clients in `src/gen/` from proto definitions\n\n---\n\n## Cross-Project Integration\n\n### Floorp OS API\nFloorp exposes browser automation via OpenAPI spec in `Floorp-OS-Automator-Backend/plugins/floorp/api-spec/openapi.yaml`. The Sapphillon floorp plugin consumes this for workflow automation.\n\n### Data Flow\n```\nFloorp Browser\n    ↓ (Floorp OS API)\nSapphillon Backend (floorp plugin)\n    ↓ (gRPC)\nFloorp-OS-Automator-Frontend\n```\n\n### Plugin System\nWorkflows in Sapphillon can invoke plugins including:\n- **floorp**: Control Floorp browser (tabs, navigation, etc.)\n- **fetch**: HTTP requests\n- **filesystem**: File operations\n- **vscode**: VS Code control\n- **finder**: macOS Finder automation\n- And more in `plugins/`\n\n---\n\n## Key Conventions\n\n### Error Handling\n- **Floorp**: Use `Result<T, E>` from fp-ts for type-safe error handling\n- **Sapphillon**: `anyhow::Result<T>` and `tonic::Status` for gRPC errors\n\n### State Management\n- **SolidJS**: `createSignal` - never mutate directly\n- **React**: `useState`, `useContext` for global state\n\n### Database Operations\n- Use SeaORM `Entity::find().all(db).await?` pattern\n- Migrations: `sea-orm-cli migrate generate <name>`\n- Entities are auto-generated - don't edit manually\n\n### Permissions\nSapphillon uses wildcard `*` plugin_function_id to grant workflows full access. Used for trusted workflows and testing.\n\n---\n\n## Language-Specific Notes\n\n### Rust\n- Edition 2024, workspace resolver \"3\"\n- Async/await with tokio runtime\n- `#[tonic::async_trait]` for gRPC service implementations\n\n### TypeScript/Deno\n- No `any` types - use explicit types or `unknown`\n- Null/undefined checks required\n- Deno permissions: `--allow-all` often needed for build scripts\n\n### React\n- Functional components only\n- Hooks over class components\n- Tailwind CSS classes (e.g., `className=\"p-4\"`)\n\n---\n\n## Critical Files Reference\n\n| Purpose | File |\n|---------|------|\n| Floorp build system | `floorp/tools/feles-build.ts` |\n| Floorp dev config | `floorp/deno.json` |\n| Sapphillon main entry | `Floorp-OS-Automator-Backend/src/main.rs` |\n| Sapphillon workflow service | `Floorp-OS-Automator-Backend/src/services/workflow.rs` |\n| Frontend Vite config | `Floorp-OS-Automator-Frontend/vite.config.ts` |\n| Floorp SolidJS renderer | `floorp/libs/solid-xul/index.ts` |\n| Plugin permissions | `Floorp-OS-Automator-Backend/src/services/workflow.rs:make_plugin_permission()` |\n"},"items":[{"name":"CLAUDE.md","path":"CLAUDE.md","title":"CLAUDE.md","content":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\nFloorp is a Firefox-based web browser (\"Noraneko\") built on top of the Gecko engine. This repo contains the custom browser features that overlay Firefox — not the Firefox source itself.\n\n## Commands\n\n```bash\ndeno install                        # Install dependencies\ndeno task feles-build dev           # Dev mode with HMR (ports 5173–5186)\ndeno task feles-build build         # Production build (two-phase: --phase before-mach / --phase after-mach)\ndeno task feles-build stage         # Staging build\ndeno task feles-build test          # Launch browser with Marionette for automated testing\ndeno task feles-build misc patch    # Manage Firefox source patches (apply/create/init)\ndeno task test                      # Run unit tests (browser-integrated, uses colocated test runner)\ndeno task test -- --near <path>     # Run tests near a specific file/directory\ndeno task test -- --layer chrome    # Run only chrome-layer tests (also: esm, pages, all)\ndeno task test:host                 # Run tool tests (Deno native)\ndeno task test:smoke                # Smoke tests\ndeno task dev-tool                  # Development utility CLI\n```\n\n## Architecture (5 Layers)\n\n```notes\nFirefox Base  ← patched Gecko, pref overrides (static/gecko/pref/override.ini)\n     ↓\nESM Modules   ← .sys.mts files with direct Firefox API access, Window Actors\n     ↓\nBridge        ← startup scripts that load features from Vite dev servers (HTTP) or chrome://noraneko/ (prod)\n     ↓\nChrome UI     ← SolidJS → XUL via custom solid-xul renderer, auto-discovered by import.meta.glob\n     ↓\nPages         ← React + Tailwind full-page UIs (settings, new tab, welcome, notes, etc.)\n```\n\nThe bridge (`bridge/startup/src/chrome_root.ts`) is the bootstrap: in dev/test mode it loads from `http://localhost:5181/loader/index.ts` with retry logic; in production it loads `chrome://noraneko/content/core.js`.\n\n## Tech Stack\n\n- **Runtime**: Deno 2.x (primary), Node.js 22 (some pages)\n- **Browser Chrome UI**: SolidJS + `@nora/solid-xul` (custom renderer that uses `document.createXULElement()` via `solid-js/universal`'s `createRenderer`)\n- **Settings/Pages UI**: React + Tailwind CSS\n- **Build**: Vite via custom `feles-build` system (`tools/feles-build.ts`)\n- **Language**: TypeScript (strict)\n\n## Path Aliases (deno.json)\n\n```typescript\n#i18n/              → ./i18n/\n#chrome/            → ./chrome/\n#libs/              → ./libs/\n#features-chrome/   → ./browser-features/chrome/\n#modules/           → ./browser-features/modules/\n#ui/                → ./src/ui/\n#themes/            → ./src/themes/\n```\n\n## Coding Conventions\n\n### File Placement\n\n| What               | Where                                                         | Framework   |\n| ------------------ | ------------------------------------------------------------- | ----------- |\n| Browser UI feature | `browser-features/chrome/common/{name}/`                      | SolidJS     |\n| Firefox API module | `browser-features/modules/modules/{name}.sys.mts`             | Firefox ESM |\n| Settings page      | `browser-features/pages-settings/src/app/{name}/`             | React       |\n| Actor (IPC)        | `browser-features/modules/actors/{Name}Parent\\|Child.sys.mts` | Firefox ESM |\n\n### Feature Auto-Discovery\n\n`browser-features/chrome/common/mod.ts` uses `import.meta.glob(\"./*/index.ts\")` — adding a directory with an `index.ts` under `common/` is sufficient. No manual registration needed.\n\nActor registration is manual: add entries to the `JS_WINDOW_ACTORS` object in `browser-features/modules/modules/BrowserGlue.sys.mts`.\n\n### Type Definitions\n\nSeparate types into dedicated `types.ts` files. Exception: `.sys.mts` files may include inline types.\n\n### No `any`\n\nNever use `any`. Use explicit types or `unknown`.\n\n### SolidJS Pattern (Browser Chrome)\n\n```typescript\nimport { noraComponent, NoraComponentBase } from \"#features-chrome/utils/base\";\nimport { render } from \"@nora/solid-xul\";\nimport { createSignal } from \"solid-js\";\n\n@noraComponent(import.meta.hot)\nexport default class MyFeature extends NoraComponentBase {\n  init(): void {\n    /* ... */\n  }\n}\n```\n\n- Always use `@noraComponent(import.meta.hot)` decorator for HMR support\n- Use `createSignal` / `createMemo` for reactive state — never mutate variables directly\n\n### Firefox ESM Modules (.sys.mts)\n\n```typescript\nconst { SomeService } = ChromeUtils.importESModule(\n  \"resource://floorp/lib/SomeService.sys.mjs\",\n);\n```\n\n### React Pattern (Settings Pages)\n\n```typescript\nexport default function MyPage() {\n  const [value, setValue] = useState(\"\");\n  return <div className=\"p-4\">...</div>;\n}\n```\n\n### i18n\n\nTranslations use i18next-style `{{variable}}` interpolation and `_plural` suffix keys. Add strings to at least `i18n/en-US/` and `i18n/ja-JP/`. Organized by feature namespace in `browser-chrome.json`.\n\n### Error Handling\n\nUse try/catch with `console.error(\"[FeatureName]\", ...)` prefix for log messages.\n\n## Testing\n\nTests run **inside the actual Firefox browser**, not in Deno/Node. They are plain TypeScript functions with a custom harness (`test_harness.ts` providing `assert`, `assertEquals`, `TestCase`), not `Deno.test()`.\n\n```typescript\n// @colocated-env browser\nimport { type TestCase, assert } from \"../../../test/utils/test_harness.ts\";\n\nfunction testSomething(): void {\n  assert(condition, \"message\");\n}\n\nexport function runAllTests(): void {\n  const tests: TestCase[] = [{ name: \"something works\", fn: testSomething }];\n  // ...run and collect failures\n}\n```\n\nColocated in `test/` directories next to source. The runner discovers them automatically.\n\n## Dev Server Ports\n\n- 5173: Main features\n- 5174–5177: Other pages\n- 5178: Settings pages\n- 5181: Feature loader (bridge)\n- 5186: New tab page\n\n## dev-tool — Browser Inspection CLI\n\n`deno task dev-tool` communicates with a running Floorp instance via the **Marionette protocol** (Firefox's TCP-based WebDriver). All browser commands require the browser to be running (started via `dev-tool start` or `feles-build dev`).\n\n### Process Management\n\n```bash\ndeno task dev-tool start      # Start dev server + browser in background (waits for Marionette ready)\ndeno task dev-tool stop       # Kill all dev processes (deno, vite, floorp) cleanly\ndeno task dev-tool restart    # Stop then start\ndeno task dev-tool rebuild    # Rebuild startup + modules + inject XHTML without restarting browser (HMR handles loader-features)\n```\n\n### Browser Commands\n\n```bash\ndeno task dev-tool status                                      # Check connection: shows page title, URL, tab count, active tab\ndeno task dev-tool eval \"JSON.stringify(Services.prefs.getStringPref('floorp.some.pref'))\"  # Execute JS in browser (returns result)\ndeno task dev-tool console                                     # Last 50 console messages (via Services.console)\ndeno task dev-tool console -l 100 -f \"workspace\" -l error      # Filtered: 100 messages, text filter \"workspace\", errors only\ndeno task dev-tool console --level error                       # Level filter: error/warn/info/debug/all\ndeno task dev-tool screenshot                                  # Full-page screenshot → _dist/screenshot.png\ndeno task dev-tool screenshot -s \"#tabbrowser-tabs\" -o out.png # Element screenshot by CSS selector\ndeno task dev-tool navigate about:preferences                  # Navigate browser to URL\ndeno task dev-tool dom \"#sidebar-box\"                          # Inspect DOM: tag, id, class, text, attributes, child count\ndeno task dev-tool title                                       # Get current page title\n```\n\n### Context Flag (`--context` / `-c`)\n\nAll browser commands accept `--context` to choose the JS execution context:\n\n- `chrome` (default) — browser chrome scope. Access `Services`, `gBrowser`, XUL elements, Firefox internals, prefs\n- `content` — web content scope. Interact with loaded page DOM as a normal web page\n\n```bash\ndeno task dev-tool eval \"gBrowser.tabs.length\" -c chrome    # Count open tabs (chrome context)\ndeno task dev-tool eval \"document.title\" -c content         # Get page title from content context\n```\n\n### Typical LLM Workflow\n\n1. `deno task dev-tool start` — launch browser\n2. Edit source files (HMR updates chrome UI automatically)\n3. `deno task dev-tool console --level error` — check for runtime errors\n4. `deno task dev-tool eval \"...\"` — inspect live state (prefs, DOM, services)\n5. `deno task dev-tool screenshot` — visually verify UI changes\n6. `deno task dev-tool rebuild` — if HMR didn't pick up changes (modules/startup only)\n7. `deno task dev-tool stop` — shut down when done\n\n## Debugging\n\n- Browser Console: `Ctrl+Shift+J` / `Cmd+Option+J`\n- DevTools: `Ctrl+Shift+I` / `Cmd+Option+I`\n- Log convention: `console.log(\"[FeatureName]\", ...)`\n\n## Further Reading\n\n- `docs/llm/project-overview.md` — Full project overview\n- `docs/llm/architecture-deep-dive.md` — 5-layer architecture, Window Actor patterns, build system internals\n- `docs/llm/development-notes.md` — Setup requirements, .sys.mts vs .ts decision matrix, dev-tool CLI\n","category":"root","tokens":2281},{"name":"AGENTS.md","path":"AGENTS.md","title":"AGENTS.md","content":"# AGENTS.md\n\nFloorp is a Firefox-based web browser (\"Noraneko\") built on top of the Gecko engine. This repo contains the custom browser features that overlay Firefox — not the Firefox source itself.\n\n## Commands\n\n```bash\ndeno install                        # Install dependencies\ndeno task feles-build dev           # Dev mode with HMR (ports 5173–5186)\ndeno task feles-build build         # Production build (two-phase: --phase before-mach / --phase after-mach)\ndeno task feles-build stage         # Staging build\ndeno task feles-build test          # Launch browser with Marionette for automated testing\ndeno task feles-build misc patch    # Manage Firefox source patches (apply/create/init)\ndeno task test                      # Run unit tests (browser-integrated, uses colocated test runner)\ndeno task test -- --near <path>     # Run tests near a specific file/directory\ndeno task test -- --layer chrome    # Run only chrome-layer tests (also: esm, pages, all)\ndeno task test:host                 # Run tool tests (Deno native)\ndeno task test:smoke                # Smoke tests\ndeno task dev-tool                  # Development utility CLI\n```\n\n## Architecture (5 Layers)\n\n```text\nFirefox Base  <- patched Gecko, pref overrides (static/gecko/pref/override.ini)\n     |\nESM Modules   <- .sys.mts files with direct Firefox API access, Window Actors\n     |\nBridge        <- startup scripts that load features from Vite dev servers (HTTP) or chrome://noraneko/ (prod)\n     |\nChrome UI     <- SolidJS -> XUL via custom solid-xul renderer, auto-discovered by import.meta.glob\n     |\nPages         <- React + Tailwind full-page UIs (settings, new tab, welcome, notes, etc.)\n```\n\nThe bridge (`bridge/startup/src/chrome_root.ts`) is the bootstrap: in dev/test mode it loads from `http://localhost:5181/loader/index.ts` with retry logic; in production it loads `chrome://noraneko/content/core.js`.\n\n## Tech Stack\n\n- **Runtime**: Deno 2.x (primary), Node.js 22 (some pages)\n- **Browser Chrome UI**: SolidJS + `@nora/solid-xul` (custom renderer that uses `document.createXULElement()` via `solid-js/universal`'s `createRenderer`)\n- **Settings/Pages UI**: React + Tailwind CSS\n- **Build**: Vite via custom `feles-build` system (`tools/feles-build.ts`)\n- **Language**: TypeScript (strict)\n\n## Path Aliases (deno.json)\n\n```typescript\n#i18n/              -> ./i18n/\n#chrome/            -> ./chrome/\n#libs/              -> ./libs/\n#features-chrome/   -> ./browser-features/chrome/\n#modules/           -> ./browser-features/modules/\n#ui/                -> ./src/ui/\n#themes/            -> ./src/themes/\n```\n\n## Coding Conventions\n\n### File Placement\n\n| What               | Where                                                         | Framework   |\n| ------------------ | ------------------------------------------------------------- | ----------- |\n| Browser UI feature | `browser-features/chrome/common/{name}/`                      | SolidJS     |\n| Firefox API module | `browser-features/modules/modules/{name}.sys.mts`             | Firefox ESM |\n| Settings page      | `browser-features/pages-settings/src/app/{name}/`             | React       |\n| Actor (IPC)        | `browser-features/modules/actors/{Name}Parent\\|Child.sys.mts` | Firefox ESM |\n\n### Feature Auto-Discovery\n\n`browser-features/chrome/common/mod.ts` uses `import.meta.glob(\"./*/index.ts\")` -- adding a directory with an `index.ts` under `common/` is sufficient. No manual registration needed.\n\nActor registration is manual: add entries to the `JS_WINDOW_ACTORS` object in `browser-features/modules/modules/BrowserGlue.sys.mts`.\n\n### Type Definitions\n\nSeparate types into dedicated `types.ts` files. Exception: `.sys.mts` files may include inline types.\n\n### No `any`\n\nNever use `any`. Use explicit types or `unknown`.\n\n### SolidJS Pattern (Browser Chrome)\n\n```typescript\nimport { noraComponent, NoraComponentBase } from \"#features-chrome/utils/base\";\nimport { render } from \"@nora/solid-xul\";\nimport { createSignal } from \"solid-js\";\n\n@noraComponent(import.meta.hot)\nexport default class MyFeature extends NoraComponentBase {\n  init(): void {\n    /* ... */\n  }\n}\n```\n\n- Always use `@noraComponent(import.meta.hot)` decorator for HMR support\n- Use `createSignal` / `createMemo` for reactive state -- never mutate variables directly\n\n### Firefox ESM Modules (.sys.mts)\n\n```typescript\nconst { SomeService } = ChromeUtils.importESModule(\n  \"resource://floorp/lib/SomeService.sys.mjs\",\n);\n```\n\n### React Pattern (Settings Pages)\n\n```typescript\nexport default function MyPage() {\n  const [value, setValue] = useState(\"\");\n  return <div className=\"p-4\">...</div>;\n}\n```\n\n### i18n\n\nTranslations use i18next-style `{{variable}}` interpolation and `_plural` suffix keys. Add strings to at least `i18n/en-US/` and `i18n/ja-JP/`. Organized by feature namespace in `browser-chrome.json`.\n\n### Error Handling\n\nUse try/catch with `console.error(\"[FeatureName]\", ...)` prefix for log messages.\n\n## Testing\n\nTests run **inside the actual Firefox browser**, not in Deno/Node. They are plain TypeScript functions with a custom harness (`test_harness.ts` providing `assert`, `assertEquals`, `TestCase`), not `Deno.test()`.\n\n```typescript\n// @colocated-env browser\nimport { type TestCase, assert } from \"../../../test/utils/test_harness.ts\";\n\nfunction testSomething(): void {\n  assert(condition, \"message\");\n}\n\nexport function runAllTests(): void {\n  const tests: TestCase[] = [{ name: \"something works\", fn: testSomething }];\n  // ...run and collect failures\n}\n```\n\nColocated in `test/` directories next to source. The runner discovers them automatically.\n\n## Dev Server Ports\n\n- 5173: Main features\n- 5174-5177: Other pages\n- 5178: Settings pages\n- 5181: Feature loader (bridge)\n- 5186: New tab page\n\n## dev-tool -- Browser Inspection CLI\n\n`deno task dev-tool` communicates with a running Floorp instance via the **Marionette protocol** (Firefox's TCP-based WebDriver). All browser commands require the browser to be running (started via `dev-tool start` or `feles-build dev`).\n\n### Process Management\n\n```bash\ndeno task dev-tool start      # Start dev server + browser in background (waits for Marionette ready)\ndeno task dev-tool stop       # Kill all dev processes (deno, vite, floorp) cleanly\ndeno task dev-tool restart    # Stop then start\ndeno task dev-tool rebuild    # Rebuild startup + modules + inject XHTML without restarting browser (HMR handles loader-features)\n```\n\n### Browser Commands\n\n```bash\ndeno task dev-tool status                                      # Check connection: shows page title, URL, tab count, active tab\ndeno task dev-tool eval \"JSON.stringify(Services.prefs.getStringPref('floorp.some.pref'))\"  # Execute JS in browser (returns result)\ndeno task dev-tool console                                     # Last 50 console messages (via Services.console)\ndeno task dev-tool console -l 100 -f \"workspace\" -l error      # Filtered: 100 messages, text filter \"workspace\", errors only\ndeno task dev-tool console --level error                       # Level filter: error/warn/info/debug/all\ndeno task dev-tool screenshot                                  # Full-page screenshot -> _dist/screenshot.png\ndeno task dev-tool screenshot -s \"#tabbrowser-tabs\" -o out.png # Element screenshot by CSS selector\ndeno task dev-tool navigate about:preferences                  # Navigate browser to URL\ndeno task dev-tool dom \"#sidebar-box\"                          # Inspect DOM: tag, id, class, text, attributes, child count\ndeno task dev-tool title                                       # Get current page title\n```\n\n### Context Flag (`--context` / `-c`)\n\nAll browser commands accept `--context` to choose the JS execution context:\n\n- `chrome` (default) -- browser chrome scope. Access `Services`, `gBrowser`, XUL elements, Firefox internals, prefs\n- `content` -- web content scope. Interact with loaded page DOM as a normal web page\n\n```bash\ndeno task dev-tool eval \"gBrowser.tabs.length\" -c chrome    # Count open tabs (chrome context)\ndeno task dev-tool eval \"document.title\" -c content         # Get page title from content context\n```\n\n### Typical LLM Workflow\n\n1. `deno task dev-tool start` -- launch browser\n2. Edit source files (HMR updates chrome UI automatically)\n3. `deno task dev-tool console --level error` -- check for runtime errors\n4. `deno task dev-tool eval \"...\"` -- inspect live state (prefs, DOM, services)\n5. `deno task dev-tool screenshot` -- visually verify UI changes\n6. `deno task dev-tool rebuild` -- if HMR didn't pick up changes (modules/startup only)\n7. `deno task dev-tool stop` -- shut down when done\n\n## Debugging\n\n- Browser Console: `Ctrl+Shift+J` / `Cmd+Option+J`\n- DevTools: `Ctrl+Shift+I` / `Cmd+Option+I`\n- Log convention: `console.log(\"[FeatureName]\", ...)`\n\n## Further Reading\n\n- `docs/llm/project-overview.md` -- Full project overview\n- `docs/llm/architecture-deep-dive.md` -- 5-layer architecture, Window Actor patterns, build system internals\n- `docs/llm/development-notes.md` -- Setup requirements, .sys.mts vs .ts decision matrix, dev-tool CLI\n","category":"root","tokens":2262},{"name":".cursorrules","path":".cursorrules","title":".cursorrules","content":"# Floorp プロジェクトルール\n\nこのプロジェクトは Mozilla Firefox をベースにした Web ブラウザ \"Floorp\" です。\n\n## 必読ドキュメント\n\nコーディング前に以下のドキュメントを参照してください：\n\n- `docs/llm/README.md` - LLM 向けドキュメントの索引\n- `docs/llm/project-overview.md` - プロジェクト全体の概要\n- `docs/llm/development-notes.md` - 開発ガイドとベストプラクティス\n- `docs/llm/architecture-deep-dive.md` - アーキテクチャ詳細\n- `.claude/context.md` - クイックリファレンス\n\n## 技術スタック\n\n- **ランタイム**: Deno 2.x (メイン), Node.js 22 (一部)\n- **UI**: SolidJS (ブラウザクローム), React (設定ページ)\n- **ビルド**: Vite, feles-build\n- **言語**: TypeScript\n- **CSS**: Tailwind CSS\n\n## コーディング規約\n\n### 型定義\n\n**重要**: 型定義は可能な限り別ファイルに分離してください。\n\n```typescript\n// Good: 型定義を types.ts に分離\n// types.ts\nexport interface Config {\n  enabled: boolean;\n  timeout: number;\n}\n\n// index.ts\nimport type { Config } from \"./types.ts\";\n\n// Bad: 実装と型を混在させる\nexport interface Config { /* ... */ }\nexport class Feature { /* ... */ }\n```\n\n**例外**: `.sys.mts` ファイルでは Firefox API との統合のため、型定義を同じファイルに書いても構いません。\n\n### TypeScript\n\n- `any` 型は避ける\n- 明確な型定義を使用\n- 型推論を活用\n- null/undefined のチェックを忘れずに\n\n```typescript\n// Good\ninterface User {\n  id: number;\n  name: string;\n}\n\nfunction getUser(id: number): User | null {\n  // ...\n}\n\n// Bad\nfunction getUser(id: any): any {\n  // ...\n}\n```\n\n### SolidJS (ブラウザクローム機能)\n\n- リアクティブな状態管理には `createSignal` を使用\n- 直接変数を変更しない\n- HMR サポートのために `@noraComponent(import.meta.hot)` デコレーターを使用\n\n```typescript\n// Good\nimport { createSignal } from \"solid-js\";\nconst [count, setCount] = createSignal(0);\nsetCount(c => c + 1);\n\n// Bad\nlet count = 0;\ncount++; // 動作しない\n```\n\n### React (設定ページ)\n\n- 関数コンポーネントを使用\n- Hooks を適切に使用\n- Tailwind CSS でスタイリング\n\n```typescript\n// Good\nexport default function SettingsPage() {\n  const [value, setValue] = useState(\"\");\n  return <div className=\"p-4\">...</div>;\n}\n```\n\n### ファイル配置\n\n- **ブラウザ UI 機能**: `browser-features/chrome/common/{feature-name}/`\n- **Firefox API モジュール**: `browser-features/modules/modules/{module-name}.sys.mts`\n- **設定ページ**: `browser-features/pages-settings/src/pages/`\n- **型定義**: 各機能の `types.ts` ファイル（`.sys.mts` を除く）\n\n### エラーハンドリング\n\n常に適切なエラーハンドリングを実装してください。\n\n```typescript\n// Good\ntry {\n  const data = await fetchData(url);\n  return data;\n} catch (error) {\n  console.error(\"[FeatureName] Failed to fetch:\", error);\n  return null; // フォールバック\n}\n\n// Bad\nconst data = await fetchData(url); // エラーが伝播\n```\n\n### コメント\n\n- 複雑なロジックには日本語または英語でコメントを追加\n- 関数の目的は JSDoc で説明\n- TODO コメントには担当者を明記\n\n```typescript\n/**\n * ユーザー設定を取得します\n * @param userId ユーザー ID\n * @returns ユーザー設定オブジェクト、存在しない場合は null\n */\nfunction getUserConfig(userId: string): UserConfig | null {\n  // TODO(@username): キャッシュ機構を実装\n  return null;\n}\n```\n\n## 新機能追加のチェックリスト\n\n1. **適切な場所に配置**\n   - ブラウザ UI → `browser-features/chrome/common/`\n   - システムモジュール → `browser-features/modules/modules/`\n   - 設定ページ → `browser-features/pages-settings/`\n\n2. **型定義を別ファイルに**\n   - `types.ts` を作成（`.sys.mts` 以外）\n   - インターフェースと型を定義\n\n3. **HMR サポートを追加**（ブラウザクローム機能のみ）\n   ```typescript\n   @noraComponent(import.meta.hot)\n   export default class MyFeature extends NoraComponentBase {\n     init(): void { /* ... */ }\n   }\n   ```\n\n4. **機能を登録**\n   - `browser-features/chrome/common/mod.ts` に追加\n\n5. **翻訳を追加**\n   - 少なくとも `i18n/en-US/` と `i18n/ja-JP/` に追加\n\n6. **必要に応じて Actor を追加**（マルチプロセス通信が必要な場合）\n   - Parent: `browser-features/modules/actors/{Name}Parent.sys.mts`\n   - Child: `browser-features/modules/actors/{Name}Child.sys.mts`\n   - 登録: `browser-features/modules/modules/BrowserGlue.sys.mts`\n\n## 開発コマンド\n\n```bash\n# 開発モード（HMR 付き）\ndeno task feles-build dev\n\n# 本番ビルド\ndeno task feles-build build\n\n# ステージングビルド\ndeno task feles-build stage\n\n# 依存関係のインストール\ndeno install\n```\n\n## モジュールパスエイリアス\n\n```typescript\nimport { foo } from \"#i18n/utils\";           // i18n/\nimport { bar } from \"#chrome/common/tab\";    // chrome/\nimport { baz } from \"#libs/shared\";          // libs/\nimport { qux } from \"#modules/experiments\";  // browser-features/modules/\n```\n\n## よくある問題\n\n### HMR が動作しない\n- `@noraComponent(import.meta.hot)` デコレーターが付いているか確認\n- `NoraComponentBase` を継承しているか確認\n\n### Firefox API にアクセスできない\n- `.sys.mts` ファイルから ChromeUtils.importESModule() を使用\n\n### 型エラー\n- 型定義を別ファイル（`types.ts`）に分離\n- `any` 型を使用していないか確認\n\n## パフォーマンス\n\n- `init()` メソッドで重い処理を避ける\n- 遅延初期化を活用\n- イベントリスナーを適切にクリーンアップ\n- メモリリークに注意\n\n## テスト\n\n- 新機能には可能な限りテストを追加\n- テストは `browser-features/chrome/test/unit/` に配置\n- Deno のテストフレームワークを使用\n\n## Git コミット\n\n- 意味のあるコミットメッセージ\n- 1 コミット = 1 つの論理的な変更\n- コミット前に `deno fmt` で整形\n\n## 参考リンク\n\n- プロジェクトドキュメント: `docs/llm/`\n- Deno: https://docs.deno.com/\n- SolidJS: https://www.solidjs.com/\n- React: https://react.dev/\n- Firefox Source: https://firefox-source-docs.mozilla.org/\n\n---\n\nこれらのルールに従って、一貫性のある高品質なコードを書いてください。\n","category":"root","tokens":1141},{"name":"copilot-instructions.md","path":".github/copilot-instructions.md","title":"copilot-instructions.md","content":"# AI Coding Agent Instructions\n\nThis workspace contains multiple interconnected projects: **Floorp** (Firefox-based browser), **Sapphillon** (workflow automation backend), **Floorp-OS-Automator-Frontend**, and **web-store**.\n\n## Project Overview\n\n### Floorp (`floorp/`)\nFirefox-based browser built with Deno 2.x, SolidJS, and React. Custom browser features overlay Firefox's Gecko engine.\n\n### Sapphillon Backend (`Floorp-OS-Automator-Backend/`)\nRust-based workflow automation backend using gRPC (tonic), SeaORM, and Deno runtime for executing JavaScript workflows.\n\n### Frontend Projects\n- **Floorp-OS-Automator-Frontend**: React + TypeScript + Vite UI for workflow management\n- **web-store**: Plugin marketplace with React + Vite\n\n---\n\n## Cross-Project Integration\n\nThis workspace contains interconnected projects. Understanding data flow and integration points is crucial for full-stack development.\n\n### Data Flow Architecture\n\n```\n┌──────────────────────────────────────────────────────────────┐\n│                    Floorp Browser                        │\n│              (Mozilla Firefox + Custom Features)           │\n│  Location: /Users/user/dev-source/floorp-dev/floorp/     │\n│  Dev: deno task dev (ports: 5173-5186)              │\n└───────────────────────────┬────────────────────────────────┘\n                          │\n                          │ Floorp OS API (OpenAPI)\n                          │ openapi.yaml:\n                          │ Floorp-OS-Automator-Backend/plugins/floorp/\n                          │\n                          ▼\n┌──────────────────────────────────────────────────────────────┐\n│              Sapphillon Backend (Rust)                │\n│  Location: ../Floorp-OS-Automator-Backend/          │\n│  Dev: make run (gRPC on localhost:50051)            │\n│  - Plugin system (floorp, fetch, filesystem, etc.)    │\n│  - Workflow engine (Deno Core runtime)                 │\n└───────────────────────────┬────────────────────────────────┘\n                          │\n                          │ gRPC (tonic + prost)\n                          │ protobuf in:\n                          │ Floorp-OS-Automator-Frontend/vender/Sapphillon_API/\n                          │\n                          ▼\n┌──────────────────────────────────────────────────────────────┐\n│         Floorp-OS-Automator-Frontend (React)          │\n│  Location: ../Floorp-OS-Automator-Frontend/          │\n│  Dev: pnpm dev (port 8081)                          │\n│  - gRPC-Web client (@connectrpc/connect-web)           │\n│  - Workflow management UI                                │\n└───────────────────────────┬────────────────────────────────┘\n                          │\n                          │ (optional, disabled)\n                          │ PostMessage to Floorp\n                          │ Progress Window\n                          ▼\n                   ┌────────────────┐\n                   │  Floorp       │\n                   │  Progress     │\n                   │  Window       │\n                   └────────────────┘\n\n                          ▲\n                          │\n                ┌─────────┴──────────┐\n                │                    │\n┌───────────────┐      ┌────────────────┐\n│  Web Store    │      │  External     │\n│  (Plugin      │      │  Plugins     │\n│   Marketplace)│      │              │\n└───────────────┘      └────────────────┘\n```\n\n### Integration Points\n\n**1. Floorp → Sapphillon** (Browser Automation):\n- Floorp exposes browser automation via OpenAPI spec at `Floorp-OS-Automator-Backend/plugins/floorp/api-spec/openapi.yaml`\n- Sapphillon's `floorp` plugin consumes this API to control browser tabs, navigation, etc.\n- Workflows can automate browser interactions (open tabs, navigate, fill forms)\n\n**2. Sapphillon → Frontend** (Workflow Management):\n- gRPC communication using `tonic` (server) and `@connectrpc/connect-web` (client)\n- Protobuf definitions in `Floorp-OS-Automator-Frontend/vender/Sapphillon_API/proto/`\n- Frontend generates TypeScript clients from `.proto` files\n- Services: Workflow, Plugin, Version, Model, Provider\n\n**3. Frontend → Floorp** (Progress Tracking):\n- Disabled by default (see `lib/workflow-progress.ts`)\n- Uses `window.OSAutomotor?.sendWorkflowProgress()` for real-time updates\n- Would show workflow progress in Floorp's native progress window\n\n**4. Web Store → Sapphillon** (Plugin Distribution):\n- Plugin marketplace at `../web-store/`\n- Plugins installed via Sapphillon's plugin installer\n- External plugins run in separate processes with gRPC communication\n\n### Development Setup for Full Stack\n\n**Recommended workflow for full-stack development**:\n```bash\n# Terminal 1: Start Floorp Browser\ncd /Users/user/dev-source/floorp-dev/floorp\ndeno task dev\n\n# Terminal 2: Start Sapphillon Backend\ncd /Users/user/dev-source/sapphillon-dev/Floorp-OS-Automator-Backend\nmake run  # Starts gRPC server on localhost:50051\n\n# Terminal 3: Start Frontend (production mode)\ncd /Users/user/dev-source/sapphillon-dev/Floorp-OS-Automator-Frontend\npnpm dev:prod  # Connects to localhost:50051\n```\n\n**Frontend-only development** (no backend needed):\n```bash\ncd /Users/user/dev-source/sapphillon-dev/Floorp-OS-Automator-Frontend\npnpm dev:mock  # Mock gRPC on port 50099, Vite on 5199\n```\n\n---\n\n## Floorp Development Patterns\n\n### Build System\n- **Primary**: `deno task dev` - Runs custom feles-build system\n- **Build orchestration**: `tools/feles-build.ts` orchestrates patches, symlinks, Vite dev servers\n- **Dev server ports**: 5173 (main), 5178 (settings), 5186 (newtab), 5174-5177 (other pages)\n\n### Code Organization\n\n**Type Definitions**: Always separate types into dedicated files (`types.ts`), not mixed with implementation.\n```typescript\n// Good: types.ts\nexport interface Config { enabled: boolean; }\n\n// index.ts\nimport type { Config } from \"./types.ts\";\n```\n**Exception**: `.sys.mts` files can include types with Firefox API integration.\n\n**File Extensions**:\n- `.ts` - General TypeScript\n- `.sys.mts` - Firefox ESM modules (loaded via `ChromeUtils.importESModule()`)\n- `.jsx` - React components in pages-*/ directories\n\n### UI Framework Usage\n\n**SolidJS** (`browser-features/chrome/`):\n- Use `createSignal` for reactive state (never mutate directly)\n- `@noraComponent(import.meta.hot)` decorator for HMR support\n- Import from `@nora/solid-xul` for rendering:\n```typescript\nimport { render, createSignal } from \"@nora/solid-xul\";\nconst [count, setCount] = createSignal(0);\nsetCount(c => c + 1);\n```\n\n**React** (`browser-features/pages-*/`):\n- Functional components with hooks\n- Tailwind CSS for styling\n- `import { createRootHMR } from \"@nora/solid-xul\"` for i18n integration\n\n### Firefox API Integration\nAccess Firefox APIs via ESM modules in `.sys.mts` files:\n```typescript\nconst { I18nUtils } = ChromeUtils.importESModule(\"resource://floorp/lib/I18nUtils.sys.mjs\");\n```\n\n---\n\n## Sapphillon Backend Patterns\n\n### Architecture\n- **gRPC Service Layer**: `src/services/` - Tonic-based services (workflow, plugin, model, version, provider)\n- **Plugin System**: Modular plugins in `plugins/` (fetch, filesystem, floorp, vscode, git, finder, etc.)\n- **Database**: SeaORM with SQLite, migrations in `migration/`, entities in `entity/`\n- **Workflow Engine**: Deno Core runtime executes JavaScript workflows with plugin permissions\n\n### Common Commands\n```bash\nmake rust_test          # Run all workspace tests\nmake rust_build         # Build entire workspace\nmake migrate            # Run SeaORM migrations\nmake entity_generate    # Generate entities from DB\nmake run                # Run with debug DB at ./debug/sqlite.db\nmake grpcui            # Launch gRPC UI on localhost:50051\n```\n\n### Testing\n- Unit tests: `cargo test --lib`\n- External plugin tests: `cargo test --test external_plugin`\n- Ignored tests: `cargo test --lib external_plugin -- --ignored`\n\n### Plugin Development\nEach plugin crate exposes Deno-compatible functions. See `plugins/floorp/` for OpenAPI-based Floorp browser control.\n\n**Debug Workflows**: Place JS files in `debug_workflow/` directory - auto-registered every 10s in debug builds with full permissions (`[DEBUG]` prefix).\n\n### gRPC & Protocol Buffers\n- Uses `tonic` for server, `prost` for code generation\n- `buf.yaml` and `buf.gen.yaml` configuration\n- Generate with `buf generate`\n\n---\n\n## Frontend Patterns (Both Projects)\n\n### Build Commands\n```bash\nnpm run dev              # Vite dev server\nnpm run build            # TypeScript check + Vite build\nnpm run test             # Vitest\nnpm run lint             # ESLint\n```\n\n### Component Patterns\n- **Chakra UI**: Primary component library\n- **i18next**: Internationalization via `src/i18n/config.ts`\n- **React Router**: Routing in `src/routes/`\n- **Type Definitions**: Export from `src/types/`, not inline\n\n### gRPC Communication\n- `@connectrpc/connect-web` for browser-based gRPC\n- `@connectrpc/connect` for Node-based\n- Generated clients in `src/gen/` from proto definitions\n\n---\n\n## Cross-Project Integration\n\n### Floorp OS API\nFloorp exposes browser automation via OpenAPI spec in `Floorp-OS-Automator-Backend/plugins/floorp/api-spec/openapi.yaml`. The Sapphillon floorp plugin consumes this for workflow automation.\n\n### Data Flow\n```\nFloorp Browser\n    ↓ (Floorp OS API)\nSapphillon Backend (floorp plugin)\n    ↓ (gRPC)\nFloorp-OS-Automator-Frontend\n```\n\n### Plugin System\nWorkflows in Sapphillon can invoke plugins including:\n- **floorp**: Control Floorp browser (tabs, navigation, etc.)\n- **fetch**: HTTP requests\n- **filesystem**: File operations\n- **vscode**: VS Code control\n- **finder**: macOS Finder automation\n- And more in `plugins/`\n\n---\n\n## Key Conventions\n\n### Error Handling\n- **Floorp**: Use `Result<T, E>` from fp-ts for type-safe error handling\n- **Sapphillon**: `anyhow::Result<T>` and `tonic::Status` for gRPC errors\n\n### State Management\n- **SolidJS**: `createSignal` - never mutate directly\n- **React**: `useState`, `useContext` for global state\n\n### Database Operations\n- Use SeaORM `Entity::find().all(db).await?` pattern\n- Migrations: `sea-orm-cli migrate generate <name>`\n- Entities are auto-generated - don't edit manually\n\n### Permissions\nSapphillon uses wildcard `*` plugin_function_id to grant workflows full access. Used for trusted workflows and testing.\n\n---\n\n## Language-Specific Notes\n\n### Rust\n- Edition 2024, workspace resolver \"3\"\n- Async/await with tokio runtime\n- `#[tonic::async_trait]` for gRPC service implementations\n\n### TypeScript/Deno\n- No `any` types - use explicit types or `unknown`\n- Null/undefined checks required\n- Deno permissions: `--allow-all` often needed for build scripts\n\n### React\n- Functional components only\n- Hooks over class components\n- Tailwind CSS classes (e.g., `className=\"p-4\"`)\n\n---\n\n## Critical Files Reference\n\n| Purpose | File |\n|---------|------|\n| Floorp build system | `floorp/tools/feles-build.ts` |\n| Floorp dev config | `floorp/deno.json` |\n| Sapphillon main entry | `Floorp-OS-Automator-Backend/src/main.rs` |\n| Sapphillon workflow service | `Floorp-OS-Automator-Backend/src/services/workflow.rs` |\n| Frontend Vite config | `Floorp-OS-Automator-Frontend/vite.config.ts` |\n| Floorp SolidJS renderer | `floorp/libs/solid-xul/index.ts` |\n| Plugin permissions | `Floorp-OS-Automator-Backend/src/services/workflow.rs:make_plugin_permission()` |\n","category":".github","tokens":2819}]}