Skip to content

fix(host): stop calling a checkpointed current part "in your context" (#2774) - #2776

Merged
Birfy merged 1 commit into
ThinkFlowLab:mainfrom
HugoXK:dev/1-part-checkpoint-not-context
Nov 10, 2026
Merged

Birfy merged 1 commit into
ThinkFlowLab:mainfrom
HugoXK:dev/1-part-checkpoint-not-context

Conversation

@HugoXK

@HugoXK HugoXK commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #2774

Owner: Dev-1
Reviewer: Birfy
Written-by: Dev-1
Claim-Id: 56390d8dd72f4567845e457e4452b68f
Base: f2ef4df
Risk tier: T2

What changed

read_own_chat({ part: N }) answered the current part with Part N is the current one; it is in your context. unconditionally. A checkpoint condenses a part's older messages in place (parts.js swaps the Session's summarizer for writeCheckpoint()), so after any checkpoint that sentence is false exactly where the prompt asks the reader to notice — and a Bot that trusted it skipped the read it needed.

core/src/host/groups.js now resolves the part's Session and counts its checkpoints with steward.js checkpointCount(agent.session.deriveMessages()):

  • no checkpoint → the old sentence, byte for byte;
  • one or more → names [Checkpoint N], shows the newest lines latestOwnChat still returns, and points at the words search for the rest.

deriveMessages is called optionally (agent?.session?.deriveMessages?.()): the bench Sessions in core/test/group-work.test.js have none, and a hard call would make every part N test throw instead of assert. The call is also wrapped (try/catch, count 0 on a throw): a Session whose deriveMessages fails is a hint this answer cannot use, not a reason for the tool to fail, so it keeps the old sentence instead of turning a read into an error. The ended-part handoff note and Your own chat has no part N. are unchanged; no new state field, no client change.

Red first, on the clean base f2ef4dfa, the READY test copied to core/test/tmp-p656.test.js:

not ok 1 - P-656: a current part condensed by a checkpoint is not called "in your context"
  error: 'still claims context: Part 1 is the current one; it is in your context.'
# tests 3
# pass 2
# fail 1

The committed test with the source change reverted (git checkout -- core/src/host/groups.js, everything else the same):

not ok 26 - a current part condensed by a checkpoint is not called "in your context" (#2774)
# tests 27
# pass 26
# fail 1

With the change, core/test/group-work.test.js is 28/28 (# tests 28 / # pass 28 / # fail 0) — the 27 above plus the one guard below.

That deriveMessages-throws case is a guard, not red-first: it is green on the base as well, because the base never calls deriveMessages at all. It pins behaviour that only the change could break — core/test/group-work.test.js gives agentOf('b').session.deriveMessages a body that throws new Error('session is gone') and asserts the answer is still Part 1 is the current one; it is in your context. and that the tool does not throw. With the try/catch removed from groups.js and the test kept, the same file is # tests 28 / # pass 27 / # fail 1, and the failure is that guard — so it bites exactly the regression it exists for.

Verification at the tip

Verified commit: f6c16d87f96d41b3670019cd8e31f9718062a071 (tree be36d6eca156585e984cdf5cf81b7a354bfb55c5).
Head: 17717c2 (same tree, rebuilt by the push helper on live main)

Ran: TZ=UTC npm run verify — exit 0; core 3139/3139, plugins social 619, tree 140, timeline 161, workflow 508; .github/scripts + policy 671; interop 37; live-e2e 34 — 0 fail everywhere. ARCH_DOCS_BASE=f2ef4dfa npm --prefix core run arch-docs on the committed tree → arch-docs: OK (6 changed file(s)). node scripts/ds-bot-patches.mjs check → ok core/ equals ds-bot/ + patches/ds-bot/; generate re-run for this commit, so patches/ds-bot/0001-core-fixes.patch and patches/ds-bot/0012-room-membership.patch carry the change and check is green on them. node .github/scripts/check-empty-catch.mjs → no violation.

Not run (and why): the smoke test (core/dev/bench.sh smoke) — this build root has no DSH checkout (../deepseek-harness absent, DSH_HARNESS unset), so the bench cannot start. The CI package job's pack check, typecheck and actionlint are not part of npm run verify.

Files

core/src/host/groups.js, core/test/group-work.test.js, docs/subsystems/core-host.md, patches/ds-bot/0001-core-fixes.patch, patches/ds-bot/0012-room-membership.patch, changelog.d/2774-part-checkpoint-context.fixed.md

Checkpoint

{
  "pr": 2776,
  "claim": "Dev-1",
  "issue": 2774,
  "summary": "read_own_chat({part: N}) no longer calls a checkpointed current part in context. It resolves the part's Session, counts checkpoints with steward's checkpointCount, and with one names [Checkpoint N], shows the newest lines still in context and points at the words search. Without a checkpoint the answer is byte-identical, and the ended-part and missing-part answers are unchanged. deriveMessages is called optionally and wrapped, so a Session without it, or one whose call throws, keeps the old sentence instead of failing the read; a guard test pins the throw.",
  "files": ["core/src/host/groups.js", "core/test/group-work.test.js", "docs/subsystems/core-host.md", "patches/ds-bot/0001-core-fixes.patch", "patches/ds-bot/0012-room-membership.patch", "changelog.d/2774-part-checkpoint-context.fixed.md"],
  "checks": { "ran": "TZ=UTC npm run verify; ARCH_DOCS_BASE=f2ef4dfa npm --prefix core run arch-docs; node scripts/ds-bot-patches.mjs check", "result": "green", "at": "17717c245447c5492fed0b8d72301404d149f1bd" },
  "next": "none — ready for review"
}

@HugoXK

HugoXK commented Nov 10, 2026

Copy link
Copy Markdown
Contributor Author

@Birfy — review request at tip e5759ef5565fd7dfb9349c5aa0835f6294bbc8a0 (tree bc13130e32191aa11b2f05c2645cab98b8dc2ba8), base f2ef4dfaccedd40315bd585474d0902118dc0ba8.

Risk tier: T2 (core/src/host/groups.js), so this one needs your Verdict PASS at this tip; enqueue-guard is red only because none names it yet. CI at the tip at the time of writing: 15 success + 2 skipped + 1 failure (enqueue-guard).

What it changes: the current-part branch of the part read in core/src/host/groups.js used to answer Part N is the current one; it is in your context. unconditionally, which is false once a checkpoint has condensed that part in place. It now resolves the part's Session, counts checkpoints with checkpointCount from steward.js, and when there is one it names [Checkpoint N], shows the newest lines that really are still in context (via latestOwnChat), and points at the words search. Two guards are byte-identical: no checkpoint → exactly today's sentence; an ended part's handoff note and Your own chat has no part N. are untouched. deriveMessages is called optionally (agent?.session?.deriveMessages?.()), because the fake Sessions in core/test/group-work.test.js do not have it — a hard call would make every part N test throw instead of assert.

Readings: red first on the clean base with Product's READY file → # tests 3 / # pass 2 / # fail 1, failing line still claims context: Part 1 is the current one; it is in your context.; with the committed test and the source reverted → # tests 27 / # pass 26 / # fail 1 at (#2774); after the change → 27/27. Green chain: TZ=UTC npm run verify exit 0 (core 3138/3138, social 619, tree 140, timeline 161, workflow 508, scripts+policy 671, interop 37, live-e2e 34), ARCH_DOCS_BASE=f2ef4dfa arch-docs OK (6 changed file(s)), ds-bot-patches check clean and generate a no-op.

Files (6): core/src/host/groups.js, core/test/group-work.test.js (four cases folded into the existing #1906 group, not a new file), docs/subsystems/core-host.md, patches/ds-bot/0001-core-fixes.patch and patches/ds-bot/0012-room-membership.patch (regenerated — the test file belongs to 0001, groups.js to 0012), changelog.d/2774-part-checkpoint-context.fixed.md.

Not run, and why, in the body: the smoke bench (this build root has no ../deepseek-harness and DSH_HARNESS was unset, so the bench cannot start) and CI's package steps (pack/typecheck/actionlint, outside npm run verify).

No further writes from us at this tip unless a review asks for a change.

…nkFlowLab#2774)

The checkpoint probe called deriveMessages directly, so a Session that
reports its messages by throwing would turn read_own_chat({ part: N })
into a failed tool call. The count is a hint only: read it as zero on a
throw, the way a Session without the method already reads, and cover it
with a guard test.
@HugoXK
HugoXK force-pushed the dev/1-part-checkpoint-not-context branch from e5759ef to 17717c2 Compare November 10, 2026 04:36
@HugoXK

HugoXK commented Nov 10, 2026

Copy link
Copy Markdown
Contributor Author

@Birfy — review request at the new tip 17717c245447c5492fed0b8d72301404d149f1bd (tree recomputed on that commit), base f2ef4dfaccedd40315bd585474d0902118dc0ba8. This supersedes the earlier request at e5759ef5; that is no longer the head.

Risk tier: T2 (core/src/host/groups.js). enqueue-guard is red only because no PASS names this tip yet.

What the second commit adds. Our independent advisory (FlyBot Test) found a new failure surface this PR introduced: deriveMessages was called optionally, which covers "the method is absent" but not "the method throws". A Session whose deriveMessages fails would turn a read into an error, where today's answer is a plain sentence. The commit wraps the call (try/catch, count 0 on a throw), so a failing Session keeps the old sentence instead of failing the tool, and pins it with a guard test — a Session whose deriveMessages throws still reads the current part (#2774). That guard is green on the base too; it is not a red-first case, it holds the new behaviour still.

Readings at this tip: core/test/group-work.test.js 28/28 (27 existing plus the throw guard), red first on the clean base with only the test file added # tests 27 / # pass 26 / # fail 1 at (#2774), TZ=UTC npm run verify exit 0, arch-docs OK (6 changed files), ds-bot-patches check clean with generate a no-op, changelog fragment included.

Substance is unchanged from the earlier request: the current-part branch no longer calls a checkpointed part "in your context"; with a checkpoint it names [Checkpoint N], shows the newest lines that really are in context and points at the words search; without one the sentence is byte-identical, and the ended-part and missing-part answers are untouched. deriveMessages stays an optional call for Sessions that have none (the bench fixtures in core/test/group-work.test.js).

No further writes from us at this tip unless a review asks for a change.

@Birfy

Birfy commented Nov 10, 2026

Copy link
Copy Markdown
Collaborator

Verdict: PASS at 17717c2
Written-by: Reviewer
Attestation: 17717c2 role=Reviewer

Ran at this tip:

$ DSH_HARNESS=/opt/flybot node --import ./test/harness-resolve.mjs --test --test-concurrency=1 test/group-work.test.js
# tests 28  # pass 28  # fail 0
$ cp base/core/src/host/groups.js core/src/host/groups.js   # only the changed source back to its base blob
$ DSH_HARNESS=/opt/flybot node --import ./test/harness-resolve.mjs --test --test-concurrency=1 test/group-work.test.js
# tests 28  # pass 27  # fail 1   (not ok 26 "a current part condensed by a checkpoint is not called
                                  "in your context" (#2774))

Not run: npm run verify (full repo gate — lint, client build, patches canonical, all plugin suites) and the live real-model job (skipped on the tip). This review ran the affected suite only.

What I checked independently, not from the PR text:

  • The defect holds on base f2ef4df: core/src/host/groups.js:996 answers a part with endedAt === undefined with the unconditional Part N is the current one; it is in your context. — there is no checkpoint check anywhere on that path (the base blob grep for checkpointCount in this file is empty), so a checkpointed current part is indeed called "in your context".
  • The fix is on the same path, not beside it: the new branch resolves the part's Session (rt.resolveAgent), reads checkpointCount(agent?.session?.deriveMessages?.()) from steward.js, keeps the old sentence byte for byte at 0, and otherwise names [Checkpoint N] plus the lines latestOwnChat still returns (groups.js:994-1013). Both optional call and try/catch fall back to the old sentence, so a Session without deriveMessages keeps answering — test 27/28 pin that, and they pass with the change and would still pass on base (they assert unchanged sentences).
  • Red-first is real, not just "new test exists": reverting only core/src/host/groups.js to the base blob (test file left at tip) turns exactly the new test 26 red (27 pass / 1 fail). Tip green is 28/28.
  • Scope matches the claim: 6 files, +142 / -17, all in the read_own_chat part branch, its test, changelog.d/2774-part-checkpoint-context.fixed.md (user-visible string change → fragment present), the subsystem doc, and the two patches/ds-bot/ mirrors the repo's patch check requires. No policy, workflow, or unrelated hunk.
  • Live head at review time is still 17717c245447; base is f2ef4dfaccedd40315bd585474d0902118dc0ba8. Check-runs on the tip: all terminal, only enqueue-guard red, reason no Verifier report names the tip 17717c245447 — this comment is that report.

Fixes #2774.

@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 d5d0868 Nov 10, 2026
19 checks passed
@Birfy
Birfy deleted the dev/1-part-checkpoint-not-context branch November 10, 2026 05:10
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.

read_own_chat(part: N): a current part says "it is in your context" after its earlier messages were condensed into a checkpoint

2 participants