Skip to content

Release v0.2.16 - #1817

Merged
Birfy merged 1 commit into
mainfrom
release/v0.2.16
Oct 30, 2026
Merged

Birfy merged 1 commit into
mainfrom
release/v0.2.16

Conversation

@Birfy

@Birfy Birfy commented Oct 30, 2026

Copy link
Copy Markdown
Collaborator

Release v0.2.16

Written-by: Release

Consumed changelog fragments (31):

  • changelog.d/1709-retired-bot-paths.fixed.md
  • changelog.d/1738-workflow-drawer-parallel-pair.fixed.md
  • changelog.d/1740-project-owner-gate.security.md
  • changelog.d/1744-result-ready-slot.fixed.md
  • changelog.d/1749-project-board-settings-members.fixed.md
  • changelog.d/1750-project-board-scrim.fixed.md
  • changelog.d/1751-project-digest-retry.fixed.md
  • changelog.d/1752-settings-graph-fit.fixed.md
  • changelog.d/1753-workflow-idle-flow.fixed.md
  • changelog.d/1754-meetings-decide-paths.fixed.md
  • changelog.d/1759-project-assistant-owner.fixed.md
  • changelog.d/1763-meetings-decide-orphan-cards.fixed.md
  • changelog.d/1764-room-rename-face-to-face.fixed.md
  • changelog.d/1766-settings-projects.added.md
  • changelog.d/1767-project-board-record.added.md
  • changelog.d/1768-project-board-queue.added.md
  • changelog.d/1769-settings-graph-left-padding.fixed.md
  • changelog.d/1773-workflow-missing-verdict.fixed.md
  • changelog.d/1774-meetings-persist.fixed.md
  • changelog.d/1779-digest-count-rollover.fixed.md
  • changelog.d/1780-digest-needs-a-look.fixed.md
  • changelog.d/1782-social-size-rollover.fixed.md
  • changelog.d/1783-panel-duration-carry.fixed.md
  • changelog.d/1786-retired-review-gate.fixed.md
  • changelog.d/1787-digest-window-range.fixed.md
  • changelog.d/1789-workflow-skipped-chip.fixed.md
  • changelog.d/1793-tree-retired-archived.fixed.md
  • changelog.d/1797-earlier-wait-now.fixed.md
  • changelog.d/1799-retired-part-pause.fixed.md
  • changelog.d/1801-retired-bot-reach.fixed.md
  • changelog.d/1804-rework-lease.fixed.md

Written-by: Release

Consumed changelog fragments (31):
- changelog.d/1709-retired-bot-paths.fixed.md
- changelog.d/1738-workflow-drawer-parallel-pair.fixed.md
- changelog.d/1740-project-owner-gate.security.md
- changelog.d/1744-result-ready-slot.fixed.md
- changelog.d/1749-project-board-settings-members.fixed.md
- changelog.d/1750-project-board-scrim.fixed.md
- changelog.d/1751-project-digest-retry.fixed.md
- changelog.d/1752-settings-graph-fit.fixed.md
- changelog.d/1753-workflow-idle-flow.fixed.md
- changelog.d/1754-meetings-decide-paths.fixed.md
- changelog.d/1759-project-assistant-owner.fixed.md
- changelog.d/1763-meetings-decide-orphan-cards.fixed.md
- changelog.d/1764-room-rename-face-to-face.fixed.md
- changelog.d/1766-settings-projects.added.md
- changelog.d/1767-project-board-record.added.md
- changelog.d/1768-project-board-queue.added.md
- changelog.d/1769-settings-graph-left-padding.fixed.md
- changelog.d/1773-workflow-missing-verdict.fixed.md
- changelog.d/1774-meetings-persist.fixed.md
- changelog.d/1779-digest-count-rollover.fixed.md
- changelog.d/1780-digest-needs-a-look.fixed.md
- changelog.d/1782-social-size-rollover.fixed.md
- changelog.d/1783-panel-duration-carry.fixed.md
- changelog.d/1786-retired-review-gate.fixed.md
- changelog.d/1787-digest-window-range.fixed.md
- changelog.d/1789-workflow-skipped-chip.fixed.md
- changelog.d/1793-tree-retired-archived.fixed.md
- changelog.d/1797-earlier-wait-now.fixed.md
- changelog.d/1799-retired-part-pause.fixed.md
- changelog.d/1801-retired-bot-reach.fixed.md
- changelog.d/1804-rework-lease.fixed.md
@Birfy
Birfy enabled auto-merge October 30, 2026 09:08
@Birfy
Birfy added this pull request to the merge queue Oct 30, 2026
Merged via the queue into main with commit adbaf32 Oct 30, 2026
13 checks passed
@Birfy
Birfy deleted the release/v0.2.16 branch October 30, 2026 09:15
HugoXK added a commit to HugoXK/FlyBot that referenced this pull request Oct 30, 2026
…t accepts (ThinkFlowLab#1823)

Fixes ThinkFlowLab#1820

## What was wrong

The Project settings panel's **Save memory** button never worked, for
anyone including the Project owner. The panel wrote `kind: 'note'`
(`core/src/client/project-board.js`), and the host accepts only
`decision` / `question` (`core/src/host/store.js:502`,
`project-assistant.js:185`, `MEMORY_KINDS` at `:28`), so every press
ended in `bot/invalid: Unknown Project memory kind note`. The success
line was unreachable, and a zh UI showed the host's English refusal
verbatim. The old test pinned that payload, so green CI never caught it.

The base is `2ea55d8a4d67cd1e4fe489ab2b14b1946cea4dd6` (live `main` when
this was pushed); the issue's `adbaf320fed0` is stale (`ThinkFlowLab#1815`, `ThinkFlowLab#1817`,
`ThinkFlowLab#1818` and `ThinkFlowLab#1822` have landed since).

## What changed

- `core/src/client/project-board.js`: the memory box sends `kind:
'decision'` — the host's own default when a writer omits `kind`
(`project-assistant.js:184`), and the only accepted kind that is not an
open question. The status line goes through `hostText`, so a refusal is
quoted in the UI language. The other two write paths are unchanged.
- `core/src/client/i18n.js`: three `HOST_ERRORS` entries, only for
refusals this panel's three write paths can actually surface — the owner
gate on all three (`Only the owner of this Project may change it`), an
empty member id on Bind/Unbind (`A binding needs the member id`), and a
stale Project id (`Unknown Project (\S+)`). The id rule is last and
takes one token, so it cannot swallow a longer `Unknown Project …`
sentence; the test keeps `Unknown Project status active` unchanged so
that stays proven. No other entry was added.
- `core/test/project-board-panels.test.js`: the stub that pinned `kind:
'note'` is replaced by a real round-trip through `rt.projectEndpoint`
(`call: (event, payload) => rt.projectEndpoint(event, payload)`), with a
control that a `decision` write lands in the memory, a control that
`note` is refused and writes nothing, and a zh assertion on the refusal
and on `记忆已保存。`.
- `docs/subsystems/core-client.md`: one paragraph on the panel's three
write paths and the memory-kind mapping.
- `changelog.d/1820-project-memory-save.fixed.md`.
- Generated surface: `core/client.js`,
`patches/ds-bot/0001-core-fixes.patch`,
`patches/ds-bot/0008-client-bundle.patch`, and the two
`patches/ds-bot/files/...` mirrors. The bulk of the diff is
`patches/ds-bot/0008-client-bundle.patch` (+5,023/−2,573 of the
+5,342/−2,598): that patch is machine-generated whenever the client
bundle is rebuilt and is never hand-edited — `npm run build-client`
regenerates it, and `node scripts/ds-bot-patches.mjs check` printed the
same three green lines on two consecutive runs. `0012` / `0014` were
reverted when the generator only changed hunk headers.

### No display surface today

This fix adds no display surface and no new wording for one. The only
reader of a `decision`-kind row is the `project-memory` endpoint, and no
client code calls it; the approved P-228 read-back panel is the one
future surface, and it labels these rows **memory entries** (记忆条目),
never "decisions". The audit below is why `decision` is the correct side
of the host's two-kind contract today.

## Memory kind mapping

The panel has no type selector: every Save memory press writes one
free-text row. `note` is not a kind the host accepts, so the panel sends
`decision`. This is a client-side mapping only — `MEMORY_KINDS`
(`project-assistant.js:28`) and the host's kind checks (`store.js:502`,
`project-assistant.js:185`) are unchanged.

**Every reader of a `decision`-kind row (base `2ea55d8a`):**

1. **`project-memory` endpoint** (`store.js:606`, routed by
`channel.js:676`, owner-gated at `store.js:605`) — returns `{project,
memory: {decisions, questions, digest}}`. Its only caller is a test
today: `core/src/client/` contains no `project-memory` read at all (the
bundle has `project-memory-write` and the `project-memory-save` action,
never the read endpoint), and no page renders the response. This is the
endpoint the approved P-228 read-back panel will use; today the row has
no display surface.
2. **The digest** (`project-assistant.js:159` `memoryOf` →
`projectMemoryFor`) — `digestForOwner` (`:432`) reads only
`memory.digest` (`:447`, `:450`); `buildDigest` (`:61`) takes
`project/rows/files/actionable` and no `decisions`/`questions`, so a
memory row never appears in the digest text, and the word "decision" is
never printed from it.
3. **The board's Decisions section** (`store.js:656`) — comes from
`project-board.js:150` `decisionsOf(project)`, which lists
`workDir/decisions/*.md` on disk. Different source from
`state.projectMemory`; a memory row never shows there and is never
labelled a decision.
4. **`rt.projectAssistant.read` / `write`** (`:176`, `:182`, exposed at
`:508`) — the internal API returns the owner's `{decisions, questions,
digest}`, but nothing calls `read` (the assistant Session registers only
`project_digest`, `:513`) and no `project_memory_write` tool is
registered (the instructions at `:37` name one that does not exist). No
assistant-side display path.
5. **The write response** — `project-memory-write` returns the updated
`memory` (`store.js:612` → `ownerView`), and the panel accepts it, but
`run()` uses it only for the success/refusal status line; `onSaved` is
not passed by any caller, so no entry is rendered.

Measured on `2ea55d8a` with the real endpoints (throwaway probe, not
committed):

```text
READBACK decisions => ["memory row: ship Friday"]
BOARD decisions => {"dir":"...","files":[{"path":"decisions/2026-10-30-ship.md",...}],"reason":""}
DIGEST => "Project Assistant (Ops) — 2026-10-30: no change since the previous digest."
```

**Why `decision` and not `question`.** `question` is the host's list for
open questions; the free text a person types on Save memory is a
statement or a settled call, so it belongs on the "recorded, no longer
open" side. `decision` is also the host's own default when a writer
omits `kind` (`project-assistant.js:184`), so the panel sends explicitly
what the host would have assumed.

**The trade-off and its condition.** Mapping to `decision` is deliberate
and holds only while no surface renders such a row under the word
"decision": today none does (readers 1–5 above), and P-228 renders them
as memory entries. It does not hold by itself. The approved P-228
read-back panel will list both arrays, and if it labels a `decisions`
row as a decision, a person's typed memory would read as a decision they
never made. For this mapping to stay honest, P-228 must render these
rows as **memory entries** (记忆条目) — or separate "recorded memory" from
"decisions" — and that requirement is P-228's acceptance, not this PR's.
The alternative here would be a third host kind (a new contract with no
reader, which the issue excludes) or a type selector in the panel (also
out of scope).

## Red first

Re-taken on the final base `2ea55d8a4d67cd1e4fe489ab2b14b1946cea4dd6`,
with only `core/src/client/project-board.js` reverted to that base and
the new tests kept:

```text
not ok 3 - the settings panel memory save lands in the Project memory through the real endpoint
  error: |-
    the panel reports the state the host answered
    + actual - expected

    + 'Unknown Project memory kind note'
    - 'Memory saved.'

not ok 4 - a memory kind the host does not know writes nothing, and the panel quotes a refusal in Chinese
  error: |-
    Expected values to be strictly equal:
    + actual - expected

    + 'Only the owner of this Project may change it'
    - '只有这个项目的主人可以修改'

# pass 4
# fail 2
```

The two failures are the two contracts this PR fixes: the panel sends a
kind the host refuses, and the panel quotes the host's English refusal
instead of the localized one. With the fix, the same file is 6/6.

## Verification at the tip

At the pushed tip `7c374bb32f38241d4d0f937f4f4ddcd11f45057c` (tree
`b1f5352cd2e2907437b75addc5dd2aba6291aca3`, the tree `npm run verify`
ran on locally as `06ac78a59af1738ff420f4e18592a6067394e044`):

```text
TZ=UTC ARCH_DOCS_BASE=2ea55d8a4d67cd1e4fe489ab2b14b1946cea4dd6 npm run verify
```

- core suite: **2182/2182** pass, 0 fail.
- core lint: **71 warnings, 0 errors**.
- `arch-docs`: **OK (10 changed file(s))** with
`ARCH_DOCS_BASE=2ea55d8a4d67cd1e4fe489ab2b14b1946cea4dd6`.
- `build-client --check`: green.
- `ds-bot-patches check` run twice, identical three lines:

```text
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/
```

- the repo changelog test (`ok 54`) is green;
`changelog.d/1820-project-memory-save.fixed.md` is the new fragment.
- the remaining plugin / script suites are green (541, 127, 135, 294 and
549 tests), and `git status` is clean apart from the untracked
`node_modules` symlinks the bench needs.

10 files changed, +5342/−2598:
`changelog.d/1820-project-memory-save.fixed.md` +1/−0, `core/client.js`
+12/−3, `core/src/client/i18n.js` +7/−0,
`core/src/client/project-board.js` +7/−4,
`core/test/project-board-panels.test.js` +132/−7,
`docs/subsystems/core-client.md` +7/−0,
`patches/ds-bot/0001-core-fixes.patch` +14/−0,
`patches/ds-bot/0008-client-bundle.patch` +5023/−2573,
`patches/ds-bot/files/src/client/project-board.js` +7/−4,
`patches/ds-bot/files/test/project-board-panels.test.js` +132/−7.

Not run: the smoke bench (no `index.js` or `core/src/host/` change), the
pack check, and actionlint — `npm run verify` does not include them.

Owner: Dev-3
Reviewer: Birfy

<!-- flybot:checkpoint -->
```json
{
  "pr": 1823,
  "claim": "Dev-3",
  "issue": 1820,
  "summary": "The Project settings memory box now writes kind decision, the host's own default, so Save memory stores the text and shows the localized success line. Refusals are quoted through hostText, with dictionary entries only for the three refusals this panel's write paths can surface. The stub that pinned kind note became a real projectEndpoint round-trip, with controls that decision lands and note writes nothing. No display surface is added; the future P-228 panel labels these rows memory entries.",
  "files": ["core/src/client/project-board.js", "core/src/client/i18n.js", "core/test/project-board-panels.test.js", "docs/subsystems/core-client.md", "changelog.d/1820-project-memory-save.fixed.md", "core/client.js", "patches/ds-bot/0001-core-fixes.patch", "patches/ds-bot/0008-client-bundle.patch", "patches/ds-bot/files/src/client/project-board.js", "patches/ds-bot/files/test/project-board-panels.test.js"],
  "checks": { "ran": "TZ=UTC ARCH_DOCS_BASE=2ea55d8a4d67cd1e4fe489ab2b14b1946cea4dd6 npm run verify", "result": "green", "at": "7c374bb32f38241d4d0f937f4f4ddcd11f45057c" },
  "next": "none — ready for review"
}
```
<!-- /flybot:checkpoint -->
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.

1 participant