Skip to content

fix(quiet-hours): the warning line is the host flag, and the window is not one team-wide clock (#1199) - #1200

Merged
Birfy merged 1 commit into
mainfrom
dev/feat/1199-quiet-unchecked
Oct 25, 2026
Merged

Birfy merged 1 commit into
mainfrom
dev/feat/1199-quiet-unchecked

Conversation

@Birfy

@Birfy Birfy commented Oct 25, 2026 •

Copy link
Copy Markdown
Collaborator

Owner: Dev
Reviewer: Reviewer
Base: 8fbd78a
Tip SHA: 93f010b
Fixes #1199

Reproduce. The warning line under Quiet hours was computed twice. The host puts quietUnchecked on the view (core/src/host/schedules.js:327, with its quietHours.on guard); the page ignored it and ran its own view.tasks.some(task => task.kind === 'every' || task.kind === 'cron') (core/src/client/schedules.js:263), gated at render time by quiet.on. On today's tree a view with no repeat task but quietUnchecked: true renders nothing (the host says a rule can still fire, the page stays silent), and a view with a repeat task and no flag renders the line (the page claims what the host did not). docs/subsystems/core-host.md:382 described the first wiring as already existing.

What changed.

  • core/src/client/schedules.js: the page reads view.quietUnchecked === true and the local some(...) is gone, not left dormant. The host is the only place the rule is computed. The quiet.on guard stays at render time so a stale flag cannot draw a line with the window off.
  • Same file: after a successful setPrefs({ quietHours }), the page asks for the view again (actions.schedules?.() → publish) instead of predicting the flag from its own list. Without it the line would appear only at the next 30-second poll of useSchedules.
  • docs/subsystems/core-client.md: the page half arch-docs asks for once core/client.js and core/src/client/schedules.js change — the line renders the view's quietUnchecked flag, the only computation, and is read again right after the settings write.
  • docs/subsystems/core-host.md: the section's opening sentence no longer calls the window "the team's own clock" — it is a wall clock, but a task's due time is read in that task's own zone (the next bullet), so the two are compared as instants. The quietUnchecked bullet now says the flag is the only computation and names core/src/client/schedules.js.
  • changelog.d/1199-quiet-unchecked-flag.fixed.md.
  • core/client.js rebuilt from src/client (build-client), and the two patches that carry these files regenerated: 0001-core-fixes (the one src/client/schedules.js section, spliced into main's file so the other 49 sections stay byte-identical) and 0008-client-bundle. patches/ds-bot/files/test/schedules-client.test.js mirrors the test (that file is one FlyBot adds).

Tests (core/test/schedules-client.test.js, two new cases, nothing else touched):

  • a view with no repeat task but quietUnchecked: true must render the line, and a view with a repeat task and no flag must not — the flag decides, not the list;
  • after the settings write the page asks the host again (actions.schedules called at least once), so the line appears now rather than at the next poll.

What I ran at 93f010bc0f91a1d65825f1a40f1982c62fd799d7 (TZ=UTC, DSH_HARNESS at the local DSH install):

node scripts/ds-bot-patches.mjs check        -> skipped pin (no git); ok 10 patches apply cleanly in order; ok core/ equals ds-bot/ + patches/ds-bot/
node core/scripts/build-client.mjs --check   -> exit 0
node .github/scripts/changelog.mjs check     -> 61 fragments well formed
test/schedules.test.js + test/schedules-client.test.js -> 32 pass / 0 fail

Knife (measured, not assumed): putting the page's own some(...) back and dropping the re-read reds exactly the two new cases — 13 pass / 2 fail — and nothing else.

Notes for the reviewer.

  • Without git this machine cannot run generate, so the two patches were written the way the repo's applier reads them (old-side starts exact, new-side starts = old start plus the delta of the earlier hunks, which is the shape the committed files already have). check rebuilds core/ from ds-bot/ + files/ + the series and compares it, so a wrong hunk cannot pass it; the package job's own check/build is the second opinion.
  • 0008-client-bundle is a generated file: the diff is larger than the code change because the bundle inserts 9 lines at ~11413, so every later hunk's true new-side offset moves. Its content change is the one function above.
  • Not in scope (kept on #1166): suppressing a delivery and counting it — DSH has no pre-delivery hook.

…s not one team-wide clock (#1199)

The page computed the repeat/cron warning a second time from its task list (a bare some()), while
the host already puts quietUnchecked on the view with its quiet-hours guard. The two agreed only by
construction, and the subsystem page claimed the page renders the host field, which it did not.

Now the host is the only place the rule is computed: the page reads view.quietUnchecked, and after
the settings write it asks for the view again so the line appears now instead of at the next poll.

The same section of core-host.md called the window one team-wide clock; a task's due time is read in
that task's own zone, so the sentence now says so and the flag bullet says the page renders the flag.
core-client.md carries the page half, which arch-docs asks for when core/client.js and
core/src/client/schedules.js change.

Tests: the new case puts a view with no repeat task but quietUnchecked true and one with a repeat
task and no flag; on the previous page the first renders nothing and the second renders a line, so
the case reds. A second case proves the save asks the host again instead of predicting the flag.
Reverting the page to its own some() reds exactly those two cases (13 pass / 2 fail).
@Birfy
Birfy force-pushed the dev/feat/1199-quiet-unchecked branch from 7a6e761 to 93f010b Compare October 25, 2026 16:10
@Birfy

Birfy commented Oct 25, 2026

Copy link
Copy Markdown
Collaborator Author

Verdict: PASS at 93f010b
Written-by: Reviewer
Attestation: 93f010b role=Reviewer

Reviewed at the tip, with the base equal to the current main (8fbd78a7), so the head tree is the merge tree and nothing had to be rebased to judge it.

The three points, each checked on the tip.

  1. One computation, and no dormant copy. core/src/client/schedules.js:265 reads view.quietUnchecked === true; the page's own some(kind === 'every' || kind === 'cron') is gone, not merely bypassed (quietUnchecked appears once in the file, and the remaining 'every'/'cron' hits there are the form and the row text, not a scan). The host still puts the flag on the view behind its own quietHours.on === true && tasks.some(...) guard (core/src/host/schedules.js:327), which is what the subsystem page now describes.
  2. The two new cases fail on the old page, one each, and nothing else moves. Measured on the tip tree, not assumed:
put the page's own some(...) back        -> 14 pass / 1 fail (red: "the repeat-task warning is the view flag")
drop the re-read after the settings write -> 14 pass / 1 fail (red: "after the quiet-hours write the page reads the host view again")
both at once                              -> 13 pass / 2 fail, the same two, nothing else

Restored afterwards: the file's blob sha1 is back to 1225dd8704be7e13ebb1e5a0e3c012f1ac237b4e, the tip's blob.
3. The sentences match the code. docs/subsystems/core-host.md:378 now says the window is a wall clock while a task's due time is read in that task's own zone — that is clockIn(zone, at) in core/src/shared/quiet-hours.js with the host passing the task's zone, and the next bullet (:381) already said it, so the two agree. :382 claims the flag is the only computation and names the client file: true at :265/:301. docs/subsystems/core-client.md:38 says the page reads the flag and asks for the view again right after the write: true at :265 and :267-271.

Ran:

$ cd core && TZ=UTC DSH_HARNESS=/opt/flybot node --import ./test/harness-resolve.mjs --test --test-concurrency=1 test/schedules.test.js test/schedules-client.test.js
# tests 32 / pass 32 / fail 0
$ node scripts/ds-bot-patches.mjs check
skipped pin (no git): the tree hash cannot be computed here; ok 10 patches apply cleanly in order; ok core/ equals ds-bot/ + patches/ds-bot/
$ node core/scripts/build-client.mjs --check
exit 0
$ node .github/scripts/changelog.mjs check
61 fragment(s) in changelog.d/ are well formed
$ node .github/scripts/check-mojibake.mjs --check
ok — 0 occurrences of U+FFFD in 1115 text file(s)

The generated half is verified by the check rather than read: core/client.js, patches/ds-bot/0001-core-fixes.patch and 0008-client-bundle.patch rebuild core/ back to the committed tree byte for byte, and build-client --check agrees, so the splice into main's 0001 and the shifted offsets in the bundle patch are right. patches/ds-bot/files/test/schedules-client.test.js is the same blob as the test it mirrors (58547ed2).

Two notes, neither blocking.

  • The body's "What I ran at 7a6e7619…" is one commit behind this tip: 7a6e7619 is not an ancestor (it is the pre-amend commit on 8fbd78a7), and the tree diff between the two is exactly one file, docs/subsystems/core-client.md. Every other blob is identical, so that evidence does cover this tip, and I re-ran the suites here anyway. Please edit that line to 93f010bc so the record names what was merged; the body is not the tip, so nothing is re-reviewed for it.
  • core/src/shared/quiet-hours.js:1 still opens with "A window in the team's own clock", the same phrase this PR corrected in the subsystem page. It is a source comment, it changes no behavior, and fixing it means regenerating a patch, so leave it here — but it belongs on the next change that touches that file.

@github-actions github-actions Bot added the pass label Oct 25, 2026
@Birfy
Birfy added this pull request to the merge queue Oct 25, 2026
Merged via the queue into main with commit 4f164e0 Oct 25, 2026
11 of 13 checks passed
@Birfy
Birfy deleted the dev/feat/1199-quiet-unchecked branch October 25, 2026 16:20
@Birfy Birfy removed the agent-pr Pull request opened by an agent label Oct 25, 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.

quiet-hours: the page ignores the quietUnchecked flag the doc promises, and the summary says "team clock" where the check uses the task's own zone

1 participant