Skip to content

fix(delivery): print one as-of time, and one CI share (#1244) - #1270

Merged
Birfy merged 1 commit into
mainfrom
dev/fix/1244-delivery-header
Oct 26, 2026
Merged

Birfy merged 1 commit into
mainfrom
dev/fix/1244-delivery-header

Conversation

@Birfy

@Birfy Birfy commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #1244

Owner: Dev4
Reviewer: Reviewer
Written-by: Dev4
Tip SHA: 2819d478fac4b5309bc9ae80f856f354b1e19e2e

Reproduce

Two cosmetic defects Triage listed on #1244 (comment 6409459951), both present at 98528d9f:

  • ① a partial day printed the same instant twice. DeliveryHeader rendered timeOf(payload.asOf) at the as-of position and the hint then rendered clockOf(payload.asOf) again, so the line read as of Oct 25, 04:00 AM · today is partial · as of 04:00 AM — and when the two clocks disagree the reader sees two different times for one fact.
  • ② the CI row and the 7-day line beside it read one day two ways. With the fixture { ci: { failed: 1, counted: 0, total: 5 } } the row printed — while dayValue() drew 0.2 on that day's point, because share() divided by counted only and dayValue() already falls back to total.
$ node -e "…metricRows({today:{ci:{failed:1,counted:0,total:5}}})…"   # CI row: '—'   chart dayValue: 0.2
$ node -e "…render DeliveryHeader with daily[today].partial=true…"     # 'as of … · today is partial · as of …'

What changed

  • core/src/client/delivery-view.js: share() divides by counted when the day has one and by total otherwise — the denominator dayValue() draws that point from — and answers — only when the day has no runs at all. DeliveryHeader computes partial once, clocks the as-of time with clockOf while today is running, and the hint is the bare t('today is partial'), so one time is printed once.
  • core/src/client/i18n.js: zh becomes 'today is partial': '今天为部分日', losing the second 截至 {time}.
  • core/test/delivery-view.test.js gains the two-time test and a zh render test; core/test/delivery-chart.test.js gains the row-vs-line test. The zh test builds its own esbuild bundle from stdin sharing one i18n instance, so it does not touch the existing harness.
  • docs/subsystems/core-client.md: the delivery-view.js row states the single time and the shared denominator, the delivery-chart.js row names which denominator the row now reads.
  • changelog.d/1244-delivery-header.fixed.md; core/client.js rebuilt with build-client.mjs; patches/ds-bot/0001 + 0008 and the three files/ mirrors regenerated by generate.

What I ran

At 2819d478fac4b5309bc9ae80f856f354b1e19e2e, on a tree whose base equals live main 779d2b38 (base tree 5550eab8 = the API's tree for that commit):

$ node scripts/ds-bot-patches.mjs check
ok   ds-bot/ = Fei2411/DeepSeek-Bot@2b10c70 (tree 5834c00, v0.1.5)
ok   10 patches apply cleanly in order
ok   core/ equals ds-bot/ + patches/ds-bot/

$ cd core && TZ=UTC node --import ./test/harness-resolve.mjs --test --test-concurrency=1 \
    test/delivery-board.test.js test/delivery-view.test.js test/delivery-chart.test.js \
    test/delivery-repo.test.js test/delivery-write-failure.test.js test/kanban.test.js \
    test/i18n.test.js test/client-bundle.test.js test/home-lock.test.js test/install.test.js
# tests 116 / pass 116 / fail 0

$ node scripts/build-client.mjs --check                       # exit 0
$ ARCH_DOCS_BASE=79fe8a5 node scripts/lint.mjs                # oxlint 0 errors (62 pre-existing warnings); arch-docs: OK (12 changed file(s))
$ node .github/scripts/changelog.mjs check                    # 9 fragment(s) well formed
$ node .github/scripts/check-mojibake.mjs --check              # 0 occurrences of U+FFFD in 1090 text files
$ cmp core/src/client/delivery-view.js patches/ds-bot/files/src/client/delivery-view.js   # same bytes

Red without the source change

Each knife reverts one fix in core/src/client/delivery-view.js, runs delivery-view.test.js, and the tree is restored before the next one:

knife reverted to red
A share() reading counted only not ok 4 - a day the host could only count by total reads the same share in the row as on the line (#1244) — expected: '20%' actual: '—'
B the old two-time header not ok 5 - a partial day prints its time once, in the task zone, instead of twice (#1244) — expected: 1 actual: 2

After each restore: delivery-view.test.js 21/21 green, working tree clean.

Not run

  • Full npm test on this box: the whole suite hits spawn … EAGAIN / pthread_create: Resource temporarily unavailable; CI on Node 24 is the reference.
  • npm run verify as one command, for the same reason — its steps are the individual commands above.
  • The smoke bench, which AGENTS.md asks for on index.js / src/host/ changes: this change is client-side only.

Risk

  • A day with runs but counted: 0 now shows a percentage computed from total. That is exactly the number its point is drawn from, so the two halves of one day cannot disagree; a day with no runs keeps —, so "unknown" never reads as 0%.
  • The zh sentence loses 截至 {time}. Nothing else consumed that string (one definition, one call site), and the new test pins the zh rendering.
  • core/client.js and the patch files are generated, so their diff is larger than the source delta; check proves they are the generator's output, not hand edits.

Checkpoint

{
  "pr": 1270,
  "claim": "Dev4",
  "issue": 1244,
  "summary": "A partial day's as-of line now prints one time, in the task zone, with the bare hint today is partial (zh 今天为部分日) instead of a second clock rendering of the same instant. The CI row divides by counted when the day has one and by total otherwise, the denominator the 7-day line already draws, so a day the host could only count by total reads the same share in the row and on the line; a day with no runs still reads a dash. Both live in core/src/client/delivery-view.js with one i18n string, plus two new view tests and one chart test.",
  "files": [
    "core/src/client/delivery-view.js",
    "core/src/client/i18n.js",
    "core/test/delivery-view.test.js",
    "core/test/delivery-chart.test.js",
    "docs/subsystems/core-client.md",
    "changelog.d/1244-delivery-header.fixed.md"
  ],
  "checks": {
    "ran": "on 2819d478fac4b5309bc9ae80f856f354b1e19e2e (base 779d2b38): node scripts/ds-bot-patches.mjs check; node core/scripts/build-client.mjs --check; ten core suites (116 tests); arch-docs; oxlint; changelog; mojibake; two knives",
    "result": "green",
    "at": "2819d478fac4b5309bc9ae80f856f354b1e19e2e"
  },
  "next": "none — ready for review"
}

@Birfy

Birfy commented Oct 26, 2026

Copy link
Copy Markdown
Collaborator Author

Why checkpoint.files has 6 entries while changed_files is 12

The rule I followed: files lists the files a reviewer must open — the six I hand-edited. The other six are output of this repo's own scripts, and check / build-client --check re-derive them from those sources. 6 authored + 6 generated = 12 in pulls/1270/files. No file of this PR is outside the diff.

The six listed (authored)

  1. core/src/client/delivery-view.js
  2. core/src/client/i18n.js
  3. core/test/delivery-view.test.js
  4. core/test/delivery-chart.test.js
  5. docs/subsystems/core-client.md
  6. changelog.d/1244-delivery-header.fixed.md

The six not listed (generated, one command each)

path produced by
core/client.js node scripts/build-client.mjs (bundle of core/src/client/**)
patches/ds-bot/0001-core-fixes.patch node scripts/ds-bot-patches.mjs generate
patches/ds-bot/0008-client-bundle.patch node scripts/ds-bot-patches.mjs generate
patches/ds-bot/files/src/client/delivery-view.js node scripts/ds-bot-patches.mjs generate
patches/ds-bot/files/test/delivery-view.test.js node scripts/ds-bot-patches.mjs generate
patches/ds-bot/files/test/delivery-chart.test.js node scripts/ds-bot-patches.mjs generate

A note so nobody hunts for a missing mirror: patches/ds-bot/files/ mirrors a fixed subset of client files and i18n.js is not in it, so the i18n change appears only in core/src/client/i18n.js and as a hunk inside 0001-core-fixes.patch — not as a separate files/ entry.

Why this is auditable rather than a shortcut

ok   ds-bot/ = Fei2411/DeepSeek-Bot@2b10c70 (tree 5834c00, v0.1.5)
ok   10 patches apply cleanly in order
ok   core/ equals ds-bot/ + patches/ds-bot/

node scripts/build-client.mjs --check → exit 0, and cmp core/src/client/delivery-view.js patches/ds-bot/files/src/client/delivery-view.js → same bytes. So the six generated entries hold no decision a reviewer can act on: if the sources are right the script output is right, and the checks fail loudly if it is not.

Why the guard accepts it: .github/scripts/enqueue-rules.mjs:246-252 caps files at 1–12 and validates only listed.some((f) => changed.has(f)) — "the 1-12 files a reviewer should open first", a pointing list, not an exhaustive manifest. All six listed paths are in this PR's diff, so enqueue-guard passes without the generated six; listing all 12 would also pass, but would point a reviewer at script output instead of at the change.

No commit pushed, tip stays 30d555fb3868597a35b6f32255e54cad2d5a4726, no label touched.

The header printed the time twice on a partial day — once from the local
clock and once from the task zone — and the CI row read '—' on a day whose
runs the host could only count by their total, while the 7-day line beside
it drew a point from that same total. The hint now follows the single time,
and the row uses the denominator the chart already draws.
@Birfy
Birfy force-pushed the dev/fix/1244-delivery-header branch from 30d555f to 2819d47 Compare October 26, 2026 09:55
@Birfy
Birfy added this pull request to the merge queue Oct 26, 2026
Merged via the queue into main with commit 4095e13 Oct 26, 2026
12 of 13 checks passed
@Birfy
Birfy deleted the dev/fix/1244-delivery-header branch October 26, 2026 10:00
@Birfy Birfy removed the agent-pr Pull request opened by an agent label Oct 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Delivery header: the as-of line repeats its own time on a partial day, and the CI share disagrees with the chart beside it

1 participant