githubnext/chopinPublic

Let's compose rich plans together

Let the room decide things together

Questionnaires, answered collaboratively in a pane beside the plan. Everyone
present edits one shared draft rather than a copy each, because the result is a
single decision: free text is a CRDT string, so two people typing merge instead
of overwriting, and whoever submits it is recorded as having decided.

The server owns the draft and is the only thing that may write to it. A patch
is applied to a clone and read back against the definition before it is kept,
so a client cannot introduce a shape the definition does not describe whatever
it sends. That rule lives in the domain package, next to the definition it
enforces; what the server decides is who may ask, not what is acceptable.

Resolution is two-phase because it has two halves. The record owns the answer
and the plan shows it, and until both have happened neither the waiting asker
nor any client may be told the decision is final. A failed document write rolls
the claim back and leaves the questionnaire open, which is a state everything
already renders.

The record is authoritative and lives beside the plan rather than in it, so
rewriting the prose around a decision cannot change the decision. What appears
in the MDX is a projection, kept so the source reads correctly on its own.

Questions are answered only in the decisions pane. A form inline in the prose
competes with the prose, and a decision is worth keeping visible after it has
been made.

A dev injector asks a sample questionnaire when DEV_QUESTIONS is set. It mints
identity and asks through the same path the agent's tool will, so what it
exercises is the real one rather than a rehearsal of it.
KCKrzysztof Cieslak authored
41a5facPatch
Parentd36845a
36 files changed+3706-155
StackedSplit
.oxlintrc.json+16 −9
apps/server/package.json+1 −0
apps/server/src/main.ts+32 −2
apps/server/src/plan/room.ts+96 −1
apps/server/src/plan/service.ts+16 −1
apps/server/src/plan/snapshot.ts+17 −1
apps/server/src/questions.test.ts+332 −0
apps/server/src/questions/inject.ts+59 −0
apps/server/src/questions/service.ts+317 −0
apps/server/src/questions/store.ts+343 −0
apps/web/src/app.tsx+11 −2
bun.lock+81 −0
packages/editor/package.json+1 −0
packages/editor/src/decisions.tsx+87 −0
packages/editor/src/index.ts+5 −1
packages/editor/src/plan-editor.tsx+13 −3
packages/editor/src/questionnaires.ts+76 −0
packages/editor/src/styles.css+7 −128
packages/editor/src/toolbar/index.tsx+0 −2
packages/editor/src/widgets-plugin.tsx+12 −2
packages/editor/src/widgets/index.ts+5 −1
packages/editor/src/widgets/questionnaire.tsx+124 −0
packages/protocol/index.d.ts+9 −2
packages/protocol/question.d.ts+208 −0
packages/question/package.json+30 −0
packages/question/src/answer.ts+78 −0
packages/question/src/draft.ts+194 −0
packages/question/src/index.ts+31 −0
packages/question/src/limits.ts+23 −0
packages/question/src/question.test.ts+180 −0
packages/question/src/react/index.ts+11 −0
packages/question/src/react/question-view.tsx+546 −0
packages/question/src/react/use-questionnaire.test.ts+122 −0
packages/question/src/react/use-questionnaire.ts+476 −0
packages/question/src/schema.ts+128 −0
packages/question/tsconfig.json+19 −0