mirror of
https://github.com/larksuite/cli.git
synced 2026-07-06 16:18:05 +08:00
feat: 增加 beautiful 模板人工审查闭环
新增 34 套 family 的本地人工审查面板和 JSON 导出。 新增 human review receipt apply 脚本,生成可追溯的 pending/pass/needs_fix/reject 结果。 人工 receipt 不直接修改 production/default_selectable,当前默认链路仍只有 blue-professional。
This commit is contained in:
@@ -19,27 +19,175 @@
|
||||
h2 { margin: 10px 0 4px; font-size: 15px; }
|
||||
p { margin: 5px 0; font-size: 12px; color: #536071; }
|
||||
code { word-break: break-all; font-size: 11px; }
|
||||
button { cursor: pointer; border: 1px solid #b8c2d2; background: #fff; color: #172033; border-radius: 6px; padding: 6px 9px; font-weight: 700; }
|
||||
button.selected { border-color: #1d4ed8; background: #dbeafe; color: #1e3a8a; }
|
||||
.badge { display: inline-block; border-radius: 999px; padding: 2px 7px; font-size: 11px; font-weight: 700; }
|
||||
.ok { color: #065f46; background: #d1fae5; }
|
||||
.warn { color: #92400e; background: #fef3c7; }
|
||||
.bad { color: #991b1b; background: #fee2e2; }
|
||||
.review-panel, .review-handoff { background: #fff; border: 1px solid #dfe5ee; border-radius: 8px; padding: 14px; margin: 16px 0; }
|
||||
.decision-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
|
||||
.review-current { font-size: 12px; color: #536071; margin-bottom: 8px; }
|
||||
.notes-label { display: block; color: #536071; font-size: 12px; }
|
||||
.notes-label input { margin-left: 8px; min-width: min(520px, 80vw); padding: 6px 8px; border: 1px solid #c7d0df; border-radius: 6px; }
|
||||
.decision-template { margin-top: 10px; }
|
||||
pre, textarea { width: 100%; box-sizing: border-box; border: 1px solid #c7d0df; border-radius: 6px; background: #f8fafc; color: #172033; }
|
||||
pre { overflow: auto; padding: 10px; font-size: 12px; }
|
||||
textarea { min-height: 180px; padding: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<p><a href="../index.html">Back to gallery</a></p>
|
||||
<h1>8-bit-orbit</h1>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt.</div>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt and does not automatically modify production/default.</div>
|
||||
<div class="meta">
|
||||
<div class="metric"><strong>10</strong>source pages</div>
|
||||
<div class="metric"><strong>blocked</strong>auto gate</div>
|
||||
<div class="metric"><strong>missing</strong>smoke</div>
|
||||
<div class="metric"><strong>passed</strong>fidelity</div>
|
||||
</div>
|
||||
<div class="review-panel">
|
||||
<h2>Human decision</h2>
|
||||
<div class="review-control" data-review-control-for="8-bit-orbit"><div class="decision-buttons"><button type="button" data-family-id="8-bit-orbit" data-review-status="pass">pass</button><button type="button" data-family-id="8-bit-orbit" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="8-bit-orbit" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="8-bit-orbit">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="8-bit-orbit" placeholder="optional apply-script context" /></label><details class="decision-template"><summary>Copyable decision JSON fragment</summary><pre>{
|
||||
"family_id": "8-bit-orbit",
|
||||
"human_review_status_before_selection": "pending",
|
||||
"notes": "",
|
||||
"promotion_action": "no_change_until_human_pass",
|
||||
"review_status": "pass | needs_fix | reject",
|
||||
"runtime_template_id": "pixel-orbit-console",
|
||||
"source_gallery_receipt_path": "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json"
|
||||
}</pre></details></div>
|
||||
</div>
|
||||
<p><strong>Known blockers:</strong> auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</p>
|
||||
</header>
|
||||
<section class="review-handoff">
|
||||
<h2>Human Review Export</h2>
|
||||
<div class="warning">This local UI does not automatically modify production/default. It only stores browser-local decisions and exports JSON for a separate apply script.</div>
|
||||
<p><code>human_review_status=pending</code> <code>promotion_action=no_change_until_human_pass</code></p>
|
||||
<p>Machine-readable gallery receipt: <code>skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json</code></p>
|
||||
<p>Apply script input: save this textarea as decisions JSON, then pass it to the apply script, for example <code>python <apply-script> --gallery-receipt skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json --decisions <exported-decisions.json></code>.</p>
|
||||
<textarea id="review-decisions-json" readonly spellcheck="false"></textarea>
|
||||
</section>
|
||||
|
||||
<main class="deck">
|
||||
<section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/8-bit-orbit-1.png" alt="slide-1" /></div><h2>1. slide-1</h2><p>cover / cover</p><p><span class="badge bad">missing_smoke</span></p><p><code>data-slide-1</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/8-bit-orbit-1.png" alt="slide-2" /></div><h2>2. slide-2</h2><p>agenda / agenda</p><p><span class="badge bad">missing_smoke</span></p><p><code>data-slide-2</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/8-bit-orbit-1.png" alt="slide-3" /></div><h2>3. slide-3</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>data-slide-3</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/8-bit-orbit-1.png" alt="slide-4" /></div><h2>4. slide-4</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>data-slide-4</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/8-bit-orbit-5.png" alt="slide-5" /></div><h2>5. slide-5</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>data-slide-5</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/8-bit-orbit-6.png" alt="slide-6" /></div><h2>6. slide-6</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge bad">missing_smoke</span></p><p><code>data-slide-6</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/8-bit-orbit-1.png" alt="slide-7" /></div><h2>7. slide-7</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>data-slide-7</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/8-bit-orbit-1.png" alt="slide-8" /></div><h2>8. slide-8</h2><p>quote_or_emphasis / quote_or_emphasis</p><p><span class="badge bad">missing_smoke</span></p><p><code>data-slide-8</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/8-bit-orbit-1.png" alt="slide-9" /></div><h2>9. slide-9</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>data-slide-9</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/8-bit-orbit-1.png" alt="slide-10" /></div><h2>10. slide-10</h2><p>closing / closing</p><p><span class="badge bad">missing_smoke</span></p><p><code>data-slide-10</code></p></section>
|
||||
</main>
|
||||
<script>
|
||||
(function () {
|
||||
var storageKey = "beautiful-production-review-decisions-v1";
|
||||
var schemaVersion = "svglide-beautiful-human-review-decisions/v1";
|
||||
var reviewBatchId = "beautiful-34";
|
||||
var receiptPath = "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json";
|
||||
var pendingHumanReviewStatus = "pending";
|
||||
var promotionAction = "no_change_until_human_pass";
|
||||
|
||||
function readState() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
||||
if (parsed && typeof parsed === "object" && parsed.decisions && typeof parsed.decisions === "object") {
|
||||
return parsed;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore malformed local state and rebuild below.
|
||||
}
|
||||
return { decisions: {} };
|
||||
}
|
||||
|
||||
function writeState(state) {
|
||||
localStorage.setItem(storageKey, JSON.stringify(state));
|
||||
}
|
||||
|
||||
function buildExport(state) {
|
||||
var decisions = Object.keys(state.decisions || {}).sort().map(function (familyId) {
|
||||
return state.decisions[familyId];
|
||||
});
|
||||
return {
|
||||
schema_version: schemaVersion,
|
||||
artifact_kind: "beautiful_template_human_review_decisions",
|
||||
review_batch_id: reviewBatchId,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
not_promotion_receipt: true,
|
||||
policy: {
|
||||
does_not_automatically_modify_production_default: true,
|
||||
apply_script_must_validate_gallery_receipt: true
|
||||
},
|
||||
decisions: decisions
|
||||
};
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.querySelectorAll("[data-review-current-for]").forEach(function (node) {
|
||||
var familyId = node.getAttribute("data-review-current-for");
|
||||
var decision = state.decisions[familyId];
|
||||
node.textContent = decision ? decision.review_status : "pending";
|
||||
});
|
||||
document.querySelectorAll("[data-review-status]").forEach(function (button) {
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var decision = state.decisions[familyId];
|
||||
button.classList.toggle("selected", Boolean(decision && decision.review_status === status));
|
||||
});
|
||||
document.querySelectorAll("[data-review-notes-for]").forEach(function (input) {
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var decision = state.decisions[familyId];
|
||||
if (decision && input.value !== decision.notes) {
|
||||
input.value = decision.notes || "";
|
||||
}
|
||||
});
|
||||
var textarea = document.getElementById("review-decisions-json");
|
||||
if (textarea) {
|
||||
textarea.value = JSON.stringify(buildExport(state), null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
var button = event.target.closest("[data-review-status]");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var existing = state.decisions[familyId] || {};
|
||||
state.decisions[familyId] = {
|
||||
family_id: familyId,
|
||||
review_status: status,
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
notes: existing.notes || "",
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
document.addEventListener("input", function (event) {
|
||||
var input = event.target.closest("[data-review-notes-for]");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var existing = state.decisions[familyId] || {
|
||||
family_id: familyId,
|
||||
review_status: "needs_fix",
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
existing.notes = input.value;
|
||||
existing.updated_at = new Date().toISOString();
|
||||
state.decisions[familyId] = existing;
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
render(readState());
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/8-bit-orbit.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "86070d51ad2d5f1cef0438e4d5505c160c16f3f5b701a0ef17a950f13f520f19"
|
||||
"sha256": "6700d6ce17310762eeb43dec97eee6a0c706da5ab7082cdf6c0d0dda83a2453d"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "86070d51ad2d5f1cef0438e4d5505c160c16f3f5b701a0ef17a950f13f520f19",
|
||||
"contact_sheet": "6700d6ce17310762eeb43dec97eee6a0c706da5ab7082cdf6c0d0dda83a2453d",
|
||||
"fidelity_receipt": "31bab9cafb1fabb4453980f01a8255d16c9a79e1f882d01585b319dee779d556",
|
||||
"reference_screenshot": "c1f0517225fbe17807d69de03a7260881738d25bc456bd4151af67fabbb15281",
|
||||
"smoke_receipt": null,
|
||||
|
||||
@@ -19,27 +19,175 @@
|
||||
h2 { margin: 10px 0 4px; font-size: 15px; }
|
||||
p { margin: 5px 0; font-size: 12px; color: #536071; }
|
||||
code { word-break: break-all; font-size: 11px; }
|
||||
button { cursor: pointer; border: 1px solid #b8c2d2; background: #fff; color: #172033; border-radius: 6px; padding: 6px 9px; font-weight: 700; }
|
||||
button.selected { border-color: #1d4ed8; background: #dbeafe; color: #1e3a8a; }
|
||||
.badge { display: inline-block; border-radius: 999px; padding: 2px 7px; font-size: 11px; font-weight: 700; }
|
||||
.ok { color: #065f46; background: #d1fae5; }
|
||||
.warn { color: #92400e; background: #fef3c7; }
|
||||
.bad { color: #991b1b; background: #fee2e2; }
|
||||
.review-panel, .review-handoff { background: #fff; border: 1px solid #dfe5ee; border-radius: 8px; padding: 14px; margin: 16px 0; }
|
||||
.decision-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
|
||||
.review-current { font-size: 12px; color: #536071; margin-bottom: 8px; }
|
||||
.notes-label { display: block; color: #536071; font-size: 12px; }
|
||||
.notes-label input { margin-left: 8px; min-width: min(520px, 80vw); padding: 6px 8px; border: 1px solid #c7d0df; border-radius: 6px; }
|
||||
.decision-template { margin-top: 10px; }
|
||||
pre, textarea { width: 100%; box-sizing: border-box; border: 1px solid #c7d0df; border-radius: 6px; background: #f8fafc; color: #172033; }
|
||||
pre { overflow: auto; padding: 10px; font-size: 12px; }
|
||||
textarea { min-height: 180px; padding: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<p><a href="../index.html">Back to gallery</a></p>
|
||||
<h1>biennale-yellow</h1>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt.</div>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt and does not automatically modify production/default.</div>
|
||||
<div class="meta">
|
||||
<div class="metric"><strong>8</strong>source pages</div>
|
||||
<div class="metric"><strong>blocked</strong>auto gate</div>
|
||||
<div class="metric"><strong>missing</strong>smoke</div>
|
||||
<div class="metric"><strong>passed</strong>fidelity</div>
|
||||
</div>
|
||||
<div class="review-panel">
|
||||
<h2>Human decision</h2>
|
||||
<div class="review-control" data-review-control-for="biennale-yellow"><div class="decision-buttons"><button type="button" data-family-id="biennale-yellow" data-review-status="pass">pass</button><button type="button" data-family-id="biennale-yellow" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="biennale-yellow" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="biennale-yellow">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="biennale-yellow" placeholder="optional apply-script context" /></label><details class="decision-template"><summary>Copyable decision JSON fragment</summary><pre>{
|
||||
"family_id": "biennale-yellow",
|
||||
"human_review_status_before_selection": "pending",
|
||||
"notes": "",
|
||||
"promotion_action": "no_change_until_human_pass",
|
||||
"review_status": "pass | needs_fix | reject",
|
||||
"runtime_template_id": "biennale-programme-poster",
|
||||
"source_gallery_receipt_path": "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json"
|
||||
}</pre></details></div>
|
||||
</div>
|
||||
<p><strong>Known blockers:</strong> auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</p>
|
||||
</header>
|
||||
<section class="review-handoff">
|
||||
<h2>Human Review Export</h2>
|
||||
<div class="warning">This local UI does not automatically modify production/default. It only stores browser-local decisions and exports JSON for a separate apply script.</div>
|
||||
<p><code>human_review_status=pending</code> <code>promotion_action=no_change_until_human_pass</code></p>
|
||||
<p>Machine-readable gallery receipt: <code>skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json</code></p>
|
||||
<p>Apply script input: save this textarea as decisions JSON, then pass it to the apply script, for example <code>python <apply-script> --gallery-receipt skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json --decisions <exported-decisions.json></code>.</p>
|
||||
<textarea id="review-decisions-json" readonly spellcheck="false"></textarea>
|
||||
</section>
|
||||
|
||||
<main class="deck">
|
||||
<section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/biennale-yellow-1.png" alt="cover" /></div><h2>1. cover</h2><p>cover / cover</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-cover</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/biennale-yellow-1.png" alt="manifesto" /></div><h2>2. manifesto</h2><p>agenda / agenda</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-manifesto</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/biennale-yellow-1.png" alt="programme" /></div><h2>3. programme</h2><p>content / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-programme</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/biennale-yellow-1.png" alt="chapter" /></div><h2>4. chapter</h2><p>closing / agenda</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-chapter</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/biennale-yellow-5.png" alt="data" /></div><h2>5. data</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-data</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/biennale-yellow-1.png" alt="quote" /></div><h2>6. quote</h2><p>quote_or_emphasis / quote_or_emphasis</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-quote</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/biennale-yellow-1.png" alt="cal" /></div><h2>7. cal</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-cal</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/biennale-yellow-8.png" alt="colophon" /></div><h2>8. colophon</h2><p>closing / closing</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-colophon</code></p></section>
|
||||
</main>
|
||||
<script>
|
||||
(function () {
|
||||
var storageKey = "beautiful-production-review-decisions-v1";
|
||||
var schemaVersion = "svglide-beautiful-human-review-decisions/v1";
|
||||
var reviewBatchId = "beautiful-34";
|
||||
var receiptPath = "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json";
|
||||
var pendingHumanReviewStatus = "pending";
|
||||
var promotionAction = "no_change_until_human_pass";
|
||||
|
||||
function readState() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
||||
if (parsed && typeof parsed === "object" && parsed.decisions && typeof parsed.decisions === "object") {
|
||||
return parsed;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore malformed local state and rebuild below.
|
||||
}
|
||||
return { decisions: {} };
|
||||
}
|
||||
|
||||
function writeState(state) {
|
||||
localStorage.setItem(storageKey, JSON.stringify(state));
|
||||
}
|
||||
|
||||
function buildExport(state) {
|
||||
var decisions = Object.keys(state.decisions || {}).sort().map(function (familyId) {
|
||||
return state.decisions[familyId];
|
||||
});
|
||||
return {
|
||||
schema_version: schemaVersion,
|
||||
artifact_kind: "beautiful_template_human_review_decisions",
|
||||
review_batch_id: reviewBatchId,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
not_promotion_receipt: true,
|
||||
policy: {
|
||||
does_not_automatically_modify_production_default: true,
|
||||
apply_script_must_validate_gallery_receipt: true
|
||||
},
|
||||
decisions: decisions
|
||||
};
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.querySelectorAll("[data-review-current-for]").forEach(function (node) {
|
||||
var familyId = node.getAttribute("data-review-current-for");
|
||||
var decision = state.decisions[familyId];
|
||||
node.textContent = decision ? decision.review_status : "pending";
|
||||
});
|
||||
document.querySelectorAll("[data-review-status]").forEach(function (button) {
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var decision = state.decisions[familyId];
|
||||
button.classList.toggle("selected", Boolean(decision && decision.review_status === status));
|
||||
});
|
||||
document.querySelectorAll("[data-review-notes-for]").forEach(function (input) {
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var decision = state.decisions[familyId];
|
||||
if (decision && input.value !== decision.notes) {
|
||||
input.value = decision.notes || "";
|
||||
}
|
||||
});
|
||||
var textarea = document.getElementById("review-decisions-json");
|
||||
if (textarea) {
|
||||
textarea.value = JSON.stringify(buildExport(state), null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
var button = event.target.closest("[data-review-status]");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var existing = state.decisions[familyId] || {};
|
||||
state.decisions[familyId] = {
|
||||
family_id: familyId,
|
||||
review_status: status,
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
notes: existing.notes || "",
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
document.addEventListener("input", function (event) {
|
||||
var input = event.target.closest("[data-review-notes-for]");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var existing = state.decisions[familyId] || {
|
||||
family_id: familyId,
|
||||
review_status: "needs_fix",
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
existing.notes = input.value;
|
||||
existing.updated_at = new Date().toISOString();
|
||||
state.decisions[familyId] = existing;
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
render(readState());
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/biennale-yellow.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "d0b40a3bfc2420a4c9c8b4c9baaf3cdf08c204a8e504d0917f1458a9b90e01e8"
|
||||
"sha256": "1c72a9c2b36088f74069f44fc0226aff8002f0b3507243531da6edf96ae4aff7"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "d0b40a3bfc2420a4c9c8b4c9baaf3cdf08c204a8e504d0917f1458a9b90e01e8",
|
||||
"contact_sheet": "1c72a9c2b36088f74069f44fc0226aff8002f0b3507243531da6edf96ae4aff7",
|
||||
"fidelity_receipt": "27b20213513d6a895ae84c07aea6d784f5acd5a5fcd4b5a6baf0d1868f4a7dfe",
|
||||
"reference_screenshot": "8acd74e991ff533d6982f60fc2934ad2020d5ea8e03c5d79d00c24899d6f9e8d",
|
||||
"smoke_receipt": null,
|
||||
|
||||
@@ -19,27 +19,175 @@
|
||||
h2 { margin: 10px 0 4px; font-size: 15px; }
|
||||
p { margin: 5px 0; font-size: 12px; color: #536071; }
|
||||
code { word-break: break-all; font-size: 11px; }
|
||||
button { cursor: pointer; border: 1px solid #b8c2d2; background: #fff; color: #172033; border-radius: 6px; padding: 6px 9px; font-weight: 700; }
|
||||
button.selected { border-color: #1d4ed8; background: #dbeafe; color: #1e3a8a; }
|
||||
.badge { display: inline-block; border-radius: 999px; padding: 2px 7px; font-size: 11px; font-weight: 700; }
|
||||
.ok { color: #065f46; background: #d1fae5; }
|
||||
.warn { color: #92400e; background: #fef3c7; }
|
||||
.bad { color: #991b1b; background: #fee2e2; }
|
||||
.review-panel, .review-handoff { background: #fff; border: 1px solid #dfe5ee; border-radius: 8px; padding: 14px; margin: 16px 0; }
|
||||
.decision-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
|
||||
.review-current { font-size: 12px; color: #536071; margin-bottom: 8px; }
|
||||
.notes-label { display: block; color: #536071; font-size: 12px; }
|
||||
.notes-label input { margin-left: 8px; min-width: min(520px, 80vw); padding: 6px 8px; border: 1px solid #c7d0df; border-radius: 6px; }
|
||||
.decision-template { margin-top: 10px; }
|
||||
pre, textarea { width: 100%; box-sizing: border-box; border: 1px solid #c7d0df; border-radius: 6px; background: #f8fafc; color: #172033; }
|
||||
pre { overflow: auto; padding: 10px; font-size: 12px; }
|
||||
textarea { min-height: 180px; padding: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<p><a href="../index.html">Back to gallery</a></p>
|
||||
<h1>block-frame</h1>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt.</div>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt and does not automatically modify production/default.</div>
|
||||
<div class="meta">
|
||||
<div class="metric"><strong>10</strong>source pages</div>
|
||||
<div class="metric"><strong>blocked</strong>auto gate</div>
|
||||
<div class="metric"><strong>missing</strong>smoke</div>
|
||||
<div class="metric"><strong>passed</strong>fidelity</div>
|
||||
</div>
|
||||
<div class="review-panel">
|
||||
<h2>Human decision</h2>
|
||||
<div class="review-control" data-review-control-for="block-frame"><div class="decision-buttons"><button type="button" data-family-id="block-frame" data-review-status="pass">pass</button><button type="button" data-family-id="block-frame" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="block-frame" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="block-frame">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="block-frame" placeholder="optional apply-script context" /></label><details class="decision-template"><summary>Copyable decision JSON fragment</summary><pre>{
|
||||
"family_id": "block-frame",
|
||||
"human_review_status_before_selection": "pending",
|
||||
"notes": "",
|
||||
"promotion_action": "no_change_until_human_pass",
|
||||
"review_status": "pass | needs_fix | reject",
|
||||
"runtime_template_id": "block-frame-grid",
|
||||
"source_gallery_receipt_path": "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json"
|
||||
}</pre></details></div>
|
||||
</div>
|
||||
<p><strong>Known blockers:</strong> auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</p>
|
||||
</header>
|
||||
<section class="review-handoff">
|
||||
<h2>Human Review Export</h2>
|
||||
<div class="warning">This local UI does not automatically modify production/default. It only stores browser-local decisions and exports JSON for a separate apply script.</div>
|
||||
<p><code>human_review_status=pending</code> <code>promotion_action=no_change_until_human_pass</code></p>
|
||||
<p>Machine-readable gallery receipt: <code>skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json</code></p>
|
||||
<p>Apply script input: save this textarea as decisions JSON, then pass it to the apply script, for example <code>python <apply-script> --gallery-receipt skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json --decisions <exported-decisions.json></code>.</p>
|
||||
<textarea id="review-decisions-json" readonly spellcheck="false"></textarea>
|
||||
</section>
|
||||
|
||||
<main class="deck">
|
||||
<section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/block-frame-1.png" alt="cover" /></div><h2>1. cover</h2><p>cover / cover</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-1</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/block-frame-1.png" alt="agenda" /></div><h2>2. agenda</h2><p>agenda / agenda</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-2</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/block-frame-1.png" alt="data_dashboard" /></div><h2>3. data_dashboard</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-3</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/block-frame-4.png" alt="data_dashboard-4" /></div><h2>4. data_dashboard-4</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-4</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/block-frame-1.png" alt="quote_or_emphasis" /></div><h2>5. quote_or_emphasis</h2><p>quote_or_emphasis / quote_or_emphasis</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-5</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/block-frame-1.png" alt="process_or_timeline" /></div><h2>6. process_or_timeline</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-6</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/block-frame-1.png" alt="process_or_timeline-7" /></div><h2>7. process_or_timeline-7</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-7</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/block-frame-8.png" alt="data_dashboard-8" /></div><h2>8. data_dashboard-8</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-8</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/block-frame-1.png" alt="process_or_timeline-9" /></div><h2>9. process_or_timeline-9</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-9</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/block-frame-1.png" alt="closing" /></div><h2>10. closing</h2><p>closing / closing</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-10</code></p></section>
|
||||
</main>
|
||||
<script>
|
||||
(function () {
|
||||
var storageKey = "beautiful-production-review-decisions-v1";
|
||||
var schemaVersion = "svglide-beautiful-human-review-decisions/v1";
|
||||
var reviewBatchId = "beautiful-34";
|
||||
var receiptPath = "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json";
|
||||
var pendingHumanReviewStatus = "pending";
|
||||
var promotionAction = "no_change_until_human_pass";
|
||||
|
||||
function readState() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
||||
if (parsed && typeof parsed === "object" && parsed.decisions && typeof parsed.decisions === "object") {
|
||||
return parsed;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore malformed local state and rebuild below.
|
||||
}
|
||||
return { decisions: {} };
|
||||
}
|
||||
|
||||
function writeState(state) {
|
||||
localStorage.setItem(storageKey, JSON.stringify(state));
|
||||
}
|
||||
|
||||
function buildExport(state) {
|
||||
var decisions = Object.keys(state.decisions || {}).sort().map(function (familyId) {
|
||||
return state.decisions[familyId];
|
||||
});
|
||||
return {
|
||||
schema_version: schemaVersion,
|
||||
artifact_kind: "beautiful_template_human_review_decisions",
|
||||
review_batch_id: reviewBatchId,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
not_promotion_receipt: true,
|
||||
policy: {
|
||||
does_not_automatically_modify_production_default: true,
|
||||
apply_script_must_validate_gallery_receipt: true
|
||||
},
|
||||
decisions: decisions
|
||||
};
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.querySelectorAll("[data-review-current-for]").forEach(function (node) {
|
||||
var familyId = node.getAttribute("data-review-current-for");
|
||||
var decision = state.decisions[familyId];
|
||||
node.textContent = decision ? decision.review_status : "pending";
|
||||
});
|
||||
document.querySelectorAll("[data-review-status]").forEach(function (button) {
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var decision = state.decisions[familyId];
|
||||
button.classList.toggle("selected", Boolean(decision && decision.review_status === status));
|
||||
});
|
||||
document.querySelectorAll("[data-review-notes-for]").forEach(function (input) {
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var decision = state.decisions[familyId];
|
||||
if (decision && input.value !== decision.notes) {
|
||||
input.value = decision.notes || "";
|
||||
}
|
||||
});
|
||||
var textarea = document.getElementById("review-decisions-json");
|
||||
if (textarea) {
|
||||
textarea.value = JSON.stringify(buildExport(state), null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
var button = event.target.closest("[data-review-status]");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var existing = state.decisions[familyId] || {};
|
||||
state.decisions[familyId] = {
|
||||
family_id: familyId,
|
||||
review_status: status,
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
notes: existing.notes || "",
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
document.addEventListener("input", function (event) {
|
||||
var input = event.target.closest("[data-review-notes-for]");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var existing = state.decisions[familyId] || {
|
||||
family_id: familyId,
|
||||
review_status: "needs_fix",
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
existing.notes = input.value;
|
||||
existing.updated_at = new Date().toISOString();
|
||||
state.decisions[familyId] = existing;
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
render(readState());
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/block-frame.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "e1eebb164177c32de707e461d85253b10fd4789cddd64ec87f390779f2b69802"
|
||||
"sha256": "cfd16fda1c5b8104b5e6f3c990b3fc2d2b829f79deaea3dae5cb1157444ea9e6"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "e1eebb164177c32de707e461d85253b10fd4789cddd64ec87f390779f2b69802",
|
||||
"contact_sheet": "cfd16fda1c5b8104b5e6f3c990b3fc2d2b829f79deaea3dae5cb1157444ea9e6",
|
||||
"fidelity_receipt": "e35a3eb5441b55568413e926f2275e9593c0b01d95a4345337995c995ffffd95",
|
||||
"reference_screenshot": "3fd1774d38f1bfbda05df46fc7f2b98a1780de45ced4d71f4925136bbf2460a0",
|
||||
"smoke_receipt": null,
|
||||
|
||||
@@ -19,27 +19,175 @@
|
||||
h2 { margin: 10px 0 4px; font-size: 15px; }
|
||||
p { margin: 5px 0; font-size: 12px; color: #536071; }
|
||||
code { word-break: break-all; font-size: 11px; }
|
||||
button { cursor: pointer; border: 1px solid #b8c2d2; background: #fff; color: #172033; border-radius: 6px; padding: 6px 9px; font-weight: 700; }
|
||||
button.selected { border-color: #1d4ed8; background: #dbeafe; color: #1e3a8a; }
|
||||
.badge { display: inline-block; border-radius: 999px; padding: 2px 7px; font-size: 11px; font-weight: 700; }
|
||||
.ok { color: #065f46; background: #d1fae5; }
|
||||
.warn { color: #92400e; background: #fef3c7; }
|
||||
.bad { color: #991b1b; background: #fee2e2; }
|
||||
.review-panel, .review-handoff { background: #fff; border: 1px solid #dfe5ee; border-radius: 8px; padding: 14px; margin: 16px 0; }
|
||||
.decision-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
|
||||
.review-current { font-size: 12px; color: #536071; margin-bottom: 8px; }
|
||||
.notes-label { display: block; color: #536071; font-size: 12px; }
|
||||
.notes-label input { margin-left: 8px; min-width: min(520px, 80vw); padding: 6px 8px; border: 1px solid #c7d0df; border-radius: 6px; }
|
||||
.decision-template { margin-top: 10px; }
|
||||
pre, textarea { width: 100%; box-sizing: border-box; border: 1px solid #c7d0df; border-radius: 6px; background: #f8fafc; color: #172033; }
|
||||
pre { overflow: auto; padding: 10px; font-size: 12px; }
|
||||
textarea { min-height: 180px; padding: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<p><a href="../index.html">Back to gallery</a></p>
|
||||
<h1>blue-professional</h1>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt.</div>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt and does not automatically modify production/default.</div>
|
||||
<div class="meta">
|
||||
<div class="metric"><strong>10</strong>source pages</div>
|
||||
<div class="metric"><strong>passed</strong>auto gate</div>
|
||||
<div class="metric"><strong>passed</strong>smoke</div>
|
||||
<div class="metric"><strong>passed</strong>fidelity</div>
|
||||
</div>
|
||||
<div class="review-panel">
|
||||
<h2>Human decision</h2>
|
||||
<div class="review-control" data-review-control-for="blue-professional"><div class="decision-buttons"><button type="button" data-family-id="blue-professional" data-review-status="pass">pass</button><button type="button" data-family-id="blue-professional" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="blue-professional" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="blue-professional">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="blue-professional" placeholder="optional apply-script context" /></label><details class="decision-template"><summary>Copyable decision JSON fragment</summary><pre>{
|
||||
"family_id": "blue-professional",
|
||||
"human_review_status_before_selection": "pending",
|
||||
"notes": "",
|
||||
"promotion_action": "no_change_until_human_pass",
|
||||
"review_status": "pass | needs_fix | reject",
|
||||
"runtime_template_id": "executive-dashboard",
|
||||
"source_gallery_receipt_path": "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json"
|
||||
}</pre></details></div>
|
||||
</div>
|
||||
<p><strong>Known blockers:</strong> none</p>
|
||||
</header>
|
||||
<section class="review-handoff">
|
||||
<h2>Human Review Export</h2>
|
||||
<div class="warning">This local UI does not automatically modify production/default. It only stores browser-local decisions and exports JSON for a separate apply script.</div>
|
||||
<p><code>human_review_status=pending</code> <code>promotion_action=no_change_until_human_pass</code></p>
|
||||
<p>Machine-readable gallery receipt: <code>skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json</code></p>
|
||||
<p>Apply script input: save this textarea as decisions JSON, then pass it to the apply script, for example <code>python <apply-script> --gallery-receipt skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json --decisions <exported-decisions.json></code>.</p>
|
||||
<textarea id="review-decisions-json" readonly spellcheck="false"></textarea>
|
||||
</section>
|
||||
|
||||
<main class="deck">
|
||||
<section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/blue-professional-1.png" alt="cover" /></div><h2>1. cover</h2><p>cover / cover</p><p><span class="badge ok">passed</span></p><p><code>layout-cover</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/blue-professional-1.png" alt="agenda" /></div><h2>2. agenda</h2><p>agenda / agenda</p><p><span class="badge ok">passed</span></p><p><code>layout-agenda</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/blue-professional-1.png" alt="metrics" /></div><h2>3. metrics</h2><p>data_metrics / data_or_structured</p><p><span class="badge ok">passed</span></p><p><code>layout-metrics</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/blue-professional-1.png" alt="dashboard" /></div><h2>4. dashboard</h2><p>data_dashboard / data_or_structured</p><p><span class="badge ok">passed</span></p><p><code>layout-dashboard</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/blue-professional-1.png" alt="split" /></div><h2>5. split</h2><p>content_split / comparison_or_split</p><p><span class="badge ok">passed</span></p><p><code>layout-split</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/blue-professional-6.png" alt="bars" /></div><h2>6. bars</h2><p>data_chart / data_or_structured</p><p><span class="badge ok">passed</span></p><p><code>layout-bars</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/blue-professional-1.png" alt="quote" /></div><h2>7. quote</h2><p>quote_or_emphasis / quote_or_emphasis</p><p><span class="badge ok">passed</span></p><p><code>layout-quote</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/blue-professional-8.png" alt="timeline" /></div><h2>8. timeline</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge ok">passed</span></p><p><code>layout-timeline</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/blue-professional-1.png" alt="detail" /></div><h2>9. detail</h2><p>detail / content</p><p><span class="badge ok">passed</span></p><p><code>layout-detail</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/blue-professional-1.png" alt="closing" /></div><h2>10. closing</h2><p>closing / closing</p><p><span class="badge ok">passed</span></p><p><code>layout-closing</code></p></section>
|
||||
</main>
|
||||
<script>
|
||||
(function () {
|
||||
var storageKey = "beautiful-production-review-decisions-v1";
|
||||
var schemaVersion = "svglide-beautiful-human-review-decisions/v1";
|
||||
var reviewBatchId = "beautiful-34";
|
||||
var receiptPath = "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json";
|
||||
var pendingHumanReviewStatus = "pending";
|
||||
var promotionAction = "no_change_until_human_pass";
|
||||
|
||||
function readState() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
||||
if (parsed && typeof parsed === "object" && parsed.decisions && typeof parsed.decisions === "object") {
|
||||
return parsed;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore malformed local state and rebuild below.
|
||||
}
|
||||
return { decisions: {} };
|
||||
}
|
||||
|
||||
function writeState(state) {
|
||||
localStorage.setItem(storageKey, JSON.stringify(state));
|
||||
}
|
||||
|
||||
function buildExport(state) {
|
||||
var decisions = Object.keys(state.decisions || {}).sort().map(function (familyId) {
|
||||
return state.decisions[familyId];
|
||||
});
|
||||
return {
|
||||
schema_version: schemaVersion,
|
||||
artifact_kind: "beautiful_template_human_review_decisions",
|
||||
review_batch_id: reviewBatchId,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
not_promotion_receipt: true,
|
||||
policy: {
|
||||
does_not_automatically_modify_production_default: true,
|
||||
apply_script_must_validate_gallery_receipt: true
|
||||
},
|
||||
decisions: decisions
|
||||
};
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.querySelectorAll("[data-review-current-for]").forEach(function (node) {
|
||||
var familyId = node.getAttribute("data-review-current-for");
|
||||
var decision = state.decisions[familyId];
|
||||
node.textContent = decision ? decision.review_status : "pending";
|
||||
});
|
||||
document.querySelectorAll("[data-review-status]").forEach(function (button) {
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var decision = state.decisions[familyId];
|
||||
button.classList.toggle("selected", Boolean(decision && decision.review_status === status));
|
||||
});
|
||||
document.querySelectorAll("[data-review-notes-for]").forEach(function (input) {
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var decision = state.decisions[familyId];
|
||||
if (decision && input.value !== decision.notes) {
|
||||
input.value = decision.notes || "";
|
||||
}
|
||||
});
|
||||
var textarea = document.getElementById("review-decisions-json");
|
||||
if (textarea) {
|
||||
textarea.value = JSON.stringify(buildExport(state), null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
var button = event.target.closest("[data-review-status]");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var existing = state.decisions[familyId] || {};
|
||||
state.decisions[familyId] = {
|
||||
family_id: familyId,
|
||||
review_status: status,
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
notes: existing.notes || "",
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
document.addEventListener("input", function (event) {
|
||||
var input = event.target.closest("[data-review-notes-for]");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var existing = state.decisions[familyId] || {
|
||||
family_id: familyId,
|
||||
review_status: "needs_fix",
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
existing.notes = input.value;
|
||||
existing.updated_at = new Date().toISOString();
|
||||
state.decisions[familyId] = existing;
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
render(readState());
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/blue-professional.html",
|
||||
"render_status": "passed",
|
||||
"sha256": "28d5646879b9daf6f8841e968e2337c2dceb316feea8bd83ae416ae65f54a7d2"
|
||||
"sha256": "315b18dd7cd44f6cb18061c82b58a74a54c88ca797b93232011edb322653e51b"
|
||||
},
|
||||
"default_selectable": true,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "28d5646879b9daf6f8841e968e2337c2dceb316feea8bd83ae416ae65f54a7d2",
|
||||
"contact_sheet": "315b18dd7cd44f6cb18061c82b58a74a54c88ca797b93232011edb322653e51b",
|
||||
"fidelity_receipt": "f6a4a0a015c09f14cb9e987f69734cbb05a06e79bba9c9b1ba2ca16ed6bc597a",
|
||||
"reference_screenshot": "0f08aefe70cb14ca7f3126ecc2f34319ca8f281ecdf81c6d6486ea93b2236f8c",
|
||||
"smoke_receipt": "ae3cfa9a3ba970c0f4d6903148d7291375019dd3d12a8c3619599c5520742804",
|
||||
|
||||
@@ -19,27 +19,175 @@
|
||||
h2 { margin: 10px 0 4px; font-size: 15px; }
|
||||
p { margin: 5px 0; font-size: 12px; color: #536071; }
|
||||
code { word-break: break-all; font-size: 11px; }
|
||||
button { cursor: pointer; border: 1px solid #b8c2d2; background: #fff; color: #172033; border-radius: 6px; padding: 6px 9px; font-weight: 700; }
|
||||
button.selected { border-color: #1d4ed8; background: #dbeafe; color: #1e3a8a; }
|
||||
.badge { display: inline-block; border-radius: 999px; padding: 2px 7px; font-size: 11px; font-weight: 700; }
|
||||
.ok { color: #065f46; background: #d1fae5; }
|
||||
.warn { color: #92400e; background: #fef3c7; }
|
||||
.bad { color: #991b1b; background: #fee2e2; }
|
||||
.review-panel, .review-handoff { background: #fff; border: 1px solid #dfe5ee; border-radius: 8px; padding: 14px; margin: 16px 0; }
|
||||
.decision-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
|
||||
.review-current { font-size: 12px; color: #536071; margin-bottom: 8px; }
|
||||
.notes-label { display: block; color: #536071; font-size: 12px; }
|
||||
.notes-label input { margin-left: 8px; min-width: min(520px, 80vw); padding: 6px 8px; border: 1px solid #c7d0df; border-radius: 6px; }
|
||||
.decision-template { margin-top: 10px; }
|
||||
pre, textarea { width: 100%; box-sizing: border-box; border: 1px solid #c7d0df; border-radius: 6px; background: #f8fafc; color: #172033; }
|
||||
pre { overflow: auto; padding: 10px; font-size: 12px; }
|
||||
textarea { min-height: 180px; padding: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<p><a href="../index.html">Back to gallery</a></p>
|
||||
<h1>bold-poster</h1>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt.</div>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt and does not automatically modify production/default.</div>
|
||||
<div class="meta">
|
||||
<div class="metric"><strong>10</strong>source pages</div>
|
||||
<div class="metric"><strong>blocked</strong>auto gate</div>
|
||||
<div class="metric"><strong>missing</strong>smoke</div>
|
||||
<div class="metric"><strong>passed</strong>fidelity</div>
|
||||
</div>
|
||||
<div class="review-panel">
|
||||
<h2>Human decision</h2>
|
||||
<div class="review-control" data-review-control-for="bold-poster"><div class="decision-buttons"><button type="button" data-family-id="bold-poster" data-review-status="pass">pass</button><button type="button" data-family-id="bold-poster" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="bold-poster" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="bold-poster">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="bold-poster" placeholder="optional apply-script context" /></label><details class="decision-template"><summary>Copyable decision JSON fragment</summary><pre>{
|
||||
"family_id": "bold-poster",
|
||||
"human_review_status_before_selection": "pending",
|
||||
"notes": "",
|
||||
"promotion_action": "no_change_until_human_pass",
|
||||
"review_status": "pass | needs_fix | reject",
|
||||
"runtime_template_id": "poster-stat-punch",
|
||||
"source_gallery_receipt_path": "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json"
|
||||
}</pre></details></div>
|
||||
</div>
|
||||
<p><strong>Known blockers:</strong> auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</p>
|
||||
</header>
|
||||
<section class="review-handoff">
|
||||
<h2>Human Review Export</h2>
|
||||
<div class="warning">This local UI does not automatically modify production/default. It only stores browser-local decisions and exports JSON for a separate apply script.</div>
|
||||
<p><code>human_review_status=pending</code> <code>promotion_action=no_change_until_human_pass</code></p>
|
||||
<p>Machine-readable gallery receipt: <code>skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json</code></p>
|
||||
<p>Apply script input: save this textarea as decisions JSON, then pass it to the apply script, for example <code>python <apply-script> --gallery-receipt skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json --decisions <exported-decisions.json></code>.</p>
|
||||
<textarea id="review-decisions-json" readonly spellcheck="false"></textarea>
|
||||
</section>
|
||||
|
||||
<main class="deck">
|
||||
<section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/bold-poster-1.png" alt="hero" /></div><h2>1. hero</h2><p>cover / cover</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-hero</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/bold-poster-1.png" alt="red" /></div><h2>2. red</h2><p>agenda / agenda</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-red</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/bold-poster-1.png" alt="summary" /></div><h2>3. summary</h2><p>detail / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-summary</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/bold-poster-4.png" alt="financial" /></div><h2>4. financial</h2><p>content / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-financial</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/bold-poster-1.png" alt="stat" /></div><h2>5. stat</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-stat</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/bold-poster-1.png" alt="services" /></div><h2>6. services</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-services</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/bold-poster-1.png" alt="roadmap" /></div><h2>7. roadmap</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-roadmap</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/bold-poster-8.png" alt="pillars" /></div><h2>8. pillars</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-pillars</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/bold-poster-1.png" alt="global" /></div><h2>9. global</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-global</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/bold-poster-1.png" alt="close" /></div><h2>10. close</h2><p>closing / closing</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-close</code></p></section>
|
||||
</main>
|
||||
<script>
|
||||
(function () {
|
||||
var storageKey = "beautiful-production-review-decisions-v1";
|
||||
var schemaVersion = "svglide-beautiful-human-review-decisions/v1";
|
||||
var reviewBatchId = "beautiful-34";
|
||||
var receiptPath = "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json";
|
||||
var pendingHumanReviewStatus = "pending";
|
||||
var promotionAction = "no_change_until_human_pass";
|
||||
|
||||
function readState() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
||||
if (parsed && typeof parsed === "object" && parsed.decisions && typeof parsed.decisions === "object") {
|
||||
return parsed;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore malformed local state and rebuild below.
|
||||
}
|
||||
return { decisions: {} };
|
||||
}
|
||||
|
||||
function writeState(state) {
|
||||
localStorage.setItem(storageKey, JSON.stringify(state));
|
||||
}
|
||||
|
||||
function buildExport(state) {
|
||||
var decisions = Object.keys(state.decisions || {}).sort().map(function (familyId) {
|
||||
return state.decisions[familyId];
|
||||
});
|
||||
return {
|
||||
schema_version: schemaVersion,
|
||||
artifact_kind: "beautiful_template_human_review_decisions",
|
||||
review_batch_id: reviewBatchId,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
not_promotion_receipt: true,
|
||||
policy: {
|
||||
does_not_automatically_modify_production_default: true,
|
||||
apply_script_must_validate_gallery_receipt: true
|
||||
},
|
||||
decisions: decisions
|
||||
};
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.querySelectorAll("[data-review-current-for]").forEach(function (node) {
|
||||
var familyId = node.getAttribute("data-review-current-for");
|
||||
var decision = state.decisions[familyId];
|
||||
node.textContent = decision ? decision.review_status : "pending";
|
||||
});
|
||||
document.querySelectorAll("[data-review-status]").forEach(function (button) {
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var decision = state.decisions[familyId];
|
||||
button.classList.toggle("selected", Boolean(decision && decision.review_status === status));
|
||||
});
|
||||
document.querySelectorAll("[data-review-notes-for]").forEach(function (input) {
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var decision = state.decisions[familyId];
|
||||
if (decision && input.value !== decision.notes) {
|
||||
input.value = decision.notes || "";
|
||||
}
|
||||
});
|
||||
var textarea = document.getElementById("review-decisions-json");
|
||||
if (textarea) {
|
||||
textarea.value = JSON.stringify(buildExport(state), null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
var button = event.target.closest("[data-review-status]");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var existing = state.decisions[familyId] || {};
|
||||
state.decisions[familyId] = {
|
||||
family_id: familyId,
|
||||
review_status: status,
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
notes: existing.notes || "",
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
document.addEventListener("input", function (event) {
|
||||
var input = event.target.closest("[data-review-notes-for]");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var existing = state.decisions[familyId] || {
|
||||
family_id: familyId,
|
||||
review_status: "needs_fix",
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
existing.notes = input.value;
|
||||
existing.updated_at = new Date().toISOString();
|
||||
state.decisions[familyId] = existing;
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
render(readState());
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/bold-poster.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "55b5c1c1fb0a11183ee0779e02f4a374cb989adceb4e3999f754dcf815f2e161"
|
||||
"sha256": "17a715b8c3cab33d9e80c8abbbd902fa00ae702f63a86ad87fa0bdeb68913433"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "55b5c1c1fb0a11183ee0779e02f4a374cb989adceb4e3999f754dcf815f2e161",
|
||||
"contact_sheet": "17a715b8c3cab33d9e80c8abbbd902fa00ae702f63a86ad87fa0bdeb68913433",
|
||||
"fidelity_receipt": "5cb7f128615cbb801b3e66df177a5c1d61b3339c92cba3a04b9db00aadce0635",
|
||||
"reference_screenshot": "95a9351619463053bda29bdf472702ed4bc650a4510fa6b3cfcc34d5e3ba79b1",
|
||||
"smoke_receipt": null,
|
||||
|
||||
@@ -19,27 +19,175 @@
|
||||
h2 { margin: 10px 0 4px; font-size: 15px; }
|
||||
p { margin: 5px 0; font-size: 12px; color: #536071; }
|
||||
code { word-break: break-all; font-size: 11px; }
|
||||
button { cursor: pointer; border: 1px solid #b8c2d2; background: #fff; color: #172033; border-radius: 6px; padding: 6px 9px; font-weight: 700; }
|
||||
button.selected { border-color: #1d4ed8; background: #dbeafe; color: #1e3a8a; }
|
||||
.badge { display: inline-block; border-radius: 999px; padding: 2px 7px; font-size: 11px; font-weight: 700; }
|
||||
.ok { color: #065f46; background: #d1fae5; }
|
||||
.warn { color: #92400e; background: #fef3c7; }
|
||||
.bad { color: #991b1b; background: #fee2e2; }
|
||||
.review-panel, .review-handoff { background: #fff; border: 1px solid #dfe5ee; border-radius: 8px; padding: 14px; margin: 16px 0; }
|
||||
.decision-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
|
||||
.review-current { font-size: 12px; color: #536071; margin-bottom: 8px; }
|
||||
.notes-label { display: block; color: #536071; font-size: 12px; }
|
||||
.notes-label input { margin-left: 8px; min-width: min(520px, 80vw); padding: 6px 8px; border: 1px solid #c7d0df; border-radius: 6px; }
|
||||
.decision-template { margin-top: 10px; }
|
||||
pre, textarea { width: 100%; box-sizing: border-box; border: 1px solid #c7d0df; border-radius: 6px; background: #f8fafc; color: #172033; }
|
||||
pre { overflow: auto; padding: 10px; font-size: 12px; }
|
||||
textarea { min-height: 180px; padding: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<p><a href="../index.html">Back to gallery</a></p>
|
||||
<h1>broadside</h1>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt.</div>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt and does not automatically modify production/default.</div>
|
||||
<div class="meta">
|
||||
<div class="metric"><strong>16</strong>source pages</div>
|
||||
<div class="metric"><strong>blocked</strong>auto gate</div>
|
||||
<div class="metric"><strong>missing</strong>smoke</div>
|
||||
<div class="metric"><strong>passed</strong>fidelity</div>
|
||||
</div>
|
||||
<div class="review-panel">
|
||||
<h2>Human decision</h2>
|
||||
<div class="review-control" data-review-control-for="broadside"><div class="decision-buttons"><button type="button" data-family-id="broadside" data-review-status="pass">pass</button><button type="button" data-family-id="broadside" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="broadside" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="broadside">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="broadside" placeholder="optional apply-script context" /></label><details class="decision-template"><summary>Copyable decision JSON fragment</summary><pre>{
|
||||
"family_id": "broadside",
|
||||
"human_review_status_before_selection": "pending",
|
||||
"notes": "",
|
||||
"promotion_action": "no_change_until_human_pass",
|
||||
"review_status": "pass | needs_fix | reject",
|
||||
"runtime_template_id": "editorial-quote-chart",
|
||||
"source_gallery_receipt_path": "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json"
|
||||
}</pre></details></div>
|
||||
</div>
|
||||
<p><strong>Known blockers:</strong> auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</p>
|
||||
</header>
|
||||
<section class="review-handoff">
|
||||
<h2>Human Review Export</h2>
|
||||
<div class="warning">This local UI does not automatically modify production/default. It only stores browser-local decisions and exports JSON for a separate apply script.</div>
|
||||
<p><code>human_review_status=pending</code> <code>promotion_action=no_change_until_human_pass</code></p>
|
||||
<p>Machine-readable gallery receipt: <code>skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json</code></p>
|
||||
<p>Apply script input: save this textarea as decisions JSON, then pass it to the apply script, for example <code>python <apply-script> --gallery-receipt skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json --decisions <exported-decisions.json></code>.</p>
|
||||
<textarea id="review-decisions-json" readonly spellcheck="false"></textarea>
|
||||
</section>
|
||||
|
||||
<main class="deck">
|
||||
<section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/broadside-1.png" alt="cover" /></div><h2>1. cover</h2><p>cover / cover</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--cover</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/broadside-1.png" alt="chapter" /></div><h2>2. chapter</h2><p>agenda / agenda</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--chapter</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/broadside-1.png" alt="statement" /></div><h2>3. statement</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--statement</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/broadside-4.png" alt="split" /></div><h2>4. split</h2><p>content_split / comparison_or_split</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--split</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/broadside-1.png" alt="stats" /></div><h2>5. stats</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--stats</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/broadside-1.png" alt="fadelist" /></div><h2>6. fadelist</h2><p>content / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--fadelist</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/broadside-1.png" alt="list" /></div><h2>7. list</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--list</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/broadside-1.png" alt="quote" /></div><h2>8. quote</h2><p>quote_or_emphasis / quote_or_emphasis</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--quote</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/broadside-1.png" alt="compare" /></div><h2>9. compare</h2><p>process_or_timeline / comparison_or_split</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--compare</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/broadside-1.png" alt="chart" /></div><h2>10. chart</h2><p>closing / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--chart</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/broadside-1.png" alt="diagram" /></div><h2>11. diagram</h2><p>detail / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--diagram</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/broadside-1.png" alt="pie" /></div><h2>12. pie</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--pie</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/broadside-13.png" alt="pyramid" /></div><h2>13. pyramid</h2><p>content / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--pyramid</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/broadside-1.png" alt="vtimeline" /></div><h2>14. vtimeline</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--vtimeline</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/broadside-1.png" alt="cycle" /></div><h2>15. cycle</h2><p>content / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--cycle</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/broadside-1.png" alt="end" /></div><h2>16. end</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--end</code></p></section>
|
||||
</main>
|
||||
<script>
|
||||
(function () {
|
||||
var storageKey = "beautiful-production-review-decisions-v1";
|
||||
var schemaVersion = "svglide-beautiful-human-review-decisions/v1";
|
||||
var reviewBatchId = "beautiful-34";
|
||||
var receiptPath = "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json";
|
||||
var pendingHumanReviewStatus = "pending";
|
||||
var promotionAction = "no_change_until_human_pass";
|
||||
|
||||
function readState() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
||||
if (parsed && typeof parsed === "object" && parsed.decisions && typeof parsed.decisions === "object") {
|
||||
return parsed;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore malformed local state and rebuild below.
|
||||
}
|
||||
return { decisions: {} };
|
||||
}
|
||||
|
||||
function writeState(state) {
|
||||
localStorage.setItem(storageKey, JSON.stringify(state));
|
||||
}
|
||||
|
||||
function buildExport(state) {
|
||||
var decisions = Object.keys(state.decisions || {}).sort().map(function (familyId) {
|
||||
return state.decisions[familyId];
|
||||
});
|
||||
return {
|
||||
schema_version: schemaVersion,
|
||||
artifact_kind: "beautiful_template_human_review_decisions",
|
||||
review_batch_id: reviewBatchId,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
not_promotion_receipt: true,
|
||||
policy: {
|
||||
does_not_automatically_modify_production_default: true,
|
||||
apply_script_must_validate_gallery_receipt: true
|
||||
},
|
||||
decisions: decisions
|
||||
};
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.querySelectorAll("[data-review-current-for]").forEach(function (node) {
|
||||
var familyId = node.getAttribute("data-review-current-for");
|
||||
var decision = state.decisions[familyId];
|
||||
node.textContent = decision ? decision.review_status : "pending";
|
||||
});
|
||||
document.querySelectorAll("[data-review-status]").forEach(function (button) {
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var decision = state.decisions[familyId];
|
||||
button.classList.toggle("selected", Boolean(decision && decision.review_status === status));
|
||||
});
|
||||
document.querySelectorAll("[data-review-notes-for]").forEach(function (input) {
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var decision = state.decisions[familyId];
|
||||
if (decision && input.value !== decision.notes) {
|
||||
input.value = decision.notes || "";
|
||||
}
|
||||
});
|
||||
var textarea = document.getElementById("review-decisions-json");
|
||||
if (textarea) {
|
||||
textarea.value = JSON.stringify(buildExport(state), null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
var button = event.target.closest("[data-review-status]");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var existing = state.decisions[familyId] || {};
|
||||
state.decisions[familyId] = {
|
||||
family_id: familyId,
|
||||
review_status: status,
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
notes: existing.notes || "",
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
document.addEventListener("input", function (event) {
|
||||
var input = event.target.closest("[data-review-notes-for]");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var existing = state.decisions[familyId] || {
|
||||
family_id: familyId,
|
||||
review_status: "needs_fix",
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
existing.notes = input.value;
|
||||
existing.updated_at = new Date().toISOString();
|
||||
state.decisions[familyId] = existing;
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
render(readState());
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/broadside.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "3f823b2d1e5a98af40443c0f04c5180e2d40c0ae8dab5a5b5c81f80494298822"
|
||||
"sha256": "db1ffb89fb710b18e5e23c50bd04a5c500bea3a9602bc7148def1cd9b712572c"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "3f823b2d1e5a98af40443c0f04c5180e2d40c0ae8dab5a5b5c81f80494298822",
|
||||
"contact_sheet": "db1ffb89fb710b18e5e23c50bd04a5c500bea3a9602bc7148def1cd9b712572c",
|
||||
"fidelity_receipt": "fd3c0b8d0ae82ecad0cbeb13974361d5bf8f9e76083619edf5a88d77b0b5f664",
|
||||
"reference_screenshot": "96805bd67e4502f94b078b723d252717183fe8eb34f2eb529c44b772b4dcdce4",
|
||||
"smoke_receipt": null,
|
||||
|
||||
@@ -19,27 +19,175 @@
|
||||
h2 { margin: 10px 0 4px; font-size: 15px; }
|
||||
p { margin: 5px 0; font-size: 12px; color: #536071; }
|
||||
code { word-break: break-all; font-size: 11px; }
|
||||
button { cursor: pointer; border: 1px solid #b8c2d2; background: #fff; color: #172033; border-radius: 6px; padding: 6px 9px; font-weight: 700; }
|
||||
button.selected { border-color: #1d4ed8; background: #dbeafe; color: #1e3a8a; }
|
||||
.badge { display: inline-block; border-radius: 999px; padding: 2px 7px; font-size: 11px; font-weight: 700; }
|
||||
.ok { color: #065f46; background: #d1fae5; }
|
||||
.warn { color: #92400e; background: #fef3c7; }
|
||||
.bad { color: #991b1b; background: #fee2e2; }
|
||||
.review-panel, .review-handoff { background: #fff; border: 1px solid #dfe5ee; border-radius: 8px; padding: 14px; margin: 16px 0; }
|
||||
.decision-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
|
||||
.review-current { font-size: 12px; color: #536071; margin-bottom: 8px; }
|
||||
.notes-label { display: block; color: #536071; font-size: 12px; }
|
||||
.notes-label input { margin-left: 8px; min-width: min(520px, 80vw); padding: 6px 8px; border: 1px solid #c7d0df; border-radius: 6px; }
|
||||
.decision-template { margin-top: 10px; }
|
||||
pre, textarea { width: 100%; box-sizing: border-box; border: 1px solid #c7d0df; border-radius: 6px; background: #f8fafc; color: #172033; }
|
||||
pre { overflow: auto; padding: 10px; font-size: 12px; }
|
||||
textarea { min-height: 180px; padding: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<p><a href="../index.html">Back to gallery</a></p>
|
||||
<h1>capsule</h1>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt.</div>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt and does not automatically modify production/default.</div>
|
||||
<div class="meta">
|
||||
<div class="metric"><strong>10</strong>source pages</div>
|
||||
<div class="metric"><strong>blocked</strong>auto gate</div>
|
||||
<div class="metric"><strong>missing</strong>smoke</div>
|
||||
<div class="metric"><strong>passed</strong>fidelity</div>
|
||||
</div>
|
||||
<div class="review-panel">
|
||||
<h2>Human decision</h2>
|
||||
<div class="review-control" data-review-control-for="capsule"><div class="decision-buttons"><button type="button" data-family-id="capsule" data-review-status="pass">pass</button><button type="button" data-family-id="capsule" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="capsule" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="capsule">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="capsule" placeholder="optional apply-script context" /></label><details class="decision-template"><summary>Copyable decision JSON fragment</summary><pre>{
|
||||
"family_id": "capsule",
|
||||
"human_review_status_before_selection": "pending",
|
||||
"notes": "",
|
||||
"promotion_action": "no_change_until_human_pass",
|
||||
"review_status": "pass | needs_fix | reject",
|
||||
"runtime_template_id": "capsule-card-system",
|
||||
"source_gallery_receipt_path": "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json"
|
||||
}</pre></details></div>
|
||||
</div>
|
||||
<p><strong>Known blockers:</strong> auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</p>
|
||||
</header>
|
||||
<section class="review-handoff">
|
||||
<h2>Human Review Export</h2>
|
||||
<div class="warning">This local UI does not automatically modify production/default. It only stores browser-local decisions and exports JSON for a separate apply script.</div>
|
||||
<p><code>human_review_status=pending</code> <code>promotion_action=no_change_until_human_pass</code></p>
|
||||
<p>Machine-readable gallery receipt: <code>skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json</code></p>
|
||||
<p>Apply script input: save this textarea as decisions JSON, then pass it to the apply script, for example <code>python <apply-script> --gallery-receipt skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json --decisions <exported-decisions.json></code>.</p>
|
||||
<textarea id="review-decisions-json" readonly spellcheck="false"></textarea>
|
||||
</section>
|
||||
|
||||
<main class="deck">
|
||||
<section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/capsule-1.png" alt="cover" /></div><h2>1. cover</h2><p>cover / cover</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-1</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/capsule-1.png" alt="agenda" /></div><h2>2. agenda</h2><p>agenda / agenda</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-2</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/capsule-1.png" alt="data_dashboard" /></div><h2>3. data_dashboard</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-3</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/capsule-4.png" alt="data_dashboard-4" /></div><h2>4. data_dashboard-4</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-4</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/capsule-1.png" alt="quote_or_emphasis" /></div><h2>5. quote_or_emphasis</h2><p>quote_or_emphasis / quote_or_emphasis</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-5</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/capsule-1.png" alt="process_or_timeline" /></div><h2>6. process_or_timeline</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-6</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/capsule-1.png" alt="data_dashboard-7" /></div><h2>7. data_dashboard-7</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-7</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/capsule-8.png" alt="slide-8" /></div><h2>8. slide-8</h2><p>content / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-8</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/capsule-1.png" alt="slide-9" /></div><h2>9. slide-9</h2><p>content / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-9</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/capsule-1.png" alt="closing" /></div><h2>10. closing</h2><p>closing / closing</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-10</code></p></section>
|
||||
</main>
|
||||
<script>
|
||||
(function () {
|
||||
var storageKey = "beautiful-production-review-decisions-v1";
|
||||
var schemaVersion = "svglide-beautiful-human-review-decisions/v1";
|
||||
var reviewBatchId = "beautiful-34";
|
||||
var receiptPath = "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json";
|
||||
var pendingHumanReviewStatus = "pending";
|
||||
var promotionAction = "no_change_until_human_pass";
|
||||
|
||||
function readState() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
||||
if (parsed && typeof parsed === "object" && parsed.decisions && typeof parsed.decisions === "object") {
|
||||
return parsed;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore malformed local state and rebuild below.
|
||||
}
|
||||
return { decisions: {} };
|
||||
}
|
||||
|
||||
function writeState(state) {
|
||||
localStorage.setItem(storageKey, JSON.stringify(state));
|
||||
}
|
||||
|
||||
function buildExport(state) {
|
||||
var decisions = Object.keys(state.decisions || {}).sort().map(function (familyId) {
|
||||
return state.decisions[familyId];
|
||||
});
|
||||
return {
|
||||
schema_version: schemaVersion,
|
||||
artifact_kind: "beautiful_template_human_review_decisions",
|
||||
review_batch_id: reviewBatchId,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
not_promotion_receipt: true,
|
||||
policy: {
|
||||
does_not_automatically_modify_production_default: true,
|
||||
apply_script_must_validate_gallery_receipt: true
|
||||
},
|
||||
decisions: decisions
|
||||
};
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.querySelectorAll("[data-review-current-for]").forEach(function (node) {
|
||||
var familyId = node.getAttribute("data-review-current-for");
|
||||
var decision = state.decisions[familyId];
|
||||
node.textContent = decision ? decision.review_status : "pending";
|
||||
});
|
||||
document.querySelectorAll("[data-review-status]").forEach(function (button) {
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var decision = state.decisions[familyId];
|
||||
button.classList.toggle("selected", Boolean(decision && decision.review_status === status));
|
||||
});
|
||||
document.querySelectorAll("[data-review-notes-for]").forEach(function (input) {
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var decision = state.decisions[familyId];
|
||||
if (decision && input.value !== decision.notes) {
|
||||
input.value = decision.notes || "";
|
||||
}
|
||||
});
|
||||
var textarea = document.getElementById("review-decisions-json");
|
||||
if (textarea) {
|
||||
textarea.value = JSON.stringify(buildExport(state), null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
var button = event.target.closest("[data-review-status]");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var existing = state.decisions[familyId] || {};
|
||||
state.decisions[familyId] = {
|
||||
family_id: familyId,
|
||||
review_status: status,
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
notes: existing.notes || "",
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
document.addEventListener("input", function (event) {
|
||||
var input = event.target.closest("[data-review-notes-for]");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var existing = state.decisions[familyId] || {
|
||||
family_id: familyId,
|
||||
review_status: "needs_fix",
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
existing.notes = input.value;
|
||||
existing.updated_at = new Date().toISOString();
|
||||
state.decisions[familyId] = existing;
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
render(readState());
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/capsule.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "35b0d6c1d01dd97448bcf50981754d1f0155439b4431efeeaa2b9d4208f7378f"
|
||||
"sha256": "b89c818def92fdd5638e4d0c343bdfd8a1ae201087c5701f9740e66d21d41636"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "35b0d6c1d01dd97448bcf50981754d1f0155439b4431efeeaa2b9d4208f7378f",
|
||||
"contact_sheet": "b89c818def92fdd5638e4d0c343bdfd8a1ae201087c5701f9740e66d21d41636",
|
||||
"fidelity_receipt": "38ef8db0e9fdaf4d3c4f83f3b9ab1a2c956661315784c6090c301faac93f2f8c",
|
||||
"reference_screenshot": "468b1b618668660274e7a46a528d0a323fb926c3e47f7e5895ec03189efd35b3",
|
||||
"smoke_receipt": null,
|
||||
|
||||
@@ -19,27 +19,175 @@
|
||||
h2 { margin: 10px 0 4px; font-size: 15px; }
|
||||
p { margin: 5px 0; font-size: 12px; color: #536071; }
|
||||
code { word-break: break-all; font-size: 11px; }
|
||||
button { cursor: pointer; border: 1px solid #b8c2d2; background: #fff; color: #172033; border-radius: 6px; padding: 6px 9px; font-weight: 700; }
|
||||
button.selected { border-color: #1d4ed8; background: #dbeafe; color: #1e3a8a; }
|
||||
.badge { display: inline-block; border-radius: 999px; padding: 2px 7px; font-size: 11px; font-weight: 700; }
|
||||
.ok { color: #065f46; background: #d1fae5; }
|
||||
.warn { color: #92400e; background: #fef3c7; }
|
||||
.bad { color: #991b1b; background: #fee2e2; }
|
||||
.review-panel, .review-handoff { background: #fff; border: 1px solid #dfe5ee; border-radius: 8px; padding: 14px; margin: 16px 0; }
|
||||
.decision-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
|
||||
.review-current { font-size: 12px; color: #536071; margin-bottom: 8px; }
|
||||
.notes-label { display: block; color: #536071; font-size: 12px; }
|
||||
.notes-label input { margin-left: 8px; min-width: min(520px, 80vw); padding: 6px 8px; border: 1px solid #c7d0df; border-radius: 6px; }
|
||||
.decision-template { margin-top: 10px; }
|
||||
pre, textarea { width: 100%; box-sizing: border-box; border: 1px solid #c7d0df; border-radius: 6px; background: #f8fafc; color: #172033; }
|
||||
pre { overflow: auto; padding: 10px; font-size: 12px; }
|
||||
textarea { min-height: 180px; padding: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<p><a href="../index.html">Back to gallery</a></p>
|
||||
<h1>cartesian</h1>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt.</div>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt and does not automatically modify production/default.</div>
|
||||
<div class="meta">
|
||||
<div class="metric"><strong>9</strong>source pages</div>
|
||||
<div class="metric"><strong>blocked</strong>auto gate</div>
|
||||
<div class="metric"><strong>missing</strong>smoke</div>
|
||||
<div class="metric"><strong>passed</strong>fidelity</div>
|
||||
</div>
|
||||
<div class="review-panel">
|
||||
<h2>Human decision</h2>
|
||||
<div class="review-control" data-review-control-for="cartesian"><div class="decision-buttons"><button type="button" data-family-id="cartesian" data-review-status="pass">pass</button><button type="button" data-family-id="cartesian" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="cartesian" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="cartesian">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="cartesian" placeholder="optional apply-script context" /></label><details class="decision-template"><summary>Copyable decision JSON fragment</summary><pre>{
|
||||
"family_id": "cartesian",
|
||||
"human_review_status_before_selection": "pending",
|
||||
"notes": "",
|
||||
"promotion_action": "no_change_until_human_pass",
|
||||
"review_status": "pass | needs_fix | reject",
|
||||
"runtime_template_id": "architectural-spec",
|
||||
"source_gallery_receipt_path": "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json"
|
||||
}</pre></details></div>
|
||||
</div>
|
||||
<p><strong>Known blockers:</strong> auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</p>
|
||||
</header>
|
||||
<section class="review-handoff">
|
||||
<h2>Human Review Export</h2>
|
||||
<div class="warning">This local UI does not automatically modify production/default. It only stores browser-local decisions and exports JSON for a separate apply script.</div>
|
||||
<p><code>human_review_status=pending</code> <code>promotion_action=no_change_until_human_pass</code></p>
|
||||
<p>Machine-readable gallery receipt: <code>skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json</code></p>
|
||||
<p>Apply script input: save this textarea as decisions JSON, then pass it to the apply script, for example <code>python <apply-script> --gallery-receipt skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json --decisions <exported-decisions.json></code>.</p>
|
||||
<textarea id="review-decisions-json" readonly spellcheck="false"></textarea>
|
||||
</section>
|
||||
|
||||
<main class="deck">
|
||||
<section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/cartesian-1.png" alt="agenda" /></div><h2>1. agenda</h2><p>agenda / agenda</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-agenda</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/cartesian-1.png" alt="statement" /></div><h2>2. statement</h2><p>agenda / agenda</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-statement</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/cartesian-1.png" alt="barchart" /></div><h2>3. barchart</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-barchart</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/cartesian-4.png" alt="twocol" /></div><h2>4. twocol</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-twocol</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/cartesian-1.png" alt="cards" /></div><h2>5. cards</h2><p>content / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-cards</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/cartesian-1.png" alt="linechart" /></div><h2>6. linechart</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-linechart</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/cartesian-1.png" alt="timeline" /></div><h2>7. timeline</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-timeline</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/cartesian-8.png" alt="team" /></div><h2>8. team</h2><p>detail / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-team</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/cartesian-1.png" alt="closing" /></div><h2>9. closing</h2><p>closing / closing</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-closing</code></p></section>
|
||||
</main>
|
||||
<script>
|
||||
(function () {
|
||||
var storageKey = "beautiful-production-review-decisions-v1";
|
||||
var schemaVersion = "svglide-beautiful-human-review-decisions/v1";
|
||||
var reviewBatchId = "beautiful-34";
|
||||
var receiptPath = "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json";
|
||||
var pendingHumanReviewStatus = "pending";
|
||||
var promotionAction = "no_change_until_human_pass";
|
||||
|
||||
function readState() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
||||
if (parsed && typeof parsed === "object" && parsed.decisions && typeof parsed.decisions === "object") {
|
||||
return parsed;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore malformed local state and rebuild below.
|
||||
}
|
||||
return { decisions: {} };
|
||||
}
|
||||
|
||||
function writeState(state) {
|
||||
localStorage.setItem(storageKey, JSON.stringify(state));
|
||||
}
|
||||
|
||||
function buildExport(state) {
|
||||
var decisions = Object.keys(state.decisions || {}).sort().map(function (familyId) {
|
||||
return state.decisions[familyId];
|
||||
});
|
||||
return {
|
||||
schema_version: schemaVersion,
|
||||
artifact_kind: "beautiful_template_human_review_decisions",
|
||||
review_batch_id: reviewBatchId,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
not_promotion_receipt: true,
|
||||
policy: {
|
||||
does_not_automatically_modify_production_default: true,
|
||||
apply_script_must_validate_gallery_receipt: true
|
||||
},
|
||||
decisions: decisions
|
||||
};
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.querySelectorAll("[data-review-current-for]").forEach(function (node) {
|
||||
var familyId = node.getAttribute("data-review-current-for");
|
||||
var decision = state.decisions[familyId];
|
||||
node.textContent = decision ? decision.review_status : "pending";
|
||||
});
|
||||
document.querySelectorAll("[data-review-status]").forEach(function (button) {
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var decision = state.decisions[familyId];
|
||||
button.classList.toggle("selected", Boolean(decision && decision.review_status === status));
|
||||
});
|
||||
document.querySelectorAll("[data-review-notes-for]").forEach(function (input) {
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var decision = state.decisions[familyId];
|
||||
if (decision && input.value !== decision.notes) {
|
||||
input.value = decision.notes || "";
|
||||
}
|
||||
});
|
||||
var textarea = document.getElementById("review-decisions-json");
|
||||
if (textarea) {
|
||||
textarea.value = JSON.stringify(buildExport(state), null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
var button = event.target.closest("[data-review-status]");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var existing = state.decisions[familyId] || {};
|
||||
state.decisions[familyId] = {
|
||||
family_id: familyId,
|
||||
review_status: status,
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
notes: existing.notes || "",
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
document.addEventListener("input", function (event) {
|
||||
var input = event.target.closest("[data-review-notes-for]");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var existing = state.decisions[familyId] || {
|
||||
family_id: familyId,
|
||||
review_status: "needs_fix",
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
existing.notes = input.value;
|
||||
existing.updated_at = new Date().toISOString();
|
||||
state.decisions[familyId] = existing;
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
render(readState());
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/cartesian.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "c1f6795edcce9b5f104edd8f19b1674ceee66b19b905b330f20f1328fde6baa4"
|
||||
"sha256": "3a68f9f0984b0c0dcd526bfb1bd7deec743e293c739d09529d31ec8dc31c548d"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "c1f6795edcce9b5f104edd8f19b1674ceee66b19b905b330f20f1328fde6baa4",
|
||||
"contact_sheet": "3a68f9f0984b0c0dcd526bfb1bd7deec743e293c739d09529d31ec8dc31c548d",
|
||||
"fidelity_receipt": "d7bec45b7684b8ab2e98755e76624fffdf5048fd864aa64d7092aeb6aba3a62d",
|
||||
"reference_screenshot": "59af0f5ee20b85f07ada82a1d6bb8ab5e69b81bb08b5abf2a7520eca4934e93e",
|
||||
"smoke_receipt": null,
|
||||
|
||||
@@ -19,27 +19,175 @@
|
||||
h2 { margin: 10px 0 4px; font-size: 15px; }
|
||||
p { margin: 5px 0; font-size: 12px; color: #536071; }
|
||||
code { word-break: break-all; font-size: 11px; }
|
||||
button { cursor: pointer; border: 1px solid #b8c2d2; background: #fff; color: #172033; border-radius: 6px; padding: 6px 9px; font-weight: 700; }
|
||||
button.selected { border-color: #1d4ed8; background: #dbeafe; color: #1e3a8a; }
|
||||
.badge { display: inline-block; border-radius: 999px; padding: 2px 7px; font-size: 11px; font-weight: 700; }
|
||||
.ok { color: #065f46; background: #d1fae5; }
|
||||
.warn { color: #92400e; background: #fef3c7; }
|
||||
.bad { color: #991b1b; background: #fee2e2; }
|
||||
.review-panel, .review-handoff { background: #fff; border: 1px solid #dfe5ee; border-radius: 8px; padding: 14px; margin: 16px 0; }
|
||||
.decision-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
|
||||
.review-current { font-size: 12px; color: #536071; margin-bottom: 8px; }
|
||||
.notes-label { display: block; color: #536071; font-size: 12px; }
|
||||
.notes-label input { margin-left: 8px; min-width: min(520px, 80vw); padding: 6px 8px; border: 1px solid #c7d0df; border-radius: 6px; }
|
||||
.decision-template { margin-top: 10px; }
|
||||
pre, textarea { width: 100%; box-sizing: border-box; border: 1px solid #c7d0df; border-radius: 6px; background: #f8fafc; color: #172033; }
|
||||
pre { overflow: auto; padding: 10px; font-size: 12px; }
|
||||
textarea { min-height: 180px; padding: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<p><a href="../index.html">Back to gallery</a></p>
|
||||
<h1>cobalt-grid</h1>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt.</div>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt and does not automatically modify production/default.</div>
|
||||
<div class="meta">
|
||||
<div class="metric"><strong>8</strong>source pages</div>
|
||||
<div class="metric"><strong>blocked</strong>auto gate</div>
|
||||
<div class="metric"><strong>missing</strong>smoke</div>
|
||||
<div class="metric"><strong>passed</strong>fidelity</div>
|
||||
</div>
|
||||
<div class="review-panel">
|
||||
<h2>Human decision</h2>
|
||||
<div class="review-control" data-review-control-for="cobalt-grid"><div class="decision-buttons"><button type="button" data-family-id="cobalt-grid" data-review-status="pass">pass</button><button type="button" data-family-id="cobalt-grid" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="cobalt-grid" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="cobalt-grid">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="cobalt-grid" placeholder="optional apply-script context" /></label><details class="decision-template"><summary>Copyable decision JSON fragment</summary><pre>{
|
||||
"family_id": "cobalt-grid",
|
||||
"human_review_status_before_selection": "pending",
|
||||
"notes": "",
|
||||
"promotion_action": "no_change_until_human_pass",
|
||||
"review_status": "pass | needs_fix | reject",
|
||||
"runtime_template_id": "trend-grid-report",
|
||||
"source_gallery_receipt_path": "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json"
|
||||
}</pre></details></div>
|
||||
</div>
|
||||
<p><strong>Known blockers:</strong> auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</p>
|
||||
</header>
|
||||
<section class="review-handoff">
|
||||
<h2>Human Review Export</h2>
|
||||
<div class="warning">This local UI does not automatically modify production/default. It only stores browser-local decisions and exports JSON for a separate apply script.</div>
|
||||
<p><code>human_review_status=pending</code> <code>promotion_action=no_change_until_human_pass</code></p>
|
||||
<p>Machine-readable gallery receipt: <code>skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json</code></p>
|
||||
<p>Apply script input: save this textarea as decisions JSON, then pass it to the apply script, for example <code>python <apply-script> --gallery-receipt skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json --decisions <exported-decisions.json></code>.</p>
|
||||
<textarea id="review-decisions-json" readonly spellcheck="false"></textarea>
|
||||
</section>
|
||||
|
||||
<main class="deck">
|
||||
<section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/cobalt-grid-1.png" alt="cover" /></div><h2>1. cover</h2><p>cover / cover</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-cover</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/cobalt-grid-1.png" alt="manifesto" /></div><h2>2. manifesto</h2><p>agenda / agenda</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-manifesto</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/cobalt-grid-3.png" alt="index" /></div><h2>3. index</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-index</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/cobalt-grid-1.png" alt="chapter" /></div><h2>4. chapter</h2><p>content / agenda</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-chapter</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/cobalt-grid-5.png" alt="data" /></div><h2>5. data</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-data</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/cobalt-grid-1.png" alt="quote" /></div><h2>6. quote</h2><p>quote_or_emphasis / quote_or_emphasis</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-quote</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/cobalt-grid-1.png" alt="table" /></div><h2>7. table</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-table</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/cobalt-grid-1.png" alt="colophon" /></div><h2>8. colophon</h2><p>content / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-colophon</code></p></section>
|
||||
</main>
|
||||
<script>
|
||||
(function () {
|
||||
var storageKey = "beautiful-production-review-decisions-v1";
|
||||
var schemaVersion = "svglide-beautiful-human-review-decisions/v1";
|
||||
var reviewBatchId = "beautiful-34";
|
||||
var receiptPath = "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json";
|
||||
var pendingHumanReviewStatus = "pending";
|
||||
var promotionAction = "no_change_until_human_pass";
|
||||
|
||||
function readState() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
||||
if (parsed && typeof parsed === "object" && parsed.decisions && typeof parsed.decisions === "object") {
|
||||
return parsed;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore malformed local state and rebuild below.
|
||||
}
|
||||
return { decisions: {} };
|
||||
}
|
||||
|
||||
function writeState(state) {
|
||||
localStorage.setItem(storageKey, JSON.stringify(state));
|
||||
}
|
||||
|
||||
function buildExport(state) {
|
||||
var decisions = Object.keys(state.decisions || {}).sort().map(function (familyId) {
|
||||
return state.decisions[familyId];
|
||||
});
|
||||
return {
|
||||
schema_version: schemaVersion,
|
||||
artifact_kind: "beautiful_template_human_review_decisions",
|
||||
review_batch_id: reviewBatchId,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
not_promotion_receipt: true,
|
||||
policy: {
|
||||
does_not_automatically_modify_production_default: true,
|
||||
apply_script_must_validate_gallery_receipt: true
|
||||
},
|
||||
decisions: decisions
|
||||
};
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.querySelectorAll("[data-review-current-for]").forEach(function (node) {
|
||||
var familyId = node.getAttribute("data-review-current-for");
|
||||
var decision = state.decisions[familyId];
|
||||
node.textContent = decision ? decision.review_status : "pending";
|
||||
});
|
||||
document.querySelectorAll("[data-review-status]").forEach(function (button) {
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var decision = state.decisions[familyId];
|
||||
button.classList.toggle("selected", Boolean(decision && decision.review_status === status));
|
||||
});
|
||||
document.querySelectorAll("[data-review-notes-for]").forEach(function (input) {
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var decision = state.decisions[familyId];
|
||||
if (decision && input.value !== decision.notes) {
|
||||
input.value = decision.notes || "";
|
||||
}
|
||||
});
|
||||
var textarea = document.getElementById("review-decisions-json");
|
||||
if (textarea) {
|
||||
textarea.value = JSON.stringify(buildExport(state), null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
var button = event.target.closest("[data-review-status]");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var existing = state.decisions[familyId] || {};
|
||||
state.decisions[familyId] = {
|
||||
family_id: familyId,
|
||||
review_status: status,
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
notes: existing.notes || "",
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
document.addEventListener("input", function (event) {
|
||||
var input = event.target.closest("[data-review-notes-for]");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var existing = state.decisions[familyId] || {
|
||||
family_id: familyId,
|
||||
review_status: "needs_fix",
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
existing.notes = input.value;
|
||||
existing.updated_at = new Date().toISOString();
|
||||
state.decisions[familyId] = existing;
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
render(readState());
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/cobalt-grid.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "f9970bf563b9fc18a08f6617c1a1769cbc8cebd4ec98dcf042c1be12398c8f46"
|
||||
"sha256": "4fd837a9e9c7fc3da874f451915c9942f7c35b2f179f07986e2523c8fb0e2e9f"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "f9970bf563b9fc18a08f6617c1a1769cbc8cebd4ec98dcf042c1be12398c8f46",
|
||||
"contact_sheet": "4fd837a9e9c7fc3da874f451915c9942f7c35b2f179f07986e2523c8fb0e2e9f",
|
||||
"fidelity_receipt": "fd2b394777733364723f20d0d732a346f93edba0a748628ce9a1e5596726cb02",
|
||||
"reference_screenshot": "e85989914eb7ca3bb279e03cc792df19c5d06f8d3ba0e59515211164fca5ae2d",
|
||||
"smoke_receipt": null,
|
||||
|
||||
@@ -19,27 +19,175 @@
|
||||
h2 { margin: 10px 0 4px; font-size: 15px; }
|
||||
p { margin: 5px 0; font-size: 12px; color: #536071; }
|
||||
code { word-break: break-all; font-size: 11px; }
|
||||
button { cursor: pointer; border: 1px solid #b8c2d2; background: #fff; color: #172033; border-radius: 6px; padding: 6px 9px; font-weight: 700; }
|
||||
button.selected { border-color: #1d4ed8; background: #dbeafe; color: #1e3a8a; }
|
||||
.badge { display: inline-block; border-radius: 999px; padding: 2px 7px; font-size: 11px; font-weight: 700; }
|
||||
.ok { color: #065f46; background: #d1fae5; }
|
||||
.warn { color: #92400e; background: #fef3c7; }
|
||||
.bad { color: #991b1b; background: #fee2e2; }
|
||||
.review-panel, .review-handoff { background: #fff; border: 1px solid #dfe5ee; border-radius: 8px; padding: 14px; margin: 16px 0; }
|
||||
.decision-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
|
||||
.review-current { font-size: 12px; color: #536071; margin-bottom: 8px; }
|
||||
.notes-label { display: block; color: #536071; font-size: 12px; }
|
||||
.notes-label input { margin-left: 8px; min-width: min(520px, 80vw); padding: 6px 8px; border: 1px solid #c7d0df; border-radius: 6px; }
|
||||
.decision-template { margin-top: 10px; }
|
||||
pre, textarea { width: 100%; box-sizing: border-box; border: 1px solid #c7d0df; border-radius: 6px; background: #f8fafc; color: #172033; }
|
||||
pre { overflow: auto; padding: 10px; font-size: 12px; }
|
||||
textarea { min-height: 180px; padding: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<p><a href="../index.html">Back to gallery</a></p>
|
||||
<h1>coral</h1>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt.</div>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt and does not automatically modify production/default.</div>
|
||||
<div class="meta">
|
||||
<div class="metric"><strong>10</strong>source pages</div>
|
||||
<div class="metric"><strong>blocked</strong>auto gate</div>
|
||||
<div class="metric"><strong>missing</strong>smoke</div>
|
||||
<div class="metric"><strong>passed</strong>fidelity</div>
|
||||
</div>
|
||||
<div class="review-panel">
|
||||
<h2>Human decision</h2>
|
||||
<div class="review-control" data-review-control-for="coral"><div class="decision-buttons"><button type="button" data-family-id="coral" data-review-status="pass">pass</button><button type="button" data-family-id="coral" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="coral" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="coral">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="coral" placeholder="optional apply-script context" /></label><details class="decision-template"><summary>Copyable decision JSON fragment</summary><pre>{
|
||||
"family_id": "coral",
|
||||
"human_review_status_before_selection": "pending",
|
||||
"notes": "",
|
||||
"promotion_action": "no_change_until_human_pass",
|
||||
"review_status": "pass | needs_fix | reject",
|
||||
"runtime_template_id": "coral-magazine-feature",
|
||||
"source_gallery_receipt_path": "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json"
|
||||
}</pre></details></div>
|
||||
</div>
|
||||
<p><strong>Known blockers:</strong> auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</p>
|
||||
</header>
|
||||
<section class="review-handoff">
|
||||
<h2>Human Review Export</h2>
|
||||
<div class="warning">This local UI does not automatically modify production/default. It only stores browser-local decisions and exports JSON for a separate apply script.</div>
|
||||
<p><code>human_review_status=pending</code> <code>promotion_action=no_change_until_human_pass</code></p>
|
||||
<p>Machine-readable gallery receipt: <code>skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json</code></p>
|
||||
<p>Apply script input: save this textarea as decisions JSON, then pass it to the apply script, for example <code>python <apply-script> --gallery-receipt skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json --decisions <exported-decisions.json></code>.</p>
|
||||
<textarea id="review-decisions-json" readonly spellcheck="false"></textarea>
|
||||
</section>
|
||||
|
||||
<main class="deck">
|
||||
<section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/coral-1.png" alt="cover" /></div><h2>1. cover</h2><p>cover / cover</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-1</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/coral-1.png" alt="agenda" /></div><h2>2. agenda</h2><p>agenda / agenda</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-2</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/coral-1.png" alt="detail" /></div><h2>3. detail</h2><p>detail / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-3</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/coral-4.png" alt="data_dashboard" /></div><h2>4. data_dashboard</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-4</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/coral-1.png" alt="process_or_timeline" /></div><h2>5. process_or_timeline</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-5</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/coral-1.png" alt="data_dashboard-6" /></div><h2>6. data_dashboard-6</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-6</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/coral-1.png" alt="quote_or_emphasis" /></div><h2>7. quote_or_emphasis</h2><p>quote_or_emphasis / quote_or_emphasis</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-7</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/coral-8.png" alt="process_or_timeline-8" /></div><h2>8. process_or_timeline-8</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-8</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/coral-1.png" alt="detail-9" /></div><h2>9. detail-9</h2><p>detail / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-9</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/coral-1.png" alt="closing" /></div><h2>10. closing</h2><p>closing / closing</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-10</code></p></section>
|
||||
</main>
|
||||
<script>
|
||||
(function () {
|
||||
var storageKey = "beautiful-production-review-decisions-v1";
|
||||
var schemaVersion = "svglide-beautiful-human-review-decisions/v1";
|
||||
var reviewBatchId = "beautiful-34";
|
||||
var receiptPath = "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json";
|
||||
var pendingHumanReviewStatus = "pending";
|
||||
var promotionAction = "no_change_until_human_pass";
|
||||
|
||||
function readState() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
||||
if (parsed && typeof parsed === "object" && parsed.decisions && typeof parsed.decisions === "object") {
|
||||
return parsed;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore malformed local state and rebuild below.
|
||||
}
|
||||
return { decisions: {} };
|
||||
}
|
||||
|
||||
function writeState(state) {
|
||||
localStorage.setItem(storageKey, JSON.stringify(state));
|
||||
}
|
||||
|
||||
function buildExport(state) {
|
||||
var decisions = Object.keys(state.decisions || {}).sort().map(function (familyId) {
|
||||
return state.decisions[familyId];
|
||||
});
|
||||
return {
|
||||
schema_version: schemaVersion,
|
||||
artifact_kind: "beautiful_template_human_review_decisions",
|
||||
review_batch_id: reviewBatchId,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
not_promotion_receipt: true,
|
||||
policy: {
|
||||
does_not_automatically_modify_production_default: true,
|
||||
apply_script_must_validate_gallery_receipt: true
|
||||
},
|
||||
decisions: decisions
|
||||
};
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.querySelectorAll("[data-review-current-for]").forEach(function (node) {
|
||||
var familyId = node.getAttribute("data-review-current-for");
|
||||
var decision = state.decisions[familyId];
|
||||
node.textContent = decision ? decision.review_status : "pending";
|
||||
});
|
||||
document.querySelectorAll("[data-review-status]").forEach(function (button) {
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var decision = state.decisions[familyId];
|
||||
button.classList.toggle("selected", Boolean(decision && decision.review_status === status));
|
||||
});
|
||||
document.querySelectorAll("[data-review-notes-for]").forEach(function (input) {
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var decision = state.decisions[familyId];
|
||||
if (decision && input.value !== decision.notes) {
|
||||
input.value = decision.notes || "";
|
||||
}
|
||||
});
|
||||
var textarea = document.getElementById("review-decisions-json");
|
||||
if (textarea) {
|
||||
textarea.value = JSON.stringify(buildExport(state), null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
var button = event.target.closest("[data-review-status]");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var existing = state.decisions[familyId] || {};
|
||||
state.decisions[familyId] = {
|
||||
family_id: familyId,
|
||||
review_status: status,
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
notes: existing.notes || "",
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
document.addEventListener("input", function (event) {
|
||||
var input = event.target.closest("[data-review-notes-for]");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var existing = state.decisions[familyId] || {
|
||||
family_id: familyId,
|
||||
review_status: "needs_fix",
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
existing.notes = input.value;
|
||||
existing.updated_at = new Date().toISOString();
|
||||
state.decisions[familyId] = existing;
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
render(readState());
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/coral.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "402b5732bbb22f8145a73ec00176e0653a5f2744245bf10ec9ea757f8b6c1e70"
|
||||
"sha256": "b47a477b472ff5e219ff685d2fd247587ea389cdbd726d2276ffabbbfebf5403"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "402b5732bbb22f8145a73ec00176e0653a5f2744245bf10ec9ea757f8b6c1e70",
|
||||
"contact_sheet": "b47a477b472ff5e219ff685d2fd247587ea389cdbd726d2276ffabbbfebf5403",
|
||||
"fidelity_receipt": "dd795f5b763b8b5769e173a07ba63f2a2da2345fefaf96cb48989b7a5ba4ef2c",
|
||||
"reference_screenshot": "3cce11542e0c380396c14d2e7ac7406af704af163e7ba85b8ce9e2fdf7d12015",
|
||||
"smoke_receipt": null,
|
||||
|
||||
@@ -19,27 +19,175 @@
|
||||
h2 { margin: 10px 0 4px; font-size: 15px; }
|
||||
p { margin: 5px 0; font-size: 12px; color: #536071; }
|
||||
code { word-break: break-all; font-size: 11px; }
|
||||
button { cursor: pointer; border: 1px solid #b8c2d2; background: #fff; color: #172033; border-radius: 6px; padding: 6px 9px; font-weight: 700; }
|
||||
button.selected { border-color: #1d4ed8; background: #dbeafe; color: #1e3a8a; }
|
||||
.badge { display: inline-block; border-radius: 999px; padding: 2px 7px; font-size: 11px; font-weight: 700; }
|
||||
.ok { color: #065f46; background: #d1fae5; }
|
||||
.warn { color: #92400e; background: #fef3c7; }
|
||||
.bad { color: #991b1b; background: #fee2e2; }
|
||||
.review-panel, .review-handoff { background: #fff; border: 1px solid #dfe5ee; border-radius: 8px; padding: 14px; margin: 16px 0; }
|
||||
.decision-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
|
||||
.review-current { font-size: 12px; color: #536071; margin-bottom: 8px; }
|
||||
.notes-label { display: block; color: #536071; font-size: 12px; }
|
||||
.notes-label input { margin-left: 8px; min-width: min(520px, 80vw); padding: 6px 8px; border: 1px solid #c7d0df; border-radius: 6px; }
|
||||
.decision-template { margin-top: 10px; }
|
||||
pre, textarea { width: 100%; box-sizing: border-box; border: 1px solid #c7d0df; border-radius: 6px; background: #f8fafc; color: #172033; }
|
||||
pre { overflow: auto; padding: 10px; font-size: 12px; }
|
||||
textarea { min-height: 180px; padding: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<p><a href="../index.html">Back to gallery</a></p>
|
||||
<h1>creative-mode</h1>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt.</div>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt and does not automatically modify production/default.</div>
|
||||
<div class="meta">
|
||||
<div class="metric"><strong>8</strong>source pages</div>
|
||||
<div class="metric"><strong>blocked</strong>auto gate</div>
|
||||
<div class="metric"><strong>missing</strong>smoke</div>
|
||||
<div class="metric"><strong>passed</strong>fidelity</div>
|
||||
</div>
|
||||
<div class="review-panel">
|
||||
<h2>Human decision</h2>
|
||||
<div class="review-control" data-review-control-for="creative-mode"><div class="decision-buttons"><button type="button" data-family-id="creative-mode" data-review-status="pass">pass</button><button type="button" data-family-id="creative-mode" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="creative-mode" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="creative-mode">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="creative-mode" placeholder="optional apply-script context" /></label><details class="decision-template"><summary>Copyable decision JSON fragment</summary><pre>{
|
||||
"family_id": "creative-mode",
|
||||
"human_review_status_before_selection": "pending",
|
||||
"notes": "",
|
||||
"promotion_action": "no_change_until_human_pass",
|
||||
"review_status": "pass | needs_fix | reject",
|
||||
"runtime_template_id": "creative-mode-grid",
|
||||
"source_gallery_receipt_path": "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json"
|
||||
}</pre></details></div>
|
||||
</div>
|
||||
<p><strong>Known blockers:</strong> auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</p>
|
||||
</header>
|
||||
<section class="review-handoff">
|
||||
<h2>Human Review Export</h2>
|
||||
<div class="warning">This local UI does not automatically modify production/default. It only stores browser-local decisions and exports JSON for a separate apply script.</div>
|
||||
<p><code>human_review_status=pending</code> <code>promotion_action=no_change_until_human_pass</code></p>
|
||||
<p>Machine-readable gallery receipt: <code>skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json</code></p>
|
||||
<p>Apply script input: save this textarea as decisions JSON, then pass it to the apply script, for example <code>python <apply-script> --gallery-receipt skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json --decisions <exported-decisions.json></code>.</p>
|
||||
<textarea id="review-decisions-json" readonly spellcheck="false"></textarea>
|
||||
</section>
|
||||
|
||||
<main class="deck">
|
||||
<section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/creative-mode-1.png" alt="s1" /></div><h2>1. s1</h2><p>cover / cover</p><p><span class="badge bad">missing_smoke</span></p><p><code>s1</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/creative-mode-1.png" alt="s2" /></div><h2>2. s2</h2><p>agenda / agenda</p><p><span class="badge bad">missing_smoke</span></p><p><code>s2</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/creative-mode-1.png" alt="s3" /></div><h2>3. s3</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s3</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/creative-mode-4.png" alt="s4" /></div><h2>4. s4</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s4</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/creative-mode-1.png" alt="s5" /></div><h2>5. s5</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s5</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/creative-mode-6.png" alt="s6" /></div><h2>6. s6</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s6</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/creative-mode-1.png" alt="s7" /></div><h2>7. s7</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s7</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/creative-mode-1.png" alt="s8" /></div><h2>8. s8</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s8</code></p></section>
|
||||
</main>
|
||||
<script>
|
||||
(function () {
|
||||
var storageKey = "beautiful-production-review-decisions-v1";
|
||||
var schemaVersion = "svglide-beautiful-human-review-decisions/v1";
|
||||
var reviewBatchId = "beautiful-34";
|
||||
var receiptPath = "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json";
|
||||
var pendingHumanReviewStatus = "pending";
|
||||
var promotionAction = "no_change_until_human_pass";
|
||||
|
||||
function readState() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
||||
if (parsed && typeof parsed === "object" && parsed.decisions && typeof parsed.decisions === "object") {
|
||||
return parsed;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore malformed local state and rebuild below.
|
||||
}
|
||||
return { decisions: {} };
|
||||
}
|
||||
|
||||
function writeState(state) {
|
||||
localStorage.setItem(storageKey, JSON.stringify(state));
|
||||
}
|
||||
|
||||
function buildExport(state) {
|
||||
var decisions = Object.keys(state.decisions || {}).sort().map(function (familyId) {
|
||||
return state.decisions[familyId];
|
||||
});
|
||||
return {
|
||||
schema_version: schemaVersion,
|
||||
artifact_kind: "beautiful_template_human_review_decisions",
|
||||
review_batch_id: reviewBatchId,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
not_promotion_receipt: true,
|
||||
policy: {
|
||||
does_not_automatically_modify_production_default: true,
|
||||
apply_script_must_validate_gallery_receipt: true
|
||||
},
|
||||
decisions: decisions
|
||||
};
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.querySelectorAll("[data-review-current-for]").forEach(function (node) {
|
||||
var familyId = node.getAttribute("data-review-current-for");
|
||||
var decision = state.decisions[familyId];
|
||||
node.textContent = decision ? decision.review_status : "pending";
|
||||
});
|
||||
document.querySelectorAll("[data-review-status]").forEach(function (button) {
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var decision = state.decisions[familyId];
|
||||
button.classList.toggle("selected", Boolean(decision && decision.review_status === status));
|
||||
});
|
||||
document.querySelectorAll("[data-review-notes-for]").forEach(function (input) {
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var decision = state.decisions[familyId];
|
||||
if (decision && input.value !== decision.notes) {
|
||||
input.value = decision.notes || "";
|
||||
}
|
||||
});
|
||||
var textarea = document.getElementById("review-decisions-json");
|
||||
if (textarea) {
|
||||
textarea.value = JSON.stringify(buildExport(state), null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
var button = event.target.closest("[data-review-status]");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var existing = state.decisions[familyId] || {};
|
||||
state.decisions[familyId] = {
|
||||
family_id: familyId,
|
||||
review_status: status,
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
notes: existing.notes || "",
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
document.addEventListener("input", function (event) {
|
||||
var input = event.target.closest("[data-review-notes-for]");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var existing = state.decisions[familyId] || {
|
||||
family_id: familyId,
|
||||
review_status: "needs_fix",
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
existing.notes = input.value;
|
||||
existing.updated_at = new Date().toISOString();
|
||||
state.decisions[familyId] = existing;
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
render(readState());
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/creative-mode.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "224db100187b471bfeb2b4d38360dc8efa283251be6ebf174da10d74700b080e"
|
||||
"sha256": "d25bb924c36879bf68e1282a46c1818b201962ec80ad0d845a1b2bef6d5b2292"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "224db100187b471bfeb2b4d38360dc8efa283251be6ebf174da10d74700b080e",
|
||||
"contact_sheet": "d25bb924c36879bf68e1282a46c1818b201962ec80ad0d845a1b2bef6d5b2292",
|
||||
"fidelity_receipt": "51de4317d40671c7a4ba0868cacfa3c86ca2de0d14eecb8d07177f6c53506acf",
|
||||
"reference_screenshot": "aaac87da4e7f0e1e294f8f3d88616b067174687f4b89dafcad0acb4b967e9633",
|
||||
"smoke_receipt": null,
|
||||
|
||||
@@ -19,27 +19,175 @@
|
||||
h2 { margin: 10px 0 4px; font-size: 15px; }
|
||||
p { margin: 5px 0; font-size: 12px; color: #536071; }
|
||||
code { word-break: break-all; font-size: 11px; }
|
||||
button { cursor: pointer; border: 1px solid #b8c2d2; background: #fff; color: #172033; border-radius: 6px; padding: 6px 9px; font-weight: 700; }
|
||||
button.selected { border-color: #1d4ed8; background: #dbeafe; color: #1e3a8a; }
|
||||
.badge { display: inline-block; border-radius: 999px; padding: 2px 7px; font-size: 11px; font-weight: 700; }
|
||||
.ok { color: #065f46; background: #d1fae5; }
|
||||
.warn { color: #92400e; background: #fef3c7; }
|
||||
.bad { color: #991b1b; background: #fee2e2; }
|
||||
.review-panel, .review-handoff { background: #fff; border: 1px solid #dfe5ee; border-radius: 8px; padding: 14px; margin: 16px 0; }
|
||||
.decision-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
|
||||
.review-current { font-size: 12px; color: #536071; margin-bottom: 8px; }
|
||||
.notes-label { display: block; color: #536071; font-size: 12px; }
|
||||
.notes-label input { margin-left: 8px; min-width: min(520px, 80vw); padding: 6px 8px; border: 1px solid #c7d0df; border-radius: 6px; }
|
||||
.decision-template { margin-top: 10px; }
|
||||
pre, textarea { width: 100%; box-sizing: border-box; border: 1px solid #c7d0df; border-radius: 6px; background: #f8fafc; color: #172033; }
|
||||
pre { overflow: auto; padding: 10px; font-size: 12px; }
|
||||
textarea { min-height: 180px; padding: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<p><a href="../index.html">Back to gallery</a></p>
|
||||
<h1>daisy-days</h1>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt.</div>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt and does not automatically modify production/default.</div>
|
||||
<div class="meta">
|
||||
<div class="metric"><strong>9</strong>source pages</div>
|
||||
<div class="metric"><strong>blocked</strong>auto gate</div>
|
||||
<div class="metric"><strong>missing</strong>smoke</div>
|
||||
<div class="metric"><strong>passed</strong>fidelity</div>
|
||||
</div>
|
||||
<div class="review-panel">
|
||||
<h2>Human decision</h2>
|
||||
<div class="review-control" data-review-control-for="daisy-days"><div class="decision-buttons"><button type="button" data-family-id="daisy-days" data-review-status="pass">pass</button><button type="button" data-family-id="daisy-days" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="daisy-days" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="daisy-days">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="daisy-days" placeholder="optional apply-script context" /></label><details class="decision-template"><summary>Copyable decision JSON fragment</summary><pre>{
|
||||
"family_id": "daisy-days",
|
||||
"human_review_status_before_selection": "pending",
|
||||
"notes": "",
|
||||
"promotion_action": "no_change_until_human_pass",
|
||||
"review_status": "pass | needs_fix | reject",
|
||||
"runtime_template_id": "daisy-workshop-playbook",
|
||||
"source_gallery_receipt_path": "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json"
|
||||
}</pre></details></div>
|
||||
</div>
|
||||
<p><strong>Known blockers:</strong> auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</p>
|
||||
</header>
|
||||
<section class="review-handoff">
|
||||
<h2>Human Review Export</h2>
|
||||
<div class="warning">This local UI does not automatically modify production/default. It only stores browser-local decisions and exports JSON for a separate apply script.</div>
|
||||
<p><code>human_review_status=pending</code> <code>promotion_action=no_change_until_human_pass</code></p>
|
||||
<p>Machine-readable gallery receipt: <code>skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json</code></p>
|
||||
<p>Apply script input: save this textarea as decisions JSON, then pass it to the apply script, for example <code>python <apply-script> --gallery-receipt skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json --decisions <exported-decisions.json></code>.</p>
|
||||
<textarea id="review-decisions-json" readonly spellcheck="false"></textarea>
|
||||
</section>
|
||||
|
||||
<main class="deck">
|
||||
<section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/daisy-days-1.png" alt="welcome" /></div><h2>1. welcome</h2><p>cover / cover</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-welcome</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/daisy-days-1.png" alt="weekly" /></div><h2>2. weekly</h2><p>agenda / agenda</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-weekly</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/daisy-days-1.png" alt="timeline" /></div><h2>3. timeline</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-timeline</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/daisy-days-4.png" alt="chart_bar" /></div><h2>4. chart_bar</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-chart-bar</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/daisy-days-1.png" alt="cards" /></div><h2>5. cards</h2><p>detail / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-cards</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/daisy-days-1.png" alt="quote" /></div><h2>6. quote</h2><p>quote_or_emphasis / quote_or_emphasis</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-quote</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/daisy-days-1.png" alt="team" /></div><h2>7. team</h2><p>detail / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-team</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/daisy-days-8.png" alt="process" /></div><h2>8. process</h2><p>content / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-process</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/daisy-days-1.png" alt="donut" /></div><h2>9. donut</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-donut</code></p></section>
|
||||
</main>
|
||||
<script>
|
||||
(function () {
|
||||
var storageKey = "beautiful-production-review-decisions-v1";
|
||||
var schemaVersion = "svglide-beautiful-human-review-decisions/v1";
|
||||
var reviewBatchId = "beautiful-34";
|
||||
var receiptPath = "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json";
|
||||
var pendingHumanReviewStatus = "pending";
|
||||
var promotionAction = "no_change_until_human_pass";
|
||||
|
||||
function readState() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
||||
if (parsed && typeof parsed === "object" && parsed.decisions && typeof parsed.decisions === "object") {
|
||||
return parsed;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore malformed local state and rebuild below.
|
||||
}
|
||||
return { decisions: {} };
|
||||
}
|
||||
|
||||
function writeState(state) {
|
||||
localStorage.setItem(storageKey, JSON.stringify(state));
|
||||
}
|
||||
|
||||
function buildExport(state) {
|
||||
var decisions = Object.keys(state.decisions || {}).sort().map(function (familyId) {
|
||||
return state.decisions[familyId];
|
||||
});
|
||||
return {
|
||||
schema_version: schemaVersion,
|
||||
artifact_kind: "beautiful_template_human_review_decisions",
|
||||
review_batch_id: reviewBatchId,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
not_promotion_receipt: true,
|
||||
policy: {
|
||||
does_not_automatically_modify_production_default: true,
|
||||
apply_script_must_validate_gallery_receipt: true
|
||||
},
|
||||
decisions: decisions
|
||||
};
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.querySelectorAll("[data-review-current-for]").forEach(function (node) {
|
||||
var familyId = node.getAttribute("data-review-current-for");
|
||||
var decision = state.decisions[familyId];
|
||||
node.textContent = decision ? decision.review_status : "pending";
|
||||
});
|
||||
document.querySelectorAll("[data-review-status]").forEach(function (button) {
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var decision = state.decisions[familyId];
|
||||
button.classList.toggle("selected", Boolean(decision && decision.review_status === status));
|
||||
});
|
||||
document.querySelectorAll("[data-review-notes-for]").forEach(function (input) {
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var decision = state.decisions[familyId];
|
||||
if (decision && input.value !== decision.notes) {
|
||||
input.value = decision.notes || "";
|
||||
}
|
||||
});
|
||||
var textarea = document.getElementById("review-decisions-json");
|
||||
if (textarea) {
|
||||
textarea.value = JSON.stringify(buildExport(state), null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
var button = event.target.closest("[data-review-status]");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var existing = state.decisions[familyId] || {};
|
||||
state.decisions[familyId] = {
|
||||
family_id: familyId,
|
||||
review_status: status,
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
notes: existing.notes || "",
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
document.addEventListener("input", function (event) {
|
||||
var input = event.target.closest("[data-review-notes-for]");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var existing = state.decisions[familyId] || {
|
||||
family_id: familyId,
|
||||
review_status: "needs_fix",
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
existing.notes = input.value;
|
||||
existing.updated_at = new Date().toISOString();
|
||||
state.decisions[familyId] = existing;
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
render(readState());
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/daisy-days.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "60ae07dae1e5cb86fbefc0ffb62eb9bdf8c371f121793ad9d9e4cee23c993443"
|
||||
"sha256": "4df7e9d7a65b8e6749d3e487481302defbcfb6d0efd98fc00bb5afc6921e20cc"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "60ae07dae1e5cb86fbefc0ffb62eb9bdf8c371f121793ad9d9e4cee23c993443",
|
||||
"contact_sheet": "4df7e9d7a65b8e6749d3e487481302defbcfb6d0efd98fc00bb5afc6921e20cc",
|
||||
"fidelity_receipt": "926bc15a8016d24e25c00a42eb878578dbb825471d6ba2abc316bf48016ab5bc",
|
||||
"reference_screenshot": "65f6615ff2ec51a3d4a77573c2a53471b356724a58bd33dffdb55ed69ab2b73b",
|
||||
"smoke_receipt": null,
|
||||
|
||||
@@ -19,27 +19,175 @@
|
||||
h2 { margin: 10px 0 4px; font-size: 15px; }
|
||||
p { margin: 5px 0; font-size: 12px; color: #536071; }
|
||||
code { word-break: break-all; font-size: 11px; }
|
||||
button { cursor: pointer; border: 1px solid #b8c2d2; background: #fff; color: #172033; border-radius: 6px; padding: 6px 9px; font-weight: 700; }
|
||||
button.selected { border-color: #1d4ed8; background: #dbeafe; color: #1e3a8a; }
|
||||
.badge { display: inline-block; border-radius: 999px; padding: 2px 7px; font-size: 11px; font-weight: 700; }
|
||||
.ok { color: #065f46; background: #d1fae5; }
|
||||
.warn { color: #92400e; background: #fef3c7; }
|
||||
.bad { color: #991b1b; background: #fee2e2; }
|
||||
.review-panel, .review-handoff { background: #fff; border: 1px solid #dfe5ee; border-radius: 8px; padding: 14px; margin: 16px 0; }
|
||||
.decision-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
|
||||
.review-current { font-size: 12px; color: #536071; margin-bottom: 8px; }
|
||||
.notes-label { display: block; color: #536071; font-size: 12px; }
|
||||
.notes-label input { margin-left: 8px; min-width: min(520px, 80vw); padding: 6px 8px; border: 1px solid #c7d0df; border-radius: 6px; }
|
||||
.decision-template { margin-top: 10px; }
|
||||
pre, textarea { width: 100%; box-sizing: border-box; border: 1px solid #c7d0df; border-radius: 6px; background: #f8fafc; color: #172033; }
|
||||
pre { overflow: auto; padding: 10px; font-size: 12px; }
|
||||
textarea { min-height: 180px; padding: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<p><a href="../index.html">Back to gallery</a></p>
|
||||
<h1>editorial-forest</h1>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt.</div>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt and does not automatically modify production/default.</div>
|
||||
<div class="meta">
|
||||
<div class="metric"><strong>8</strong>source pages</div>
|
||||
<div class="metric"><strong>blocked</strong>auto gate</div>
|
||||
<div class="metric"><strong>missing</strong>smoke</div>
|
||||
<div class="metric"><strong>passed</strong>fidelity</div>
|
||||
</div>
|
||||
<div class="review-panel">
|
||||
<h2>Human decision</h2>
|
||||
<div class="review-control" data-review-control-for="editorial-forest"><div class="decision-buttons"><button type="button" data-family-id="editorial-forest" data-review-status="pass">pass</button><button type="button" data-family-id="editorial-forest" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="editorial-forest" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="editorial-forest">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="editorial-forest" placeholder="optional apply-script context" /></label><details class="decision-template"><summary>Copyable decision JSON fragment</summary><pre>{
|
||||
"family_id": "editorial-forest",
|
||||
"human_review_status_before_selection": "pending",
|
||||
"notes": "",
|
||||
"promotion_action": "no_change_until_human_pass",
|
||||
"review_status": "pass | needs_fix | reject",
|
||||
"runtime_template_id": "serif-stat-editorial",
|
||||
"source_gallery_receipt_path": "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json"
|
||||
}</pre></details></div>
|
||||
</div>
|
||||
<p><strong>Known blockers:</strong> auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</p>
|
||||
</header>
|
||||
<section class="review-handoff">
|
||||
<h2>Human Review Export</h2>
|
||||
<div class="warning">This local UI does not automatically modify production/default. It only stores browser-local decisions and exports JSON for a separate apply script.</div>
|
||||
<p><code>human_review_status=pending</code> <code>promotion_action=no_change_until_human_pass</code></p>
|
||||
<p>Machine-readable gallery receipt: <code>skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json</code></p>
|
||||
<p>Apply script input: save this textarea as decisions JSON, then pass it to the apply script, for example <code>python <apply-script> --gallery-receipt skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json --decisions <exported-decisions.json></code>.</p>
|
||||
<textarea id="review-decisions-json" readonly spellcheck="false"></textarea>
|
||||
</section>
|
||||
|
||||
<main class="deck">
|
||||
<section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/editorial-forest-1.png" alt="cover" /></div><h2>1. cover</h2><p>cover / cover</p><p><span class="badge bad">missing_smoke</span></p><p><code>cover</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/editorial-forest-2.png" alt="agenda" /></div><h2>2. agenda</h2><p>agenda / agenda</p><p><span class="badge bad">missing_smoke</span></p><p><code>agenda</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/editorial-forest-1.png" alt="statement" /></div><h2>3. statement</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>statement</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/editorial-forest-1.png" alt="two_col" /></div><h2>4. two_col</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>two-col</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/editorial-forest-5.png" alt="data" /></div><h2>5. data</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>data</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/editorial-forest-1.png" alt="framework" /></div><h2>6. framework</h2><p>detail / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>framework</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/editorial-forest-1.png" alt="stats" /></div><h2>7. stats</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>stats</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/editorial-forest-1.png" alt="summary" /></div><h2>8. summary</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>summary</code></p></section>
|
||||
</main>
|
||||
<script>
|
||||
(function () {
|
||||
var storageKey = "beautiful-production-review-decisions-v1";
|
||||
var schemaVersion = "svglide-beautiful-human-review-decisions/v1";
|
||||
var reviewBatchId = "beautiful-34";
|
||||
var receiptPath = "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json";
|
||||
var pendingHumanReviewStatus = "pending";
|
||||
var promotionAction = "no_change_until_human_pass";
|
||||
|
||||
function readState() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
||||
if (parsed && typeof parsed === "object" && parsed.decisions && typeof parsed.decisions === "object") {
|
||||
return parsed;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore malformed local state and rebuild below.
|
||||
}
|
||||
return { decisions: {} };
|
||||
}
|
||||
|
||||
function writeState(state) {
|
||||
localStorage.setItem(storageKey, JSON.stringify(state));
|
||||
}
|
||||
|
||||
function buildExport(state) {
|
||||
var decisions = Object.keys(state.decisions || {}).sort().map(function (familyId) {
|
||||
return state.decisions[familyId];
|
||||
});
|
||||
return {
|
||||
schema_version: schemaVersion,
|
||||
artifact_kind: "beautiful_template_human_review_decisions",
|
||||
review_batch_id: reviewBatchId,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
not_promotion_receipt: true,
|
||||
policy: {
|
||||
does_not_automatically_modify_production_default: true,
|
||||
apply_script_must_validate_gallery_receipt: true
|
||||
},
|
||||
decisions: decisions
|
||||
};
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.querySelectorAll("[data-review-current-for]").forEach(function (node) {
|
||||
var familyId = node.getAttribute("data-review-current-for");
|
||||
var decision = state.decisions[familyId];
|
||||
node.textContent = decision ? decision.review_status : "pending";
|
||||
});
|
||||
document.querySelectorAll("[data-review-status]").forEach(function (button) {
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var decision = state.decisions[familyId];
|
||||
button.classList.toggle("selected", Boolean(decision && decision.review_status === status));
|
||||
});
|
||||
document.querySelectorAll("[data-review-notes-for]").forEach(function (input) {
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var decision = state.decisions[familyId];
|
||||
if (decision && input.value !== decision.notes) {
|
||||
input.value = decision.notes || "";
|
||||
}
|
||||
});
|
||||
var textarea = document.getElementById("review-decisions-json");
|
||||
if (textarea) {
|
||||
textarea.value = JSON.stringify(buildExport(state), null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
var button = event.target.closest("[data-review-status]");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var existing = state.decisions[familyId] || {};
|
||||
state.decisions[familyId] = {
|
||||
family_id: familyId,
|
||||
review_status: status,
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
notes: existing.notes || "",
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
document.addEventListener("input", function (event) {
|
||||
var input = event.target.closest("[data-review-notes-for]");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var existing = state.decisions[familyId] || {
|
||||
family_id: familyId,
|
||||
review_status: "needs_fix",
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
existing.notes = input.value;
|
||||
existing.updated_at = new Date().toISOString();
|
||||
state.decisions[familyId] = existing;
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
render(readState());
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/editorial-forest.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "6966fb4b3014525f5b221bd6ad46a06c7f98b2046882f23d9a96c35876453e30"
|
||||
"sha256": "a72d3845093b54b819d538e7549951871fe1cb07d991b6eb84b48b2a398c653f"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "6966fb4b3014525f5b221bd6ad46a06c7f98b2046882f23d9a96c35876453e30",
|
||||
"contact_sheet": "a72d3845093b54b819d538e7549951871fe1cb07d991b6eb84b48b2a398c653f",
|
||||
"fidelity_receipt": "64abadb7a840271a45d482c1f3a7e8f4e75909ac007ef2c13d4ac0f77c77fdaf",
|
||||
"reference_screenshot": "a081f3b16a3dd72dd16d9fdfcf30aa61cf66c79c865189eb380d22bd425c2a1c",
|
||||
"smoke_receipt": null,
|
||||
|
||||
@@ -19,27 +19,175 @@
|
||||
h2 { margin: 10px 0 4px; font-size: 15px; }
|
||||
p { margin: 5px 0; font-size: 12px; color: #536071; }
|
||||
code { word-break: break-all; font-size: 11px; }
|
||||
button { cursor: pointer; border: 1px solid #b8c2d2; background: #fff; color: #172033; border-radius: 6px; padding: 6px 9px; font-weight: 700; }
|
||||
button.selected { border-color: #1d4ed8; background: #dbeafe; color: #1e3a8a; }
|
||||
.badge { display: inline-block; border-radius: 999px; padding: 2px 7px; font-size: 11px; font-weight: 700; }
|
||||
.ok { color: #065f46; background: #d1fae5; }
|
||||
.warn { color: #92400e; background: #fef3c7; }
|
||||
.bad { color: #991b1b; background: #fee2e2; }
|
||||
.review-panel, .review-handoff { background: #fff; border: 1px solid #dfe5ee; border-radius: 8px; padding: 14px; margin: 16px 0; }
|
||||
.decision-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
|
||||
.review-current { font-size: 12px; color: #536071; margin-bottom: 8px; }
|
||||
.notes-label { display: block; color: #536071; font-size: 12px; }
|
||||
.notes-label input { margin-left: 8px; min-width: min(520px, 80vw); padding: 6px 8px; border: 1px solid #c7d0df; border-radius: 6px; }
|
||||
.decision-template { margin-top: 10px; }
|
||||
pre, textarea { width: 100%; box-sizing: border-box; border: 1px solid #c7d0df; border-radius: 6px; background: #f8fafc; color: #172033; }
|
||||
pre { overflow: auto; padding: 10px; font-size: 12px; }
|
||||
textarea { min-height: 180px; padding: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<p><a href="../index.html">Back to gallery</a></p>
|
||||
<h1>editorial-tri-tone</h1>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt.</div>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt and does not automatically modify production/default.</div>
|
||||
<div class="meta">
|
||||
<div class="metric"><strong>8</strong>source pages</div>
|
||||
<div class="metric"><strong>blocked</strong>auto gate</div>
|
||||
<div class="metric"><strong>missing</strong>smoke</div>
|
||||
<div class="metric"><strong>passed</strong>fidelity</div>
|
||||
</div>
|
||||
<div class="review-panel">
|
||||
<h2>Human decision</h2>
|
||||
<div class="review-control" data-review-control-for="editorial-tri-tone"><div class="decision-buttons"><button type="button" data-family-id="editorial-tri-tone" data-review-status="pass">pass</button><button type="button" data-family-id="editorial-tri-tone" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="editorial-tri-tone" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="editorial-tri-tone">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="editorial-tri-tone" placeholder="optional apply-script context" /></label><details class="decision-template"><summary>Copyable decision JSON fragment</summary><pre>{
|
||||
"family_id": "editorial-tri-tone",
|
||||
"human_review_status_before_selection": "pending",
|
||||
"notes": "",
|
||||
"promotion_action": "no_change_until_human_pass",
|
||||
"review_status": "pass | needs_fix | reject",
|
||||
"runtime_template_id": "tritone-editorial-spread",
|
||||
"source_gallery_receipt_path": "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json"
|
||||
}</pre></details></div>
|
||||
</div>
|
||||
<p><strong>Known blockers:</strong> auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</p>
|
||||
</header>
|
||||
<section class="review-handoff">
|
||||
<h2>Human Review Export</h2>
|
||||
<div class="warning">This local UI does not automatically modify production/default. It only stores browser-local decisions and exports JSON for a separate apply script.</div>
|
||||
<p><code>human_review_status=pending</code> <code>promotion_action=no_change_until_human_pass</code></p>
|
||||
<p>Machine-readable gallery receipt: <code>skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json</code></p>
|
||||
<p>Apply script input: save this textarea as decisions JSON, then pass it to the apply script, for example <code>python <apply-script> --gallery-receipt skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json --decisions <exported-decisions.json></code>.</p>
|
||||
<textarea id="review-decisions-json" readonly spellcheck="false"></textarea>
|
||||
</section>
|
||||
|
||||
<main class="deck">
|
||||
<section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/editorial-tri-tone-1.png" alt="cover" /></div><h2>1. cover</h2><p>cover / cover</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-cover</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/editorial-tri-tone-1.png" alt="manifesto" /></div><h2>2. manifesto</h2><p>agenda / agenda</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-manifesto</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/editorial-tri-tone-3.png" alt="grid" /></div><h2>3. grid</h2><p>content / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-grid</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/editorial-tri-tone-4.png" alt="stat" /></div><h2>4. stat</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-stat</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/editorial-tri-tone-1.png" alt="timeline" /></div><h2>5. timeline</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-timeline</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/editorial-tri-tone-1.png" alt="chart" /></div><h2>6. chart</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-chart</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/editorial-tri-tone-1.png" alt="quote" /></div><h2>7. quote</h2><p>quote_or_emphasis / quote_or_emphasis</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-quote</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/editorial-tri-tone-1.png" alt="closer" /></div><h2>8. closer</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-closer</code></p></section>
|
||||
</main>
|
||||
<script>
|
||||
(function () {
|
||||
var storageKey = "beautiful-production-review-decisions-v1";
|
||||
var schemaVersion = "svglide-beautiful-human-review-decisions/v1";
|
||||
var reviewBatchId = "beautiful-34";
|
||||
var receiptPath = "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json";
|
||||
var pendingHumanReviewStatus = "pending";
|
||||
var promotionAction = "no_change_until_human_pass";
|
||||
|
||||
function readState() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
||||
if (parsed && typeof parsed === "object" && parsed.decisions && typeof parsed.decisions === "object") {
|
||||
return parsed;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore malformed local state and rebuild below.
|
||||
}
|
||||
return { decisions: {} };
|
||||
}
|
||||
|
||||
function writeState(state) {
|
||||
localStorage.setItem(storageKey, JSON.stringify(state));
|
||||
}
|
||||
|
||||
function buildExport(state) {
|
||||
var decisions = Object.keys(state.decisions || {}).sort().map(function (familyId) {
|
||||
return state.decisions[familyId];
|
||||
});
|
||||
return {
|
||||
schema_version: schemaVersion,
|
||||
artifact_kind: "beautiful_template_human_review_decisions",
|
||||
review_batch_id: reviewBatchId,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
not_promotion_receipt: true,
|
||||
policy: {
|
||||
does_not_automatically_modify_production_default: true,
|
||||
apply_script_must_validate_gallery_receipt: true
|
||||
},
|
||||
decisions: decisions
|
||||
};
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.querySelectorAll("[data-review-current-for]").forEach(function (node) {
|
||||
var familyId = node.getAttribute("data-review-current-for");
|
||||
var decision = state.decisions[familyId];
|
||||
node.textContent = decision ? decision.review_status : "pending";
|
||||
});
|
||||
document.querySelectorAll("[data-review-status]").forEach(function (button) {
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var decision = state.decisions[familyId];
|
||||
button.classList.toggle("selected", Boolean(decision && decision.review_status === status));
|
||||
});
|
||||
document.querySelectorAll("[data-review-notes-for]").forEach(function (input) {
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var decision = state.decisions[familyId];
|
||||
if (decision && input.value !== decision.notes) {
|
||||
input.value = decision.notes || "";
|
||||
}
|
||||
});
|
||||
var textarea = document.getElementById("review-decisions-json");
|
||||
if (textarea) {
|
||||
textarea.value = JSON.stringify(buildExport(state), null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
var button = event.target.closest("[data-review-status]");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var existing = state.decisions[familyId] || {};
|
||||
state.decisions[familyId] = {
|
||||
family_id: familyId,
|
||||
review_status: status,
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
notes: existing.notes || "",
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
document.addEventListener("input", function (event) {
|
||||
var input = event.target.closest("[data-review-notes-for]");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var existing = state.decisions[familyId] || {
|
||||
family_id: familyId,
|
||||
review_status: "needs_fix",
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
existing.notes = input.value;
|
||||
existing.updated_at = new Date().toISOString();
|
||||
state.decisions[familyId] = existing;
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
render(readState());
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/editorial-tri-tone.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "ba27daa57e94914e24e341b6a8ae1d7434dfb715f5bc6a54643173865839fb10"
|
||||
"sha256": "dfa4ea5c54fbd6428d4c98cba1707e4e7a6fa3f11b74dc8879c25305b20ca07f"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "ba27daa57e94914e24e341b6a8ae1d7434dfb715f5bc6a54643173865839fb10",
|
||||
"contact_sheet": "dfa4ea5c54fbd6428d4c98cba1707e4e7a6fa3f11b74dc8879c25305b20ca07f",
|
||||
"fidelity_receipt": "5bf44805d7dc674b07da8f0ac8f0a749bfc78893371e921567db82e5bf3a251b",
|
||||
"reference_screenshot": "0b89022af5bfcc26356b7bdb48156510ba16b643e9bc01027ae8197092ead507",
|
||||
"smoke_receipt": null,
|
||||
|
||||
@@ -19,27 +19,175 @@
|
||||
h2 { margin: 10px 0 4px; font-size: 15px; }
|
||||
p { margin: 5px 0; font-size: 12px; color: #536071; }
|
||||
code { word-break: break-all; font-size: 11px; }
|
||||
button { cursor: pointer; border: 1px solid #b8c2d2; background: #fff; color: #172033; border-radius: 6px; padding: 6px 9px; font-weight: 700; }
|
||||
button.selected { border-color: #1d4ed8; background: #dbeafe; color: #1e3a8a; }
|
||||
.badge { display: inline-block; border-radius: 999px; padding: 2px 7px; font-size: 11px; font-weight: 700; }
|
||||
.ok { color: #065f46; background: #d1fae5; }
|
||||
.warn { color: #92400e; background: #fef3c7; }
|
||||
.bad { color: #991b1b; background: #fee2e2; }
|
||||
.review-panel, .review-handoff { background: #fff; border: 1px solid #dfe5ee; border-radius: 8px; padding: 14px; margin: 16px 0; }
|
||||
.decision-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
|
||||
.review-current { font-size: 12px; color: #536071; margin-bottom: 8px; }
|
||||
.notes-label { display: block; color: #536071; font-size: 12px; }
|
||||
.notes-label input { margin-left: 8px; min-width: min(520px, 80vw); padding: 6px 8px; border: 1px solid #c7d0df; border-radius: 6px; }
|
||||
.decision-template { margin-top: 10px; }
|
||||
pre, textarea { width: 100%; box-sizing: border-box; border: 1px solid #c7d0df; border-radius: 6px; background: #f8fafc; color: #172033; }
|
||||
pre { overflow: auto; padding: 10px; font-size: 12px; }
|
||||
textarea { min-height: 180px; padding: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<p><a href="../index.html">Back to gallery</a></p>
|
||||
<h1>emerald-editorial</h1>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt.</div>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt and does not automatically modify production/default.</div>
|
||||
<div class="meta">
|
||||
<div class="metric"><strong>8</strong>source pages</div>
|
||||
<div class="metric"><strong>blocked</strong>auto gate</div>
|
||||
<div class="metric"><strong>missing</strong>smoke</div>
|
||||
<div class="metric"><strong>passed</strong>fidelity</div>
|
||||
</div>
|
||||
<div class="review-panel">
|
||||
<h2>Human decision</h2>
|
||||
<div class="review-control" data-review-control-for="emerald-editorial"><div class="decision-buttons"><button type="button" data-family-id="emerald-editorial" data-review-status="pass">pass</button><button type="button" data-family-id="emerald-editorial" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="emerald-editorial" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="emerald-editorial">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="emerald-editorial" placeholder="optional apply-script context" /></label><details class="decision-template"><summary>Copyable decision JSON fragment</summary><pre>{
|
||||
"family_id": "emerald-editorial",
|
||||
"human_review_status_before_selection": "pending",
|
||||
"notes": "",
|
||||
"promotion_action": "no_change_until_human_pass",
|
||||
"review_status": "pass | needs_fix | reject",
|
||||
"runtime_template_id": "emerald-editorial-cover",
|
||||
"source_gallery_receipt_path": "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json"
|
||||
}</pre></details></div>
|
||||
</div>
|
||||
<p><strong>Known blockers:</strong> auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</p>
|
||||
</header>
|
||||
<section class="review-handoff">
|
||||
<h2>Human Review Export</h2>
|
||||
<div class="warning">This local UI does not automatically modify production/default. It only stores browser-local decisions and exports JSON for a separate apply script.</div>
|
||||
<p><code>human_review_status=pending</code> <code>promotion_action=no_change_until_human_pass</code></p>
|
||||
<p>Machine-readable gallery receipt: <code>skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json</code></p>
|
||||
<p>Apply script input: save this textarea as decisions JSON, then pass it to the apply script, for example <code>python <apply-script> --gallery-receipt skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json --decisions <exported-decisions.json></code>.</p>
|
||||
<textarea id="review-decisions-json" readonly spellcheck="false"></textarea>
|
||||
</section>
|
||||
|
||||
<main class="deck">
|
||||
<section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/emerald-editorial-1.png" alt="s1" /></div><h2>1. s1</h2><p>cover / cover</p><p><span class="badge bad">missing_smoke</span></p><p><code>s1</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/emerald-editorial-1.png" alt="s2" /></div><h2>2. s2</h2><p>agenda / agenda</p><p><span class="badge bad">missing_smoke</span></p><p><code>s2</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/emerald-editorial-3.png" alt="s3" /></div><h2>3. s3</h2><p>detail / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>s3</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/emerald-editorial-1.png" alt="s4" /></div><h2>4. s4</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge bad">missing_smoke</span></p><p><code>s4</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/emerald-editorial-1.png" alt="s5" /></div><h2>5. s5</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s5</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/emerald-editorial-6.png" alt="s6" /></div><h2>6. s6</h2><p>detail / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>s6</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/emerald-editorial-1.png" alt="s7" /></div><h2>7. s7</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s7</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/emerald-editorial-1.png" alt="s8" /></div><h2>8. s8</h2><p>closing / closing</p><p><span class="badge bad">missing_smoke</span></p><p><code>s8</code></p></section>
|
||||
</main>
|
||||
<script>
|
||||
(function () {
|
||||
var storageKey = "beautiful-production-review-decisions-v1";
|
||||
var schemaVersion = "svglide-beautiful-human-review-decisions/v1";
|
||||
var reviewBatchId = "beautiful-34";
|
||||
var receiptPath = "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json";
|
||||
var pendingHumanReviewStatus = "pending";
|
||||
var promotionAction = "no_change_until_human_pass";
|
||||
|
||||
function readState() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
||||
if (parsed && typeof parsed === "object" && parsed.decisions && typeof parsed.decisions === "object") {
|
||||
return parsed;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore malformed local state and rebuild below.
|
||||
}
|
||||
return { decisions: {} };
|
||||
}
|
||||
|
||||
function writeState(state) {
|
||||
localStorage.setItem(storageKey, JSON.stringify(state));
|
||||
}
|
||||
|
||||
function buildExport(state) {
|
||||
var decisions = Object.keys(state.decisions || {}).sort().map(function (familyId) {
|
||||
return state.decisions[familyId];
|
||||
});
|
||||
return {
|
||||
schema_version: schemaVersion,
|
||||
artifact_kind: "beautiful_template_human_review_decisions",
|
||||
review_batch_id: reviewBatchId,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
not_promotion_receipt: true,
|
||||
policy: {
|
||||
does_not_automatically_modify_production_default: true,
|
||||
apply_script_must_validate_gallery_receipt: true
|
||||
},
|
||||
decisions: decisions
|
||||
};
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.querySelectorAll("[data-review-current-for]").forEach(function (node) {
|
||||
var familyId = node.getAttribute("data-review-current-for");
|
||||
var decision = state.decisions[familyId];
|
||||
node.textContent = decision ? decision.review_status : "pending";
|
||||
});
|
||||
document.querySelectorAll("[data-review-status]").forEach(function (button) {
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var decision = state.decisions[familyId];
|
||||
button.classList.toggle("selected", Boolean(decision && decision.review_status === status));
|
||||
});
|
||||
document.querySelectorAll("[data-review-notes-for]").forEach(function (input) {
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var decision = state.decisions[familyId];
|
||||
if (decision && input.value !== decision.notes) {
|
||||
input.value = decision.notes || "";
|
||||
}
|
||||
});
|
||||
var textarea = document.getElementById("review-decisions-json");
|
||||
if (textarea) {
|
||||
textarea.value = JSON.stringify(buildExport(state), null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
var button = event.target.closest("[data-review-status]");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var existing = state.decisions[familyId] || {};
|
||||
state.decisions[familyId] = {
|
||||
family_id: familyId,
|
||||
review_status: status,
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
notes: existing.notes || "",
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
document.addEventListener("input", function (event) {
|
||||
var input = event.target.closest("[data-review-notes-for]");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var existing = state.decisions[familyId] || {
|
||||
family_id: familyId,
|
||||
review_status: "needs_fix",
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
existing.notes = input.value;
|
||||
existing.updated_at = new Date().toISOString();
|
||||
state.decisions[familyId] = existing;
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
render(readState());
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/emerald-editorial.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "e082713ef62b3a90e195a07823726c77e4909aaed1cde7ca7b57b4b888860833"
|
||||
"sha256": "ae8042a321313b12a03e9b25379c89544421c4a9e8886b08f87990638f02d7da"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "e082713ef62b3a90e195a07823726c77e4909aaed1cde7ca7b57b4b888860833",
|
||||
"contact_sheet": "ae8042a321313b12a03e9b25379c89544421c4a9e8886b08f87990638f02d7da",
|
||||
"fidelity_receipt": "7aa06118b44f3dcc6202b56e64ec03134f5487d3e48a25279a9ccfeb09c1c81b",
|
||||
"reference_screenshot": "fda35bb4c4810369a5c5bccd70cbcd9d474691027c79a0d94ebf59dbf673c150",
|
||||
"smoke_receipt": null,
|
||||
|
||||
@@ -19,27 +19,175 @@
|
||||
h2 { margin: 10px 0 4px; font-size: 15px; }
|
||||
p { margin: 5px 0; font-size: 12px; color: #536071; }
|
||||
code { word-break: break-all; font-size: 11px; }
|
||||
button { cursor: pointer; border: 1px solid #b8c2d2; background: #fff; color: #172033; border-radius: 6px; padding: 6px 9px; font-weight: 700; }
|
||||
button.selected { border-color: #1d4ed8; background: #dbeafe; color: #1e3a8a; }
|
||||
.badge { display: inline-block; border-radius: 999px; padding: 2px 7px; font-size: 11px; font-weight: 700; }
|
||||
.ok { color: #065f46; background: #d1fae5; }
|
||||
.warn { color: #92400e; background: #fef3c7; }
|
||||
.bad { color: #991b1b; background: #fee2e2; }
|
||||
.review-panel, .review-handoff { background: #fff; border: 1px solid #dfe5ee; border-radius: 8px; padding: 14px; margin: 16px 0; }
|
||||
.decision-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
|
||||
.review-current { font-size: 12px; color: #536071; margin-bottom: 8px; }
|
||||
.notes-label { display: block; color: #536071; font-size: 12px; }
|
||||
.notes-label input { margin-left: 8px; min-width: min(520px, 80vw); padding: 6px 8px; border: 1px solid #c7d0df; border-radius: 6px; }
|
||||
.decision-template { margin-top: 10px; }
|
||||
pre, textarea { width: 100%; box-sizing: border-box; border: 1px solid #c7d0df; border-radius: 6px; background: #f8fafc; color: #172033; }
|
||||
pre { overflow: auto; padding: 10px; font-size: 12px; }
|
||||
textarea { min-height: 180px; padding: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<p><a href="../index.html">Back to gallery</a></p>
|
||||
<h1>grove</h1>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt.</div>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt and does not automatically modify production/default.</div>
|
||||
<div class="meta">
|
||||
<div class="metric"><strong>12</strong>source pages</div>
|
||||
<div class="metric"><strong>blocked</strong>auto gate</div>
|
||||
<div class="metric"><strong>missing</strong>smoke</div>
|
||||
<div class="metric"><strong>passed</strong>fidelity</div>
|
||||
</div>
|
||||
<div class="review-panel">
|
||||
<h2>Human decision</h2>
|
||||
<div class="review-control" data-review-control-for="grove"><div class="decision-buttons"><button type="button" data-family-id="grove" data-review-status="pass">pass</button><button type="button" data-family-id="grove" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="grove" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="grove">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="grove" placeholder="optional apply-script context" /></label><details class="decision-template"><summary>Copyable decision JSON fragment</summary><pre>{
|
||||
"family_id": "grove",
|
||||
"human_review_status_before_selection": "pending",
|
||||
"notes": "",
|
||||
"promotion_action": "no_change_until_human_pass",
|
||||
"review_status": "pass | needs_fix | reject",
|
||||
"runtime_template_id": "grove-organic-brief",
|
||||
"source_gallery_receipt_path": "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json"
|
||||
}</pre></details></div>
|
||||
</div>
|
||||
<p><strong>Known blockers:</strong> auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</p>
|
||||
</header>
|
||||
<section class="review-handoff">
|
||||
<h2>Human Review Export</h2>
|
||||
<div class="warning">This local UI does not automatically modify production/default. It only stores browser-local decisions and exports JSON for a separate apply script.</div>
|
||||
<p><code>human_review_status=pending</code> <code>promotion_action=no_change_until_human_pass</code></p>
|
||||
<p>Machine-readable gallery receipt: <code>skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json</code></p>
|
||||
<p>Apply script input: save this textarea as decisions JSON, then pass it to the apply script, for example <code>python <apply-script> --gallery-receipt skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json --decisions <exported-decisions.json></code>.</p>
|
||||
<textarea id="review-decisions-json" readonly spellcheck="false"></textarea>
|
||||
</section>
|
||||
|
||||
<main class="deck">
|
||||
<section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/grove-1.png" alt="cover" /></div><h2>1. cover</h2><p>cover / cover</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--cover</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/grove-1.png" alt="chapter" /></div><h2>2. chapter</h2><p>agenda / agenda</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--chapter</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/grove-1.png" alt="statement" /></div><h2>3. statement</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--statement</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/grove-4.png" alt="split" /></div><h2>4. split</h2><p>content_split / comparison_or_split</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--split</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/grove-1.png" alt="stats" /></div><h2>5. stats</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--stats</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/grove-1.png" alt="list" /></div><h2>6. list</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--list</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/grove-1.png" alt="quote" /></div><h2>7. quote</h2><p>quote_or_emphasis / quote_or_emphasis</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--quote</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/grove-8.png" alt="compare" /></div><h2>8. compare</h2><p>data_dashboard / comparison_or_split</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--compare</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/grove-1.png" alt="chapter-9" /></div><h2>9. chapter-9</h2><p>content / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--chapter</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/grove-1.png" alt="statement-10" /></div><h2>10. statement-10</h2><p>closing / closing</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--statement</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/grove-1.png" alt="chart" /></div><h2>11. chart</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--chart</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/grove-1.png" alt="end" /></div><h2>12. end</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--end</code></p></section>
|
||||
</main>
|
||||
<script>
|
||||
(function () {
|
||||
var storageKey = "beautiful-production-review-decisions-v1";
|
||||
var schemaVersion = "svglide-beautiful-human-review-decisions/v1";
|
||||
var reviewBatchId = "beautiful-34";
|
||||
var receiptPath = "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json";
|
||||
var pendingHumanReviewStatus = "pending";
|
||||
var promotionAction = "no_change_until_human_pass";
|
||||
|
||||
function readState() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
||||
if (parsed && typeof parsed === "object" && parsed.decisions && typeof parsed.decisions === "object") {
|
||||
return parsed;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore malformed local state and rebuild below.
|
||||
}
|
||||
return { decisions: {} };
|
||||
}
|
||||
|
||||
function writeState(state) {
|
||||
localStorage.setItem(storageKey, JSON.stringify(state));
|
||||
}
|
||||
|
||||
function buildExport(state) {
|
||||
var decisions = Object.keys(state.decisions || {}).sort().map(function (familyId) {
|
||||
return state.decisions[familyId];
|
||||
});
|
||||
return {
|
||||
schema_version: schemaVersion,
|
||||
artifact_kind: "beautiful_template_human_review_decisions",
|
||||
review_batch_id: reviewBatchId,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
not_promotion_receipt: true,
|
||||
policy: {
|
||||
does_not_automatically_modify_production_default: true,
|
||||
apply_script_must_validate_gallery_receipt: true
|
||||
},
|
||||
decisions: decisions
|
||||
};
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.querySelectorAll("[data-review-current-for]").forEach(function (node) {
|
||||
var familyId = node.getAttribute("data-review-current-for");
|
||||
var decision = state.decisions[familyId];
|
||||
node.textContent = decision ? decision.review_status : "pending";
|
||||
});
|
||||
document.querySelectorAll("[data-review-status]").forEach(function (button) {
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var decision = state.decisions[familyId];
|
||||
button.classList.toggle("selected", Boolean(decision && decision.review_status === status));
|
||||
});
|
||||
document.querySelectorAll("[data-review-notes-for]").forEach(function (input) {
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var decision = state.decisions[familyId];
|
||||
if (decision && input.value !== decision.notes) {
|
||||
input.value = decision.notes || "";
|
||||
}
|
||||
});
|
||||
var textarea = document.getElementById("review-decisions-json");
|
||||
if (textarea) {
|
||||
textarea.value = JSON.stringify(buildExport(state), null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
var button = event.target.closest("[data-review-status]");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var existing = state.decisions[familyId] || {};
|
||||
state.decisions[familyId] = {
|
||||
family_id: familyId,
|
||||
review_status: status,
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
notes: existing.notes || "",
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
document.addEventListener("input", function (event) {
|
||||
var input = event.target.closest("[data-review-notes-for]");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var existing = state.decisions[familyId] || {
|
||||
family_id: familyId,
|
||||
review_status: "needs_fix",
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
existing.notes = input.value;
|
||||
existing.updated_at = new Date().toISOString();
|
||||
state.decisions[familyId] = existing;
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
render(readState());
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/grove.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "35333c79ea1ad148e7763b55a6d5886dae6c077cd65c49430a954e69d5997eb7"
|
||||
"sha256": "da6b1ce28c3ae75ea17159bc4a656369fc659bdbfcff3b953aa9ac3ca4c74e28"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "35333c79ea1ad148e7763b55a6d5886dae6c077cd65c49430a954e69d5997eb7",
|
||||
"contact_sheet": "da6b1ce28c3ae75ea17159bc4a656369fc659bdbfcff3b953aa9ac3ca4c74e28",
|
||||
"fidelity_receipt": "72a5d983bb922049b536f086eedb89d0e3a7959b72480aab5fcfce63842d7455",
|
||||
"reference_screenshot": "6a01598d4b183837b96c698eb9453962fea4bea072a431ee4d71aef6e09da3eb",
|
||||
"smoke_receipt": null,
|
||||
|
||||
@@ -19,27 +19,175 @@
|
||||
h2 { margin: 10px 0 4px; font-size: 15px; }
|
||||
p { margin: 5px 0; font-size: 12px; color: #536071; }
|
||||
code { word-break: break-all; font-size: 11px; }
|
||||
button { cursor: pointer; border: 1px solid #b8c2d2; background: #fff; color: #172033; border-radius: 6px; padding: 6px 9px; font-weight: 700; }
|
||||
button.selected { border-color: #1d4ed8; background: #dbeafe; color: #1e3a8a; }
|
||||
.badge { display: inline-block; border-radius: 999px; padding: 2px 7px; font-size: 11px; font-weight: 700; }
|
||||
.ok { color: #065f46; background: #d1fae5; }
|
||||
.warn { color: #92400e; background: #fef3c7; }
|
||||
.bad { color: #991b1b; background: #fee2e2; }
|
||||
.review-panel, .review-handoff { background: #fff; border: 1px solid #dfe5ee; border-radius: 8px; padding: 14px; margin: 16px 0; }
|
||||
.decision-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
|
||||
.review-current { font-size: 12px; color: #536071; margin-bottom: 8px; }
|
||||
.notes-label { display: block; color: #536071; font-size: 12px; }
|
||||
.notes-label input { margin-left: 8px; min-width: min(520px, 80vw); padding: 6px 8px; border: 1px solid #c7d0df; border-radius: 6px; }
|
||||
.decision-template { margin-top: 10px; }
|
||||
pre, textarea { width: 100%; box-sizing: border-box; border: 1px solid #c7d0df; border-radius: 6px; background: #f8fafc; color: #172033; }
|
||||
pre { overflow: auto; padding: 10px; font-size: 12px; }
|
||||
textarea { min-height: 180px; padding: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<p><a href="../index.html">Back to gallery</a></p>
|
||||
<h1>long-table</h1>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt.</div>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt and does not automatically modify production/default.</div>
|
||||
<div class="meta">
|
||||
<div class="metric"><strong>8</strong>source pages</div>
|
||||
<div class="metric"><strong>blocked</strong>auto gate</div>
|
||||
<div class="metric"><strong>missing</strong>smoke</div>
|
||||
<div class="metric"><strong>passed</strong>fidelity</div>
|
||||
</div>
|
||||
<div class="review-panel">
|
||||
<h2>Human decision</h2>
|
||||
<div class="review-control" data-review-control-for="long-table"><div class="decision-buttons"><button type="button" data-family-id="long-table" data-review-status="pass">pass</button><button type="button" data-family-id="long-table" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="long-table" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="long-table">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="long-table" placeholder="optional apply-script context" /></label><details class="decision-template"><summary>Copyable decision JSON fragment</summary><pre>{
|
||||
"family_id": "long-table",
|
||||
"human_review_status_before_selection": "pending",
|
||||
"notes": "",
|
||||
"promotion_action": "no_change_until_human_pass",
|
||||
"review_status": "pass | needs_fix | reject",
|
||||
"runtime_template_id": "printed-program",
|
||||
"source_gallery_receipt_path": "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json"
|
||||
}</pre></details></div>
|
||||
</div>
|
||||
<p><strong>Known blockers:</strong> auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</p>
|
||||
</header>
|
||||
<section class="review-handoff">
|
||||
<h2>Human Review Export</h2>
|
||||
<div class="warning">This local UI does not automatically modify production/default. It only stores browser-local decisions and exports JSON for a separate apply script.</div>
|
||||
<p><code>human_review_status=pending</code> <code>promotion_action=no_change_until_human_pass</code></p>
|
||||
<p>Machine-readable gallery receipt: <code>skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json</code></p>
|
||||
<p>Apply script input: save this textarea as decisions JSON, then pass it to the apply script, for example <code>python <apply-script> --gallery-receipt skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json --decisions <exported-decisions.json></code>.</p>
|
||||
<textarea id="review-decisions-json" readonly spellcheck="false"></textarea>
|
||||
</section>
|
||||
|
||||
<main class="deck">
|
||||
<section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/long-table-1.png" alt="cover" /></div><h2>1. cover</h2><p>cover / cover</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-cover</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/long-table-1.png" alt="manifesto" /></div><h2>2. manifesto</h2><p>agenda / agenda</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-manifesto</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/long-table-3.png" alt="index" /></div><h2>3. index</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-index</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/long-table-1.png" alt="featured" /></div><h2>4. featured</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-featured</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/long-table-1.png" alt="menu" /></div><h2>5. menu</h2><p>content / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-menu</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/long-table-1.png" alt="quote" /></div><h2>6. quote</h2><p>quote_or_emphasis / quote_or_emphasis</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-quote</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/long-table-7.png" alt="cal" /></div><h2>7. cal</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-cal</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/long-table-1.png" alt="closing" /></div><h2>8. closing</h2><p>closing / closing</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-closing</code></p></section>
|
||||
</main>
|
||||
<script>
|
||||
(function () {
|
||||
var storageKey = "beautiful-production-review-decisions-v1";
|
||||
var schemaVersion = "svglide-beautiful-human-review-decisions/v1";
|
||||
var reviewBatchId = "beautiful-34";
|
||||
var receiptPath = "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json";
|
||||
var pendingHumanReviewStatus = "pending";
|
||||
var promotionAction = "no_change_until_human_pass";
|
||||
|
||||
function readState() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
||||
if (parsed && typeof parsed === "object" && parsed.decisions && typeof parsed.decisions === "object") {
|
||||
return parsed;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore malformed local state and rebuild below.
|
||||
}
|
||||
return { decisions: {} };
|
||||
}
|
||||
|
||||
function writeState(state) {
|
||||
localStorage.setItem(storageKey, JSON.stringify(state));
|
||||
}
|
||||
|
||||
function buildExport(state) {
|
||||
var decisions = Object.keys(state.decisions || {}).sort().map(function (familyId) {
|
||||
return state.decisions[familyId];
|
||||
});
|
||||
return {
|
||||
schema_version: schemaVersion,
|
||||
artifact_kind: "beautiful_template_human_review_decisions",
|
||||
review_batch_id: reviewBatchId,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
not_promotion_receipt: true,
|
||||
policy: {
|
||||
does_not_automatically_modify_production_default: true,
|
||||
apply_script_must_validate_gallery_receipt: true
|
||||
},
|
||||
decisions: decisions
|
||||
};
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.querySelectorAll("[data-review-current-for]").forEach(function (node) {
|
||||
var familyId = node.getAttribute("data-review-current-for");
|
||||
var decision = state.decisions[familyId];
|
||||
node.textContent = decision ? decision.review_status : "pending";
|
||||
});
|
||||
document.querySelectorAll("[data-review-status]").forEach(function (button) {
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var decision = state.decisions[familyId];
|
||||
button.classList.toggle("selected", Boolean(decision && decision.review_status === status));
|
||||
});
|
||||
document.querySelectorAll("[data-review-notes-for]").forEach(function (input) {
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var decision = state.decisions[familyId];
|
||||
if (decision && input.value !== decision.notes) {
|
||||
input.value = decision.notes || "";
|
||||
}
|
||||
});
|
||||
var textarea = document.getElementById("review-decisions-json");
|
||||
if (textarea) {
|
||||
textarea.value = JSON.stringify(buildExport(state), null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
var button = event.target.closest("[data-review-status]");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var existing = state.decisions[familyId] || {};
|
||||
state.decisions[familyId] = {
|
||||
family_id: familyId,
|
||||
review_status: status,
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
notes: existing.notes || "",
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
document.addEventListener("input", function (event) {
|
||||
var input = event.target.closest("[data-review-notes-for]");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var existing = state.decisions[familyId] || {
|
||||
family_id: familyId,
|
||||
review_status: "needs_fix",
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
existing.notes = input.value;
|
||||
existing.updated_at = new Date().toISOString();
|
||||
state.decisions[familyId] = existing;
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
render(readState());
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/long-table.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "03eff66d27ff955a40c9ff4fda6f840251594bcaa9698d1452cc3527118a7317"
|
||||
"sha256": "451fb96587eb1e8dad65a4e7e34a40c7f81ce178256f9e61f72fb57090c4c61a"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "03eff66d27ff955a40c9ff4fda6f840251594bcaa9698d1452cc3527118a7317",
|
||||
"contact_sheet": "451fb96587eb1e8dad65a4e7e34a40c7f81ce178256f9e61f72fb57090c4c61a",
|
||||
"fidelity_receipt": "96948f5547801870efb639d755ee4b944114cd0925c3fd03f6d15cafe935119e",
|
||||
"reference_screenshot": "79f7956399971a6038c6b98ba7850b8d232c593bafb1c484c7127e5d3fd60bba",
|
||||
"smoke_receipt": null,
|
||||
|
||||
@@ -19,27 +19,175 @@
|
||||
h2 { margin: 10px 0 4px; font-size: 15px; }
|
||||
p { margin: 5px 0; font-size: 12px; color: #536071; }
|
||||
code { word-break: break-all; font-size: 11px; }
|
||||
button { cursor: pointer; border: 1px solid #b8c2d2; background: #fff; color: #172033; border-radius: 6px; padding: 6px 9px; font-weight: 700; }
|
||||
button.selected { border-color: #1d4ed8; background: #dbeafe; color: #1e3a8a; }
|
||||
.badge { display: inline-block; border-radius: 999px; padding: 2px 7px; font-size: 11px; font-weight: 700; }
|
||||
.ok { color: #065f46; background: #d1fae5; }
|
||||
.warn { color: #92400e; background: #fef3c7; }
|
||||
.bad { color: #991b1b; background: #fee2e2; }
|
||||
.review-panel, .review-handoff { background: #fff; border: 1px solid #dfe5ee; border-radius: 8px; padding: 14px; margin: 16px 0; }
|
||||
.decision-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
|
||||
.review-current { font-size: 12px; color: #536071; margin-bottom: 8px; }
|
||||
.notes-label { display: block; color: #536071; font-size: 12px; }
|
||||
.notes-label input { margin-left: 8px; min-width: min(520px, 80vw); padding: 6px 8px; border: 1px solid #c7d0df; border-radius: 6px; }
|
||||
.decision-template { margin-top: 10px; }
|
||||
pre, textarea { width: 100%; box-sizing: border-box; border: 1px solid #c7d0df; border-radius: 6px; background: #f8fafc; color: #172033; }
|
||||
pre { overflow: auto; padding: 10px; font-size: 12px; }
|
||||
textarea { min-height: 180px; padding: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<p><a href="../index.html">Back to gallery</a></p>
|
||||
<h1>mat</h1>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt.</div>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt and does not automatically modify production/default.</div>
|
||||
<div class="meta">
|
||||
<div class="metric"><strong>9</strong>source pages</div>
|
||||
<div class="metric"><strong>blocked</strong>auto gate</div>
|
||||
<div class="metric"><strong>missing</strong>smoke</div>
|
||||
<div class="metric"><strong>passed</strong>fidelity</div>
|
||||
</div>
|
||||
<div class="review-panel">
|
||||
<h2>Human decision</h2>
|
||||
<div class="review-control" data-review-control-for="mat"><div class="decision-buttons"><button type="button" data-family-id="mat" data-review-status="pass">pass</button><button type="button" data-family-id="mat" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="mat" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="mat">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="mat" placeholder="optional apply-script context" /></label><details class="decision-template"><summary>Copyable decision JSON fragment</summary><pre>{
|
||||
"family_id": "mat",
|
||||
"human_review_status_before_selection": "pending",
|
||||
"notes": "",
|
||||
"promotion_action": "no_change_until_human_pass",
|
||||
"review_status": "pass | needs_fix | reject",
|
||||
"runtime_template_id": "mat-midcentury-board",
|
||||
"source_gallery_receipt_path": "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json"
|
||||
}</pre></details></div>
|
||||
</div>
|
||||
<p><strong>Known blockers:</strong> auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</p>
|
||||
</header>
|
||||
<section class="review-handoff">
|
||||
<h2>Human Review Export</h2>
|
||||
<div class="warning">This local UI does not automatically modify production/default. It only stores browser-local decisions and exports JSON for a separate apply script.</div>
|
||||
<p><code>human_review_status=pending</code> <code>promotion_action=no_change_until_human_pass</code></p>
|
||||
<p>Machine-readable gallery receipt: <code>skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json</code></p>
|
||||
<p>Apply script input: save this textarea as decisions JSON, then pass it to the apply script, for example <code>python <apply-script> --gallery-receipt skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json --decisions <exported-decisions.json></code>.</p>
|
||||
<textarea id="review-decisions-json" readonly spellcheck="false"></textarea>
|
||||
</section>
|
||||
|
||||
<main class="deck">
|
||||
<section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/mat-1.png" alt="cover" /></div><h2>1. cover</h2><p>cover / cover</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--cover</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/mat-1.png" alt="statement" /></div><h2>2. statement</h2><p>agenda / agenda</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--statement</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/mat-1.png" alt="split" /></div><h2>3. split</h2><p>content_split / comparison_or_split</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--split</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/mat-4.png" alt="stats" /></div><h2>4. stats</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--stats</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/mat-1.png" alt="quote" /></div><h2>5. quote</h2><p>quote_or_emphasis / quote_or_emphasis</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--quote</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/mat-1.png" alt="list" /></div><h2>6. list</h2><p>content / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--list</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/mat-1.png" alt="compare" /></div><h2>7. compare</h2><p>content / comparison_or_split</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--compare</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/mat-8.png" alt="chart" /></div><h2>8. chart</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--chart</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/mat-1.png" alt="end" /></div><h2>9. end</h2><p>content / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--end</code></p></section>
|
||||
</main>
|
||||
<script>
|
||||
(function () {
|
||||
var storageKey = "beautiful-production-review-decisions-v1";
|
||||
var schemaVersion = "svglide-beautiful-human-review-decisions/v1";
|
||||
var reviewBatchId = "beautiful-34";
|
||||
var receiptPath = "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json";
|
||||
var pendingHumanReviewStatus = "pending";
|
||||
var promotionAction = "no_change_until_human_pass";
|
||||
|
||||
function readState() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
||||
if (parsed && typeof parsed === "object" && parsed.decisions && typeof parsed.decisions === "object") {
|
||||
return parsed;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore malformed local state and rebuild below.
|
||||
}
|
||||
return { decisions: {} };
|
||||
}
|
||||
|
||||
function writeState(state) {
|
||||
localStorage.setItem(storageKey, JSON.stringify(state));
|
||||
}
|
||||
|
||||
function buildExport(state) {
|
||||
var decisions = Object.keys(state.decisions || {}).sort().map(function (familyId) {
|
||||
return state.decisions[familyId];
|
||||
});
|
||||
return {
|
||||
schema_version: schemaVersion,
|
||||
artifact_kind: "beautiful_template_human_review_decisions",
|
||||
review_batch_id: reviewBatchId,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
not_promotion_receipt: true,
|
||||
policy: {
|
||||
does_not_automatically_modify_production_default: true,
|
||||
apply_script_must_validate_gallery_receipt: true
|
||||
},
|
||||
decisions: decisions
|
||||
};
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.querySelectorAll("[data-review-current-for]").forEach(function (node) {
|
||||
var familyId = node.getAttribute("data-review-current-for");
|
||||
var decision = state.decisions[familyId];
|
||||
node.textContent = decision ? decision.review_status : "pending";
|
||||
});
|
||||
document.querySelectorAll("[data-review-status]").forEach(function (button) {
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var decision = state.decisions[familyId];
|
||||
button.classList.toggle("selected", Boolean(decision && decision.review_status === status));
|
||||
});
|
||||
document.querySelectorAll("[data-review-notes-for]").forEach(function (input) {
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var decision = state.decisions[familyId];
|
||||
if (decision && input.value !== decision.notes) {
|
||||
input.value = decision.notes || "";
|
||||
}
|
||||
});
|
||||
var textarea = document.getElementById("review-decisions-json");
|
||||
if (textarea) {
|
||||
textarea.value = JSON.stringify(buildExport(state), null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
var button = event.target.closest("[data-review-status]");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var existing = state.decisions[familyId] || {};
|
||||
state.decisions[familyId] = {
|
||||
family_id: familyId,
|
||||
review_status: status,
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
notes: existing.notes || "",
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
document.addEventListener("input", function (event) {
|
||||
var input = event.target.closest("[data-review-notes-for]");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var existing = state.decisions[familyId] || {
|
||||
family_id: familyId,
|
||||
review_status: "needs_fix",
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
existing.notes = input.value;
|
||||
existing.updated_at = new Date().toISOString();
|
||||
state.decisions[familyId] = existing;
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
render(readState());
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/mat.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "80cc3f0b8990075017711519795bc91a6a73eb5e748ec350fcf1dbbec092738f"
|
||||
"sha256": "45c1a37544d752c06e326d5789a8ad1a51ba2a7926e27db048490526898423b4"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "80cc3f0b8990075017711519795bc91a6a73eb5e748ec350fcf1dbbec092738f",
|
||||
"contact_sheet": "45c1a37544d752c06e326d5789a8ad1a51ba2a7926e27db048490526898423b4",
|
||||
"fidelity_receipt": "e1e95e38f4ea8124a378b7de4a0eb81593f192811ea42e7b31085ed84410cf34",
|
||||
"reference_screenshot": "acac0ac30af8fbb206adfb6810573c72d3ca96b00293f9f850fdeefed1ae11dc",
|
||||
"smoke_receipt": null,
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -10,11 +10,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/monochrome.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "98ff05a96dc1ba8c6d1567cdc05e07d956cf6c4d8acb8ff95ec73df343d9e6d7"
|
||||
"sha256": "3d2584d894dc76b41f1abd78da0a0dba991a1b9cbc6e63672bb9cb45f75418a1"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "98ff05a96dc1ba8c6d1567cdc05e07d956cf6c4d8acb8ff95ec73df343d9e6d7",
|
||||
"contact_sheet": "3d2584d894dc76b41f1abd78da0a0dba991a1b9cbc6e63672bb9cb45f75418a1",
|
||||
"fidelity_receipt": "7fd4a1a4f9929a0add47861c0f489f80b3cfe4dd9e91dc13014ec264811c78c5",
|
||||
"reference_screenshot": "bac6b00bf1d0b3c97b19d2a0c45edf44af5cbf369f2cf3ebe78a207a7b6b8c7b",
|
||||
"smoke_receipt": null,
|
||||
|
||||
@@ -19,27 +19,175 @@
|
||||
h2 { margin: 10px 0 4px; font-size: 15px; }
|
||||
p { margin: 5px 0; font-size: 12px; color: #536071; }
|
||||
code { word-break: break-all; font-size: 11px; }
|
||||
button { cursor: pointer; border: 1px solid #b8c2d2; background: #fff; color: #172033; border-radius: 6px; padding: 6px 9px; font-weight: 700; }
|
||||
button.selected { border-color: #1d4ed8; background: #dbeafe; color: #1e3a8a; }
|
||||
.badge { display: inline-block; border-radius: 999px; padding: 2px 7px; font-size: 11px; font-weight: 700; }
|
||||
.ok { color: #065f46; background: #d1fae5; }
|
||||
.warn { color: #92400e; background: #fef3c7; }
|
||||
.bad { color: #991b1b; background: #fee2e2; }
|
||||
.review-panel, .review-handoff { background: #fff; border: 1px solid #dfe5ee; border-radius: 8px; padding: 14px; margin: 16px 0; }
|
||||
.decision-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
|
||||
.review-current { font-size: 12px; color: #536071; margin-bottom: 8px; }
|
||||
.notes-label { display: block; color: #536071; font-size: 12px; }
|
||||
.notes-label input { margin-left: 8px; min-width: min(520px, 80vw); padding: 6px 8px; border: 1px solid #c7d0df; border-radius: 6px; }
|
||||
.decision-template { margin-top: 10px; }
|
||||
pre, textarea { width: 100%; box-sizing: border-box; border: 1px solid #c7d0df; border-radius: 6px; background: #f8fafc; color: #172033; }
|
||||
pre { overflow: auto; padding: 10px; font-size: 12px; }
|
||||
textarea { min-height: 180px; padding: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<p><a href="../index.html">Back to gallery</a></p>
|
||||
<h1>neo-grid-bold</h1>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt.</div>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt and does not automatically modify production/default.</div>
|
||||
<div class="meta">
|
||||
<div class="metric"><strong>12</strong>source pages</div>
|
||||
<div class="metric"><strong>blocked</strong>auto gate</div>
|
||||
<div class="metric"><strong>missing</strong>smoke</div>
|
||||
<div class="metric"><strong>passed</strong>fidelity</div>
|
||||
</div>
|
||||
<div class="review-panel">
|
||||
<h2>Human decision</h2>
|
||||
<div class="review-control" data-review-control-for="neo-grid-bold"><div class="decision-buttons"><button type="button" data-family-id="neo-grid-bold" data-review-status="pass">pass</button><button type="button" data-family-id="neo-grid-bold" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="neo-grid-bold" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="neo-grid-bold">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="neo-grid-bold" placeholder="optional apply-script context" /></label><details class="decision-template"><summary>Copyable decision JSON fragment</summary><pre>{
|
||||
"family_id": "neo-grid-bold",
|
||||
"human_review_status_before_selection": "pending",
|
||||
"notes": "",
|
||||
"promotion_action": "no_change_until_human_pass",
|
||||
"review_status": "pass | needs_fix | reject",
|
||||
"runtime_template_id": "dense-panel-grid",
|
||||
"source_gallery_receipt_path": "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json"
|
||||
}</pre></details></div>
|
||||
</div>
|
||||
<p><strong>Known blockers:</strong> auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</p>
|
||||
</header>
|
||||
<section class="review-handoff">
|
||||
<h2>Human Review Export</h2>
|
||||
<div class="warning">This local UI does not automatically modify production/default. It only stores browser-local decisions and exports JSON for a separate apply script.</div>
|
||||
<p><code>human_review_status=pending</code> <code>promotion_action=no_change_until_human_pass</code></p>
|
||||
<p>Machine-readable gallery receipt: <code>skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json</code></p>
|
||||
<p>Apply script input: save this textarea as decisions JSON, then pass it to the apply script, for example <code>python <apply-script> --gallery-receipt skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json --decisions <exported-decisions.json></code>.</p>
|
||||
<textarea id="review-decisions-json" readonly spellcheck="false"></textarea>
|
||||
</section>
|
||||
|
||||
<main class="deck">
|
||||
<section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/neo-grid-bold-1.png" alt="cover" /></div><h2>1. cover</h2><p>cover / cover</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-cover</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/neo-grid-bold-1.png" alt="toc" /></div><h2>2. toc</h2><p>agenda / agenda</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-toc</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/neo-grid-bold-3.png" alt="stats" /></div><h2>3. stats</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-stats</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/neo-grid-bold-1.png" alt="features" /></div><h2>4. features</h2><p>detail / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-features</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/neo-grid-bold-1.png" alt="chart" /></div><h2>5. chart</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-chart</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/neo-grid-bold-1.png" alt="section" /></div><h2>6. section</h2><p>content / agenda</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-section</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/neo-grid-bold-1.png" alt="quote" /></div><h2>7. quote</h2><p>quote_or_emphasis / quote_or_emphasis</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-quote</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/neo-grid-bold-8.png" alt="cta" /></div><h2>8. cta</h2><p>detail / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-cta</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/neo-grid-bold-1.png" alt="consult" /></div><h2>9. consult</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-consult</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/neo-grid-bold-1.png" alt="chart2" /></div><h2>10. chart2</h2><p>closing / closing</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-chart2</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/neo-grid-bold-1.png" alt="process2" /></div><h2>11. process2</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-process2</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/neo-grid-bold-1.png" alt="matrix2" /></div><h2>12. matrix2</h2><p>content / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-matrix2</code></p></section>
|
||||
</main>
|
||||
<script>
|
||||
(function () {
|
||||
var storageKey = "beautiful-production-review-decisions-v1";
|
||||
var schemaVersion = "svglide-beautiful-human-review-decisions/v1";
|
||||
var reviewBatchId = "beautiful-34";
|
||||
var receiptPath = "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json";
|
||||
var pendingHumanReviewStatus = "pending";
|
||||
var promotionAction = "no_change_until_human_pass";
|
||||
|
||||
function readState() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
||||
if (parsed && typeof parsed === "object" && parsed.decisions && typeof parsed.decisions === "object") {
|
||||
return parsed;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore malformed local state and rebuild below.
|
||||
}
|
||||
return { decisions: {} };
|
||||
}
|
||||
|
||||
function writeState(state) {
|
||||
localStorage.setItem(storageKey, JSON.stringify(state));
|
||||
}
|
||||
|
||||
function buildExport(state) {
|
||||
var decisions = Object.keys(state.decisions || {}).sort().map(function (familyId) {
|
||||
return state.decisions[familyId];
|
||||
});
|
||||
return {
|
||||
schema_version: schemaVersion,
|
||||
artifact_kind: "beautiful_template_human_review_decisions",
|
||||
review_batch_id: reviewBatchId,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
not_promotion_receipt: true,
|
||||
policy: {
|
||||
does_not_automatically_modify_production_default: true,
|
||||
apply_script_must_validate_gallery_receipt: true
|
||||
},
|
||||
decisions: decisions
|
||||
};
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.querySelectorAll("[data-review-current-for]").forEach(function (node) {
|
||||
var familyId = node.getAttribute("data-review-current-for");
|
||||
var decision = state.decisions[familyId];
|
||||
node.textContent = decision ? decision.review_status : "pending";
|
||||
});
|
||||
document.querySelectorAll("[data-review-status]").forEach(function (button) {
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var decision = state.decisions[familyId];
|
||||
button.classList.toggle("selected", Boolean(decision && decision.review_status === status));
|
||||
});
|
||||
document.querySelectorAll("[data-review-notes-for]").forEach(function (input) {
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var decision = state.decisions[familyId];
|
||||
if (decision && input.value !== decision.notes) {
|
||||
input.value = decision.notes || "";
|
||||
}
|
||||
});
|
||||
var textarea = document.getElementById("review-decisions-json");
|
||||
if (textarea) {
|
||||
textarea.value = JSON.stringify(buildExport(state), null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
var button = event.target.closest("[data-review-status]");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var existing = state.decisions[familyId] || {};
|
||||
state.decisions[familyId] = {
|
||||
family_id: familyId,
|
||||
review_status: status,
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
notes: existing.notes || "",
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
document.addEventListener("input", function (event) {
|
||||
var input = event.target.closest("[data-review-notes-for]");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var existing = state.decisions[familyId] || {
|
||||
family_id: familyId,
|
||||
review_status: "needs_fix",
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
existing.notes = input.value;
|
||||
existing.updated_at = new Date().toISOString();
|
||||
state.decisions[familyId] = existing;
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
render(readState());
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/neo-grid-bold.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "ceebdd152351e3d9124f365de2ea46b5b03bd90f8ca532d7f99f79bc29cfd95d"
|
||||
"sha256": "dfdb0c6be0e75f49ecd5d5a782eff136bb25cc679bfbfd17540b9aa47d14356e"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "ceebdd152351e3d9124f365de2ea46b5b03bd90f8ca532d7f99f79bc29cfd95d",
|
||||
"contact_sheet": "dfdb0c6be0e75f49ecd5d5a782eff136bb25cc679bfbfd17540b9aa47d14356e",
|
||||
"fidelity_receipt": "9d0ced3d64a642e028edf86ff6457c36def39175b3079fff6a4c97b645803228",
|
||||
"reference_screenshot": "c53ba5da0f1b85b23ad1975da65edafaee84f029f06c468b2fbd036031ce15e5",
|
||||
"smoke_receipt": null,
|
||||
|
||||
@@ -19,27 +19,175 @@
|
||||
h2 { margin: 10px 0 4px; font-size: 15px; }
|
||||
p { margin: 5px 0; font-size: 12px; color: #536071; }
|
||||
code { word-break: break-all; font-size: 11px; }
|
||||
button { cursor: pointer; border: 1px solid #b8c2d2; background: #fff; color: #172033; border-radius: 6px; padding: 6px 9px; font-weight: 700; }
|
||||
button.selected { border-color: #1d4ed8; background: #dbeafe; color: #1e3a8a; }
|
||||
.badge { display: inline-block; border-radius: 999px; padding: 2px 7px; font-size: 11px; font-weight: 700; }
|
||||
.ok { color: #065f46; background: #d1fae5; }
|
||||
.warn { color: #92400e; background: #fef3c7; }
|
||||
.bad { color: #991b1b; background: #fee2e2; }
|
||||
.review-panel, .review-handoff { background: #fff; border: 1px solid #dfe5ee; border-radius: 8px; padding: 14px; margin: 16px 0; }
|
||||
.decision-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
|
||||
.review-current { font-size: 12px; color: #536071; margin-bottom: 8px; }
|
||||
.notes-label { display: block; color: #536071; font-size: 12px; }
|
||||
.notes-label input { margin-left: 8px; min-width: min(520px, 80vw); padding: 6px 8px; border: 1px solid #c7d0df; border-radius: 6px; }
|
||||
.decision-template { margin-top: 10px; }
|
||||
pre, textarea { width: 100%; box-sizing: border-box; border: 1px solid #c7d0df; border-radius: 6px; background: #f8fafc; color: #172033; }
|
||||
pre { overflow: auto; padding: 10px; font-size: 12px; }
|
||||
textarea { min-height: 180px; padding: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<p><a href="../index.html">Back to gallery</a></p>
|
||||
<h1>peoples-platform</h1>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt.</div>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt and does not automatically modify production/default.</div>
|
||||
<div class="meta">
|
||||
<div class="metric"><strong>10</strong>source pages</div>
|
||||
<div class="metric"><strong>blocked</strong>auto gate</div>
|
||||
<div class="metric"><strong>missing</strong>smoke</div>
|
||||
<div class="metric"><strong>passed</strong>fidelity</div>
|
||||
</div>
|
||||
<div class="review-panel">
|
||||
<h2>Human decision</h2>
|
||||
<div class="review-control" data-review-control-for="peoples-platform"><div class="decision-buttons"><button type="button" data-family-id="peoples-platform" data-review-status="pass">pass</button><button type="button" data-family-id="peoples-platform" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="peoples-platform" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="peoples-platform">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="peoples-platform" placeholder="optional apply-script context" /></label><details class="decision-template"><summary>Copyable decision JSON fragment</summary><pre>{
|
||||
"family_id": "peoples-platform",
|
||||
"human_review_status_before_selection": "pending",
|
||||
"notes": "",
|
||||
"promotion_action": "no_change_until_human_pass",
|
||||
"review_status": "pass | needs_fix | reject",
|
||||
"runtime_template_id": "people-platform-manifesto",
|
||||
"source_gallery_receipt_path": "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json"
|
||||
}</pre></details></div>
|
||||
</div>
|
||||
<p><strong>Known blockers:</strong> auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing</p>
|
||||
</header>
|
||||
<section class="review-handoff">
|
||||
<h2>Human Review Export</h2>
|
||||
<div class="warning">This local UI does not automatically modify production/default. It only stores browser-local decisions and exports JSON for a separate apply script.</div>
|
||||
<p><code>human_review_status=pending</code> <code>promotion_action=no_change_until_human_pass</code></p>
|
||||
<p>Machine-readable gallery receipt: <code>skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json</code></p>
|
||||
<p>Apply script input: save this textarea as decisions JSON, then pass it to the apply script, for example <code>python <apply-script> --gallery-receipt skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json --decisions <exported-decisions.json></code>.</p>
|
||||
<textarea id="review-decisions-json" readonly spellcheck="false"></textarea>
|
||||
</section>
|
||||
|
||||
<main class="deck">
|
||||
<section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/peoples-platform-1.png" alt="cover" /></div><h2>1. cover</h2><p>cover / cover</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-cover</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/peoples-platform-1.png" alt="toc" /></div><h2>2. toc</h2><p>agenda / agenda</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-toc</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/peoples-platform-1.png" alt="manifesto" /></div><h2>3. manifesto</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-manifesto</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/peoples-platform-4.png" alt="pillars" /></div><h2>4. pillars</h2><p>detail / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-pillars</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/peoples-platform-1.png" alt="stat" /></div><h2>5. stat</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-stat</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/peoples-platform-1.png" alt="platform" /></div><h2>6. platform</h2><p>detail / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-platform</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/peoples-platform-1.png" alt="quote" /></div><h2>7. quote</h2><p>quote_or_emphasis / quote_or_emphasis</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-quote</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/peoples-platform-8.png" alt="timeline" /></div><h2>8. timeline</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-timeline</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/peoples-platform-1.png" alt="compare" /></div><h2>9. compare</h2><p>detail / comparison_or_split</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-compare</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/peoples-platform-1.png" alt="close" /></div><h2>10. close</h2><p>closing / closing</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-close</code></p></section>
|
||||
</main>
|
||||
<script>
|
||||
(function () {
|
||||
var storageKey = "beautiful-production-review-decisions-v1";
|
||||
var schemaVersion = "svglide-beautiful-human-review-decisions/v1";
|
||||
var reviewBatchId = "beautiful-34";
|
||||
var receiptPath = "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json";
|
||||
var pendingHumanReviewStatus = "pending";
|
||||
var promotionAction = "no_change_until_human_pass";
|
||||
|
||||
function readState() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
||||
if (parsed && typeof parsed === "object" && parsed.decisions && typeof parsed.decisions === "object") {
|
||||
return parsed;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore malformed local state and rebuild below.
|
||||
}
|
||||
return { decisions: {} };
|
||||
}
|
||||
|
||||
function writeState(state) {
|
||||
localStorage.setItem(storageKey, JSON.stringify(state));
|
||||
}
|
||||
|
||||
function buildExport(state) {
|
||||
var decisions = Object.keys(state.decisions || {}).sort().map(function (familyId) {
|
||||
return state.decisions[familyId];
|
||||
});
|
||||
return {
|
||||
schema_version: schemaVersion,
|
||||
artifact_kind: "beautiful_template_human_review_decisions",
|
||||
review_batch_id: reviewBatchId,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
not_promotion_receipt: true,
|
||||
policy: {
|
||||
does_not_automatically_modify_production_default: true,
|
||||
apply_script_must_validate_gallery_receipt: true
|
||||
},
|
||||
decisions: decisions
|
||||
};
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.querySelectorAll("[data-review-current-for]").forEach(function (node) {
|
||||
var familyId = node.getAttribute("data-review-current-for");
|
||||
var decision = state.decisions[familyId];
|
||||
node.textContent = decision ? decision.review_status : "pending";
|
||||
});
|
||||
document.querySelectorAll("[data-review-status]").forEach(function (button) {
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var decision = state.decisions[familyId];
|
||||
button.classList.toggle("selected", Boolean(decision && decision.review_status === status));
|
||||
});
|
||||
document.querySelectorAll("[data-review-notes-for]").forEach(function (input) {
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var decision = state.decisions[familyId];
|
||||
if (decision && input.value !== decision.notes) {
|
||||
input.value = decision.notes || "";
|
||||
}
|
||||
});
|
||||
var textarea = document.getElementById("review-decisions-json");
|
||||
if (textarea) {
|
||||
textarea.value = JSON.stringify(buildExport(state), null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
var button = event.target.closest("[data-review-status]");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var existing = state.decisions[familyId] || {};
|
||||
state.decisions[familyId] = {
|
||||
family_id: familyId,
|
||||
review_status: status,
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
notes: existing.notes || "",
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
document.addEventListener("input", function (event) {
|
||||
var input = event.target.closest("[data-review-notes-for]");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var existing = state.decisions[familyId] || {
|
||||
family_id: familyId,
|
||||
review_status: "needs_fix",
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
existing.notes = input.value;
|
||||
existing.updated_at = new Date().toISOString();
|
||||
state.decisions[familyId] = existing;
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
render(readState());
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/peoples-platform.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "6cde51c31f47436c3b5b6db4fbaccb4181b795fb84213c6a1e0ace77cd88eb66"
|
||||
"sha256": "35f74a4093000ea952bfbfef2a211fd0d47f6c926ecbc6cb6fc95a07f3946acf"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "6cde51c31f47436c3b5b6db4fbaccb4181b795fb84213c6a1e0ace77cd88eb66",
|
||||
"contact_sheet": "35f74a4093000ea952bfbfef2a211fd0d47f6c926ecbc6cb6fc95a07f3946acf",
|
||||
"fidelity_receipt": "679368f5526815a2cb311d583f0f86871000639c85643e6b47099ab91566d5cc",
|
||||
"reference_screenshot": "9a0c40acaa0fb9c058745cbd16c875f9b7a0417d46c6c37dede388e32cf52d25",
|
||||
"smoke_receipt": null,
|
||||
|
||||
@@ -19,27 +19,175 @@
|
||||
h2 { margin: 10px 0 4px; font-size: 15px; }
|
||||
p { margin: 5px 0; font-size: 12px; color: #536071; }
|
||||
code { word-break: break-all; font-size: 11px; }
|
||||
button { cursor: pointer; border: 1px solid #b8c2d2; background: #fff; color: #172033; border-radius: 6px; padding: 6px 9px; font-weight: 700; }
|
||||
button.selected { border-color: #1d4ed8; background: #dbeafe; color: #1e3a8a; }
|
||||
.badge { display: inline-block; border-radius: 999px; padding: 2px 7px; font-size: 11px; font-weight: 700; }
|
||||
.ok { color: #065f46; background: #d1fae5; }
|
||||
.warn { color: #92400e; background: #fef3c7; }
|
||||
.bad { color: #991b1b; background: #fee2e2; }
|
||||
.review-panel, .review-handoff { background: #fff; border: 1px solid #dfe5ee; border-radius: 8px; padding: 14px; margin: 16px 0; }
|
||||
.decision-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
|
||||
.review-current { font-size: 12px; color: #536071; margin-bottom: 8px; }
|
||||
.notes-label { display: block; color: #536071; font-size: 12px; }
|
||||
.notes-label input { margin-left: 8px; min-width: min(520px, 80vw); padding: 6px 8px; border: 1px solid #c7d0df; border-radius: 6px; }
|
||||
.decision-template { margin-top: 10px; }
|
||||
pre, textarea { width: 100%; box-sizing: border-box; border: 1px solid #c7d0df; border-radius: 6px; background: #f8fafc; color: #172033; }
|
||||
pre { overflow: auto; padding: 10px; font-size: 12px; }
|
||||
textarea { min-height: 180px; padding: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<p><a href="../index.html">Back to gallery</a></p>
|
||||
<h1>pin-and-paper</h1>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt.</div>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt and does not automatically modify production/default.</div>
|
||||
<div class="meta">
|
||||
<div class="metric"><strong>11</strong>source pages</div>
|
||||
<div class="metric"><strong>blocked</strong>auto gate</div>
|
||||
<div class="metric"><strong>missing</strong>smoke</div>
|
||||
<div class="metric"><strong>passed</strong>fidelity</div>
|
||||
</div>
|
||||
<div class="review-panel">
|
||||
<h2>Human decision</h2>
|
||||
<div class="review-control" data-review-control-for="pin-and-paper"><div class="decision-buttons"><button type="button" data-family-id="pin-and-paper" data-review-status="pass">pass</button><button type="button" data-family-id="pin-and-paper" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="pin-and-paper" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="pin-and-paper">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="pin-and-paper" placeholder="optional apply-script context" /></label><details class="decision-template"><summary>Copyable decision JSON fragment</summary><pre>{
|
||||
"family_id": "pin-and-paper",
|
||||
"human_review_status_before_selection": "pending",
|
||||
"notes": "",
|
||||
"promotion_action": "no_change_until_human_pass",
|
||||
"review_status": "pass | needs_fix | reject",
|
||||
"runtime_template_id": "annotated-field-board",
|
||||
"source_gallery_receipt_path": "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json"
|
||||
}</pre></details></div>
|
||||
</div>
|
||||
<p><strong>Known blockers:</strong> auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</p>
|
||||
</header>
|
||||
<section class="review-handoff">
|
||||
<h2>Human Review Export</h2>
|
||||
<div class="warning">This local UI does not automatically modify production/default. It only stores browser-local decisions and exports JSON for a separate apply script.</div>
|
||||
<p><code>human_review_status=pending</code> <code>promotion_action=no_change_until_human_pass</code></p>
|
||||
<p>Machine-readable gallery receipt: <code>skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json</code></p>
|
||||
<p>Apply script input: save this textarea as decisions JSON, then pass it to the apply script, for example <code>python <apply-script> --gallery-receipt skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json --decisions <exported-decisions.json></code>.</p>
|
||||
<textarea id="review-decisions-json" readonly spellcheck="false"></textarea>
|
||||
</section>
|
||||
|
||||
<main class="deck">
|
||||
<section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/pin-and-paper-1.png" alt="cover" /></div><h2>1. cover</h2><p>cover / cover</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-cover</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/pin-and-paper-1.png" alt="agenda" /></div><h2>2. agenda</h2><p>agenda / agenda</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-agenda</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/pin-and-paper-3.png" alt="notes" /></div><h2>3. notes</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-notes</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/pin-and-paper-1.png" alt="sec" /></div><h2>4. sec</h2><p>content / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-sec</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/pin-and-paper-1.png" alt="notice" /></div><h2>5. notice</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-notice</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/pin-and-paper-1.png" alt="chart" /></div><h2>6. chart</h2><p>process_or_timeline / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-chart</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/pin-and-paper-1.png" alt="process" /></div><h2>7. process</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-process</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/pin-and-paper-1.png" alt="matrix" /></div><h2>8. matrix</h2><p>process_or_timeline / comparison_or_split</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-matrix</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/pin-and-paper-1.png" alt="stats" /></div><h2>9. stats</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-stats</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/pin-and-paper-1.png" alt="quote" /></div><h2>10. quote</h2><p>quote_or_emphasis / quote_or_emphasis</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-quote</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/pin-and-paper-11.png" alt="cta" /></div><h2>11. cta</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-cta</code></p></section>
|
||||
</main>
|
||||
<script>
|
||||
(function () {
|
||||
var storageKey = "beautiful-production-review-decisions-v1";
|
||||
var schemaVersion = "svglide-beautiful-human-review-decisions/v1";
|
||||
var reviewBatchId = "beautiful-34";
|
||||
var receiptPath = "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json";
|
||||
var pendingHumanReviewStatus = "pending";
|
||||
var promotionAction = "no_change_until_human_pass";
|
||||
|
||||
function readState() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
||||
if (parsed && typeof parsed === "object" && parsed.decisions && typeof parsed.decisions === "object") {
|
||||
return parsed;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore malformed local state and rebuild below.
|
||||
}
|
||||
return { decisions: {} };
|
||||
}
|
||||
|
||||
function writeState(state) {
|
||||
localStorage.setItem(storageKey, JSON.stringify(state));
|
||||
}
|
||||
|
||||
function buildExport(state) {
|
||||
var decisions = Object.keys(state.decisions || {}).sort().map(function (familyId) {
|
||||
return state.decisions[familyId];
|
||||
});
|
||||
return {
|
||||
schema_version: schemaVersion,
|
||||
artifact_kind: "beautiful_template_human_review_decisions",
|
||||
review_batch_id: reviewBatchId,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
not_promotion_receipt: true,
|
||||
policy: {
|
||||
does_not_automatically_modify_production_default: true,
|
||||
apply_script_must_validate_gallery_receipt: true
|
||||
},
|
||||
decisions: decisions
|
||||
};
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.querySelectorAll("[data-review-current-for]").forEach(function (node) {
|
||||
var familyId = node.getAttribute("data-review-current-for");
|
||||
var decision = state.decisions[familyId];
|
||||
node.textContent = decision ? decision.review_status : "pending";
|
||||
});
|
||||
document.querySelectorAll("[data-review-status]").forEach(function (button) {
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var decision = state.decisions[familyId];
|
||||
button.classList.toggle("selected", Boolean(decision && decision.review_status === status));
|
||||
});
|
||||
document.querySelectorAll("[data-review-notes-for]").forEach(function (input) {
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var decision = state.decisions[familyId];
|
||||
if (decision && input.value !== decision.notes) {
|
||||
input.value = decision.notes || "";
|
||||
}
|
||||
});
|
||||
var textarea = document.getElementById("review-decisions-json");
|
||||
if (textarea) {
|
||||
textarea.value = JSON.stringify(buildExport(state), null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
var button = event.target.closest("[data-review-status]");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var existing = state.decisions[familyId] || {};
|
||||
state.decisions[familyId] = {
|
||||
family_id: familyId,
|
||||
review_status: status,
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
notes: existing.notes || "",
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
document.addEventListener("input", function (event) {
|
||||
var input = event.target.closest("[data-review-notes-for]");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var existing = state.decisions[familyId] || {
|
||||
family_id: familyId,
|
||||
review_status: "needs_fix",
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
existing.notes = input.value;
|
||||
existing.updated_at = new Date().toISOString();
|
||||
state.decisions[familyId] = existing;
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
render(readState());
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/pin-and-paper.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "d3300e5df932d79e82fd0853a9af8c252aa090d1e1df988d77b4d1045ca63002"
|
||||
"sha256": "063652158d00662045c6a94a70a8e7ae36f00aabf3ea5216463e7f8c6564256a"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "d3300e5df932d79e82fd0853a9af8c252aa090d1e1df988d77b4d1045ca63002",
|
||||
"contact_sheet": "063652158d00662045c6a94a70a8e7ae36f00aabf3ea5216463e7f8c6564256a",
|
||||
"fidelity_receipt": "b6aa5696947e5fc7fcd633c340cea26e983956f97a0a54b72eb035818d6a3d76",
|
||||
"reference_screenshot": "35ff94a10d71d18318fa11e1c95fb6a32e2b1801ffff24ccc8e0f36afe187387",
|
||||
"smoke_receipt": null,
|
||||
|
||||
@@ -19,27 +19,175 @@
|
||||
h2 { margin: 10px 0 4px; font-size: 15px; }
|
||||
p { margin: 5px 0; font-size: 12px; color: #536071; }
|
||||
code { word-break: break-all; font-size: 11px; }
|
||||
button { cursor: pointer; border: 1px solid #b8c2d2; background: #fff; color: #172033; border-radius: 6px; padding: 6px 9px; font-weight: 700; }
|
||||
button.selected { border-color: #1d4ed8; background: #dbeafe; color: #1e3a8a; }
|
||||
.badge { display: inline-block; border-radius: 999px; padding: 2px 7px; font-size: 11px; font-weight: 700; }
|
||||
.ok { color: #065f46; background: #d1fae5; }
|
||||
.warn { color: #92400e; background: #fef3c7; }
|
||||
.bad { color: #991b1b; background: #fee2e2; }
|
||||
.review-panel, .review-handoff { background: #fff; border: 1px solid #dfe5ee; border-radius: 8px; padding: 14px; margin: 16px 0; }
|
||||
.decision-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
|
||||
.review-current { font-size: 12px; color: #536071; margin-bottom: 8px; }
|
||||
.notes-label { display: block; color: #536071; font-size: 12px; }
|
||||
.notes-label input { margin-left: 8px; min-width: min(520px, 80vw); padding: 6px 8px; border: 1px solid #c7d0df; border-radius: 6px; }
|
||||
.decision-template { margin-top: 10px; }
|
||||
pre, textarea { width: 100%; box-sizing: border-box; border: 1px solid #c7d0df; border-radius: 6px; background: #f8fafc; color: #172033; }
|
||||
pre { overflow: auto; padding: 10px; font-size: 12px; }
|
||||
textarea { min-height: 180px; padding: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<p><a href="../index.html">Back to gallery</a></p>
|
||||
<h1>pink-script</h1>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt.</div>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt and does not automatically modify production/default.</div>
|
||||
<div class="meta">
|
||||
<div class="metric"><strong>9</strong>source pages</div>
|
||||
<div class="metric"><strong>blocked</strong>auto gate</div>
|
||||
<div class="metric"><strong>missing</strong>smoke</div>
|
||||
<div class="metric"><strong>passed</strong>fidelity</div>
|
||||
</div>
|
||||
<div class="review-panel">
|
||||
<h2>Human decision</h2>
|
||||
<div class="review-control" data-review-control-for="pink-script"><div class="decision-buttons"><button type="button" data-family-id="pink-script" data-review-status="pass">pass</button><button type="button" data-family-id="pink-script" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="pink-script" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="pink-script">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="pink-script" placeholder="optional apply-script context" /></label><details class="decision-template"><summary>Copyable decision JSON fragment</summary><pre>{
|
||||
"family_id": "pink-script",
|
||||
"human_review_status_before_selection": "pending",
|
||||
"notes": "",
|
||||
"promotion_action": "no_change_until_human_pass",
|
||||
"review_status": "pass | needs_fix | reject",
|
||||
"runtime_template_id": "pink-nocturne-feature",
|
||||
"source_gallery_receipt_path": "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json"
|
||||
}</pre></details></div>
|
||||
</div>
|
||||
<p><strong>Known blockers:</strong> auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</p>
|
||||
</header>
|
||||
<section class="review-handoff">
|
||||
<h2>Human Review Export</h2>
|
||||
<div class="warning">This local UI does not automatically modify production/default. It only stores browser-local decisions and exports JSON for a separate apply script.</div>
|
||||
<p><code>human_review_status=pending</code> <code>promotion_action=no_change_until_human_pass</code></p>
|
||||
<p>Machine-readable gallery receipt: <code>skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json</code></p>
|
||||
<p>Apply script input: save this textarea as decisions JSON, then pass it to the apply script, for example <code>python <apply-script> --gallery-receipt skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json --decisions <exported-decisions.json></code>.</p>
|
||||
<textarea id="review-decisions-json" readonly spellcheck="false"></textarea>
|
||||
</section>
|
||||
|
||||
<main class="deck">
|
||||
<section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/pink-script-1.png" alt="cover" /></div><h2>1. cover</h2><p>cover / cover</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-cover</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/pink-script-1.png" alt="toc" /></div><h2>2. toc</h2><p>agenda / agenda</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-toc</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/pink-script-1.png" alt="stats" /></div><h2>3. stats</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-stats</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/pink-script-4.png" alt="section" /></div><h2>4. section</h2><p>content / agenda</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-section</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/pink-script-1.png" alt="chart" /></div><h2>5. chart</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-chart</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/pink-script-1.png" alt="process" /></div><h2>6. process</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-process</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/pink-script-1.png" alt="matrix" /></div><h2>7. matrix</h2><p>content / comparison_or_split</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-matrix</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/pink-script-8.png" alt="quote" /></div><h2>8. quote</h2><p>quote_or_emphasis / quote_or_emphasis</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-quote</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/pink-script-1.png" alt="cta" /></div><h2>9. cta</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-cta</code></p></section>
|
||||
</main>
|
||||
<script>
|
||||
(function () {
|
||||
var storageKey = "beautiful-production-review-decisions-v1";
|
||||
var schemaVersion = "svglide-beautiful-human-review-decisions/v1";
|
||||
var reviewBatchId = "beautiful-34";
|
||||
var receiptPath = "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json";
|
||||
var pendingHumanReviewStatus = "pending";
|
||||
var promotionAction = "no_change_until_human_pass";
|
||||
|
||||
function readState() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
||||
if (parsed && typeof parsed === "object" && parsed.decisions && typeof parsed.decisions === "object") {
|
||||
return parsed;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore malformed local state and rebuild below.
|
||||
}
|
||||
return { decisions: {} };
|
||||
}
|
||||
|
||||
function writeState(state) {
|
||||
localStorage.setItem(storageKey, JSON.stringify(state));
|
||||
}
|
||||
|
||||
function buildExport(state) {
|
||||
var decisions = Object.keys(state.decisions || {}).sort().map(function (familyId) {
|
||||
return state.decisions[familyId];
|
||||
});
|
||||
return {
|
||||
schema_version: schemaVersion,
|
||||
artifact_kind: "beautiful_template_human_review_decisions",
|
||||
review_batch_id: reviewBatchId,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
not_promotion_receipt: true,
|
||||
policy: {
|
||||
does_not_automatically_modify_production_default: true,
|
||||
apply_script_must_validate_gallery_receipt: true
|
||||
},
|
||||
decisions: decisions
|
||||
};
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.querySelectorAll("[data-review-current-for]").forEach(function (node) {
|
||||
var familyId = node.getAttribute("data-review-current-for");
|
||||
var decision = state.decisions[familyId];
|
||||
node.textContent = decision ? decision.review_status : "pending";
|
||||
});
|
||||
document.querySelectorAll("[data-review-status]").forEach(function (button) {
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var decision = state.decisions[familyId];
|
||||
button.classList.toggle("selected", Boolean(decision && decision.review_status === status));
|
||||
});
|
||||
document.querySelectorAll("[data-review-notes-for]").forEach(function (input) {
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var decision = state.decisions[familyId];
|
||||
if (decision && input.value !== decision.notes) {
|
||||
input.value = decision.notes || "";
|
||||
}
|
||||
});
|
||||
var textarea = document.getElementById("review-decisions-json");
|
||||
if (textarea) {
|
||||
textarea.value = JSON.stringify(buildExport(state), null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
var button = event.target.closest("[data-review-status]");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var existing = state.decisions[familyId] || {};
|
||||
state.decisions[familyId] = {
|
||||
family_id: familyId,
|
||||
review_status: status,
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
notes: existing.notes || "",
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
document.addEventListener("input", function (event) {
|
||||
var input = event.target.closest("[data-review-notes-for]");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var existing = state.decisions[familyId] || {
|
||||
family_id: familyId,
|
||||
review_status: "needs_fix",
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
existing.notes = input.value;
|
||||
existing.updated_at = new Date().toISOString();
|
||||
state.decisions[familyId] = existing;
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
render(readState());
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/pink-script.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "b0b78d2776184009efaedb026d3c5dc4528a29f8fba7d7b6c5da4618fbd42497"
|
||||
"sha256": "be97ade117aa12ee9ffcd562c2e2f905076db7c4ba21ebbc3efa92b4aa0890ae"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "b0b78d2776184009efaedb026d3c5dc4528a29f8fba7d7b6c5da4618fbd42497",
|
||||
"contact_sheet": "be97ade117aa12ee9ffcd562c2e2f905076db7c4ba21ebbc3efa92b4aa0890ae",
|
||||
"fidelity_receipt": "ff075c2947f7c09785c47c57f68d995722873676d91251a822747e0b096b88bf",
|
||||
"reference_screenshot": "d39af58b620fe59ab0e28db0f070fd6e13214896115aa984be069369ef594ff7",
|
||||
"smoke_receipt": null,
|
||||
|
||||
@@ -19,27 +19,175 @@
|
||||
h2 { margin: 10px 0 4px; font-size: 15px; }
|
||||
p { margin: 5px 0; font-size: 12px; color: #536071; }
|
||||
code { word-break: break-all; font-size: 11px; }
|
||||
button { cursor: pointer; border: 1px solid #b8c2d2; background: #fff; color: #172033; border-radius: 6px; padding: 6px 9px; font-weight: 700; }
|
||||
button.selected { border-color: #1d4ed8; background: #dbeafe; color: #1e3a8a; }
|
||||
.badge { display: inline-block; border-radius: 999px; padding: 2px 7px; font-size: 11px; font-weight: 700; }
|
||||
.ok { color: #065f46; background: #d1fae5; }
|
||||
.warn { color: #92400e; background: #fef3c7; }
|
||||
.bad { color: #991b1b; background: #fee2e2; }
|
||||
.review-panel, .review-handoff { background: #fff; border: 1px solid #dfe5ee; border-radius: 8px; padding: 14px; margin: 16px 0; }
|
||||
.decision-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
|
||||
.review-current { font-size: 12px; color: #536071; margin-bottom: 8px; }
|
||||
.notes-label { display: block; color: #536071; font-size: 12px; }
|
||||
.notes-label input { margin-left: 8px; min-width: min(520px, 80vw); padding: 6px 8px; border: 1px solid #c7d0df; border-radius: 6px; }
|
||||
.decision-template { margin-top: 10px; }
|
||||
pre, textarea { width: 100%; box-sizing: border-box; border: 1px solid #c7d0df; border-radius: 6px; background: #f8fafc; color: #172033; }
|
||||
pre { overflow: auto; padding: 10px; font-size: 12px; }
|
||||
textarea { min-height: 180px; padding: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<p><a href="../index.html">Back to gallery</a></p>
|
||||
<h1>playful</h1>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt.</div>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt and does not automatically modify production/default.</div>
|
||||
<div class="meta">
|
||||
<div class="metric"><strong>10</strong>source pages</div>
|
||||
<div class="metric"><strong>blocked</strong>auto gate</div>
|
||||
<div class="metric"><strong>missing</strong>smoke</div>
|
||||
<div class="metric"><strong>passed</strong>fidelity</div>
|
||||
</div>
|
||||
<div class="review-panel">
|
||||
<h2>Human decision</h2>
|
||||
<div class="review-control" data-review-control-for="playful"><div class="decision-buttons"><button type="button" data-family-id="playful" data-review-status="pass">pass</button><button type="button" data-family-id="playful" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="playful" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="playful">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="playful" placeholder="optional apply-script context" /></label><details class="decision-template"><summary>Copyable decision JSON fragment</summary><pre>{
|
||||
"family_id": "playful",
|
||||
"human_review_status_before_selection": "pending",
|
||||
"notes": "",
|
||||
"promotion_action": "no_change_until_human_pass",
|
||||
"review_status": "pass | needs_fix | reject",
|
||||
"runtime_template_id": "playful-indie-launch",
|
||||
"source_gallery_receipt_path": "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json"
|
||||
}</pre></details></div>
|
||||
</div>
|
||||
<p><strong>Known blockers:</strong> auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</p>
|
||||
</header>
|
||||
<section class="review-handoff">
|
||||
<h2>Human Review Export</h2>
|
||||
<div class="warning">This local UI does not automatically modify production/default. It only stores browser-local decisions and exports JSON for a separate apply script.</div>
|
||||
<p><code>human_review_status=pending</code> <code>promotion_action=no_change_until_human_pass</code></p>
|
||||
<p>Machine-readable gallery receipt: <code>skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json</code></p>
|
||||
<p>Apply script input: save this textarea as decisions JSON, then pass it to the apply script, for example <code>python <apply-script> --gallery-receipt skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json --decisions <exported-decisions.json></code>.</p>
|
||||
<textarea id="review-decisions-json" readonly spellcheck="false"></textarea>
|
||||
</section>
|
||||
|
||||
<main class="deck">
|
||||
<section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/playful-1.png" alt="cover" /></div><h2>1. cover</h2><p>cover / cover</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-1</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/playful-1.png" alt="agenda" /></div><h2>2. agenda</h2><p>agenda / agenda</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-2</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/playful-1.png" alt="data_dashboard" /></div><h2>3. data_dashboard</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-3</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/playful-1.png" alt="data_dashboard-4" /></div><h2>4. data_dashboard-4</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-4</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/playful-1.png" alt="detail" /></div><h2>5. detail</h2><p>detail / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-5</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/playful-6.png" alt="data_dashboard-6" /></div><h2>6. data_dashboard-6</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-6</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/playful-1.png" alt="process_or_timeline" /></div><h2>7. process_or_timeline</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-7</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/playful-8.png" alt="data_dashboard-8" /></div><h2>8. data_dashboard-8</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-8</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/playful-1.png" alt="slide-9" /></div><h2>9. slide-9</h2><p>content / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-9</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/playful-1.png" alt="closing" /></div><h2>10. closing</h2><p>closing / closing</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-10</code></p></section>
|
||||
</main>
|
||||
<script>
|
||||
(function () {
|
||||
var storageKey = "beautiful-production-review-decisions-v1";
|
||||
var schemaVersion = "svglide-beautiful-human-review-decisions/v1";
|
||||
var reviewBatchId = "beautiful-34";
|
||||
var receiptPath = "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json";
|
||||
var pendingHumanReviewStatus = "pending";
|
||||
var promotionAction = "no_change_until_human_pass";
|
||||
|
||||
function readState() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
||||
if (parsed && typeof parsed === "object" && parsed.decisions && typeof parsed.decisions === "object") {
|
||||
return parsed;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore malformed local state and rebuild below.
|
||||
}
|
||||
return { decisions: {} };
|
||||
}
|
||||
|
||||
function writeState(state) {
|
||||
localStorage.setItem(storageKey, JSON.stringify(state));
|
||||
}
|
||||
|
||||
function buildExport(state) {
|
||||
var decisions = Object.keys(state.decisions || {}).sort().map(function (familyId) {
|
||||
return state.decisions[familyId];
|
||||
});
|
||||
return {
|
||||
schema_version: schemaVersion,
|
||||
artifact_kind: "beautiful_template_human_review_decisions",
|
||||
review_batch_id: reviewBatchId,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
not_promotion_receipt: true,
|
||||
policy: {
|
||||
does_not_automatically_modify_production_default: true,
|
||||
apply_script_must_validate_gallery_receipt: true
|
||||
},
|
||||
decisions: decisions
|
||||
};
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.querySelectorAll("[data-review-current-for]").forEach(function (node) {
|
||||
var familyId = node.getAttribute("data-review-current-for");
|
||||
var decision = state.decisions[familyId];
|
||||
node.textContent = decision ? decision.review_status : "pending";
|
||||
});
|
||||
document.querySelectorAll("[data-review-status]").forEach(function (button) {
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var decision = state.decisions[familyId];
|
||||
button.classList.toggle("selected", Boolean(decision && decision.review_status === status));
|
||||
});
|
||||
document.querySelectorAll("[data-review-notes-for]").forEach(function (input) {
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var decision = state.decisions[familyId];
|
||||
if (decision && input.value !== decision.notes) {
|
||||
input.value = decision.notes || "";
|
||||
}
|
||||
});
|
||||
var textarea = document.getElementById("review-decisions-json");
|
||||
if (textarea) {
|
||||
textarea.value = JSON.stringify(buildExport(state), null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
var button = event.target.closest("[data-review-status]");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var existing = state.decisions[familyId] || {};
|
||||
state.decisions[familyId] = {
|
||||
family_id: familyId,
|
||||
review_status: status,
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
notes: existing.notes || "",
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
document.addEventListener("input", function (event) {
|
||||
var input = event.target.closest("[data-review-notes-for]");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var existing = state.decisions[familyId] || {
|
||||
family_id: familyId,
|
||||
review_status: "needs_fix",
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
existing.notes = input.value;
|
||||
existing.updated_at = new Date().toISOString();
|
||||
state.decisions[familyId] = existing;
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
render(readState());
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/playful.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "8c06c02b5802f957b497d1332e8cb0ab3d3a2c1825f551c946d00c38244aadad"
|
||||
"sha256": "dce30937bc181379275aeb74ef278b312b7cbceea99f2e2522aaefe6d6f16878"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "8c06c02b5802f957b497d1332e8cb0ab3d3a2c1825f551c946d00c38244aadad",
|
||||
"contact_sheet": "dce30937bc181379275aeb74ef278b312b7cbceea99f2e2522aaefe6d6f16878",
|
||||
"fidelity_receipt": "e828f367dda5704dca8c804fb833051e8e3888202e9b76169082ac50164873d8",
|
||||
"reference_screenshot": "75c22cf0736c2c349599de769e984af4e55440dbf83fb4abac35e5c0842abe81",
|
||||
"smoke_receipt": null,
|
||||
|
||||
@@ -19,27 +19,175 @@
|
||||
h2 { margin: 10px 0 4px; font-size: 15px; }
|
||||
p { margin: 5px 0; font-size: 12px; color: #536071; }
|
||||
code { word-break: break-all; font-size: 11px; }
|
||||
button { cursor: pointer; border: 1px solid #b8c2d2; background: #fff; color: #172033; border-radius: 6px; padding: 6px 9px; font-weight: 700; }
|
||||
button.selected { border-color: #1d4ed8; background: #dbeafe; color: #1e3a8a; }
|
||||
.badge { display: inline-block; border-radius: 999px; padding: 2px 7px; font-size: 11px; font-weight: 700; }
|
||||
.ok { color: #065f46; background: #d1fae5; }
|
||||
.warn { color: #92400e; background: #fef3c7; }
|
||||
.bad { color: #991b1b; background: #fee2e2; }
|
||||
.review-panel, .review-handoff { background: #fff; border: 1px solid #dfe5ee; border-radius: 8px; padding: 14px; margin: 16px 0; }
|
||||
.decision-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
|
||||
.review-current { font-size: 12px; color: #536071; margin-bottom: 8px; }
|
||||
.notes-label { display: block; color: #536071; font-size: 12px; }
|
||||
.notes-label input { margin-left: 8px; min-width: min(520px, 80vw); padding: 6px 8px; border: 1px solid #c7d0df; border-radius: 6px; }
|
||||
.decision-template { margin-top: 10px; }
|
||||
pre, textarea { width: 100%; box-sizing: border-box; border: 1px solid #c7d0df; border-radius: 6px; background: #f8fafc; color: #172033; }
|
||||
pre { overflow: auto; padding: 10px; font-size: 12px; }
|
||||
textarea { min-height: 180px; padding: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<p><a href="../index.html">Back to gallery</a></p>
|
||||
<h1>raw-grid</h1>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt.</div>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt and does not automatically modify production/default.</div>
|
||||
<div class="meta">
|
||||
<div class="metric"><strong>10</strong>source pages</div>
|
||||
<div class="metric"><strong>blocked</strong>auto gate</div>
|
||||
<div class="metric"><strong>missing</strong>smoke</div>
|
||||
<div class="metric"><strong>passed</strong>fidelity</div>
|
||||
</div>
|
||||
<div class="review-panel">
|
||||
<h2>Human decision</h2>
|
||||
<div class="review-control" data-review-control-for="raw-grid"><div class="decision-buttons"><button type="button" data-family-id="raw-grid" data-review-status="pass">pass</button><button type="button" data-family-id="raw-grid" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="raw-grid" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="raw-grid">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="raw-grid" placeholder="optional apply-script context" /></label><details class="decision-template"><summary>Copyable decision JSON fragment</summary><pre>{
|
||||
"family_id": "raw-grid",
|
||||
"human_review_status_before_selection": "pending",
|
||||
"notes": "",
|
||||
"promotion_action": "no_change_until_human_pass",
|
||||
"review_status": "pass | needs_fix | reject",
|
||||
"runtime_template_id": "brutalist-matrix",
|
||||
"source_gallery_receipt_path": "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json"
|
||||
}</pre></details></div>
|
||||
</div>
|
||||
<p><strong>Known blockers:</strong> auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</p>
|
||||
</header>
|
||||
<section class="review-handoff">
|
||||
<h2>Human Review Export</h2>
|
||||
<div class="warning">This local UI does not automatically modify production/default. It only stores browser-local decisions and exports JSON for a separate apply script.</div>
|
||||
<p><code>human_review_status=pending</code> <code>promotion_action=no_change_until_human_pass</code></p>
|
||||
<p>Machine-readable gallery receipt: <code>skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json</code></p>
|
||||
<p>Apply script input: save this textarea as decisions JSON, then pass it to the apply script, for example <code>python <apply-script> --gallery-receipt skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json --decisions <exported-decisions.json></code>.</p>
|
||||
<textarea id="review-decisions-json" readonly spellcheck="false"></textarea>
|
||||
</section>
|
||||
|
||||
<main class="deck">
|
||||
<section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/raw-grid-1.png" alt="s1" /></div><h2>1. s1</h2><p>cover / cover</p><p><span class="badge bad">missing_smoke</span></p><p><code>s1</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/raw-grid-1.png" alt="s2" /></div><h2>2. s2</h2><p>agenda / agenda</p><p><span class="badge bad">missing_smoke</span></p><p><code>s2</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/raw-grid-1.png" alt="s3" /></div><h2>3. s3</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s3</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/raw-grid-4.png" alt="s4" /></div><h2>4. s4</h2><p>content / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>s4</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/raw-grid-1.png" alt="s5" /></div><h2>5. s5</h2><p>content / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>s5</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/raw-grid-1.png" alt="s6" /></div><h2>6. s6</h2><p>detail / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>s6</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/raw-grid-1.png" alt="s7" /></div><h2>7. s7</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s7</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/raw-grid-8.png" alt="s8" /></div><h2>8. s8</h2><p>quote_or_emphasis / quote_or_emphasis</p><p><span class="badge bad">missing_smoke</span></p><p><code>s8</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/raw-grid-1.png" alt="s9" /></div><h2>9. s9</h2><p>content / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>s9</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/raw-grid-1.png" alt="s10" /></div><h2>10. s10</h2><p>closing / closing</p><p><span class="badge bad">missing_smoke</span></p><p><code>s10</code></p></section>
|
||||
</main>
|
||||
<script>
|
||||
(function () {
|
||||
var storageKey = "beautiful-production-review-decisions-v1";
|
||||
var schemaVersion = "svglide-beautiful-human-review-decisions/v1";
|
||||
var reviewBatchId = "beautiful-34";
|
||||
var receiptPath = "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json";
|
||||
var pendingHumanReviewStatus = "pending";
|
||||
var promotionAction = "no_change_until_human_pass";
|
||||
|
||||
function readState() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
||||
if (parsed && typeof parsed === "object" && parsed.decisions && typeof parsed.decisions === "object") {
|
||||
return parsed;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore malformed local state and rebuild below.
|
||||
}
|
||||
return { decisions: {} };
|
||||
}
|
||||
|
||||
function writeState(state) {
|
||||
localStorage.setItem(storageKey, JSON.stringify(state));
|
||||
}
|
||||
|
||||
function buildExport(state) {
|
||||
var decisions = Object.keys(state.decisions || {}).sort().map(function (familyId) {
|
||||
return state.decisions[familyId];
|
||||
});
|
||||
return {
|
||||
schema_version: schemaVersion,
|
||||
artifact_kind: "beautiful_template_human_review_decisions",
|
||||
review_batch_id: reviewBatchId,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
not_promotion_receipt: true,
|
||||
policy: {
|
||||
does_not_automatically_modify_production_default: true,
|
||||
apply_script_must_validate_gallery_receipt: true
|
||||
},
|
||||
decisions: decisions
|
||||
};
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.querySelectorAll("[data-review-current-for]").forEach(function (node) {
|
||||
var familyId = node.getAttribute("data-review-current-for");
|
||||
var decision = state.decisions[familyId];
|
||||
node.textContent = decision ? decision.review_status : "pending";
|
||||
});
|
||||
document.querySelectorAll("[data-review-status]").forEach(function (button) {
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var decision = state.decisions[familyId];
|
||||
button.classList.toggle("selected", Boolean(decision && decision.review_status === status));
|
||||
});
|
||||
document.querySelectorAll("[data-review-notes-for]").forEach(function (input) {
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var decision = state.decisions[familyId];
|
||||
if (decision && input.value !== decision.notes) {
|
||||
input.value = decision.notes || "";
|
||||
}
|
||||
});
|
||||
var textarea = document.getElementById("review-decisions-json");
|
||||
if (textarea) {
|
||||
textarea.value = JSON.stringify(buildExport(state), null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
var button = event.target.closest("[data-review-status]");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var existing = state.decisions[familyId] || {};
|
||||
state.decisions[familyId] = {
|
||||
family_id: familyId,
|
||||
review_status: status,
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
notes: existing.notes || "",
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
document.addEventListener("input", function (event) {
|
||||
var input = event.target.closest("[data-review-notes-for]");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var existing = state.decisions[familyId] || {
|
||||
family_id: familyId,
|
||||
review_status: "needs_fix",
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
existing.notes = input.value;
|
||||
existing.updated_at = new Date().toISOString();
|
||||
state.decisions[familyId] = existing;
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
render(readState());
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/raw-grid.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "87221867c254043e20ca653260daa52ccb0f88492fe1fc5595db51edb2d5c87a"
|
||||
"sha256": "0fc408b566d5f90530b8afb2e380258a3d6013f7ed2089e4b53921eb49d97c57"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "87221867c254043e20ca653260daa52ccb0f88492fe1fc5595db51edb2d5c87a",
|
||||
"contact_sheet": "0fc408b566d5f90530b8afb2e380258a3d6013f7ed2089e4b53921eb49d97c57",
|
||||
"fidelity_receipt": "fee9ac2b5c6d69612a2a082849f1829f5b3c75f2a5c2d29b76657361f4fc04cc",
|
||||
"reference_screenshot": "4056c85b9415ba7a9a988d45f5316cbdfbaf18ee959e3f7727e2ef90f59f42bc",
|
||||
"smoke_receipt": null,
|
||||
|
||||
@@ -19,27 +19,175 @@
|
||||
h2 { margin: 10px 0 4px; font-size: 15px; }
|
||||
p { margin: 5px 0; font-size: 12px; color: #536071; }
|
||||
code { word-break: break-all; font-size: 11px; }
|
||||
button { cursor: pointer; border: 1px solid #b8c2d2; background: #fff; color: #172033; border-radius: 6px; padding: 6px 9px; font-weight: 700; }
|
||||
button.selected { border-color: #1d4ed8; background: #dbeafe; color: #1e3a8a; }
|
||||
.badge { display: inline-block; border-radius: 999px; padding: 2px 7px; font-size: 11px; font-weight: 700; }
|
||||
.ok { color: #065f46; background: #d1fae5; }
|
||||
.warn { color: #92400e; background: #fef3c7; }
|
||||
.bad { color: #991b1b; background: #fee2e2; }
|
||||
.review-panel, .review-handoff { background: #fff; border: 1px solid #dfe5ee; border-radius: 8px; padding: 14px; margin: 16px 0; }
|
||||
.decision-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
|
||||
.review-current { font-size: 12px; color: #536071; margin-bottom: 8px; }
|
||||
.notes-label { display: block; color: #536071; font-size: 12px; }
|
||||
.notes-label input { margin-left: 8px; min-width: min(520px, 80vw); padding: 6px 8px; border: 1px solid #c7d0df; border-radius: 6px; }
|
||||
.decision-template { margin-top: 10px; }
|
||||
pre, textarea { width: 100%; box-sizing: border-box; border: 1px solid #c7d0df; border-radius: 6px; background: #f8fafc; color: #172033; }
|
||||
pre { overflow: auto; padding: 10px; font-size: 12px; }
|
||||
textarea { min-height: 180px; padding: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<p><a href="../index.html">Back to gallery</a></p>
|
||||
<h1>retro-windows</h1>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt.</div>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt and does not automatically modify production/default.</div>
|
||||
<div class="meta">
|
||||
<div class="metric"><strong>10</strong>source pages</div>
|
||||
<div class="metric"><strong>blocked</strong>auto gate</div>
|
||||
<div class="metric"><strong>missing</strong>smoke</div>
|
||||
<div class="metric"><strong>passed</strong>fidelity</div>
|
||||
</div>
|
||||
<div class="review-panel">
|
||||
<h2>Human decision</h2>
|
||||
<div class="review-control" data-review-control-for="retro-windows"><div class="decision-buttons"><button type="button" data-family-id="retro-windows" data-review-status="pass">pass</button><button type="button" data-family-id="retro-windows" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="retro-windows" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="retro-windows">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="retro-windows" placeholder="optional apply-script context" /></label><details class="decision-template"><summary>Copyable decision JSON fragment</summary><pre>{
|
||||
"family_id": "retro-windows",
|
||||
"human_review_status_before_selection": "pending",
|
||||
"notes": "",
|
||||
"promotion_action": "no_change_until_human_pass",
|
||||
"review_status": "pass | needs_fix | reject",
|
||||
"runtime_template_id": "retro-ui-dashboard",
|
||||
"source_gallery_receipt_path": "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json"
|
||||
}</pre></details></div>
|
||||
</div>
|
||||
<p><strong>Known blockers:</strong> auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</p>
|
||||
</header>
|
||||
<section class="review-handoff">
|
||||
<h2>Human Review Export</h2>
|
||||
<div class="warning">This local UI does not automatically modify production/default. It only stores browser-local decisions and exports JSON for a separate apply script.</div>
|
||||
<p><code>human_review_status=pending</code> <code>promotion_action=no_change_until_human_pass</code></p>
|
||||
<p>Machine-readable gallery receipt: <code>skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json</code></p>
|
||||
<p>Apply script input: save this textarea as decisions JSON, then pass it to the apply script, for example <code>python <apply-script> --gallery-receipt skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json --decisions <exported-decisions.json></code>.</p>
|
||||
<textarea id="review-decisions-json" readonly spellcheck="false"></textarea>
|
||||
</section>
|
||||
|
||||
<main class="deck">
|
||||
<section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/retro-windows-1.png" alt="slide-1" /></div><h2>1. slide-1</h2><p>cover / cover</p><p><span class="badge bad">missing_smoke</span></p><p><code>data-slide-1</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/retro-windows-1.png" alt="slide-2" /></div><h2>2. slide-2</h2><p>agenda / agenda</p><p><span class="badge bad">missing_smoke</span></p><p><code>data-slide-2</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/retro-windows-1.png" alt="slide-3" /></div><h2>3. slide-3</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>data-slide-3</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/retro-windows-4.png" alt="slide-4" /></div><h2>4. slide-4</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>data-slide-4</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/retro-windows-1.png" alt="slide-5" /></div><h2>5. slide-5</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>data-slide-5</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/retro-windows-1.png" alt="slide-6" /></div><h2>6. slide-6</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>data-slide-6</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/retro-windows-1.png" alt="slide-7" /></div><h2>7. slide-7</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>data-slide-7</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/retro-windows-8.png" alt="slide-8" /></div><h2>8. slide-8</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>data-slide-8</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/retro-windows-1.png" alt="slide-9" /></div><h2>9. slide-9</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge bad">missing_smoke</span></p><p><code>data-slide-9</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/retro-windows-1.png" alt="slide-10" /></div><h2>10. slide-10</h2><p>closing / closing</p><p><span class="badge bad">missing_smoke</span></p><p><code>data-slide-10</code></p></section>
|
||||
</main>
|
||||
<script>
|
||||
(function () {
|
||||
var storageKey = "beautiful-production-review-decisions-v1";
|
||||
var schemaVersion = "svglide-beautiful-human-review-decisions/v1";
|
||||
var reviewBatchId = "beautiful-34";
|
||||
var receiptPath = "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json";
|
||||
var pendingHumanReviewStatus = "pending";
|
||||
var promotionAction = "no_change_until_human_pass";
|
||||
|
||||
function readState() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
||||
if (parsed && typeof parsed === "object" && parsed.decisions && typeof parsed.decisions === "object") {
|
||||
return parsed;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore malformed local state and rebuild below.
|
||||
}
|
||||
return { decisions: {} };
|
||||
}
|
||||
|
||||
function writeState(state) {
|
||||
localStorage.setItem(storageKey, JSON.stringify(state));
|
||||
}
|
||||
|
||||
function buildExport(state) {
|
||||
var decisions = Object.keys(state.decisions || {}).sort().map(function (familyId) {
|
||||
return state.decisions[familyId];
|
||||
});
|
||||
return {
|
||||
schema_version: schemaVersion,
|
||||
artifact_kind: "beautiful_template_human_review_decisions",
|
||||
review_batch_id: reviewBatchId,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
not_promotion_receipt: true,
|
||||
policy: {
|
||||
does_not_automatically_modify_production_default: true,
|
||||
apply_script_must_validate_gallery_receipt: true
|
||||
},
|
||||
decisions: decisions
|
||||
};
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.querySelectorAll("[data-review-current-for]").forEach(function (node) {
|
||||
var familyId = node.getAttribute("data-review-current-for");
|
||||
var decision = state.decisions[familyId];
|
||||
node.textContent = decision ? decision.review_status : "pending";
|
||||
});
|
||||
document.querySelectorAll("[data-review-status]").forEach(function (button) {
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var decision = state.decisions[familyId];
|
||||
button.classList.toggle("selected", Boolean(decision && decision.review_status === status));
|
||||
});
|
||||
document.querySelectorAll("[data-review-notes-for]").forEach(function (input) {
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var decision = state.decisions[familyId];
|
||||
if (decision && input.value !== decision.notes) {
|
||||
input.value = decision.notes || "";
|
||||
}
|
||||
});
|
||||
var textarea = document.getElementById("review-decisions-json");
|
||||
if (textarea) {
|
||||
textarea.value = JSON.stringify(buildExport(state), null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
var button = event.target.closest("[data-review-status]");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var existing = state.decisions[familyId] || {};
|
||||
state.decisions[familyId] = {
|
||||
family_id: familyId,
|
||||
review_status: status,
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
notes: existing.notes || "",
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
document.addEventListener("input", function (event) {
|
||||
var input = event.target.closest("[data-review-notes-for]");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var existing = state.decisions[familyId] || {
|
||||
family_id: familyId,
|
||||
review_status: "needs_fix",
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
existing.notes = input.value;
|
||||
existing.updated_at = new Date().toISOString();
|
||||
state.decisions[familyId] = existing;
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
render(readState());
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/retro-windows.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "847e69a200f8f595339c4816826ed87853faf0a4fc468a6b0672f6f2946cf8a3"
|
||||
"sha256": "599e3dad5711c9a858067f8ce03036d104d9b8a01cc12c9eef04e7efd5550437"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "847e69a200f8f595339c4816826ed87853faf0a4fc468a6b0672f6f2946cf8a3",
|
||||
"contact_sheet": "599e3dad5711c9a858067f8ce03036d104d9b8a01cc12c9eef04e7efd5550437",
|
||||
"fidelity_receipt": "d9f718418fe0cba65d03c26230b5655764011c1197b9b52cb3ab15b0787cd8b6",
|
||||
"reference_screenshot": "8d9fc0a05ab025310cc35f15c2d3b2de629c79a49df9fe1c7d63b2f7b8a00543",
|
||||
"smoke_receipt": null,
|
||||
|
||||
@@ -19,27 +19,175 @@
|
||||
h2 { margin: 10px 0 4px; font-size: 15px; }
|
||||
p { margin: 5px 0; font-size: 12px; color: #536071; }
|
||||
code { word-break: break-all; font-size: 11px; }
|
||||
button { cursor: pointer; border: 1px solid #b8c2d2; background: #fff; color: #172033; border-radius: 6px; padding: 6px 9px; font-weight: 700; }
|
||||
button.selected { border-color: #1d4ed8; background: #dbeafe; color: #1e3a8a; }
|
||||
.badge { display: inline-block; border-radius: 999px; padding: 2px 7px; font-size: 11px; font-weight: 700; }
|
||||
.ok { color: #065f46; background: #d1fae5; }
|
||||
.warn { color: #92400e; background: #fef3c7; }
|
||||
.bad { color: #991b1b; background: #fee2e2; }
|
||||
.review-panel, .review-handoff { background: #fff; border: 1px solid #dfe5ee; border-radius: 8px; padding: 14px; margin: 16px 0; }
|
||||
.decision-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
|
||||
.review-current { font-size: 12px; color: #536071; margin-bottom: 8px; }
|
||||
.notes-label { display: block; color: #536071; font-size: 12px; }
|
||||
.notes-label input { margin-left: 8px; min-width: min(520px, 80vw); padding: 6px 8px; border: 1px solid #c7d0df; border-radius: 6px; }
|
||||
.decision-template { margin-top: 10px; }
|
||||
pre, textarea { width: 100%; box-sizing: border-box; border: 1px solid #c7d0df; border-radius: 6px; background: #f8fafc; color: #172033; }
|
||||
pre { overflow: auto; padding: 10px; font-size: 12px; }
|
||||
textarea { min-height: 180px; padding: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<p><a href="../index.html">Back to gallery</a></p>
|
||||
<h1>retro-zine</h1>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt.</div>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt and does not automatically modify production/default.</div>
|
||||
<div class="meta">
|
||||
<div class="metric"><strong>10</strong>source pages</div>
|
||||
<div class="metric"><strong>blocked</strong>auto gate</div>
|
||||
<div class="metric"><strong>missing</strong>smoke</div>
|
||||
<div class="metric"><strong>passed</strong>fidelity</div>
|
||||
</div>
|
||||
<div class="review-panel">
|
||||
<h2>Human decision</h2>
|
||||
<div class="review-control" data-review-control-for="retro-zine"><div class="decision-buttons"><button type="button" data-family-id="retro-zine" data-review-status="pass">pass</button><button type="button" data-family-id="retro-zine" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="retro-zine" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="retro-zine">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="retro-zine" placeholder="optional apply-script context" /></label><details class="decision-template"><summary>Copyable decision JSON fragment</summary><pre>{
|
||||
"family_id": "retro-zine",
|
||||
"human_review_status_before_selection": "pending",
|
||||
"notes": "",
|
||||
"promotion_action": "no_change_until_human_pass",
|
||||
"review_status": "pass | needs_fix | reject",
|
||||
"runtime_template_id": "retro-zine-spread",
|
||||
"source_gallery_receipt_path": "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json"
|
||||
}</pre></details></div>
|
||||
</div>
|
||||
<p><strong>Known blockers:</strong> auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</p>
|
||||
</header>
|
||||
<section class="review-handoff">
|
||||
<h2>Human Review Export</h2>
|
||||
<div class="warning">This local UI does not automatically modify production/default. It only stores browser-local decisions and exports JSON for a separate apply script.</div>
|
||||
<p><code>human_review_status=pending</code> <code>promotion_action=no_change_until_human_pass</code></p>
|
||||
<p>Machine-readable gallery receipt: <code>skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json</code></p>
|
||||
<p>Apply script input: save this textarea as decisions JSON, then pass it to the apply script, for example <code>python <apply-script> --gallery-receipt skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json --decisions <exported-decisions.json></code>.</p>
|
||||
<textarea id="review-decisions-json" readonly spellcheck="false"></textarea>
|
||||
</section>
|
||||
|
||||
<main class="deck">
|
||||
<section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/retro-zine-1.png" alt="hero" /></div><h2>1. hero</h2><p>cover / cover</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-hero</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/retro-zine-1.png" alt="split" /></div><h2>2. split</h2><p>content_split / comparison_or_split</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-split</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/retro-zine-1.png" alt="statement" /></div><h2>3. statement</h2><p>quote_or_emphasis / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-statement</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/retro-zine-4.png" alt="grid" /></div><h2>4. grid</h2><p>detail / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-grid</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/retro-zine-1.png" alt="visual" /></div><h2>5. visual</h2><p>content / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-visual</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/retro-zine-1.png" alt="editorial" /></div><h2>6. editorial</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-editorial</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/retro-zine-1.png" alt="numbers" /></div><h2>7. numbers</h2><p>content / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-numbers</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/retro-zine-8.png" alt="collage" /></div><h2>8. collage</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-collage</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/retro-zine-1.png" alt="rsvp" /></div><h2>9. rsvp</h2><p>closing / closing</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-rsvp</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/retro-zine-1.png" alt="closing" /></div><h2>10. closing</h2><p>closing / closing</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide-closing</code></p></section>
|
||||
</main>
|
||||
<script>
|
||||
(function () {
|
||||
var storageKey = "beautiful-production-review-decisions-v1";
|
||||
var schemaVersion = "svglide-beautiful-human-review-decisions/v1";
|
||||
var reviewBatchId = "beautiful-34";
|
||||
var receiptPath = "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json";
|
||||
var pendingHumanReviewStatus = "pending";
|
||||
var promotionAction = "no_change_until_human_pass";
|
||||
|
||||
function readState() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
||||
if (parsed && typeof parsed === "object" && parsed.decisions && typeof parsed.decisions === "object") {
|
||||
return parsed;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore malformed local state and rebuild below.
|
||||
}
|
||||
return { decisions: {} };
|
||||
}
|
||||
|
||||
function writeState(state) {
|
||||
localStorage.setItem(storageKey, JSON.stringify(state));
|
||||
}
|
||||
|
||||
function buildExport(state) {
|
||||
var decisions = Object.keys(state.decisions || {}).sort().map(function (familyId) {
|
||||
return state.decisions[familyId];
|
||||
});
|
||||
return {
|
||||
schema_version: schemaVersion,
|
||||
artifact_kind: "beautiful_template_human_review_decisions",
|
||||
review_batch_id: reviewBatchId,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
not_promotion_receipt: true,
|
||||
policy: {
|
||||
does_not_automatically_modify_production_default: true,
|
||||
apply_script_must_validate_gallery_receipt: true
|
||||
},
|
||||
decisions: decisions
|
||||
};
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.querySelectorAll("[data-review-current-for]").forEach(function (node) {
|
||||
var familyId = node.getAttribute("data-review-current-for");
|
||||
var decision = state.decisions[familyId];
|
||||
node.textContent = decision ? decision.review_status : "pending";
|
||||
});
|
||||
document.querySelectorAll("[data-review-status]").forEach(function (button) {
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var decision = state.decisions[familyId];
|
||||
button.classList.toggle("selected", Boolean(decision && decision.review_status === status));
|
||||
});
|
||||
document.querySelectorAll("[data-review-notes-for]").forEach(function (input) {
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var decision = state.decisions[familyId];
|
||||
if (decision && input.value !== decision.notes) {
|
||||
input.value = decision.notes || "";
|
||||
}
|
||||
});
|
||||
var textarea = document.getElementById("review-decisions-json");
|
||||
if (textarea) {
|
||||
textarea.value = JSON.stringify(buildExport(state), null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
var button = event.target.closest("[data-review-status]");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var existing = state.decisions[familyId] || {};
|
||||
state.decisions[familyId] = {
|
||||
family_id: familyId,
|
||||
review_status: status,
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
notes: existing.notes || "",
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
document.addEventListener("input", function (event) {
|
||||
var input = event.target.closest("[data-review-notes-for]");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var existing = state.decisions[familyId] || {
|
||||
family_id: familyId,
|
||||
review_status: "needs_fix",
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
existing.notes = input.value;
|
||||
existing.updated_at = new Date().toISOString();
|
||||
state.decisions[familyId] = existing;
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
render(readState());
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/retro-zine.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "5328e4b636054dbd363032e7fdb7fea6f0b31eb39d87215ffb4badae2fe02a97"
|
||||
"sha256": "2461333873da620b3c97e88c9ad80c1814ed28433cbc211c781f4999b1a62833"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "5328e4b636054dbd363032e7fdb7fea6f0b31eb39d87215ffb4badae2fe02a97",
|
||||
"contact_sheet": "2461333873da620b3c97e88c9ad80c1814ed28433cbc211c781f4999b1a62833",
|
||||
"fidelity_receipt": "70330ed527a665653b1934d49e3ad5f14e2f4f866de429f38615ca98f18657ba",
|
||||
"reference_screenshot": "bd93d862d934f00253a36df8f03f4aef74f87fb1b0f870c777002b39ae7f2af9",
|
||||
"smoke_receipt": null,
|
||||
|
||||
@@ -19,27 +19,175 @@
|
||||
h2 { margin: 10px 0 4px; font-size: 15px; }
|
||||
p { margin: 5px 0; font-size: 12px; color: #536071; }
|
||||
code { word-break: break-all; font-size: 11px; }
|
||||
button { cursor: pointer; border: 1px solid #b8c2d2; background: #fff; color: #172033; border-radius: 6px; padding: 6px 9px; font-weight: 700; }
|
||||
button.selected { border-color: #1d4ed8; background: #dbeafe; color: #1e3a8a; }
|
||||
.badge { display: inline-block; border-radius: 999px; padding: 2px 7px; font-size: 11px; font-weight: 700; }
|
||||
.ok { color: #065f46; background: #d1fae5; }
|
||||
.warn { color: #92400e; background: #fef3c7; }
|
||||
.bad { color: #991b1b; background: #fee2e2; }
|
||||
.review-panel, .review-handoff { background: #fff; border: 1px solid #dfe5ee; border-radius: 8px; padding: 14px; margin: 16px 0; }
|
||||
.decision-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
|
||||
.review-current { font-size: 12px; color: #536071; margin-bottom: 8px; }
|
||||
.notes-label { display: block; color: #536071; font-size: 12px; }
|
||||
.notes-label input { margin-left: 8px; min-width: min(520px, 80vw); padding: 6px 8px; border: 1px solid #c7d0df; border-radius: 6px; }
|
||||
.decision-template { margin-top: 10px; }
|
||||
pre, textarea { width: 100%; box-sizing: border-box; border: 1px solid #c7d0df; border-radius: 6px; background: #f8fafc; color: #172033; }
|
||||
pre { overflow: auto; padding: 10px; font-size: 12px; }
|
||||
textarea { min-height: 180px; padding: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<p><a href="../index.html">Back to gallery</a></p>
|
||||
<h1>sakura-chroma</h1>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt.</div>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt and does not automatically modify production/default.</div>
|
||||
<div class="meta">
|
||||
<div class="metric"><strong>8</strong>source pages</div>
|
||||
<div class="metric"><strong>blocked</strong>auto gate</div>
|
||||
<div class="metric"><strong>missing</strong>smoke</div>
|
||||
<div class="metric"><strong>passed</strong>fidelity</div>
|
||||
</div>
|
||||
<div class="review-panel">
|
||||
<h2>Human decision</h2>
|
||||
<div class="review-control" data-review-control-for="sakura-chroma"><div class="decision-buttons"><button type="button" data-family-id="sakura-chroma" data-review-status="pass">pass</button><button type="button" data-family-id="sakura-chroma" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="sakura-chroma" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="sakura-chroma">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="sakura-chroma" placeholder="optional apply-script context" /></label><details class="decision-template"><summary>Copyable decision JSON fragment</summary><pre>{
|
||||
"family_id": "sakura-chroma",
|
||||
"human_review_status_before_selection": "pending",
|
||||
"notes": "",
|
||||
"promotion_action": "no_change_until_human_pass",
|
||||
"review_status": "pass | needs_fix | reject",
|
||||
"runtime_template_id": "product-ribbon",
|
||||
"source_gallery_receipt_path": "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json"
|
||||
}</pre></details></div>
|
||||
</div>
|
||||
<p><strong>Known blockers:</strong> auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</p>
|
||||
</header>
|
||||
<section class="review-handoff">
|
||||
<h2>Human Review Export</h2>
|
||||
<div class="warning">This local UI does not automatically modify production/default. It only stores browser-local decisions and exports JSON for a separate apply script.</div>
|
||||
<p><code>human_review_status=pending</code> <code>promotion_action=no_change_until_human_pass</code></p>
|
||||
<p>Machine-readable gallery receipt: <code>skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json</code></p>
|
||||
<p>Apply script input: save this textarea as decisions JSON, then pass it to the apply script, for example <code>python <apply-script> --gallery-receipt skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json --decisions <exported-decisions.json></code>.</p>
|
||||
<textarea id="review-decisions-json" readonly spellcheck="false"></textarea>
|
||||
</section>
|
||||
|
||||
<main class="deck">
|
||||
<section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/sakura-chroma-1.png" alt="cover" /></div><h2>1. cover</h2><p>cover / cover</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-cover</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/sakura-chroma-1.png" alt="manifesto" /></div><h2>2. manifesto</h2><p>agenda / agenda</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-manifesto</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/sakura-chroma-3.png" alt="catalogue" /></div><h2>3. catalogue</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-catalogue</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/sakura-chroma-4.png" alt="stripe" /></div><h2>4. stripe</h2><p>quote_or_emphasis / quote_or_emphasis</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-stripe</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/sakura-chroma-1.png" alt="data" /></div><h2>5. data</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-data</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/sakura-chroma-1.png" alt="quote" /></div><h2>6. quote</h2><p>quote_or_emphasis / quote_or_emphasis</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-quote</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/sakura-chroma-1.png" alt="cal" /></div><h2>7. cal</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-cal</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/sakura-chroma-1.png" alt="colophon" /></div><h2>8. colophon</h2><p>content / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-colophon</code></p></section>
|
||||
</main>
|
||||
<script>
|
||||
(function () {
|
||||
var storageKey = "beautiful-production-review-decisions-v1";
|
||||
var schemaVersion = "svglide-beautiful-human-review-decisions/v1";
|
||||
var reviewBatchId = "beautiful-34";
|
||||
var receiptPath = "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json";
|
||||
var pendingHumanReviewStatus = "pending";
|
||||
var promotionAction = "no_change_until_human_pass";
|
||||
|
||||
function readState() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
||||
if (parsed && typeof parsed === "object" && parsed.decisions && typeof parsed.decisions === "object") {
|
||||
return parsed;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore malformed local state and rebuild below.
|
||||
}
|
||||
return { decisions: {} };
|
||||
}
|
||||
|
||||
function writeState(state) {
|
||||
localStorage.setItem(storageKey, JSON.stringify(state));
|
||||
}
|
||||
|
||||
function buildExport(state) {
|
||||
var decisions = Object.keys(state.decisions || {}).sort().map(function (familyId) {
|
||||
return state.decisions[familyId];
|
||||
});
|
||||
return {
|
||||
schema_version: schemaVersion,
|
||||
artifact_kind: "beautiful_template_human_review_decisions",
|
||||
review_batch_id: reviewBatchId,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
not_promotion_receipt: true,
|
||||
policy: {
|
||||
does_not_automatically_modify_production_default: true,
|
||||
apply_script_must_validate_gallery_receipt: true
|
||||
},
|
||||
decisions: decisions
|
||||
};
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.querySelectorAll("[data-review-current-for]").forEach(function (node) {
|
||||
var familyId = node.getAttribute("data-review-current-for");
|
||||
var decision = state.decisions[familyId];
|
||||
node.textContent = decision ? decision.review_status : "pending";
|
||||
});
|
||||
document.querySelectorAll("[data-review-status]").forEach(function (button) {
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var decision = state.decisions[familyId];
|
||||
button.classList.toggle("selected", Boolean(decision && decision.review_status === status));
|
||||
});
|
||||
document.querySelectorAll("[data-review-notes-for]").forEach(function (input) {
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var decision = state.decisions[familyId];
|
||||
if (decision && input.value !== decision.notes) {
|
||||
input.value = decision.notes || "";
|
||||
}
|
||||
});
|
||||
var textarea = document.getElementById("review-decisions-json");
|
||||
if (textarea) {
|
||||
textarea.value = JSON.stringify(buildExport(state), null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
var button = event.target.closest("[data-review-status]");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var existing = state.decisions[familyId] || {};
|
||||
state.decisions[familyId] = {
|
||||
family_id: familyId,
|
||||
review_status: status,
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
notes: existing.notes || "",
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
document.addEventListener("input", function (event) {
|
||||
var input = event.target.closest("[data-review-notes-for]");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var existing = state.decisions[familyId] || {
|
||||
family_id: familyId,
|
||||
review_status: "needs_fix",
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
existing.notes = input.value;
|
||||
existing.updated_at = new Date().toISOString();
|
||||
state.decisions[familyId] = existing;
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
render(readState());
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/sakura-chroma.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "2f4e9111d34cafd0344975f49c5a1d13c3ab8732ac520107a9d0f060b0486108"
|
||||
"sha256": "fd7eb1ddf9e58fcdabc02eb17dd814491227a3ac00a735bfd8b4d7065c482bcf"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "2f4e9111d34cafd0344975f49c5a1d13c3ab8732ac520107a9d0f060b0486108",
|
||||
"contact_sheet": "fd7eb1ddf9e58fcdabc02eb17dd814491227a3ac00a735bfd8b4d7065c482bcf",
|
||||
"fidelity_receipt": "01ed753670341664ee282238d30060766dba929200e59bb279b31497ec8af736",
|
||||
"reference_screenshot": "92bae8fc25051d0dbbb648f931befbfb653cbc331e876ea5e5aaf76afbad0733",
|
||||
"smoke_receipt": null,
|
||||
|
||||
@@ -19,27 +19,175 @@
|
||||
h2 { margin: 10px 0 4px; font-size: 15px; }
|
||||
p { margin: 5px 0; font-size: 12px; color: #536071; }
|
||||
code { word-break: break-all; font-size: 11px; }
|
||||
button { cursor: pointer; border: 1px solid #b8c2d2; background: #fff; color: #172033; border-radius: 6px; padding: 6px 9px; font-weight: 700; }
|
||||
button.selected { border-color: #1d4ed8; background: #dbeafe; color: #1e3a8a; }
|
||||
.badge { display: inline-block; border-radius: 999px; padding: 2px 7px; font-size: 11px; font-weight: 700; }
|
||||
.ok { color: #065f46; background: #d1fae5; }
|
||||
.warn { color: #92400e; background: #fef3c7; }
|
||||
.bad { color: #991b1b; background: #fee2e2; }
|
||||
.review-panel, .review-handoff { background: #fff; border: 1px solid #dfe5ee; border-radius: 8px; padding: 14px; margin: 16px 0; }
|
||||
.decision-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
|
||||
.review-current { font-size: 12px; color: #536071; margin-bottom: 8px; }
|
||||
.notes-label { display: block; color: #536071; font-size: 12px; }
|
||||
.notes-label input { margin-left: 8px; min-width: min(520px, 80vw); padding: 6px 8px; border: 1px solid #c7d0df; border-radius: 6px; }
|
||||
.decision-template { margin-top: 10px; }
|
||||
pre, textarea { width: 100%; box-sizing: border-box; border: 1px solid #c7d0df; border-radius: 6px; background: #f8fafc; color: #172033; }
|
||||
pre { overflow: auto; padding: 10px; font-size: 12px; }
|
||||
textarea { min-height: 180px; padding: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<p><a href="../index.html">Back to gallery</a></p>
|
||||
<h1>scatterbrain</h1>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt.</div>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt and does not automatically modify production/default.</div>
|
||||
<div class="meta">
|
||||
<div class="metric"><strong>8</strong>source pages</div>
|
||||
<div class="metric"><strong>blocked</strong>auto gate</div>
|
||||
<div class="metric"><strong>missing</strong>smoke</div>
|
||||
<div class="metric"><strong>passed</strong>fidelity</div>
|
||||
</div>
|
||||
<div class="review-panel">
|
||||
<h2>Human decision</h2>
|
||||
<div class="review-control" data-review-control-for="scatterbrain"><div class="decision-buttons"><button type="button" data-family-id="scatterbrain" data-review-status="pass">pass</button><button type="button" data-family-id="scatterbrain" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="scatterbrain" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="scatterbrain">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="scatterbrain" placeholder="optional apply-script context" /></label><details class="decision-template"><summary>Copyable decision JSON fragment</summary><pre>{
|
||||
"family_id": "scatterbrain",
|
||||
"human_review_status_before_selection": "pending",
|
||||
"notes": "",
|
||||
"promotion_action": "no_change_until_human_pass",
|
||||
"review_status": "pass | needs_fix | reject",
|
||||
"runtime_template_id": "sticky-workshop-board",
|
||||
"source_gallery_receipt_path": "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json"
|
||||
}</pre></details></div>
|
||||
</div>
|
||||
<p><strong>Known blockers:</strong> auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</p>
|
||||
</header>
|
||||
<section class="review-handoff">
|
||||
<h2>Human Review Export</h2>
|
||||
<div class="warning">This local UI does not automatically modify production/default. It only stores browser-local decisions and exports JSON for a separate apply script.</div>
|
||||
<p><code>human_review_status=pending</code> <code>promotion_action=no_change_until_human_pass</code></p>
|
||||
<p>Machine-readable gallery receipt: <code>skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json</code></p>
|
||||
<p>Apply script input: save this textarea as decisions JSON, then pass it to the apply script, for example <code>python <apply-script> --gallery-receipt skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json --decisions <exported-decisions.json></code>.</p>
|
||||
<textarea id="review-decisions-json" readonly spellcheck="false"></textarea>
|
||||
</section>
|
||||
|
||||
<main class="deck">
|
||||
<section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/scatterbrain-1.png" alt="slide-1" /></div><h2>1. slide-1</h2><p>cover / cover</p><p><span class="badge bad">missing_smoke</span></p><p><code>data-slide-1</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/scatterbrain-1.png" alt="slide-2" /></div><h2>2. slide-2</h2><p>agenda / agenda</p><p><span class="badge bad">missing_smoke</span></p><p><code>data-slide-2</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/scatterbrain-1.png" alt="slide-3" /></div><h2>3. slide-3</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>data-slide-3</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/scatterbrain-4.png" alt="slide-4" /></div><h2>4. slide-4</h2><p>detail / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>data-slide-4</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/scatterbrain-1.png" alt="slide-5" /></div><h2>5. slide-5</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge bad">missing_smoke</span></p><p><code>data-slide-5</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/scatterbrain-1.png" alt="slide-6" /></div><h2>6. slide-6</h2><p>content / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>data-slide-6</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/scatterbrain-1.png" alt="slide-7" /></div><h2>7. slide-7</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>data-slide-7</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/scatterbrain-8.png" alt="slide-8" /></div><h2>8. slide-8</h2><p>closing / closing</p><p><span class="badge bad">missing_smoke</span></p><p><code>data-slide-8</code></p></section>
|
||||
</main>
|
||||
<script>
|
||||
(function () {
|
||||
var storageKey = "beautiful-production-review-decisions-v1";
|
||||
var schemaVersion = "svglide-beautiful-human-review-decisions/v1";
|
||||
var reviewBatchId = "beautiful-34";
|
||||
var receiptPath = "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json";
|
||||
var pendingHumanReviewStatus = "pending";
|
||||
var promotionAction = "no_change_until_human_pass";
|
||||
|
||||
function readState() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
||||
if (parsed && typeof parsed === "object" && parsed.decisions && typeof parsed.decisions === "object") {
|
||||
return parsed;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore malformed local state and rebuild below.
|
||||
}
|
||||
return { decisions: {} };
|
||||
}
|
||||
|
||||
function writeState(state) {
|
||||
localStorage.setItem(storageKey, JSON.stringify(state));
|
||||
}
|
||||
|
||||
function buildExport(state) {
|
||||
var decisions = Object.keys(state.decisions || {}).sort().map(function (familyId) {
|
||||
return state.decisions[familyId];
|
||||
});
|
||||
return {
|
||||
schema_version: schemaVersion,
|
||||
artifact_kind: "beautiful_template_human_review_decisions",
|
||||
review_batch_id: reviewBatchId,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
not_promotion_receipt: true,
|
||||
policy: {
|
||||
does_not_automatically_modify_production_default: true,
|
||||
apply_script_must_validate_gallery_receipt: true
|
||||
},
|
||||
decisions: decisions
|
||||
};
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.querySelectorAll("[data-review-current-for]").forEach(function (node) {
|
||||
var familyId = node.getAttribute("data-review-current-for");
|
||||
var decision = state.decisions[familyId];
|
||||
node.textContent = decision ? decision.review_status : "pending";
|
||||
});
|
||||
document.querySelectorAll("[data-review-status]").forEach(function (button) {
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var decision = state.decisions[familyId];
|
||||
button.classList.toggle("selected", Boolean(decision && decision.review_status === status));
|
||||
});
|
||||
document.querySelectorAll("[data-review-notes-for]").forEach(function (input) {
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var decision = state.decisions[familyId];
|
||||
if (decision && input.value !== decision.notes) {
|
||||
input.value = decision.notes || "";
|
||||
}
|
||||
});
|
||||
var textarea = document.getElementById("review-decisions-json");
|
||||
if (textarea) {
|
||||
textarea.value = JSON.stringify(buildExport(state), null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
var button = event.target.closest("[data-review-status]");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var existing = state.decisions[familyId] || {};
|
||||
state.decisions[familyId] = {
|
||||
family_id: familyId,
|
||||
review_status: status,
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
notes: existing.notes || "",
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
document.addEventListener("input", function (event) {
|
||||
var input = event.target.closest("[data-review-notes-for]");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var existing = state.decisions[familyId] || {
|
||||
family_id: familyId,
|
||||
review_status: "needs_fix",
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
existing.notes = input.value;
|
||||
existing.updated_at = new Date().toISOString();
|
||||
state.decisions[familyId] = existing;
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
render(readState());
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/scatterbrain.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "4cf01462c6953780cc59a29d83f051278e5315763f9365240abc3138c204eca2"
|
||||
"sha256": "5a5157baf391062f4ed34e0bde225c820785e216e69b9e7af3d7c460ffdb0c80"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "4cf01462c6953780cc59a29d83f051278e5315763f9365240abc3138c204eca2",
|
||||
"contact_sheet": "5a5157baf391062f4ed34e0bde225c820785e216e69b9e7af3d7c460ffdb0c80",
|
||||
"fidelity_receipt": "8f986c32012e5a26fff7d1e4b2c73fb73db59885a7bb3f8ba7fc7f1f0cfd927f",
|
||||
"reference_screenshot": "c2ed8f8d89fd124c65976fa3ece9b153afe4f4542d95880c367922bb88d910ca",
|
||||
"smoke_receipt": null,
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -10,11 +10,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/signal.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "ab533fc6ac798c710cc537d93a18e247830e183fa813ce2a5ee08a582272c1e1"
|
||||
"sha256": "c00894a3fff05448914443bf4fec131fcd6ca87b0ed2aabce5a9f239f3e4082a"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "ab533fc6ac798c710cc537d93a18e247830e183fa813ce2a5ee08a582272c1e1",
|
||||
"contact_sheet": "c00894a3fff05448914443bf4fec131fcd6ca87b0ed2aabce5a9f239f3e4082a",
|
||||
"fidelity_receipt": "f33e1fed9d3fe80ed000386d4649be14d1120ea455b57d33b8d97a87d2769231",
|
||||
"reference_screenshot": "ca5487dc68264f209951400c5edddb93c4ae1fc7174b88c2b3dc54a82e0be64a",
|
||||
"smoke_receipt": null,
|
||||
|
||||
@@ -19,27 +19,175 @@
|
||||
h2 { margin: 10px 0 4px; font-size: 15px; }
|
||||
p { margin: 5px 0; font-size: 12px; color: #536071; }
|
||||
code { word-break: break-all; font-size: 11px; }
|
||||
button { cursor: pointer; border: 1px solid #b8c2d2; background: #fff; color: #172033; border-radius: 6px; padding: 6px 9px; font-weight: 700; }
|
||||
button.selected { border-color: #1d4ed8; background: #dbeafe; color: #1e3a8a; }
|
||||
.badge { display: inline-block; border-radius: 999px; padding: 2px 7px; font-size: 11px; font-weight: 700; }
|
||||
.ok { color: #065f46; background: #d1fae5; }
|
||||
.warn { color: #92400e; background: #fef3c7; }
|
||||
.bad { color: #991b1b; background: #fee2e2; }
|
||||
.review-panel, .review-handoff { background: #fff; border: 1px solid #dfe5ee; border-radius: 8px; padding: 14px; margin: 16px 0; }
|
||||
.decision-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
|
||||
.review-current { font-size: 12px; color: #536071; margin-bottom: 8px; }
|
||||
.notes-label { display: block; color: #536071; font-size: 12px; }
|
||||
.notes-label input { margin-left: 8px; min-width: min(520px, 80vw); padding: 6px 8px; border: 1px solid #c7d0df; border-radius: 6px; }
|
||||
.decision-template { margin-top: 10px; }
|
||||
pre, textarea { width: 100%; box-sizing: border-box; border: 1px solid #c7d0df; border-radius: 6px; background: #f8fafc; color: #172033; }
|
||||
pre { overflow: auto; padding: 10px; font-size: 12px; }
|
||||
textarea { min-height: 180px; padding: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<p><a href="../index.html">Back to gallery</a></p>
|
||||
<h1>soft-editorial</h1>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt.</div>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt and does not automatically modify production/default.</div>
|
||||
<div class="meta">
|
||||
<div class="metric"><strong>12</strong>source pages</div>
|
||||
<div class="metric"><strong>blocked</strong>auto gate</div>
|
||||
<div class="metric"><strong>missing</strong>smoke</div>
|
||||
<div class="metric"><strong>passed</strong>fidelity</div>
|
||||
</div>
|
||||
<div class="review-panel">
|
||||
<h2>Human decision</h2>
|
||||
<div class="review-control" data-review-control-for="soft-editorial"><div class="decision-buttons"><button type="button" data-family-id="soft-editorial" data-review-status="pass">pass</button><button type="button" data-family-id="soft-editorial" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="soft-editorial" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="soft-editorial">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="soft-editorial" placeholder="optional apply-script context" /></label><details class="decision-template"><summary>Copyable decision JSON fragment</summary><pre>{
|
||||
"family_id": "soft-editorial",
|
||||
"human_review_status_before_selection": "pending",
|
||||
"notes": "",
|
||||
"promotion_action": "no_change_until_human_pass",
|
||||
"review_status": "pass | needs_fix | reject",
|
||||
"runtime_template_id": "soft-editorial-feature",
|
||||
"source_gallery_receipt_path": "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json"
|
||||
}</pre></details></div>
|
||||
</div>
|
||||
<p><strong>Known blockers:</strong> auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</p>
|
||||
</header>
|
||||
<section class="review-handoff">
|
||||
<h2>Human Review Export</h2>
|
||||
<div class="warning">This local UI does not automatically modify production/default. It only stores browser-local decisions and exports JSON for a separate apply script.</div>
|
||||
<p><code>human_review_status=pending</code> <code>promotion_action=no_change_until_human_pass</code></p>
|
||||
<p>Machine-readable gallery receipt: <code>skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json</code></p>
|
||||
<p>Apply script input: save this textarea as decisions JSON, then pass it to the apply script, for example <code>python <apply-script> --gallery-receipt skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json --decisions <exported-decisions.json></code>.</p>
|
||||
<textarea id="review-decisions-json" readonly spellcheck="false"></textarea>
|
||||
</section>
|
||||
|
||||
<main class="deck">
|
||||
<section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/soft-editorial-4.png" alt="cover" /></div><h2>1. cover</h2><p>cover / cover</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-cover</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/soft-editorial-4.png" alt="foreword" /></div><h2>2. foreword</h2><p>agenda / agenda</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-foreword</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/soft-editorial-4.png" alt="method" /></div><h2>3. method</h2><p>detail / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-method</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/soft-editorial-4.png" alt="insights" /></div><h2>4. insights</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-insights</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/soft-editorial-4.png" alt="closer" /></div><h2>5. closer</h2><p>content / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-closer</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/soft-editorial-6.png" alt="numbers" /></div><h2>6. numbers</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-numbers</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/soft-editorial-4.png" alt="quote" /></div><h2>7. quote</h2><p>quote_or_emphasis / quote_or_emphasis</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-quote</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/soft-editorial-4.png" alt="next" /></div><h2>8. next</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-next</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/soft-editorial-4.png" alt="consult" /></div><h2>9. consult</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-consult</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/soft-editorial-10.png" alt="chart" /></div><h2>10. chart</h2><p>closing / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-chart</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/soft-editorial-4.png" alt="process" /></div><h2>11. process</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-process</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/soft-editorial-4.png" alt="matrix" /></div><h2>12. matrix</h2><p>content / comparison_or_split</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-matrix</code></p></section>
|
||||
</main>
|
||||
<script>
|
||||
(function () {
|
||||
var storageKey = "beautiful-production-review-decisions-v1";
|
||||
var schemaVersion = "svglide-beautiful-human-review-decisions/v1";
|
||||
var reviewBatchId = "beautiful-34";
|
||||
var receiptPath = "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json";
|
||||
var pendingHumanReviewStatus = "pending";
|
||||
var promotionAction = "no_change_until_human_pass";
|
||||
|
||||
function readState() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
||||
if (parsed && typeof parsed === "object" && parsed.decisions && typeof parsed.decisions === "object") {
|
||||
return parsed;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore malformed local state and rebuild below.
|
||||
}
|
||||
return { decisions: {} };
|
||||
}
|
||||
|
||||
function writeState(state) {
|
||||
localStorage.setItem(storageKey, JSON.stringify(state));
|
||||
}
|
||||
|
||||
function buildExport(state) {
|
||||
var decisions = Object.keys(state.decisions || {}).sort().map(function (familyId) {
|
||||
return state.decisions[familyId];
|
||||
});
|
||||
return {
|
||||
schema_version: schemaVersion,
|
||||
artifact_kind: "beautiful_template_human_review_decisions",
|
||||
review_batch_id: reviewBatchId,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
not_promotion_receipt: true,
|
||||
policy: {
|
||||
does_not_automatically_modify_production_default: true,
|
||||
apply_script_must_validate_gallery_receipt: true
|
||||
},
|
||||
decisions: decisions
|
||||
};
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.querySelectorAll("[data-review-current-for]").forEach(function (node) {
|
||||
var familyId = node.getAttribute("data-review-current-for");
|
||||
var decision = state.decisions[familyId];
|
||||
node.textContent = decision ? decision.review_status : "pending";
|
||||
});
|
||||
document.querySelectorAll("[data-review-status]").forEach(function (button) {
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var decision = state.decisions[familyId];
|
||||
button.classList.toggle("selected", Boolean(decision && decision.review_status === status));
|
||||
});
|
||||
document.querySelectorAll("[data-review-notes-for]").forEach(function (input) {
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var decision = state.decisions[familyId];
|
||||
if (decision && input.value !== decision.notes) {
|
||||
input.value = decision.notes || "";
|
||||
}
|
||||
});
|
||||
var textarea = document.getElementById("review-decisions-json");
|
||||
if (textarea) {
|
||||
textarea.value = JSON.stringify(buildExport(state), null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
var button = event.target.closest("[data-review-status]");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var existing = state.decisions[familyId] || {};
|
||||
state.decisions[familyId] = {
|
||||
family_id: familyId,
|
||||
review_status: status,
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
notes: existing.notes || "",
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
document.addEventListener("input", function (event) {
|
||||
var input = event.target.closest("[data-review-notes-for]");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var existing = state.decisions[familyId] || {
|
||||
family_id: familyId,
|
||||
review_status: "needs_fix",
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
existing.notes = input.value;
|
||||
existing.updated_at = new Date().toISOString();
|
||||
state.decisions[familyId] = existing;
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
render(readState());
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/soft-editorial.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "64eec701c1883f956200f4c07c18bb893e15272505132a612b554a942026bcee"
|
||||
"sha256": "f377bd08e444ba86e0ebb24b2b6fb6147a292402479d5854424ad483450e6aa3"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "64eec701c1883f956200f4c07c18bb893e15272505132a612b554a942026bcee",
|
||||
"contact_sheet": "f377bd08e444ba86e0ebb24b2b6fb6147a292402479d5854424ad483450e6aa3",
|
||||
"fidelity_receipt": "a7543b7f841153c3dd8d182b0c43d5d3688dc128b4da2f392cb41ee20d275ff3",
|
||||
"reference_screenshot": "3e37602cf749a0a383ef0f0a1f25db85e9633da1d74bafc2be76a91b004a866b",
|
||||
"smoke_receipt": null,
|
||||
|
||||
@@ -19,27 +19,175 @@
|
||||
h2 { margin: 10px 0 4px; font-size: 15px; }
|
||||
p { margin: 5px 0; font-size: 12px; color: #536071; }
|
||||
code { word-break: break-all; font-size: 11px; }
|
||||
button { cursor: pointer; border: 1px solid #b8c2d2; background: #fff; color: #172033; border-radius: 6px; padding: 6px 9px; font-weight: 700; }
|
||||
button.selected { border-color: #1d4ed8; background: #dbeafe; color: #1e3a8a; }
|
||||
.badge { display: inline-block; border-radius: 999px; padding: 2px 7px; font-size: 11px; font-weight: 700; }
|
||||
.ok { color: #065f46; background: #d1fae5; }
|
||||
.warn { color: #92400e; background: #fef3c7; }
|
||||
.bad { color: #991b1b; background: #fee2e2; }
|
||||
.review-panel, .review-handoff { background: #fff; border: 1px solid #dfe5ee; border-radius: 8px; padding: 14px; margin: 16px 0; }
|
||||
.decision-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
|
||||
.review-current { font-size: 12px; color: #536071; margin-bottom: 8px; }
|
||||
.notes-label { display: block; color: #536071; font-size: 12px; }
|
||||
.notes-label input { margin-left: 8px; min-width: min(520px, 80vw); padding: 6px 8px; border: 1px solid #c7d0df; border-radius: 6px; }
|
||||
.decision-template { margin-top: 10px; }
|
||||
pre, textarea { width: 100%; box-sizing: border-box; border: 1px solid #c7d0df; border-radius: 6px; background: #f8fafc; color: #172033; }
|
||||
pre { overflow: auto; padding: 10px; font-size: 12px; }
|
||||
textarea { min-height: 180px; padding: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<p><a href="../index.html">Back to gallery</a></p>
|
||||
<h1>stencil-tablet</h1>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt.</div>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt and does not automatically modify production/default.</div>
|
||||
<div class="meta">
|
||||
<div class="metric"><strong>11</strong>source pages</div>
|
||||
<div class="metric"><strong>blocked</strong>auto gate</div>
|
||||
<div class="metric"><strong>missing</strong>smoke</div>
|
||||
<div class="metric"><strong>passed</strong>fidelity</div>
|
||||
</div>
|
||||
<div class="review-panel">
|
||||
<h2>Human decision</h2>
|
||||
<div class="review-control" data-review-control-for="stencil-tablet"><div class="decision-buttons"><button type="button" data-family-id="stencil-tablet" data-review-status="pass">pass</button><button type="button" data-family-id="stencil-tablet" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="stencil-tablet" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="stencil-tablet">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="stencil-tablet" placeholder="optional apply-script context" /></label><details class="decision-template"><summary>Copyable decision JSON fragment</summary><pre>{
|
||||
"family_id": "stencil-tablet",
|
||||
"human_review_status_before_selection": "pending",
|
||||
"notes": "",
|
||||
"promotion_action": "no_change_until_human_pass",
|
||||
"review_status": "pass | needs_fix | reject",
|
||||
"runtime_template_id": "stencil-field-manual",
|
||||
"source_gallery_receipt_path": "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json"
|
||||
}</pre></details></div>
|
||||
</div>
|
||||
<p><strong>Known blockers:</strong> auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</p>
|
||||
</header>
|
||||
<section class="review-handoff">
|
||||
<h2>Human Review Export</h2>
|
||||
<div class="warning">This local UI does not automatically modify production/default. It only stores browser-local decisions and exports JSON for a separate apply script.</div>
|
||||
<p><code>human_review_status=pending</code> <code>promotion_action=no_change_until_human_pass</code></p>
|
||||
<p>Machine-readable gallery receipt: <code>skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json</code></p>
|
||||
<p>Apply script input: save this textarea as decisions JSON, then pass it to the apply script, for example <code>python <apply-script> --gallery-receipt skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json --decisions <exported-decisions.json></code>.</p>
|
||||
<textarea id="review-decisions-json" readonly spellcheck="false"></textarea>
|
||||
</section>
|
||||
|
||||
<main class="deck">
|
||||
<section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/stencil-tablet-1.png" alt="cover" /></div><h2>1. cover</h2><p>cover / cover</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-cover</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/stencil-tablet-1.png" alt="agenda" /></div><h2>2. agenda</h2><p>agenda / agenda</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-agenda</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/stencil-tablet-3.png" alt="princ" /></div><h2>3. princ</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-princ</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/stencil-tablet-1.png" alt="sec" /></div><h2>4. sec</h2><p>content / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-sec</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/stencil-tablet-1.png" alt="consult" /></div><h2>5. consult</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-consult</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/stencil-tablet-1.png" alt="chart" /></div><h2>6. chart</h2><p>process_or_timeline / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-chart</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/stencil-tablet-1.png" alt="process" /></div><h2>7. process</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-process</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/stencil-tablet-8.png" alt="matrix" /></div><h2>8. matrix</h2><p>process_or_timeline / comparison_or_split</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-matrix</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/stencil-tablet-1.png" alt="stats" /></div><h2>9. stats</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-stats</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/stencil-tablet-1.png" alt="quote" /></div><h2>10. quote</h2><p>quote_or_emphasis / quote_or_emphasis</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-quote</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/stencil-tablet-1.png" alt="cta" /></div><h2>11. cta</h2><p>process_or_timeline / process_or_timeline</p><p><span class="badge bad">missing_smoke</span></p><p><code>s-cta</code></p></section>
|
||||
</main>
|
||||
<script>
|
||||
(function () {
|
||||
var storageKey = "beautiful-production-review-decisions-v1";
|
||||
var schemaVersion = "svglide-beautiful-human-review-decisions/v1";
|
||||
var reviewBatchId = "beautiful-34";
|
||||
var receiptPath = "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json";
|
||||
var pendingHumanReviewStatus = "pending";
|
||||
var promotionAction = "no_change_until_human_pass";
|
||||
|
||||
function readState() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
||||
if (parsed && typeof parsed === "object" && parsed.decisions && typeof parsed.decisions === "object") {
|
||||
return parsed;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore malformed local state and rebuild below.
|
||||
}
|
||||
return { decisions: {} };
|
||||
}
|
||||
|
||||
function writeState(state) {
|
||||
localStorage.setItem(storageKey, JSON.stringify(state));
|
||||
}
|
||||
|
||||
function buildExport(state) {
|
||||
var decisions = Object.keys(state.decisions || {}).sort().map(function (familyId) {
|
||||
return state.decisions[familyId];
|
||||
});
|
||||
return {
|
||||
schema_version: schemaVersion,
|
||||
artifact_kind: "beautiful_template_human_review_decisions",
|
||||
review_batch_id: reviewBatchId,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
not_promotion_receipt: true,
|
||||
policy: {
|
||||
does_not_automatically_modify_production_default: true,
|
||||
apply_script_must_validate_gallery_receipt: true
|
||||
},
|
||||
decisions: decisions
|
||||
};
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.querySelectorAll("[data-review-current-for]").forEach(function (node) {
|
||||
var familyId = node.getAttribute("data-review-current-for");
|
||||
var decision = state.decisions[familyId];
|
||||
node.textContent = decision ? decision.review_status : "pending";
|
||||
});
|
||||
document.querySelectorAll("[data-review-status]").forEach(function (button) {
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var decision = state.decisions[familyId];
|
||||
button.classList.toggle("selected", Boolean(decision && decision.review_status === status));
|
||||
});
|
||||
document.querySelectorAll("[data-review-notes-for]").forEach(function (input) {
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var decision = state.decisions[familyId];
|
||||
if (decision && input.value !== decision.notes) {
|
||||
input.value = decision.notes || "";
|
||||
}
|
||||
});
|
||||
var textarea = document.getElementById("review-decisions-json");
|
||||
if (textarea) {
|
||||
textarea.value = JSON.stringify(buildExport(state), null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
var button = event.target.closest("[data-review-status]");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var existing = state.decisions[familyId] || {};
|
||||
state.decisions[familyId] = {
|
||||
family_id: familyId,
|
||||
review_status: status,
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
notes: existing.notes || "",
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
document.addEventListener("input", function (event) {
|
||||
var input = event.target.closest("[data-review-notes-for]");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var existing = state.decisions[familyId] || {
|
||||
family_id: familyId,
|
||||
review_status: "needs_fix",
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
existing.notes = input.value;
|
||||
existing.updated_at = new Date().toISOString();
|
||||
state.decisions[familyId] = existing;
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
render(readState());
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/stencil-tablet.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "761d7d2063337a41bb0058766d75ed1d470584c07569ea68930e42ec37d2630a"
|
||||
"sha256": "ca62bc4d64abeff11aafb248051fe51438501c1f6c3b486a414fc05d1c05c4c8"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "761d7d2063337a41bb0058766d75ed1d470584c07569ea68930e42ec37d2630a",
|
||||
"contact_sheet": "ca62bc4d64abeff11aafb248051fe51438501c1f6c3b486a414fc05d1c05c4c8",
|
||||
"fidelity_receipt": "bf32692b17d20d5a20c9c87ac02226c93739131b38f83c7f3b452a14451128fd",
|
||||
"reference_screenshot": "b8321134113e99f90a0e17e44e326ab25e64f3735150dd82269e0b2daabaaa2b",
|
||||
"smoke_receipt": null,
|
||||
|
||||
@@ -19,27 +19,175 @@
|
||||
h2 { margin: 10px 0 4px; font-size: 15px; }
|
||||
p { margin: 5px 0; font-size: 12px; color: #536071; }
|
||||
code { word-break: break-all; font-size: 11px; }
|
||||
button { cursor: pointer; border: 1px solid #b8c2d2; background: #fff; color: #172033; border-radius: 6px; padding: 6px 9px; font-weight: 700; }
|
||||
button.selected { border-color: #1d4ed8; background: #dbeafe; color: #1e3a8a; }
|
||||
.badge { display: inline-block; border-radius: 999px; padding: 2px 7px; font-size: 11px; font-weight: 700; }
|
||||
.ok { color: #065f46; background: #d1fae5; }
|
||||
.warn { color: #92400e; background: #fef3c7; }
|
||||
.bad { color: #991b1b; background: #fee2e2; }
|
||||
.review-panel, .review-handoff { background: #fff; border: 1px solid #dfe5ee; border-radius: 8px; padding: 14px; margin: 16px 0; }
|
||||
.decision-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
|
||||
.review-current { font-size: 12px; color: #536071; margin-bottom: 8px; }
|
||||
.notes-label { display: block; color: #536071; font-size: 12px; }
|
||||
.notes-label input { margin-left: 8px; min-width: min(520px, 80vw); padding: 6px 8px; border: 1px solid #c7d0df; border-radius: 6px; }
|
||||
.decision-template { margin-top: 10px; }
|
||||
pre, textarea { width: 100%; box-sizing: border-box; border: 1px solid #c7d0df; border-radius: 6px; background: #f8fafc; color: #172033; }
|
||||
pre { overflow: auto; padding: 10px; font-size: 12px; }
|
||||
textarea { min-height: 180px; padding: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<p><a href="../index.html">Back to gallery</a></p>
|
||||
<h1>studio</h1>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt.</div>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt and does not automatically modify production/default.</div>
|
||||
<div class="meta">
|
||||
<div class="metric"><strong>12</strong>source pages</div>
|
||||
<div class="metric"><strong>blocked</strong>auto gate</div>
|
||||
<div class="metric"><strong>missing</strong>smoke</div>
|
||||
<div class="metric"><strong>passed</strong>fidelity</div>
|
||||
</div>
|
||||
<div class="review-panel">
|
||||
<h2>Human decision</h2>
|
||||
<div class="review-control" data-review-control-for="studio"><div class="decision-buttons"><button type="button" data-family-id="studio" data-review-status="pass">pass</button><button type="button" data-family-id="studio" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="studio" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="studio">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="studio" placeholder="optional apply-script context" /></label><details class="decision-template"><summary>Copyable decision JSON fragment</summary><pre>{
|
||||
"family_id": "studio",
|
||||
"human_review_status_before_selection": "pending",
|
||||
"notes": "",
|
||||
"promotion_action": "no_change_until_human_pass",
|
||||
"review_status": "pass | needs_fix | reject",
|
||||
"runtime_template_id": "type-mass-poster",
|
||||
"source_gallery_receipt_path": "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json"
|
||||
}</pre></details></div>
|
||||
</div>
|
||||
<p><strong>Known blockers:</strong> auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</p>
|
||||
</header>
|
||||
<section class="review-handoff">
|
||||
<h2>Human Review Export</h2>
|
||||
<div class="warning">This local UI does not automatically modify production/default. It only stores browser-local decisions and exports JSON for a separate apply script.</div>
|
||||
<p><code>human_review_status=pending</code> <code>promotion_action=no_change_until_human_pass</code></p>
|
||||
<p>Machine-readable gallery receipt: <code>skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json</code></p>
|
||||
<p>Apply script input: save this textarea as decisions JSON, then pass it to the apply script, for example <code>python <apply-script> --gallery-receipt skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json --decisions <exported-decisions.json></code>.</p>
|
||||
<textarea id="review-decisions-json" readonly spellcheck="false"></textarea>
|
||||
</section>
|
||||
|
||||
<main class="deck">
|
||||
<section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/studio-1.png" alt="cover" /></div><h2>1. cover</h2><p>cover / cover</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--cover</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/studio-1.png" alt="chapter" /></div><h2>2. chapter</h2><p>agenda / agenda</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--chapter</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/studio-1.png" alt="statement" /></div><h2>3. statement</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--statement</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/studio-4.png" alt="split" /></div><h2>4. split</h2><p>content_split / comparison_or_split</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--split</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/studio-1.png" alt="stats" /></div><h2>5. stats</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--stats</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/studio-1.png" alt="list" /></div><h2>6. list</h2><p>content / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--list</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/studio-1.png" alt="quote" /></div><h2>7. quote</h2><p>quote_or_emphasis / quote_or_emphasis</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--quote</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/studio-8.png" alt="compare" /></div><h2>8. compare</h2><p>content / comparison_or_split</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--compare</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/studio-1.png" alt="chapter-9" /></div><h2>9. chapter-9</h2><p>content / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--chapter</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/studio-1.png" alt="statement-10" /></div><h2>10. statement-10</h2><p>closing / closing</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--statement</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/studio-1.png" alt="chart" /></div><h2>11. chart</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--chart</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/studio-1.png" alt="end" /></div><h2>12. end</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--end</code></p></section>
|
||||
</main>
|
||||
<script>
|
||||
(function () {
|
||||
var storageKey = "beautiful-production-review-decisions-v1";
|
||||
var schemaVersion = "svglide-beautiful-human-review-decisions/v1";
|
||||
var reviewBatchId = "beautiful-34";
|
||||
var receiptPath = "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json";
|
||||
var pendingHumanReviewStatus = "pending";
|
||||
var promotionAction = "no_change_until_human_pass";
|
||||
|
||||
function readState() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
||||
if (parsed && typeof parsed === "object" && parsed.decisions && typeof parsed.decisions === "object") {
|
||||
return parsed;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore malformed local state and rebuild below.
|
||||
}
|
||||
return { decisions: {} };
|
||||
}
|
||||
|
||||
function writeState(state) {
|
||||
localStorage.setItem(storageKey, JSON.stringify(state));
|
||||
}
|
||||
|
||||
function buildExport(state) {
|
||||
var decisions = Object.keys(state.decisions || {}).sort().map(function (familyId) {
|
||||
return state.decisions[familyId];
|
||||
});
|
||||
return {
|
||||
schema_version: schemaVersion,
|
||||
artifact_kind: "beautiful_template_human_review_decisions",
|
||||
review_batch_id: reviewBatchId,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
not_promotion_receipt: true,
|
||||
policy: {
|
||||
does_not_automatically_modify_production_default: true,
|
||||
apply_script_must_validate_gallery_receipt: true
|
||||
},
|
||||
decisions: decisions
|
||||
};
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.querySelectorAll("[data-review-current-for]").forEach(function (node) {
|
||||
var familyId = node.getAttribute("data-review-current-for");
|
||||
var decision = state.decisions[familyId];
|
||||
node.textContent = decision ? decision.review_status : "pending";
|
||||
});
|
||||
document.querySelectorAll("[data-review-status]").forEach(function (button) {
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var decision = state.decisions[familyId];
|
||||
button.classList.toggle("selected", Boolean(decision && decision.review_status === status));
|
||||
});
|
||||
document.querySelectorAll("[data-review-notes-for]").forEach(function (input) {
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var decision = state.decisions[familyId];
|
||||
if (decision && input.value !== decision.notes) {
|
||||
input.value = decision.notes || "";
|
||||
}
|
||||
});
|
||||
var textarea = document.getElementById("review-decisions-json");
|
||||
if (textarea) {
|
||||
textarea.value = JSON.stringify(buildExport(state), null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
var button = event.target.closest("[data-review-status]");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var existing = state.decisions[familyId] || {};
|
||||
state.decisions[familyId] = {
|
||||
family_id: familyId,
|
||||
review_status: status,
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
notes: existing.notes || "",
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
document.addEventListener("input", function (event) {
|
||||
var input = event.target.closest("[data-review-notes-for]");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var existing = state.decisions[familyId] || {
|
||||
family_id: familyId,
|
||||
review_status: "needs_fix",
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
existing.notes = input.value;
|
||||
existing.updated_at = new Date().toISOString();
|
||||
state.decisions[familyId] = existing;
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
render(readState());
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/studio.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "2e5c78fc922e036219c15f98dc9608883d9013cda1c3e1b0f9f31d5d0bb8bbd6"
|
||||
"sha256": "d05050e509a7940a4893fbda99624438c1130317d811140d6337fdecb6357b94"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "2e5c78fc922e036219c15f98dc9608883d9013cda1c3e1b0f9f31d5d0bb8bbd6",
|
||||
"contact_sheet": "d05050e509a7940a4893fbda99624438c1130317d811140d6337fdecb6357b94",
|
||||
"fidelity_receipt": "95baeec998aed196a738e4491cc7cab3ad34dbca2c3d5e96a94943f62075f60c",
|
||||
"reference_screenshot": "0d7c0646a85c56b4b26e09f0cf8a0b658fe0b1cf36be38255900fd259d0c42d4",
|
||||
"smoke_receipt": null,
|
||||
|
||||
@@ -19,27 +19,175 @@
|
||||
h2 { margin: 10px 0 4px; font-size: 15px; }
|
||||
p { margin: 5px 0; font-size: 12px; color: #536071; }
|
||||
code { word-break: break-all; font-size: 11px; }
|
||||
button { cursor: pointer; border: 1px solid #b8c2d2; background: #fff; color: #172033; border-radius: 6px; padding: 6px 9px; font-weight: 700; }
|
||||
button.selected { border-color: #1d4ed8; background: #dbeafe; color: #1e3a8a; }
|
||||
.badge { display: inline-block; border-radius: 999px; padding: 2px 7px; font-size: 11px; font-weight: 700; }
|
||||
.ok { color: #065f46; background: #d1fae5; }
|
||||
.warn { color: #92400e; background: #fef3c7; }
|
||||
.bad { color: #991b1b; background: #fee2e2; }
|
||||
.review-panel, .review-handoff { background: #fff; border: 1px solid #dfe5ee; border-radius: 8px; padding: 14px; margin: 16px 0; }
|
||||
.decision-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
|
||||
.review-current { font-size: 12px; color: #536071; margin-bottom: 8px; }
|
||||
.notes-label { display: block; color: #536071; font-size: 12px; }
|
||||
.notes-label input { margin-left: 8px; min-width: min(520px, 80vw); padding: 6px 8px; border: 1px solid #c7d0df; border-radius: 6px; }
|
||||
.decision-template { margin-top: 10px; }
|
||||
pre, textarea { width: 100%; box-sizing: border-box; border: 1px solid #c7d0df; border-radius: 6px; background: #f8fafc; color: #172033; }
|
||||
pre { overflow: auto; padding: 10px; font-size: 12px; }
|
||||
textarea { min-height: 180px; padding: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<p><a href="../index.html">Back to gallery</a></p>
|
||||
<h1>vellum</h1>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt.</div>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt and does not automatically modify production/default.</div>
|
||||
<div class="meta">
|
||||
<div class="metric"><strong>9</strong>source pages</div>
|
||||
<div class="metric"><strong>blocked</strong>auto gate</div>
|
||||
<div class="metric"><strong>missing</strong>smoke</div>
|
||||
<div class="metric"><strong>passed</strong>fidelity</div>
|
||||
</div>
|
||||
<div class="review-panel">
|
||||
<h2>Human decision</h2>
|
||||
<div class="review-control" data-review-control-for="vellum"><div class="decision-buttons"><button type="button" data-family-id="vellum" data-review-status="pass">pass</button><button type="button" data-family-id="vellum" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="vellum" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="vellum">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="vellum" placeholder="optional apply-script context" /></label><details class="decision-template"><summary>Copyable decision JSON fragment</summary><pre>{
|
||||
"family_id": "vellum",
|
||||
"human_review_status_before_selection": "pending",
|
||||
"notes": "",
|
||||
"promotion_action": "no_change_until_human_pass",
|
||||
"review_status": "pass | needs_fix | reject",
|
||||
"runtime_template_id": "vellum-scholar-brief",
|
||||
"source_gallery_receipt_path": "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json"
|
||||
}</pre></details></div>
|
||||
</div>
|
||||
<p><strong>Known blockers:</strong> auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</p>
|
||||
</header>
|
||||
<section class="review-handoff">
|
||||
<h2>Human Review Export</h2>
|
||||
<div class="warning">This local UI does not automatically modify production/default. It only stores browser-local decisions and exports JSON for a separate apply script.</div>
|
||||
<p><code>human_review_status=pending</code> <code>promotion_action=no_change_until_human_pass</code></p>
|
||||
<p>Machine-readable gallery receipt: <code>skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json</code></p>
|
||||
<p>Apply script input: save this textarea as decisions JSON, then pass it to the apply script, for example <code>python <apply-script> --gallery-receipt skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json --decisions <exported-decisions.json></code>.</p>
|
||||
<textarea id="review-decisions-json" readonly spellcheck="false"></textarea>
|
||||
</section>
|
||||
|
||||
<main class="deck">
|
||||
<section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/vellum-1.png" alt="cover" /></div><h2>1. cover</h2><p>cover / cover</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--cover</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/vellum-1.png" alt="statement" /></div><h2>2. statement</h2><p>agenda / agenda</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--statement</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/vellum-1.png" alt="text" /></div><h2>3. text</h2><p>content / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--text</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/vellum-4.png" alt="stats" /></div><h2>4. stats</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--stats</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/vellum-1.png" alt="list" /></div><h2>5. list</h2><p>content / content</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--list</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/vellum-1.png" alt="quote" /></div><h2>6. quote</h2><p>quote_or_emphasis / quote_or_emphasis</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--quote</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/vellum-1.png" alt="compare" /></div><h2>7. compare</h2><p>data_dashboard / comparison_or_split</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--compare</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/vellum-8.png" alt="chart" /></div><h2>8. chart</h2><p>data_dashboard / data_or_structured</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--chart</code></p></section><section class="page"><div class="thumb"><img src="file:///Users/bytedance/bd-projects/beautiful-html-templates/screenshots/vellum-1.png" alt="end" /></div><h2>9. end</h2><p>closing / closing</p><p><span class="badge bad">missing_smoke</span></p><p><code>slide--end</code></p></section>
|
||||
</main>
|
||||
<script>
|
||||
(function () {
|
||||
var storageKey = "beautiful-production-review-decisions-v1";
|
||||
var schemaVersion = "svglide-beautiful-human-review-decisions/v1";
|
||||
var reviewBatchId = "beautiful-34";
|
||||
var receiptPath = "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json";
|
||||
var pendingHumanReviewStatus = "pending";
|
||||
var promotionAction = "no_change_until_human_pass";
|
||||
|
||||
function readState() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
||||
if (parsed && typeof parsed === "object" && parsed.decisions && typeof parsed.decisions === "object") {
|
||||
return parsed;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore malformed local state and rebuild below.
|
||||
}
|
||||
return { decisions: {} };
|
||||
}
|
||||
|
||||
function writeState(state) {
|
||||
localStorage.setItem(storageKey, JSON.stringify(state));
|
||||
}
|
||||
|
||||
function buildExport(state) {
|
||||
var decisions = Object.keys(state.decisions || {}).sort().map(function (familyId) {
|
||||
return state.decisions[familyId];
|
||||
});
|
||||
return {
|
||||
schema_version: schemaVersion,
|
||||
artifact_kind: "beautiful_template_human_review_decisions",
|
||||
review_batch_id: reviewBatchId,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
not_promotion_receipt: true,
|
||||
policy: {
|
||||
does_not_automatically_modify_production_default: true,
|
||||
apply_script_must_validate_gallery_receipt: true
|
||||
},
|
||||
decisions: decisions
|
||||
};
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.querySelectorAll("[data-review-current-for]").forEach(function (node) {
|
||||
var familyId = node.getAttribute("data-review-current-for");
|
||||
var decision = state.decisions[familyId];
|
||||
node.textContent = decision ? decision.review_status : "pending";
|
||||
});
|
||||
document.querySelectorAll("[data-review-status]").forEach(function (button) {
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var decision = state.decisions[familyId];
|
||||
button.classList.toggle("selected", Boolean(decision && decision.review_status === status));
|
||||
});
|
||||
document.querySelectorAll("[data-review-notes-for]").forEach(function (input) {
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var decision = state.decisions[familyId];
|
||||
if (decision && input.value !== decision.notes) {
|
||||
input.value = decision.notes || "";
|
||||
}
|
||||
});
|
||||
var textarea = document.getElementById("review-decisions-json");
|
||||
if (textarea) {
|
||||
textarea.value = JSON.stringify(buildExport(state), null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
var button = event.target.closest("[data-review-status]");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var existing = state.decisions[familyId] || {};
|
||||
state.decisions[familyId] = {
|
||||
family_id: familyId,
|
||||
review_status: status,
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
notes: existing.notes || "",
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
document.addEventListener("input", function (event) {
|
||||
var input = event.target.closest("[data-review-notes-for]");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var existing = state.decisions[familyId] || {
|
||||
family_id: familyId,
|
||||
review_status: "needs_fix",
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
existing.notes = input.value;
|
||||
existing.updated_at = new Date().toISOString();
|
||||
state.decisions[familyId] = existing;
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
render(readState());
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/vellum.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "d1cba07fdba73ba6d0b49076d091f1fba3e299f86f44d1bab7d2c2836b26551f"
|
||||
"sha256": "ceadac634245686ba842f84a704d927fb688127f0c14b60eece6d7daa3805c10"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "d1cba07fdba73ba6d0b49076d091f1fba3e299f86f44d1bab7d2c2836b26551f",
|
||||
"contact_sheet": "ceadac634245686ba842f84a704d927fb688127f0c14b60eece6d7daa3805c10",
|
||||
"fidelity_receipt": "3152f66c029a0f4be72c43d417b2aec470b483239a8070136e5b87993e57ae68",
|
||||
"reference_screenshot": "8c99c96677fec3c94235098b8fe36b9beeefd31ebfd173989f0ce358d91c4b73",
|
||||
"smoke_receipt": null,
|
||||
|
||||
@@ -12,11 +12,19 @@
|
||||
.summary { display: flex; gap: 12px; flex-wrap: wrap; margin: 18px 0; }
|
||||
.metric { background: #fff; border: 1px solid #dbe1ea; border-radius: 8px; padding: 10px 12px; min-width: 150px; }
|
||||
.metric strong { display: block; font-size: 22px; }
|
||||
button { cursor: pointer; border: 1px solid #b8c2d2; background: #fff; color: #172033; border-radius: 6px; padding: 6px 9px; font-weight: 700; }
|
||||
button.selected { border-color: #1d4ed8; background: #dbeafe; color: #1e3a8a; }
|
||||
table { border-collapse: collapse; width: 100%; background: #fff; border: 1px solid #dbe1ea; }
|
||||
th, td { border-bottom: 1px solid #e5e9f0; padding: 10px; text-align: left; vertical-align: top; font-size: 13px; }
|
||||
th { background: #eef2f7; font-size: 12px; text-transform: uppercase; letter-spacing: .04em; }
|
||||
code { font-size: 11px; color: #4a5870; word-break: break-all; }
|
||||
small { color: #65728a; }
|
||||
.decision-buttons { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
|
||||
.review-current { font-size: 12px; color: #536071; margin-bottom: 8px; }
|
||||
.notes-label { display: block; color: #536071; font-size: 12px; }
|
||||
.notes-label input { width: min(220px, 80vw); padding: 6px 8px; border: 1px solid #c7d0df; border-radius: 6px; }
|
||||
.review-handoff { background: #fff; border: 1px solid #dbe1ea; border-radius: 8px; padding: 14px; margin: 18px 0; max-width: 1180px; }
|
||||
textarea { width: 100%; min-height: 180px; box-sizing: border-box; border: 1px solid #c7d0df; border-radius: 6px; background: #f8fafc; color: #172033; padding: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
||||
.badge { display: inline-block; border-radius: 999px; padding: 2px 7px; font-size: 11px; font-weight: 700; }
|
||||
.ok { color: #065f46; background: #d1fae5; }
|
||||
.warn { color: #92400e; background: #fef3c7; }
|
||||
@@ -26,7 +34,7 @@
|
||||
<body>
|
||||
<header>
|
||||
<h1>SVGlide Beautiful Production Review Gallery</h1>
|
||||
<div class="warning">This gallery is review input only. It is not a promotion receipt and does not change production/default_selectable status.</div>
|
||||
<div class="warning">This gallery is review input only. It is not a promotion receipt, does not change production/default_selectable status, and does not automatically modify production/default.</div>
|
||||
<div class="summary">
|
||||
<div class="metric"><strong>34</strong>candidates</div>
|
||||
<div class="metric"><strong>1</strong>production + default</div>
|
||||
@@ -34,6 +42,15 @@
|
||||
<div class="metric"><strong>{"missing": 33, "passed": 1}</strong>smoke status counts</div>
|
||||
</div>
|
||||
</header>
|
||||
<section class="review-handoff">
|
||||
<h2>Human Review Export</h2>
|
||||
<div class="warning">This local UI does not automatically modify production/default. It only stores browser-local decisions and exports JSON for a separate apply script.</div>
|
||||
<p><code>human_review_status=pending</code> <code>promotion_action=no_change_until_human_pass</code></p>
|
||||
<p>Machine-readable gallery receipt: <code>skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json</code></p>
|
||||
<p>Apply script input: save this textarea as decisions JSON, then pass it to the apply script, for example <code>python <apply-script> --gallery-receipt skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json --decisions <exported-decisions.json></code>.</p>
|
||||
<textarea id="review-decisions-json" readonly spellcheck="false"></textarea>
|
||||
</section>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -44,45 +61,162 @@
|
||||
<th>Smoke</th>
|
||||
<th>Fidelity</th>
|
||||
<th>Known Blockers</th>
|
||||
<th>Human Decision</th>
|
||||
<th>Evidence</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td><strong><a href="families/8-bit-orbit.html">8-bit-orbit</a></strong><br><small>pixel-orbit-console</small></td><td>needs_review<br><small>default=false</small></td><td>10 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human=pending</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><code>skills/lark-slides/references/visual-contracts/beautiful/8-bit-orbit.pixel-orbit-console.json</code><br><code>beautiful-html-templates/screenshots/8-bit-orbit-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/biennale-yellow.html">biennale-yellow</a></strong><br><small>biennale-programme-poster</small></td><td>needs_review<br><small>default=false</small></td><td>8 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human=pending</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><code>skills/lark-slides/references/visual-contracts/beautiful/biennale-yellow.biennale-programme-poster.json</code><br><code>beautiful-html-templates/screenshots/biennale-yellow-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/block-frame.html">block-frame</a></strong><br><small>block-frame-grid</small></td><td>needs_review<br><small>default=false</small></td><td>10 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human=pending</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><code>skills/lark-slides/references/visual-contracts/beautiful/block-frame.block-frame-grid.json</code><br><code>beautiful-html-templates/screenshots/block-frame-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/blue-professional.html">blue-professional</a></strong><br><small>executive-dashboard</small></td><td>production<br><small>default=true</small></td><td>10 source<br><small>10 implemented</small></td><td><span class="badge ok">passed</span><br><small>human=pending</small></td><td>passed<br><small>10 rendered</small></td><td>passed</td><td>none</td><td><code>skills/lark-slides/references/visual-contracts/beautiful/blue-professional.executive-dashboard.json</code><br><code>beautiful-html-templates/screenshots/blue-professional-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/bold-poster.html">bold-poster</a></strong><br><small>poster-stat-punch</small></td><td>needs_review<br><small>default=false</small></td><td>10 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human=pending</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><code>skills/lark-slides/references/visual-contracts/beautiful/bold-poster.poster-stat-punch.json</code><br><code>beautiful-html-templates/screenshots/bold-poster-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/broadside.html">broadside</a></strong><br><small>editorial-quote-chart</small></td><td>needs_review<br><small>default=false</small></td><td>16 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human=pending</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><code>skills/lark-slides/references/visual-contracts/beautiful/broadside.editorial-quote-chart.json</code><br><code>beautiful-html-templates/screenshots/broadside-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/capsule.html">capsule</a></strong><br><small>capsule-card-system</small></td><td>needs_review<br><small>default=false</small></td><td>10 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human=pending</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><code>skills/lark-slides/references/visual-contracts/beautiful/capsule.capsule-card-system.json</code><br><code>beautiful-html-templates/screenshots/capsule-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/cartesian.html">cartesian</a></strong><br><small>architectural-spec</small></td><td>needs_review<br><small>default=false</small></td><td>9 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human=pending</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><code>skills/lark-slides/references/visual-contracts/beautiful/cartesian.architectural-spec.json</code><br><code>beautiful-html-templates/screenshots/cartesian-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/cobalt-grid.html">cobalt-grid</a></strong><br><small>trend-grid-report</small></td><td>needs_review<br><small>default=false</small></td><td>8 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human=pending</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><code>skills/lark-slides/references/visual-contracts/beautiful/cobalt-grid.trend-grid-report.json</code><br><code>beautiful-html-templates/screenshots/cobalt-grid-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/coral.html">coral</a></strong><br><small>coral-magazine-feature</small></td><td>needs_review<br><small>default=false</small></td><td>10 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human=pending</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><code>skills/lark-slides/references/visual-contracts/beautiful/coral.coral-magazine-feature.json</code><br><code>beautiful-html-templates/screenshots/coral-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/creative-mode.html">creative-mode</a></strong><br><small>creative-mode-grid</small></td><td>needs_review<br><small>default=false</small></td><td>8 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human=pending</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><code>skills/lark-slides/references/visual-contracts/beautiful/creative-mode.creative-mode-grid.json</code><br><code>beautiful-html-templates/screenshots/creative-mode-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/daisy-days.html">daisy-days</a></strong><br><small>daisy-workshop-playbook</small></td><td>needs_review<br><small>default=false</small></td><td>9 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human=pending</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><code>skills/lark-slides/references/visual-contracts/beautiful/daisy-days.daisy-workshop-playbook.json</code><br><code>beautiful-html-templates/screenshots/daisy-days-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/editorial-forest.html">editorial-forest</a></strong><br><small>serif-stat-editorial</small></td><td>needs_review<br><small>default=false</small></td><td>8 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human=pending</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><code>skills/lark-slides/references/visual-contracts/beautiful/editorial-forest.serif-stat-editorial.json</code><br><code>beautiful-html-templates/screenshots/editorial-forest-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/editorial-tri-tone.html">editorial-tri-tone</a></strong><br><small>tritone-editorial-spread</small></td><td>needs_review<br><small>default=false</small></td><td>8 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human=pending</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><code>skills/lark-slides/references/visual-contracts/beautiful/editorial-tri-tone.tritone-editorial-spread.json</code><br><code>beautiful-html-templates/screenshots/editorial-tri-tone-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/emerald-editorial.html">emerald-editorial</a></strong><br><small>emerald-editorial-cover</small></td><td>needs_review<br><small>default=false</small></td><td>8 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human=pending</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><code>skills/lark-slides/references/visual-contracts/beautiful/emerald-editorial.emerald-editorial-cover.json</code><br><code>beautiful-html-templates/screenshots/emerald-editorial-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/grove.html">grove</a></strong><br><small>grove-organic-brief</small></td><td>needs_review<br><small>default=false</small></td><td>12 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human=pending</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><code>skills/lark-slides/references/visual-contracts/beautiful/grove.grove-organic-brief.json</code><br><code>beautiful-html-templates/screenshots/grove-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/long-table.html">long-table</a></strong><br><small>printed-program</small></td><td>needs_review<br><small>default=false</small></td><td>8 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human=pending</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><code>skills/lark-slides/references/visual-contracts/beautiful/long-table.printed-program.json</code><br><code>beautiful-html-templates/screenshots/long-table-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/mat.html">mat</a></strong><br><small>mat-midcentury-board</small></td><td>needs_review<br><small>default=false</small></td><td>9 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human=pending</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><code>skills/lark-slides/references/visual-contracts/beautiful/mat.mat-midcentury-board.json</code><br><code>beautiful-html-templates/screenshots/mat-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/monochrome.html">monochrome</a></strong><br><small>ledger-briefing</small></td><td>needs_review<br><small>default=false</small></td><td>16 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human=pending</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><code>skills/lark-slides/references/visual-contracts/beautiful/monochrome.ledger-briefing.json</code><br><code>beautiful-html-templates/screenshots/monochrome-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/neo-grid-bold.html">neo-grid-bold</a></strong><br><small>dense-panel-grid</small></td><td>needs_review<br><small>default=false</small></td><td>12 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human=pending</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><code>skills/lark-slides/references/visual-contracts/beautiful/neo-grid-bold.dense-panel-grid.json</code><br><code>beautiful-html-templates/screenshots/neo-grid-bold-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/peoples-platform.html">peoples-platform</a></strong><br><small>people-platform-manifesto</small></td><td>needs_review<br><small>default=false</small></td><td>10 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human=pending</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing</td><td><code>skills/lark-slides/references/visual-contracts/beautiful/peoples-platform.people-platform-manifesto.json</code><br><code>beautiful-html-templates/screenshots/peoples-platform-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/pin-and-paper.html">pin-and-paper</a></strong><br><small>annotated-field-board</small></td><td>needs_review<br><small>default=false</small></td><td>11 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human=pending</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><code>skills/lark-slides/references/visual-contracts/beautiful/pin-and-paper.annotated-field-board.json</code><br><code>beautiful-html-templates/screenshots/pin-and-paper-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/pink-script.html">pink-script</a></strong><br><small>pink-nocturne-feature</small></td><td>needs_review<br><small>default=false</small></td><td>9 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human=pending</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><code>skills/lark-slides/references/visual-contracts/beautiful/pink-script.pink-nocturne-feature.json</code><br><code>beautiful-html-templates/screenshots/pink-script-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/playful.html">playful</a></strong><br><small>playful-indie-launch</small></td><td>needs_review<br><small>default=false</small></td><td>10 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human=pending</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><code>skills/lark-slides/references/visual-contracts/beautiful/playful.playful-indie-launch.json</code><br><code>beautiful-html-templates/screenshots/playful-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/raw-grid.html">raw-grid</a></strong><br><small>brutalist-matrix</small></td><td>needs_review<br><small>default=false</small></td><td>10 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human=pending</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><code>skills/lark-slides/references/visual-contracts/beautiful/raw-grid.brutalist-matrix.json</code><br><code>beautiful-html-templates/screenshots/raw-grid-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/retro-windows.html">retro-windows</a></strong><br><small>retro-ui-dashboard</small></td><td>needs_review<br><small>default=false</small></td><td>10 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human=pending</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><code>skills/lark-slides/references/visual-contracts/beautiful/retro-windows.retro-ui-dashboard.json</code><br><code>beautiful-html-templates/screenshots/retro-windows-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/retro-zine.html">retro-zine</a></strong><br><small>retro-zine-spread</small></td><td>needs_review<br><small>default=false</small></td><td>10 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human=pending</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><code>skills/lark-slides/references/visual-contracts/beautiful/retro-zine.retro-zine-spread.json</code><br><code>beautiful-html-templates/screenshots/retro-zine-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/sakura-chroma.html">sakura-chroma</a></strong><br><small>product-ribbon</small></td><td>needs_review<br><small>default=false</small></td><td>8 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human=pending</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><code>skills/lark-slides/references/visual-contracts/beautiful/sakura-chroma.product-ribbon.json</code><br><code>beautiful-html-templates/screenshots/sakura-chroma-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/scatterbrain.html">scatterbrain</a></strong><br><small>sticky-workshop-board</small></td><td>needs_review<br><small>default=false</small></td><td>8 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human=pending</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><code>skills/lark-slides/references/visual-contracts/beautiful/scatterbrain.sticky-workshop-board.json</code><br><code>beautiful-html-templates/screenshots/scatterbrain-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/signal.html">signal</a></strong><br><small>intelligence-brief</small></td><td>needs_review<br><small>default=false</small></td><td>18 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human=pending</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing</td><td><code>skills/lark-slides/references/visual-contracts/beautiful/signal.intelligence-brief.json</code><br><code>beautiful-html-templates/screenshots/signal-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/soft-editorial.html">soft-editorial</a></strong><br><small>soft-editorial-feature</small></td><td>needs_review<br><small>default=false</small></td><td>12 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human=pending</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><code>skills/lark-slides/references/visual-contracts/beautiful/soft-editorial.soft-editorial-feature.json</code><br><code>beautiful-html-templates/screenshots/soft-editorial-4.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/stencil-tablet.html">stencil-tablet</a></strong><br><small>stencil-field-manual</small></td><td>needs_review<br><small>default=false</small></td><td>11 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human=pending</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><code>skills/lark-slides/references/visual-contracts/beautiful/stencil-tablet.stencil-field-manual.json</code><br><code>beautiful-html-templates/screenshots/stencil-tablet-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/studio.html">studio</a></strong><br><small>type-mass-poster</small></td><td>needs_review<br><small>default=false</small></td><td>12 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human=pending</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><code>skills/lark-slides/references/visual-contracts/beautiful/studio.type-mass-poster.json</code><br><code>beautiful-html-templates/screenshots/studio-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/vellum.html">vellum</a></strong><br><small>vellum-scholar-brief</small></td><td>needs_review<br><small>default=false</small></td><td>9 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human=pending</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><code>skills/lark-slides/references/visual-contracts/beautiful/vellum.vellum-scholar-brief.json</code><br><code>beautiful-html-templates/screenshots/vellum-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/8-bit-orbit.html">8-bit-orbit</a></strong><br><small>pixel-orbit-console</small></td><td>needs_review<br><small>default=false</small></td><td>10 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human_review_status=pending</small><br><small>promotion_action=no_change_until_human_pass</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><div class="review-control" data-review-control-for="8-bit-orbit"><div class="decision-buttons"><button type="button" data-family-id="8-bit-orbit" data-review-status="pass">pass</button><button type="button" data-family-id="8-bit-orbit" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="8-bit-orbit" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="8-bit-orbit">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="8-bit-orbit" placeholder="optional apply-script context" /></label></div></td><td><code>skills/lark-slides/references/visual-contracts/beautiful/8-bit-orbit.pixel-orbit-console.json</code><br><code>beautiful-html-templates/screenshots/8-bit-orbit-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/biennale-yellow.html">biennale-yellow</a></strong><br><small>biennale-programme-poster</small></td><td>needs_review<br><small>default=false</small></td><td>8 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human_review_status=pending</small><br><small>promotion_action=no_change_until_human_pass</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><div class="review-control" data-review-control-for="biennale-yellow"><div class="decision-buttons"><button type="button" data-family-id="biennale-yellow" data-review-status="pass">pass</button><button type="button" data-family-id="biennale-yellow" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="biennale-yellow" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="biennale-yellow">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="biennale-yellow" placeholder="optional apply-script context" /></label></div></td><td><code>skills/lark-slides/references/visual-contracts/beautiful/biennale-yellow.biennale-programme-poster.json</code><br><code>beautiful-html-templates/screenshots/biennale-yellow-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/block-frame.html">block-frame</a></strong><br><small>block-frame-grid</small></td><td>needs_review<br><small>default=false</small></td><td>10 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human_review_status=pending</small><br><small>promotion_action=no_change_until_human_pass</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><div class="review-control" data-review-control-for="block-frame"><div class="decision-buttons"><button type="button" data-family-id="block-frame" data-review-status="pass">pass</button><button type="button" data-family-id="block-frame" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="block-frame" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="block-frame">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="block-frame" placeholder="optional apply-script context" /></label></div></td><td><code>skills/lark-slides/references/visual-contracts/beautiful/block-frame.block-frame-grid.json</code><br><code>beautiful-html-templates/screenshots/block-frame-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/blue-professional.html">blue-professional</a></strong><br><small>executive-dashboard</small></td><td>production<br><small>default=true</small></td><td>10 source<br><small>10 implemented</small></td><td><span class="badge ok">passed</span><br><small>human_review_status=pending</small><br><small>promotion_action=no_change_until_human_pass</small></td><td>passed<br><small>10 rendered</small></td><td>passed</td><td>none</td><td><div class="review-control" data-review-control-for="blue-professional"><div class="decision-buttons"><button type="button" data-family-id="blue-professional" data-review-status="pass">pass</button><button type="button" data-family-id="blue-professional" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="blue-professional" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="blue-professional">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="blue-professional" placeholder="optional apply-script context" /></label></div></td><td><code>skills/lark-slides/references/visual-contracts/beautiful/blue-professional.executive-dashboard.json</code><br><code>beautiful-html-templates/screenshots/blue-professional-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/bold-poster.html">bold-poster</a></strong><br><small>poster-stat-punch</small></td><td>needs_review<br><small>default=false</small></td><td>10 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human_review_status=pending</small><br><small>promotion_action=no_change_until_human_pass</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><div class="review-control" data-review-control-for="bold-poster"><div class="decision-buttons"><button type="button" data-family-id="bold-poster" data-review-status="pass">pass</button><button type="button" data-family-id="bold-poster" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="bold-poster" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="bold-poster">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="bold-poster" placeholder="optional apply-script context" /></label></div></td><td><code>skills/lark-slides/references/visual-contracts/beautiful/bold-poster.poster-stat-punch.json</code><br><code>beautiful-html-templates/screenshots/bold-poster-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/broadside.html">broadside</a></strong><br><small>editorial-quote-chart</small></td><td>needs_review<br><small>default=false</small></td><td>16 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human_review_status=pending</small><br><small>promotion_action=no_change_until_human_pass</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><div class="review-control" data-review-control-for="broadside"><div class="decision-buttons"><button type="button" data-family-id="broadside" data-review-status="pass">pass</button><button type="button" data-family-id="broadside" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="broadside" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="broadside">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="broadside" placeholder="optional apply-script context" /></label></div></td><td><code>skills/lark-slides/references/visual-contracts/beautiful/broadside.editorial-quote-chart.json</code><br><code>beautiful-html-templates/screenshots/broadside-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/capsule.html">capsule</a></strong><br><small>capsule-card-system</small></td><td>needs_review<br><small>default=false</small></td><td>10 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human_review_status=pending</small><br><small>promotion_action=no_change_until_human_pass</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><div class="review-control" data-review-control-for="capsule"><div class="decision-buttons"><button type="button" data-family-id="capsule" data-review-status="pass">pass</button><button type="button" data-family-id="capsule" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="capsule" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="capsule">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="capsule" placeholder="optional apply-script context" /></label></div></td><td><code>skills/lark-slides/references/visual-contracts/beautiful/capsule.capsule-card-system.json</code><br><code>beautiful-html-templates/screenshots/capsule-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/cartesian.html">cartesian</a></strong><br><small>architectural-spec</small></td><td>needs_review<br><small>default=false</small></td><td>9 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human_review_status=pending</small><br><small>promotion_action=no_change_until_human_pass</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><div class="review-control" data-review-control-for="cartesian"><div class="decision-buttons"><button type="button" data-family-id="cartesian" data-review-status="pass">pass</button><button type="button" data-family-id="cartesian" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="cartesian" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="cartesian">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="cartesian" placeholder="optional apply-script context" /></label></div></td><td><code>skills/lark-slides/references/visual-contracts/beautiful/cartesian.architectural-spec.json</code><br><code>beautiful-html-templates/screenshots/cartesian-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/cobalt-grid.html">cobalt-grid</a></strong><br><small>trend-grid-report</small></td><td>needs_review<br><small>default=false</small></td><td>8 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human_review_status=pending</small><br><small>promotion_action=no_change_until_human_pass</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><div class="review-control" data-review-control-for="cobalt-grid"><div class="decision-buttons"><button type="button" data-family-id="cobalt-grid" data-review-status="pass">pass</button><button type="button" data-family-id="cobalt-grid" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="cobalt-grid" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="cobalt-grid">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="cobalt-grid" placeholder="optional apply-script context" /></label></div></td><td><code>skills/lark-slides/references/visual-contracts/beautiful/cobalt-grid.trend-grid-report.json</code><br><code>beautiful-html-templates/screenshots/cobalt-grid-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/coral.html">coral</a></strong><br><small>coral-magazine-feature</small></td><td>needs_review<br><small>default=false</small></td><td>10 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human_review_status=pending</small><br><small>promotion_action=no_change_until_human_pass</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><div class="review-control" data-review-control-for="coral"><div class="decision-buttons"><button type="button" data-family-id="coral" data-review-status="pass">pass</button><button type="button" data-family-id="coral" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="coral" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="coral">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="coral" placeholder="optional apply-script context" /></label></div></td><td><code>skills/lark-slides/references/visual-contracts/beautiful/coral.coral-magazine-feature.json</code><br><code>beautiful-html-templates/screenshots/coral-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/creative-mode.html">creative-mode</a></strong><br><small>creative-mode-grid</small></td><td>needs_review<br><small>default=false</small></td><td>8 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human_review_status=pending</small><br><small>promotion_action=no_change_until_human_pass</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><div class="review-control" data-review-control-for="creative-mode"><div class="decision-buttons"><button type="button" data-family-id="creative-mode" data-review-status="pass">pass</button><button type="button" data-family-id="creative-mode" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="creative-mode" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="creative-mode">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="creative-mode" placeholder="optional apply-script context" /></label></div></td><td><code>skills/lark-slides/references/visual-contracts/beautiful/creative-mode.creative-mode-grid.json</code><br><code>beautiful-html-templates/screenshots/creative-mode-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/daisy-days.html">daisy-days</a></strong><br><small>daisy-workshop-playbook</small></td><td>needs_review<br><small>default=false</small></td><td>9 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human_review_status=pending</small><br><small>promotion_action=no_change_until_human_pass</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><div class="review-control" data-review-control-for="daisy-days"><div class="decision-buttons"><button type="button" data-family-id="daisy-days" data-review-status="pass">pass</button><button type="button" data-family-id="daisy-days" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="daisy-days" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="daisy-days">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="daisy-days" placeholder="optional apply-script context" /></label></div></td><td><code>skills/lark-slides/references/visual-contracts/beautiful/daisy-days.daisy-workshop-playbook.json</code><br><code>beautiful-html-templates/screenshots/daisy-days-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/editorial-forest.html">editorial-forest</a></strong><br><small>serif-stat-editorial</small></td><td>needs_review<br><small>default=false</small></td><td>8 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human_review_status=pending</small><br><small>promotion_action=no_change_until_human_pass</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><div class="review-control" data-review-control-for="editorial-forest"><div class="decision-buttons"><button type="button" data-family-id="editorial-forest" data-review-status="pass">pass</button><button type="button" data-family-id="editorial-forest" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="editorial-forest" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="editorial-forest">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="editorial-forest" placeholder="optional apply-script context" /></label></div></td><td><code>skills/lark-slides/references/visual-contracts/beautiful/editorial-forest.serif-stat-editorial.json</code><br><code>beautiful-html-templates/screenshots/editorial-forest-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/editorial-tri-tone.html">editorial-tri-tone</a></strong><br><small>tritone-editorial-spread</small></td><td>needs_review<br><small>default=false</small></td><td>8 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human_review_status=pending</small><br><small>promotion_action=no_change_until_human_pass</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><div class="review-control" data-review-control-for="editorial-tri-tone"><div class="decision-buttons"><button type="button" data-family-id="editorial-tri-tone" data-review-status="pass">pass</button><button type="button" data-family-id="editorial-tri-tone" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="editorial-tri-tone" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="editorial-tri-tone">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="editorial-tri-tone" placeholder="optional apply-script context" /></label></div></td><td><code>skills/lark-slides/references/visual-contracts/beautiful/editorial-tri-tone.tritone-editorial-spread.json</code><br><code>beautiful-html-templates/screenshots/editorial-tri-tone-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/emerald-editorial.html">emerald-editorial</a></strong><br><small>emerald-editorial-cover</small></td><td>needs_review<br><small>default=false</small></td><td>8 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human_review_status=pending</small><br><small>promotion_action=no_change_until_human_pass</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><div class="review-control" data-review-control-for="emerald-editorial"><div class="decision-buttons"><button type="button" data-family-id="emerald-editorial" data-review-status="pass">pass</button><button type="button" data-family-id="emerald-editorial" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="emerald-editorial" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="emerald-editorial">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="emerald-editorial" placeholder="optional apply-script context" /></label></div></td><td><code>skills/lark-slides/references/visual-contracts/beautiful/emerald-editorial.emerald-editorial-cover.json</code><br><code>beautiful-html-templates/screenshots/emerald-editorial-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/grove.html">grove</a></strong><br><small>grove-organic-brief</small></td><td>needs_review<br><small>default=false</small></td><td>12 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human_review_status=pending</small><br><small>promotion_action=no_change_until_human_pass</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><div class="review-control" data-review-control-for="grove"><div class="decision-buttons"><button type="button" data-family-id="grove" data-review-status="pass">pass</button><button type="button" data-family-id="grove" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="grove" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="grove">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="grove" placeholder="optional apply-script context" /></label></div></td><td><code>skills/lark-slides/references/visual-contracts/beautiful/grove.grove-organic-brief.json</code><br><code>beautiful-html-templates/screenshots/grove-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/long-table.html">long-table</a></strong><br><small>printed-program</small></td><td>needs_review<br><small>default=false</small></td><td>8 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human_review_status=pending</small><br><small>promotion_action=no_change_until_human_pass</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><div class="review-control" data-review-control-for="long-table"><div class="decision-buttons"><button type="button" data-family-id="long-table" data-review-status="pass">pass</button><button type="button" data-family-id="long-table" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="long-table" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="long-table">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="long-table" placeholder="optional apply-script context" /></label></div></td><td><code>skills/lark-slides/references/visual-contracts/beautiful/long-table.printed-program.json</code><br><code>beautiful-html-templates/screenshots/long-table-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/mat.html">mat</a></strong><br><small>mat-midcentury-board</small></td><td>needs_review<br><small>default=false</small></td><td>9 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human_review_status=pending</small><br><small>promotion_action=no_change_until_human_pass</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><div class="review-control" data-review-control-for="mat"><div class="decision-buttons"><button type="button" data-family-id="mat" data-review-status="pass">pass</button><button type="button" data-family-id="mat" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="mat" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="mat">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="mat" placeholder="optional apply-script context" /></label></div></td><td><code>skills/lark-slides/references/visual-contracts/beautiful/mat.mat-midcentury-board.json</code><br><code>beautiful-html-templates/screenshots/mat-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/monochrome.html">monochrome</a></strong><br><small>ledger-briefing</small></td><td>needs_review<br><small>default=false</small></td><td>16 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human_review_status=pending</small><br><small>promotion_action=no_change_until_human_pass</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><div class="review-control" data-review-control-for="monochrome"><div class="decision-buttons"><button type="button" data-family-id="monochrome" data-review-status="pass">pass</button><button type="button" data-family-id="monochrome" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="monochrome" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="monochrome">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="monochrome" placeholder="optional apply-script context" /></label></div></td><td><code>skills/lark-slides/references/visual-contracts/beautiful/monochrome.ledger-briefing.json</code><br><code>beautiful-html-templates/screenshots/monochrome-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/neo-grid-bold.html">neo-grid-bold</a></strong><br><small>dense-panel-grid</small></td><td>needs_review<br><small>default=false</small></td><td>12 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human_review_status=pending</small><br><small>promotion_action=no_change_until_human_pass</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><div class="review-control" data-review-control-for="neo-grid-bold"><div class="decision-buttons"><button type="button" data-family-id="neo-grid-bold" data-review-status="pass">pass</button><button type="button" data-family-id="neo-grid-bold" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="neo-grid-bold" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="neo-grid-bold">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="neo-grid-bold" placeholder="optional apply-script context" /></label></div></td><td><code>skills/lark-slides/references/visual-contracts/beautiful/neo-grid-bold.dense-panel-grid.json</code><br><code>beautiful-html-templates/screenshots/neo-grid-bold-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/peoples-platform.html">peoples-platform</a></strong><br><small>people-platform-manifesto</small></td><td>needs_review<br><small>default=false</small></td><td>10 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human_review_status=pending</small><br><small>promotion_action=no_change_until_human_pass</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing</td><td><div class="review-control" data-review-control-for="peoples-platform"><div class="decision-buttons"><button type="button" data-family-id="peoples-platform" data-review-status="pass">pass</button><button type="button" data-family-id="peoples-platform" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="peoples-platform" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="peoples-platform">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="peoples-platform" placeholder="optional apply-script context" /></label></div></td><td><code>skills/lark-slides/references/visual-contracts/beautiful/peoples-platform.people-platform-manifesto.json</code><br><code>beautiful-html-templates/screenshots/peoples-platform-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/pin-and-paper.html">pin-and-paper</a></strong><br><small>annotated-field-board</small></td><td>needs_review<br><small>default=false</small></td><td>11 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human_review_status=pending</small><br><small>promotion_action=no_change_until_human_pass</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><div class="review-control" data-review-control-for="pin-and-paper"><div class="decision-buttons"><button type="button" data-family-id="pin-and-paper" data-review-status="pass">pass</button><button type="button" data-family-id="pin-and-paper" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="pin-and-paper" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="pin-and-paper">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="pin-and-paper" placeholder="optional apply-script context" /></label></div></td><td><code>skills/lark-slides/references/visual-contracts/beautiful/pin-and-paper.annotated-field-board.json</code><br><code>beautiful-html-templates/screenshots/pin-and-paper-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/pink-script.html">pink-script</a></strong><br><small>pink-nocturne-feature</small></td><td>needs_review<br><small>default=false</small></td><td>9 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human_review_status=pending</small><br><small>promotion_action=no_change_until_human_pass</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><div class="review-control" data-review-control-for="pink-script"><div class="decision-buttons"><button type="button" data-family-id="pink-script" data-review-status="pass">pass</button><button type="button" data-family-id="pink-script" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="pink-script" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="pink-script">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="pink-script" placeholder="optional apply-script context" /></label></div></td><td><code>skills/lark-slides/references/visual-contracts/beautiful/pink-script.pink-nocturne-feature.json</code><br><code>beautiful-html-templates/screenshots/pink-script-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/playful.html">playful</a></strong><br><small>playful-indie-launch</small></td><td>needs_review<br><small>default=false</small></td><td>10 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human_review_status=pending</small><br><small>promotion_action=no_change_until_human_pass</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><div class="review-control" data-review-control-for="playful"><div class="decision-buttons"><button type="button" data-family-id="playful" data-review-status="pass">pass</button><button type="button" data-family-id="playful" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="playful" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="playful">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="playful" placeholder="optional apply-script context" /></label></div></td><td><code>skills/lark-slides/references/visual-contracts/beautiful/playful.playful-indie-launch.json</code><br><code>beautiful-html-templates/screenshots/playful-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/raw-grid.html">raw-grid</a></strong><br><small>brutalist-matrix</small></td><td>needs_review<br><small>default=false</small></td><td>10 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human_review_status=pending</small><br><small>promotion_action=no_change_until_human_pass</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><div class="review-control" data-review-control-for="raw-grid"><div class="decision-buttons"><button type="button" data-family-id="raw-grid" data-review-status="pass">pass</button><button type="button" data-family-id="raw-grid" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="raw-grid" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="raw-grid">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="raw-grid" placeholder="optional apply-script context" /></label></div></td><td><code>skills/lark-slides/references/visual-contracts/beautiful/raw-grid.brutalist-matrix.json</code><br><code>beautiful-html-templates/screenshots/raw-grid-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/retro-windows.html">retro-windows</a></strong><br><small>retro-ui-dashboard</small></td><td>needs_review<br><small>default=false</small></td><td>10 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human_review_status=pending</small><br><small>promotion_action=no_change_until_human_pass</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><div class="review-control" data-review-control-for="retro-windows"><div class="decision-buttons"><button type="button" data-family-id="retro-windows" data-review-status="pass">pass</button><button type="button" data-family-id="retro-windows" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="retro-windows" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="retro-windows">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="retro-windows" placeholder="optional apply-script context" /></label></div></td><td><code>skills/lark-slides/references/visual-contracts/beautiful/retro-windows.retro-ui-dashboard.json</code><br><code>beautiful-html-templates/screenshots/retro-windows-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/retro-zine.html">retro-zine</a></strong><br><small>retro-zine-spread</small></td><td>needs_review<br><small>default=false</small></td><td>10 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human_review_status=pending</small><br><small>promotion_action=no_change_until_human_pass</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><div class="review-control" data-review-control-for="retro-zine"><div class="decision-buttons"><button type="button" data-family-id="retro-zine" data-review-status="pass">pass</button><button type="button" data-family-id="retro-zine" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="retro-zine" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="retro-zine">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="retro-zine" placeholder="optional apply-script context" /></label></div></td><td><code>skills/lark-slides/references/visual-contracts/beautiful/retro-zine.retro-zine-spread.json</code><br><code>beautiful-html-templates/screenshots/retro-zine-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/sakura-chroma.html">sakura-chroma</a></strong><br><small>product-ribbon</small></td><td>needs_review<br><small>default=false</small></td><td>8 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human_review_status=pending</small><br><small>promotion_action=no_change_until_human_pass</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><div class="review-control" data-review-control-for="sakura-chroma"><div class="decision-buttons"><button type="button" data-family-id="sakura-chroma" data-review-status="pass">pass</button><button type="button" data-family-id="sakura-chroma" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="sakura-chroma" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="sakura-chroma">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="sakura-chroma" placeholder="optional apply-script context" /></label></div></td><td><code>skills/lark-slides/references/visual-contracts/beautiful/sakura-chroma.product-ribbon.json</code><br><code>beautiful-html-templates/screenshots/sakura-chroma-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/scatterbrain.html">scatterbrain</a></strong><br><small>sticky-workshop-board</small></td><td>needs_review<br><small>default=false</small></td><td>8 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human_review_status=pending</small><br><small>promotion_action=no_change_until_human_pass</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><div class="review-control" data-review-control-for="scatterbrain"><div class="decision-buttons"><button type="button" data-family-id="scatterbrain" data-review-status="pass">pass</button><button type="button" data-family-id="scatterbrain" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="scatterbrain" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="scatterbrain">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="scatterbrain" placeholder="optional apply-script context" /></label></div></td><td><code>skills/lark-slides/references/visual-contracts/beautiful/scatterbrain.sticky-workshop-board.json</code><br><code>beautiful-html-templates/screenshots/scatterbrain-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/signal.html">signal</a></strong><br><small>intelligence-brief</small></td><td>needs_review<br><small>default=false</small></td><td>18 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human_review_status=pending</small><br><small>promotion_action=no_change_until_human_pass</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing</td><td><div class="review-control" data-review-control-for="signal"><div class="decision-buttons"><button type="button" data-family-id="signal" data-review-status="pass">pass</button><button type="button" data-family-id="signal" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="signal" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="signal">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="signal" placeholder="optional apply-script context" /></label></div></td><td><code>skills/lark-slides/references/visual-contracts/beautiful/signal.intelligence-brief.json</code><br><code>beautiful-html-templates/screenshots/signal-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/soft-editorial.html">soft-editorial</a></strong><br><small>soft-editorial-feature</small></td><td>needs_review<br><small>default=false</small></td><td>12 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human_review_status=pending</small><br><small>promotion_action=no_change_until_human_pass</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><div class="review-control" data-review-control-for="soft-editorial"><div class="decision-buttons"><button type="button" data-family-id="soft-editorial" data-review-status="pass">pass</button><button type="button" data-family-id="soft-editorial" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="soft-editorial" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="soft-editorial">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="soft-editorial" placeholder="optional apply-script context" /></label></div></td><td><code>skills/lark-slides/references/visual-contracts/beautiful/soft-editorial.soft-editorial-feature.json</code><br><code>beautiful-html-templates/screenshots/soft-editorial-4.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/stencil-tablet.html">stencil-tablet</a></strong><br><small>stencil-field-manual</small></td><td>needs_review<br><small>default=false</small></td><td>11 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human_review_status=pending</small><br><small>promotion_action=no_change_until_human_pass</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><div class="review-control" data-review-control-for="stencil-tablet"><div class="decision-buttons"><button type="button" data-family-id="stencil-tablet" data-review-status="pass">pass</button><button type="button" data-family-id="stencil-tablet" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="stencil-tablet" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="stencil-tablet">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="stencil-tablet" placeholder="optional apply-script context" /></label></div></td><td><code>skills/lark-slides/references/visual-contracts/beautiful/stencil-tablet.stencil-field-manual.json</code><br><code>beautiful-html-templates/screenshots/stencil-tablet-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/studio.html">studio</a></strong><br><small>type-mass-poster</small></td><td>needs_review<br><small>default=false</small></td><td>12 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human_review_status=pending</small><br><small>promotion_action=no_change_until_human_pass</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><div class="review-control" data-review-control-for="studio"><div class="decision-buttons"><button type="button" data-family-id="studio" data-review-status="pass">pass</button><button type="button" data-family-id="studio" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="studio" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="studio">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="studio" placeholder="optional apply-script context" /></label></div></td><td><code>skills/lark-slides/references/visual-contracts/beautiful/studio.type-mass-poster.json</code><br><code>beautiful-html-templates/screenshots/studio-1.png</code></td></tr>
|
||||
<tr><td><strong><a href="families/vellum.html">vellum</a></strong><br><small>vellum-scholar-brief</small></td><td>needs_review<br><small>default=false</small></td><td>9 source<br><small>0 implemented</small></td><td><span class="badge bad">blocked</span><br><small>human_review_status=pending</small><br><small>promotion_action=no_change_until_human_pass</small></td><td>missing<br><small> rendered</small></td><td>passed</td><td>auto_gate_blocked, missing_smoke, page_family_smoke_missing_or_failed, production_review_pending, quality_gate_integration_pending, selector_gate_missing, source_core_roles_missing</td><td><div class="review-control" data-review-control-for="vellum"><div class="decision-buttons"><button type="button" data-family-id="vellum" data-review-status="pass">pass</button><button type="button" data-family-id="vellum" data-review-status="needs_fix">needs_fix</button><button type="button" data-family-id="vellum" data-review-status="reject">reject</button></div><div class="review-current">Selected: <strong data-review-current-for="vellum">pending</strong></div><label class="notes-label">Notes <input type="text" data-review-notes-for="vellum" placeholder="optional apply-script context" /></label></div></td><td><code>skills/lark-slides/references/visual-contracts/beautiful/vellum.vellum-scholar-brief.json</code><br><code>beautiful-html-templates/screenshots/vellum-1.png</code></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<script>
|
||||
(function () {
|
||||
var storageKey = "beautiful-production-review-decisions-v1";
|
||||
var schemaVersion = "svglide-beautiful-human-review-decisions/v1";
|
||||
var reviewBatchId = "beautiful-34";
|
||||
var receiptPath = "skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json";
|
||||
var pendingHumanReviewStatus = "pending";
|
||||
var promotionAction = "no_change_until_human_pass";
|
||||
|
||||
function readState() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
||||
if (parsed && typeof parsed === "object" && parsed.decisions && typeof parsed.decisions === "object") {
|
||||
return parsed;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore malformed local state and rebuild below.
|
||||
}
|
||||
return { decisions: {} };
|
||||
}
|
||||
|
||||
function writeState(state) {
|
||||
localStorage.setItem(storageKey, JSON.stringify(state));
|
||||
}
|
||||
|
||||
function buildExport(state) {
|
||||
var decisions = Object.keys(state.decisions || {}).sort().map(function (familyId) {
|
||||
return state.decisions[familyId];
|
||||
});
|
||||
return {
|
||||
schema_version: schemaVersion,
|
||||
artifact_kind: "beautiful_template_human_review_decisions",
|
||||
review_batch_id: reviewBatchId,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
not_promotion_receipt: true,
|
||||
policy: {
|
||||
does_not_automatically_modify_production_default: true,
|
||||
apply_script_must_validate_gallery_receipt: true
|
||||
},
|
||||
decisions: decisions
|
||||
};
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.querySelectorAll("[data-review-current-for]").forEach(function (node) {
|
||||
var familyId = node.getAttribute("data-review-current-for");
|
||||
var decision = state.decisions[familyId];
|
||||
node.textContent = decision ? decision.review_status : "pending";
|
||||
});
|
||||
document.querySelectorAll("[data-review-status]").forEach(function (button) {
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var decision = state.decisions[familyId];
|
||||
button.classList.toggle("selected", Boolean(decision && decision.review_status === status));
|
||||
});
|
||||
document.querySelectorAll("[data-review-notes-for]").forEach(function (input) {
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var decision = state.decisions[familyId];
|
||||
if (decision && input.value !== decision.notes) {
|
||||
input.value = decision.notes || "";
|
||||
}
|
||||
});
|
||||
var textarea = document.getElementById("review-decisions-json");
|
||||
if (textarea) {
|
||||
textarea.value = JSON.stringify(buildExport(state), null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
var button = event.target.closest("[data-review-status]");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var existing = state.decisions[familyId] || {};
|
||||
state.decisions[familyId] = {
|
||||
family_id: familyId,
|
||||
review_status: status,
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
notes: existing.notes || "",
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
document.addEventListener("input", function (event) {
|
||||
var input = event.target.closest("[data-review-notes-for]");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var existing = state.decisions[familyId] || {
|
||||
family_id: familyId,
|
||||
review_status: "needs_fix",
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
existing.notes = input.value;
|
||||
existing.updated_at = new Date().toISOString();
|
||||
state.decisions[familyId] = existing;
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
render(readState());
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/8-bit-orbit.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "86070d51ad2d5f1cef0438e4d5505c160c16f3f5b701a0ef17a950f13f520f19"
|
||||
"sha256": "6700d6ce17310762eeb43dec97eee6a0c706da5ab7082cdf6c0d0dda83a2453d"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "86070d51ad2d5f1cef0438e4d5505c160c16f3f5b701a0ef17a950f13f520f19",
|
||||
"contact_sheet": "6700d6ce17310762eeb43dec97eee6a0c706da5ab7082cdf6c0d0dda83a2453d",
|
||||
"fidelity_receipt": "31bab9cafb1fabb4453980f01a8255d16c9a79e1f882d01585b319dee779d556",
|
||||
"reference_screenshot": "c1f0517225fbe17807d69de03a7260881738d25bc456bd4151af67fabbb15281",
|
||||
"smoke_receipt": null,
|
||||
@@ -1256,11 +1256,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/biennale-yellow.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "d0b40a3bfc2420a4c9c8b4c9baaf3cdf08c204a8e504d0917f1458a9b90e01e8"
|
||||
"sha256": "1c72a9c2b36088f74069f44fc0226aff8002f0b3507243531da6edf96ae4aff7"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "d0b40a3bfc2420a4c9c8b4c9baaf3cdf08c204a8e504d0917f1458a9b90e01e8",
|
||||
"contact_sheet": "1c72a9c2b36088f74069f44fc0226aff8002f0b3507243531da6edf96ae4aff7",
|
||||
"fidelity_receipt": "27b20213513d6a895ae84c07aea6d784f5acd5a5fcd4b5a6baf0d1868f4a7dfe",
|
||||
"reference_screenshot": "8acd74e991ff533d6982f60fc2934ad2020d5ea8e03c5d79d00c24899d6f9e8d",
|
||||
"smoke_receipt": null,
|
||||
@@ -2265,11 +2265,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/block-frame.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "e1eebb164177c32de707e461d85253b10fd4789cddd64ec87f390779f2b69802"
|
||||
"sha256": "cfd16fda1c5b8104b5e6f3c990b3fc2d2b829f79deaea3dae5cb1157444ea9e6"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "e1eebb164177c32de707e461d85253b10fd4789cddd64ec87f390779f2b69802",
|
||||
"contact_sheet": "cfd16fda1c5b8104b5e6f3c990b3fc2d2b829f79deaea3dae5cb1157444ea9e6",
|
||||
"fidelity_receipt": "e35a3eb5441b55568413e926f2275e9593c0b01d95a4345337995c995ffffd95",
|
||||
"reference_screenshot": "3fd1774d38f1bfbda05df46fc7f2b98a1780de45ced4d71f4925136bbf2460a0",
|
||||
"smoke_receipt": null,
|
||||
@@ -3514,11 +3514,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/blue-professional.html",
|
||||
"render_status": "passed",
|
||||
"sha256": "28d5646879b9daf6f8841e968e2337c2dceb316feea8bd83ae416ae65f54a7d2"
|
||||
"sha256": "315b18dd7cd44f6cb18061c82b58a74a54c88ca797b93232011edb322653e51b"
|
||||
},
|
||||
"default_selectable": true,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "28d5646879b9daf6f8841e968e2337c2dceb316feea8bd83ae416ae65f54a7d2",
|
||||
"contact_sheet": "315b18dd7cd44f6cb18061c82b58a74a54c88ca797b93232011edb322653e51b",
|
||||
"fidelity_receipt": "f6a4a0a015c09f14cb9e987f69734cbb05a06e79bba9c9b1ba2ca16ed6bc597a",
|
||||
"reference_screenshot": "0f08aefe70cb14ca7f3126ecc2f34319ca8f281ecdf81c6d6486ea93b2236f8c",
|
||||
"smoke_receipt": "ae3cfa9a3ba970c0f4d6903148d7291375019dd3d12a8c3619599c5520742804",
|
||||
@@ -4889,11 +4889,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/bold-poster.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "55b5c1c1fb0a11183ee0779e02f4a374cb989adceb4e3999f754dcf815f2e161"
|
||||
"sha256": "17a715b8c3cab33d9e80c8abbbd902fa00ae702f63a86ad87fa0bdeb68913433"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "55b5c1c1fb0a11183ee0779e02f4a374cb989adceb4e3999f754dcf815f2e161",
|
||||
"contact_sheet": "17a715b8c3cab33d9e80c8abbbd902fa00ae702f63a86ad87fa0bdeb68913433",
|
||||
"fidelity_receipt": "5cb7f128615cbb801b3e66df177a5c1d61b3339c92cba3a04b9db00aadce0635",
|
||||
"reference_screenshot": "95a9351619463053bda29bdf472702ed4bc650a4510fa6b3cfcc34d5e3ba79b1",
|
||||
"smoke_receipt": null,
|
||||
@@ -6102,11 +6102,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/broadside.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "3f823b2d1e5a98af40443c0f04c5180e2d40c0ae8dab5a5b5c81f80494298822"
|
||||
"sha256": "db1ffb89fb710b18e5e23c50bd04a5c500bea3a9602bc7148def1cd9b712572c"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "3f823b2d1e5a98af40443c0f04c5180e2d40c0ae8dab5a5b5c81f80494298822",
|
||||
"contact_sheet": "db1ffb89fb710b18e5e23c50bd04a5c500bea3a9602bc7148def1cd9b712572c",
|
||||
"fidelity_receipt": "fd3c0b8d0ae82ecad0cbeb13974361d5bf8f9e76083619edf5a88d77b0b5f664",
|
||||
"reference_screenshot": "96805bd67e4502f94b078b723d252717183fe8eb34f2eb529c44b772b4dcdce4",
|
||||
"smoke_receipt": null,
|
||||
@@ -7935,11 +7935,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/capsule.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "35b0d6c1d01dd97448bcf50981754d1f0155439b4431efeeaa2b9d4208f7378f"
|
||||
"sha256": "b89c818def92fdd5638e4d0c343bdfd8a1ae201087c5701f9740e66d21d41636"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "35b0d6c1d01dd97448bcf50981754d1f0155439b4431efeeaa2b9d4208f7378f",
|
||||
"contact_sheet": "b89c818def92fdd5638e4d0c343bdfd8a1ae201087c5701f9740e66d21d41636",
|
||||
"fidelity_receipt": "38ef8db0e9fdaf4d3c4f83f3b9ab1a2c956661315784c6090c301faac93f2f8c",
|
||||
"reference_screenshot": "468b1b618668660274e7a46a528d0a323fb926c3e47f7e5895ec03189efd35b3",
|
||||
"smoke_receipt": null,
|
||||
@@ -9162,11 +9162,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/cartesian.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "c1f6795edcce9b5f104edd8f19b1674ceee66b19b905b330f20f1328fde6baa4"
|
||||
"sha256": "3a68f9f0984b0c0dcd526bfb1bd7deec743e293c739d09529d31ec8dc31c548d"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "c1f6795edcce9b5f104edd8f19b1674ceee66b19b905b330f20f1328fde6baa4",
|
||||
"contact_sheet": "3a68f9f0984b0c0dcd526bfb1bd7deec743e293c739d09529d31ec8dc31c548d",
|
||||
"fidelity_receipt": "d7bec45b7684b8ab2e98755e76624fffdf5048fd864aa64d7092aeb6aba3a62d",
|
||||
"reference_screenshot": "59af0f5ee20b85f07ada82a1d6bb8ab5e69b81bb08b5abf2a7520eca4934e93e",
|
||||
"smoke_receipt": null,
|
||||
@@ -10307,11 +10307,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/cobalt-grid.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "f9970bf563b9fc18a08f6617c1a1769cbc8cebd4ec98dcf042c1be12398c8f46"
|
||||
"sha256": "4fd837a9e9c7fc3da874f451915c9942f7c35b2f179f07986e2523c8fb0e2e9f"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "f9970bf563b9fc18a08f6617c1a1769cbc8cebd4ec98dcf042c1be12398c8f46",
|
||||
"contact_sheet": "4fd837a9e9c7fc3da874f451915c9942f7c35b2f179f07986e2523c8fb0e2e9f",
|
||||
"fidelity_receipt": "fd2b394777733364723f20d0d732a346f93edba0a748628ce9a1e5596726cb02",
|
||||
"reference_screenshot": "e85989914eb7ca3bb279e03cc792df19c5d06f8d3ba0e59515211164fca5ae2d",
|
||||
"smoke_receipt": null,
|
||||
@@ -11332,11 +11332,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/coral.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "402b5732bbb22f8145a73ec00176e0653a5f2744245bf10ec9ea757f8b6c1e70"
|
||||
"sha256": "b47a477b472ff5e219ff685d2fd247587ea389cdbd726d2276ffabbbfebf5403"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "402b5732bbb22f8145a73ec00176e0653a5f2744245bf10ec9ea757f8b6c1e70",
|
||||
"contact_sheet": "b47a477b472ff5e219ff685d2fd247587ea389cdbd726d2276ffabbbfebf5403",
|
||||
"fidelity_receipt": "dd795f5b763b8b5769e173a07ba63f2a2da2345fefaf96cb48989b7a5ba4ef2c",
|
||||
"reference_screenshot": "3cce11542e0c380396c14d2e7ac7406af704af163e7ba85b8ce9e2fdf7d12015",
|
||||
"smoke_receipt": null,
|
||||
@@ -12559,11 +12559,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/creative-mode.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "224db100187b471bfeb2b4d38360dc8efa283251be6ebf174da10d74700b080e"
|
||||
"sha256": "d25bb924c36879bf68e1282a46c1818b201962ec80ad0d845a1b2bef6d5b2292"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "224db100187b471bfeb2b4d38360dc8efa283251be6ebf174da10d74700b080e",
|
||||
"contact_sheet": "d25bb924c36879bf68e1282a46c1818b201962ec80ad0d845a1b2bef6d5b2292",
|
||||
"fidelity_receipt": "51de4317d40671c7a4ba0868cacfa3c86ca2de0d14eecb8d07177f6c53506acf",
|
||||
"reference_screenshot": "aaac87da4e7f0e1e294f8f3d88616b067174687f4b89dafcad0acb4b967e9633",
|
||||
"smoke_receipt": null,
|
||||
@@ -13571,11 +13571,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/daisy-days.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "60ae07dae1e5cb86fbefc0ffb62eb9bdf8c371f121793ad9d9e4cee23c993443"
|
||||
"sha256": "4df7e9d7a65b8e6749d3e487481302defbcfb6d0efd98fc00bb5afc6921e20cc"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "60ae07dae1e5cb86fbefc0ffb62eb9bdf8c371f121793ad9d9e4cee23c993443",
|
||||
"contact_sheet": "4df7e9d7a65b8e6749d3e487481302defbcfb6d0efd98fc00bb5afc6921e20cc",
|
||||
"fidelity_receipt": "926bc15a8016d24e25c00a42eb878578dbb825471d6ba2abc316bf48016ab5bc",
|
||||
"reference_screenshot": "65f6615ff2ec51a3d4a77573c2a53471b356724a58bd33dffdb55ed69ab2b73b",
|
||||
"smoke_receipt": null,
|
||||
@@ -14715,11 +14715,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/editorial-forest.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "6966fb4b3014525f5b221bd6ad46a06c7f98b2046882f23d9a96c35876453e30"
|
||||
"sha256": "a72d3845093b54b819d538e7549951871fe1cb07d991b6eb84b48b2a398c653f"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "6966fb4b3014525f5b221bd6ad46a06c7f98b2046882f23d9a96c35876453e30",
|
||||
"contact_sheet": "a72d3845093b54b819d538e7549951871fe1cb07d991b6eb84b48b2a398c653f",
|
||||
"fidelity_receipt": "64abadb7a840271a45d482c1f3a7e8f4e75909ac007ef2c13d4ac0f77c77fdaf",
|
||||
"reference_screenshot": "a081f3b16a3dd72dd16d9fdfcf30aa61cf66c79c865189eb380d22bd425c2a1c",
|
||||
"smoke_receipt": null,
|
||||
@@ -15732,11 +15732,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/editorial-tri-tone.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "ba27daa57e94914e24e341b6a8ae1d7434dfb715f5bc6a54643173865839fb10"
|
||||
"sha256": "dfa4ea5c54fbd6428d4c98cba1707e4e7a6fa3f11b74dc8879c25305b20ca07f"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "ba27daa57e94914e24e341b6a8ae1d7434dfb715f5bc6a54643173865839fb10",
|
||||
"contact_sheet": "dfa4ea5c54fbd6428d4c98cba1707e4e7a6fa3f11b74dc8879c25305b20ca07f",
|
||||
"fidelity_receipt": "5bf44805d7dc674b07da8f0ac8f0a749bfc78893371e921567db82e5bf3a251b",
|
||||
"reference_screenshot": "0b89022af5bfcc26356b7bdb48156510ba16b643e9bc01027ae8197092ead507",
|
||||
"smoke_receipt": null,
|
||||
@@ -16765,11 +16765,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/emerald-editorial.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "e082713ef62b3a90e195a07823726c77e4909aaed1cde7ca7b57b4b888860833"
|
||||
"sha256": "ae8042a321313b12a03e9b25379c89544421c4a9e8886b08f87990638f02d7da"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "e082713ef62b3a90e195a07823726c77e4909aaed1cde7ca7b57b4b888860833",
|
||||
"contact_sheet": "ae8042a321313b12a03e9b25379c89544421c4a9e8886b08f87990638f02d7da",
|
||||
"fidelity_receipt": "7aa06118b44f3dcc6202b56e64ec03134f5487d3e48a25279a9ccfeb09c1c81b",
|
||||
"reference_screenshot": "fda35bb4c4810369a5c5bccd70cbcd9d474691027c79a0d94ebf59dbf673c150",
|
||||
"smoke_receipt": null,
|
||||
@@ -17798,11 +17798,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/grove.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "35333c79ea1ad148e7763b55a6d5886dae6c077cd65c49430a954e69d5997eb7"
|
||||
"sha256": "da6b1ce28c3ae75ea17159bc4a656369fc659bdbfcff3b953aa9ac3ca4c74e28"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "35333c79ea1ad148e7763b55a6d5886dae6c077cd65c49430a954e69d5997eb7",
|
||||
"contact_sheet": "da6b1ce28c3ae75ea17159bc4a656369fc659bdbfcff3b953aa9ac3ca4c74e28",
|
||||
"fidelity_receipt": "72a5d983bb922049b536f086eedb89d0e3a7959b72480aab5fcfce63842d7455",
|
||||
"reference_screenshot": "6a01598d4b183837b96c698eb9453962fea4bea072a431ee4d71aef6e09da3eb",
|
||||
"smoke_receipt": null,
|
||||
@@ -19256,11 +19256,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/long-table.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "03eff66d27ff955a40c9ff4fda6f840251594bcaa9698d1452cc3527118a7317"
|
||||
"sha256": "451fb96587eb1e8dad65a4e7e34a40c7f81ce178256f9e61f72fb57090c4c61a"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "03eff66d27ff955a40c9ff4fda6f840251594bcaa9698d1452cc3527118a7317",
|
||||
"contact_sheet": "451fb96587eb1e8dad65a4e7e34a40c7f81ce178256f9e61f72fb57090c4c61a",
|
||||
"fidelity_receipt": "96948f5547801870efb639d755ee4b944114cd0925c3fd03f6d15cafe935119e",
|
||||
"reference_screenshot": "79f7956399971a6038c6b98ba7850b8d232c593bafb1c484c7127e5d3fd60bba",
|
||||
"smoke_receipt": null,
|
||||
@@ -20277,11 +20277,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/mat.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "80cc3f0b8990075017711519795bc91a6a73eb5e748ec350fcf1dbbec092738f"
|
||||
"sha256": "45c1a37544d752c06e326d5789a8ad1a51ba2a7926e27db048490526898423b4"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "80cc3f0b8990075017711519795bc91a6a73eb5e748ec350fcf1dbbec092738f",
|
||||
"contact_sheet": "45c1a37544d752c06e326d5789a8ad1a51ba2a7926e27db048490526898423b4",
|
||||
"fidelity_receipt": "e1e95e38f4ea8124a378b7de4a0eb81593f192811ea42e7b31085ed84410cf34",
|
||||
"reference_screenshot": "acac0ac30af8fbb206adfb6810573c72d3ca96b00293f9f850fdeefed1ae11dc",
|
||||
"smoke_receipt": null,
|
||||
@@ -21421,11 +21421,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/monochrome.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "98ff05a96dc1ba8c6d1567cdc05e07d956cf6c4d8acb8ff95ec73df343d9e6d7"
|
||||
"sha256": "3d2584d894dc76b41f1abd78da0a0dba991a1b9cbc6e63672bb9cb45f75418a1"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "98ff05a96dc1ba8c6d1567cdc05e07d956cf6c4d8acb8ff95ec73df343d9e6d7",
|
||||
"contact_sheet": "3d2584d894dc76b41f1abd78da0a0dba991a1b9cbc6e63672bb9cb45f75418a1",
|
||||
"fidelity_receipt": "7fd4a1a4f9929a0add47861c0f489f80b3cfe4dd9e91dc13014ec264811c78c5",
|
||||
"reference_screenshot": "bac6b00bf1d0b3c97b19d2a0c45edf44af5cbf369f2cf3ebe78a207a7b6b8c7b",
|
||||
"smoke_receipt": null,
|
||||
@@ -23264,11 +23264,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/neo-grid-bold.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "ceebdd152351e3d9124f365de2ea46b5b03bd90f8ca532d7f99f79bc29cfd95d"
|
||||
"sha256": "dfdb0c6be0e75f49ecd5d5a782eff136bb25cc679bfbfd17540b9aa47d14356e"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "ceebdd152351e3d9124f365de2ea46b5b03bd90f8ca532d7f99f79bc29cfd95d",
|
||||
"contact_sheet": "dfdb0c6be0e75f49ecd5d5a782eff136bb25cc679bfbfd17540b9aa47d14356e",
|
||||
"fidelity_receipt": "9d0ced3d64a642e028edf86ff6457c36def39175b3079fff6a4c97b645803228",
|
||||
"reference_screenshot": "c53ba5da0f1b85b23ad1975da65edafaee84f029f06c468b2fbd036031ce15e5",
|
||||
"smoke_receipt": null,
|
||||
@@ -24692,11 +24692,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/peoples-platform.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "6cde51c31f47436c3b5b6db4fbaccb4181b795fb84213c6a1e0ace77cd88eb66"
|
||||
"sha256": "35f74a4093000ea952bfbfef2a211fd0d47f6c926ecbc6cb6fc95a07f3946acf"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "6cde51c31f47436c3b5b6db4fbaccb4181b795fb84213c6a1e0ace77cd88eb66",
|
||||
"contact_sheet": "35f74a4093000ea952bfbfef2a211fd0d47f6c926ecbc6cb6fc95a07f3946acf",
|
||||
"fidelity_receipt": "679368f5526815a2cb311d583f0f86871000639c85643e6b47099ab91566d5cc",
|
||||
"reference_screenshot": "9a0c40acaa0fb9c058745cbd16c875f9b7a0417d46c6c37dede388e32cf52d25",
|
||||
"smoke_receipt": null,
|
||||
@@ -25918,11 +25918,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/pin-and-paper.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "d3300e5df932d79e82fd0853a9af8c252aa090d1e1df988d77b4d1045ca63002"
|
||||
"sha256": "063652158d00662045c6a94a70a8e7ae36f00aabf3ea5216463e7f8c6564256a"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "d3300e5df932d79e82fd0853a9af8c252aa090d1e1df988d77b4d1045ca63002",
|
||||
"contact_sheet": "063652158d00662045c6a94a70a8e7ae36f00aabf3ea5216463e7f8c6564256a",
|
||||
"fidelity_receipt": "b6aa5696947e5fc7fcd633c340cea26e983956f97a0a54b72eb035818d6a3d76",
|
||||
"reference_screenshot": "35ff94a10d71d18318fa11e1c95fb6a32e2b1801ffff24ccc8e0f36afe187387",
|
||||
"smoke_receipt": null,
|
||||
@@ -27274,11 +27274,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/pink-script.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "b0b78d2776184009efaedb026d3c5dc4528a29f8fba7d7b6c5da4618fbd42497"
|
||||
"sha256": "be97ade117aa12ee9ffcd562c2e2f905076db7c4ba21ebbc3efa92b4aa0890ae"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "b0b78d2776184009efaedb026d3c5dc4528a29f8fba7d7b6c5da4618fbd42497",
|
||||
"contact_sheet": "be97ade117aa12ee9ffcd562c2e2f905076db7c4ba21ebbc3efa92b4aa0890ae",
|
||||
"fidelity_receipt": "ff075c2947f7c09785c47c57f68d995722873676d91251a822747e0b096b88bf",
|
||||
"reference_screenshot": "d39af58b620fe59ab0e28db0f070fd6e13214896115aa984be069369ef594ff7",
|
||||
"smoke_receipt": null,
|
||||
@@ -28400,11 +28400,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/playful.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "8c06c02b5802f957b497d1332e8cb0ab3d3a2c1825f551c946d00c38244aadad"
|
||||
"sha256": "dce30937bc181379275aeb74ef278b312b7cbceea99f2e2522aaefe6d6f16878"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "8c06c02b5802f957b497d1332e8cb0ab3d3a2c1825f551c946d00c38244aadad",
|
||||
"contact_sheet": "dce30937bc181379275aeb74ef278b312b7cbceea99f2e2522aaefe6d6f16878",
|
||||
"fidelity_receipt": "e828f367dda5704dca8c804fb833051e8e3888202e9b76169082ac50164873d8",
|
||||
"reference_screenshot": "75c22cf0736c2c349599de769e984af4e55440dbf83fb4abac35e5c0842abe81",
|
||||
"smoke_receipt": null,
|
||||
@@ -29637,11 +29637,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/raw-grid.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "87221867c254043e20ca653260daa52ccb0f88492fe1fc5595db51edb2d5c87a"
|
||||
"sha256": "0fc408b566d5f90530b8afb2e380258a3d6013f7ed2089e4b53921eb49d97c57"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "87221867c254043e20ca653260daa52ccb0f88492fe1fc5595db51edb2d5c87a",
|
||||
"contact_sheet": "0fc408b566d5f90530b8afb2e380258a3d6013f7ed2089e4b53921eb49d97c57",
|
||||
"fidelity_receipt": "fee9ac2b5c6d69612a2a082849f1829f5b3c75f2a5c2d29b76657361f4fc04cc",
|
||||
"reference_screenshot": "4056c85b9415ba7a9a988d45f5316cbdfbaf18ee959e3f7727e2ef90f59f42bc",
|
||||
"smoke_receipt": null,
|
||||
@@ -30871,11 +30871,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/retro-windows.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "847e69a200f8f595339c4816826ed87853faf0a4fc468a6b0672f6f2946cf8a3"
|
||||
"sha256": "599e3dad5711c9a858067f8ce03036d104d9b8a01cc12c9eef04e7efd5550437"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "847e69a200f8f595339c4816826ed87853faf0a4fc468a6b0672f6f2946cf8a3",
|
||||
"contact_sheet": "599e3dad5711c9a858067f8ce03036d104d9b8a01cc12c9eef04e7efd5550437",
|
||||
"fidelity_receipt": "d9f718418fe0cba65d03c26230b5655764011c1197b9b52cb3ab15b0787cd8b6",
|
||||
"reference_screenshot": "8d9fc0a05ab025310cc35f15c2d3b2de629c79a49df9fe1c7d63b2f7b8a00543",
|
||||
"smoke_receipt": null,
|
||||
@@ -32133,11 +32133,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/retro-zine.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "5328e4b636054dbd363032e7fdb7fea6f0b31eb39d87215ffb4badae2fe02a97"
|
||||
"sha256": "2461333873da620b3c97e88c9ad80c1814ed28433cbc211c781f4999b1a62833"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "5328e4b636054dbd363032e7fdb7fea6f0b31eb39d87215ffb4badae2fe02a97",
|
||||
"contact_sheet": "2461333873da620b3c97e88c9ad80c1814ed28433cbc211c781f4999b1a62833",
|
||||
"fidelity_receipt": "70330ed527a665653b1934d49e3ad5f14e2f4f866de429f38615ca98f18657ba",
|
||||
"reference_screenshot": "bd93d862d934f00253a36df8f03f4aef74f87fb1b0f870c777002b39ae7f2af9",
|
||||
"smoke_receipt": null,
|
||||
@@ -33343,11 +33343,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/sakura-chroma.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "2f4e9111d34cafd0344975f49c5a1d13c3ab8732ac520107a9d0f060b0486108"
|
||||
"sha256": "fd7eb1ddf9e58fcdabc02eb17dd814491227a3ac00a735bfd8b4d7065c482bcf"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "2f4e9111d34cafd0344975f49c5a1d13c3ab8732ac520107a9d0f060b0486108",
|
||||
"contact_sheet": "fd7eb1ddf9e58fcdabc02eb17dd814491227a3ac00a735bfd8b4d7065c482bcf",
|
||||
"fidelity_receipt": "01ed753670341664ee282238d30060766dba929200e59bb279b31497ec8af736",
|
||||
"reference_screenshot": "92bae8fc25051d0dbbb648f931befbfb653cbc331e876ea5e5aaf76afbad0733",
|
||||
"smoke_receipt": null,
|
||||
@@ -34344,11 +34344,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/scatterbrain.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "4cf01462c6953780cc59a29d83f051278e5315763f9365240abc3138c204eca2"
|
||||
"sha256": "5a5157baf391062f4ed34e0bde225c820785e216e69b9e7af3d7c460ffdb0c80"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "4cf01462c6953780cc59a29d83f051278e5315763f9365240abc3138c204eca2",
|
||||
"contact_sheet": "5a5157baf391062f4ed34e0bde225c820785e216e69b9e7af3d7c460ffdb0c80",
|
||||
"fidelity_receipt": "8f986c32012e5a26fff7d1e4b2c73fb73db59885a7bb3f8ba7fc7f1f0cfd927f",
|
||||
"reference_screenshot": "c2ed8f8d89fd124c65976fa3ece9b153afe4f4542d95880c367922bb88d910ca",
|
||||
"smoke_receipt": null,
|
||||
@@ -35389,11 +35389,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/signal.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "ab533fc6ac798c710cc537d93a18e247830e183fa813ce2a5ee08a582272c1e1"
|
||||
"sha256": "c00894a3fff05448914443bf4fec131fcd6ca87b0ed2aabce5a9f239f3e4082a"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "ab533fc6ac798c710cc537d93a18e247830e183fa813ce2a5ee08a582272c1e1",
|
||||
"contact_sheet": "c00894a3fff05448914443bf4fec131fcd6ca87b0ed2aabce5a9f239f3e4082a",
|
||||
"fidelity_receipt": "f33e1fed9d3fe80ed000386d4649be14d1120ea455b57d33b8d97a87d2769231",
|
||||
"reference_screenshot": "ca5487dc68264f209951400c5edddb93c4ae1fc7174b88c2b3dc54a82e0be64a",
|
||||
"smoke_receipt": null,
|
||||
@@ -37437,11 +37437,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/soft-editorial.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "64eec701c1883f956200f4c07c18bb893e15272505132a612b554a942026bcee"
|
||||
"sha256": "f377bd08e444ba86e0ebb24b2b6fb6147a292402479d5854424ad483450e6aa3"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "64eec701c1883f956200f4c07c18bb893e15272505132a612b554a942026bcee",
|
||||
"contact_sheet": "f377bd08e444ba86e0ebb24b2b6fb6147a292402479d5854424ad483450e6aa3",
|
||||
"fidelity_receipt": "a7543b7f841153c3dd8d182b0c43d5d3688dc128b4da2f392cb41ee20d275ff3",
|
||||
"reference_screenshot": "3e37602cf749a0a383ef0f0a1f25db85e9633da1d74bafc2be76a91b004a866b",
|
||||
"smoke_receipt": null,
|
||||
@@ -38856,11 +38856,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/stencil-tablet.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "761d7d2063337a41bb0058766d75ed1d470584c07569ea68930e42ec37d2630a"
|
||||
"sha256": "ca62bc4d64abeff11aafb248051fe51438501c1f6c3b486a414fc05d1c05c4c8"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "761d7d2063337a41bb0058766d75ed1d470584c07569ea68930e42ec37d2630a",
|
||||
"contact_sheet": "ca62bc4d64abeff11aafb248051fe51438501c1f6c3b486a414fc05d1c05c4c8",
|
||||
"fidelity_receipt": "bf32692b17d20d5a20c9c87ac02226c93739131b38f83c7f3b452a14451128fd",
|
||||
"reference_screenshot": "b8321134113e99f90a0e17e44e326ab25e64f3735150dd82269e0b2daabaaa2b",
|
||||
"smoke_receipt": null,
|
||||
@@ -40215,11 +40215,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/studio.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "2e5c78fc922e036219c15f98dc9608883d9013cda1c3e1b0f9f31d5d0bb8bbd6"
|
||||
"sha256": "d05050e509a7940a4893fbda99624438c1130317d811140d6337fdecb6357b94"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "2e5c78fc922e036219c15f98dc9608883d9013cda1c3e1b0f9f31d5d0bb8bbd6",
|
||||
"contact_sheet": "d05050e509a7940a4893fbda99624438c1130317d811140d6337fdecb6357b94",
|
||||
"fidelity_receipt": "95baeec998aed196a738e4491cc7cab3ad34dbca2c3d5e96a94943f62075f60c",
|
||||
"reference_screenshot": "0d7c0646a85c56b4b26e09f0cf8a0b658fe0b1cf36be38255900fd259d0c42d4",
|
||||
"smoke_receipt": null,
|
||||
@@ -41649,11 +41649,11 @@
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
"html_path": "families/vellum.html",
|
||||
"render_status": "missing_smoke",
|
||||
"sha256": "d1cba07fdba73ba6d0b49076d091f1fba3e299f86f44d1bab7d2c2836b26551f"
|
||||
"sha256": "ceadac634245686ba842f84a704d927fb688127f0c14b60eece6d7daa3805c10"
|
||||
},
|
||||
"default_selectable": false,
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "d1cba07fdba73ba6d0b49076d091f1fba3e299f86f44d1bab7d2c2836b26551f",
|
||||
"contact_sheet": "ceadac634245686ba842f84a704d927fb688127f0c14b60eece6d7daa3805c10",
|
||||
"fidelity_receipt": "3152f66c029a0f4be72c43d417b2aec470b483239a8070136e5b87993e57ae68",
|
||||
"reference_screenshot": "8c99c96677fec3c94235098b8fe36b9beeefd31ebfd173989f0ce358d91c4b73",
|
||||
"smoke_receipt": null,
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
],
|
||||
"auto_gate_status": "blocked",
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "86070d51ad2d5f1cef0438e4d5505c160c16f3f5b701a0ef17a950f13f520f19",
|
||||
"contact_sheet": "6700d6ce17310762eeb43dec97eee6a0c706da5ab7082cdf6c0d0dda83a2453d",
|
||||
"fidelity_receipt": "31bab9cafb1fabb4453980f01a8255d16c9a79e1f882d01585b319dee779d556",
|
||||
"reference_screenshot": "c1f0517225fbe17807d69de03a7260881738d25bc456bd4151af67fabbb15281",
|
||||
"smoke_receipt": null,
|
||||
@@ -51,7 +51,7 @@
|
||||
],
|
||||
"auto_gate_status": "blocked",
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "d0b40a3bfc2420a4c9c8b4c9baaf3cdf08c204a8e504d0917f1458a9b90e01e8",
|
||||
"contact_sheet": "1c72a9c2b36088f74069f44fc0226aff8002f0b3507243531da6edf96ae4aff7",
|
||||
"fidelity_receipt": "27b20213513d6a895ae84c07aea6d784f5acd5a5fcd4b5a6baf0d1868f4a7dfe",
|
||||
"reference_screenshot": "8acd74e991ff533d6982f60fc2934ad2020d5ea8e03c5d79d00c24899d6f9e8d",
|
||||
"smoke_receipt": null,
|
||||
@@ -93,7 +93,7 @@
|
||||
],
|
||||
"auto_gate_status": "blocked",
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "e1eebb164177c32de707e461d85253b10fd4789cddd64ec87f390779f2b69802",
|
||||
"contact_sheet": "cfd16fda1c5b8104b5e6f3c990b3fc2d2b829f79deaea3dae5cb1157444ea9e6",
|
||||
"fidelity_receipt": "e35a3eb5441b55568413e926f2275e9593c0b01d95a4345337995c995ffffd95",
|
||||
"reference_screenshot": "3fd1774d38f1bfbda05df46fc7f2b98a1780de45ced4d71f4925136bbf2460a0",
|
||||
"smoke_receipt": null,
|
||||
@@ -135,7 +135,7 @@
|
||||
],
|
||||
"auto_gate_status": "passed",
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "28d5646879b9daf6f8841e968e2337c2dceb316feea8bd83ae416ae65f54a7d2",
|
||||
"contact_sheet": "315b18dd7cd44f6cb18061c82b58a74a54c88ca797b93232011edb322653e51b",
|
||||
"fidelity_receipt": "f6a4a0a015c09f14cb9e987f69734cbb05a06e79bba9c9b1ba2ca16ed6bc597a",
|
||||
"reference_screenshot": "0f08aefe70cb14ca7f3126ecc2f34319ca8f281ecdf81c6d6486ea93b2236f8c",
|
||||
"smoke_receipt": "ae3cfa9a3ba970c0f4d6903148d7291375019dd3d12a8c3619599c5520742804",
|
||||
@@ -168,7 +168,7 @@
|
||||
],
|
||||
"auto_gate_status": "blocked",
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "55b5c1c1fb0a11183ee0779e02f4a374cb989adceb4e3999f754dcf815f2e161",
|
||||
"contact_sheet": "17a715b8c3cab33d9e80c8abbbd902fa00ae702f63a86ad87fa0bdeb68913433",
|
||||
"fidelity_receipt": "5cb7f128615cbb801b3e66df177a5c1d61b3339c92cba3a04b9db00aadce0635",
|
||||
"reference_screenshot": "95a9351619463053bda29bdf472702ed4bc650a4510fa6b3cfcc34d5e3ba79b1",
|
||||
"smoke_receipt": null,
|
||||
@@ -210,7 +210,7 @@
|
||||
],
|
||||
"auto_gate_status": "blocked",
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "3f823b2d1e5a98af40443c0f04c5180e2d40c0ae8dab5a5b5c81f80494298822",
|
||||
"contact_sheet": "db1ffb89fb710b18e5e23c50bd04a5c500bea3a9602bc7148def1cd9b712572c",
|
||||
"fidelity_receipt": "fd3c0b8d0ae82ecad0cbeb13974361d5bf8f9e76083619edf5a88d77b0b5f664",
|
||||
"reference_screenshot": "96805bd67e4502f94b078b723d252717183fe8eb34f2eb529c44b772b4dcdce4",
|
||||
"smoke_receipt": null,
|
||||
@@ -252,7 +252,7 @@
|
||||
],
|
||||
"auto_gate_status": "blocked",
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "35b0d6c1d01dd97448bcf50981754d1f0155439b4431efeeaa2b9d4208f7378f",
|
||||
"contact_sheet": "b89c818def92fdd5638e4d0c343bdfd8a1ae201087c5701f9740e66d21d41636",
|
||||
"fidelity_receipt": "38ef8db0e9fdaf4d3c4f83f3b9ab1a2c956661315784c6090c301faac93f2f8c",
|
||||
"reference_screenshot": "468b1b618668660274e7a46a528d0a323fb926c3e47f7e5895ec03189efd35b3",
|
||||
"smoke_receipt": null,
|
||||
@@ -294,7 +294,7 @@
|
||||
],
|
||||
"auto_gate_status": "blocked",
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "c1f6795edcce9b5f104edd8f19b1674ceee66b19b905b330f20f1328fde6baa4",
|
||||
"contact_sheet": "3a68f9f0984b0c0dcd526bfb1bd7deec743e293c739d09529d31ec8dc31c548d",
|
||||
"fidelity_receipt": "d7bec45b7684b8ab2e98755e76624fffdf5048fd864aa64d7092aeb6aba3a62d",
|
||||
"reference_screenshot": "59af0f5ee20b85f07ada82a1d6bb8ab5e69b81bb08b5abf2a7520eca4934e93e",
|
||||
"smoke_receipt": null,
|
||||
@@ -336,7 +336,7 @@
|
||||
],
|
||||
"auto_gate_status": "blocked",
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "f9970bf563b9fc18a08f6617c1a1769cbc8cebd4ec98dcf042c1be12398c8f46",
|
||||
"contact_sheet": "4fd837a9e9c7fc3da874f451915c9942f7c35b2f179f07986e2523c8fb0e2e9f",
|
||||
"fidelity_receipt": "fd2b394777733364723f20d0d732a346f93edba0a748628ce9a1e5596726cb02",
|
||||
"reference_screenshot": "e85989914eb7ca3bb279e03cc792df19c5d06f8d3ba0e59515211164fca5ae2d",
|
||||
"smoke_receipt": null,
|
||||
@@ -378,7 +378,7 @@
|
||||
],
|
||||
"auto_gate_status": "blocked",
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "402b5732bbb22f8145a73ec00176e0653a5f2744245bf10ec9ea757f8b6c1e70",
|
||||
"contact_sheet": "b47a477b472ff5e219ff685d2fd247587ea389cdbd726d2276ffabbbfebf5403",
|
||||
"fidelity_receipt": "dd795f5b763b8b5769e173a07ba63f2a2da2345fefaf96cb48989b7a5ba4ef2c",
|
||||
"reference_screenshot": "3cce11542e0c380396c14d2e7ac7406af704af163e7ba85b8ce9e2fdf7d12015",
|
||||
"smoke_receipt": null,
|
||||
@@ -420,7 +420,7 @@
|
||||
],
|
||||
"auto_gate_status": "blocked",
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "224db100187b471bfeb2b4d38360dc8efa283251be6ebf174da10d74700b080e",
|
||||
"contact_sheet": "d25bb924c36879bf68e1282a46c1818b201962ec80ad0d845a1b2bef6d5b2292",
|
||||
"fidelity_receipt": "51de4317d40671c7a4ba0868cacfa3c86ca2de0d14eecb8d07177f6c53506acf",
|
||||
"reference_screenshot": "aaac87da4e7f0e1e294f8f3d88616b067174687f4b89dafcad0acb4b967e9633",
|
||||
"smoke_receipt": null,
|
||||
@@ -462,7 +462,7 @@
|
||||
],
|
||||
"auto_gate_status": "blocked",
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "60ae07dae1e5cb86fbefc0ffb62eb9bdf8c371f121793ad9d9e4cee23c993443",
|
||||
"contact_sheet": "4df7e9d7a65b8e6749d3e487481302defbcfb6d0efd98fc00bb5afc6921e20cc",
|
||||
"fidelity_receipt": "926bc15a8016d24e25c00a42eb878578dbb825471d6ba2abc316bf48016ab5bc",
|
||||
"reference_screenshot": "65f6615ff2ec51a3d4a77573c2a53471b356724a58bd33dffdb55ed69ab2b73b",
|
||||
"smoke_receipt": null,
|
||||
@@ -504,7 +504,7 @@
|
||||
],
|
||||
"auto_gate_status": "blocked",
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "6966fb4b3014525f5b221bd6ad46a06c7f98b2046882f23d9a96c35876453e30",
|
||||
"contact_sheet": "a72d3845093b54b819d538e7549951871fe1cb07d991b6eb84b48b2a398c653f",
|
||||
"fidelity_receipt": "64abadb7a840271a45d482c1f3a7e8f4e75909ac007ef2c13d4ac0f77c77fdaf",
|
||||
"reference_screenshot": "a081f3b16a3dd72dd16d9fdfcf30aa61cf66c79c865189eb380d22bd425c2a1c",
|
||||
"smoke_receipt": null,
|
||||
@@ -546,7 +546,7 @@
|
||||
],
|
||||
"auto_gate_status": "blocked",
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "ba27daa57e94914e24e341b6a8ae1d7434dfb715f5bc6a54643173865839fb10",
|
||||
"contact_sheet": "dfa4ea5c54fbd6428d4c98cba1707e4e7a6fa3f11b74dc8879c25305b20ca07f",
|
||||
"fidelity_receipt": "5bf44805d7dc674b07da8f0ac8f0a749bfc78893371e921567db82e5bf3a251b",
|
||||
"reference_screenshot": "0b89022af5bfcc26356b7bdb48156510ba16b643e9bc01027ae8197092ead507",
|
||||
"smoke_receipt": null,
|
||||
@@ -588,7 +588,7 @@
|
||||
],
|
||||
"auto_gate_status": "blocked",
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "e082713ef62b3a90e195a07823726c77e4909aaed1cde7ca7b57b4b888860833",
|
||||
"contact_sheet": "ae8042a321313b12a03e9b25379c89544421c4a9e8886b08f87990638f02d7da",
|
||||
"fidelity_receipt": "7aa06118b44f3dcc6202b56e64ec03134f5487d3e48a25279a9ccfeb09c1c81b",
|
||||
"reference_screenshot": "fda35bb4c4810369a5c5bccd70cbcd9d474691027c79a0d94ebf59dbf673c150",
|
||||
"smoke_receipt": null,
|
||||
@@ -630,7 +630,7 @@
|
||||
],
|
||||
"auto_gate_status": "blocked",
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "35333c79ea1ad148e7763b55a6d5886dae6c077cd65c49430a954e69d5997eb7",
|
||||
"contact_sheet": "da6b1ce28c3ae75ea17159bc4a656369fc659bdbfcff3b953aa9ac3ca4c74e28",
|
||||
"fidelity_receipt": "72a5d983bb922049b536f086eedb89d0e3a7959b72480aab5fcfce63842d7455",
|
||||
"reference_screenshot": "6a01598d4b183837b96c698eb9453962fea4bea072a431ee4d71aef6e09da3eb",
|
||||
"smoke_receipt": null,
|
||||
@@ -672,7 +672,7 @@
|
||||
],
|
||||
"auto_gate_status": "blocked",
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "03eff66d27ff955a40c9ff4fda6f840251594bcaa9698d1452cc3527118a7317",
|
||||
"contact_sheet": "451fb96587eb1e8dad65a4e7e34a40c7f81ce178256f9e61f72fb57090c4c61a",
|
||||
"fidelity_receipt": "96948f5547801870efb639d755ee4b944114cd0925c3fd03f6d15cafe935119e",
|
||||
"reference_screenshot": "79f7956399971a6038c6b98ba7850b8d232c593bafb1c484c7127e5d3fd60bba",
|
||||
"smoke_receipt": null,
|
||||
@@ -714,7 +714,7 @@
|
||||
],
|
||||
"auto_gate_status": "blocked",
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "80cc3f0b8990075017711519795bc91a6a73eb5e748ec350fcf1dbbec092738f",
|
||||
"contact_sheet": "45c1a37544d752c06e326d5789a8ad1a51ba2a7926e27db048490526898423b4",
|
||||
"fidelity_receipt": "e1e95e38f4ea8124a378b7de4a0eb81593f192811ea42e7b31085ed84410cf34",
|
||||
"reference_screenshot": "acac0ac30af8fbb206adfb6810573c72d3ca96b00293f9f850fdeefed1ae11dc",
|
||||
"smoke_receipt": null,
|
||||
@@ -756,7 +756,7 @@
|
||||
],
|
||||
"auto_gate_status": "blocked",
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "98ff05a96dc1ba8c6d1567cdc05e07d956cf6c4d8acb8ff95ec73df343d9e6d7",
|
||||
"contact_sheet": "3d2584d894dc76b41f1abd78da0a0dba991a1b9cbc6e63672bb9cb45f75418a1",
|
||||
"fidelity_receipt": "7fd4a1a4f9929a0add47861c0f489f80b3cfe4dd9e91dc13014ec264811c78c5",
|
||||
"reference_screenshot": "bac6b00bf1d0b3c97b19d2a0c45edf44af5cbf369f2cf3ebe78a207a7b6b8c7b",
|
||||
"smoke_receipt": null,
|
||||
@@ -798,7 +798,7 @@
|
||||
],
|
||||
"auto_gate_status": "blocked",
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "ceebdd152351e3d9124f365de2ea46b5b03bd90f8ca532d7f99f79bc29cfd95d",
|
||||
"contact_sheet": "dfdb0c6be0e75f49ecd5d5a782eff136bb25cc679bfbfd17540b9aa47d14356e",
|
||||
"fidelity_receipt": "9d0ced3d64a642e028edf86ff6457c36def39175b3079fff6a4c97b645803228",
|
||||
"reference_screenshot": "c53ba5da0f1b85b23ad1975da65edafaee84f029f06c468b2fbd036031ce15e5",
|
||||
"smoke_receipt": null,
|
||||
@@ -840,7 +840,7 @@
|
||||
],
|
||||
"auto_gate_status": "blocked",
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "6cde51c31f47436c3b5b6db4fbaccb4181b795fb84213c6a1e0ace77cd88eb66",
|
||||
"contact_sheet": "35f74a4093000ea952bfbfef2a211fd0d47f6c926ecbc6cb6fc95a07f3946acf",
|
||||
"fidelity_receipt": "679368f5526815a2cb311d583f0f86871000639c85643e6b47099ab91566d5cc",
|
||||
"reference_screenshot": "9a0c40acaa0fb9c058745cbd16c875f9b7a0417d46c6c37dede388e32cf52d25",
|
||||
"smoke_receipt": null,
|
||||
@@ -880,7 +880,7 @@
|
||||
],
|
||||
"auto_gate_status": "blocked",
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "d3300e5df932d79e82fd0853a9af8c252aa090d1e1df988d77b4d1045ca63002",
|
||||
"contact_sheet": "063652158d00662045c6a94a70a8e7ae36f00aabf3ea5216463e7f8c6564256a",
|
||||
"fidelity_receipt": "b6aa5696947e5fc7fcd633c340cea26e983956f97a0a54b72eb035818d6a3d76",
|
||||
"reference_screenshot": "35ff94a10d71d18318fa11e1c95fb6a32e2b1801ffff24ccc8e0f36afe187387",
|
||||
"smoke_receipt": null,
|
||||
@@ -922,7 +922,7 @@
|
||||
],
|
||||
"auto_gate_status": "blocked",
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "b0b78d2776184009efaedb026d3c5dc4528a29f8fba7d7b6c5da4618fbd42497",
|
||||
"contact_sheet": "be97ade117aa12ee9ffcd562c2e2f905076db7c4ba21ebbc3efa92b4aa0890ae",
|
||||
"fidelity_receipt": "ff075c2947f7c09785c47c57f68d995722873676d91251a822747e0b096b88bf",
|
||||
"reference_screenshot": "d39af58b620fe59ab0e28db0f070fd6e13214896115aa984be069369ef594ff7",
|
||||
"smoke_receipt": null,
|
||||
@@ -964,7 +964,7 @@
|
||||
],
|
||||
"auto_gate_status": "blocked",
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "8c06c02b5802f957b497d1332e8cb0ab3d3a2c1825f551c946d00c38244aadad",
|
||||
"contact_sheet": "dce30937bc181379275aeb74ef278b312b7cbceea99f2e2522aaefe6d6f16878",
|
||||
"fidelity_receipt": "e828f367dda5704dca8c804fb833051e8e3888202e9b76169082ac50164873d8",
|
||||
"reference_screenshot": "75c22cf0736c2c349599de769e984af4e55440dbf83fb4abac35e5c0842abe81",
|
||||
"smoke_receipt": null,
|
||||
@@ -1006,7 +1006,7 @@
|
||||
],
|
||||
"auto_gate_status": "blocked",
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "87221867c254043e20ca653260daa52ccb0f88492fe1fc5595db51edb2d5c87a",
|
||||
"contact_sheet": "0fc408b566d5f90530b8afb2e380258a3d6013f7ed2089e4b53921eb49d97c57",
|
||||
"fidelity_receipt": "fee9ac2b5c6d69612a2a082849f1829f5b3c75f2a5c2d29b76657361f4fc04cc",
|
||||
"reference_screenshot": "4056c85b9415ba7a9a988d45f5316cbdfbaf18ee959e3f7727e2ef90f59f42bc",
|
||||
"smoke_receipt": null,
|
||||
@@ -1048,7 +1048,7 @@
|
||||
],
|
||||
"auto_gate_status": "blocked",
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "847e69a200f8f595339c4816826ed87853faf0a4fc468a6b0672f6f2946cf8a3",
|
||||
"contact_sheet": "599e3dad5711c9a858067f8ce03036d104d9b8a01cc12c9eef04e7efd5550437",
|
||||
"fidelity_receipt": "d9f718418fe0cba65d03c26230b5655764011c1197b9b52cb3ab15b0787cd8b6",
|
||||
"reference_screenshot": "8d9fc0a05ab025310cc35f15c2d3b2de629c79a49df9fe1c7d63b2f7b8a00543",
|
||||
"smoke_receipt": null,
|
||||
@@ -1090,7 +1090,7 @@
|
||||
],
|
||||
"auto_gate_status": "blocked",
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "5328e4b636054dbd363032e7fdb7fea6f0b31eb39d87215ffb4badae2fe02a97",
|
||||
"contact_sheet": "2461333873da620b3c97e88c9ad80c1814ed28433cbc211c781f4999b1a62833",
|
||||
"fidelity_receipt": "70330ed527a665653b1934d49e3ad5f14e2f4f866de429f38615ca98f18657ba",
|
||||
"reference_screenshot": "bd93d862d934f00253a36df8f03f4aef74f87fb1b0f870c777002b39ae7f2af9",
|
||||
"smoke_receipt": null,
|
||||
@@ -1132,7 +1132,7 @@
|
||||
],
|
||||
"auto_gate_status": "blocked",
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "2f4e9111d34cafd0344975f49c5a1d13c3ab8732ac520107a9d0f060b0486108",
|
||||
"contact_sheet": "fd7eb1ddf9e58fcdabc02eb17dd814491227a3ac00a735bfd8b4d7065c482bcf",
|
||||
"fidelity_receipt": "01ed753670341664ee282238d30060766dba929200e59bb279b31497ec8af736",
|
||||
"reference_screenshot": "92bae8fc25051d0dbbb648f931befbfb653cbc331e876ea5e5aaf76afbad0733",
|
||||
"smoke_receipt": null,
|
||||
@@ -1174,7 +1174,7 @@
|
||||
],
|
||||
"auto_gate_status": "blocked",
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "4cf01462c6953780cc59a29d83f051278e5315763f9365240abc3138c204eca2",
|
||||
"contact_sheet": "5a5157baf391062f4ed34e0bde225c820785e216e69b9e7af3d7c460ffdb0c80",
|
||||
"fidelity_receipt": "8f986c32012e5a26fff7d1e4b2c73fb73db59885a7bb3f8ba7fc7f1f0cfd927f",
|
||||
"reference_screenshot": "c2ed8f8d89fd124c65976fa3ece9b153afe4f4542d95880c367922bb88d910ca",
|
||||
"smoke_receipt": null,
|
||||
@@ -1216,7 +1216,7 @@
|
||||
],
|
||||
"auto_gate_status": "blocked",
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "ab533fc6ac798c710cc537d93a18e247830e183fa813ce2a5ee08a582272c1e1",
|
||||
"contact_sheet": "c00894a3fff05448914443bf4fec131fcd6ca87b0ed2aabce5a9f239f3e4082a",
|
||||
"fidelity_receipt": "f33e1fed9d3fe80ed000386d4649be14d1120ea455b57d33b8d97a87d2769231",
|
||||
"reference_screenshot": "ca5487dc68264f209951400c5edddb93c4ae1fc7174b88c2b3dc54a82e0be64a",
|
||||
"smoke_receipt": null,
|
||||
@@ -1256,7 +1256,7 @@
|
||||
],
|
||||
"auto_gate_status": "blocked",
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "64eec701c1883f956200f4c07c18bb893e15272505132a612b554a942026bcee",
|
||||
"contact_sheet": "f377bd08e444ba86e0ebb24b2b6fb6147a292402479d5854424ad483450e6aa3",
|
||||
"fidelity_receipt": "a7543b7f841153c3dd8d182b0c43d5d3688dc128b4da2f392cb41ee20d275ff3",
|
||||
"reference_screenshot": "3e37602cf749a0a383ef0f0a1f25db85e9633da1d74bafc2be76a91b004a866b",
|
||||
"smoke_receipt": null,
|
||||
@@ -1298,7 +1298,7 @@
|
||||
],
|
||||
"auto_gate_status": "blocked",
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "761d7d2063337a41bb0058766d75ed1d470584c07569ea68930e42ec37d2630a",
|
||||
"contact_sheet": "ca62bc4d64abeff11aafb248051fe51438501c1f6c3b486a414fc05d1c05c4c8",
|
||||
"fidelity_receipt": "bf32692b17d20d5a20c9c87ac02226c93739131b38f83c7f3b452a14451128fd",
|
||||
"reference_screenshot": "b8321134113e99f90a0e17e44e326ab25e64f3735150dd82269e0b2daabaaa2b",
|
||||
"smoke_receipt": null,
|
||||
@@ -1340,7 +1340,7 @@
|
||||
],
|
||||
"auto_gate_status": "blocked",
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "2e5c78fc922e036219c15f98dc9608883d9013cda1c3e1b0f9f31d5d0bb8bbd6",
|
||||
"contact_sheet": "d05050e509a7940a4893fbda99624438c1130317d811140d6337fdecb6357b94",
|
||||
"fidelity_receipt": "95baeec998aed196a738e4491cc7cab3ad34dbca2c3d5e96a94943f62075f60c",
|
||||
"reference_screenshot": "0d7c0646a85c56b4b26e09f0cf8a0b658fe0b1cf36be38255900fd259d0c42d4",
|
||||
"smoke_receipt": null,
|
||||
@@ -1382,7 +1382,7 @@
|
||||
],
|
||||
"auto_gate_status": "blocked",
|
||||
"evidence_hashes": {
|
||||
"contact_sheet": "d1cba07fdba73ba6d0b49076d091f1fba3e299f86f44d1bab7d2c2836b26551f",
|
||||
"contact_sheet": "ceadac634245686ba842f84a704d927fb688127f0c14b60eece6d7daa3805c10",
|
||||
"fidelity_receipt": "3152f66c029a0f4be72c43d417b2aec470b483239a8070136e5b87993e57ae68",
|
||||
"reference_screenshot": "8c99c96677fec3c94235098b8fe36b9beeefd31ebfd173989f0ce358d91c4b73",
|
||||
"smoke_receipt": null,
|
||||
@@ -1429,7 +1429,7 @@
|
||||
},
|
||||
"review_batch_id": "beautiful-34",
|
||||
"schema_version": "svglide-beautiful-production-review-gallery/v2",
|
||||
"source_manifest_sha256": "9195c9e2ed8ab146411dcd4a15270500c08b75d85d7047f6307b1b78bfed2e8e",
|
||||
"source_manifest_sha256": "273dd37eda72bca25176baa9f8f899a201e1a852fe5e8415d0218bc1b3d6cfd1",
|
||||
"summary": {
|
||||
"auto_gate_blocked_count": 33,
|
||||
"auto_gate_passed_count": 1,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,319 @@
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2026 Lark Technologies Pte. Ltd.
|
||||
# SPDX-License-Identifier: MIT
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
|
||||
SCRIPT_DIR = Path(__file__).resolve().parent
|
||||
REFERENCES_DIR = SCRIPT_DIR.parent / "references"
|
||||
MATRIX_PATH = REFERENCES_DIR / "beautiful-template-executable-matrix.json"
|
||||
DEFAULT_GALLERY_RECEIPT = REFERENCES_DIR / "receipts" / "production-review" / "beautiful-34-gallery.json"
|
||||
DEFAULT_HUMAN_REVIEW_RECEIPT = REFERENCES_DIR / "receipts" / "production-review" / "beautiful-34-human-review.json"
|
||||
SCHEMA_VERSION = "svglide-beautiful-human-review/v1"
|
||||
ALLOWED_HUMAN_STATUS = ["pending", "pass", "needs_fix", "reject"]
|
||||
ALLOWED_REVIEW_STATUS = set(ALLOWED_HUMAN_STATUS)
|
||||
|
||||
|
||||
def read_json(path: Path) -> dict[str, Any]:
|
||||
payload = read_json_value(path)
|
||||
if not isinstance(payload, dict):
|
||||
raise ValueError(f"expected JSON object: {path}")
|
||||
return payload
|
||||
|
||||
|
||||
def read_json_value(path: Path) -> Any:
|
||||
return json.loads(path.read_text(encoding="utf-8"))
|
||||
|
||||
|
||||
def file_sha256(path: Path) -> str:
|
||||
return hashlib.sha256(path.read_bytes()).hexdigest()
|
||||
|
||||
|
||||
def _as_list(value: object) -> list[Any]:
|
||||
return value if isinstance(value, list) else []
|
||||
|
||||
|
||||
def _normalise_decisions(payload: object | None) -> dict[str, dict[str, Any]]:
|
||||
if not payload:
|
||||
return {}
|
||||
raw = payload.get("decisions", payload.get("families", payload)) if isinstance(payload, dict) else payload
|
||||
decisions: dict[str, dict[str, Any]] = {}
|
||||
if isinstance(raw, dict):
|
||||
for family_id, value in raw.items():
|
||||
if isinstance(value, dict):
|
||||
decisions[str(family_id)] = value
|
||||
elif isinstance(raw, list):
|
||||
for item in raw:
|
||||
if not isinstance(item, dict) or not item.get("family_id"):
|
||||
continue
|
||||
decisions[str(item["family_id"])] = item
|
||||
return decisions
|
||||
|
||||
|
||||
def _summary_counts(families: list[dict[str, Any]]) -> dict[str, Any]:
|
||||
counts = {status: 0 for status in ALLOWED_HUMAN_STATUS}
|
||||
for family in families:
|
||||
status = str(family.get("human_review_status") or "pending")
|
||||
counts[status] = counts.get(status, 0) + 1
|
||||
return {
|
||||
"family_count": len(families),
|
||||
"status_counts": counts,
|
||||
"pending_count": counts.get("pending", 0),
|
||||
"pass_count": counts.get("pass", 0),
|
||||
"needs_fix_count": counts.get("needs_fix", 0),
|
||||
"reject_count": counts.get("reject", 0),
|
||||
}
|
||||
|
||||
|
||||
def _matrix_status_summary() -> dict[str, Any]:
|
||||
matrix = read_json(MATRIX_PATH)
|
||||
rows = [row for row in _as_list(matrix.get("candidates")) if isinstance(row, dict)]
|
||||
production_default_families = [
|
||||
str(row.get("family_id"))
|
||||
for row in rows
|
||||
if row.get("promotion_status") == "production" and row.get("default_selectable") is True
|
||||
]
|
||||
return {
|
||||
"matrix_candidate_count": len(rows),
|
||||
"production_count": sum(1 for row in rows if row.get("promotion_status") == "production"),
|
||||
"default_selectable_count": sum(1 for row in rows if row.get("default_selectable") is True),
|
||||
"production_default_selectable_count": len(production_default_families),
|
||||
"production_default_selectable_families": production_default_families,
|
||||
}
|
||||
|
||||
|
||||
def _gallery_url(base_family: dict[str, Any]) -> object:
|
||||
if base_family.get("gallery_url"):
|
||||
return base_family.get("gallery_url")
|
||||
contact_sheet = base_family.get("contact_sheet")
|
||||
if isinstance(contact_sheet, dict):
|
||||
return contact_sheet.get("html_path")
|
||||
return None
|
||||
|
||||
|
||||
def _review_family(base_family: dict[str, Any], decision: dict[str, Any], *, reviewer: str, reviewed_at: str) -> dict[str, Any]:
|
||||
status = str(decision.get("human_review_status") or decision.get("status") or base_family.get("human_review_status") or "pending")
|
||||
note = str(decision.get("human_review_note") or decision.get("note") or "").strip()
|
||||
issue_codes = [str(item) for item in _as_list(decision.get("issue_codes")) if str(item).strip()]
|
||||
if status not in ALLOWED_REVIEW_STATUS:
|
||||
status = "pending"
|
||||
issue_codes.append("invalid_human_review_status")
|
||||
validation_issues: list[str] = []
|
||||
if status in {"needs_fix", "reject"} and not note and not issue_codes:
|
||||
validation_issues.append("human_review_note_or_issue_codes_required")
|
||||
auto_gate_status = str(base_family.get("auto_gate_status") or "blocked")
|
||||
promotion_eligible = auto_gate_status == "passed" and status == "pass"
|
||||
return {
|
||||
"family_id": base_family.get("family_id"),
|
||||
"runtime_template_id": base_family.get("runtime_template_id"),
|
||||
"gallery_url": _gallery_url(base_family),
|
||||
"auto_gate_status": auto_gate_status,
|
||||
"allowed_human_status": ALLOWED_HUMAN_STATUS,
|
||||
"human_review_status": status,
|
||||
"human_review_note": note,
|
||||
"issue_codes": issue_codes,
|
||||
"reviewer": str(decision.get("reviewer") or reviewer),
|
||||
"reviewed_at": str(decision.get("reviewed_at") or reviewed_at),
|
||||
"promotion_eligible": promotion_eligible,
|
||||
"promotion_action": "candidate_for_m9_production_review" if promotion_eligible else "no_change",
|
||||
"known_blockers": _as_list(base_family.get("known_blockers")),
|
||||
"missing_roles": _as_list(base_family.get("missing_roles")),
|
||||
"evidence_hashes": base_family.get("evidence_hashes") if isinstance(base_family.get("evidence_hashes"), dict) else {},
|
||||
"validation_issues": validation_issues,
|
||||
}
|
||||
|
||||
|
||||
def _promotion_candidates(families: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
||||
return [
|
||||
{
|
||||
"family_id": family["family_id"],
|
||||
"runtime_template_id": family["runtime_template_id"],
|
||||
"action": "create_separate_production_review_receipt",
|
||||
"reason": "auto_gate_status=passed and human_review_status=pass",
|
||||
"evidence_hashes": family["evidence_hashes"],
|
||||
}
|
||||
for family in families
|
||||
if family["promotion_eligible"]
|
||||
]
|
||||
|
||||
|
||||
def _fix_queue(families: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
||||
return [
|
||||
{
|
||||
"family_id": family["family_id"],
|
||||
"runtime_template_id": family["runtime_template_id"],
|
||||
"action": "fix_and_resubmit_human_review",
|
||||
"note": family["human_review_note"],
|
||||
"issue_codes": family["issue_codes"] or family["known_blockers"],
|
||||
}
|
||||
for family in families
|
||||
if family["human_review_status"] == "needs_fix"
|
||||
]
|
||||
|
||||
|
||||
def _reject_queue(families: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
||||
return [
|
||||
{
|
||||
"family_id": family["family_id"],
|
||||
"runtime_template_id": family["runtime_template_id"],
|
||||
"action": "keep_out_of_promotion_pool",
|
||||
"note": family["human_review_note"],
|
||||
"issue_codes": family["issue_codes"] or family["known_blockers"],
|
||||
}
|
||||
for family in families
|
||||
if family["human_review_status"] == "reject"
|
||||
]
|
||||
|
||||
|
||||
def _next_actions(families: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
||||
actions: list[dict[str, Any]] = []
|
||||
for family in families:
|
||||
status = family["human_review_status"]
|
||||
if status == "pending":
|
||||
actions.append(
|
||||
{
|
||||
"family_id": family["family_id"],
|
||||
"runtime_template_id": family["runtime_template_id"],
|
||||
"action": "await_human_review",
|
||||
"reason": "human_review_status=pending",
|
||||
}
|
||||
)
|
||||
elif status == "pass" and not family["promotion_eligible"]:
|
||||
actions.append(
|
||||
{
|
||||
"family_id": family["family_id"],
|
||||
"runtime_template_id": family["runtime_template_id"],
|
||||
"action": "human_pass_waiting_for_auto_gate",
|
||||
"reason": f"auto_gate_status={family['auto_gate_status']}",
|
||||
}
|
||||
)
|
||||
elif status == "needs_fix":
|
||||
actions.append(
|
||||
{
|
||||
"family_id": family["family_id"],
|
||||
"runtime_template_id": family["runtime_template_id"],
|
||||
"action": "fix_and_resubmit_human_review",
|
||||
"reason": family["human_review_note"] or "needs_fix",
|
||||
}
|
||||
)
|
||||
elif status == "reject":
|
||||
actions.append(
|
||||
{
|
||||
"family_id": family["family_id"],
|
||||
"runtime_template_id": family["runtime_template_id"],
|
||||
"action": "keep_out_of_promotion_pool",
|
||||
"reason": family["human_review_note"] or "reject",
|
||||
}
|
||||
)
|
||||
return actions
|
||||
|
||||
|
||||
def build_human_review_receipt(
|
||||
*,
|
||||
gallery_receipt_path: Path = DEFAULT_GALLERY_RECEIPT,
|
||||
decisions_path: Path | None = None,
|
||||
reviewer: str = "user",
|
||||
reviewed_at: str = "pending",
|
||||
) -> dict[str, Any]:
|
||||
gallery_receipt = read_json(gallery_receipt_path)
|
||||
if gallery_receipt.get("not_promotion_receipt") is not True:
|
||||
raise ValueError("gallery receipt must be marked not_promotion_receipt")
|
||||
decisions = _normalise_decisions(read_json_value(decisions_path) if decisions_path else None)
|
||||
families = []
|
||||
for family in _as_list(gallery_receipt.get("families")):
|
||||
if not isinstance(family, dict) or not family.get("family_id"):
|
||||
continue
|
||||
decision = decisions.get(str(family["family_id"]), {})
|
||||
families.append(_review_family(family, decision, reviewer=reviewer, reviewed_at=reviewed_at))
|
||||
promotion_candidates = _promotion_candidates(families)
|
||||
fix_queue = _fix_queue(families)
|
||||
reject_queue = _reject_queue(families)
|
||||
next_actions = _next_actions(families)
|
||||
invalid_reviews = [
|
||||
{
|
||||
"family_id": family["family_id"],
|
||||
"runtime_template_id": family["runtime_template_id"],
|
||||
"validation_issues": family["validation_issues"],
|
||||
}
|
||||
for family in families
|
||||
if family["validation_issues"]
|
||||
]
|
||||
return {
|
||||
"schema_version": SCHEMA_VERSION,
|
||||
"artifact_kind": "human_review_receipt",
|
||||
"review_batch_id": gallery_receipt.get("review_batch_id"),
|
||||
"review_surface": "local_html_gallery",
|
||||
"not_promotion_receipt": True,
|
||||
"does_not_modify_matrix": True,
|
||||
"allowed_human_status": ALLOWED_HUMAN_STATUS,
|
||||
"source_gallery_receipt": str(gallery_receipt_path),
|
||||
"source_gallery": str(gallery_receipt_path),
|
||||
"source_gallery_receipt_sha256": file_sha256(gallery_receipt_path),
|
||||
"source_manifest_sha256": gallery_receipt.get("source_manifest_sha256"),
|
||||
"summary": {
|
||||
**_summary_counts(families),
|
||||
**_matrix_status_summary(),
|
||||
"promotion_candidates": [item["family_id"] for item in promotion_candidates],
|
||||
"fix_queue": [item["family_id"] for item in fix_queue],
|
||||
"reject_queue": [item["family_id"] for item in reject_queue],
|
||||
"promotion_candidate_count": len(promotion_candidates),
|
||||
"fix_queue_count": len(fix_queue),
|
||||
"reject_queue_count": len(reject_queue),
|
||||
"next_action_count": len(next_actions),
|
||||
"invalid_review_count": len(invalid_reviews),
|
||||
},
|
||||
"policy": {
|
||||
"human_review_pass_does_not_promote_without_auto_gate": True,
|
||||
"human_review_pass_does_not_modify_matrix": True,
|
||||
"apply_does_not_write_matrix": True,
|
||||
"apply_outputs_candidates_or_next_actions_only": True,
|
||||
"promotion_requires_separate_production_review_receipt": True,
|
||||
},
|
||||
"families": families,
|
||||
"promotion_candidates": promotion_candidates,
|
||||
"fix_queue": fix_queue,
|
||||
"reject_queue": reject_queue,
|
||||
"next_actions": next_actions,
|
||||
"invalid_reviews": invalid_reviews,
|
||||
}
|
||||
|
||||
|
||||
def write_human_review_receipt(receipt: dict[str, Any], output_path: Path = DEFAULT_HUMAN_REVIEW_RECEIPT) -> Path:
|
||||
output_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
output_path.write_text(json.dumps(receipt, ensure_ascii=False, indent=2, sort_keys=True) + "\n", encoding="utf-8")
|
||||
return output_path
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("command", nargs="?", choices=["seed", "apply"], default="seed")
|
||||
parser.add_argument("--gallery-receipt", "--gallery-source", dest="gallery_receipt", default=str(DEFAULT_GALLERY_RECEIPT))
|
||||
parser.add_argument("--decisions")
|
||||
parser.add_argument("--output", default=str(DEFAULT_HUMAN_REVIEW_RECEIPT))
|
||||
parser.add_argument("--reviewer", default="user")
|
||||
parser.add_argument("--reviewed-at", default="pending")
|
||||
parser.add_argument("--stdout", action="store_true")
|
||||
parser.add_argument("--pretty", action="store_true")
|
||||
args = parser.parse_args()
|
||||
receipt = build_human_review_receipt(
|
||||
gallery_receipt_path=Path(args.gallery_receipt),
|
||||
decisions_path=Path(args.decisions) if args.decisions else None,
|
||||
reviewer=args.reviewer,
|
||||
reviewed_at=args.reviewed_at,
|
||||
)
|
||||
if args.stdout:
|
||||
print(json.dumps(receipt, ensure_ascii=False, indent=2 if args.pretty else None, sort_keys=True))
|
||||
return 0 if not receipt["invalid_reviews"] else 1
|
||||
output_path = write_human_review_receipt(receipt, Path(args.output))
|
||||
print(json.dumps({"output_path": str(output_path), **receipt["summary"]}, ensure_ascii=False, indent=2 if args.pretty else None, sort_keys=True))
|
||||
return 0 if not receipt["invalid_reviews"] else 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -0,0 +1,151 @@
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2026 Lark Technologies Pte. Ltd.
|
||||
# SPDX-License-Identifier: MIT
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
||||
|
||||
import beautiful_template_production_review_apply as apply
|
||||
|
||||
|
||||
REFERENCES_DIR = Path(__file__).resolve().parent.parent / "references"
|
||||
|
||||
|
||||
def write_json(path: Path, payload: dict[str, object]) -> None:
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text(json.dumps(payload, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
|
||||
|
||||
|
||||
class BeautifulTemplateProductionReviewApplyTest(unittest.TestCase):
|
||||
def test_seed_human_review_receipt_contains_34_pending_families(self) -> None:
|
||||
receipt = apply.build_human_review_receipt()
|
||||
|
||||
self.assertEqual("human_review_receipt", receipt["artifact_kind"])
|
||||
self.assertTrue(receipt["not_promotion_receipt"])
|
||||
self.assertTrue(receipt["does_not_modify_matrix"])
|
||||
self.assertEqual("beautiful-34", receipt["review_batch_id"])
|
||||
self.assertEqual(["pending", "pass", "needs_fix", "reject"], receipt["allowed_human_status"])
|
||||
self.assertEqual(34, receipt["summary"]["family_count"])
|
||||
self.assertEqual({"pending": 34, "pass": 0, "needs_fix": 0, "reject": 0}, receipt["summary"]["status_counts"])
|
||||
self.assertEqual(34, receipt["summary"]["pending_count"])
|
||||
self.assertEqual(0, receipt["summary"]["promotion_candidate_count"])
|
||||
self.assertEqual(["blue-professional"], receipt["summary"]["production_default_selectable_families"])
|
||||
self.assertEqual(34, len(receipt["families"]))
|
||||
for family in receipt["families"]:
|
||||
self.assertEqual(["pending", "pass", "needs_fix", "reject"], family["allowed_human_status"])
|
||||
self.assertEqual("pending", family["human_review_status"])
|
||||
self.assertEqual("no_change", family["promotion_action"])
|
||||
self.assertIn("evidence_hashes", family)
|
||||
|
||||
def test_can_seed_from_gallery_manifest_contact_sheet_fields(self) -> None:
|
||||
manifest_path = REFERENCES_DIR / "production-review" / "beautiful" / "manifest.json"
|
||||
|
||||
receipt = apply.build_human_review_receipt(gallery_receipt_path=manifest_path)
|
||||
|
||||
self.assertEqual(34, receipt["summary"]["family_count"])
|
||||
blue = next(item for item in receipt["families"] if item["family_id"] == "blue-professional")
|
||||
self.assertEqual("families/blue-professional.html", blue["gallery_url"])
|
||||
self.assertEqual("passed", blue["auto_gate_status"])
|
||||
|
||||
def test_decisions_route_pass_fix_reject_without_modifying_matrix(self) -> None:
|
||||
matrix_path = REFERENCES_DIR / "beautiful-template-executable-matrix.json"
|
||||
before = apply.file_sha256(matrix_path)
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
decisions_path = Path(tmp) / "decisions.json"
|
||||
output_path = Path(tmp) / "human-review.json"
|
||||
write_json(
|
||||
decisions_path,
|
||||
{
|
||||
"decisions": [
|
||||
{
|
||||
"family_id": "blue-professional",
|
||||
"status": "pass",
|
||||
"note": "整体可用,继续进入逐套 production review。",
|
||||
},
|
||||
{
|
||||
"family_id": "8-bit-orbit",
|
||||
"status": "needs_fix",
|
||||
"note": "缺 page-family smoke,数据页需要复刻。",
|
||||
},
|
||||
{
|
||||
"family_id": "bold-poster",
|
||||
"status": "reject",
|
||||
"note": "当前不适合默认链路。",
|
||||
},
|
||||
]
|
||||
},
|
||||
)
|
||||
|
||||
receipt = apply.build_human_review_receipt(decisions_path=decisions_path, reviewed_at="2026-06-24T00:00:00+08:00")
|
||||
apply.write_human_review_receipt(receipt, output_path)
|
||||
self.assertTrue(output_path.is_file())
|
||||
|
||||
after = apply.file_sha256(matrix_path)
|
||||
self.assertEqual(before, after)
|
||||
self.assertEqual(1, receipt["summary"]["promotion_candidate_count"])
|
||||
self.assertEqual(1, receipt["summary"]["fix_queue_count"])
|
||||
self.assertEqual(1, receipt["summary"]["reject_queue_count"])
|
||||
self.assertEqual(["blue-professional"], receipt["summary"]["promotion_candidates"])
|
||||
self.assertEqual(["8-bit-orbit"], receipt["summary"]["fix_queue"])
|
||||
self.assertEqual(["bold-poster"], receipt["summary"]["reject_queue"])
|
||||
self.assertEqual(["blue-professional"], [item["family_id"] for item in receipt["promotion_candidates"]])
|
||||
self.assertEqual(["8-bit-orbit"], [item["family_id"] for item in receipt["fix_queue"]])
|
||||
self.assertEqual(["bold-poster"], [item["family_id"] for item in receipt["reject_queue"]])
|
||||
self.assertTrue(receipt["next_actions"])
|
||||
for item in receipt["promotion_candidates"] + receipt["next_actions"]:
|
||||
self.assertNotIn("promotion_status", item)
|
||||
self.assertNotIn("default_selectable", item)
|
||||
|
||||
def test_human_pass_on_blocked_family_does_not_create_promotion_candidate(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
decisions_path = Path(tmp) / "decisions.json"
|
||||
write_json(
|
||||
decisions_path,
|
||||
{
|
||||
"families": {
|
||||
"8-bit-orbit": {
|
||||
"human_review_status": "pass",
|
||||
"human_review_note": "人工觉得好看,但自动门禁仍 blocked。",
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
receipt = apply.build_human_review_receipt(decisions_path=decisions_path)
|
||||
|
||||
family = next(item for item in receipt["families"] if item["family_id"] == "8-bit-orbit")
|
||||
self.assertFalse(family["promotion_eligible"])
|
||||
self.assertEqual("no_change", family["promotion_action"])
|
||||
self.assertEqual([], receipt["promotion_candidates"])
|
||||
self.assertEqual(0, receipt["summary"]["invalid_review_count"])
|
||||
self.assertIn("human_pass_waiting_for_auto_gate", [item["action"] for item in receipt["next_actions"]])
|
||||
|
||||
def test_needs_fix_and_reject_require_note_or_issue_codes(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
decisions_path = Path(tmp) / "decisions.json"
|
||||
write_json(
|
||||
decisions_path,
|
||||
{
|
||||
"families": {
|
||||
"8-bit-orbit": {"human_review_status": "needs_fix"},
|
||||
"bold-poster": {"human_review_status": "reject", "issue_codes": ["visual_quality_low"]},
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
receipt = apply.build_human_review_receipt(decisions_path=decisions_path)
|
||||
|
||||
bad = next(item for item in receipt["families"] if item["family_id"] == "8-bit-orbit")
|
||||
good = next(item for item in receipt["families"] if item["family_id"] == "bold-poster")
|
||||
self.assertIn("human_review_note_or_issue_codes_required", bad["validation_issues"])
|
||||
self.assertEqual([], good["validation_issues"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -20,6 +20,11 @@ DEFAULT_OUTPUT_DIR = REFERENCES_DIR / "production-review" / "beautiful"
|
||||
DEFAULT_RECEIPT_PATH = REFERENCES_DIR / "receipts" / "production-review" / "beautiful-34-gallery.json"
|
||||
GENERATOR_VERSION = "svglide-beautiful-production-review-gallery/v2"
|
||||
REVIEW_BATCH_ID = "beautiful-34"
|
||||
HUMAN_REVIEW_STATUS = "pending"
|
||||
PROMOTION_ACTION = "no_change_until_human_pass"
|
||||
REVIEW_STATUSES = ("pass", "needs_fix", "reject")
|
||||
REVIEW_STORAGE_KEY = "beautiful-production-review-decisions-v1"
|
||||
REVIEW_DECISIONS_SCHEMA_VERSION = "svglide-beautiful-human-review-decisions/v1"
|
||||
|
||||
CORE_REVIEW_ROLES = [
|
||||
"cover",
|
||||
@@ -463,9 +468,9 @@ def _family_review(row: dict[str, Any]) -> dict[str, Any]:
|
||||
"page_family_promotion_gate_status": promotion_gate["status"],
|
||||
"page_family_promotion_gate": promotion_gate,
|
||||
"auto_gate_status": auto_gate_status,
|
||||
"human_review_status": "pending",
|
||||
"allowed_human_status": ["pass", "needs_fix", "reject"],
|
||||
"promotion_action": "no_change_until_human_pass",
|
||||
"human_review_status": HUMAN_REVIEW_STATUS,
|
||||
"allowed_human_status": list(REVIEW_STATUSES),
|
||||
"promotion_action": PROMOTION_ACTION,
|
||||
"evidence_hashes": evidence_hashes,
|
||||
"contact_sheet": {
|
||||
"artifact_kind": "smoke_deck_contact_sheet_review_model",
|
||||
@@ -563,6 +568,189 @@ def _badge(value: object) -> str:
|
||||
return f'<span class="badge {css}">{text}</span>'
|
||||
|
||||
|
||||
def _review_receipt_relpath() -> str:
|
||||
return relpath(DEFAULT_RECEIPT_PATH) or DEFAULT_RECEIPT_PATH.as_posix()
|
||||
|
||||
|
||||
def _review_decision_template(family: dict[str, Any]) -> dict[str, Any]:
|
||||
return {
|
||||
"family_id": family["family_id"],
|
||||
"runtime_template_id": family["runtime_template_id"],
|
||||
"review_status": "pass | needs_fix | reject",
|
||||
"human_review_status_before_selection": HUMAN_REVIEW_STATUS,
|
||||
"promotion_action": PROMOTION_ACTION,
|
||||
"source_gallery_receipt_path": _review_receipt_relpath(),
|
||||
"notes": "",
|
||||
}
|
||||
|
||||
|
||||
def _review_controls_html(family: dict[str, Any], *, include_snippet: bool = False) -> str:
|
||||
family_id = str(family["family_id"])
|
||||
safe_family_id = html.escape(family_id, quote=True)
|
||||
buttons = "".join(
|
||||
f'<button type="button" data-family-id="{safe_family_id}" data-review-status="{html.escape(status, quote=True)}">{html.escape(status)}</button>'
|
||||
for status in REVIEW_STATUSES
|
||||
)
|
||||
snippet = ""
|
||||
if include_snippet:
|
||||
template = json.dumps(_review_decision_template(family), ensure_ascii=False, indent=2, sort_keys=True)
|
||||
snippet = (
|
||||
'<details class="decision-template">'
|
||||
"<summary>Copyable decision JSON fragment</summary>"
|
||||
f"<pre>{html.escape(template)}</pre>"
|
||||
"</details>"
|
||||
)
|
||||
return (
|
||||
f'<div class="review-control" data-review-control-for="{safe_family_id}">'
|
||||
f'<div class="decision-buttons">{buttons}</div>'
|
||||
f'<div class="review-current">Selected: <strong data-review-current-for="{safe_family_id}">pending</strong></div>'
|
||||
f'<label class="notes-label">Notes <input type="text" data-review-notes-for="{safe_family_id}" placeholder="optional apply-script context" /></label>'
|
||||
f"{snippet}"
|
||||
"</div>"
|
||||
)
|
||||
|
||||
|
||||
def _review_handoff_html() -> str:
|
||||
receipt_path = _review_receipt_relpath()
|
||||
command = f"python <apply-script> --gallery-receipt {receipt_path} --decisions <exported-decisions.json>"
|
||||
return f"""<section class="review-handoff">
|
||||
<h2>Human Review Export</h2>
|
||||
<div class="warning">This local UI does not automatically modify production/default. It only stores browser-local decisions and exports JSON for a separate apply script.</div>
|
||||
<p><code>human_review_status={html.escape(HUMAN_REVIEW_STATUS)}</code> <code>promotion_action={html.escape(PROMOTION_ACTION)}</code></p>
|
||||
<p>Machine-readable gallery receipt: <code>{html.escape(receipt_path)}</code></p>
|
||||
<p>Apply script input: save this textarea as decisions JSON, then pass it to the apply script, for example <code>{html.escape(command)}</code>.</p>
|
||||
<textarea id="review-decisions-json" readonly spellcheck="false"></textarea>
|
||||
</section>
|
||||
"""
|
||||
|
||||
|
||||
def _review_script_html() -> str:
|
||||
receipt_path = _review_receipt_relpath()
|
||||
return """ <script>
|
||||
(function () {
|
||||
var storageKey = %(storage_key)s;
|
||||
var schemaVersion = %(schema_version)s;
|
||||
var reviewBatchId = %(review_batch_id)s;
|
||||
var receiptPath = %(receipt_path)s;
|
||||
var pendingHumanReviewStatus = %(pending_status)s;
|
||||
var promotionAction = %(promotion_action)s;
|
||||
|
||||
function readState() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
||||
if (parsed && typeof parsed === "object" && parsed.decisions && typeof parsed.decisions === "object") {
|
||||
return parsed;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore malformed local state and rebuild below.
|
||||
}
|
||||
return { decisions: {} };
|
||||
}
|
||||
|
||||
function writeState(state) {
|
||||
localStorage.setItem(storageKey, JSON.stringify(state));
|
||||
}
|
||||
|
||||
function buildExport(state) {
|
||||
var decisions = Object.keys(state.decisions || {}).sort().map(function (familyId) {
|
||||
return state.decisions[familyId];
|
||||
});
|
||||
return {
|
||||
schema_version: schemaVersion,
|
||||
artifact_kind: "beautiful_template_human_review_decisions",
|
||||
review_batch_id: reviewBatchId,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
not_promotion_receipt: true,
|
||||
policy: {
|
||||
does_not_automatically_modify_production_default: true,
|
||||
apply_script_must_validate_gallery_receipt: true
|
||||
},
|
||||
decisions: decisions
|
||||
};
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.querySelectorAll("[data-review-current-for]").forEach(function (node) {
|
||||
var familyId = node.getAttribute("data-review-current-for");
|
||||
var decision = state.decisions[familyId];
|
||||
node.textContent = decision ? decision.review_status : "pending";
|
||||
});
|
||||
document.querySelectorAll("[data-review-status]").forEach(function (button) {
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var decision = state.decisions[familyId];
|
||||
button.classList.toggle("selected", Boolean(decision && decision.review_status === status));
|
||||
});
|
||||
document.querySelectorAll("[data-review-notes-for]").forEach(function (input) {
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var decision = state.decisions[familyId];
|
||||
if (decision && input.value !== decision.notes) {
|
||||
input.value = decision.notes || "";
|
||||
}
|
||||
});
|
||||
var textarea = document.getElementById("review-decisions-json");
|
||||
if (textarea) {
|
||||
textarea.value = JSON.stringify(buildExport(state), null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
var button = event.target.closest("[data-review-status]");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = button.getAttribute("data-family-id");
|
||||
var status = button.getAttribute("data-review-status");
|
||||
var existing = state.decisions[familyId] || {};
|
||||
state.decisions[familyId] = {
|
||||
family_id: familyId,
|
||||
review_status: status,
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
notes: existing.notes || "",
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
document.addEventListener("input", function (event) {
|
||||
var input = event.target.closest("[data-review-notes-for]");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
var state = readState();
|
||||
var familyId = input.getAttribute("data-review-notes-for");
|
||||
var existing = state.decisions[familyId] || {
|
||||
family_id: familyId,
|
||||
review_status: "needs_fix",
|
||||
human_review_status_before_selection: pendingHumanReviewStatus,
|
||||
promotion_action: promotionAction,
|
||||
source_gallery_receipt_path: receiptPath,
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
existing.notes = input.value;
|
||||
existing.updated_at = new Date().toISOString();
|
||||
state.decisions[familyId] = existing;
|
||||
writeState(state);
|
||||
render(state);
|
||||
});
|
||||
|
||||
render(readState());
|
||||
})();
|
||||
</script>
|
||||
""" % {
|
||||
"storage_key": json.dumps(REVIEW_STORAGE_KEY),
|
||||
"schema_version": json.dumps(REVIEW_DECISIONS_SCHEMA_VERSION),
|
||||
"review_batch_id": json.dumps(REVIEW_BATCH_ID),
|
||||
"receipt_path": json.dumps(receipt_path),
|
||||
"pending_status": json.dumps(HUMAN_REVIEW_STATUS),
|
||||
"promotion_action": json.dumps(PROMOTION_ACTION),
|
||||
}
|
||||
|
||||
|
||||
def _render_family_html(family: dict[str, Any]) -> str:
|
||||
pages = []
|
||||
for page in family["pages"]:
|
||||
@@ -601,28 +789,45 @@ def _render_family_html(family: dict[str, Any]) -> str:
|
||||
h2 {{ margin: 10px 0 4px; font-size: 15px; }}
|
||||
p {{ margin: 5px 0; font-size: 12px; color: #536071; }}
|
||||
code {{ word-break: break-all; font-size: 11px; }}
|
||||
button {{ cursor: pointer; border: 1px solid #b8c2d2; background: #fff; color: #172033; border-radius: 6px; padding: 6px 9px; font-weight: 700; }}
|
||||
button.selected {{ border-color: #1d4ed8; background: #dbeafe; color: #1e3a8a; }}
|
||||
.badge {{ display: inline-block; border-radius: 999px; padding: 2px 7px; font-size: 11px; font-weight: 700; }}
|
||||
.ok {{ color: #065f46; background: #d1fae5; }}
|
||||
.warn {{ color: #92400e; background: #fef3c7; }}
|
||||
.bad {{ color: #991b1b; background: #fee2e2; }}
|
||||
.review-panel, .review-handoff {{ background: #fff; border: 1px solid #dfe5ee; border-radius: 8px; padding: 14px; margin: 16px 0; }}
|
||||
.decision-buttons {{ display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }}
|
||||
.review-current {{ font-size: 12px; color: #536071; margin-bottom: 8px; }}
|
||||
.notes-label {{ display: block; color: #536071; font-size: 12px; }}
|
||||
.notes-label input {{ margin-left: 8px; min-width: min(520px, 80vw); padding: 6px 8px; border: 1px solid #c7d0df; border-radius: 6px; }}
|
||||
.decision-template {{ margin-top: 10px; }}
|
||||
pre, textarea {{ width: 100%; box-sizing: border-box; border: 1px solid #c7d0df; border-radius: 6px; background: #f8fafc; color: #172033; }}
|
||||
pre {{ overflow: auto; padding: 10px; font-size: 12px; }}
|
||||
textarea {{ min-height: 180px; padding: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<p><a href="../index.html">Back to gallery</a></p>
|
||||
<h1>{html.escape(family['family_id'])}</h1>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt.</div>
|
||||
<div class="warning">Review input only. This contact sheet is not a production promotion receipt and does not automatically modify production/default.</div>
|
||||
<div class="meta">
|
||||
<div class="metric"><strong>{html.escape(str(family['page_variant_count']))}</strong>source pages</div>
|
||||
<div class="metric"><strong>{html.escape(str(family['auto_gate_status']))}</strong>auto gate</div>
|
||||
<div class="metric"><strong>{html.escape(str(family['smoke_status']))}</strong>smoke</div>
|
||||
<div class="metric"><strong>{html.escape(str(family['fidelity_status']))}</strong>fidelity</div>
|
||||
</div>
|
||||
<div class="review-panel">
|
||||
<h2>Human decision</h2>
|
||||
{_review_controls_html(family, include_snippet=True)}
|
||||
</div>
|
||||
<p><strong>Known blockers:</strong> {html.escape(blockers)}</p>
|
||||
</header>
|
||||
{_review_handoff_html()}
|
||||
<main class="deck">
|
||||
{"".join(pages)}
|
||||
</main>
|
||||
{_review_script_html()}
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
@@ -639,10 +844,11 @@ def _render_html(manifest: dict[str, Any]) -> str:
|
||||
f"<td><strong><a href=\"{html.escape(contact)}\">{html.escape(family['family_id'])}</a></strong><br><small>{html.escape(family['runtime_template_id'])}</small></td>"
|
||||
f"<td>{html.escape(str(family['promotion_status']))}<br><small>default={html.escape(str(family['default_selectable']).lower())}</small></td>"
|
||||
f"<td>{family['page_variant_count']} source<br><small>{family['implemented_page_variant_count']} implemented</small></td>"
|
||||
f"<td>{_badge(family['auto_gate_status'])}<br><small>human={html.escape(str(family['human_review_status']))}</small></td>"
|
||||
f"<td>{_badge(family['auto_gate_status'])}<br><small>human_review_status={html.escape(str(family['human_review_status']))}</small><br><small>promotion_action={html.escape(str(family['promotion_action']))}</small></td>"
|
||||
f"<td>{html.escape(str(family['smoke_status']))}<br><small>{html.escape(str(family['smoke'].get('rendered_pages') or ''))} rendered</small></td>"
|
||||
f"<td>{html.escape(str(family['fidelity_status']))}</td>"
|
||||
f"<td>{html.escape(blocker_text)}</td>"
|
||||
f"<td>{_review_controls_html(family)}</td>"
|
||||
f"<td><code>{html.escape(str(family['visual_contract_path']))}</code><br><code>{html.escape(str(family['reference_screenshot']))}</code></td>"
|
||||
"</tr>"
|
||||
)
|
||||
@@ -660,11 +866,19 @@ def _render_html(manifest: dict[str, Any]) -> str:
|
||||
.summary { display: flex; gap: 12px; flex-wrap: wrap; margin: 18px 0; }
|
||||
.metric { background: #fff; border: 1px solid #dbe1ea; border-radius: 8px; padding: 10px 12px; min-width: 150px; }
|
||||
.metric strong { display: block; font-size: 22px; }
|
||||
button { cursor: pointer; border: 1px solid #b8c2d2; background: #fff; color: #172033; border-radius: 6px; padding: 6px 9px; font-weight: 700; }
|
||||
button.selected { border-color: #1d4ed8; background: #dbeafe; color: #1e3a8a; }
|
||||
table { border-collapse: collapse; width: 100%%; background: #fff; border: 1px solid #dbe1ea; }
|
||||
th, td { border-bottom: 1px solid #e5e9f0; padding: 10px; text-align: left; vertical-align: top; font-size: 13px; }
|
||||
th { background: #eef2f7; font-size: 12px; text-transform: uppercase; letter-spacing: .04em; }
|
||||
code { font-size: 11px; color: #4a5870; word-break: break-all; }
|
||||
small { color: #65728a; }
|
||||
.decision-buttons { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
|
||||
.review-current { font-size: 12px; color: #536071; margin-bottom: 8px; }
|
||||
.notes-label { display: block; color: #536071; font-size: 12px; }
|
||||
.notes-label input { width: min(220px, 80vw); padding: 6px 8px; border: 1px solid #c7d0df; border-radius: 6px; }
|
||||
.review-handoff { background: #fff; border: 1px solid #dbe1ea; border-radius: 8px; padding: 14px; margin: 18px 0; max-width: 1180px; }
|
||||
textarea { width: 100%%; min-height: 180px; box-sizing: border-box; border: 1px solid #c7d0df; border-radius: 6px; background: #f8fafc; color: #172033; padding: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
||||
.badge { display: inline-block; border-radius: 999px; padding: 2px 7px; font-size: 11px; font-weight: 700; }
|
||||
.ok { color: #065f46; background: #d1fae5; }
|
||||
.warn { color: #92400e; background: #fef3c7; }
|
||||
@@ -674,7 +888,7 @@ def _render_html(manifest: dict[str, Any]) -> str:
|
||||
<body>
|
||||
<header>
|
||||
<h1>SVGlide Beautiful Production Review Gallery</h1>
|
||||
<div class="warning">This gallery is review input only. It is not a promotion receipt and does not change production/default_selectable status.</div>
|
||||
<div class="warning">This gallery is review input only. It is not a promotion receipt, does not change production/default_selectable status, and does not automatically modify production/default.</div>
|
||||
<div class="summary">
|
||||
<div class="metric"><strong>%(candidate_count)s</strong>candidates</div>
|
||||
<div class="metric"><strong>%(production_default)s</strong>production + default</div>
|
||||
@@ -682,6 +896,7 @@ def _render_html(manifest: dict[str, Any]) -> str:
|
||||
<div class="metric"><strong>%(smoke_counts)s</strong>smoke status counts</div>
|
||||
</div>
|
||||
</header>
|
||||
%(handoff)s
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -692,6 +907,7 @@ def _render_html(manifest: dict[str, Any]) -> str:
|
||||
<th>Smoke</th>
|
||||
<th>Fidelity</th>
|
||||
<th>Known Blockers</th>
|
||||
<th>Human Decision</th>
|
||||
<th>Evidence</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -699,6 +915,7 @@ def _render_html(manifest: dict[str, Any]) -> str:
|
||||
%(rows)s
|
||||
</tbody>
|
||||
</table>
|
||||
%(script)s
|
||||
</body>
|
||||
</html>
|
||||
""" % {
|
||||
@@ -706,7 +923,9 @@ def _render_html(manifest: dict[str, Any]) -> str:
|
||||
"production_default": html.escape(str(summary["production_default_selectable_count"])),
|
||||
"auto_passed": html.escape(str(summary["auto_gate_passed_count"])),
|
||||
"smoke_counts": html.escape(json.dumps(summary["smoke_status_counts"], sort_keys=True)),
|
||||
"handoff": _review_handoff_html(),
|
||||
"rows": "\n".join(rows),
|
||||
"script": _review_script_html(),
|
||||
}
|
||||
|
||||
|
||||
@@ -743,12 +962,33 @@ def write_gallery_artifacts(output_dir: Path = DEFAULT_OUTPUT_DIR, receipt_path:
|
||||
}
|
||||
|
||||
|
||||
def write_gallery_html_artifacts(output_dir: Path = DEFAULT_OUTPUT_DIR) -> dict[str, Any]:
|
||||
output_dir.mkdir(parents=True, exist_ok=True)
|
||||
families_dir = output_dir / "families"
|
||||
families_dir.mkdir(parents=True, exist_ok=True)
|
||||
manifest = build_gallery_manifest()
|
||||
for family in manifest["families"]:
|
||||
family_html_path = families_dir / f"{family['family_id']}.html"
|
||||
family_html_path.write_text(_render_family_html(family), encoding="utf-8")
|
||||
html_path = output_dir / "index.html"
|
||||
html_path.write_text(_render_html(manifest), encoding="utf-8")
|
||||
return {
|
||||
"html_path": str(html_path),
|
||||
"family_html_count": len(manifest["families"]),
|
||||
"candidate_count": manifest["summary"]["candidate_count"],
|
||||
"production_default_selectable_count": manifest["summary"]["production_default_selectable_count"],
|
||||
"default_selectable_count": manifest["summary"]["default_selectable_count"],
|
||||
"auto_gate_passed_count": manifest["summary"]["auto_gate_passed_count"],
|
||||
}
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--output-dir", default=str(DEFAULT_OUTPUT_DIR))
|
||||
parser.add_argument("--receipt-path", default=str(DEFAULT_RECEIPT_PATH))
|
||||
parser.add_argument("--stdout", action="store_true", help="print manifest only and do not write artifacts")
|
||||
parser.add_argument("--receipt-stdout", action="store_true", help="print gallery receipt only and do not write artifacts")
|
||||
parser.add_argument("--html-only", action="store_true", help="write index/family HTML only and leave manifest/receipt JSON unchanged")
|
||||
parser.add_argument("--pretty", action="store_true")
|
||||
args = parser.parse_args()
|
||||
if args.stdout:
|
||||
@@ -759,6 +999,10 @@ def main() -> int:
|
||||
receipt = build_gallery_receipt()
|
||||
print(json.dumps(receipt, ensure_ascii=False, indent=2 if args.pretty else None, sort_keys=True))
|
||||
return 0
|
||||
if args.html_only:
|
||||
result = write_gallery_html_artifacts(Path(args.output_dir))
|
||||
print(json.dumps(result, ensure_ascii=False, indent=2 if args.pretty else None, sort_keys=True))
|
||||
return 0
|
||||
result = write_gallery_artifacts(Path(args.output_dir), Path(args.receipt_path))
|
||||
print(json.dumps(result, ensure_ascii=False, indent=2 if args.pretty else None, sort_keys=True))
|
||||
return 0
|
||||
|
||||
@@ -104,7 +104,7 @@ class BeautifulTemplateProductionReviewGalleryTest(unittest.TestCase):
|
||||
def test_write_artifacts_keeps_production_default_counts_unchanged(self) -> None:
|
||||
before = gallery.matrix_status_counts()
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
result = gallery.write_gallery_artifacts(Path(tmpdir))
|
||||
result = gallery.write_gallery_artifacts(Path(tmpdir), Path(tmpdir) / "receipt.json")
|
||||
manifest_path = Path(result["manifest_path"])
|
||||
html_path = Path(result["html_path"])
|
||||
|
||||
@@ -119,6 +119,26 @@ class BeautifulTemplateProductionReviewGalleryTest(unittest.TestCase):
|
||||
self.assertEqual(34, manifest["summary"]["candidate_count"])
|
||||
self.assertTrue(manifest["not_promotion_receipt"])
|
||||
|
||||
def test_rendered_html_is_human_review_entrypoint_not_promotion_action(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
result = gallery.write_gallery_artifacts(Path(tmpdir), Path(tmpdir) / "receipt.json")
|
||||
output_dir = Path(tmpdir)
|
||||
|
||||
index_html = Path(result["html_path"]).read_text(encoding="utf-8")
|
||||
family_html = (output_dir / "families" / "blue-professional.html").read_text(encoding="utf-8")
|
||||
|
||||
for page_html in (index_html, family_html):
|
||||
self.assertIn('data-review-status="pass"', page_html)
|
||||
self.assertIn('data-review-status="needs_fix"', page_html)
|
||||
self.assertIn('data-review-status="reject"', page_html)
|
||||
self.assertIn("human_review_status=pending", page_html)
|
||||
self.assertIn("promotion_action=no_change_until_human_pass", page_html)
|
||||
self.assertIn("beautiful-production-review-decisions-v1", page_html)
|
||||
self.assertIn("review-decisions-json", page_html)
|
||||
self.assertIn("does not automatically modify production/default", page_html)
|
||||
self.assertIn("skills/lark-slides/references/receipts/production-review/beautiful-34-gallery.json", page_html)
|
||||
self.assertIn("apply script", page_html)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user