Skip to content

Commit e3751ea

Browse files
author
SqlRush
committed
Accept numeric transcript metadata IDs
1 parent dd0e54e commit e3751ea

5 files changed

Lines changed: 23 additions & 1 deletion

File tree

docs/cc-100-roadmap.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,8 @@ M7 补充:prompt history `LogEntry` 读取现在接受 `sessionID`/`session`/`
326326

327327
本轮补充:transcript metadata loader 现在接受 `sessionID``session` 作为 session-scoped metadata ID 别名,并容忍 `prNumber``timeSavedMs``lastSpawnTokens` 等计数字段使用数字字符串。
328328

329+
本轮补充:transcript metadata ID helper 现在复用 contract `ID` JSON 解码,`messageID`/`sessionID` 等 metadata ID 字段可接受 JSON number 并保留为字符串。
330+
329331
本轮补充:context-collapse snapshot metadata 接受 `isArmed`/`enabled` bool 别名、`spawnTokens`/`tokenCount` 计数字段别名,以及 `stagedMessages`/`items` staged payload wrapper,full loader 和 metadata loader 保持一致。
330332

331333
本轮补充:transcript message 和嵌套 contract message 现在接受 `sessionID` 顶层别名,`LoadTranscript``LoadTranscriptIndex` 和 indexed resume 会保留该 session id(覆盖测试:`TestLoadTranscriptAcceptsSessionIDUpperAlias`)。

docs/claude-code-go-rewrite-plan.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ test/parity/ # golden tests against TS/official behavior
198198
- 本轮补充:transcript resume 的嵌套 content block 接受 `toolUseId`/`toolUseID``isError``cacheControl``cacheReference` 字段别名,并保留 cache edit 的 `cacheReference`
199199
- 本轮补充:lightweight transcript metadata loader 在 `system`/`compact_boundary` 后清空旧 `marble-origami-commit`/`marble-origami-snapshot` 状态,和 full loader/官方 sessionStorage compact-boundary 语义一致。
200200
- 本轮补充:transcript metadata loader 接受 `sessionID`/`session` 作为 session-scoped metadata ID 别名,并容忍 `prNumber``timeSavedMs``lastSpawnTokens` 等计数字段使用数字字符串。
201+
- 本轮补充:transcript metadata ID helper 现在复用 contract `ID` JSON 解码,`messageID`/`sessionID` 等 metadata ID 字段可接受 JSON number 并保留为字符串。
201202
- 本轮补充:context-collapse snapshot metadata 接受 `isArmed`/`enabled` bool 别名、`spawnTokens`/`tokenCount` 计数字段别名,以及 `stagedMessages`/`items` staged payload wrapper,full loader 和 metadata loader 保持一致。
202203
- 本轮补充:transcript message 和嵌套 contract message 接受顶层 `sessionID` 作为 session id 别名,`LoadTranscript``LoadTranscriptIndex` 和 indexed resume 会保留该 session id(覆盖测试:`TestLoadTranscriptAcceptsSessionIDUpperAlias`)。
203204
- 本轮补充:嵌套 contract message 接受 `parentUUID``parentId`/`parentID`/`parent_id``parentMessageId`/`parentMessageID`/`parent_message_id` 和 parent-message UUID 别名,transcript/remote history payload 自带 parent alias 时不会丢失嵌套 parent。

docs/first-second-parity-audit.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ M6 progress now includes:
161161
- `internal/session`: transcript message loading now preserves structured SerializedMessage metadata such as `userType`, `entrypoint`, `version`, and `slug`, including common alias spellings.
162162
- `internal/session`: lightweight transcript metadata loading now clears stale context-collapse commit/snapshot state after compact-boundary messages, matching the full loader and official sessionStorage restore semantics.
163163
- `internal/session`: transcript metadata loading now accepts `sessionID` and `session` as session-scoped ID aliases and tolerates numeric strings for counters such as `prNumber`, `timeSavedMs`, and `lastSpawnTokens`.
164+
- `internal/session`: transcript metadata ID helpers now reuse contract `ID` JSON decoding so metadata IDs such as `messageID` and `sessionID` can be JSON numbers preserved as strings.
164165
- `internal/session`: context-collapse snapshot metadata now accepts alternate armed, token-count, and staged payload field names in both full and lightweight metadata loaders.
165166
- `internal/session` and `internal/contracts`: transcript records and nested contract messages now accept top-level `sessionID` as a session id alias, preserving it through `LoadTranscript`, `LoadTranscriptIndex`, and indexed resume (`TestLoadTranscriptAcceptsSessionIDUpperAlias`).
166167
- `internal/contracts`/`internal/session`: remote-history `SDKEvent` decoding now accepts top-level `sessionID` as an event session id alias and preserves it during transcript materialization (`TestRemoteHistoryTranscriptMessagesAcceptsSessionIDUpperAlias`).

internal/session/transcript_metadata_fields.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,17 @@ func (f transcriptMetadataFields) stringValue(keys ...string) string {
3434
}
3535

3636
func (f transcriptMetadataFields) idValue(keys ...string) contracts.ID {
37-
return contracts.ID(f.stringValue(keys...))
37+
for _, key := range keys {
38+
raw, ok := f[key]
39+
if !ok || isNullJSON(raw) {
40+
continue
41+
}
42+
var value contracts.ID
43+
if err := json.Unmarshal(raw, &value); err == nil {
44+
return value
45+
}
46+
}
47+
return ""
3848
}
3949

4050
func (f transcriptMetadataFields) sessionIDValue() contracts.ID {

internal/session/transcript_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -820,6 +820,8 @@ func TestLoadTranscriptCollectsMetadataEntries(t *testing.T) {
820820

821821
func TestLoadTranscriptMetadataAcceptsSessionIDAndNumericStrings(t *testing.T) {
822822
path := writeTranscript(t, []string{
823+
`{"type":"summary","messageID":123,"content":"numeric summary"}`,
824+
`{"type":"tag","sessionID":404,"label":"numeric-session"}`,
823825
`{"type":"pr-link","sessionID":"s4","prNumber":"44","prUrl":"https://github.com/o/r/pull/44","prRepository":"o/r"}`,
824826
`{"type":"speculation-accept","createdAt":"2026-01-01T00:00:05Z","timeSavedMs":"5600"}`,
825827
`{"type":"marble-origami-snapshot","sessionID":"s4","isArmed":"true","spawnTokens":"96","items":[{"uuid":"pending_1"}]}`,
@@ -831,6 +833,9 @@ func TestLoadTranscriptMetadataAcceptsSessionIDAndNumericStrings(t *testing.T) {
831833
if transcript.PRLinks["s4"].PRNumber != 44 || transcript.PRLinks["s4"].PRRepository != "o/r" {
832834
t.Fatalf("transcript pr link = %#v", transcript.PRLinks)
833835
}
836+
if transcript.Summaries["123"] != "numeric summary" || transcript.Tags["404"] != "numeric-session" {
837+
t.Fatalf("transcript numeric metadata = summaries:%#v tags:%#v", transcript.Summaries, transcript.Tags)
838+
}
834839
if len(transcript.SpeculationAccepts) != 1 || transcript.SpeculationAccepts[0].TimeSavedMS != 5600 || transcript.SpeculationAccepts[0].Timestamp != "2026-01-01T00:00:05Z" {
835840
t.Fatalf("transcript speculation = %#v", transcript.SpeculationAccepts)
836841
}
@@ -845,6 +850,9 @@ func TestLoadTranscriptMetadataAcceptsSessionIDAndNumericStrings(t *testing.T) {
845850
if metadata.PRLinks["s4"].PRNumber != 44 || metadata.ContextCollapseSnapshot == nil || !metadata.ContextCollapseSnapshot.Armed || metadata.ContextCollapseSnapshot.LastSpawnTokens != 96 || len(metadata.ContextCollapseSnapshot.Staged) != 1 {
846851
t.Fatalf("metadata = %#v snapshot=%#v", metadata.PRLinks, metadata.ContextCollapseSnapshot)
847852
}
853+
if metadata.Summaries["123"] != "numeric summary" || metadata.Tags["404"] != "numeric-session" {
854+
t.Fatalf("lightweight numeric metadata = summaries:%#v tags:%#v", metadata.Summaries, metadata.Tags)
855+
}
848856
if len(metadata.SpeculationAccepts) != 1 || metadata.SpeculationAccepts[0].TimeSavedMS != 5600 {
849857
t.Fatalf("metadata speculation = %#v", metadata.SpeculationAccepts)
850858
}

0 commit comments

Comments
 (0)