fix(session-title): typed rename rejection, provenance invariant, contract docs

SessionTitleInvalidError narrows the one rename failure that blames the
input; the fallback-unpin append extracts to appendFallback beside
ensureFallback's guarded twin; a deferred-provider test proves rename
supersedes ACTIVE generation; the invariant companion enforces
messageSeqs-empty iff user-source on every appended session/title event
(tsconfig gains the session-title invariant path); SessionTitleEventData
field docs state the third source kind and the empty-seqs rule, mirrored
into the bilingual core-data-structures page; the note qualifies the
refresh unpin as conditional on a derivable replacement.
This commit is contained in:
imccyu
2026-07-29 20:10:42 +08:00
parent a6eba044b2
commit c8374e916f
11 changed files with 151 additions and 30 deletions

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/feature/2026-07-21-log-backed-session-titles.md
2026-07-21-log-backed-session-titles.md: 8d429ad93dbe348700696737dd14a71fd3a97c05
2026-07-21-log-backed-session-titles.zh.md: b8f59d77cc2e9a09f2638849f8015bf95b92fb4f
2026-07-21-log-backed-session-titles.md: 81ac687c6f55dd0ca1eaeb9d84c811edcfe17b5c
2026-07-21-log-backed-session-titles.zh.md: b0c7e9d76a1b9365fa16dcb223b390b5aec3e174

View File

@@ -38,7 +38,7 @@ Automatic provider failures are nonfatal warnings and retain the latest title. E
### Explicit rename
`rename(session, title)` accepts a user title synchronously: it normalizes the text under the accepted-title byte limit, supersedes in-flight automatic work, and appends a `session/title` event with the third source kind, `user`. A user-sourced latest title pins the session: `onUserMessage` schedules no automatic revision while it stands, under either cadence. An explicit `refresh()` remains the deliberate unpin — it reserves a revision and appends a provider or fallback event over the pinned one. The Web host exposes this as the `session.rename` unary method (resuming cold sessions first) and returns the normalized title plus its event seq so the client settles its `title` projection cell before the push frame arrives.
`rename(session, title)` accepts a user title synchronously: it normalizes the text under the accepted-title byte limit, supersedes in-flight automatic work, and appends a `session/title` event with the third source kind, `user`. A user-sourced latest title pins the session: `onUserMessage` schedules no automatic revision while it stands, under either cadence. An explicit `refresh()` remains the deliberate unpin — it appends a provider or fallback event over the pinned one whenever a replacement title is derivable (an underivable fallback, e.g. under a tiny byte cap, leaves the pin standing). The Web host exposes this as the `session.rename` unary method (resuming cold sessions first) and returns the normalized title plus its event seq so the client settles its `title` projection cell before the push frame arrives.
### Forks and consumers

View File

@@ -38,7 +38,7 @@ Status: implemented
### 显式重命名
`rename(session, title)` 同步接受用户标题:按已接受标题的字节上限规范化文本、取代在途自动工作,并追加一条第三种来源 `user``session/title` 事件。最新标题来源为 user 即钉住该会话:只要它还在,`onUserMessage` 在任一节奏下都不再安排自动修订。显式 `refresh()` 仍是有意的解钉手段——它预留一个修订号,并在被钉住的标题之上追加提供方或回退事件。Web host 将其暴露为 `session.rename` unary 方法(冷会话先恢复),并返回规范化后的标题及其事件 seq使 client 在推送帧到达前就结算自己的 `title` 投影格。
`rename(session, title)` 同步接受用户标题:按已接受标题的字节上限规范化文本、取代在途自动工作,并追加一条第三种来源 `user``session/title` 事件。最新标题来源为 user 即钉住该会话:只要它还在,`onUserMessage` 在任一节奏下都不再安排自动修订。显式 `refresh()` 仍是有意的解钉手段——只要能推导出替代标题,它就在被钉住的标题之上追加提供方或回退事件(推导不出回退标题时,例如字节上限过小,钉住状态保持不变)。Web host 将其暴露为 `session.rename` unary 方法(冷会话先恢复),并返回规范化后的标题及其事件 seq使 client 在推送帧到达前就结算自己的 `title` 投影格。
### Fork 与消费方