Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 136 additions & 0 deletions .claude/skills/code-to-docs/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
---
name: code-to-docs
description: >-
Propagate a code change into the documentation corpus (docs/). Use after
merging or before shipping any change that alters user-visible behaviour
(UI, routes, permissions, tiers, endpoints, copy), or when someone says
"the docs are out of date", "sync the docs", or "update docs for this PR".
Takes PR numbers or a commit range; maps the diff to affected docs pages,
updates them grounded in the code, and opens a review PR. Never pushes
docs straight to main.
---

# code-to-docs: propagate a code diff into the docs

This is the code → docs half of the two-way docs/code sync. (The docs → code
half - editing a doc and trickling the change into code - is planned, not
built.) The docs corpus is `docs/` at the repo root, published to
docs.echo-next.dembrane.com on every main push touching `docs/**`. The agent
service also cites these pages in chat, so stale docs mislead both people
and the assistant.

Read `docs/_authoring/FACTS.md` (what is true) and `docs/_authoring/STYLE.md`
(how to write it) before touching any page. They override anything here.

## Input

One of, in order of preference:

1. PR numbers: `gh pr view <n>` + `gh pr diff <n>` for each.
2. A commit range: `git log --oneline <range>` + `git diff <range>`.
3. Nothing given: diff the current branch against main and confirm the scope
with the user before writing.

When docs have drifted for a while, find the catch-up range with
`git log --oneline --since=<last docs sync> -- ':!docs'` and treat every
user-visible PR in it as input.

## Procedure

### 1. Classify the diff

For each change, decide: does it alter something a reader can observe?

- UI surfaces, labels, flows, empty states, buttons
- Routes and navigation
- Permissions, roles, tiers, limits, prices
- Endpoints or fields external developers use
- Behaviour: what gets stored, who can see it, when things fire

Internal-only changes (refactors, tests, CI, performance with no visible
effect) need no docs. Say so explicitly in your output - "no docs impact"
is a valid, reviewable conclusion. Internal ARCHITECTURE changes may still
affect `docs/users/developer-internal/*`; check that section before
concluding no impact.

### 2. Map the diff to pages

Build the candidate list from three directions; union them:

- **By feature**: which `docs/features/<feature>.md` page owns each changed
behaviour? `docs/map.md` is the index of everything.
- **By audience**: every `docs/users/<type>/` page that retells an affected
feature. `grep -rli '<feature term>' docs/users` - the same capability is
deliberately documented once per audience.
- **By reference**: grep the docs for exact strings from the diff - old UI
labels, route paths, endpoint names, tier names. Every hit is a candidate.
Old labels that the diff renamed or removed are the highest-value hits.

Then add the structural pages: `docs/_authoring/FACTS.md` (always check),
`docs/map.md` and the section `index.md` (only when a page is added or
retitled), and the `.nl-NL.md` twin of every page you touch, if one exists.

### 3. Update, facts first

Order matters:

1. **FACTS.md first.** It is the corpus's source of truth; every page must
agree with it. Update the affected sections (roles, tiers, routes,
feature inventory) before any prose page.
2. **The feature page** (`docs/features/`) - the canonical reference.
3. **The audience pages** (`docs/users/`) - retell from that reader's
vantage; they link back to the feature page and must not contradict it.
4. **Trickle to related pages.** After editing a page, grep for pages that
link to it or restate the same behaviour, and reconcile them. A change
rarely lives on one page.

### 4. Ground every claim in code

- Never document from a PR title or description alone - read the code the
diff touches. PR descriptions say what was intended; code says what
shipped.
- UI labels must be copied exactly from source (`<Trans>` strings, `t`
macros, button children). Never guess a label.
- Permissions and gating: read the actual policy checks (`require`,
`has_policy`, tier gates), not the PR summary.
- If you cannot verify a behaviour in code, leave it out. STYLE.md's
accuracy rule applies: write around what you don't know; never invent.
- Production vs preview: this corpus documents echo-next. Features that are
main-only (not in a production release yet) follow the existing
convention: mark them via [dembrane next](../../docs/features/dembrane-next.md)
the way current pages do.

### 5. Verify

- Every relative link on touched pages resolves to a real file.
- New pages are reachable: linked from their section `index.md` AND
`docs/map.md` (folder2website only publishes pages reachable from
README.md by links).
- Build if the toolchain is available:
`bunx github:spashii/folder2website#main docs --out /tmp/docs-site`
(mirrors `.github/workflows/dev-deploy-docs.yml`). A broken build blocks
the PR.

### 6. Open a PR - the review gate

Docs changes ship as a PR, never a direct push. One PR per code diff (or
per catch-up batch). The PR body must list, per finding:

- the code change (PR number or commit) that caused it
- the pages updated, and the pages checked but deliberately left alone
- anything you could not verify and therefore omitted

The review is the point: a human confirms the docs now say what the code
does. Merging the PR publishes the site.

## Judgement calls

- **Scope discipline**: update what the diff changed, resist rewriting whole
pages. Reviewers must be able to map each docs hunk to a code change.
- **When code and docs disagree about intent** (the code looks wrong, the
doc describes the desired behaviour): do not silently document the bug.
Surface the conflict to the user - that disagreement is exactly what the
two-way sync exists to catch.
- **Honesty over coverage**: an accurate page missing a feature beats a
complete page with an invented detail. The docs feed the in-app assistant;
invented details become confidently wrong answers to hosts.
41 changes: 39 additions & 2 deletions docs/_authoring/FACTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,9 @@ Auth: `/login /register /check-your-email /verify-email /password-reset /request
2FA supported. `/onboarding` wizard (create workspace + project). `/invite/accept`, `/invites`.

- *Workspaces* `/w/:workspaceId/home`, `/w/new`. Settings `/w/:id/settings/:section`:
name/logo, members (invite/roles/visibility/inherit-org), billing & usage, data ownership.
name/logo, *assistant context* (host guidance handed to the assistant in every project chat,
admins, autosaves) + *assistant memory* (workspace-scope notes, view + Remove),
members (invite/roles/visibility/inherit-org), billing & usage, data ownership.
Members `/w/:id/members/*`. Org `/o/:orgId`, `/o/:orgId/settings/:section` (admin matrix:
members × workspaces, access requests, pending invites, discoverable workspaces, org usage rollup).
- *Projects* `/w/:id/projects` (home, pinned, search), create wizard `/new` (name & context →
Expand All @@ -241,6 +243,37 @@ Auth: `/login /register /check-your-email /verify-email /password-reset /request
- *Chat / Ask* `/.../chats/new`, `/.../chats/:chatId` (+ `/debug`): RAG over selected
conversations; auto-select vs manual context; sources; templates (built-in + user templates);
standard mode + *agentic mode* (tool use, separate agent service). Free-tier chat gate.
`ENABLE_AGENTIC_CHAT = byEnv({production:false}, true)` - agentic OFF in production. Where
it's on, `/chats/new` is the *Ask home*: chat list + a question bar that filters chats and
creates one on Enter, a `Templates` insert menu, starter chips, and a
"Prefer the old chat? Start a Specific Details chat" escape hatch. Agentic runs show live
progress, a Send↔Stop morph, named citation links ("{name}'s conversation" →
`#chunk-` deep links), and documentation citations via a chooser modal
("Open documentation" / "Open chat documentation"). Agent tools (echo/agent, 20): inventory/
search/transcripts (`listProjectConversations, findConvosByKeywords, listConvoSummary,
listConvoFullTranscript, grepConvoSnippets`), docs (`listDocs, readDoc, grepDocs, readSkill`),
settings (`getProjectSettings, proposeProjectUpdate, proposeCustomVerificationTopic` - all
changes are proposals the host applies via a review card), chats (`listProjectChats,
readChat` - respects others' private chats), live status (`getLiveConversationStatus`),
support (`reachOutToDembrane` → `support_request` outbox; never promises follow-up),
memory (`readMemory, remember` - see memory below), progress (`sendProgressUpdate`).
*Assistant memory*: one `agent_memory` collection, scope `workspace|project|user` (user scope
is the only one that may hold personal detail; owner-only). Hosts view + delete (never edit)
memories via `/v2/bff/memory/*`; surfaces = user settings *Assistant* section, project
settings *Assistant memory*, workspace settings general tab. The assistant is the only
writer. *Workspace context* (`workspace.context`): host-written standing guidance, edited on
the workspace settings general tab ("Assistant context", autosaves), injected into every
agentic run prompt alongside project context.
- *Monitor* `/.../monitor` (sidebar entry *Monitor*, no role gate): live view of a project's
recording sessions. *Live participant flow* funnel (canvas, scales to thousands): lanes
`Scanned → Setting up → Recording`, fed by portal visitor beacons (per-stage outcomes:
mic ok/skipped/blocked, terms, details). Per-conversation rows: state pills (Recording,
Paused, Verifying, Exploring, Typing, Finishing, Finished, Waiting, Just started, Idle),
`Transcribing N clips` chip, `catch up ~N min` backlog estimate, red `Error` badge,
`Audio stopped?` (stalled) and `Screen locked` (backgrounded) warnings, weak-network and
low-battery hints, live transcript snippet. Real-time over SSE
(`GET /v2/bff/conversations/monitor/stream`, Redis-cached snapshot ≤1 Directus read/3s).
Project home shows a *Live & recent* section embedding the same monitor.
- *Library / analysis* `/.../library`, `/.../library/views/:viewId`,
`/.../views/:viewId/aspects/:aspectId`: AI-extracted topics/aspects/quotes; custom views;
library generation (status, regenerate). Gated (Changemaker+ / "contact sales" if unavailable).
Expand All @@ -250,7 +283,11 @@ Auth: `/login /register /check-your-email /verify-email /password-reset /request
- *Host guide* `/.../projects/:projectId/host-guide`: PDF + QR for participants.
- *Portal editor* `/.../settings/portal-editor` (see §8).
- *Settings (user)* `/settings/:section`: account & security (display name, password, 2FA, audit logs),
my access (orgs/workspaces & roles), appearance (font/size/language; 8 locales), project-defaults (legal basis).
my access (orgs/workspaces & roles), appearance (font/size/language; 8 locales), *assistant*
(Memory card: the caller's own user-scope assistant memories, view + Remove only),
project-defaults (legal basis). Account deletion: server endpoint only
(`DELETE /user-settings/account` suspends + marks for purge within 30 days) - NO in-app UI yet;
don't document a button.
- Sidebar *Documentation* link → Notion Info Hub, locale-aware (see §11).

i18n: 8 locales `en-US, nl-NL, de-DE, fr-FR, es-ES, it-IT, uk-UA, cs-CZ` (Lingui).
Expand Down
9 changes: 9 additions & 0 deletions docs/features/account-and-security.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,15 @@ consistent footing rather than a blank field, which matters when you're recordin
The wider picture of who owns the data is in
[data ownership & compliance](./data-ownership-and-compliance.md).

## What the assistant remembers about you

*[dembrane next only](./dembrane-next.md).* If you use [Ask's agentic mode](./chat-and-ask.md),
the assistant can save notes about how you like to work - saved during your chats, read back at
the start of the next one. *Settings → Assistant* shows every note it keeps about you; only you
see these, and *Remove* makes it forget one for every future chat. The assistant writes the
notes; you can't edit them, only remove them. (Project and workspace notes have their own
surfaces - see [chat & Ask](./chat-and-ask.md#agentic-mode-in-more-detail).)

## Your access at a glance

A *my access* view lists the organisations and workspaces you belong to and the
Expand Down
38 changes: 35 additions & 3 deletions docs/features/chat-and-ask.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,44 @@ conversations:
[tag](./conversations-and-transcripts.md#tags), and answers come back with exact quotes and
citations. Best when you want precision: one session, one cohort, exact wording. If you're
already viewing one conversation when you start, it's selected for you.
- *Agentic* (*[dembrane next only](./dembrane-next.md)*) - multi-step analysis with live tool
execution: it can search across conversations, fetch transcripts, and chain steps to answer
harder questions. A preview feature, not in production yet.
- *Agentic* (*[dembrane next only](./dembrane-next.md)*) - an assistant that works in steps:
it searches conversations, reads transcripts, and chains what it finds to answer harder
questions. A preview feature, not in production yet - see below for what it adds.

Specific Details is the usual move once a project gets large and you want precision over breadth.

## Agentic mode, in more detail

*[dembrane next only](./dembrane-next.md).* On dembrane next, *Ask* opens as a home for all
your chats: your chat list with a question bar on top. Typing filters your earlier chats;
pressing Enter asks the question as a new chat. A *Templates* menu inserts a saved prompt, and
if you'd rather pick conversations yourself there's a one-click way to start a classic
*Specific Details* chat instead.

While the assistant works you see its progress step by step, and a *Stop* control replaces
*Send* so you can halt a run that's going the wrong way. Answers cite their sources by name -
*"Maria's conversation"*, *"Maria's transcript excerpt"* - and each link jumps to the exact
place in the [transcript](./conversations-and-transcripts.md).

Beyond answering questions, it can:

- *Check what's live* - ask *"is anyone recording right now?"* and it reads the same live
status as the [monitor](./recording.md#watch-it-live-the-monitor).
- *Read earlier chats* in the project (your colleagues' private chats stay private).
- *Answer "how do I" questions* from this documentation, citing the page it used.
- *Suggest settings changes* - it never edits your project itself; every change arrives as a
proposal you review and apply (or reject).
- *Log a question with the dembrane team* when you're stuck - see
[getting help](../users/host/getting-help.md).
- *Remember* - it can save notes about your preferences and the project so the next chat
starts smarter. You can see and remove everything it remembers: your own notes under
*Settings → Assistant*, project notes in project settings, workspace notes in
[workspace settings](./organisations-and-workspaces.md). The assistant writes these notes;
you can't edit them, only remove them.

Hosts steer it with standing guidance too: the project *context* field, and a workspace-wide
*assistant context* in workspace settings that reaches every project chat in the workspace.

## Cited sources

Every answer lists the conversations it drew on. Click through to read a source in full on its
Expand Down
4 changes: 3 additions & 1 deletion docs/features/dembrane-next.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ now, so you always know whether something you read about is actually available t

| Feature | What it is | Where |
|---|---|---|
| *Agentic mode* (in Ask) | A chat mode that works in steps - searching across conversations, fetching transcripts, and chaining tool calls to answer harder questions. | [Chat & Ask → Agentic mode](./chat-and-ask.md#agentic-mode) |
| *Agentic mode* (in Ask) | An assistant that works in steps - searching, reading transcripts, checking live status, answering from the docs, and proposing settings changes for your review. Ask opens as a home for your chats, with named citations and a Stop control. | [Chat & Ask → Agentic mode](./chat-and-ask.md#agentic-mode-in-more-detail) |
| *Assistant memory & context* | The assistant saves notes (you view and remove them in user, project, and workspace settings) and takes standing guidance from a workspace-wide *assistant context*. | [Account & security](./account-and-security.md#what-the-assistant-remembers-about-you), [managing your workspace](../users/host/managing-your-workspace.md#give-the-assistant-standing-context) |
| *The Monitor* | A live view of a session: the participant flow from QR scan to recording, live recordings with audio warnings, and transcription progress. | [Recording → Watch it live](./recording.md#watch-it-live-the-monitor) |

If the table is short, that's a good sign: most of dembrane is the same on next and
production. Only genuinely in-progress features live here.
Expand Down
20 changes: 20 additions & 0 deletions docs/features/recording.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,26 @@ The conversation shows up in your dashboard as soon as it starts. The transcript
pieces, and the higher-quality transcription takes a little extra processing time. After that
it keeps growing as people speak.

## Watch it live: the Monitor

*[dembrane next only](./dembrane-next.md).* While people record, the project's *Monitor* page
(in the project sidebar) shows the whole room in real time:

- *Live participant flow* - from the moment someone scans the QR, they appear and move across
three stages: *Scanned → Setting up → Recording*. You see people stall at the mic check or
drop off before recording, while it's still fixable.
- *Each live recording* - who's recording, paused, or finishing, with a live transcript
snippet and a running duration.
- *Is the audio coming in?* - a recording that was sending audio and stopped gets an
*Audio stopped?* warning (they may have lost connection); a locked phone or hidden tab shows
*Screen locked*, because recording pauses until they come back.
- *Transcription progress* - a *Transcribing* count per conversation, a rough *catch up*
estimate when a backlog builds, and an *Error* badge when something needs attention.

The project home page shows the same view in brief as *Live & recent*. See
[collecting conversations](../users/host/collecting-conversations.md#watch-the-room-the-monitor-page)
for how to use it mid-session.

## Pause, resume, stop

- *Pause / resume* - step away mid-session without ending the recording. What's recorded so
Expand Down
1 change: 1 addition & 0 deletions docs/map.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,4 @@ it's for, and how it works.
- [Background jobs & scheduler](./users/developer-internal/background-jobs-and-scheduler.md)
- [Local development](./users/developer-internal/local-development.md)
- [Deployment & releases](./users/developer-internal/deployment-and-releases.md)
- [Developing & maintaining the docs](./users/developer-internal/maintaining-docs.md)
Loading
Loading