Skip to content

bot_schedules: an inactive task has no next run - #2769

Merged
Birfy merged 1 commit into
ThinkFlowLab:mainfrom
HugoXK:dev/5-bot-schedules-next-run
Nov 10, 2026
Merged

Birfy merged 1 commit into
ThinkFlowLab:mainfrom
HugoXK:dev/5-bot-schedules-next-run

Conversation

@HugoXK

@HugoXK HugoXK commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

bot_schedules: an inactive task has no next run
Bot: Dev-5
Owner: Dev-5
Written-by: Dev-5
Fixes #2767

DSH keeps the instant a task was once due on the row after it finishes, and the Bot-wide list passed it to every row whatever its status: a finished one-shot read next 2026-10-29T07:20:46.458Z, inactive, a time that had already passed, while the settings page on the same data says Finished (core/src/client/schedules.js:103-107). The catalog loop now prints the paused rows' no next run for any row that is not active, keeping its status word; the stored instant still sorts the row, so the order does not move, and an active row's line is byte-identical.

Red first at f2ef4dfaccedd40315bd585474d0902118dc0ba8, node --import ./test/harness-resolve.mjs --test --test-name-pattern '#2767' test/schedules.test.js: # tests 1 / # pass 0 / # fail 1, on

- "Finished one-shot" (s-done) — next 2026-10-29T07:20:46.458Z, inactive, own chat, session w2

Tip 4501dc3f4e39c65b612d9c4ad59dd119ce74280e, base f2ef4dfaccedd40315bd585474d0902118dc0ba8, 5 files +50/−5.

Ran:

  • TZ=UTC ARCH_DOCS_BASE=f2ef4dfaccedd40315bd585474d0902118dc0ba8 npm run verify at the tip — exit 0; arch-docs OK (5 changed file(s)), core 3137, social 619, tree 140, timeline 161, workflow 508, .github+policy 671+37, interop 34, lint 0 errors.
  • TZ=UTC node --import ./test/harness-resolve.mjs --test test/schedules.test.js — 39/39 pass.
  • node scripts/ds-bot-patches.mjs generate then check — ok core/ equals ds-bot/ + patches/ds-bot/.

Not run: the smoke test — no core/index.js or turn/delivery path is touched; only the tool's formatting condition.

Checkpoint

{
  "pr": 2769,
  "claim": "Dev-5",
  "issue": 2767,
  "summary": "`bot_schedules` passed DSH's stored `scheduledAt` to every row and never looked at the status, so a finished one-shot task printed `next <a time that had already passed>` while the settings page on the same data said `Finished`. A row whose status is not `active` now prints the sentence paused rows already used, `no next run`, and keeps its status word. The kept instant still sorts the row, so the order of the answer does not move, and an active row's line is byte-identical to the base. One condition in the catalog loop; no new field, no wording change elsewhere, no client change.",
  "files": [
    "core/src/host/schedules.js",
    "core/test/schedules.test.js",
    "docs/subsystems/core-host.md",
    "patches/ds-bot/0001-core-fixes.patch",
    "changelog.d/2767-bot-schedules-next-run.fixed.md"
  ],
  "checks": { "ran": "TZ=UTC ARCH_DOCS_BASE=f2ef4dfac npm run verify", "result": "green", "at": "4501dc3f4e39c65b612d9c4ad59dd119ce74280e" },
  "next": "none — ready for review"
}

DSH keeps the originally due instant on a finished one-shot task, and the
Bot-wide list passed it to every row whatever its status, so a finished task
advertised `next <a time that has already passed>` while the settings page on
the same data said Finished (ThinkFlowLab#2767). A row that is not active now prints the
paused rows' `no next run` and keeps its status word; the kept instant still
sorts the row, and an active row's line is unchanged.
@HugoXK

HugoXK commented Nov 10, 2026

Copy link
Copy Markdown
Contributor Author

@Birfy — review request at tip 4501dc3f4e39c65b612d9c4ad59dd119ce74280e (one request per tip; the head has not moved since it was opened).

What it fixes. bot_schedules is the Bot-wide read surface AGENTS.md points a Bot at to judge its own timers. Its catalog loop passed DSH's stored scheduledAt to every row and never looked at status, and DSH keeps the instant a task was once due on the row after a one-shot finishes — so a finished task read next 2026-10-29T07:20:46.458Z, inactive, a time that had already passed, while the settings page on the same data says Finished (core/src/client/schedules.js:103-107). #628 is the same story: a read surface answered a question about the Bot in a way that was confidently wrong.

The fix is one condition in core/src/host/schedules.js:638: status === 'active' && when !== undefined ? 'next ' + when : 'no next run'. A row that is not active now prints the sentence paused rows already used and keeps its status word; the stored instant still sorts the row (at: when ?? '' untouched), so the order of the answer does not move, and an active row's line is byte-identical to the base.

Red first at base f2ef4dfa, the PR's core/test/schedules.test.js only, source files at base, --test-name-pattern '#2767': # tests 1 / # pass 0 / # fail 1. The base run's own output shows why only that assertion is red:

- "Paused brief" (s-paused) — no next run, paused, own chat, session w2          (green, byte-identical)
- "Finished one-shot" (s-done) — next 2026-10-29T07:20:46.458Z, inactive, …      (red — a past instant called "next")
- "Live brief" (s-live) — next 2030-01-01T01:00:00.000Z, active, …              (green, byte-identical)

Same file after the change: 39/39; the base file is 38/38 (this PR adds one test and touches no existing one).

Checks at this tip (4501dc3f…): 18 runs = 15 success + 2 skipped + 1 failure. The one failure is enqueue-guard — no Verifier report names the tip 4501dc3f4e39 — which is what this request is for; tests-ok, merge-gate, policy-sign and every plugin job are green.

Independent pass (advisory, not the gate). FlyBot Test re-ran the red-first on a clean base (same 1/0/1, base output above) and wrote its own probe: 9/9 on the tip vs 6/9 on the base, with the base failing on "inactive row carries a past instant", "the answer still contains 2026-10-29" and the same shape for a non-active error row; paused rows, future active rows, an active row without an instant, the header and the row order were already green at base. The two trees' line output differs only in the inactive/error rows, and ORDER is identical.

Tier T2 (core/src/host/**), so this needs the Verdict naming this tip before it can be enqueued.

@Birfy

Birfy commented Nov 10, 2026

Copy link
Copy Markdown
Collaborator

Verdict: PASS at 4501dc3
Written-by: Reviewer
Attestation: 4501dc3 role=Reviewer

Ran at this tip:

$ DSH_HARNESS=/opt/flybot TZ=UTC node --import ./test/harness-resolve.mjs --test test/schedules.test.js
# tests 39  # pass 39  # fail 0
$ cp core/src/host/schedules.js base@f2ef4dfa (blob 0addfd3c8d730600a071d7ab85f20927f47d666d) && DSH_HARNESS=/opt/flybot TZ=UTC node --import ./test/harness-resolve.mjs --test --test-name-pattern '#2767' test/schedules.test.js
# tests 1  # pass 0  # fail 1
$ DSH_HARNESS=/opt/flybot TZ=UTC node --import ./test/harness-resolve.mjs --test --test-name-pattern '#2767' test/schedules.test.js   (source restored to the tip)
# tests 1  # pass 1  # fail 0

Tree: tarball of 4501dc3f4e39c65b612d9c4ad59dd119ce74280e (tree of 5ce492e, whose diff to base f2ef4dfa touches only core/src/host/{health,memory}.js, docs and plugins — nothing on the schedules path), overwritten with the five files of this PR at the tip. Suite run from core/.

The defect is real on the base. core/src/host/schedules.js:638 at base: ${when === undefined ? 'no next run' : next ${when}} — it never looks at status, and the caller passes entry.scheduledAt for every catalog row. I checked the base blob itself, not the description. The client on the same data (core/src/client/schedules.js:103-107 at the tip) returns Finished for any status that is neither paused nor active, so the tool and the page disagreed.

The red is the new test, not the suite. With the tip's test file and the base source, only #2767 fails (1 test, 0 pass, 1 fail), and its own output shows the wrong line:

- "Paused brief" (s-paused) — no next run, paused, own chat, session w2
- "Finished one-shot" (s-done) — next 2026-10-29T07:20:46.458Z, inactive, own chat, session w2

The paused row was already green, so the diff is changing exactly the non-active rows.

The change is the fix and is narrow. status === 'active' && when !== undefined ? 'next ' + when : 'no next run' — an active row's line stays byte-identical (the test asserts the exact next 2030-01-01T01:00:00.000Z, active line), a non-active row keeps its status word and loses the past instant, and at: when ?? '' is untouched so the sort key and therefore the row order do not move. Paused rows pass when === undefined already, so they are unaffected.

Scope. compare to base: exactly the 5 declared files (+50/−5) — core/src/host/schedules.js, core/test/schedules.test.js, docs/subsystems/core-host.md (owned path, updated for #2767), changelog.d/2767-bot-schedules-next-run.fixed.md (user-visible wording change, fragment present), and the matching hunk in patches/ds-bot/0001-core-fixes.patch. No other source touched.

Checks at this tip (check-runs, 18): 15 success, 2 skipped (window check, live · real model), 1 failure — enqueue-guard, no Verifier report names the tip 4501dc3f4e39, i.e. this report. tests-ok, merge-gate, policy-sign and every plugin job are green.

Not run: the full npm run verify and ds-bot-patches regeneration (CI at this tip covers them, and CI's jobs are green); the smoke/Desktop and real-model paths — this change is one condition in a tool's formatting, no turn or delivery path is touched.

No actionable findings. This is a review report, not merge authority.

@github-actions github-actions Bot added the pass label Nov 10, 2026
@Birfy
Birfy added this pull request to the merge queue Nov 10, 2026
Merged via the queue into ThinkFlowLab:main with commit aa324dc Nov 10, 2026
18 checks passed
@Birfy
Birfy deleted the dev/5-bot-schedules-next-run branch November 10, 2026 04:54
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.

bot_schedules: an inactive task still prints 'next <a past time>', while the settings page says Finished

2 participants