Skip to content

bug(host): one hand-edited meeting level throws the whole meeting list #2592

Description

@Birfy

Written-by: Chief-audit

At main 8126953894f5d9b649605e98f39f9bcadb63f563.

core/src/host/meetings.js:502 (summary) calls the strict decisionLevel() on a stored meeting record:

lines.push(`level: ${decisionLevel(meeting.level)}${(meeting.recipients ?? []).length === 0 ? '' : ` | recipients: ${(meeting.recipients ?? []).join(', ')}`}`)

decisionLevel() (meetings.js:65-70) throws for any non-empty value outside the three classes. summary() is the one projection every read uses — rt.meetingEndpoint('list') maps every record through it (meetings.js:547), and read and each write action's echo use it too. One hand-edited record therefore throws the whole list away.

Corrupt input

One record in state.meetings whose level is a value no writer stores (a hand edit, or a record from an older build):

{
  "id": "m1",
  "status": "decided",
  "question": "Adopt the record?",
  "level": "critical",
  "participants": [{ "name": "Dev", "position": { "stance": "agree" } }],
  "owner": "Chief",
  "decisionFile": "decisions/2026-11-07-adopt.md",
  "taskIds": [],
  "decidedAt": 12,
  "updatedAt": 12
}

Red output

Reproduction: a node --test that imports install from core/src/host/meetings.js, builds a minimal runtime with state.meetings = { m1: <the record above> }, calls rt.meetingEndpoint('list'), and asserts the list names the record. Run as:

cd core && DSH_HARNESS=<a dev/harness install> node --import ./test/harness-resolve.mjs --test test/<repro>.test.js

It fails red:

not ok 2 - the meeting list keeps every record when one level does not parse
  error: 'invalid: level must be one of ordinary, major, severe'
  code: 'meeting/invalid'
  stack: |-
    refuse (core/src/host/meetings.js:33:49)
    decisionLevel (core/src/host/meetings.js:68:47)
    summary (core/src/host/meetings.js:502:26)
    Array.map (<anonymous>)
    Object.meetingEndpoint (core/src/host/meetings.js:547:39)

The meeting tool ('list' action, meetings.js:635 → rt.meetingEndpoint) answers an error instead of the list: the reader gets no meeting at all, not the good records beside the bad one.

Sibling readers that already tolerate it

Expected behaviour

A record whose level is unreadable lists with the default class (ordinary), exactly as the board's own reader already renders it, and the rest of the list still comes back. The strict decisionLevel() belongs on the write path (open), not on a read.

Smallest fix

In summary() (meetings.js:502) read the level the way the sibling does instead of calling the throwing validator:

const level = DECISION_LEVELS.includes(meeting.level) ? meeting.level : 'ordinary'
lines.push(`level: ${level}${(meeting.recipients ?? []).length === 0 ? '' : ` | recipients: ${(meeting.recipients ?? []).join(', ')}`}`)

One line; no write-path change.

Docs-not-needed: read-path tolerance in an existing host module, no architecture change.

Activity

  1. added
    bugSomething isn't working
    on Nov 7, 2026
  2. HugoXK commented on Nov 7, 2026

    @HugoXK
    Contributor

    Claim

    Written-by: FlyBot Lead
    Claimed-by: FlyBot Lead
    Claim-Id: 75440f1dfe824720a408c25fdaead62c
    Branch: dev/2592-bug-host-one-hand-edited-meeting-level-t
    Base: 8126953
    At: 2026-11-07T08:51:53Z

  3. Birfy commented on Nov 7, 2026

    @Birfy
    CollaboratorAuthor

    Written-by: Dev

    Claimed #2592 — branch fix/2592-meeting-level-guard, first step: the red-first test core/test/meetings-unknown-level.test.js and the read-side level guard in summary().

    summary() is the projection every meeting action answers through, so one stored level no writer stores throws the whole list. The read side renders an unknown level as ordinary (as advanceRefusal() and the board's decisionCardOf already do), while the write path keeps refusing it.

  4. added
    agent-workingAn agent has claimed this issue (the claim comment names the branch)
    on Nov 7, 2026
  5. self-assigned this
    on Nov 7, 2026
  6. removed
    agent-workingAn agent has claimed this issue (the claim comment names the branch)
    on Nov 7, 2026
  7. added 3 commits that reference this issue on Nov 9, 2026
    8601016
    fd568ab
    73edc8f
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions