Skip to content

Read the caller's own digest opt-out back into Project settings - #1879

Merged
Birfy merged 1 commit into
ThinkFlowLab:mainfrom
HugoXK:dev/3-p230-assistant-off-readback
Oct 31, 2026
Merged

Birfy merged 1 commit into
ThinkFlowLab:mainfrom
HugoXK:dev/3-p230-assistant-off-readback

Conversation

@HugoXK

@HugoXK HugoXK commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #1845

Written-by: Dev-3
Owner: Dev-3
Reviewer: Birfy
Claim-Id: de9b235e787c4b8d825d97566020a16a
Branch: dev/3-p230-assistant-off-readback
Base: 1c44a78

What was wrong

Project settings read project.assistant.off, a field the host never writes. The digest opt-out is per owner: setOwner stores it on project.assistant.owners[<ownerId>].off (core/src/host/project-assistant.js), and the assistant record itself carries only { botId, sessionId, createdAt, scheduleId? }. project-read returned the stored Project alone, so the field was undefined for every caller.

The reader saw an unticked Pause the daily digest for a digest she had paused, and one Save on that row — even to change something else — posted settings: { off: false }. The host then stored false and sent schedule-resume, so the paused digest ran again the next morning with nothing on screen saying so.

What changed

  • project-read answers one more field, assistantMine: { off, quiet }, read by rt.projectAssistant.mine from owners[actorId] for the calling actor. No new endpoint, no widening of the write surface; an absent Project still answers exactly { project: null, canManage: false }, the shape it had.
  • The panel draws the box from assistantMine.off (the page carries it from the same project-read), so each owner sees their own switch and never another owner's; project.assistant.off survives only as the fallback a caller with no such read had.
  • setOwner now touches record.off and the 09:00 task only when the value actually changes: a Save that writes the value already stored neither rewrites the record nor calls schedule-pause/schedule-resume. The quiet/zone writes, the owner gate and the pause/resume shape are unchanged.
  • Generated, not hand-edited: node core/scripts/build-client.mjs → core/client.js + patches/ds-bot/0008-client-bundle.patch; node scripts/ds-bot-patches.mjs generate → patches/ds-bot/0002-flybot-api-host.patch and the files/ mirrors. One changelog fragment (changelog.d/1845-assistant-off-readback.fixed.md) and one line each in docs/subsystems/core-client.md and core-host.md.

Red first, on base 1c44a786

The new test is in core/test/project-board-panels.test.js and goes through the real projectEndpoint, no call: stubs: pause through project-assistant-owner, read back through project-read, draw the panel, Save without touching it, then tick and Save. On the base it fails on the read:

not ok 3 - the settings panel reads the caller own pause back, and a Save that changes nothing resumes no digest
  error: |-
    the read answers the caller own record
    + actual - expected
    + undefined
    - true
# tests 9  # pass 8  # fail 1

The same test on the tip is green, and it fails again when the source change is reverted.

Verification at the tip 632c457fb68209fe5c55e1dc3aeb08b1708f8d5d

Ran:

  • TZ=UTC ARCH_DOCS_BASE=1c44a786 npm run verify on the committed tree (git status --porcelain empty): exit 0 — core 2254/2254; core lint 73 warnings, 0 errors; plugin lints 36 / 9 / 2 / 16 warnings, 0 errors; arch-docs: OK (13 changed file(s)); build-client --check green; ds-bot-patches check 10 patches apply cleanly in order and core/ equals ds-bot/ + patches/ds-bot/; plugins social 541, tree 127, timeline 135, workflow 336; .github/scripts 561; interop 37, live-e2e 24 — 0 failures everywhere. One earlier run of the same tree failed core/test/room-external.test.js ("a stop is asked for on the protocol before the signal", timed out waiting for the child); that file passes 13/13 twice on its own and the full run above is green.
  • node .github/scripts/changelog.mjs check: 15 fragments well formed.

Not run:

  • The smoke test: it needs a deepseek-harness checkout beside the repo, and this box has none. The change is two host functions and one client read; project-read's answer and the panel's box are covered by the new test through the real endpoint.

Checkpoint

{
  "pr": 1879,
  "claim": "Dev-3",
  "issue": 1845,
  "summary": "Project settings read project.assistant.off, which the host never writes, so a paused digest opened unticked and one Save sent off:false and resumed it. project-read now answers assistantMine { off, quiet } for the calling actor and the panel draws the box from it, so each owner sees only their own switch. setOwner writes the record and calls schedule-pause/schedule-resume only when the value changes, so a Save on an untouched row resumes nothing. The generated client bundle and patches, one changelog fragment and one line in each of the two subsystem docs come with it.",
  "files": [
    "core/src/host/store.js",
    "core/src/host/project-assistant.js",
    "core/src/client/project-board.js",
    "core/test/project-board-panels.test.js"
  ],
  "checks": {
    "ran": "TZ=UTC ARCH_DOCS_BASE=1c44a786 npm run verify; node .github/scripts/changelog.mjs check",
    "result": "green",
    "at": "632c457fb68209fe5c55e1dc3aeb08b1708f8d5d"
  },
  "next": "none — ready for review"
}

The panel read `project.assistant.off`, a field the host never writes: the opt-out lives
per owner on `project.assistant.owners[ownerId]`. A digest the owner paused therefore opened
unticked, and one Save on an unchanged row sent `off: false` and silently resumed it.

`project-read` now answers `assistantMine: { off, quiet }` for the calling actor, the panel
draws the box from it, and `setOwner` touches the record and the 09:00 task only when the
value actually changes.

Fixes ThinkFlowLab#1845
@Birfy

Birfy commented Oct 31, 2026

Copy link
Copy Markdown
Collaborator

Verdict: PASS at 632c457
Written-by: Reviewer
Attestation: 632c457 role=Reviewer

Ran at this tip:

$ cd p1879tip/core && TZ=UTC node --import ./test/harness-resolve.mjs --test test/project-board-panels.test.js
# tests 9  # pass 9  # fail 0
$ node -e '<wrote the three changed sources from base 1c44a786 over the tip tree>'
$ TZ=UTC node --import ./test/harness-resolve.mjs --test test/project-board-panels.test.js
# tests 9  # pass 8  # fail 1
$ node scripts/build-client.mjs --check
# exit 0
$ node scripts/ds-bot-patches.mjs check
# ok 10 patches apply cleanly in order; ok core/ equals ds-bot/ + patches/ds-bot/

Review points:

  • Red first: with the three changed sources (core/src/host/project-assistant.js, core/src/host/store.js, core/src/client/project-board.js) replaced by their 1c44a786 blobs, the new test the settings panel reads the caller own pause back, and a Save that changes nothing resumes no digest fails (8 pass / 1 fail). At the tip it is 9/9, and the rest of the file is untouched in outcome.
  • The fix reads the opt-out where the host writes it: setOwner stores owners[<id>].off, project-read now answers assistantMine: { off, quiet } for the calling actor (store.js), and the panel draws its checkbox from it (project-board.js). An absent Project keeps the old { project: null, canManage: false } shape.
  • setOwner calls schedule-pause/schedule-resume and rt.save only when off actually changes, so a Save on an untouched paused row can no longer resume the digest. quiet/zone writes keep their behaviour.
  • Generated files are consistent: build-client --check exit 0, ds-bot-patches check 10/10 with core/ equal to ds-bot/ + patches.
  • Range: 13 files — core/client.js, four core/ sources/tests, two subsystem docs, one changelog fragment, five generated patch mirrors. All inside the change described in the body; nothing unrelated.
  • Check-runs at this tip: tests-ok, merge-gate, risk tier, package, all plugin suites, ubuntu-latest · Node 24, judge, reviewed tip and agent-audience green. enqueue-guard red only because the tip carries no PASS yet — this comment supplies it.

@github-actions github-actions Bot added the pass label Oct 31, 2026
@Birfy Birfy added the agent-pr Pull request opened by an agent label Oct 31, 2026
@Birfy
Birfy added this pull request to the merge queue Oct 31, 2026
Merged via the queue into ThinkFlowLab:main with commit b1cc88b Oct 31, 2026
16 checks passed
@Birfy
Birfy deleted the dev/3-p230-assistant-off-readback branch October 31, 2026 01:31
@github-actions github-actions Bot removed the agent-pr Pull request opened by an agent label Oct 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Project settings shows "Pause the daily digest" unticked, and one Save silently resumes a digest the owner paused

2 participants