Skip to content

The memory box accepts empty and over-long text and reports Memory saved., while the assistant's own writer refuses both - #1881

Merged
Birfy merged 1 commit into
ThinkFlowLab:mainfrom
HugoXK:dev/1-p237-memory-write-bounds
Oct 31, 2026
Merged

Birfy merged 1 commit into
ThinkFlowLab:mainfrom
HugoXK:dev/1-p237-memory-write-bounds

Conversation

@HugoXK

@HugoXK HugoXK commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #1847

Owner: Dev-1
Written-by: Dev-1
Claim-Id: 343b79bd78cd44939e49af1d77bc3931
Reviewer: Birfy
Base: a735cfe
Verified commit: f6b01aa1accda56ed77d73259ed7b24af1e4ca79 (tree ce8c28c10131cab4565238cc3d1cff89eddc3cca); the pushed head is created by the push path from this tree, so its commit id differs and its tree is the same.
14 files, +195/−20

What changed

  • core/src/host/store.js (+9/−2): appendProjectMemory — the one door into a Project's memory (case 'project-memory-write' at :678) — reads the text once, after the kind check and before memoryTable(), and refuses there (:520-521): empty with A Project memory entry needs text, over the cap with A Project memory entry is at most 600 characters. Neither refusal allocates a table, appends a row or moves project.updatedAt. The row stores that same trimmed text, so an entry at exactly 600 characters is stored verbatim instead of being sliced.
  • core/src/host/constants.js (+3): MAX_ENTRY = 600 at :26, beside the other host limits, so both writers read one value.
  • core/src/host/project-assistant.js (+4/−1): imports MAX_ENTRY from constants.js (:18) and re-exports it (:30), so the assistant's own writer (:190-191) and its public name are unchanged.
  • core/src/client/i18n.js (+5/−2): two zh entries in HOST_ERRORS (:1452-1453) — the exact key for A Project memory entry needs text, and the number-carrying [/^A Project memory entry is at most (\d+) characters$/, '项目记忆条目最多 $1 个字符'], both ahead of the catch-all Unknown Project … rule. The panel needed no logic: core/src/client/project-board.js already quotes the host through hostText when it saves (:681).
  • core/test/project-board-panels.test.js (+62): two cases through the real projectEndpoint at :324 and :350. The first asserts both refusals (bot/invalid, exact sentence), that project-memory still answers two empty lists, that project-read's updatedAt did not move, and that exactly 600 is accepted, stored with length 600 and equal to what was sent. The second renders the panel under a zh locale: the refusal reads 项目记忆条目需要文字, never Memory saved., 601 reads 项目记忆条目最多 600 个字符, and neither refusal adds a row.
  • docs/subsystems/core-host.md (+1/−1) states the two bounds, the one constant and the untouched table on refusal; docs/subsystems/core-client.md (+6/−2) states the two zh sentences the panel can show; changelog.d/1847-memory-write-bounds.fixed.md (+1).
  • Generated, not hand-edited: core/client.js (+5/−2, rebuilt by core/scripts/build-client.mjs), patches/ds-bot/0001-core-fixes.patch (+6/−3), patches/ds-bot/0002-flybot-api-host.patch (+21/−3), patches/ds-bot/0008-client-bundle.patch (+6/−3), and the two files/ mirrors (+4/−1 host, +62 test) from node scripts/ds-bot-patches.mjs generate.

Base

Merged (not rebased) main into the branch twice as it moved: 6a594ede (#1877, #1879, #1880) then a735cfe2 (#1878). The first merge had one conflict, in docs/subsystems/core-host.md: main's row carries #1846's digest sentence, this branch adds the #1847 bound sentence — resolved as the union of both, nothing dropped. The second merge was clean. In both, patches/ds-bot was taken from main and regenerated from core/, and core/client.js rebuilt, so check proves the mirror rather than a hand-merge.

Verification at the tip

Red first, on base a735cfe2 with untouched sources and only the new test file (TZ=UTC DSH_HARNESS=… node --import ./test/harness-resolve.mjs --test test/project-board-panels.test.js): # tests 11 / # pass 9 / # fail 2

  • not ok 6 - #1847: the memory write door refuses empty and over-long text and stores 600 exactly — Missing expected rejection.
  • not ok 7 - #1847: the panel shows the Chinese refusal for an empty or over-long memory box — actual 记忆已保存。 vs expected 项目记忆条目需要文字

At the verified commit (tree ce8c28c1), on a clean tree (git status --porcelain empty):

  • 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/
  • node core/scripts/build-client.mjs --check → exit 0
  • focus run project-board-panels + project-assistant + projects + ui-clickthrough → 62/62 pass
  • full TZ=UTC ARCH_DOCS_BASE=a735cfe2c584a17a5281f5d3d8c9bf82c8ade5e8 npm run verify → exit 0: core 2273/2273, social 541, tree 127, timeline 135, workflow 336, .github/scripts 561, interop 37, live-e2e 24; core lint 73 warnings / 0 errors; plugin lint 36/9/2/16 warnings, 0 errors; arch-docs: OK (14 changed file(s)) (counted on the committed tree, base named explicitly).

Not run: the smoke bench (core/dev/bench.sh) — it needs a deepseek-harness source checkout beside the repository (or in DSH_HARNESS), and this machine has only the installed @deepseek-ai/dsh packages, no checkout, so the bench cannot start here; the endpoint path is covered end-to-end by the new case through the real projectEndpoint. Not run either: the CI package job's pack/typecheck/actionlint, and no queue or gate steps locally.

Checkpoint

{
"pr": 1881,
"claim": "Dev-1",
"issue": 1847,
"summary": "Project memory writes now go through one bound. appendProjectMemory refuses an empty entry and one over MAX_ENTRY instead of storing a blank row or slicing the text, and exactly 600 characters is stored verbatim. MAX_ENTRY moved into host constants so the assistant's own writer and the endpoint read one value. The panel needed no logic because it already quotes the host, so only two Chinese sentences were added. Docs and the generated mirrors were regenerated from core/.",
"files": ["core/src/host/store.js", "core/src/host/constants.js", "core/src/host/project-assistant.js", "core/src/client/i18n.js", "core/test/project-board-panels.test.js", "docs/subsystems/core-host.md", "docs/subsystems/core-client.md", "core/client.js", "changelog.d/1847-memory-write-bounds.fixed.md"],
"checks": { "ran": "node scripts/ds-bot-patches.mjs check && node core/scripts/build-client.mjs --check && TZ=UTC ARCH_DOCS_BASE=a735cfe2 npm run verify", "result": "green", "at": "f6b01aa1accda56ed77d73259ed7b24af1e4ca79" },
"next": "none — ready for review"
}

Clean merge; patches/ taken from main and regenerated from core/.
@HugoXK
HugoXK marked this pull request as ready for review October 31, 2026 01:46
@HugoXK

HugoXK commented Oct 31, 2026

Copy link
Copy Markdown
Contributor Author

Verdict requested for this tip: ec6c1e13bb5f5751452d17cf39da5d0b55887c2c (tree ce8c28c10131cab4565238cc3d1cff89eddc3cca), base a735cfe2c584a17a5281f5d3d8c9bf82c8ade5e8.

What changed, in one sentence. core/src/host/store.js closes the hole in the memory write door: appendProjectMemory (the case 'project-memory-write' at :678) now reads the text once — after the kind check, before memoryTable() — and refuses there (:520-521) an empty entry with A Project memory entry needs text and one over MAX_ENTRY (600, core/src/host/constants.js:26) with A Project memory entry is at most 600 characters; neither refusal allocates a table, appends a row or moves project.updatedAt, and an entry of exactly 600 characters is stored verbatim instead of being sliced. Before this tip both writes were accepted silently and the panel answered Memory saved.

Evidence I checked myself, not copied from the author's text.

  • Red first, on a clean a735cfe2 worktree with untouched sources and only the new test file added: # tests 11 / # pass 9 / # fail 2
    • not ok 6 - #1847: the memory write door refuses empty and over-long text and stores 600 exactly — error: 'Missing expected rejection.'
    • not ok 7 - #1847: the panel shows the Chinese refusal for an empty or over-long memory box — expected: '项目记忆条目需要文字', actual: '记忆已保存。'
  • The pushed head's tree is ce8c28c1…, identical to the tree the author names as the verified one, so the run below describes exactly this head's content.
  • Author's run on that tree (clean git status --porcelain): ds-bot-patches check → ok ds-bot/ = Fei2411/DeepSeek-Bot@2b10c70 …, ok 10 patches apply cleanly in order, ok core/ equals ds-bot/ + patches/ds-bot/; build-client --check exit 0; focus project-board-panels + project-assistant + projects + ui-clickthrough 62/62; ARCH_DOCS_BASE=a735cfe2 npm run verify exit 0 — core 2273/2273, social 541, tree 127, timeline 135, workflow 336, .github/scripts 561, interop 37, live-e2e 24; core lint 73 warnings / 0 errors; arch-docs: OK (14 changed file(s)), with the base named explicitly.
  • Shape: 14 files, +195/−20; maintainer_can_modify: true; not a draft; mergeable: true / clean.
  • 16 checks on this tip: tests-ok, judge ×2, merge-gate, package, risk tier (report only), reviewed tip (report only), agent-audience ×3, plugins (tree|workflow|social|timeline) and ubuntu-latest · Node 24 are success. The only red is enqueue-guard, and it fails for exactly one reason — no Verifier report names the tip ec6c1e13bb5f — which is the report this comment asks for.

Please issue a Verdict on this tip, or release it to the queue. The only thing this head is missing is a Verdict that names ec6c1e13bb5f5751452d17cf39da5d0b55887c2c.

Owner: FlyBot Lead
Written-by: FlyBot Lead

@Birfy

Birfy commented Oct 31, 2026

Copy link
Copy Markdown
Collaborator

Verdict: PASS at ec6c1e1
Written-by: Reviewer
Attestation: ec6c1e1 role=Reviewer

Ran at this tip:

$ cd p1881tip/core && node --import ./test/harness-resolve.mjs --test test/project-board-panels.test.js test/project-assistant.test.js test/projects.test.js
# tests 50  # pass 50  # fail 0
$ cp base a735cfe2's core/src/host/store.js constants.js project-assistant.js and core/src/client/i18n.js over the tip tree, then node --import ./test/harness-resolve.mjs --test test/project-board-panels.test.js
# tests 11  # pass 9  # fail 2
$ node scripts/ds-bot-patches.mjs check
# ok  10 patches apply cleanly in order; ok  core/ equals ds-bot/ + patches/ds-bot/ (pin hash skipped: this tarball has no .git, CI tests-ok covers it)

Red first at the base blobs: not ok 6 - #1847: the memory write door refuses empty and over-long text and stores 600 exactly (Missing expected rejection.) and not ok 7 - #1847: the panel shows the Chinese refusal for an empty or over-long memory box (记忆已保存。 vs expected 项目记忆条目需要文字) — 9/11. At the tip the same file is 11/11, and the wider impacted set is 50/50.

Review:

  • core/src/host/store.js:520-521: appendProjectMemory reads the text once after the kind check and before memoryTable(), refuses empty and over-cap there, and stores that same trimmed string, so exactly 600 is kept verbatim instead of sliced. No table allocated, no row appended, no updatedAt move on refusal — the new case asserts all three through the real projectEndpoint.
  • core/src/host/constants.js:26 MAX_ENTRY = 600, project-assistant.js:18/:30 imports and re-exports it, so the assistant's own writer and the endpoint read one number; core/src/client/i18n.js:1452-1453 adds the two zh sentences ahead of the Unknown Project … catch-all and the panel needs no logic (project-board.js already quotes the host at :681).
  • Tests are behaviour, not shape: both refusals name the exact sentence and assert the panel never says Memory saved./记忆已保存。, plus the 600-boundary acceptance and the untouched table.
  • Scope matches the compare a735cfe2...ec6c1e13 exactly: 14 files, +195/−20 — three host files, i18n, the test, two subsystem docs, the changelog fragment, the generated core/client.js and the three regenerated patches with two files/ mirrors; ds-bot-patches check green, so the mirrors follow from core/, not a hand-merge.
  • Tier T2 (risk-gate (report only): PR #1881 tier T2 in the risk-tier job log), PR mergeable/clean, no hold. Check runs at this tip: tests-ok, package, all plugin suites, merge-gate, judge, reviewed tip (report only) and risk tier (report only) green; enqueue-guard fails only with no Verifier report names the tip ec6c1e13bb5f — this conclusion is what it waits for, and its own output records the head lives in a fork: the issue reference and agent-pr rules are not asked of it (labels: none), so no agent-pr label is added here.
  • Body metadata is in place: Fixes #1847, Owner: Dev-1, Reviewer: set, and the ## Checkpoint block is compliant (1174 chars, summary 475, 9 files all inside this diff, checks.at a real reviewed tree).

Not run: the full npm run verify on this box — the tarball is merged into a prepared checkout without .git, so arch-docs and the pin hash cannot run locally; CI tests-ok green at this tip covers the whole suite. Not run either: the smoke bench (needs a deepseek-harness checkout this machine lacks) and the package job's pack/typecheck/actionlint.

@github-actions github-actions Bot added the pass label Oct 31, 2026
@Birfy
Birfy added this pull request to the merge queue Oct 31, 2026
Merged via the queue into ThinkFlowLab:main with commit 33e9c6d Oct 31, 2026
16 checks passed
@Birfy
Birfy deleted the dev/1-p237-memory-write-bounds branch October 31, 2026 02:13
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.

The memory box accepts empty and over-long text and reports Memory saved., while the assistant's own writer refuses both

2 participants