🧭 Comment editor rebuild — behavioral spec

One mutable working version · publish makes the version · 3 freely-toggleable comment states · full LIFO undo · version-history browse

Personas & jobs-to-be-done

Each journey is walked by a named protagonist (BMAD pattern): a concrete persona with a job-to-be-done trigger, so the spec reads as behaviour rather than abstract requirements.

2 personas14 scenariosslug comment-editor-rebuild
P1

Réka — az ügyfél (prospect) Hungarian-speaking prospect, opens the design link with no login, reviews on desktop

JTBD: When I get a design link, I want to point at exactly what to change so the studio fixes my site without a meeting.

P2

Ádám — Studio admin / reviewer logged-in studio admin, triages client feedback and edits the page

JTBD: When client feedback arrives, I want to fix everything on one working copy and ship a clean version only when I am ready.

Scenario catalog

Every distinct leaf path, classified happy / edge / failure / recovery. The proposed test-IDs are the bridge that plan-techspec reads from scenario_map.json to seed acceptance checks.

IDScenarioPersonaPathStepsProposed test-IDs
S1Client leaves multi-page feedback and submits onceP1🟢 happy9T-S1-no-login-open, T-S1-pagecount-badge, T-S1-atomic-image-text, T-S1-no-kesz-toggle, T-S1-crosspage-submit, T-S1-submitted-not-done
S2Empty-comment guard and image-only commentP1🟡 edge2T-S2-empty-guard, T-S2-image-only-single-row
S3Drafts survive navigation and tab reopen with no duplicationP1🟣 recovery4T-S3-nav-no-dupe, T-S3-delete-authoritative, T-S3-reopen-restore, T-S3-client-uid-isolation
S4Autosave fails then recovers — nothing lost or duplicatedP1🔴 failure2T-S4-autosave-fail-pill, T-S4-retry-idempotent-submit
S5Client sees results, browses versions, never sees AI internalsP1🟢 happy5T-S5-auto-advance, T-S5-summary-banner, T-S5-state-badges, T-S5-version-browse-readonly, T-S5-no-ai-leak
S6Admin receives and triages with correct project-wide countP2🟢 happy6T-S6-count-22, T-S6-both-pages, T-S6-notify-deduped, T-S6-question-flag-orthogonal, T-S6-view-toggle, T-S6-filter-by-state
S7Admin fixes in place on the working version — NO new version; client locksP2🟢 happy5T-S7-inplace-no-new-version, T-S7-client-lock-on-edit, T-S7-open-editor-no-lock, T-S7-section-ai-scoped, T-S7-regen-only-not-done
S8Per-comment AI run / re-run / revert (in place)P2🟢 happy3T-S8-per-comment-apply, T-S8-revert-keeps-html, T-S8-rerun-on-top
S9Reject with note and free state toggling in all directionsP2🟢 happy3T-S9-reject-note-field, T-S9-elvetve-reversible, T-S9-client-elvetve-text-only
S10AI run in flight — publish/discard blocked, other sections still editableP2🔴 failure3T-S10-publish-blocked-during-ai, T-S10-per-section-concurrency, T-S10-callback-no-clobber
S11Publish — the only checkpoint that mints a versionP2🟢 happy5T-S11-publish-only-mints, T-S11-warning-crosspage-counts, T-S11-carry-not-done, T-S11-origin-badge, T-S11-freeze-done-rejected, T-S11-client-unlock-on-publish
S12Browse a previous version from the version-history dropdown (read-only)P2🟢 happy3T-S12-history-load-html-and-comments, T-S12-history-readonly, T-S12-history-nondestructive
S13Per-edit undo — strict LIFO stackP2🟣 recovery3T-S13-undo-lifo, T-S13-undo-restores-before-state
S14Audit download — exact prompts + raw output (JSON + MD)P2🟢 happy3T-S14-editlog-onscreen, T-S14-download-json-prompts, T-S14-download-md-prompts

Scenarios — click-by-click step tables

Each row is one concrete UI interaction: who acts · the exact element clicked or seen · the copy shown · the system action · the resulting state · where it branches.

S1 — Client leaves multi-page feedback and submits once 🟢 happy P1

Trigger: Réka opens the share link and wants to request changes on two pages.

#ActorUI element (clicked / seen)Copy shownSystem actionResulting stateBranch to
1userOpen the client share link (no login screen)First-time hint tooltipGET /v/{token}viewing_published
2userClick the ✕ on the first-time hint to dismiss it(hint dismissed)viewing_published
3userOpen the page dropdown (top bar) showing all 5 pages with per-page unresolved-count badgesPage list with count badgesuses comment_counts (project-wide)viewing_published
4userClick '💬 Megjegyzés', then click a hero section on page A💬 Megjegyzésoverlay.js captures anchordraft_open
5userPick an intent chip 'Szöveg csere' and type the change in the draft cardSzöveg csere / Kép csere / Törlés / Új elem / Új szekció / EgyébPOST /comments/autosave (idempotent upsert by temp_id)draft_dirty
6userAttach an image to the same draft via the 📎 button (or paste / drag-drop)(image thumbnail)presigned PUT to R2; image attached to same temp_iddraft_dirty
7userSelect text directly on the page → a draft pre-fills as „…" helyett:‚…' helyett:draft_dirty
8userSwitch to page B via the page dropdown and add a '🌐 Oldal-szintű' page-level comment (no pin)🌐 Oldal-szintűdraft_dirty
9userClick the submit button reading 'Beküldés (N · 2 oldal)'Beküldés (N · 2 oldal)POST /comments/submit (both pages)submitted

Proposed acceptance test-IDs: T-S1-no-login-open, T-S1-pagecount-badge, T-S1-atomic-image-text, T-S1-no-kesz-toggle, T-S1-crosspage-submit, T-S1-submitted-not-done

S2 — Empty-comment guard and image-only comment 🟡 edge P1

Trigger: Réka opens a draft but has nothing typed, then leaves only an image.

#ActorUI element (clicked / seen)Copy shownSystem actionResulting stateBranch to
1userOpen a draft card and click submit with no body and no image(submit disabled / guard message)draft_open
2userAttach only an image (no text) to the draft, then submit(kép)POST /comments/submitsubmitted

Proposed acceptance test-IDs: T-S2-empty-guard, T-S2-image-only-single-row

S3 — Drafts survive navigation and tab reopen with no duplication 🟣 recovery P1

Trigger: Réka jumps between pages and reopens the tab while drafting.

#ActorUI element (clicked / seen)Copy shownSystem actionResulting stateBranch to
1userCreate drafts on page A, navigate to page B, then back to page Are-fetch authoritative drafts from serverdraft_dirty
2userDelete one draft with its ✕ button, then navigate away and backauthoritative server-side deletedraft_dirty
3userClose the browser tab and reopen the same link in the same browserrestore by client_uiddraft_dirty
4systemA second browser (a different client) opens the same linkdraft_dirty

Proposed acceptance test-IDs: T-S3-nav-no-dupe, T-S3-delete-authoritative, T-S3-reopen-restore, T-S3-client-uid-isolation

S4 — Autosave fails then recovers — nothing lost or duplicated 🔴 failure P1

Trigger: Réka's autosave requests are blocked (flaky network) while she edits.

#ActorUI element (clicked / seen)Copy shownSystem actionResulting stateBranch to
1systemBlock POST /comments/autosave (DevTools network block)⚠️ Mentés sikertelen…draft_dirty_offline
2userRestore the network and let autosave retry, then click submitidempotent upsert by temp_id → POST /comments/submitsubmitted

Proposed acceptance test-IDs: T-S4-autosave-fail-pill, T-S4-retry-idempotent-submit

S5 — Client sees results, browses versions, never sees AI internals 🟢 happy P1

Trigger: After Ádám publishes, Réka returns to see what was done.

#ActorUI element (clicked / seen)Copy shownSystem actionResulting stateBranch to
1systemClient tab auto-advances (~20s poll) to the newly published version labelled '· legújabb'· legújabbpoll detects new published versionviewing_published_latest
2userRead the summary banner '✓ N/M megjegyzés feldolgozva'✓ N/M megjegyzés feldolgozvaviewing_published_latest
3userOpen 'Korábbi verziók megjegyzései' and read the per-comment state badges✓ Kész · 🤖 (if AI) · Elvetve — <note>viewing_published_latest
4userPick an older version from the version dropdown (read-only browse), then click '↩ Legújabb'↩ Legújabbload frozen version (HTML + frozen comment states)viewing_old_version
5userScan the whole client view for any rep-only control or AI artefactviewing_published_latest

Proposed acceptance test-IDs: T-S5-auto-advance, T-S5-summary-banner, T-S5-state-badges, T-S5-version-browse-readonly, T-S5-no-ai-leak

S6 — Admin receives and triages with correct project-wide count 🟢 happy P2

Trigger: 22 comments arrived across 3 pages; Ádám opens the reviewer.

#ActorUI element (clicked / seen)Copy shownSystem actionResulting stateBranch to
1userOpen the reviewer; read the 'Új ügyfél-visszajelzés!' popup countÚj ügyfél-visszajelzés! (22)comment_counts project-wide (mirror _attention_flags)reviewing
2userSwitch between the two affected pages and confirm comments appear on bothreviewing
3systemConfirm one notification per submit (Slack/email), de-dupedone notification per submit sessionreviewing
4userOpen a question-style comment showing the amber 'Kérdés van' flag and 🤖 answer optionsKérdés vanreviewing
5userToggle '🔧 Szerkesztő ↔ 👤 Ügyfél nézet' and click '🔗 Ügyfél link' to copy🔧 Szerkesztő · 👤 Ügyfél nézet · 🔗 Ügyfél linkreviewing
6userUse the reviewer filter/sort by page and by state (nincs kész / kész / elvetve / locked)nincs kész · kész · elvetve · lockedreviewing

Proposed acceptance test-IDs: T-S6-count-22, T-S6-both-pages, T-S6-notify-deduped, T-S6-question-flag-orthogonal, T-S6-view-toggle, T-S6-filter-by-state

S7 — Admin fixes in place on the working version — NO new version; client locks 🟢 happy P2

Trigger: Ádám edits HTML/CSS, reorders, and regenerates — all before publishing.

#ActorUI element (clicked / seen)Copy shownSystem actionResulting stateBranch to
1userOpen the '</>' HTML editor and edit one section, then savein-place section splice + sha1 manifest recompute (no new Version row)working_edited
2systemAfter this first real edit, the client view shows '🔧 Feldolgozás alatt' and commenting is disabled🔧 Feldolgozás alattclient_locked
3userEdit global CSS, then drag-reorder a section with the ⋮⋮ handle⋮⋮in-place CSS save + reorder (deterministic, bypass LLM)working_edited
4userRun a per-section '🤖' free-prompt AI edit on one section🤖 (per-section, free prompt)spawn apply worker; only that section's outerHTML rewrittenworking_edited
5userClick '♻️ Szekciók újragenerálása' (regenerate-all) and watch the 'fog'♻️ Szekciók újragenerálásaAI on only not_done comments; mutate working in placeworking_edited

Proposed acceptance test-IDs: T-S7-inplace-no-new-version, T-S7-client-lock-on-edit, T-S7-open-editor-no-lock, T-S7-section-ai-scoped, T-S7-regen-only-not-done

S8 — Per-comment AI run / re-run / revert (in place) 🟢 happy P2

Trigger: Ádám resolves one comment with AI and iterates on it.

#ActorUI element (clicked / seen)Copy shownSystem actionResulting stateBranch to
1userOn a single nincs kész comment, click its per-comment AI 'run' buttonspawn apply for that one comment against the working versionworking_edited
2userRevert that AI-kész comment back to 'nincs kész'status flip only (HTML kept)working_edited
3userClick per-comment AI 'run' again (re-run) on the now nincs kész commentspawn apply again on current HTMLworking_edited

Proposed acceptance test-IDs: T-S8-per-comment-apply, T-S8-revert-keeps-html, T-S8-rerun-on-top

S9 — Reject with note and free state toggling in all directions 🟢 happy P2

Trigger: Ádám dismisses one comment, then changes his mind.

#ActorUI element (clicked / seen)Copy shownSystem actionResulting stateBranch to
1userClick 'Visszautasít' on a comment and type an optional Hungarian noteVisszautasít / Elvetésset status=rejected + reject_noteworking_edited
2userToggle the same 'elvetve' comment back to 'nincs kész', then to 'kész'nincs kész ⇄ kész ⇄ elvetvefree transition (working version)working_edited
3systemOpen the client view of the rejected commentElvetve — <note>viewing_published

Proposed acceptance test-IDs: T-S9-reject-note-field, T-S9-elvetve-reversible, T-S9-client-elvetve-text-only

S10 — AI run in flight — publish/discard blocked, other sections still editable 🔴 failure P2

Trigger: Ádám tries to publish while an AI run is still going.

#ActorUI element (clicked / seen)Copy shownSystem actionResulting stateBranch to
1userStart an AI run on section 1, then immediately click 'Új verzió / Ügyfélnek küldés →'AI-futtatás zajlik…per-section guard returns busy for section 1ai_running
2userWhile section 1 runs, edit a DIFFERENT section (section 2)per-section guard (not page-wide lock)working_edited
3systemSection 1's AI run completes via the HMAC callbackPOST /internal/jobs/{id}/completeworking_edited

Proposed acceptance test-IDs: T-S10-publish-blocked-during-ai, T-S10-per-section-concurrency, T-S10-callback-no-clobber

S11 — Publish — the only checkpoint that mints a version 🟢 happy P2

Trigger: Ádám is happy with the working copy and ships it to the client.

#ActorUI element (clicked / seen)Copy shownSystem actionResulting stateBranch to
1userClick 'Új verzió létrehozása / Ügyfélnek küldés →'Új verzió létrehozása / Ügyfélnek küldés →publish_confirm
2userRead the cross-page warning popup: 'X megjegyzés átkerül (nincs kész), Y lezárul (kész/elvetve)'X megjegyzés átkerül (nincs kész) · Y lezárul (kész/elvetve)plan_checkpoint counts across ALL pagespublish_confirm
3userClick confirm in the popupfreeze working → published; fork working n+1; carry_and_reanchor not_donepublished
4userInspect a carried-forward comment on working n+1(faint origin badge, e.g. 'V1')working_edited
5systemThe client tab auto-advances (~20s) to published n and unlocks· legújabbviewing_published_latest

Proposed acceptance test-IDs: T-S11-publish-only-mints, T-S11-warning-crosspage-counts, T-S11-carry-not-done, T-S11-origin-badge, T-S11-freeze-done-rejected, T-S11-client-unlock-on-publish

S12 — Browse a previous version from the version-history dropdown (read-only) 🟢 happy P2

Trigger: Ádám wants to look back at an earlier shipped version (NOT a destructive restore).

#ActorUI element (clicked / seen)Copy shownSystem actionResulting stateBranch to
1userOpen the version-history dropdown and select an earlier published versionload that version's frozen blob (HTML) + its frozen commentsviewing_old_version
2userConfirm the loaded old version is read-only (no editing/commenting)viewing_old_version
3userReturn to the current working/latest version from the dropdownreselect latestworking_edited

Proposed acceptance test-IDs: T-S12-history-load-html-and-comments, T-S12-history-readonly, T-S12-history-nondestructive

S13 — Per-edit undo — strict LIFO stack 🟣 recovery P2

Trigger: Ádám makes three edits then wants the last one gone.

#ActorUI element (clicked / seen)Copy shownSystem actionResulting stateBranch to
1userMake three in-place edits (edit A, edit B, edit C) on the working versionappend EditEvent A, B, Cworking_edited
2userClick undo oncepop EditEvent C; restore its before-stateworking_edited
3userConfirm undo is LIFO (the next undo would remove B, not A)working_edited

Proposed acceptance test-IDs: T-S13-undo-lifo, T-S13-undo-restores-before-state

S14 — Audit download — exact prompts + raw output (JSON + MD) 🟢 happy P2

Trigger: Ádám needs the full AI trail for a version.

#ActorUI element (clicked / seen)Copy shownSystem actionResulting stateBranch to
1userOpen the version diff page and click '📋 Szerkesztési napló'📋 Szerkesztési naplóreviewing
2userClick the audit 'Letöltés' and choose JSONLetöltés (JSON)serialize EditEvents → JSONreviewing
3userClick the audit 'Letöltés' and choose MarkdownLetöltés (MD)serialize EditEvents → Markdownreviewing

Proposed acceptance test-IDs: T-S14-editlog-onscreen, T-S14-download-json-prompts, T-S14-download-md-prompts

Global branching flowchart

Conditions on the arrows; colours follow the path-type legend. Per-scenario sub-flows appear inside each scenario above.

flowchart TD
  CL["Client opens link"] --> DR["draft (autosave, server-authoritative)"]
  DR --> SUB["Beküldés → status=not_done"]
  SUB --> REV["Admin reviewer (count project-wide)"]
  REV --> TGL{"toggle state (working)"}
  TGL -->|nincs kész ⇄ kész ⇄ elvetve| TGL
  REV --> FIX["edit in place: HTML/CSS/reorder/AI"]
  FIX -->|first real edit| LOCK["client locked: 🔧 Feldolgozás alatt"]
  FIX -->|append EditEvent| UNDO["undo: strict LIFO"]
  FIX --> PUB["Új verzió / Ügyfélnek küldés →"]
  PUB --> WARN{"warning popup: X carry · Y close"}
  WARN -->|confirm| FREEZE["freeze → published n"]
  FREEZE --> FORK["fork working n+1: not_done carried (origin badge)"]
  FREEZE --> CLU["client unlocks, auto-advances ~20s"]
  FREEZE -.->|read-only browse| HIST["version-history dropdown: load HTML + frozen comments"]

Copy index — message · copy · source · mode · status

MessageCopy / subjectSourceSend / show modeStatus
Comment entry button💬 Megjegyzésshell.jsin-pagelive
Intent chipsSzöveg csere / Kép csere / Törlés / Új elem / Új szekció / Egyébshell.jsin-pagelive
Text-select prefill‚…' helyett:shell.jsin-pagelive
Image-only label(kép)shell.jsin-pagechanged
Page-level comment🌐 Oldal-szintűshell.jsin-pagelive
Cross-page submitBeküldés (N · 2 oldal)shell.jsin-pagelive
New-feedback popupÚj ügyfél-visszajelzés!viewer.py / shell.jsin-pagechanged
Question flagKérdés vanshell.jsin-pagechanged
View toggle + link🔧 Szerkesztő · 👤 Ügyfél nézet · 🔗 Ügyfél linkshell.jsin-pagelive
Regenerate-all♻️ Szekciók újragenerálásashell.jsin-pagechanged
Reject actionVisszautasít / Elvetésshell.jsin-pagelive
Reject display (client)Elvetve — <note>viewer.py:_resolutionin-pagechanged
Publish / checkpointÚj verzió létrehozása / Ügyfélnek küldés →shell.js / revision_api.pyin-pagechanged
Pre-publish warningX megjegyzés átkerül (nincs kész) · Y lezárul (kész/elvetve)shell.jspopupplanned
AI-running blockAI-futtatás zajlik…revision_api.py 409 → shell.jsin-pagechanged
Client mid-fix lock🔧 Feldolgozás alattshell.jsin-pagechanged
Admin 'client watching'👁 ügyfél nézishell.jsin-pagelive
Autosave failure pill⚠️ Mentés sikertelen…shell.jsin-pagelive
Client summary banner✓ N/M megjegyzés feldolgozvashell.jsin-pagelive
Older comments sectionKorábbi verziók megjegyzéseishell.jsin-pagelive
State badges (client)✓ Kész · 🤖 · Elvetveshell.jsin-pagechanged
Back to newest↩ Legújabbshell.jsin-pagelive
Latest label· legújabbshell.jsin-pagelive
Edit log📋 Szerkesztési naplóshell.jsin-pagelive
Audit downloadLetöltés (JSON / MD)revision_api.pydownloadplanned
Carried-comment origin badgeV1 (faint)shell.jsin-pageplanned
Mobile gate💻 nyisd meg szélesebb képernyőnshell.jsin-pagelive

State reference

StateMeaningEntered byExits to
not_done (nincs kész)Default for every submitted comment; the only state AI acts onsubmit, revert, or toggle while workingdone, rejected (free, while working); carried to n+1 on publish
done (kész)Resolved manually or by AI (resolved_by=ai → 🤖 badge)admin toggle or successful AI applynot_done, rejected (free, while working); freezes to locked on publish
rejected (elvetve)Admin-dismissed with an optional note; client sees 'Elvetve — note'Visszautasít (+ optional note) while workingnot_done, done (free, while working); freezes to locked on publish; does NOT carry
locked (derived)Any done/rejected comment living in a frozen/published versionpublish (checkpoint) of its versionread-only (never edited again; appears in version-history browse)
working (Version.state)The single mutable editable copy per pagefirst version of a page, or fork on publish (n+1)published on explicit publish
published (Version.state)Frozen, client-visible checkpoint with a changelogexplicit 'Új verzió / Ügyfélnek küldés →'immutable; browsable read-only via version history
client_lockedClient view disabled for editing after the admin's first real editadmin's first in-place HTML/CSS/AI edit on the working versionunlocks when the next version is published

Generated by the user-journeys skill on 2026-06-23 · hosted at https://comment-editor-rebuild-journeys.pages.dev. Rendering: Mermaid flowchart syntax. No screenshots — this is a behavioral spec, not a visual QA artifact.