Skip to content

feat(content): schedule an entry from Studio, and keep what MCP plans in meta - #229

Merged
ABB65 merged 2 commits into
mainfrom
feat/scheduling-meta-passthrough
Sep 2, 2026
Merged

feat(content): schedule an entry from Studio, and keep what MCP plans in meta#229
ABB65 merged 2 commits into
mainfrom
feat/scheduling-meta-passthrough

Conversation

@ABB65

@ABB65 ABB65 commented Sep 2, 2026

Copy link
Copy Markdown
Member

Summary

Stacked on #228 (merge that first; this PR's own diff is the second commit).

MCP 3.1.8 puts publish_at / expire_at on the ContentEntry: meta only, null clears, absent leaves alone, and it never changes status. Studio could neither set nor keep them.

  • Meta override starts from the plan. applyStudioMetaOverrides rebuilt the record from the file on contentrain and dropped every key the plan had just set. It now takes MCP's planned meta as the base (prior record + this write's schedule) and re-owns only status / updated_by / updated_at. Existing semantics are unchanged (MCP already keeps the current status; autoPublish is the one rule Studio adds) and the prior-file read is gone from the hot path — it remains only for a caller whose plan carries no meta change.
  • Scheduling passthrough. SaveOptions.schedule on saveContent / saveDocument; shapeEntriesForSave puts it on each entry; validateSchedule refuses a non-date or an expiry before the publish date; splitEntrySchedule lifts an undeclared publish_at/expire_at out of entry data (and document frontmatter) so it never reaches the content file.
  • Agent + route. save_content takes publish_at / expire_at beside data with the MCP wording ("NEVER change status … publishing is update_status"); the conversation engine maps them to the engine; the content route accepts the same body keys. New prompt rule rules.scheduling.
  • Docs: CLAUDE.md invariant.

Not in scope: a date picker in the edit modal and the boundary-time rebuild (migration track S-03) — this PR is the engine and agent side S-03 needs.

Test plan

  • content-engine.test.ts: schedule lands in meta with status untouched and Studio's stamps on top; null clears / omitted leaves alone; a schedule inside data is lifted; invalid and inverted dates refused before any git work; document schedule lands in slug meta and the frontmatter stays clean
  • agent-tools.test.ts: schema and wording
  • lint, nuxt typecheck, unit + integration green; nuxt project green when run alone (31 files)
  • Staging: ask the agent to "schedule X for next Monday 09:00" — the branch touches only meta, status stays draft, and the agent says so

🤖 Generated with Claude Code

https://claude.ai/code/session_01Chid3TnLdPHjsKip4n63Ky

Contentrain added 2 commits September 2, 2026 16:25
Studio pinned types 1.2.0 / mcp 3.1.0 / query 7.0.6, seven releases
behind. The gap is narrower than it looks: between mcp 3.1.0 and 3.1.7
the package source did not change (types bumps only), and types 1.3
through 1.9 added the WordPress migration contracts without touching
FieldDef, ModelDefinition, PATH_PATTERNS or any symbol Studio imports.

The substantive change is 3.1.8 / 1.9.1: the generic `api_key = …`
secret rule now checks what it captured before it fires. Studio's
validateContent comes from the MCP validator and calls detectSecrets,
so until now a setup guide that said `api_key = your_project_api_key_here`
was refused by every Studio write path — UI, agent, Conversation API.
The new test pins that the fix reaches Studio, and that an issued key
is still refused.

Also in 3.1.8, for the next PRs: publish_at/expire_at ride on
ContentEntry (meta only, null clears), legacy field names are
grandfathered by the MCP validator, and title_field inference matches
Studio's resolver.
… in meta

MCP 3.1.8 moved publish_at/expire_at onto the entry: meta only, never
the content file, never a status change. Studio had no way to set them
— the save_content tool, the content route and shapeEntriesForSave
carried data alone — and could not have kept them if it did:
applyStudioMetaOverrides rebuilt the meta record from the file on
contentrain and threw away every key the plan had just set.

The override now starts from the meta MCP planned, which already holds
the prior record plus this write's schedule, and re-owns only status,
updated_by and updated_at (autoPublish is the one rule Studio adds on
top; MCP already keeps the current status). One fewer read per save.

save_content takes publish_at/expire_at beside data (null clears,
absent leaves alone); the content route accepts the same body keys;
the engine validates the dates and lifts any the caller still put
inside data, so nothing leaks into the content file — the habit the
older MCP taught the agent, and the leak its validator now warns about.
A prompt rule says scheduling is a delivery gate, not a publish.
@ABB65
ABB65 merged commit 1ed42dc into main Sep 2, 2026
2 checks passed
@ABB65
ABB65 deleted the feat/scheduling-meta-passthrough branch September 2, 2026 16:31
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