> ## Documentation Index
> Fetch the complete documentation index at: https://skaum.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Endringsforslag: story map

> User story map for forslag, the Redaksjonskomité and the text question, sliced into releases from the owner's decisions of 2026-10-30

> [!NOTE]
>
> Planned, not built. This page is the story map agreed on 2026-10-30 after a design grilling. The decisions behind it are in engram under `odd/endringsforslag/decisions` (per-question answers in `odd/endringsforslag/answers-1` to `answers-8`), the competitor and procedure research under `research/endringsforslag-reference`. The Linear project «Endringsforslag» (P-VOT-33) has one issue per slice, listed in the slice table below. When a slice ships, its detail moves to `domenemodell.mdx` and `arkitektur.mdx` and this page keeps the map.

## Why

tilvotering runs the vote. Until now the secretary writes every question by hand, and nothing a delegate wants to change reaches the app before the chair reads it from the rostrum. Landsmøter, ting and synoder (the product's core customers) work the other way round: forslag arrive weeks ahead, a redaksjonskomité sorts and tidies them, and the meeting votes its way through a voteringsorden. This feature brings that flow into the app in three steps that follow the meeting's own states:

1. **Sakspapirer before the meeting.** Delegates sign in while the meeting is in forberedelse and submit forslag on the saker the secretariat has opened. A Redaksjonskomité approves, numbers and edits them, with every edit kept as a version with a comment.
2. **Forslag in the meeting.** The sak's forslag are on every screen: the delegate's, the chair's and the projector. New ones come from the floor until the sak is closed for forslag: by its forslagsfrist, by hand, or by strek.
3. **The text question.** A sak about a text (vedtekter, a program, an uttalelse) carries the text with line numbers. Amendments are strike-and-add on a line range, the app proposes the voteringsorden, generates the chain of polls, marks what falls, and produces the final text.

The principle from the research holds throughout: the software handles submission, listing, order and the record. Deciding what falls, what is merged and what is put to a vote stays with the chair and the committee, who get good defaults and never a locked-in rule.

## Personas

| Persona | Who | Where |
| - | - | - |
| **Delegat** | A participant with forslagsrett (its own right, shaped like talerett: voters, everyone, or chosen by custom field) | Pre-meeting screen, the one-screen participant view |
| **Forslagsstiller** | Whoever stands behind a forslag: one or more participants, or a «body» (fylkeslag, styret, a committee) kept as a free-text tag | Named on the forslag, in the protokoll and on the projector |
| **Saksansvarlig** | The person who presents a sak, named on the sak itself; not a proposer | Chair's card, protokoll |
| **Redaksjonskomité** | A flag on any participant (they keep their role and vote), or an outsider with a new non-voting role outside the voting base, roll call, CSV and tier limit | Fifth meeting view on the secretary shell: «Forslag», «Saksliste», «Forslagsstillere» |
| **Sekretær** | Has every committee power plus the question form | Secretary view |
| **Ordstyrer** | Drives the sak, the order and the votes | Chair view |
| **Projektor** | The room | Widgets «Forslag på saken» and «Forslag under votering» |

## The map at a glance

Activities follow the meeting flow from left to right. Each cell lists the stories a release adds to that activity; the stories themselves are in the tables below.

| Activity | R1 Sakspapirer | R2 I møtet | R3 Voteringsorden | R4 Tekstforslag | R5 Flytskjema |
| - | - | - | - | - | - |
| A. Set up the meeting | A1 A2 A3 A4 A5 | A6 | | | |
| B. Open a sak for forslag | B1 B2 | B3 B4 | | B5 | |
| C. Submit a forslag | C1 C2 C3 C4 C5 C6 C7 | C8 C9 C10 | | C11 C12 | |
| D. Review and edit | D1 D2 D3 D4 D5 D6 D7 D8 D9 | | | | |
| E. Build the vote | E1 | | E2 E3 E4 E5 | E6 | E7 |
| F. Vote | F1 F10 | F2 F3 | F4 F5 F6 F7 | F8 F9 | |
| G. Record | G1 G2 | G3 | G4 | G5 | |

## Stories

Each story names its persona and the slice that builds it (slice numbers are in the table at the end). A story is one observable behaviour; its acceptance details are written in the slice's issue and feature document, not here.

### A. Set up the meeting

| ID | Story | Persona | Slice |
| - | - | - | - |
| A1 | Set forslagsrett on «Møtedetaljer»: voters, everyone, or chosen by a custom field; default «samme som talerett». Observers can have it | Sekretær | 2 |
| A2 | Set the meeting's default for «Åpen for forslag» on new saker | Sekretær | 2 |
| A3 | Set «Forslag vises: straks / etter godkjenning»; default «etter godkjenning» | Sekretær | 3 |
| A4 | Appoint the Redaksjonskomité: flag a participant, or add an outsider with the non-voting role. Only a chair or org admin may do it, as for the chair role | Ordstyrer, org admin | 3 |
| A5 | Forslag are available on every paid tier (single\_meeting, standard, pro); the test tier tries it in rehearsal within its participant cap | Org admin | 2 |
| A6 | Set whether strek also closes the sak for forslag («Strek lukker også for forslag», NJ's rule); default on | Sekretær | 4 |

### B. Open a sak for forslag

| ID | Story | Persona | Slice |
| - | - | - | - |
| B1 | «Åpne for forslag» / «Lukk for forslag» on a sak; an optional «Forslagsfrist» (date and time, Oslo) closes it by itself. A closed sak shows its forslag but takes none | Sekretær, Redaksjonskomité | 2 |
| B2 | Name a saksansvarlig on the sak | Sekretær | 1 |
| B3 | «Lukk for forslag» / «Åpne for forslag» on the current sak live from the chair's card | Ordstyrer | 4 |
| B4 | A forslag that arrives after the sak was closed is badged «Etter fristen» and admitted by the ordinary «Godkjenn» once the room has consented; no «Slipp inn» for forslag, that word stays the talerliste's | Ordstyrer, Redaksjonskomité | 4 |
| B5 | Paste the sak's text as a text question: the app numbers the lines, the current text is the base, and the board's innstilling is registered as forslag nr 1 with its own diff | Sekretær, Redaksjonskomité | 6 |

### C. Submit a forslag

| ID | Story | Persona | Slice |
| - | - | - | - |
| C1 | Sign in before the meeting with the ordinary login and see the saksliste with the open saker and their forslag, in place of today's welcome message. Rehearsal (bots, test votes, participation links) is untouched and still purged at «Start møte»; forslag are real data and survive | Delegat | 2 |
| C2 | Submit an endringsforslag as free text on an open sak, naming the forslagsstillere: yourself, co-proposers from the participant list, or a body typed as a tag and reused later. Locked on send: no editing after | Delegat | 2 |
| C3 | Propose a new sak (innkommet sak) with a title, text and forslagsstillere | Delegat | 2 |
| C4 | Nominate a candidate to an election sak before the meeting | Delegat | 2 |
| C5 | See your own forslag with its state («Ubehandlet», «Godkjent», «Avvist» with the reason, «Trukket») and open «Historikk» to read each version and the committee's comment | Delegat | 2 |
| C6 | Withdraw your own forslag until its poll opens; it stays in the protokoll as «Trukket». Co-proposers cannot withdraw | Delegat | 2 |
| C7 | Register a forslag on behalf of a person or a body, for a paper or oral one, with the sender named as forslagsstiller | Sekretær, Redaksjonskomité | 2 |
| C8 | During the meeting, open the «Forslag (N)» sheet on the current sak from the one-screen view (next to «Meld på talerlisten», at 375 px), read the sak's forslag and submit a new one while the sak is open | Delegat | 4 |
| C9 | Submit a formal forslag (utsettelse, oversendelse, avvisning); it is put first in the voteringsorden | Delegat | 4 |
| C10 | Benkeforslag: propose a candidate from the floor; the candidate's consent is recorded; the secretary adds the candidate to the election with «Fra forslag» (E1) | Delegat | 4 |
| C11 | Amend a text question on the phone: tap a paragraph to select its lines, adjust from and to with steppers, rewrite the lines in a box, see the computed strike-and-add, send. Shortcuts «Stryk» and «Tilføy etter linje N» | Delegat | 6 |
| C12 | Choose whether the amendment targets the current text or the innstilling (forslag nr 1); the app shows which on every screen | Delegat | 6 |

### D. Review and edit

| ID | Story | Persona | Slice |
| - | - | - | - |
| D1 | Open the «Redaksjonskomité» view and work a queue of «Ubehandlet» forslag per sak, with the sak's text and the forslag's forslagsstillere | Redaksjonskomité, Sekretær | 3 |
| D2 | Approve a forslag, which gives it its number, or reject it with a reason («Utenfor realiteten», «For sent», free text). With «etter godkjenning» the other delegates see it only from here | Redaksjonskomité | 3 |
| D3 | Edit a forslag's text with a comment («Avtalt med forslagsstiller: skrivefeil»); the edit is a version everyone can open. No in-app confirmation by the proposer | Redaksjonskomité | 3 |
| D4 | Edit a sak's question or body with a comment; the edit is a version shown in «Historikk». No version once a round has opened (the question lock of VOT-468) | Sekretær, Redaksjonskomité | 1 |
| D5 | Merge two forslag: edit one to the agreed text and reject the other with a comment that points to the survivor. No separate merge feature | Redaksjonskomité | 3 |
| D6 | Manage the meeting's forslagsstillere: bodies created on demand as tags, renamed and merged on the «Forslagsstillere» page | Redaksjonskomité, Sekretær | 1 |
| D7 | Accept an innkommet sak into the saksliste as a new agenda item, placed by the committee, or reject it | Redaksjonskomité | 3 |
| D8 | Accept a nomination as a candidate on the election sak, or reject it | Redaksjonskomité | 3 |
| D9 | Withdraw a forslag on the proposer's behalf with a comment | Redaksjonskomité | 3 |

### E. Build the vote

| ID | Story | Persona | Slice |
| - | - | - | - |
| E1 | «Fra forslag» in the question form: pick an approved forslag as an option or as the question text; the forslagsstillere follow it onto the option. The bridge that makes R1 usable in a real meeting while polls are still built by hand | Sekretær | 2 |
| E2 | Order the sak's forslag: the app proposes (formal forslag first, then in the order received), the committee and the chair drag to reorder, and the chair announces the voteringsorden the meeting adopts | Redaksjonskomité, Ordstyrer | 5 |
| E3 | Set dependencies by hand: «hvis 3 vedtas, bortfaller 5 og 6». Nothing is inferred | Redaksjonskomité | 5 |
| E4 | Group non-conflicting forslag into one step, «Samlet votering», adopted or rejected together | Redaksjonskomité | 5 |
| E5 | Generate the chain of draft polls from the order: an alternative vote where forslag compete, FOR/MOT for a single one, the final text last. Each step is a poll the chair runs as today | Redaksjonskomité, Sekretær | 5 |
| E6 | For a text question the proposed order follows the line ranges in document order, most far-reaching first; forslag on the same lines are alternatives in one step | Redaksjonskomité | 6 |
| E7 | See the voteringsorden and its dependencies as a flowchart: which paths are open, what ends the sak | Redaksjonskomité, Ordstyrer | 7 |

### F. Vote

| ID | Story | Persona | Slice |
| - | - | - | - |
| F1 | When the chair opens a sak, its forslagsstillere are offered the first places on the talerliste; the chair can skip them | Ordstyrer | 1 |
| F2 | See the current sak's forslag in a column next to the talerliste column, with their states | Ordstyrer | 4 |
| F3 | Projector widget «Forslag på saken»: the sak's forslag with their forslagsstillere | Projektor | 4 |
| F4 | Step through the chain: «Neste votering» is the card's primary action; open the step as a poll, or register its manual result as for any poll today; skip a step; regroup a «Samlet votering» live, and take a forslag out of it when a delegate demands it before the vote opens | Ordstyrer | 5 |
| F5 | When a step is decided, its dependants are marked «Bortfalt» and skipped | Ordstyrer | 5 |
| F6 | Projector widget «Forslag under votering»: the forslag text of the open step; the participant ballot shows the same text | Projektor, Delegat | 5 |
| F7 | A step that the meeting settles by acclamation gets its manual result in one click from the chair's card. Not a new concept: the manual result exists today, it only has to be close at hand | Ordstyrer | 5 |
| F8 | The ballot and the projector render a text amendment as strike-and-add on the numbered lines, in the projector's own tokens | Projektor, Delegat | 6 |
| F9 | The last step votes the whole text as amended, with the threshold the decision rule gives it (2/3 for vedtekter) | Ordstyrer | 6 |
| F10 | The forslagsstiller's presentation runs on its own clock: a speaker kind «Innledning» with its own limit on «Møtedetaljer», longer than an innlegg; the chair marks a speaker as innledning, and the offered first place (F1) is one automatically | Ordstyrer | 8 |

### G. Record

| ID | Story | Persona | Slice |
| - | - | - | - |
| G1 | The protokoll names the forslagsstillere of every forslag and option, and the saksansvarlig of every sak | Sekretær | 1 |
| G2 | The protokoll lists every forslag per sak with its number, text, forslagsstillere, versions and state, including «Trukket» and «Avvist», as additive keys in schema 2.x and a `forslag.csv` sheet | Sekretær | 2 |
| G3 | «Lukket for forslag» is logged as its own event with its cause (forslagsfrist, by hand, or strek), and a forslag admitted «Etter fristen» is marked so in the protokoll | Sekretær | 4 |
| G4 | The protokoll records the outcome of every step: «Vedtatt», «Falt», «Bortfalt», «Oversendt», a «Samlet votering» with its members, and the counts where a poll ran | Sekretær | 5 |
| G5 | The protokoll and the export carry the final text with the adopted amendments applied; two adopted edits on the same lines are flagged for the committee to resolve by hand | Sekretær | 6 |

## States of a forslag

A proposal for the domain model, to be fixed in slice 2 and extended by slice 5:

| State | Set by | Meaning |
| - | - | - |
| `submitted` («Ubehandlet») | the proposer, or the secretariat on their behalf | Visible to the proposer and the committee; to everyone when the meeting shows forslag «straks» |
| `approved` («Godkjent») | the committee | Numbered and visible to everyone; eligible for «Fra forslag» and the voteringsorden |
| `rejected` («Avvist») | the committee, with a reason | Kept in the protokoll |
| `withdrawn` («Trukket») | the proposer, or the committee on their behalf | Kept in the protokoll; allowed until the forslag's poll opens |
| `adopted` / `failed` («Vedtatt» / «Falt») | the result of its step | Slice 5 |
| `lapsed` («Bortfalt») | a dependency, when another step is decided | Slice 5 |
| `referred` («Oversendt») | the chair, for a forslag sent on to the board or a committee | Slice 5 |

Numbering is per sak in approval order, shown with the sak's number («Forslag 7.3»), assumption to confirm in slice 2.

## Slices and releases

One Linear issue per slice, with the stories as its sub-task checklist. Sizes are the owner's S/M/L scale for a batch, not estimates in hours. Release 1 is the first that is worth selling; the rest ship slice by slice as they are done, without a target date.

| Slice | Release | Name | Stories | Depends on | Size | Linear |
| - | - | - | - | - | - | - |
| 1 | R1 | Forslagsstillere og versjoner: the backer list on saker and options, bodies as tags, saksansvarlig, versions with a comment, the talerliste first place | B2 D4 D6 F1 G1 | | M | VOT-523 |
| 2 | R1 | Innsending før møtet: forslagsrett, «Åpen for forslag», the pre-meeting screen, the three pre-meeting kinds, withdraw, on behalf, the forslag states, «Fra forslag», the protokoll list | A1 A2 A5 B1 C1 C2 C3 C4 C5 C6 C7 E1 G2 | 1 | L | VOT-524 |
| 3 | R1 | Redaksjonskomité: the flag and the outsider role, the fifth view, the review queue, approve and reject, edit with a version, merge by hand, accept new saker and nominations, «straks / etter godkjenning» | A3 A4 D1 D2 D3 D5 D7 D8 D9 | 1, 2 | L | VOT-525 |
| 4 | R2 | Forslag i møtet: the participant sheet, the chair column, the projector list, «Lukk for forslag» live, strek closing forslag, late forslag «Etter fristen», formal forslag and benkeforslag | A6 B3 B4 C8 C9 C10 F2 F3 G3 | 2, 3 | L | VOT-526 |
| 5 | R3 | Voteringsorden og generert votering: order, dependencies by hand, «Samlet votering», the generated chain, «Neste votering», manual results per step, «Bortfalt», the projector's open step, outcomes in the protokoll | E2 E3 E4 E5 F4 F5 F6 F7 G4 | 4 | L | VOT-527 |
| 6 | R4 | Tekstforslag: the text question kind with line numbers, two layers, the phone's line picker and computed diff, diff rendering, line-range order, the final text vote and the consolidated text | B5 C11 C12 E6 F8 F9 G5 | 5 | L | VOT-528 |
| 7 | R5 | Flytskjema: the voteringsorden as a diagram | E7 | 5 | M | VOT-529 |
| 8 | R1 | Taletid for forslagsstiller: the speaker kind «Innledning» with its own limit, marked by hand or set by the offered first place | F10 | 1 (automatic placement only) | M | VOT-530 |

Dependencies read: slice 3 needs the forslag of slice 2 and the versions of slice 1. Slice 8 stands alone (the owner's request of 2026-10-30: many organisations give the forslagsstiller's intro more time than an innlegg); only its automatic placement waits for slice 1. Slice 1 is deliberately first and alone: it changes saker and options that exist today, and it is the only slice that touches the protokoll before any delegate can submit.

## Constraints every slice respects

* **No in-process state**: production runs two Puma workers; coalescing and throttles go through Solid Cache and Solid Cable.
* **Broadcast streams**: a new or changed forslag is a structural change on `[meeting, "updates"]`, coalesced like a talerliste sign-up; a step's result travels as a refresh, never as a tally.
* **The capability matrix**: submitting, reviewing and ordering are capabilities keyed by meeting state, so a closed meeting refuses them with the standard message and no role bypass.
* **Rehearsal**: forslag are real data in forberedelse; «Start møte» and «Nullstill møte» leave them alone and the purge list says so explicitly. Bots never submit forslag.
* **The one-screen participant view** at about 375 px: forslag arrive as a bottom sheet and a pre-meeting saksliste, never a second screen during the meeting.
* **The question lock**: no version of a question, a body or a forslag once a round on the sak has opened.
* **Protokoll schema 2.x** is additive only; every new key is documented in `protokoll-json-schema.mdx` before it ships.
* **The projector widget catalogue** gets two keys; both render in every meeting state and in the projector's own `--pj-*` tokens.
* **Norwegian UI**, English code and docs. UI terms: forslag, endringsforslag, tilleggsforslag, innkommet sak, forslagsstiller, saksansvarlig, redaksjonskomité, voteringsorden, «Samlet votering», «Bortfalt», «Oversendt», «Forslagsfrist», «Lukk for forslag», «Etter fristen»; strek and «Slipp inn» belong to the talerliste only.

## Assumptions and open points

Assumptions written into the stories above, each to be confirmed in its slice:

* The secretariat may register a forslag on someone's behalf (C7); the owner's answer implied it without saying so.
* Two deadlines, two vocabularies: the forslag window («Åpen for forslag», «Forslagsfrist», «Lukk for forslag») and the talerliste's strek; the words are never mixed. Strek also closes forslag by default (A6). A late forslag is admitted by «Godkjenn» with no in-app consent count; the chair or the committee records the room's consent by clicking.
* Numbering is per sak in approval order («Forslag 7.3»).
* Merging two forslag is done by hand (D5); no automatic jamking.
* Proposer names are meeting data and visible to every participant, as in every competing tool.
* Reservasjoner (dissent recorded against a decision) are out of scope for all slices.
* Inference of what falls from overlapping line ranges is out of scope; the owner chose explicit dependencies only. It can return as a suggestion in slice 6 if the committee's work proves heavy.

## Mockups

Mockups cover the full vision with the first release marked, under `Mockup/endringsforslag/v1-<description>/`, one folder per iteration. The example mockup walks two cases end to end: an innkommet sak from a fylkeslag with the body as forslagsstiller (slices 2 and 3), and a benkeforslag in an election (slice 4 with E1).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.