After lesson 06, Laya suggests seven things to cover, and most of them are right. The tempting next step is to cover all seven automatically. In this lesson we do the opposite: nothing is covered until a person says yes. Checkpoint: redact-07-review, after redact-06-laya

Why a person decides

A model’s mistakes come in two kinds, and they cost very different amounts. If the model writes the output directly, both kinds of mistake ship silently. With a person in between, a false suggestion costs a click, and a miss is still on screen to catch. The model saves you effort; it doesn’t take the responsibility. That’s Redact’s trust boundary: a suggestion is evidence, and only a decision makes a black box. About Redact’s trust boundary goes further.

Suggestions and marks are different things

In the code, a suggestion (a candidate) has a status: proposed, accepted or rejected. A mark is the black box the exporter paints. The only way from one to the other is accepting it. There’s also a gate: while any suggestion is still proposed, Done stays disabled. You can’t save a copy with an open question in it.

1. Get this lesson’s code

Stop the app and the service if they’re running. From the repository root, redact-course, bring in this lesson’s commit:
No packages change, so there’s nothing to install. To see every change, open the comparison on GitHub.

2. Read how accepting works

Open src/features/redact/workflow-domain.ts and find acceptCandidate:
It does nothing for a suggestion that’s already accepted, so clicking twice is harmless. It does work on a rejected one, so you can change your mind after a Reject. It creates an ordinary mark at the suggestion’s position, with source: "accepted" so you can tell later where it came from. From here on, the exporter treats it exactly like a box you drew by hand. The rest of the function marks the suggestion accepted and adds a line to the audit:
rejectCandidate is the same shape, but it creates no mark and logs Rejected local suggestion.

3. Read the gate

finishReview runs when you select Done:
In lesson 06, RedactApp.tsx called it with { allowUnresolved: true }; this lesson removes that. The review screen also counts open suggestions and disables Done while there are any:
So the rule is enforced twice: once in the interface, and once in the data layer in case the interface is ever wrong.

4. Start the service and the app

In one terminal, npm run qvac:service. In a second, npm run dev -- --port 3101. Both models are already cached, so there’s no download.

5. Prepare the chat again

Open localhost:3101, upload public/test-files/redact/chat-private.png, choose Private, and type:
Select Prepare for review. After about half a minute the review screen opens.

6. Notice the gate

Above the document, a banner reads:
Done is disabled. Each of the seven cards now has Accept and Reject buttons, and its percentage now reads score. Safe-share preview has no black boxes yet.

7. Decide

On the name card, select Accept. A black box covers Maya Chen in the preview, a new entry appears in the Redactions list, and the banner drops to 6. Under Recent activity you’ll see Accepted local suggestion with name · Maya Chen. On the email card, select Reject. The email stays readable, no redaction is added, and Recent activity shows Rejected local suggestion. Accept the remaining five. The banner disappears and Done becomes available. Each decided card now shows accepted or rejected where its score was. A rejected card keeps an Accept button, in case you change your mind. In the Redactions list, accepted suggestions are named by their label, such as name or other; only marks you drew yourself say Manual redaction. An accepted suggestion is now an ordinary redaction: drag it on Original to move it, or drag a corner to resize it.

8. Save and check the copy

Select Done, then Save copy. Open the downloaded chat-private.redacted.png outside the browser. The name, address, phone number, account number, reference and the “amount” line are solid black. maya.chen@example.com is still readable, because you rejected it. Rejecting a suggestion means choosing to leave that text visible.

If something goes wrong

  • Done stays disabled after deciding everything. On a multi-page PDF, use Next → to check the other pages; the count covers every page.
  • A box covers too little. Accepting copies the OCR outline exactly; drag a corner to enlarge it, like any manual mark.
  • You accepted something by mistake. Remove that redaction from the Redactions list; its suggestion becomes rejected, and its Accept button lets you bring it back.

9. Check your work

Stop both terminals, then:
npm test reports Tests 67 passed (67).

So what just happened?

Suggestions became questions a person answers. Nothing is covered until it’s accepted, nothing is saved until every suggestion has an answer, and every answer is written to the audit. An accepted suggestion becomes an ordinary mark, so the exporter didn’t need to change at all.

Try it yourself

Accept the name suggestion, then remove that redaction from the Redactions list. Watch the card change to rejected and Recent activity record the removal. Then select Accept on that card again and watch the redaction come back. Why do you think removing an accepted mark rejects the suggestion, rather than putting it back to proposed?

Where to next

Next: Keep working when analysis fails (lesson 08)