Filing gate: ① a product defect with a named landing site and a reach:. Finding class (a). reach: is a public door: GET /api/v1/meta/:type/:name/diff with no from / to, measured on the real REST stack (routes and writes over better-sqlite3) by the #20397 dev.
Filed by the domain:engine execution seat 1 (session_01N8TPEsoJxPsdSdNKGnNGEN, os-warren) from the #20397 dev's out_of_scope_findings[0] (os-dev-report 5870523105 on #20397, PR #20443). The contract review 5870786413 on PR #20443 judged it pre-existing, the documented rule, outside that PR's scope, and recommended filing it for triage. ⛔ Filed bare: routing and grading belong to triage. ⛔ Not a claim.
What happens
Take an item with v1 active, then a v2 draft save, then a v3 publish of that draft. The default range answers 2 → 3, "no changes". It answers the same with a v4 draft pending, once PR #20443 lands (before it, 3 → 4 with a v4 draft pending).
The builder who has just published sees an empty diff. The change the publish carried (v1 → v3) is never the default answer; it is reachable only by naming ?from=1&to=3.
Why
diffMetaItem's fromVersion default is "the history version immediately before the to side" (packages/metadata-protocol/src/protocol.ts, diffMetaItem). sys_metadata_history appends a row for every save, drafts included, and promoteDraft writes the published body as the next history row. So the row before a published version is usually the draft save it was published from, which carries the same body.
This is the documented rule, not a slip. Changing it means deciding which history rows count as versions for the default range: every save, or published versions only.
Why it is its own card
The remedy is triage's to route. Two readings:
- the default from side skips draft saves, which needs the history to say which rows were published;
- or the rule stays, and the endpoint's documentation says a post-publish default diff is empty by design.
Dedupe
search_issues "meta diff default range no changes after publish draft history row previous published version" in objectstack-ai/objectstack, open and closed: 4 hits.
None is this one.
Dedupe words: diff default from version draft save · meta diff after publish no changes · diffMetaItem fromVersion default history row
Filing gate: ① a product defect with a named landing site and a
reach:. Finding class (a).reach:is a public door:GET /api/v1/meta/:type/:name/diffwith nofrom/to, measured on the real REST stack (routes and writes over better-sqlite3) by the #20397 dev.Filed by the
domain:engineexecution seat 1 (session_01N8TPEsoJxPsdSdNKGnNGEN,os-warren) from the #20397 dev'sout_of_scope_findings[0](os-dev-report5870523105 on #20397, PR #20443). The contract review 5870786413 on PR #20443 judged it pre-existing, the documented rule, outside that PR's scope, and recommended filing it for triage. ⛔ Filed bare: routing and grading belong to triage. ⛔ Not a claim.What happens
Take an item with v1 active, then a v2 draft save, then a v3 publish of that draft. The default range answers
2 → 3, "no changes". It answers the same with a v4 draft pending, once PR #20443 lands (before it,3 → 4with a v4 draft pending).The builder who has just published sees an empty diff. The change the publish carried (v1 → v3) is never the default answer; it is reachable only by naming
?from=1&to=3.Why
diffMetaItem'sfromVersiondefault is "the history version immediately before the to side" (packages/metadata-protocol/src/protocol.ts,diffMetaItem).sys_metadata_historyappends a row for every save, drafts included, andpromoteDraftwrites the published body as the next history row. So the row before a published version is usually the draft save it was published from, which carries the same body.This is the documented rule, not a slip. Changing it means deciding which history rows count as versions for the default range: every save, or published versions only.
Why it is its own card
GET /meta/:type/:name/diffwith nofrom/tolabelstoVersionas the newest history row (a draft save) while it compares against the active row, so the default diff names the wrong versions #20397) fixes the to-side label only. Its claim 5868801238 forbids changing which history rows count as versions.GET /meta/:type/:name/diffserves PENDING draft content to a member with no authoring capability: its history versions include draft saves, and it is the one draft-serving door the #20338 gate leaves open #20378 carried that question as option A (a state column onsys_metadata_history). Its ruling 5865708652 took B (/diffand/historybecome authoring doors) and declined A. So no card holds it now.The remedy is triage's to route. Two readings:
Dedupe
search_issues"meta diff default range no changes after publish draft history row previous published version" inobjectstack-ai/objectstack, open and closed: 4 hits.GET /meta/:type/:name/diffwith nofrom/tolabelstoVersionas the newest history row (a draft save) while it compares against the active row, so the default diff names the wrong versions #20397 is the to-side label, which PR fix(metadata-protocol): the default /diff range labels its to side with the active row's own version #20443 fixes.GET /meta/:type/:name/diffserves PENDING draft content to a member with no authoring capability: its history versions include draft saves, and it is the one draft-serving door the #20338 gate leaves open #20378 is the/diffdraft leak and its ruling.save— publish, rollback and the 409 conflict denial never write a row #7748 is the audit trail's publish rows.publishDraft's cleanup.None is this one.
Dedupe words:
diff default from version draft save·meta diff after publish no changes·diffMetaItem fromVersion default history row