Skip to content

fix(memory): default missing daily[].date to today UTC (closes #435) - #438

Closed
samxu01 wants to merge 2 commits into
mainfrom
phase-3/memory-daily-schema
Closed

fix(memory): default missing daily[].date to today UTC (closes #435)#438
samxu01 wants to merge 2 commits into
mainfrom
phase-3/memory-daily-schema

Conversation

@samxu01

@samxu01 samxu01 commented May 24, 2026

Copy link
Copy Markdown
Contributor

Summary

Why

Surfaced 2026-05-24 by Cody (cloud-codex) during the Phase 2 huddle smoke. The MCP tool advertises section: 'daily' with entries as input but doesn't tell callers each entry must already carry a date: YYYY-MM-DD. Natural writes fail:

sections.daily[].date must be YYYY-MM-DD

Cody's long_term writes worked; his daily write didn't. Same bug for any agent calling the tool naturally.

Fix

In backend/routes/agentsRuntime.ts's validateSectionsPayload, before checking isValidYMD(d?.date), default d.date to today's UTC YYYY-MM-DD if missing. Explicit values still flow through unchanged:

  • date: '2026/04/14' (wrong format) — still 400 (existing test passes)
  • date: '2026-02-30' (calendar-invalid) — still 400 (existing test passes)
  • date omitted — fills in today (new test added)

This is the kindest fix for the common caller: doesn't widen the schema, just normalizes one absent field.

Test plan

  • New test in backend/__tests__/service/agent-memory-envelope.test.js: defaults missing daily[].date to today UTC (YYYY-MM-DD) — POSTs { daily: [{ content: 'x' }] } (no date), expects 200, then GETs the memory and verifies today's date is on the stored entry.
  • Existing tests preserved (rejects-wrong-format + rejects-calendar-invalid + rejects-invalid-visibility).
  • CI green
  • After merge + deploy: Cody (or any agent) calls commonly_save_my_memory({ section: 'daily', entries: [{ content: '...' }] }) without specifying date, confirms 200 + entry lands.

Companion

🤖 Generated with Claude Code

samxu01 and others added 2 commits May 24, 2026 00:22
`commonly_save_my_memory` MCP tool contract documents `entries` as the
daily-write shape but doesn't disclose that each entry must already
carry a `date: YYYY-MM-DD` field. Cody surfaced this on 2026-05-24
during the Phase 2 huddle smoke: `long_term` writes succeeded, a
natural `daily` write failed with `sections.daily[].date must be
YYYY-MM-DD`.

Server-side default: when `date` is absent on a daily entry, fill in
today's UTC `YYYY-MM-DD` before validation. Explicit values still
flow through unchanged — `date: '2026/04/14'` (wrong format) and
`date: '2026-02-30'` (calendar-invalid) both still 400 per existing
tests. Only the omitted-date case is normalized.

This unblocks the most natural caller usage ("today's note") without
widening the schema's accepted shape. Backend-side fix keeps the
@commonlyai/mcp tool contract simple — no MCP tool-side change
needed.

## Tests

backend/__tests__/service/agent-memory-envelope.test.js — new test
case verifies that posting `{ sections: { daily: [{ content: 'x' }] } }`
without a date succeeds (200) and that the stored entry comes back
with today's UTC YYYY-MM-DD via a follow-up GET.

Existing tests still pass:
  - rejects invalid YYYY-MM-DD date on daily entries (2026/04/14)
  - also rejects calendar-invalid dates (feb 30)
  - rejects invalid visibility on a daily entry

## Companion

GH issue #435 captures the original contract
drift report from Cody, including the MCP-tool seam pointer at
commonly-mcp/src/tools.js:230. After this lands the
`MCP tool says 'pass entries (array)' but backend says 'date is
required'` mismatch resolves to "tool says 'pass entries (array)',
backend fills date when missing" — caller-friendly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…route)

Self-review caught: the new daily-date-default test used mode: 'merge'
which the /memory/sync route validator rejects (only 'full' and 'patch'
are valid). My fix's defaulting logic runs BEFORE the mode validation
in validateSectionsPayload, so the test was failing at the mode check
not the date check. Switching to mode: 'patch' (merge-into-existing
semantics, which is what we want) lets the route accept the request
and exercise the date-defaulting path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
samxu01 added a commit that referenced this pull request May 24, 2026
…435)

`commonly_save_my_memory` MCP tool contract advertises `entries` as the
daily-write shape but doesn't disclose that each entry must already
carry a `date: YYYY-MM-DD` field. Cody surfaced this on 2026-05-24
during the Phase 2 huddle smoke: `long_term` writes succeeded, a
natural `daily` write failed with `sections.daily[].date must be
YYYY-MM-DD`.

Server-side default: when `date` is absent on a daily entry, fill
in today's UTC `YYYY-MM-DD` before validation. Explicit values still
flow through unchanged:

  - date: '2026/04/14' (wrong format) → still 400 (preserved)
  - date: '2026-02-30' (calendar-invalid) → still 400 (preserved)
  - date omitted → fills in today (new behaviour)

Kindest fix for the common caller use case ("today's note") without
widening the schema. Backend-only — no @commonlyai/mcp tool-side
change needed.

Test added in backend/__tests__/service/agent-memory-envelope.test.js
verifies the default fills + the stored entry comes back with today's
YYYY-MM-DD via a follow-up GET. Existing rejection tests preserved.

Companion: GH issue #435 — Cody's original
report with the MCP-tool seam pointer at commonly-mcp/src/tools.js:230.

Co-Authored-By: Cody <cody@commonly.me>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@samxu01

samxu01 commented May 24, 2026

Copy link
Copy Markdown
Contributor Author

Merged via local squash to main as c42722d (preserves Co-Authored-By for @cody).

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.

commonly_save_my_memory daily-section contract is out of sync with backend YYYY-MM-DD validation

1 participant