|
377 | 377 | "title": "Metadata draft→publish lifecycle: drafts staged not served, publish flips visibility atomically, conflicts and invalid drafts refused, and the history/audit/diff/rollback forensics tell the truth", |
378 | 378 | "since": "v16", |
379 | 379 | "status": "active", |
380 | | - "revision": 7, |
| 380 | + "revision": 8, |
381 | 381 | "priority": "P1", |
382 | 382 | "surface": "mixed", |
383 | 383 | "personas": ["admin (authors drafts)", "end user (must not see drafts)"], |
|
386 | 386 | "requires": [ |
387 | 387 | "scratch metadata names only (e.g. qa_lifecycle_probe) via the draft door PUT /api/v1/meta/<type>/<name>?mode=draft — no shipped showcase file is touched", |
388 | 388 | "a writable package with two stageable drafts for the package-wide publish-drafts door" |
| 389 | + ], |
| 390 | + "knownGaps": [ |
| 391 | + "NO PIN COVERS A FULL CLAUSE — `automated` was dropped at revision 8, so this P1 item is hand-driven (Tier 2). packages/qa/dogfood/test/dashboard-designer-roundtrip.dogfood.test.ts, the pin it cited, saves a layout-less dashboard as a draft (PUT ?mode=draft answers 200), publishes it (200) and reads it back as { type, name, item } with its three widgets. That is acceptance[1]'s post-publish half and nothing more: it asserts no state:'draft' receipt and makes no pre-publish read (acceptance[0], and acceptance[1]'s never-served half), and it probes none of acceptance[2]–[11]: no second draft, stale If-Match, publish-drafts batch, invalid draft, Studio chrome, history, diff, rollback, audit or X-Actor. So it scores no clause (Tier 1 run #24598: every clause not-run). Re-add `automated` only with a pin that asserts a full clause." |
389 | 392 | ] |
390 | 393 | }, |
391 | 394 | "steps": [ |
|
486 | 489 | "OPEN LEDGER QUESTION, not a verdict (run #7695 → #7753 item 2): publish-drafts' namespace-gate abort answers HTTP 200 with data.success:false rather than a 4xx. The envelope-level success flag may well be the intended contract for this door, and the atomicity behind it is correct (the abort leaves both names 404) — but an HTTP-status-only client reads an aborted publish as a successful one, which is why it is worth ONE deliberate ruling. Recorded here so the observation is not re-derived every run; a runner does not adjudicate it and does not score it as a FAIL" |
487 | 490 | ], |
488 | 491 | "traps": ["hydration-race", "dispatcher-vs-hono-route"], |
489 | | - "automated": { "kind": "e2e", "ref": "packages/qa/dogfood/test/dashboard-designer-roundtrip.dogfood.test.ts" }, |
490 | 492 | "source": [ |
491 | 493 | "packages/spec/src/api/protocol.zod.ts#SaveMetaItemResponse (SaveMetaItemResponse: state draft|active, version as If-Match/409 OCC token, 'staged only — not served until published')", |
492 | 494 | "packages/runtime/src/domains/packages.ts#packages (POST /packages/:id/publish-drafts, ADR-0033/ADR-0045 visibility flip + its failure warning)", |
|
503 | 505 | { "revision": 4, "date": "2026-08-17", "change": "re-spell after [#7941]: the rollback step and the audit clause named X-Actor as an alternate actor source alongside the session identity; #7941 removed the header limb from resolveMetaWriteActor entirely (landed as commit 4dc8a618e, PR #9119) so it is now the SOLE source and X-Actor is ignored outright, not consulted even as a fallback. Re-spelled the rollback step, the audit acceptance clause, and the rest-server.ts source pointer to name the single source; added a new step + acceptance clause pairing the inverted check the finding asked for — send X-Actor and confirm it does NOT change the recorded actor — since that is now a meaningful QA-layer assertion nothing else covers (the unit pins live in packages/rest/src/meta-write-actor-identity.test.ts, added as a source pointer). The capability itself (audit rows name the acting user, never anonymous) is unchanged and was never wrong.", "ref": "#9118" }, |
504 | 506 | { "revision": 5, "date": "2026-10-13", "change": "steps[9] and acceptance[8] (clause and verify) diff the two publish versions read off /history, and steps[8] and acceptance[7].verify say how history counts (assertion defect, #23166 A8; parked on #23121, carried by #23169). sys_metadata_history records draft saves and publishes alike, so ?from=1&to=2 compared the first draft save with its own publish (changed []); on QA run #23166's clean two-round run the published revisions were v2 and v4, and their diff named the edited widget key. The rollback steps are unchanged", "ref": "#23169" }, |
505 | 507 | { "revision": 6, "date": "2026-10-16", "change": "steps[2] and acceptance[6] (clause, verify) re-pointed (checklist-accuracy finding 4 of QA run #23942, wave #23878). The Studio counter is no longer 'Changes · n' text but a numbered pill on the Changes button (objectui#12459), and the pill counts the drafts of the package in scope — an env-wide (package-less) dashboard draft is counted in none, so #23942 staged the browser leg's draft in a writable package. The step and clause name the pill and the writable-package staging, and the step says how to reach the draft in Studio — through an app of that package whose navigation names the dashboard, since a package with no app offers no dashboard to select (the re-run on #24036 found no chip until it staged one). Not loosened: a chip or pill that survives the publish, or is missing while the draft is pending, still FAILS", "ref": "#24036" }, |
506 | | - { "revision": 7, "date": "2026-10-19", "change": "steps[2], acceptance[6].clause and acceptance[6].verify corrected from QA run #24604 (18.0 sweep round 2, ba4afcc2), re-read at the console pin 4016370af3c9: the Studio item header reads 'Draft · N unpublished' (engine.studio.itemDraftPending, objectui#12725) — 'Unpublished draft' is the chip of other surfaces (ObjectListViewInspector, the OWD overview), not this item header — and a REST publish shows in Studio only after a reload. The round's other draft notes are not taken: no step of this item discards a draft (so the ?state=draft discard spelling has no clause to correct), and the NS_ prefix a scratch dashboard was given is not required (the namespace-prefix rule judges objects only — packages/spec/src/kernel/namespace-prefix.ts). Wave anchor #24579 round 2 §3 (6272314386)", "ref": "#24671" } |
| 508 | + { "revision": 7, "date": "2026-10-19", "change": "steps[2], acceptance[6].clause and acceptance[6].verify corrected from QA run #24604 (18.0 sweep round 2, ba4afcc2), re-read at the console pin 4016370af3c9: the Studio item header reads 'Draft · N unpublished' (engine.studio.itemDraftPending, objectui#12725) — 'Unpublished draft' is the chip of other surfaces (ObjectListViewInspector, the OWD overview), not this item header — and a REST publish shows in Studio only after a reload. The round's other draft notes are not taken: no step of this item discards a draft (so the ?state=draft discard spelling has no clause to correct), and the NS_ prefix a scratch dashboard was given is not required (the namespace-prefix rule judges objects only — packages/spec/src/kernel/namespace-prefix.ts). Wave anchor #24579 round 2 §3 (6272314386)", "ref": "#24671" }, |
| 509 | + { "revision": 8, "date": "2026-10-20", "change": "automated dropped and fixtures.knownGaps[0] added — §2 theme \"pins that cover no full clause\" of wave anchor #24579 (18.0 sweep), one of the leftovers round 6 (#24697) named. Tier 1 run #24598 scored every clause not-run on dashboard-designer-roundtrip.dogfood.test.ts, green 3/3 at ba4afcc2: it saves, publishes and reads back a layout-less dashboard, which is acceptance[1]'s post-publish half and no full clause. Round 1's QA run #24571 had scored acceptance[0]–[5] and [7]–[11] pass on that pin alone; QA run #24604 drove acceptance[6] and negative[0]–[4] by hand. The item had no knownGaps, so the line is new: it says what the pin asserts and when `automated` may return. The item is now Tier 2 (P1, no pin). No clause changed", "ref": "#PENDING-24579R8" } |
507 | 510 | ] |
508 | 511 | }, |
509 | 512 | { |
|
0 commit comments