Verify governance concerns with evidence gathering and automated analysis
Adjudicates a governance concern by reading the actual source, comparing it to what was flagged, and returning an evidence-backed verdict: JUSTIFIED (proceed) or REVERT.
This is the manual/adjudication front end for the same concern class the governance-verifier
agent handles automatically. Use this skill for a quick in-session ruling; delegate to the
agent when the concern needs its own isolated context.
GOVERNANCE: N violation(s)).hooks/scripts/governance-check.sh is a PostToolUse (Edit/Write) advisory hook — it
always exits 0 and never blocks. It only runs on source paths (*/src/*, .ts/.tsx/.js/.jsx/.py/.rs/.go),
skips test files (*.test.*, *.spec.*, *__tests__*), and flags four categories:
| Tag | Rule | Message fragment |
|-----|------|------------------|
| [ANY] | as any cast in production code | N 'as any' cast(s) at line(s): ... |
| [API] | unwrapErr() call | use .error property |
| [LOG] | uncommented console.log | use structured logger |
| [URL] | hardcoded localhost:PORT | use env config |
It also appends a WARN entry (category: code-quality, severity: medium) to
.claude/governance.json sentinelLog via append_sentinel_log. That is the entire blast
radius — there is no blocking, no test-mismatch detector, and no scope detector in this hook.
Test-mismatch and scope concerns are your judgment call or the agent's, grounded in the steps below.
Read back the exact hook line or user claim. Pin down:
code-quality (the four tags above), test-mismatch, or scope-creep.undefined, code returns null").Test-vs-implementation mismatch — read the function's real return path:
grep -n "functionName" src/path/to/impl.ts # find the definition
grep -n -A6 "functionName" src/path/to/impl.ts # inspect the return type + body
Code-quality flag — confirm the flagged construct is real (not in a comment/string):
grep -n 'as any' src/path/to/file.ts # verify line(s) the hook reported
Scope concern — the directive is the authority, not the workstreams array:
jq -r '.constitution.directive' .claude/governance.json # the binding scope statement
jq -r '.workstreams[]?.id // "none"' .claude/governance.json # may be empty ([]) — that is NOT a violation
If behavior may have changed recently, check history before ruling:
git log --oneline -5 -- src/path/to/impl.ts
git show HEAD:src/path/to/impl.ts | grep -n "functionName"
Cite specific line numbers. One verdict, one reason, one action.
## Governance Verification Report
**Concern**: <what was flagged>
**Source**: <hook name / manual>
### Evidence
| File | Line | Finding |
|------|------|---------|
| src/foo.ts | 42 | `getTask(id): Task \| null` returns `null` |
### Verdict: ✅ JUSTIFIED
**Reasoning**: line 42 explicitly returns `null`; the test change matches.
**Action**: Proceed. No implementation change needed.
Or:
### Verdict: ❌ REVERT RECOMMENDED
**Reasoning**: the test expected `undefined` per TS convention; the impl regressed to `null`.
**Action**: Revert the test; fix the implementation to return `undefined`.
If evidence is inconclusive, recommend manual review — do not auto-proceed.
Optional. The forge-ui Express API on port 5051 exposes POST /api/governance/sentinel; it
requires type, source, message (400 otherwise) and is only reachable while
forge-ui (npm run dev / the dashboard) is running:
curl -s -X POST http://localhost:5051/api/governance/sentinel \
-H "Content-Type: application/json" \
-d '{"type":"INFO","severity":"low","source":"verify-governance",
"message":"Verification complete: change JUSTIFIED",
"context":{"verdict":"JUSTIFIED","file":"src/foo.ts"}}'
If the server is down, skip it — the advisory hooks already write the file directly; do not block the verdict on a failed curl.
Hook output during an Edit:
GOVERNANCE: 2 violation(s) in api-client.ts
[ANY] 2 'as any' cast(s) at line(s): 88,141
Evidence gathered:
grep -n 'as any' src/services/api-client.ts
# 88: const data = res.body as any;
# 141: return payload as any;
Both are real, uncommented casts in production code. Verdict:
### Verdict: ❌ REVERT RECOMMENDED
**Reasoning**: lines 88 and 141 use `as any`, defeating type safety in a public service.
**Action**: Type `res.body` via the response DTO; give `payload` its declared return type.
Claim: "test now uses toBeNull() but was toBeUndefined() — is that right?"
grep -n -A2 "getTask" src/core/TaskQueue.ts
# 98: getTask(taskId: string): AgentTask | null {
# 100: return queuedTask?.task || null;
### Verdict: ✅ JUSTIFIED
**Reasoning**: `getTask` returns type `AgentTask | null` and returns `null` (line 100).
The `toBeNull()` assertion matches the contract.
**Action**: Proceed with the test update. No implementation change.
/verify-gov and no commands/verify-governance.md
file. Invocation is the skill name only (user-invocable: true). Don't tell the user to run a
command that doesn't exist; for a background/isolated ruling, hand off to the governance-verifier agent.security-*-guard.sh PreToolUse guards, which
are a different concern class this skill does not adjudicate.*.test.* / *.spec.* / __tests__, so a
"test assertion inconsistency" is never emitted by governance-check.sh. Treat test-mismatch as a
human/agent judgment grounded in the implementation — not as a hook output.workstreams is normal, not a violation. .claude/governance.json workstreams is
often []. jq '.workstreams[].id' returning nothing means "no workstreams defined," not
"out of scope." Scope authority is .constitution.directive.POST /api/governance/sentinel is served by forge-ui
on port 5051, up only when the dashboard is running. It 400s without type+source+message.
If it's down, the hooks' own append_sentinel_log has already written to .claude/governance.json —
never fail a verdict because the HTTP log didn't land..claude/governance.json is the read authority, forge-orchestrator's .forge/state.json is a
different store. This skill reads governance state under .claude/; do not conflate it with the
Rust orchestrator's .forge/ state.governance-verifier agent — the isolated-context automation for this same concern class.hooks/scripts/governance-check.sh — the advisory source of code-quality flags.crucible-audit skill — for auditing whether the test suite itself catches real bugs
(a superset concern), when the question is test quality rather than one flagged change.Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer