comply
Take a change that carries risk (a launch, a new vendor, a new use of personal data) to a risk position its owner has signed: a risk register scored inherent and residual, a DPIA when personal data is processed, the evidence behind every control the ratings rely on, a script that checks the register, and a sign-off only the named owner can give.
- Use it when
- Use when the user says "get this ready for risk sign-off", "run the comply loop", "what do we need before we can launch this", or needs a register, a DPIA and audit evidence that agree with each other.
- Comes with
- The grc pack
- Where you decide
- Check (G8): a script decides
- Sign-off (G8.1): you decide
- Size
- 5 stages · 2 gates · up to 3 revision rounds
Installs the loop as an invokable skill, plus every skill its stages run.
Other ways to install
Every loop in its pack, with their skills:
The loop alone, without its stage skills (each stage falls back to an inline version):
In Claude Code, the grc plugin includes it:
The loop
%%{init: {'theme':'base','themeVariables':{'fontFamily':'Segoe UI, Helvetica, Arial','fontSize':'15px','lineColor':'#9AA5B1'},'flowchart':{'curve':'basis','rankSpacing':70,'nodeSpacing':50,'padding':16}}}%%
flowchart LR
classDef gen fill:#E8F0FE,stroke:#4C7DF0,stroke-width:1.5px,color:#1A3A8F;
classDef review fill:#FDEAEA,stroke:#E05B5B,stroke-width:1.5px,color:#8A1F1F;
classDef gate fill:#FBE3A2,stroke:#D9971E,stroke-width:2px,color:#6B4500,font-weight:bold;
classDef ship fill:#E6F7EC,stroke:#34A853,stroke-width:2px,color:#0F6B33,font-weight:bold;
register["register<br/><small>risk-register</small>"]:::gen
assess["assess<br/><small>dpia</small>"]:::gen
evidence["evidence<br/><small>soc2-evidence-map</small>"]:::gen
check["check<br/><small>risk-register</small>"]:::review
sign-off["sign-off<br/><small>doc-critique</small>"]:::gate
G8{"G8 · mechanical"}:::gate
G8_1{"G8.1 · human"}:::gate
DONE(["complete"]):::ship
register --> assess
assess --> evidence
evidence --> check
check --> G8
G8 == "READY" ==> sign-off
sign-off --> G8_1
G8_1 == "PROCEED" ==> DONE
G8 -- "NOT READY (max 3)" --> register
G8_1 -- "REVISE (max 3)" --> register
Stages
| # | Stage | What it does | Skills | Gate |
|---|---|---|---|---|
| 1 | register generate | Write the change's risks as cause, event and consequence, scored inherent and residual on a stated scale, each with a named owner and a treatment. | risk-register | — |
| 2 | assess generate | Screen for a DPIA and, where one is needed, score the harm to people; each risk to people left at medium or high gets its own row in the register. | dpia | — |
| 3 | evidence generate | For every control the residual ratings and the DPIA's measures rely on, name the evidence that it operates today, and mark the gaps. | soc2-evidence-map | — |
| 4 | check verify | Run the register's own check, after evidence gaps have put residual ratings back where the evidence leaves them. | risk-register | G8 — a script decides READY · NOT READY · BLOCKED |
| 5 | sign-off gate | The named owner accepts each residual risk, or doesn't. The critique informs that decision; it does not make it. | doc-critique | G8.1 — you decide PROCEED · PROCEED WITH CONDITIONS · REVISE · RECONSIDER · BLOCKED |
One change, from its risks to a signature. Each of the three documents is useful alone. The loop exists for the places where they disagree. A register can rate a risk low because of a control that leaves no record. A DPIA can find a high risk to people that never reaches the register its owner reads. An evidence map can show a gap that nobody connects to the rating that relied on it. The loop makes the three agree. Then the register's own script checks them, and the person who owns the risk decides.
This loop prepares material for a qualified reviewer: a DPO, a risk committee, an auditor. It is not legal or audit advice, and every document it produces says so once, at the top.
How to run this loop
- Register the change's risks. Run
risk-registerwith the change as its scope and the objective it threatens. Saverisk-register.csv. Owners come from the person; a missing owner stays an error to resolve, never a guessed name. - Screen and assess personal data. Run
dpiaon the processing the change introduces.- When the screening finds no criteria that apply, keep its short screening record and go on.
- When a DPIA is needed, complete it. Then give each risk to people still at medium or high residual its own register row, with the harm to people as the consequence, the same owner as the DPIA measure, and
DPIAin its controls cell. The DPIA keeps scoring harm to people; the register row is how its owner sees it.
- Evidence every control the ratings rely on. List the controls named in the register's residual ratings and the DPIA's in-place measures, and run
soc2-evidence-mapon that list. Use the organisation's SOC 2 scope when it has one; otherwise use the skill's default, Security only, tagged[assumption]. - Put the evidence gaps back into the register. A residual rating can count only controls that operate today. For each control the map marks
gap:- set the residual likelihood and impact of every risk that relied on it back to their inherent values;
- move the control to a dated action under the treatment. A
partialcontrol keeps its credit only for what its evidence covers; say what that is in the summary for the owner. Don't lower a rating to make a heat map look better.
- Check at G8. Run the register's script on the final CSV:
# Claude Code (the loop and risk-register installed side by side)
python3 "${CLAUDE_SKILL_DIR}/../risk-register/scripts/check_register.py" risk-register.csv --top 5 --out register-check.txt
# Other IDEs (from the folder the skills were installed into)
python3 risk-register/scripts/check_register.py risk-register.csv --top 5 --out register-check.txt
The exit code is the verdict: 0 is READY, 1 is NOT READY, 2 is BLOCKED. NOT READY returns to register to fix what the script names, then runs check again. Report its warnings to the person; don't edit scores to silence them.
- Critique, then put the decision to the owner at G8.1. Run
doc-critiqueon the summary the owner will read. Then show them:- the residual heat map from the script, as printed;
- every risk they are asked to accept;
- the evidence gaps and their dates;
- the DPIA's view on prior consultation. Each owner accepts their own risks. A high or critical residual risk that its own owner accepts needs a sign-off from someone above them, named in the summary.
Verdicts
Defined in contracts/terminals.json.
- G8 emits
READY,NOT READYorBLOCKED, from the script's exit code alone. - G8.1 emits:
PROCEED: every residual risk is accepted or treated, by its named owner.PROCEED WITH CONDITIONS: accepted, subject to named actions with dates, each recorded as a control anddue_dateon its risk.REVISE: the owner rejects a rating or a treatment. Return toregisterwith their reasons.RECONSIDER: the change shouldn't go ahead as designed, for example when a residual risk to people stays high and the design has to change before prior consultation. The loop ends here.BLOCKED: no owner is available, or the DPO's advice is required and not yet given.
Non-interactive runs
With no person present, G8.1 cannot be satisfied. Run every stage through G8, deliver the documents, and emit BLOCKED: need sign-off from <the named owners>. Never accept a risk on someone's behalf, never fill an owner, a retention period or a vendor location with a plausible guess, and leave the DPIA's DPO advice and decision fields blank.
When a stage's skill is not installed
Name the missing skill and skilldrop as its source, do the minimal inline version of that stage, and record that it ran degraded. Without risk-register, G8 has no script. Say so, check the register by hand against the script's rules (every required field, owners that name a person, residual never above inherent, dates that are dates), and mark G8 degraded. Never skip G8.1.
Run log (opt-in)
Only when the environment variable SKILLDROP_LOOP_LOG is set to a file path: after each gate's verdict, append one JSON line to that file. Nothing else is recorded, and nothing is sent anywhere. When the variable isn't set, or you can't read it, skip this section.
printf '%s\n' '{"ts":"2026-10-19T14:03:00Z","loop":"comply","stage":"check","gate":"G8","verdict":"READY","round":1}' >> "$SKILLDROP_LOOP_LOG"
Fields: ts (UTC), loop, stage, gate (null for a stage without one), verdict (the gate's exact word), and round (1 for the first attempt, counting returns under the cap). The log holds verdicts only: never a risk, an owner's name or any personal data. skilldrop loop-stats summarises the file.
Quality bar
- The three documents agree. Every DPIA risk at medium or high residual has a register row, and every control a residual rating relies on appears in the evidence map.
- A residual rating counts only evidenced controls. A control with an evidence gap gives no credit until the evidence exists, and the gap has a dated action.
- G8 is the script's exit code. The register reaches its owner only with zero errors.
- Only a named owner accepts a risk. High and critical residual risks accepted by their own owner carry a second, named sign-off.
- Not legal or audit advice, said once. The DPO's advice, the decision and the sign-off fields are left for the people who give them.
Anti-patterns to avoid
- ❌ Filing the DPIA beside the register instead of into it. A high risk to people that isn't on the owner's list doesn't get signed off; it gets missed.
- ❌ Leaving a residual rating on a control the evidence map marked
gap. That is a planned control scored as a real one, the exact thing the register bans. - ❌ Editing the register to turn G8 green. Fix the risk the script names; don't delete the row or soften the score.
- ❌ Running the evidence map on the whole SOC 2 scope. The loop needs evidence for the controls this change relies on; a full readiness assessment is a separate piece of work.
- ❌ Self-signing at G8.1. A clean check says the register is well-formed. It cannot say the risk is acceptable.
- ❌ Writing a guessed vendor location or retention period to complete the DPIA. It stays
[to confirm: …]and becomes a DPO question.