Files
boocode/openspec
indifferentketchup 211e903620 v1.13.20-drop-legacy-cols: final phase of v1.13.0 strangler-fig
Removes the dual-write into messages.tool_calls / messages.tool_results JSON
columns and drops the columns. message_parts is now the only source of truth
for tool calls and tool results.

10 dual-write sites stripped (5 in tool-phase.ts, 2 in routes/skills.ts, 2 in
routes/messages.ts, 1 in routes/chats.ts fork-clone). The recon-driven grep
caught 2 sites beyond the original v1.13.2 roadmap inventory and an extra
fixture file (tool_cost_stats.test.ts) with a direct legacy-column INSERT.

messages_with_parts view rewritten to parts-only subselects (COALESCE
fallbacks gone). View runs via CREATE OR REPLACE so it lands before the
column DROPs in startup DDL — Postgres rejects column-drop on view-referenced
cols. v1.12.1 cleanup DO block (DROP CONSTRAINT messages_status_check /
messages_role_check) removed; those one-shots have done their work.

Adversarial review caught a runtime bug the green test suite missed: the
discard_stale endpoint (chats.ts) had a RETURNING ... tool_calls, tool_results
clause that would have crashed on every 60s-no-token-activity recovery in
production. Fixed by switching to two-step UPDATE returning id, then SELECT
from messages_with_parts so parts-synthesized fields keep flowing on the wire.

Message API type retains tool_calls? / tool_results? — the view synthesizes
those keys from parts so the wire shape is unchanged; frontend reads need no
update. Override on the original v1.13.2 plan, captured in the openspec
proposal.

339/339 server tests passing (including 7 DB-integration tests that applied
the schema migration to a live DB and ran the parts-only view end-to-end).
tsc + web build clean.

Pairs with v1.13.0-ai-sdk-v6 (introduced the dual-write) and v1.13.1-B (moved
the read path to messages_with_parts). Umbrella v1.13 tag ships on this same
commit, marking the strangler-fig closed.

CLAUDE.md picks up Sam's pre-existing edits documenting tag-naming and
CHANGELOG conventions — both already in use by v1.13.19 / v1.13.20.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 13:03:51 +00:00
..

openspec

Per-batch documentation convention adopted v1.13.15-openspec.

Lift source: Fission-AI/OpenSpec directory layout. No CLI dependency — just the folder shape. Full OpenSpec lifecycle adoption is a future v1.14+ batch.

Layout

openspec/
  changes/
    <slug>/                          # one folder per shipped or planned batch
      proposal.md                    # Why + scope summary
      tasks.md                       # implementation step list
      design.md                      # architecture / data-model decisions (optional)
      specs/                         # reserved for future OpenSpec CLI adoption
    archived/                        # snapshots of pre-v1.13.15 batch docs
      <original-filename>.md
  specs/                             # global specs, future v1.14+ use

Conventions

  • Slugs are lowercase-hyphenated derived from the batch title (e.g. v1-13-10-per-tool-cost, file-attachments-v3-5).
  • Already-shipped pre-v1.13.15 batches live in changes/archived/ as single-file snapshots. They were not split into proposal/tasks because the work was already complete; archiving preserves git history.
  • New v1.13.15+ batches should land directly in changes/<slug>/proposal.md (+ tasks.md, + design.md when applicable).
  • proposal.md carries the "Why" and scope. tasks.md is the action list (numbered or checkbox). design.md is for non-trivial architectural decisions worth recording separately.
  • A canonical dispatch brief (matching the v1.13.9 / v1.13.10 format) is most naturally split as proposal.md (Where we are, Why this matters, rationale sections) + tasks.md (Scope items, Build + smoke) + design.md (Attribution model, Filtering, Canonical mapping).