| name | countersign |
| description | Review and sign off pending human decisions in the findings disposition ledger — machine-refuted false positives awaiting an LDAP-verified countersignature, and queued needs-review items. Renders each pending decision as a self-contained card (claim + refutation + evidence) so nothing needs to be remembered from the original reports, records decisions through the countersign workbench, and rebuilds the cumulative reports. Use when asked to "countersign findings", "sign off false positives", "review pending refutations", "what's waiting for my signature", or "clear the disposition queue". |
| argument-hint | [<findings-root>|<product>/<repo>] [--identity <kerberos-id>] |
| user-invocable | true |
| allowed-tools | ["Read","Write","Glob","Grep","AskUserQuestion","Bash(python3 *scripts/countersign.py:*)","Bash(python3 *scripts/validate_report.py:*)","Bash(git:*)","Bash(ls:*)","Bash(wc:*)","Bash(jq:*)"] |
countersign
The human inbox for the disposition ledger. Machine false-positive
evidence pends (refuted_awaiting_signoff) until an LDAP-verified human
decides; undetermined findings and audit-valve samples queue in
needs_review. Both are derived state — this skill materializes them as
decision cards and records the human's determinations through
scripts/countersign.py, never by hand-assembling ledger events.
Paths: <skill-base> is this skill's base directory; <harness> =
<skill-base>/../... The default findings root is the
analysis-results/findings sibling of the harness checkout; a
<product>/<repo> argument narrows to one repo directory.
What signing means (state it to the user up front, once): a
countersign records validity: false_positive attributed to them,
LDAP-verified. The finding stays in the refuted register — fuzzing or
live validation can still override the signature with a reproducing
exploit (fp_overridden). Rejecting a refutation (keep_open) records a
human confirmed and requires their own rationale. Deferring records
nothing.
Procedure
1. Build the inbox
python3 <harness>/scripts/countersign.py queue \
--root <findings-root> --out ./countersign-queue.md \
--json-out ./countersign-queue.json --base <findings-root>/..
(Use --repo-dir for a single-repo argument.) Read the JSON summary. If
nothing is pending, tell the user the inbox is empty — name the last
rebuild time of the newest cumulative report so "empty" is credible —
and stop.
2. Identify the signer
One AskUserQuestion for the kerberos ID (offer the workstation username
as the recommended option; --identity from the arguments skips this).
Do NOT verify yet — verification happens once, at recording time, inside
the workbench. Tell the user recording will be refused if LDAP
verification fails (VPN required).
3. Present ONE card per question
For each awaiting-signoff card, one AskUserQuestion call with ONE
question. Attach the card's full text as the preview of every option so
the evidence is on screen at decision time:
- Confirm false positive — "adopts the verifiers' rationale as your
determination unless you dictate your own (use Other to dictate)"
- Keep open — reject the refutation — "records a human
confirmed;
you MUST provide your own rationale (use Other to state it, or answer
and provide it at the follow-up)"
- Defer — "leave pending; it stays in the inbox"
Batch at most 4 findings per AskUserQuestion call (one question each)
when the queue is long; never merge multiple findings into one question —
that recreates the wall-of-text failure this skill exists to fix. A
keep_open answer without a rationale gets exactly one follow-up
question; if still none, treat as defer and say so.
Then walk pending needs_review items the same way (confirm → the
suggested disposition becomes a recorded event via the queue-file flow;
reject → record a resolution_note). This includes
needs_manual_test items — unconfident triage confirmations awaiting a
human PoC or live validation.
Attention cards (the queue's middle section) are derived states that
need eyes, not always signatures: fp_overridden (an execution proof
overturned a human FP — informational, acknowledge and move on),
fp_reassertion_blocked (a SECOND independent signer must concur to
re-assert FP against a PoC — their own rationale mandatory), and
conflict (both confirmed and false_positive in the ledger — adjudicate
with your own rationale either way). Present these after the signoff
cards, same one-card-per-question pattern.
4. Record through the workbench
Annotate the generated countersign-queue.md with the collected
decisions (Write: mark [x] and fill RATIONALE: lines — leave adopted
rationales blank so the tool applies the canonical adopted-determination
framing), then ONE call:
python3 <harness>/scripts/countersign.py apply ./countersign-queue.md \
--identity <kerberos-id>
The workbench LDAP-verifies once, appends canonical events (idempotent
per signer-day), rebuilds the cumulative report pair per touched repo,
and prints a receipt. If verification fails, report it verbatim and stop
— NEVER work around it, never set ldap_verified by hand.
5. Receipt and follow-through
Show the receipt (decisions recorded, events, new validity summary per
repo). Validate each touched cumulative report
(validate_report.py <repo>-findings-current.json). Remind the user the
ledger artifacts are committable (*-findings-layer.json,
*-findings-current.{json,md}) and offer to commit/push. Clean up
./countersign-queue.{md,json} unless the user wants to keep the
annotated copy.
Gotchas
- The queue file's cards carry
<!-- countersign finding=… layer=… -->
markers the apply parser depends on — do not reformat them.
- Decisions are per-finding, never bulk: "countersign everything" from
the user still means presenting each card (they can answer fast; the
evidence must still have been in front of them).
- This skill records validity determinations only. Resolution changes
(resolved/risk-accepted) belong to
/track-findings ingestion from
Jira/MRs/verification reports.
- Design rationale:
docs/disposition-ledger.md §6/§6a.