Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions skills/vendor-risk-review/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
name: vendor-risk-review
version: "0.1.0"
description: Relationship-level vendor risk judgment that records approved-with-conditions or rejected decisions against a supplied trust policy.
---

# vendor-risk-review

`vendor-risk-review` judges a vendor relationship against a supplied trust policy. It reads bounded contract text, vendor context, policy thresholds, and prior risk record state, then emits a relationship decision plus a data-store append event shape.

The skill is not a clause redliner and does not send stakeholder notifications. Its durable seam is the vendor risk record append through `registry:runx/data-store@0.1.2`; any notify step belongs to a separate governed `send-as` run.

## Inputs

- `contract_text`: bounded contract excerpt or summary.
- `vendor_context`: `{ vendor_ref, history, industry }`.
- `policy`: `{ required_sla_terms, max_liability, data_handling_floor, termination_window, policy_id, created_at }`.
- `data_source_ref`: public-safe source reference for the contract packet.
- `store_id`: pinned data-store identifier.
- `prior_risk_record`: optional `{ version }` read projection result.

## Decision rules

- Approve with conditions when the relationship is usable but recoverable gaps remain, such as an SLA floor miss or termination notice gap.
- Reject when liability is unbounded or above the policy cap, or when required data-handling evidence falls below the policy floor.
- Stop before writing when policy fields are missing, vendor identity is ambiguous, or prior state is unreadable.
- Every condition or rejection reason is grounded in a named supplied policy field.

## Output

The default runner emits:

- `decision`: `{ approved, rejected, reason, conditions, policy_id, created_at }`.
- `risk_record_event`: durable vendor risk event payload.
- `data_store_append_event`: CAS append evidence with store id, aggregate id, idempotency key, before/after version, and package ref.
- `record_written`: true when a complete policy and vendor identity allow the event.
- `escalation`: null for sealed decisions, `needs_human` only for stopped or ambiguous inputs.

## Validation

Run from the repository root:

```bash
runx harness ./skills/vendor-risk-review
```

Expected cases:

- `approve-with-conditions-sla-gap`
- `reject-unbounded-liability-data-floor`
- `missing-policy-stop`
142 changes: 142 additions & 0 deletions skills/vendor-risk-review/X.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
skill: vendor-risk-review
version: "0.1.0"

catalog:
kind: skill
audience: public
visibility: public
role: context

harness:
cases:
- name: approve-with-conditions-sla-gap
runner: judge
inputs:
contract_text: "Vendor provides SOC 2 Type II controls, encryption at rest, a signed DPA, liability capped at USD 50000, and 30 day termination notice. Service uptime commitment is 99.0 percent."
vendor_context:
vendor_ref: "vendor:acme-mailops"
history: "Existing email operations vendor with one renewal cycle."
industry: "email operations"
policy:
required_sla_terms:
min_uptime_percent: 99.9
support_response_hours: 24
max_liability: 100000
data_handling_floor:
- "soc 2"
- "encryption"
- "dpa"
termination_window: 30
policy_id: "trust-policy-2026-06"
created_at: "2026-06-30T00:00:00Z"
data_source_ref: "artifact://vendor-risk/acme-mailops-contract"
store_id: "vendor-risk-store-main"
prior_risk_record:
version: 2
caller:
answers:
agent_task.vendor-risk-review.output:
decision:
approved: true
rejected: false
record_written: true
escalation: null
expect:
status: sealed
receipt:
schema: runx.receipt.v1
state: sealed

- name: reject-unbounded-liability-data-floor
runner: judge
inputs:
contract_text: "Vendor may process customer data without SOC 2 evidence or DPA. Encryption is not guaranteed. Liability is unlimited and termination requires 120 days."
vendor_context:
vendor_ref: "vendor:bulkdata-sync"
history: "New data sync vendor."
industry: "data processing"
policy:
required_sla_terms:
min_uptime_percent: 99.5
support_response_hours: 24
max_liability: 75000
data_handling_floor:
- "soc 2"
- "encryption"
- "dpa"
termination_window: 45
policy_id: "trust-policy-2026-06"
created_at: "2026-06-30T00:00:00Z"
data_source_ref: "artifact://vendor-risk/bulkdata-sync-contract"
store_id: "vendor-risk-store-main"
prior_risk_record:
version: 4
caller:
answers:
agent_task.vendor-risk-review.output:
decision:
approved: false
rejected: true
record_written: true
escalation: null
expect:
status: sealed
receipt:
schema: runx.receipt.v1
state: sealed

- name: missing-policy-stop
runner: judge
inputs:
contract_text: "Vendor provides SOC 2 controls and 30 day termination notice."
vendor_context:
vendor_ref: "vendor:unclear-policy"
history: "New vendor."
industry: "operations"
data_source_ref: "artifact://vendor-risk/missing-policy"
store_id: "vendor-risk-store-main"
expect:
status: failure

runners:
judge:
default: true
type: cli-tool
command: node
args:
- run.mjs
outputs:
decision: object
risk_record_event: object
data_store_append_event: object
record_written: boolean
escalation: string
evidence_summary: object
artifacts:
wrap_as: vendor_risk_packet
packet: runx.vendor_risk_review.v1
inputs:
contract_text:
type: string
required: true
description: "Bounded contract text or summary to judge."
vendor_context:
type: json
required: true
description: "Vendor identifier, history, and industry context."
policy:
type: json
required: true
description: "Trust policy fields and thresholds."
data_source_ref:
type: string
required: true
description: "Public-safe source reference for the contract packet."
store_id:
type: string
required: true
description: "Pinned data-store identifier."
prior_risk_record:
type: json
required: false
description: "Read projection result carrying the current version."
189 changes: 189 additions & 0 deletions skills/vendor-risk-review/evidence/dogfood-receipt.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
{
"acts": [
{
"artifact_refs": [

],
"closure": {
"closed_at": "2026-06-30T12:59:41.313Z",
"disposition": "closed",
"reason_code": "process_exit",
"summary": "cli-tool exited successfully"
},
"criterion_bindings": [
{
"criterion_id": "process_exit",
"evidence_refs": [

],
"status": "verified",
"summary": "cli-tool exited successfully",
"verification_refs": [

]
}
],
"form": "observation",
"id": "act_judge",
"intent": {
"constraints": [

],
"derived_from": [

],
"legitimacy": "Runtime graph execution was admitted by the local harness",
"purpose": "Run graph step judge",
"success_criteria": [
{
"criterion_id": "process_exit",
"required": true,
"statement": "cli-tool exits successfully"
}
]
},
"source_refs": [

],
"summary": "Executed graph step judge",
"target_refs": [

]
}
],
"authority": {
"actor_ref": {
"type": "principal",
"uri": "runx:principal:local_runtime"
},
"attenuation": {
"parent_authority_ref": null,
"subset_proof": null
},
"authority_proof_refs": [

],
"enforcement": {
"profile_hash": "sha256:635fdb0a7eef93911e3c6bd0b25b5e635edba32e0259133042b3a5f1fb19394e",
"redaction_refs": [

],
"setup_refs": [

],
"teardown_refs": [

]
},
"grant_refs": [

],
"scope_refs": [

],
"terms": [

]
},
"canonicalization": "runx.receipt.c14n.v1",
"created_at": "2026-06-30T12:59:41.313Z",
"decisions": [
{
"artifact_refs": [

],
"choice": "open",
"closure": null,
"decision_id": "dec_judge",
"inputs": {
"opportunity_refs": [

],
"selection_ref": null,
"signal_refs": [

],
"target_ref": null
},
"justification": {
"evidence_refs": [

],
"summary": "runtime graph planner selected this node"
},
"proposed_intent": {
"constraints": [

],
"derived_from": [

],
"legitimacy": "Local graph execution requested this node",
"purpose": "Open runtime node judge",
"success_criteria": [

]
},
"selected_act_id": "act_judge",
"selected_harness_ref": null
}
],
"digest": "sha256:e0c87f6fd84049a8aff2ac4cec38028f1832fcca53c468f89508d7772375c8de",
"id": "sha256:9222ecb7a2f81d5542ac095e6f49c5dd97d8ba0127275f50f4bb808f9822d896",
"idempotency": {
"content_hash": "sha256:run_judge_6c4c07a106c6-judge-content",
"intent_key": "sha256:run_judge_6c4c07a106c6-judge-intent",
"trigger_fingerprint": "sha256:run_judge_6c4c07a106c6-judge-trigger"
},
"issuer": {
"kid": "runx-demo-key",
"public_key_sha256": "sha256:139e3940e64b5491722088d9a0d741628fc826e09475d341a780acde3c4b8070",
"type": "hosted"
},
"lineage": {
"children": [

],
"sync": [

]
},
"schema": "runx.receipt.v1",
"seal": {
"closed_at": "2026-06-30T12:59:41.313Z",
"criteria": [
{
"criterion_id": "process_exit",
"evidence_refs": [

],
"status": "verified",
"summary": "cli-tool exited successfully",
"verification_refs": [

]
}
],
"disposition": "closed",
"last_observed_at": "2026-06-30T12:59:41.313Z",
"reason_code": "process_closed",
"summary": "cli-tool judge completed"
},
"signals": [

],
"signature": {
"alg": "Ed25519",
"value": "base64:3hN_r3cIB9hdRAyPeVGn5Tj5-vMlf9YpRdG7VB0YD1fHpmhEwwYzjDDjgIpKbc6I9fxM_IB68kPQWHMfSXYoCA"
},
"subject": {
"commitments": [

],
"kind": "skill",
"ref": {
"type": "harness",
"uri": "hrn_run_judge_6c4c07a106c6_judge"
}
}
}
Loading