Per operator charter shift 2026-05-20: "we don't care about privacy hardening.
At least here." Archive flow is internal-only (no external transmission),
which reframes the password-masking P0-5 defect from privacy-regulation
gravity to operator-hygiene polish.
Re-phasing applied across 4 planning artifacts:
ROADMAP.md:
- Original Phase 2 ("Stabilize DOM + event-capture privacy") REMOVED entirely
(summary list + Phase Details section + Progress table row).
- DOM + event-log VERIFICATION (REQ-rrweb-dom-buffer + REQ-user-event-log)
ABSORBED by new Phase 3 (SPEC §10 smoke verification).
- Phase numbering: old 3 → new 2 (export), old 4 → new 3 (smoke), old 5 → new 4
(optional harden). Dependency chains updated accordingly.
- Overview blurb + journey narrative + success criteria refreshed.
- Phase 3 (smoke) explicitly NOT-in-scope: P0-5 password masking dropped.
REQUIREMENTS.md traceability:
- REQ-rrweb-dom-buffer: Phase 2 → Phase 3 (verification scope; UAT harness
A24+ extension planned).
- REQ-user-event-log: Phase 2 → Phase 3 (same context).
- REQ-password-confidentiality: Phase 2 → Out of Scope (v1) — DEFERRED per
charter shift.
- REQ-popup-ui, REQ-screenshot-on-export, REQ-archive-layout,
REQ-meta-json-schema, REQ-archive-export-latency: Phase 3 → Phase 2
(renumbered; substantively shipped via Plans 01-08 + 01-09 + 01-12;
residual gaps in Phase 2).
- Coverage: 10 mapped + 1 out-of-scope (was 11 mapped).
PROJECT.md:
- CON-sensitive-data-masking: DEFERRED 2026-05-20 (preserves audit trail
via strikethrough; rationale documented).
- DEC-004 amendment: rrweb 5000-event cap retained; masking deferred. Cites
rrweb 2.0.0-alpha.4 maskInputSelector→maskInputFn API change.
STATE.md:
- frontmatter total_phases: 5 → 4.
- stopped_at narrative captures the re-phasing event.
CLI bug note: this re-phasing was attempted via `gsd-sdk query phase.remove 2`
+ canonical `/gsd-remove-phase 2` Skill invocation, but BOTH paths produced
corrupted output (cascading rename via reverse-iteration loop at
phase.cjs:670-679 collapsed all subsequent phases to "Phase 2", plus a
mysterious "2026"→"2002" date corruption). Recovery applied as manual edits
in this commit. CLI bug logged as upstream GSD-framework concern; not a
Mokosh-side issue.
Plan: next is `/gsd-discuss-phase 2` (new Phase 2 = export pipeline; narrowed
scope per re-phasing — ~2-3 plans expected since Plans 01-08 + 01-09 + 01-10
+ 01-12 already shipped most surface).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
10 KiB
Mokosh
What This Is
Mokosh is a Chrome Manifest V3 browser extension that silently and continuously records an operator's browser session — the last 30 seconds of active-tab video, the last 10 minutes of DOM events (via rrweb), and the last 10 minutes of user and runtime events — and, on a single button press, packages everything plus a screenshot into a self-contained ZIP delivered to the user's "Downloads" folder for handoff to support.
The name is taken from Mokosh (Мокошь), the Slavic goddess of fate and weaving: each operator session is a thread she weaves into the archive.
Core Value
When an operator hits a bug, one click MUST produce a self-contained archive that lets support reproduce what happened — in under five seconds, with no server involved, and with the operator's passwords never appearing in the output.
Requirements
Validated
(None yet — Phase 1 of the SPEC ships from a partially-broken first attempt; nothing is validated until SPEC §10 acceptance passes.)
Active
- Continuous 30 s active-tab video ring buffer (REQ-video-ring-buffer)
- 10 min / 5 000-event rrweb DOM buffer with sensitive masking (REQ-rrweb-dom-buffer)
- 10 min user/runtime event log with password filtering (REQ-user-event-log)
- One-shot screenshot at export time (REQ-screenshot-on-export)
- Russian-language popup with idle → "Сохраняю..." → "Готово! ✓" state machine (REQ-popup-ui)
- ZIP archive layout
session_report_YYYY-MM-DD_HH-MM-SS.zip(REQ-archive-layout) meta.jsonschema (REQ-meta-json-schema)- Exact manifest permission set per SPEC §7 (REQ-manifest-permissions)
- Click-to-download latency < 5 s (REQ-archive-export-latency)
- Passwords never appear in rrweb snapshots or event log (REQ-password-confidentiality)
- Extension installs unpacked into Chrome without errors (REQ-install-clean)
Out of Scope
- Server upload of captured data — SPEC §9; reserved for Phase 2.
- AI-driven diagnostics — SPEC §9; reserved for Phase 2.
- Automatic ticket creation — SPEC §9; reserved for Phase 2.
- Analytics dashboard — SPEC §9; reserved for Phase 2.
- Audio recording — SPEC §9; reserved for Phase 2.
- Persisting rolling buffers to
chrome.storage/ IndexedDB — CON-buffer-storage; buffers are in-memory only in Phase 1.
Context
- Source documents: Russian-authored SPEC (
Тз расширение фаза1.md) and a Russian-authored README. All user-facing UI strings ("Сохранить отчёт об ошибке", "Последние 30 сек видео + 10 мин лога", "Сохраняю...", "Готово! ✓") are part of the contract and MUST be preserved verbatim. Section identifiers and code use Latin script. - Codebase state: A partially-broken first attempt at the SPEC already
exists under
src/(background service worker, content script, popup) andoffscreen/. An external audit identified 7 P0 defects that prevent SPEC §10 acceptance. Phase 1 of this roadmap is remediation against the SPEC, not greenfield. See ROADMAP.md. - Operator context (SPEC §1): Operators work inside a browser and periodically make mistakes that are hard to diagnose after the fact. The extension runs silently in the background; the operator only interacts with it when they need to file a report.
- Build toolchain (DOC-only): Vite + the
crxjsplugin in TypeScript. The SPEC does not prescribe a build tool, so this is auto-overridable by a future ADR/SPEC.
Constraints
- Performance: Click-to-archive-on-disk < 5 s (CON-archive-export-latency, SPEC §10 #6) — drives synchronous Blob assembly and avoidance of base64 data URLs.
- Memory: Background RAM ceiling 50 MB (CON-ram-ceiling, SPEC §10 #9). Expected steady-state is ~3–10 MB; the ceiling is a hard upper bound, not a target.
- Video format:
video/webm; codecs=vp9@ 400 000 bps,MediaRecordertimeslice 2000 ms, single continuous recorder (CON-video-codec). The first chunk (WebM header) MUST be retained indefinitely (CON-webm-header-retention, DEC-009) — without it, the assembled file is not playable. - Buffer windows: Video 30 s rolling, rrweb 10 min / 5 000 events whichever is tighter, user-event log 10 min (CON-video-window, CON-rrweb-window, CON-event-log-window).
- Sensitive data:
DEFERRED 2026-05-20 per charter shift ("we don't care about privacy hardening. At least here."). Archive flow is internal-only (no external transmission); CON-sensitive-data- masking re-classified as Phase 4 optional hardening or v2 work. Operator- facing password masking remains a future polish item but is no longer v1-blocking.input[type=password]and[data-sensitive="true"]MUST be masked in rrweb (via v2maskInputFn) AND the event logger MUST drop password field values (CON-sensitive-data-masking). - Service Worker lifecycle: MV3 SW unloads after ~30 s idle; a long-lived
chrome.runtime.connectport from offscreen to SW emits a PING every 25 s to keep the SW alive (CON-display-capture-binding, AMENDED from CON-service-worker-keepalive). - Tab capture binding: REMOVED (CON-tab-capture-binding RETIRED). The new
getDisplayMediabinding (CON-display-capture-binding) is screen/window- scoped, not tab-scoped, and survives tab switches without re-attach. - Manifest permissions:
tabCapture,activeTab,downloads,scripting,storage;host_permissions: ["<all_urls>"]— exactly this set, no more, no less (CON-manifest-permissions). - Storage strategy: All Phase 1 rolling buffers live in memory only
(CON-buffer-storage).
chrome.storageis permitted but MUST NOT be used to persist rolling buffers. - Network: No server upload in Phase 1 (CON-no-server-upload). All export
is local-only via
chrome.downloads.
Key Decisions
| Decision | Rationale | Outcome | Status |
|---|---|---|---|
| DEC-001: Chrome Extension Manifest V3 | SPEC §2, §7 — required for chrome.tabCapture, chrome.downloads, chrome.alarms. |
— Pending | locked (Phase 1) |
| DEC-002: Service Worker as background coordinator | SPEC §2, §3, §8 — MV3 has no persistent background page; SW coordinates video buffer + archive packaging. | — Pending | locked (Phase 1) |
DEC-003: Active video via getDisplayMedia() (vp9 / 400 kbps / 2000 ms) |
AMENDED by Phase 01: SPEC §2/§4.1/§7 originally specified chrome.tabCapture; Phase 01 swaps to getDisplayMedia invoked in the offscreen document with chrome.offscreen.Reason.DISPLAY_MEDIA. Codec/bitrate/timeslice binding unchanged. See .planning/intel/decisions.md DEC-003 Amendment. |
— Pending | locked (Phase 1, post-Amendment) |
DEC-004: DOM capture via rrweb with 5 000-event cap. maskInputSelector maskingmaskInputSelector was rrweb 1.x; v2.0.0-alpha.4 requires maskInputFn. Per 2026-05-20 charter shift, masking deferred to Phase 4 (optional) or v2; AMENDED to "rrweb 5000-event cap; masking deferred". |
SPEC §2, §4.2 — rrweb is the only mature DOM-recording option; cap is part of the memory contract; masking originally part of privacy contract (deferred). | — Pending | locked (Phase 1, post-Amendment) |
| DEC-005: Archive packaging via JSZip | SPEC §2, §3, §6 — only ZIP library bundled per SPEC. | — Pending | locked (Phase 1) |
DEC-006: File download via chrome.downloads |
SPEC §2, §5, §7 — no server upload in Phase 1 (SPEC §9). | — Pending | locked (Phase 1) |
| DEC-007: In-memory buffers only (no Phase 1 persistence) | SPEC §2, §4.1–§4.3 — rolling buffers in SW (video) and Content Script (rrweb + log). | — Pending | locked (Phase 1) |
DEC-008: Screenshot via chrome.tabs.captureVisibleTab |
SPEC §4.4, §5 — captured at export time, not continuously. | — Pending | locked (Phase 1) |
| DEC-009: WebM header chunk retained indefinitely | SPEC §4.1, §8 — WebM without its header is not playable. | — Pending | locked (Phase 1) |
| DEC-010: Service Worker keepalive via long-lived port | AMENDED by Phase 01: SPEC §8 originally specified chrome.alarms at 20 s; Phase 01 swaps to a chrome.runtime.connect port between offscreen and SW with 25 s ping cadence and 290 s pre-emptive reconnect. See .planning/intel/decisions.md DEC-010 Amendment. |
— Pending | locked (Phase 1, post-Amendment) |
| DEC-011: Manifest permissions set | SPEC §7 — tabCapture, activeTab, downloads, scripting, storage + host_permissions: ["<all_urls>"]. |
— Pending | locked (Phase 1) |
| DEC-012: Vite + crxjs + TypeScript build toolchain | README §"Технический стек" — DOC-level only; SPEC does not prescribe. | — Pending | locked (Phase 1) — auto-overridable by future ADR |
Success Metric (Developer-Facing)
Phase 1 is "done" when all 9 SPEC §10 acceptance criteria pass against an unpacked load of the build into Chrome:
- Extension installs in Chrome without errors.
- Video buffer runs continuously on any tab.
- Buffer never holds more than 30 s of footage.
- rrweb records DOM events without errors on typical pages (forms, tables, modals).
- Event log captures clicks, navigation, and network errors.
- Archive downloads to "Downloads" in < 5 s after button press.
- Archive opens cleanly;
last_30sec.webmplays back in a browser. - Passwords do not appear in the event log or rrweb snapshots.
- Extension RAM consumption does not exceed 50 MB in the background.
The verbatim list lives in REQUIREMENTS.md under "Phase 1 Acceptance Criteria (SPEC §10 verbatim)".
Last updated: 2026-05-15 after initial bootstrap from intel synthesis