@@ -6,7 +6,7 @@ Use this checkpoint on comp-led builds after producing the initial component kit
Keep the measured spec's region IDs. Include every visible region: produced raster assets and working HTML/CSS/SVG for text, controls, patterns, decoration and layout elements. A region rendered in code needs an actual review document, not a promise to implement it later. Use semantic HTML for content and controls. Do not flatten the page or combine unrelated regions to avoid review. Report omitted regions so the user can mark what is missing.
For a repeated code pattern, give instances of the same component and role the same `reviewGroup` name. Group peers of the same kind, not a container with its contents or unrelated text roles. Keep every instance and its region ID in the manifest, in the same kit document. The user can inspect instances and explicitly apply one decision to the unreviewed group. Unique raster assets still require their own review; grouping never removes inventory or gate checks.
For a repeated code pattern, give instances of the same component and role the same `reviewGroup` name. Group peers of the same kind, not a container with its contents or unrelated text roles. Keep every instance and its region ID in the manifest, in the same kit document. The review opens with one item per group and shows its instances together. One explicit group decision applies to its unreviewed instances; the user can open an instance to leave an exception. Existing decisions are preserved. Unique raster assets still require their own review; grouping never removes inventory or gate checks.
Before producing assets, inspect each reference crop against its named subject. Coarse grid cells and automatic ink snapping can include neighbors or omit parts of a compound element. Correct the measured region with an explicit normalized `box`; do not build to a known bad crop. Check the code preview contains the complete component before presenting it. The capture tool refuses content cut off by the review crop.
expect(draft.decisions['room-0'].feedback).toBe('Fix this one');expect(reviewUnits(p,draft)[0]).toMatchObject({pending:0,kind:'feedback',stateLabel:'1 need work'});
conststatusMessage=error||(uncommitted?'Save or cancel your open feedback before sending.':submitted?(options.preview?'Preview submitted. No run changed.':'Review submitted.'):stats.hasFeedback?'Ready to send for corrections.':stats.pending?`${stats.pending} left to review`:!draft.inventoryConfirmed?'Confirm the map is complete.':'Ready to continue.');
conststatusMessage=error||(uncommitted?'Save or cancel your open feedback before sending.':submitted?(options.preview?'Preview submitted. No run changed.':'Review submitted.'):stats.hasFeedback?'Ready to send for corrections.':stats.pending?`${pendingUnits} left to review`:!draft.inventoryConfirmed?'Confirm the map is complete.':'Ready to continue.');
<header><div><h1>${submitted?'Review record.':assembled?'Review the assembled page.':'Review the components.'}</h1><p>${esc(packet.title)} <span>· Round ${packet.round}</span></p></div>${submitted?'<span class="badge">Submitted · read-only</span>':options.preview?'<span class="badge">Interactive preview</span>':''}</header>
${options.preview?'<p class="preview-note">Historical hotel artwork for testing this interface. Decisions stay in this preview; no run is changed.</p>':''}
${history&&!assembled?`<section class="round-summary" aria-label="Changes since previous round"><p><strong>${stats.pending}${stats.pending===1?'component':'components'} to review</strong><span>${summaryDetails}</span></p>${stats.pending?`<button id="review-changes" class="icon-button" aria-label="Next to review" title="Next to review">${icon('next')}</button>`:''}${history.removed.length?`<details><summary>Removed from the map</summary><p>${history.removed.map(item=>esc(item.name)).join(' · ')}. Confirm these omissions are intentional before accepting the map.</p></details>`:''}</section>`:''}
${history&&!assembled?`<section class="round-summary" aria-label="Changes since previous round"><p><strong>${pendingUnits}${pendingUnits===1?'item':'items'} to review</strong><span>${summaryDetails}</span></p>${stats.pending?`<button id="review-changes" class="icon-button" aria-label="Next to review" title="Next to review">${icon('next')}</button>`:''}${history.removed.length?`<details><summary>Removed from the map</summary><p>${history.removed.map(item=>esc(item.name)).join(' · ')}. Confirm these omissions are intentional before accepting the map.</p></details>`:''}</section>`:''}
${finished&&!assembled?`<section class="review-summary" id="review-summary" tabindex="-1"><div class="completion-mark" aria-hidden="true">${checkIcon}</div><h2>${submitted?'Review sent.':'All components reviewed.'}</h2><p>${stats.approved} approved · ${stats.revisions} flagged for repair${draft.missing.length?` · ${draft.missing.length} missing`:''}</p><p>${submitted?'Your decisions are saved.':stats.hasFeedback?'Send your feedback to start the next repair round.':'Confirm nothing is missing, then approve and continue.'}</p><div class="summary-decisions">${packet.components.map(item=>{constdecision=draft.decisions[item.id];conststate=stateFor(item);return`<button data-select="${esc(item.id)}"><strong>${esc(item.name)}</strong><span>${state.kind==='pending'?'Not reviewed':state.kind==='feedback'?'Needs work':'Approved'}</span>${decision?.action==='revise'?`<small>${esc(decision.feedback||'No note — agent will diagnose.')}</small>`:''}</button>`;}).join('')}${draft.missing.map(item=>`<button data-select="${esc(item.id)}"><strong>${esc(item.name)}</strong><span>Missing</span><small>${esc(item.feedback)}</small></button>`).join('')}</div></section></div>${notice?`<div class="review-form">${notice}</div>`:''}`:c?`
${finished&&!assembled?`<section class="review-summary" id="review-summary" tabindex="-1"><div class="completion-mark" aria-hidden="true">${checkIcon}</div><h2>${submitted?'Review sent.':'All components reviewed.'}</h2><p>${stats.approved} approved · ${stats.revisions} flagged for repair${draft.missing.length?` · ${draft.missing.length} missing`:''}</p><p>${submitted?'Your decisions are saved.':stats.hasFeedback?'Send your feedback to start the next repair round.':'Confirm nothing is missing, then approve and continue.'}</p><div class="summary-decisions">${units.map(u=>{constitem=u.representative;constdecision=draft.decisions[item.id];conststate=stateFor(item);return`<button data-select="${esc(item.id)}"><strong>${esc(u.label)}</strong><span>${u.kind==='pending'?'Not reviewed':state.kind==='feedback'?'Needs work':'Approved'}</span>${decision?.action==='revise'?`<small>${esc(decision.feedback||'No note — agent will diagnose.')}</small>`:''}</button>`;}).join('')}${draft.missing.map(item=>`<button data-select="${esc(item.id)}"><strong>${esc(item.name)}</strong><span>Missing</span><small>${esc(item.feedback)}</small></button>`).join('')}</div></section></div>${notice?`<div class="review-form">${notice}</div>`:''}`:c?`
${history?`<div class="repair-context">
${viewingPrevious&&repair?.prior?.action==='revise'?`<section class="previous-feedback" aria-label="Previous feedback"><h3>Previous feedback <span>· Round ${repair.feedbackRound}</span></h3><blockquote>${esc(repair.prior.feedback||'No written feedback was supplied.')}</blockquote>${repair.prior.split?'<p>Requested: split into separately reviewable components.</p>':''}</section>`:repair?.carried?`<p class="kept-approval">Unchanged · approval kept</p>`:''}
</div></div>${!assembled?`<div class="component-details"><div class="material">${icon(presentation!.code?'code':'image')}<strong>${esc(materialLabel)}</strong><span>${v?.material?`${v.material.width}×${v.material.height} px`:''}</span></div>${vp.stage==='components'&&presentation?.captured&&!v?.preview.isolation?'<p class="layering">Legacy region capture · may include overlapping components.</p>':''}${v?.context?.layering&&(isRaster||useContext)?`<p class="layering">${esc(v.context.layering)}</p>`:''}
</div></div>${!assembled&&!groupOverview?`<div class="component-details"><div class="material">${icon(presentation!.code?'code':'image')}<strong>${esc(materialLabel)}</strong><span>${v?.material?`${v.material.width}×${v.material.height} px`:''}</span></div>${vp.stage==='components'&&presentation?.captured&&!v?.preview.isolation?'<p class="layering">Legacy region capture · may include overlapping components.</p>':''}${v?.context?.layering&&(isRaster||useContext)?`<p class="layering">${esc(v.context.layering)}</p>`:''}
<p class="component-note">${esc(v!.note)}</p>
</div>`:''}</div><div class="review-form">${notice}${viewingPrevious?'<p class="previous-notice">Viewing the previous round. Return to Current to make a decision.</p>':''}${submitted?`<div class="record-verdict"><strong>${d?.action==='approve'?'Approved':d?.action==='revise'?'Changes requested':'Not reviewed'}</strong><span>Submitted in round ${packet.round} · read-only</span></div>`:`<div class="decisions" role="group" aria-label="Decision for ${esc(c.name)}">${!assembled?`<div class="decision-title"><strong>Your review <span>Round ${packet.round}</span></strong>${viewingPrevious?'<p>Return to Current to review this round.</p>':''}</div>`:''}<button id="approve" class="decision-approve ${d?.action==='approve'?'approved':''}" aria-pressed="${d?.action==='approve'}">${assembled?(sending?'Sending…':'Approve & continue'):targets.length>1?`Approve ${targets.length} instances`:'Looks good'}</button><button id="revise" class="decision-revise ${d?.action==='revise'?'revise':''}" aria-pressed="${d?.action==='revise'}">${targets.length>1?`Revise ${targets.length} instances`:'Needs work'}</button>${d&&!assembled?`<button id="clear" class="quiet icon-button" aria-label="Clear decision" title="Clear decision">${icon('undo')}</button>`:''}</div>`}
</div>`:''}</div><div class="review-form">${notice}${viewingPrevious?'<p class="previous-notice">Viewing the previous round. Return to Current to make a decision.</p>':''}${submitted?`<div class="record-verdict"><strong>${d?.action==='approve'?'Approved':d?.action==='revise'?'Changes requested':'Not reviewed'}</strong><span>Submitted in round ${packet.round} · read-only</span></div>`:`<div class="decisions" role="group" aria-label="Decision for ${esc(c.name)}">${!assembled?`<div class="decision-title"><strong>Your review <span>Round ${packet.round}</span></strong>${viewingPrevious?'<p>Return to Current to review this round.</p>':''}</div>`:''}<button id="approve"${!targets.length?'disabled':''} class="decision-approve ${d?.action==='approve'?'approved':''}" aria-pressed="${d?.action==='approve'}">${assembled?(sending?'Sending…':'Approve & continue'):targets.length>1?`Approve ${targets.length} instances`:'Looks good'}</button><button id="revise"${!targets.length?'disabled':''} class="decision-revise ${d?.action==='revise'?'revise':''}" aria-pressed="${d?.action==='revise'}">${targets.length>1?`Revise ${targets.length} instances`:'Needs work'}</button>${d&&!assembled&&!groupOverview?`<button id="clear" class="quiet icon-button" aria-label="Clear decision" title="Clear decision">${icon('undo')}</button>`:''}</div>`}
${edit?`<form id="feedback-form"><div class="feedback-fields"><label class="feedback-field">What needs to change?<textarea id="feedback" aria-describedby="feedback-hint">${esc(edit.feedback)}</textarea></label><p id="feedback-hint" class="feedback-hint">Optional — leave blank for the agent to diagnose.</p>${!assembled?`<label class="check"><input id="split" type="checkbox" ${edit.split?'checked':''}> Split into separately reviewable components</label>`:''}</div><div class="feedback-actions"><button id="cancel-feedback" type="button" class="quiet">Cancel</button><button id="save-feedback" type="submit" class="primary">${assembled?'Send feedback':isLast?'Save & finish review':'Save & next'} <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 12h15m-6-6 6 6-6 6"/></svg></button><span class="shortcut-hint">${shortcutLabel}</span></div></form>`:d?.action==='revise'?`<p class="saved-feedback">${esc(d.feedback||'No note — agent will diagnose.')}</p>`:''}
${assembled?`<p class="page-review-status" role="status">${esc(error||(submitted?'Your decision is saved.':sending?'Sending…':edit?'':'Approval confirms the composition and that nothing is missing.'))}</p>`:''}</div>`:missing?`<p>This piece will be added to the unresolved inventory.</p><label class="feedback-field">Name<input id="missing-name" value="${esc(missing.name)}"></label><label class="feedback-field">What is missing?<textarea id="missing-feedback">${esc(missing.feedback)}</textarea></label><div class="coordinates">${(['x','y','w','h']asconst).map(k=>`<label>${{x:'Left',y:'Top',w:'Width',h:'Height'}[k]} %<input type="number" data-coordinate="${k}" value="${Math.round(missing.box[k]*1000)/10}" min="0" max="100" step="0.1"></label>`).join('')}</div><button id="remove-missing">Remove this mark</button></div>`:'<p>No components supplied.</p></div>'}
panes.forEach(p=>{constpannable=p.scrollWidth>p.clientWidth+1||p.scrollHeight>p.clientHeight+1;p.classList.toggle('pannable',pannable);p.style.cursor=expandedComparison?'':'zoom-in';p.setAttribute('role',expandedComparison?'region':'button');p.title=expandedComparison?(pannable?'Move your pointer to pan. You can also scroll, swipe, or use arrow keys.':''):'Click to enlarge comparison';});
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.