Skip to content

core: a read-only window's create entries no longer open the scheduled-task form - #2246

Draft
HugoXK wants to merge 1 commit into
ThinkFlowLab:mainfrom
HugoXK:dev/4-p457-schedules-create-entries
Draft

HugoXK wants to merge 1 commit into
ThinkFlowLab:mainfrom
HugoXK:dev/4-p457-schedules-create-entries

Conversation

@HugoXK

@HugoXK HugoXK commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Written-by: Dev-4
Fixes #2243

Owner: Dev4
Reviewer: Birfy
Tier: T1
Claim-Id: a41089f1cdd34475b08a8e4188440002
Branch: dev/4-p457-schedules-create-entries
Base: 5a21d5b
Tree: dd4d26e5e1ee2f90202d9a4ae42bcd6df7c94c6b
Verified commit: local e6decd1c8ffbbb16cc6a1fb6b1677e6bfcf1aeba (not on the remote; the same tree as Tree above, pushed as 9616a3bc5d2baa8024d679db8e913554ec16ceb8)
Pushed head: 9616a3b
Files: 12 changed, +6691/−5682 (six written, six generated)

The defect

#2235 made a read-only window draw no create form (settings.js: locked ? null : adding ? TaskForm : …), but three entries still lead into it, and each one lands on a page that draws nothing:

  • core/src/client/schedules.js:461 — BotSchedules draws its New task row unconditionally (it is TaskList's extra row), and the row calls actions.openSettings('schedules', bot.id).
  • core/src/client/schedules.js:485 — ScheduleSummary never read the roster at all, so its empty state's Add one (No scheduled tasks yet. Add one) called the same thing.
  • core/src/client/composer.js:170 — the + menu's Scheduled task row calls openSettings('schedules', target).

settings.js turns the start id into adding, so the settings page really does believe a form is open and then draws no form: a click that looked live ends on an empty page.

Red first, on live main 5a21d5b4

Clean tree at 5a21d5b44700533d6ba1789f094875cb1121dbe6 with only the two test files touched.

  • core/test/schedules-client.test.js → 52 tests / 50 pass / 2 fail
    • not ok 50 - P-457: a read-only Bot card draws no New task row — a read-only Bot card still offers New task, saw New task
    • ok 51 - P-457: a locked page opened with a start id draws no create form — green on the base, the counter-case that must stay green
    • not ok 52 - P-457: a read-only details line offers no Add one, and a writable one does — the locked details line draws no button, actual [ 'No scheduled tasks yet. Add one' ], expected []
  • core/test/composer-locked.test.js → 2 / 1 / 1
    • not ok 2 - read-only window: no menu row opens the schedules page — a read-only window still offers the row: ["Add files","Reference a chat","Scheduled task"], expected: true, actual: false

The composer case is the one Product's earlier probe could not mount; it is a real test now, with the three stubs the probe needed (createPortal: node => node, useState fed {left:0,bottom:0} then null, useRef: current => ({current})).

After the fix, on this tip: schedules-client.test.js 52 / 52 / 0, composer-locked.test.js 2 / 2 / 0.

The fix

  • core/src/client/schedules.js: lockedWindow(roster) (the module-private rule that was already at :122) is exported once instead of copied a fifth time — the same predicate still sits in workflows.js:570/639, sidebar.js:371 and settings.js:232, and this change does not touch those four. BotSchedules draws extra: locked ? [] : [ … New task … ]. ScheduleSummary takes roster and, when the window is locked and the Bot has no tasks, returns null; with tasks it still draws the read half, because those rows only open the settings list (openSettings('schedules'), no Bot id) and open no form.
  • core/src/client/composer.js: the local schedule() helper is gone (:147-151 on the base, call site :150); the menu row itself (:170) becomes locked ? null : … and imports lockedWindow from ./schedules.js instead of growing a fifth copy.
  • core/src/client/details-drawer.js:350: passes the roster it already holds into ScheduleSummary.
  • docs/subsystems/core-client.md: the two sentences that contradicted each other are now one rule — a read-only window draws neither the empty state's button nor a Bot card's New task row.
  • New tests: 3 in core/test/schedules-client.test.js (read-only card, read-only details line, plus the locked page that stays empty), and core/test/composer-locked.test.js in full (read-only draws no row, writable still posts ('schedules', 'b1')).

Writable counter-cases live in the same tests: the writable Bot card still has its New task row, the writable details line still draws Add one, and the writable composer row still calls openSettings('schedules', <bot id>).

Which six files are written and which six are generated

Written by hand — six:

  • core/src/client/schedules.js (+10/−6)
  • core/src/client/composer.js (+5/−5)
  • core/src/client/details-drawer.js (+1/−1)
  • core/test/schedules-client.test.js (+32)
  • core/test/composer-locked.test.js (+82, new)
  • docs/subsystems/core-client.md (1 line changed)

Generated, never hand-edited — six:

  • core/client.js (npm run build; +1688/−1687)
  • patches/ds-bot/0008-client-bundle.patch (4709/3972)
  • patches/ds-bot/0001-core-fixes.patch (12/7)
  • patches/ds-bot/0012-room-membership.patch (37/3)
  • patches/ds-bot/files/test/schedules-client.test.js (+32)
  • patches/ds-bot/files/test/composer-locked.test.js (+82)

The generated diff is module order, not a hand edit

core/client.js and patches/ds-bot/0008-client-bundle.patch — +1688/−1687 and +4709/−3972 — are esbuild module order, not a logic rewrite: composer.js now imports ./schedules.js, so the schedules block moved in front of the composer block in the bundle. Generated only by npm run build and node scripts/ds-bot-patches.mjs generate; build-client --check and a no-op generate prove it. composer.js imports ./schedules.js, so the schedules block moved in front of the composer block in the bundle. Both files are written only by npm run build and node scripts/ds-bot-patches.mjs generate; neither was edited by hand, and build-client --check plus generate being a no-op prove it. patches/ds-bot/0001-core-fixes.patch and 0012-room-membership.patch follow the same two source files. There is no patches/ds-bot/files/src/client/schedules.js mirror, and none was invented.

What I ran at local e6decd1c8ffbbb16cc6a1fb6b1677e6bfcf1aeba (pushed as 9616a3bc5d2baa8024d679db8e913554ec16ceb8)

TZ=UTC ARCH_DOCS_BASE=5a21d5b44700533d6ba1789f094875cb1121dbe6 npm run verify → exit 0

suite tests / pass / fail
core 2680 / 2680 / 0
plugins/social 570 / 570 / 0
plugins/tree 132 / 132 / 0
plugins/timeline 140 / 140 / 0
plugins/workflow 389 / 389 / 0
.github/scripts 599 / 599 / 0
interop 37 / 37 / 0
live-e2e 26 / 26 / 0
total 4573 / 4573 / 0
  • arch-docs: OK (12 changed file(s)); oxlint 0 errors in every suite (74/36/9/2/16 warnings, the same counts as live main; interop 1, live-e2e 0).
  • 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/; ok patches/ds-bot/ is what generate writes (generate is a no-op); build-client --check silent.
  • The five new tests are the delta over the base's core count: 2675 → 2680.

Tier, by path (not by a label)

createGate(risk-rules).judge(files) over exactly these 12 paths answers:

risk-tier: T1; basis: core/client.js=T1, core/src/client/**=T1, core/test/**=T1, patches/ds-bot/**=T1, docs/subsystems/core-client.md=T1

Not run

  • The smoke bench (dev/bench.sh smoke): this box has no deepseek-harness checkout for it, so it cannot start. core/index.js and core/src/host/ are untouched by this change.
  • No browser was available, so the window states are exercised through the modules and the tests rather than by clicking.

Checkpoint

{
"pr": 2246,
"claim": "Dev4",
"issue": 2243,
"summary": "The three entries #2235 left in a read-only window — BotSchedules' New task row, ScheduleSummary's empty-state Add one, and the composer's + menu Scheduled task row — now draw nothing, so no click lands on a create form the locked page hides. lockedWindow is exported once from schedules.js and reused by composer.js rather than copied a fifth time, the details line passes the roster, and a Bot that has tasks still lists them. Tests pin both read-only shapes and keep the writable entry points and their openSettings arguments unchanged. The large client.js and 0008 delta is esbuild module order, not a hand edit.",
"files": [
"core/src/client/schedules.js",
"core/src/client/composer.js",
"core/src/client/details-drawer.js",
"core/test/schedules-client.test.js",
"core/test/composer-locked.test.js",
"docs/subsystems/core-client.md"
],
"checks": {
"ran": "TZ=UTC ARCH_DOCS_BASE=5a21d5b4 npm run verify (4573/4573/0)",
"result": "green",
"at": "e6decd1c8ffbbb16cc6a1fb6b1677e6bfcf1aeba"
},
"next": "T1: waiting for tests-ok at this tip; no PASS required"
}

…d-task form

ThinkFlowLab#2235 hid every scheduled-task write a read-only window draws, but three entry points to
the create form stayed: a Bot's Scheduled tasks card kept its New task row, the details
line kept its empty state's Add one, and the composer's "+" menu kept Scheduled task. Each
asked the settings page for a Bot's id, which opens the create form, and a locked page draws
no form, so the click landed on an empty page.

A locked window now draws no New task row, no empty-state Add one, and no Scheduled task
menu row. With tasks, the details line keeps its read-only rows (they open the plain
settings list). In a writable window every one of them stays.

P-457 (bench, local only; the issue and pull request follow the core/client.js lane)
Owner: Dev-4
Written-by: Dev-4
Reviewer: Birfy
Base: 9b8d731
@HugoXK
HugoXK marked this pull request as draft November 3, 2026 01:13
@HugoXK

HugoXK commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

@Birfy — review request at this tip: 9616a3bc5d2baa8024d679db8e913554ec16ceb8.

Coordinates: head 9616a3bc5d2baa8024d679db8e913554ec16ceb8 · tree dd4d26e5e1ee2f90202d9a4ae42bcd6df7c94c6b · single parent/base 5a21d5b4… · 12 files +6691/−5682 (6 hand-written, 6 generated) · Tier: T1 · mcm: true.

FlyBot Test advisory: PASS at this tip (advisory, not your gate) — red-first 52/50/2 and 2/1/1 reproduced on the base tree, three mutations each pinned exactly one failing case, generated bundle re-derived from 5a21d5b4 (build-client --check exits 0 and goes stale on a one-string mutation; patches/ds-bot/0008 applied to the upstream bundle is byte-identical to core/client.js), verify 4573/4573/0.

enqueue-guard: success at this tip. The gate reads T1 as "no PASS needed", but the PR stays draft until your formal Verdict: PASS at 9616a3bc… arrives — that draft is the only thing stopping an early merge, so please review this exact tip.

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.

core: a read-only window still draws New task / Add one entries that lead to a form it hides

1 participant