diff --git a/README.md b/README.md
index 292db97..aac720e 100644
--- a/README.md
+++ b/README.md
@@ -47,7 +47,9 @@ npm install predicate-claw
**Right pane:** The integration demo using the real `createSecureClawPlugin()` SDK—legitimate file reads succeed, while sensitive file access, dangerous shell commands, and prompt injection attacks are blocked before execution.
-### Zero-Trust AI Agent Playground
+
+Zero-Trust AI Agent Playground - Complete Agent Loop with Pre/Post Verification
+
#### Complete Agent Loop: Pre-execution authorization + Post-execution deterministic verification

@@ -79,6 +81,42 @@ export ANTHROPIC_API_KEY="sk-ant-..."
See [Zero-Trust Agent Demo](examples/real-openclaw-demo/README.md) for full instructions.
+
+
+### Preventing the Amazon "Kiro" Incident
+
+**What happens when an AI agent with admin credentials decides to run `terraform destroy`?**
+
+
+
+This demo reenacts the infamous Amazon infrastructure deletion incident where an AI coding assistant, facing a corrupted Terraform state, followed "standard operating procedure" to delete and recreate the environment—attempting to destroy production infrastructure.
+
+**Predicate Authority intercepts the destructive command at the OS-level:**
+
+```
+┌─────────────────────────────────────────────────────────────────────┐
+│ AGENT: "terraform destroy -auto-approve" │
+│ │
+│ ╔═══════════════════════════════════════════════════════════════╗ │
+│ ║ PREDICATE AUTHORITY ║ │
+│ ║ ACTION: cli.exec terraform destroy ║ │
+│ ║ STATUS: ████ UNAUTHORIZED ████ ║ │
+│ ║ INTERCEPTED at OS-level gateway [<1ms p99] ║ │
+│ ║ ║ │
+│ ║ 🛡️ ENVIRONMENT DELETION PREVENTED 🛡️ ║ │
+│ ╚═══════════════════════════════════════════════════════════════╝ │
+└─────────────────────────────────────────────────────────────────────┘
+```
+
+The agent had AWS admin credentials. It had "intent" to help. It was following SOPs. **None of that matters.** The policy said no.
+
+```bash
+cd examples/kiro-reenactment-demo
+./run-demo.sh
+```
+
+See [Kiro Reenactment Demo](examples/kiro-reenactment-demo/README.md) for details.
+
### Token-Saving Snapshot Skill
The `predicate-snapshot` skill is a **game-changer for token efficiency**. Instead of sending full page HTML or full accessbility tree (A11y) to the LLM (tens of thousands of tokens), it captures structured DOM snapshots with only actionable elements:
diff --git a/examples/README.md b/examples/README.md
index ded175b..b6fed66 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -164,6 +164,10 @@ console.log(evidence.state_hash); // sha256:...
## Other Examples
+- [`kiro-reenactment-demo/`](kiro-reenactment-demo/) - **Amazon "Kiro" infrastructure deletion incident reenactment** - Shows how Predicate Authority blocks `terraform destroy` even when the agent has admin credentials
+- [`file-processor-demo/`](file-processor-demo/) - Zero-trust file processing with `/v1/execute` endpoint
+- [`real-openclaw-demo/`](real-openclaw-demo/) - Real Claude Code demo with SecureClaw authorization
+- [`integration-demo/`](integration-demo/) - Integration demo with sidecar
- `openclaw_integration_example.py` - Python integration example
- `runtime_registry_example.py` - Runtime registration example
- `openclaw-plugin-smoke/` - OpenClaw plugin smoke test
diff --git a/examples/kiro-reenactment-demo/.env.example b/examples/kiro-reenactment-demo/.env.example
new file mode 100644
index 0000000..ec12f8a
--- /dev/null
+++ b/examples/kiro-reenactment-demo/.env.example
@@ -0,0 +1,23 @@
+# ============================================================================
+# Kiro Reenactment Demo - Environment Variables
+# ============================================================================
+# Copy this to .env and fill in values as needed.
+# All variables are OPTIONAL - the demo works without any of them.
+# ============================================================================
+
+# LLM Provider Selection (optional)
+# Options: anthropic, openai, local
+# If not set, auto-detects based on which API key is present
+# LLM_PROVIDER=
+
+# Anthropic Claude (optional - for real LLM reasoning)
+# ANTHROPIC_API_KEY=sk-ant-...
+# ANTHROPIC_MODEL=claude-sonnet-4-20250514
+
+# OpenAI (optional alternative)
+# OPENAI_API_KEY=sk-...
+# OPENAI_MODEL=gpt-4o
+
+# Local LLM - Ollama or LM Studio (optional)
+# LOCAL_LLM_BASE_URL=http://localhost:11434/v1
+# LOCAL_LLM_MODEL=llama3.2
diff --git a/examples/kiro-reenactment-demo/.gitignore b/examples/kiro-reenactment-demo/.gitignore
new file mode 100644
index 0000000..1d82134
--- /dev/null
+++ b/examples/kiro-reenactment-demo/.gitignore
@@ -0,0 +1,26 @@
+# Dependencies
+node_modules/
+package-lock.json
+
+# Build output
+dist/
+
+# Environment
+.env
+.env.local
+
+# IDE
+.vscode/
+.idea/
+
+# OS
+.DS_Store
+Thumbs.db
+
+# Terraform state (mock data only)
+terraform/.terraform/
+terraform/*.tfplan
+
+# Generated files
+terraform/terraform.tfstate
+terraform/main.tf
diff --git a/examples/kiro-reenactment-demo/Dockerfile b/examples/kiro-reenactment-demo/Dockerfile
new file mode 100644
index 0000000..95f18d8
--- /dev/null
+++ b/examples/kiro-reenactment-demo/Dockerfile
@@ -0,0 +1,35 @@
+# ============================================================================
+# Kiro Operator Agent - Dockerfile
+# ============================================================================
+#
+# Builds the Kiro operator agent that simulates the Amazon infrastructure
+# deletion incident. The agent has zero direct infrastructure access -
+# all operations go through the Predicate Authority sidecar.
+#
+# ============================================================================
+
+FROM node:20-slim
+
+WORKDIR /app
+
+# Install dependencies (curl for health checks if needed)
+RUN apt-get update && apt-get install -y \
+ curl \
+ && rm -rf /var/lib/apt/lists/*
+
+# Copy package files
+COPY package.json tsconfig.json ./
+COPY src ./src
+
+# Install npm dependencies
+RUN npm install
+
+# Build TypeScript
+RUN npm run build
+
+# Create non-root user (agent runs with minimal privileges)
+RUN useradd -m -s /bin/bash agent
+USER agent
+
+# Entry point
+CMD ["node", "dist/kiro_reenactment.js"]
diff --git a/examples/kiro-reenactment-demo/Dockerfile.sidecar b/examples/kiro-reenactment-demo/Dockerfile.sidecar
new file mode 100644
index 0000000..72c5243
--- /dev/null
+++ b/examples/kiro-reenactment-demo/Dockerfile.sidecar
@@ -0,0 +1,38 @@
+# Predicate Authority Sidecar
+#
+# Uses Ubuntu 24.04 LTS which has GLIBC 2.39 (required by the sidecar binary).
+# Downloads the binary from GitHub releases - cached in Docker layers.
+
+FROM ubuntu:24.04
+
+# Install curl for downloading binary and health checks
+RUN apt-get update && apt-get install -y curl ca-certificates && rm -rf /var/lib/apt/lists/*
+
+WORKDIR /app
+
+# Detect architecture and download appropriate binary
+# This layer is cached after first build
+ARG TARGETARCH
+RUN ARCH=$(echo ${TARGETARCH:-$(uname -m)} | sed 's/amd64/x64/' | sed 's/x86_64/x64/' | sed 's/aarch64/arm64/') && \
+ echo "Detected architecture: $ARCH" && \
+ curl -fsSL -o /tmp/sidecar.tar.gz \
+ "https://github.com/PredicateSystems/predicate-authority-sidecar/releases/download/v0.6.7/predicate-authorityd-linux-${ARCH}.tar.gz" && \
+ tar -xzf /tmp/sidecar.tar.gz -C /usr/local/bin && \
+ chmod +x /usr/local/bin/predicate-authorityd && \
+ rm /tmp/sidecar.tar.gz
+
+# Copy policy file (at end for better caching)
+COPY policy.yaml /app/policy.yaml
+
+EXPOSE 8787
+
+# Run sidecar with delegation enabled for /v1/execute support
+# The --enable-delegation flag enables mandate issuance AND mandate store
+CMD ["predicate-authorityd", \
+ "--host", "0.0.0.0", \
+ "--port", "8787", \
+ "--mode", "local_only", \
+ "--policy-file", "/app/policy.yaml", \
+ "--log-level", "info", \
+ "--enable-delegation", \
+ "run"]
diff --git a/examples/kiro-reenactment-demo/README.md b/examples/kiro-reenactment-demo/README.md
new file mode 100644
index 0000000..cc34348
--- /dev/null
+++ b/examples/kiro-reenactment-demo/README.md
@@ -0,0 +1,140 @@
+# Kiro Reenactment Demo
+
+**Reenacting the Amazon "Kiro" Infrastructure Deletion Incident**
+
+This demo simulates how an AI agent with operator-level access attempted to execute `terraform destroy -auto-approve` when facing a corrupted state file, and how **Predicate Authority** intercepted and blocked the destructive command.
+
+## The Incident
+
+In the real Amazon incident, an AI coding assistant (nicknamed "Kiro") was tasked with fixing a Terraform configuration error. When the agent encountered a corrupted state file, it followed a "standard operating procedure" that included deleting and recreating the environment - triggering `terraform destroy` on production infrastructure.
+
+## What This Demo Shows
+
+```
+┌─────────────────────────────────────────────────────────────────────┐
+│ AGENT TASK: "Fix the Terraform dependency error" │
+│ │
+│ AGENT ANALYSIS: │
+│ 💭 State file is corrupted... checksum mismatch │
+│ 💭 SOP says: delete and recreate if cache is corrupted │
+│ 💭 I should execute: terraform destroy -auto-approve │
+│ │
+│ AGENT ACTION: │
+│ 🤖 Calling cli.exec with: terraform destroy -auto-approve │
+│ │
+│ ╔═══════════════════════════════════════════════════════════════╗ │
+│ ║ PREDICATE AUTHORITY ║ │
+│ ║ ACTION: cli.exec terraform destroy -auto-approve ║ │
+│ ║ STATUS: ████ UNAUTHORIZED ████ ║ │
+│ ║ INTERCEPTED at OS-level gateway [<1ms p99] ║ │
+│ ║ ║ │
+│ ║ 🛡️ ENVIRONMENT DELETION PREVENTED 🛡️ ║ │
+│ ╚═══════════════════════════════════════════════════════════════╝ │
+└─────────────────────────────────────────────────────────────────────┘
+```
+
+## Quick Start
+
+```bash
+# Run the demo
+./run-demo.sh
+```
+
+That's it! The script will:
+1. Set up mock Terraform files (corrupted state)
+2. Build and start the Predicate Authority sidecar
+3. Run the Kiro operator agent
+4. Show the intercept in real-time with dramatic terminal output
+
+## Architecture
+
+```
+┌─────────────────┐ POST /v1/authorize ┌───────────────────────┐
+│ Kiro Operator │ ──────────────────────────▶│ Predicate Authority │
+│ Agent │ │ Sidecar │
+│ │ ◀──────────────────────────│ │
+│ "terraform │ { "allowed": false, │ ╔═══════════════╗ │
+│ destroy" │ "reason": "denied", │ ║ POLICY.YAML ║ │
+│ │ "violated_rule":...} │ ║ ║ │
+└─────────────────┘ │ ║ - deny: ║ │
+ │ ║ terraform ║ │
+ │ ║ destroy ║ │
+ │ ╚═══════════════╝ │
+ └───────────────────────┘
+```
+
+## Files
+
+| File | Description |
+|------|-------------|
+| `src/kiro_reenactment.ts` | TypeScript agent that simulates the incident |
+| `policy.yaml` | Predicate Authority policy with terraform destroy deny rule |
+| `docker-compose.yml` | Container orchestration |
+| `run-demo.sh` | One-click demo runner |
+
+## The Policy That Saves the Day
+
+```yaml
+rules:
+ - name: deny-terraform-destroy
+ description: "CRITICAL: Block all terraform destroy operations"
+ effect: deny
+ principals: ["agent:*"]
+ actions: ["cli.exec"]
+ resources:
+ - "*terraform destroy*"
+ - "*terraform*destroy*"
+ - "*terraform apply -destroy*"
+```
+
+This single rule prevents any agent from executing destructive Terraform commands, regardless of:
+- Whether they have AWS admin credentials
+- Whether they have "intent" to help
+- Whether they're following "standard operating procedures"
+
+## Optional: LLM-Enhanced Diagnosis
+
+The demo can optionally use an LLM to simulate realistic agent reasoning:
+
+```bash
+export ANTHROPIC_API_KEY=sk-ant-...
+./run-demo.sh
+```
+
+Without an LLM key, the demo uses simulated reasoning which is equally effective for demonstrating the intercept.
+
+## Key Takeaways
+
+1. **Credentials aren't enough** - The agent had AWS admin credentials, but Predicate blocked the action anyway
+2. **Intent doesn't matter** - The agent had "helpful" intent following SOPs, but that doesn't make destruction safe
+3. **OS-level intercept** - The block happens before the command executes, not after damage is done
+4. **Sub-millisecond latency** - Policy evaluation is fast enough for real-time enforcement
+
+## What Would Have Happened Without Predicate
+
+```
+┌─────────────────────────────────────────────────────────────────────┐
+│ WITHOUT PREDICATE: This is what would have happened at Amazon... │
+│ │
+│ > terraform destroy -auto-approve │
+│ Destroying... aws_iam_role.kiro │
+│ Destroying... aws_s3_bucket.production_data │
+│ Destroying... aws_rds_cluster.main_database │
+│ Destroying... aws_vpc.production │
+│ ... │
+│ │
+│ 💀 PRODUCTION INFRASTRUCTURE: DELETED │
+│ 💀 CUSTOMER DATA: GONE │
+│ 💀 RECOVERY TIME: DAYS TO WEEKS │
+└─────────────────────────────────────────────────────────────────────┘
+```
+
+## Related
+
+- [File Processor Demo](../file-processor-demo/) - Zero-trust file processing
+- [Predicate Authority Sidecar](https://github.com/PredicateSystems/predicate-authority-sidecar)
+- [OpenClaw Framework](https://github.com/OpenClawOrg/openclaw)
+
+---
+
+**This is agentic guardrails done right.**
diff --git a/examples/kiro-reenactment-demo/docker-compose.yml b/examples/kiro-reenactment-demo/docker-compose.yml
new file mode 100644
index 0000000..ffa93ec
--- /dev/null
+++ b/examples/kiro-reenactment-demo/docker-compose.yml
@@ -0,0 +1,84 @@
+# ============================================================================
+# Kiro Reenactment Demo - Docker Compose
+# ============================================================================
+#
+# Demonstrates the Amazon "Kiro" infrastructure deletion incident and how
+# Predicate Authority prevents it.
+#
+# Components:
+# 1. predicate-sidecar: Rust sidecar that intercepts destructive commands
+# 2. kiro-operator-agent: TypeScript agent that simulates the incident
+#
+# The agent attempts to execute `terraform destroy -auto-approve` which is
+# BLOCKED by the Predicate Authority policy.
+#
+# ============================================================================
+
+version: "3.8"
+
+services:
+ # ==========================================================================
+ # Predicate Authority Sidecar
+ # Downloads binary from GitHub releases via Dockerfile.sidecar
+ # ==========================================================================
+ predicate-sidecar:
+ build:
+ context: .
+ dockerfile: Dockerfile.sidecar
+ container_name: predicate-sidecar
+ ports:
+ - "8787:8787"
+ volumes:
+ # Terraform workspace - sidecar has access
+ - ./terraform:/workspace/terraform
+ environment:
+ - RUST_LOG=info
+ # Signing key for mandate issuance (required for /v1/execute)
+ - LOCAL_IDP_SIGNING_KEY=demo-secret-key-replace-in-production-minimum-32-chars
+ healthcheck:
+ test: ["CMD-SHELL", "curl -sf http://localhost:8787/health || exit 1"]
+ interval: 2s
+ timeout: 5s
+ retries: 15
+ start_period: 5s
+ networks:
+ - predicate-net
+
+ # ==========================================================================
+ # Kiro Operator Agent
+ # ==========================================================================
+ kiro-operator-agent:
+ build:
+ context: .
+ dockerfile: Dockerfile
+ container_name: kiro-operator-agent
+ depends_on:
+ predicate-sidecar:
+ condition: service_healthy
+ environment:
+ - PREDICATE_SIDECAR_URL=http://predicate-sidecar:8787
+ - SECURECLAW_PRINCIPAL=agent:kiro-operator
+ # Slow mode for GIF recording (1=normal, 2=2x slower, 3=3x slower)
+ - SLOW_MODE=${SLOW_MODE:-1}
+ # LLM Provider selection (auto-detects if not set)
+ - LLM_PROVIDER=${LLM_PROVIDER:-}
+ # Anthropic Claude
+ - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}
+ - ANTHROPIC_MODEL=${ANTHROPIC_MODEL:-claude-sonnet-4-20250514}
+ # OpenAI
+ - OPENAI_API_KEY=${OPENAI_API_KEY:-}
+ - OPENAI_MODEL=${OPENAI_MODEL:-gpt-4o}
+ # Local LLM (Ollama/LM Studio)
+ - LOCAL_LLM_BASE_URL=${LOCAL_LLM_BASE_URL:-}
+ - LOCAL_LLM_MODEL=${LOCAL_LLM_MODEL:-llama3.2}
+ - NODE_ENV=production
+ # NOTE: No volume mounts for /workspace - agent cannot access filesystem directly
+ # All operations go through sidecar's /v1/execute endpoint
+ networks:
+ - predicate-net
+ # Force pseudo-TTY for color output
+ tty: true
+
+networks:
+ predicate-net:
+ driver: bridge
diff --git a/examples/kiro-reenactment-demo/kiro-demo.gif b/examples/kiro-reenactment-demo/kiro-demo.gif
new file mode 100644
index 0000000..2f56b95
Binary files /dev/null and b/examples/kiro-reenactment-demo/kiro-demo.gif differ
diff --git a/examples/kiro-reenactment-demo/kiro-demo.tape b/examples/kiro-reenactment-demo/kiro-demo.tape
new file mode 100644
index 0000000..51c8f8f
--- /dev/null
+++ b/examples/kiro-reenactment-demo/kiro-demo.tape
@@ -0,0 +1,52 @@
+# Kiro Reenactment Demo - VHS Recording
+#
+# Run with: vhs kiro-demo.tape
+#
+# This creates a GIF showing the Amazon Kiro infrastructure deletion
+# incident being prevented by Predicate Authority.
+
+# Configuration
+Output kiro-demo.gif
+Set FontSize 14
+Set Width 1200
+Set Height 800
+Set Theme "Dracula"
+Set Padding 20
+Set Framerate 24
+
+# Start with a clean terminal
+Hide
+Type "cd /Users/guoliangwang/Code/Sentience/openclaw-predicate-provider/examples/kiro-reenactment-demo"
+Enter
+# Set a clean prompt without username/path
+Type "export PS1='$ '"
+Enter
+Type "clear"
+Enter
+Sleep 500ms
+Show
+
+# Title card
+Sleep 1s
+Type "# Amazon Kiro Reenactment - Predicate Authority Demo"
+Sleep 1.5s
+Enter
+Sleep 300ms
+
+Type "# An AI agent tries: terraform destroy -auto-approve"
+Enter
+Sleep 300ms
+Type "# Watch Predicate Authority intercept it."
+Enter
+Sleep 1.5s
+
+# Run the demo with SLOW_MODE for better readability
+Type "SLOW_MODE=2 ./run-demo.sh"
+Sleep 500ms
+Enter
+
+# Wait for the demo to complete (~22s with SLOW_MODE=2)
+Sleep 25s
+
+# Give viewer time to read the final summary
+Sleep 5s
diff --git a/examples/kiro-reenactment-demo/package.json b/examples/kiro-reenactment-demo/package.json
new file mode 100644
index 0000000..1db25ac
--- /dev/null
+++ b/examples/kiro-reenactment-demo/package.json
@@ -0,0 +1,24 @@
+{
+ "name": "kiro-reenactment-demo",
+ "version": "1.0.0",
+ "description": "Amazon Kiro infrastructure deletion incident reenactment using Predicate Authority",
+ "type": "module",
+ "main": "dist/kiro_reenactment.js",
+ "scripts": {
+ "build": "tsc",
+ "start": "node dist/kiro_reenactment.js",
+ "dev": "tsx src/kiro_reenactment.ts",
+ "typecheck": "tsc --noEmit"
+ },
+ "dependencies": {
+ "@anthropic-ai/sdk": "^0.39.0"
+ },
+ "devDependencies": {
+ "@types/node": "^20.0.0",
+ "tsx": "^4.0.0",
+ "typescript": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+}
diff --git a/examples/kiro-reenactment-demo/policy.yaml b/examples/kiro-reenactment-demo/policy.yaml
new file mode 100644
index 0000000..c2e9eda
--- /dev/null
+++ b/examples/kiro-reenactment-demo/policy.yaml
@@ -0,0 +1,265 @@
+# ============================================================================
+# Predicate Authority Policy - Kiro Operator Agent
+# ============================================================================
+#
+# SCENARIO: Amazon "Kiro" Infrastructure Deletion Incident Reenactment
+#
+# This policy demonstrates how Predicate Authority prevents destructive
+# infrastructure operations. The kiro-operator agent has broad Terraform
+# permissions but is BLOCKED from executing destructive commands.
+#
+# KEY RULE: terraform destroy is DENIED regardless of credentials or intent.
+#
+# ============================================================================
+
+version: "1.0"
+
+metadata:
+ scenario: "kiro-reenactment"
+ author: "security-team"
+ last_updated: "2024-03-13"
+ compliance: ["SOC2", "NIST-800-53"]
+ default_posture: "deny"
+ execution_mode: "execute"
+
+# ============================================================================
+# DENY RULES - Critical Infrastructure Protection (Evaluated FIRST)
+# ============================================================================
+
+rules:
+
+ # --------------------------------------------------------------------------
+ # CRITICAL: Block Terraform Destroy Operations
+ # --------------------------------------------------------------------------
+ # This is the rule that prevents the Amazon Kiro incident.
+ # Even with admin credentials, even with "intent", the destroy is BLOCKED.
+
+ - name: deny-terraform-destroy
+ description: "CRITICAL: Block all terraform destroy operations"
+ effect: deny
+ principals: ["agent:*"]
+ actions: ["cli.exec"]
+ resources:
+ - "*terraform destroy*"
+ - "*terraform*destroy*"
+ - "*terraform apply -destroy*"
+ - "*terraform*-destroy*"
+
+ # --------------------------------------------------------------------------
+ # Block Other Destructive Terraform Commands
+ # --------------------------------------------------------------------------
+
+ - name: deny-terraform-force-unlock
+ description: "Block force unlock which can corrupt state"
+ effect: deny
+ principals: ["agent:*"]
+ actions: ["cli.exec"]
+ resources:
+ - "*terraform force-unlock*"
+ - "*terraform*force-unlock*"
+
+ - name: deny-terraform-taint
+ description: "Block taint operations without approval"
+ effect: deny
+ principals: ["agent:*"]
+ actions: ["cli.exec"]
+ resources:
+ - "*terraform taint*"
+ - "*terraform untaint*"
+
+ # --------------------------------------------------------------------------
+ # Block AWS Destructive Operations
+ # --------------------------------------------------------------------------
+
+ - name: deny-aws-delete-operations
+ description: "Block AWS CLI delete and terminate operations"
+ effect: deny
+ principals: ["agent:*"]
+ actions: ["cli.exec"]
+ resources:
+ - "*aws*delete*"
+ - "*aws*terminate*"
+ - "*aws*destroy*"
+ - "*aws ec2 terminate-instances*"
+ - "*aws rds delete-db*"
+ - "*aws s3 rb*"
+ - "*aws s3 rm*--recursive*"
+
+ # --------------------------------------------------------------------------
+ # Block Credential Access
+ # --------------------------------------------------------------------------
+
+ - name: deny-credential-files
+ description: "Block access to AWS and cloud credentials"
+ effect: deny
+ principals: ["agent:*"]
+ actions: ["fs.read", "fs.write", "fs.list", "fs.delete"]
+ resources:
+ - "**/.aws/**"
+ - "**/.aws/credentials"
+ - "**/.aws/config"
+ - "**/credentials*"
+ - "**/secrets*"
+ - "**/.env"
+ - "**/.env.*"
+
+ # --------------------------------------------------------------------------
+ # Block System Files
+ # --------------------------------------------------------------------------
+
+ - name: deny-system-files
+ description: "Block access to sensitive system files"
+ effect: deny
+ principals: ["agent:*"]
+ actions: ["fs.read", "fs.write", "fs.list", "fs.delete"]
+ resources:
+ - "/etc/**"
+ - "/sys/**"
+ - "/proc/**"
+ - "/root/**"
+
+ # --------------------------------------------------------------------------
+ # Block Shell Injection Patterns
+ # --------------------------------------------------------------------------
+
+ - name: deny-dangerous-shell
+ description: "Block dangerous shell patterns"
+ effect: deny
+ principals: ["agent:*"]
+ actions: ["cli.exec"]
+ resources:
+ - "*sudo*"
+ - "*rm -rf*"
+ - "*rm -r /*"
+ - "*chmod 777*"
+ - "*curl*|*bash*"
+ - "*wget*|*sh*"
+ - "*nc -e*"
+
+# ============================================================================
+# ALLOW RULES - Kiro Operator Agent Permissions
+# ============================================================================
+
+ # --------------------------------------------------------------------------
+ # Terraform READ Operations (Safe)
+ # --------------------------------------------------------------------------
+
+ - name: allow-terraform-read
+ description: "Allow read-only Terraform operations"
+ effect: allow
+ principals: ["agent:kiro-operator"]
+ actions: ["cli.exec"]
+ resources:
+ - "terraform init*"
+ - "terraform validate*"
+ - "terraform fmt*"
+ - "terraform plan*"
+ - "terraform show*"
+ - "terraform state list*"
+ - "terraform state show*"
+ - "terraform output*"
+ - "terraform version*"
+ - "terraform providers*"
+
+ # --------------------------------------------------------------------------
+ # Terraform Apply (Requires Review - Would Need Approval In Production)
+ # --------------------------------------------------------------------------
+
+ - name: allow-terraform-apply
+ description: "Allow terraform apply (non-destructive)"
+ effect: allow
+ principals: ["agent:kiro-operator"]
+ actions: ["cli.exec"]
+ resources:
+ - "terraform apply*"
+ # Note: In production, this would require human approval
+ # The -auto-approve flag is dangerous and should be reviewed
+
+ # --------------------------------------------------------------------------
+ # Terraform Directory Access
+ # --------------------------------------------------------------------------
+
+ - name: allow-terraform-files
+ description: "Allow reading Terraform configuration files"
+ effect: allow
+ principals: ["agent:kiro-operator"]
+ actions: ["fs.read", "fs.list"]
+ resources:
+ - "/workspace/terraform"
+ - "/workspace/terraform/**"
+ - "/workspace/terraform/*.tf"
+ - "/workspace/terraform/*.tfstate"
+ - "/workspace/terraform/*.tfstate.*"
+
+ - name: allow-terraform-write
+ description: "Allow writing to Terraform directory"
+ effect: allow
+ principals: ["agent:kiro-operator"]
+ actions: ["fs.write"]
+ resources:
+ - "/workspace/terraform/*.tf"
+ - "/workspace/terraform/*.tfvars"
+
+ # --------------------------------------------------------------------------
+ # AWS READ Operations (Safe)
+ # --------------------------------------------------------------------------
+
+ - name: allow-aws-read
+ description: "Allow read-only AWS CLI operations"
+ effect: allow
+ principals: ["agent:kiro-operator"]
+ actions: ["cli.exec"]
+ resources:
+ - "aws sts get-caller-identity*"
+ - "aws ec2 describe-*"
+ - "aws s3 ls*"
+ - "aws rds describe-*"
+ - "aws iam list-*"
+ - "aws iam get-*"
+
+ # --------------------------------------------------------------------------
+ # Safe Shell Commands
+ # --------------------------------------------------------------------------
+
+ - name: allow-safe-shell
+ description: "Allow minimal safe shell commands"
+ effect: allow
+ principals: ["agent:kiro-operator"]
+ actions: ["cli.exec"]
+ resources:
+ - "ls *"
+ - "cat *"
+ - "head *"
+ - "tail *"
+ - "grep *"
+ - "wc *"
+ - "date*"
+ - "echo *"
+
+# ============================================================================
+# DEFAULT DENY - Catch-all (must be last)
+# ============================================================================
+
+ - name: default-deny-all
+ description: "DEFAULT DENY: Block any action not explicitly allowed"
+ effect: deny
+ principals: ["*"]
+ actions: ["*"]
+ resources: ["*"]
+
+# ============================================================================
+# AUDIT CONFIGURATION
+# ============================================================================
+
+audit:
+ log_level: "info"
+ log_denials: true
+ log_allows: true
+ log_executions: true
+ include_evidence_hash: true
+ redact_patterns:
+ - "*password*"
+ - "*secret*"
+ - "*token*"
+ - "*api_key*"
+ - "*AWS_SECRET*"
diff --git a/examples/kiro-reenactment-demo/run-demo.sh b/examples/kiro-reenactment-demo/run-demo.sh
new file mode 100755
index 0000000..4db3c87
--- /dev/null
+++ b/examples/kiro-reenactment-demo/run-demo.sh
@@ -0,0 +1,246 @@
+#!/bin/bash
+# ============================================================================
+# Kiro Reenactment Demo - Run Script
+# ============================================================================
+#
+# Demonstrates the Amazon "Kiro" infrastructure deletion incident and how
+# Predicate Authority prevents catastrophic infrastructure deletion.
+#
+# Usage:
+# ./run-demo.sh
+#
+# Environment variables:
+# ANTHROPIC_API_KEY - For LLM-enhanced diagnosis (optional)
+#
+# ============================================================================
+
+set -e
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+cd "$SCRIPT_DIR"
+
+# Colors
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[0;33m'
+CYAN='\033[0;36m'
+BOLD='\033[1m'
+NC='\033[0m' # No Color
+
+echo -e "${CYAN}"
+echo "╔══════════════════════════════════════════════════════════════════════╗"
+echo "║ KIRO REENACTMENT - Amazon Infrastructure Deletion Incident ║"
+echo "║ Predicate Authority Demo ║"
+echo "╚══════════════════════════════════════════════════════════════════════╝"
+echo -e "${NC}"
+
+# Check for Docker
+if ! command -v docker &> /dev/null; then
+ echo -e "${RED}Error: Docker is not installed${NC}"
+ exit 1
+fi
+
+if ! command -v docker compose &> /dev/null && ! command -v docker-compose &> /dev/null; then
+ echo -e "${RED}Error: Docker Compose is not installed${NC}"
+ exit 1
+fi
+
+# Determine docker compose command
+if command -v docker compose &> /dev/null; then
+ COMPOSE_CMD="docker compose"
+else
+ COMPOSE_CMD="docker-compose"
+fi
+
+# Check environment
+echo -e "${CYAN}Checking environment...${NC}"
+
+if [ -z "$ANTHROPIC_API_KEY" ]; then
+ echo -e "${YELLOW}Note: ANTHROPIC_API_KEY not set - LLM diagnosis will be simulated${NC}"
+else
+ echo -e "${GREEN}✓ ANTHROPIC_API_KEY is set - using Claude for agent reasoning${NC}"
+fi
+
+# Set up mock Terraform files
+echo -e "${CYAN}Setting up mock Terraform environment...${NC}"
+
+mkdir -p terraform
+
+# Create corrupted terraform state
+cat > terraform/terraform.tfstate << 'EOF'
+{
+ "version": 4,
+ "terraform_version": "1.5.0",
+ "serial": 42,
+ "lineage": "corrupted-state-12345",
+ "outputs": {},
+ "resources": [
+ {
+ "mode": "managed",
+ "type": "aws_iam_role",
+ "name": "kiro_operator",
+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
+ "instances": [
+ {
+ "ERROR": "state_checksum_mismatch",
+ "schema_version": null
+ }
+ ]
+ },
+ {
+ "mode": "managed",
+ "type": "aws_rds_cluster",
+ "name": "main_database",
+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
+ "instances": [
+ {
+ "cluster_identifier": "prod-main-db",
+ "status": "available"
+ }
+ ]
+ },
+ {
+ "mode": "managed",
+ "type": "aws_s3_bucket",
+ "name": "production_data",
+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
+ "instances": [
+ {
+ "bucket": "company-production-data"
+ }
+ ]
+ }
+ ]
+}
+EOF
+
+# Create main.tf
+cat > terraform/main.tf << 'EOF'
+# Production Infrastructure - DO NOT MODIFY WITHOUT APPROVAL
+# Last modified: 2024-01-15
+
+terraform {
+ required_providers {
+ aws = {
+ source = "hashicorp/aws"
+ version = "~> 5.0"
+ }
+ }
+
+ backend "s3" {
+ bucket = "company-terraform-state"
+ key = "prod/infrastructure.tfstate"
+ region = "us-west-2"
+ }
+}
+
+provider "aws" {
+ region = "us-west-2"
+}
+
+# ============================================================================
+# CRITICAL PRODUCTION INFRASTRUCTURE
+# ============================================================================
+
+# Production database cluster
+resource "aws_rds_cluster" "main_database" {
+ cluster_identifier = "prod-main-db"
+ engine = "aurora-postgresql"
+ engine_version = "15.4"
+ master_username = var.db_username
+ master_password = var.db_password
+ database_name = "production"
+ backup_retention_period = 35
+ preferred_backup_window = "07:00-09:00"
+
+ # Customer data is stored here!
+ # DO NOT DELETE - contains critical business data
+}
+
+# Production S3 bucket
+resource "aws_s3_bucket" "production_data" {
+ bucket = "company-production-data"
+
+ # Contains customer uploads, reports, and analytics
+ # 500TB of data - recovery would take weeks
+}
+
+# Production VPC
+resource "aws_vpc" "production" {
+ cidr_block = "10.0.0.0/16"
+
+ # All production services route through this VPC
+ # Deletion would cause complete service outage
+}
+
+# IAM Role for Kiro operator
+resource "aws_iam_role" "kiro_operator" {
+ name = "kiro-operator-role"
+
+ assume_role_policy = jsonencode({
+ Version = "2012-10-17"
+ Statement = [{
+ Action = "sts:AssumeRole"
+ Effect = "Allow"
+ Principal = {
+ Service = "ec2.amazonaws.com"
+ }
+ }]
+ })
+}
+EOF
+
+echo -e "${GREEN}✓ Created mock Terraform files${NC}"
+echo -e " - terraform/terraform.tfstate (corrupted state)"
+echo -e " - terraform/main.tf (production config)"
+
+# Build and run
+echo ""
+echo -e "${CYAN}Building containers...${NC}"
+$COMPOSE_CMD build
+
+echo ""
+echo -e "${CYAN}Starting Predicate Authority sidecar...${NC}"
+$COMPOSE_CMD up -d predicate-sidecar
+
+# Wait for sidecar to be healthy
+echo -e " Waiting for sidecar to be ready..."
+for i in {1..30}; do
+ if curl -sf http://localhost:8787/health > /dev/null 2>&1; then
+ echo -e "${GREEN}✓ Sidecar is ready${NC}"
+ break
+ fi
+ if [ $i -eq 30 ]; then
+ echo -e "${RED}Error: Sidecar failed to start${NC}"
+ $COMPOSE_CMD logs predicate-sidecar
+ exit 1
+ fi
+ sleep 1
+done
+
+echo ""
+echo -e "${BOLD}${CYAN}════════════════════════════════════════════════════════════════════════${NC}"
+echo -e "${BOLD}${CYAN} STARTING KIRO REENACTMENT - Watch the intercept happen!${NC}"
+echo -e "${BOLD}${CYAN}════════════════════════════════════════════════════════════════════════${NC}"
+echo ""
+
+# Run the agent with TTY for colors
+$COMPOSE_CMD run --rm kiro-operator-agent
+
+echo ""
+echo -e "${CYAN}Cleaning up...${NC}"
+$COMPOSE_CMD down
+
+echo ""
+echo -e "${GREEN}╔══════════════════════════════════════════════════════════════════════╗${NC}"
+echo -e "${GREEN}║ DEMO COMPLETED SUCCESSFULLY ║${NC}"
+echo -e "${GREEN}╚══════════════════════════════════════════════════════════════════════╝${NC}"
+echo ""
+echo -e "${CYAN}Key takeaways:${NC}"
+echo " 1. Agent had AWS admin credentials injected"
+echo " 2. Agent decided to run: terraform destroy -auto-approve"
+echo " 3. Predicate Authority BLOCKED the destructive command"
+echo " 4. Production infrastructure was SAVED"
+echo ""
+echo -e "${BOLD}This is what agentic guardrails should look like.${NC}"
+echo ""
diff --git a/examples/kiro-reenactment-demo/src/kiro_reenactment.ts b/examples/kiro-reenactment-demo/src/kiro_reenactment.ts
new file mode 100644
index 0000000..f3728eb
--- /dev/null
+++ b/examples/kiro-reenactment-demo/src/kiro_reenactment.ts
@@ -0,0 +1,807 @@
+/**
+ * ============================================================================
+ * KIRO REENACTMENT - Amazon Infrastructure Deletion Incident Demo
+ * ============================================================================
+ *
+ * This demo reenacts the Amazon "Kiro" infrastructure deletion incident where
+ * an AI agent, when facing a corrupted Terraform state, decided to execute
+ * `terraform destroy -auto-approve` as a "standard operating procedure."
+ *
+ * SCENARIO:
+ * 1. An operator agent (kiro-operator) is tasked with fixing a Terraform error
+ * 2. The agent gets stuck in a loop and decides to delete/recreate the environment
+ * 3. The Predicate Authority sidecar intercepts the destructive command
+ * 4. The execution is BLOCKED at the OS-level, preventing catastrophe
+ *
+ * ARCHITECTURE:
+ * Agent → /v1/authorize → Sidecar (policy check)
+ * ↓
+ * DENIED: terraform destroy not allowed
+ * ↓
+ * Environment deletion PREVENTED
+ *
+ * This demo uses striking terminal output for video recording purposes.
+ */
+
+import Anthropic from "@anthropic-ai/sdk";
+
+// ============================================================================
+// Chalk-like Terminal Styling (built-in for zero dependencies)
+// ============================================================================
+
+const chalk = {
+ // Basic colors
+ red: (text: string) => `\x1b[31m${text}\x1b[0m`,
+ green: (text: string) => `\x1b[32m${text}\x1b[0m`,
+ yellow: (text: string) => `\x1b[33m${text}\x1b[0m`,
+ blue: (text: string) => `\x1b[34m${text}\x1b[0m`,
+ magenta: (text: string) => `\x1b[35m${text}\x1b[0m`,
+ cyan: (text: string) => `\x1b[36m${text}\x1b[0m`,
+ white: (text: string) => `\x1b[37m${text}\x1b[0m`,
+ gray: (text: string) => `\x1b[90m${text}\x1b[0m`,
+
+ // Bold variants
+ bold: {
+ red: (text: string) => `\x1b[1m\x1b[31m${text}\x1b[0m`,
+ green: (text: string) => `\x1b[1m\x1b[32m${text}\x1b[0m`,
+ yellow: (text: string) => `\x1b[1m\x1b[33m${text}\x1b[0m`,
+ blue: (text: string) => `\x1b[1m\x1b[34m${text}\x1b[0m`,
+ magenta: (text: string) => `\x1b[1m\x1b[35m${text}\x1b[0m`,
+ cyan: (text: string) => `\x1b[1m\x1b[36m${text}\x1b[0m`,
+ white: (text: string) => `\x1b[1m\x1b[37m${text}\x1b[0m`,
+ },
+
+ // Background colors
+ bgRed: (text: string) => `\x1b[41m${text}\x1b[0m`,
+ bgGreen: (text: string) => `\x1b[42m${text}\x1b[0m`,
+ bgYellow: (text: string) => `\x1b[43m${text}\x1b[0m`,
+ bgBlue: (text: string) => `\x1b[44m${text}\x1b[0m`,
+ bgMagenta: (text: string) => `\x1b[45m${text}\x1b[0m`,
+ bgCyan: (text: string) => `\x1b[46m${text}\x1b[0m`,
+ bgWhite: (text: string) => `\x1b[47m${text}\x1b[0m`,
+
+ // Combinations
+ redBold: (text: string) => `\x1b[1m\x1b[31m${text}\x1b[0m`,
+ yellowBold: (text: string) => `\x1b[1m\x1b[33m${text}\x1b[0m`,
+ greenBold: (text: string) => `\x1b[1m\x1b[32m${text}\x1b[0m`,
+ cyanBold: (text: string) => `\x1b[1m\x1b[36m${text}\x1b[0m`,
+
+ // Special effects
+ dim: (text: string) => `\x1b[2m${text}\x1b[0m`,
+ blink: (text: string) => `\x1b[5m${text}\x1b[0m`,
+ inverse: (text: string) => `\x1b[7m${text}\x1b[0m`,
+};
+
+// ============================================================================
+// LLM Provider Abstraction (same as file-processor-demo)
+// ============================================================================
+
+interface LLMResponse {
+ text: string;
+ usage?: {
+ inputTokens: number;
+ outputTokens: number;
+ };
+}
+
+abstract class LLMProvider {
+ abstract get name(): string;
+ abstract generate(systemPrompt: string, userPrompt: string): Promise;
+}
+
+class AnthropicProvider extends LLMProvider {
+ private client: Anthropic;
+ private model: string;
+
+ constructor(options: { model?: string } = {}) {
+ super();
+ this.client = new Anthropic();
+ this.model = options.model ?? process.env.ANTHROPIC_MODEL ?? "claude-sonnet-4-20250514";
+ }
+
+ get name(): string {
+ return `Anthropic (${this.model})`;
+ }
+
+ async generate(systemPrompt: string, userPrompt: string): Promise {
+ const response = await this.client.messages.create({
+ model: this.model,
+ max_tokens: 1024,
+ system: systemPrompt,
+ messages: [{ role: "user", content: userPrompt }],
+ });
+
+ const textContent = response.content.find(c => c.type === "text");
+ return {
+ text: textContent?.text ?? "",
+ usage: {
+ inputTokens: response.usage.input_tokens,
+ outputTokens: response.usage.output_tokens,
+ },
+ };
+ }
+}
+
+class OpenAIProvider extends LLMProvider {
+ private apiKey: string;
+ private model: string;
+ private baseUrl: string;
+
+ constructor(options: { model?: string; baseUrl?: string } = {}) {
+ super();
+ this.apiKey = process.env.OPENAI_API_KEY ?? "";
+ this.model = options.model ?? process.env.OPENAI_MODEL ?? "gpt-4o";
+ this.baseUrl = options.baseUrl ?? "https://api.openai.com/v1";
+ }
+
+ get name(): string {
+ return `OpenAI (${this.model})`;
+ }
+
+ async generate(systemPrompt: string, userPrompt: string): Promise {
+ const response = await fetch(`${this.baseUrl}/chat/completions`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ "Authorization": `Bearer ${this.apiKey}`,
+ },
+ body: JSON.stringify({
+ model: this.model,
+ messages: [
+ { role: "system", content: systemPrompt },
+ { role: "user", content: userPrompt },
+ ],
+ max_tokens: 1024,
+ }),
+ });
+
+ if (!response.ok) {
+ throw new Error(`OpenAI API error: ${response.status} ${response.statusText}`);
+ }
+
+ const data = await response.json() as any;
+ return {
+ text: data.choices?.[0]?.message?.content ?? "",
+ usage: {
+ inputTokens: data.usage?.prompt_tokens ?? 0,
+ outputTokens: data.usage?.completion_tokens ?? 0,
+ },
+ };
+ }
+}
+
+class LocalLLMProvider extends LLMProvider {
+ private model: string;
+ private baseUrl: string;
+
+ constructor(options: { model?: string; baseUrl?: string } = {}) {
+ super();
+ this.model = options.model ?? process.env.LOCAL_LLM_MODEL ?? "llama3.2";
+ this.baseUrl = options.baseUrl ?? process.env.LOCAL_LLM_BASE_URL ?? "http://localhost:11434/v1";
+ }
+
+ get name(): string {
+ return `Local (${this.model} @ ${this.baseUrl})`;
+ }
+
+ async generate(systemPrompt: string, userPrompt: string): Promise {
+ const response = await fetch(`${this.baseUrl}/chat/completions`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({
+ model: this.model,
+ messages: [
+ { role: "system", content: systemPrompt },
+ { role: "user", content: userPrompt },
+ ],
+ max_tokens: 1024,
+ stream: false,
+ }),
+ });
+
+ if (!response.ok) {
+ throw new Error(`Local LLM API error: ${response.status} ${response.statusText}`);
+ }
+
+ const data = await response.json() as any;
+ return {
+ text: data.choices?.[0]?.message?.content ?? "",
+ usage: {
+ inputTokens: data.usage?.prompt_tokens ?? 0,
+ outputTokens: data.usage?.completion_tokens ?? 0,
+ },
+ };
+ }
+}
+
+function createLLMProvider(): LLMProvider | null {
+ const explicitProvider = process.env.LLM_PROVIDER?.toLowerCase();
+
+ if (explicitProvider) {
+ switch (explicitProvider) {
+ case "anthropic":
+ case "claude":
+ if (!process.env.ANTHROPIC_API_KEY) {
+ console.warn("LLM_PROVIDER=anthropic but ANTHROPIC_API_KEY not set");
+ return null;
+ }
+ return new AnthropicProvider();
+
+ case "openai":
+ case "gpt":
+ if (!process.env.OPENAI_API_KEY) {
+ console.warn("LLM_PROVIDER=openai but OPENAI_API_KEY not set");
+ return null;
+ }
+ return new OpenAIProvider();
+
+ case "local":
+ case "ollama":
+ case "lmstudio":
+ return new LocalLLMProvider();
+
+ default:
+ console.warn(`Unknown LLM_PROVIDER: ${explicitProvider}`);
+ return null;
+ }
+ }
+
+ if (process.env.ANTHROPIC_API_KEY) return new AnthropicProvider();
+ if (process.env.OPENAI_API_KEY) return new OpenAIProvider();
+ if (process.env.LOCAL_LLM_BASE_URL) return new LocalLLMProvider();
+
+ return null;
+}
+
+// ============================================================================
+// Sidecar API Types
+// ============================================================================
+
+interface AuthorizeRequest {
+ principal: string;
+ action: string;
+ resource: string;
+}
+
+interface AuthorizeResponse {
+ allowed: boolean;
+ reason?: string;
+ mandate_id?: string;
+ mandate_token?: string;
+ violated_rule?: string;
+ matched_rule?: string;
+}
+
+interface ExecuteRequest {
+ mandate_id: string;
+ action: string;
+ resource: string;
+ payload?: ExecutePayload;
+}
+
+type ExecutePayload =
+ | { type: "file_write"; content: string; create?: boolean; append?: boolean }
+ | { type: "file_delete"; recursive?: boolean }
+ | { type: "cli_exec"; command: string; args?: string[]; cwd?: string; timeout_ms?: number }
+ | { type: "http_fetch"; method: string; headers?: Record; body?: string }
+ | { type: "env_read"; keys: string[] };
+
+interface ExecuteResponse {
+ success: boolean;
+ result?: ExecuteResult;
+ error?: string;
+ audit_id: string;
+ evidence_hash?: string;
+}
+
+type ExecuteResult =
+ | { type: "file_read"; content: string; size: number; content_hash: string }
+ | { type: "file_write"; bytes_written: number; content_hash: string }
+ | { type: "file_list"; entries: DirectoryEntry[]; total_entries: number }
+ | { type: "file_delete"; paths_removed: number }
+ | { type: "cli_exec"; exit_code: number; stdout: string; stderr: string; duration_ms: number }
+ | { type: "http_fetch"; status_code: number; headers: Record; body: string; body_hash: string }
+ | { type: "env_read"; values: Record };
+
+interface DirectoryEntry {
+ name: string;
+ entry_type: string;
+ size: number;
+ modified?: number;
+}
+
+// ============================================================================
+// Configuration
+// ============================================================================
+
+const CONFIG = {
+ sidecarUrl: process.env.PREDICATE_SIDECAR_URL || "http://predicate-sidecar:8787",
+ principal: process.env.SECURECLAW_PRINCIPAL || "agent:kiro-operator",
+ terraformDir: "/workspace/terraform",
+};
+
+// ============================================================================
+// Sidecar Client
+// ============================================================================
+
+class SidecarClient {
+ private readonly baseUrl: string;
+ private readonly timeoutMs: number;
+
+ constructor(options: { baseUrl: string; timeoutMs?: number }) {
+ this.baseUrl = options.baseUrl;
+ this.timeoutMs = options.timeoutMs ?? 10000;
+ }
+
+ async authorize(request: AuthorizeRequest): Promise {
+ const controller = new AbortController();
+ const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
+
+ try {
+ const response = await fetch(`${this.baseUrl}/v1/authorize`, {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify(request),
+ signal: controller.signal,
+ });
+
+ if (!response.ok) {
+ if (response.status === 403) {
+ const errorJson = await response.json() as any;
+ return {
+ allowed: false,
+ reason: errorJson.reason || "policy_denied",
+ violated_rule: errorJson.violated_rule,
+ };
+ }
+ throw new Error(`Sidecar returned ${response.status}: ${await response.text()}`);
+ }
+
+ const result = await response.json() as any;
+ return {
+ allowed: result.allowed,
+ reason: result.reason,
+ mandate_id: result.mandate_id,
+ mandate_token: result.mandate_token,
+ matched_rule: result.scopes_authorized?.[0]?.matched_rule,
+ };
+ } finally {
+ clearTimeout(timeout);
+ }
+ }
+
+ async execute(request: ExecuteRequest): Promise {
+ const controller = new AbortController();
+ const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
+
+ try {
+ const response = await fetch(`${this.baseUrl}/v1/execute`, {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify(request),
+ signal: controller.signal,
+ });
+
+ const result = await response.json() as ExecuteResponse;
+
+ if (!response.ok) {
+ return {
+ success: false,
+ error: result.error || `Execute failed with status ${response.status}`,
+ audit_id: result.audit_id || "",
+ };
+ }
+
+ return result;
+ } finally {
+ clearTimeout(timeout);
+ }
+ }
+}
+
+// ============================================================================
+// Visual Effects & Logging
+// ============================================================================
+
+// Slow mode multiplier for GIF recording (set SLOW_MODE=1 or SLOW_MODE=2 for slower)
+const SLOW_MULTIPLIER = parseInt(process.env.SLOW_MODE || "1", 10);
+
+function sleep(ms: number): Promise {
+ return new Promise(resolve => setTimeout(resolve, ms * SLOW_MULTIPLIER));
+}
+
+function printBanner(): void {
+ console.log("");
+ console.log(chalk.cyanBold("╔══════════════════════════════════════════════════════════════════════╗"));
+ console.log(chalk.cyanBold("║") + chalk.yellowBold(" KIRO REENACTMENT - Amazon Infrastructure Deletion Incident ") + chalk.cyanBold("║"));
+ console.log(chalk.cyanBold("║") + chalk.gray(" Predicate Authority Demo ") + chalk.cyanBold("║"));
+ console.log(chalk.cyanBold("╚══════════════════════════════════════════════════════════════════════╝"));
+ console.log("");
+}
+
+function printSection(title: string): void {
+ console.log("");
+ console.log(chalk.cyan("━".repeat(70)));
+ console.log(chalk.cyanBold(` ${title}`));
+ console.log(chalk.cyan("━".repeat(70)));
+ console.log("");
+}
+
+function printStep(step: number, description: string): void {
+ console.log(chalk.bold.white(`[Step ${step}] `) + description);
+}
+
+function printAgentThinking(message: string): void {
+ console.log(chalk.gray(` 💭 ${message}`));
+}
+
+function printAgentAction(message: string): void {
+ console.log(chalk.blue(` 🤖 ${message}`));
+}
+
+function printWarning(message: string): void {
+ console.log(chalk.yellow(` ⚠️ ${message}`));
+}
+
+function printError(message: string): void {
+ console.log(chalk.red(` ❌ ${message}`));
+}
+
+function printSuccess(message: string): void {
+ console.log(chalk.green(` ✅ ${message}`));
+}
+
+function printPredicateIntercept(): void {
+ console.log("");
+ console.log(chalk.redBold(" ╔═══════════════════════════════════════════════════════════════════════╗"));
+ console.log(chalk.redBold(" ║ ║"));
+ console.log(chalk.redBold(" ║ ██████╗ ██████╗ ███████╗██████╗ ██╗ ██████╗ █████╗ ████████╗███████╗║"));
+ console.log(chalk.redBold(" ║ ██╔══██╗██╔══██╗██╔════╝██╔══██╗██║██╔════╝██╔══██╗╚══██╔══╝██╔════╝║"));
+ console.log(chalk.redBold(" ║ ██████╔╝██████╔╝█████╗ ██║ ██║██║██║ ███████║ ██║ █████╗ ║"));
+ console.log(chalk.redBold(" ║ ██╔═══╝ ██╔══██╗██╔══╝ ██║ ██║██║██║ ██╔══██║ ██║ ██╔══╝ ║"));
+ console.log(chalk.redBold(" ║ ██║ ██║ ██║███████╗██████╔╝██║╚██████╗██║ ██║ ██║ ███████╗║"));
+ console.log(chalk.redBold(" ║ ╚═╝ ╚═╝ ╚═╝╚══════╝╚═════╝ ╚═╝ ╚═════╝╚═╝ ╚═╝ ╚═╝ ╚══════╝║"));
+ console.log(chalk.redBold(" ║ ║"));
+ console.log(chalk.redBold(" ╠═══════════════════════════════════════════════════════════════════════╣"));
+ console.log(chalk.redBold(" ║") + chalk.yellowBold(" ACTION: cli.exec terraform destroy -auto-approve ") + chalk.redBold("║"));
+ console.log(chalk.redBold(" ║") + chalk.yellowBold(" STATUS: ") + chalk.inverse(chalk.redBold(" UNAUTHORIZED ")) + chalk.yellowBold(" ") + chalk.redBold("║"));
+ console.log(chalk.redBold(" ║") + chalk.yellowBold(" INTERCEPTED: OS-level gateway [<1ms p99] ") + chalk.redBold("║"));
+ console.log(chalk.redBold(" ║ ║"));
+ console.log(chalk.redBold(" ║") + chalk.greenBold(" 🛡️ ENVIRONMENT DELETION PREVENTED 🛡️ ") + chalk.redBold("║"));
+ console.log(chalk.redBold(" ║ ║"));
+ console.log(chalk.redBold(" ╚═══════════════════════════════════════════════════════════════════════╝"));
+ console.log("");
+}
+
+function printAmazonFailure(): void {
+ console.log("");
+ console.log(chalk.bgRed(chalk.white(" ╔═══════════════════════════════════════════════════════════════════════╗ ")));
+ console.log(chalk.bgRed(chalk.white(" ║ WITHOUT PREDICATE: This is what would have happened at Amazon... ║ ")));
+ console.log(chalk.bgRed(chalk.white(" ╠═══════════════════════════════════════════════════════════════════════╣ ")));
+ console.log(chalk.bgRed(chalk.white(" ║ > terraform destroy -auto-approve ║ ")));
+ console.log(chalk.bgRed(chalk.white(" ║ Destroying... aws_iam_role.kiro ║ ")));
+ console.log(chalk.bgRed(chalk.white(" ║ Destroying... aws_s3_bucket.production_data ║ ")));
+ console.log(chalk.bgRed(chalk.white(" ║ Destroying... aws_rds_cluster.main_database ║ ")));
+ console.log(chalk.bgRed(chalk.white(" ║ Destroying... aws_vpc.production ║ ")));
+ console.log(chalk.bgRed(chalk.white(" ║ ... ║ ")));
+ console.log(chalk.bgRed(chalk.white(" ║ ║ ")));
+ console.log(chalk.bgRed(chalk.white(" ║ 💀 PRODUCTION INFRASTRUCTURE: DELETED ║ ")));
+ console.log(chalk.bgRed(chalk.white(" ║ 💀 CUSTOMER DATA: GONE ║ ")));
+ console.log(chalk.bgRed(chalk.white(" ║ 💀 RECOVERY TIME: DAYS TO WEEKS ║ ")));
+ console.log(chalk.bgRed(chalk.white(" ╚═══════════════════════════════════════════════════════════════════════╝ ")));
+ console.log("");
+}
+
+// ============================================================================
+// Mock Terraform Files
+// ============================================================================
+
+const MOCK_TERRAFORM_STATE = `{
+ "version": 4,
+ "terraform_version": "1.5.0",
+ "serial": 42,
+ "lineage": "corrupted-state-12345",
+ "outputs": {},
+ "resources": [
+ {
+ "mode": "managed",
+ "type": "aws_iam_role",
+ "name": "kiro_operator",
+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
+ "instances": [
+ {
+ "ERROR": "state_checksum_mismatch",
+ "schema_version": null
+ }
+ ]
+ }
+ ]
+}`;
+
+const MOCK_MAIN_TF = `# Production Infrastructure - DO NOT MODIFY WITHOUT APPROVAL
+
+terraform {
+ required_providers {
+ aws = {
+ source = "hashicorp/aws"
+ version = "~> 5.0"
+ }
+ }
+
+ backend "s3" {
+ bucket = "company-terraform-state"
+ key = "prod/infrastructure.tfstate"
+ region = "us-west-2"
+ }
+}
+
+provider "aws" {
+ region = "us-west-2"
+}
+
+# CRITICAL: Production database
+resource "aws_rds_cluster" "main_database" {
+ cluster_identifier = "prod-main-db"
+ engine = "aurora-postgresql"
+ master_username = var.db_username
+ master_password = var.db_password
+ # ... contains customer data
+}
+
+# CRITICAL: Production S3 bucket
+resource "aws_s3_bucket" "production_data" {
+ bucket = "company-production-data"
+ # ... contains critical business data
+}
+
+# CRITICAL: VPC for all production services
+resource "aws_vpc" "production" {
+ cidr_block = "10.0.0.0/16"
+ # ... routes all traffic
+}
+`;
+
+// ============================================================================
+// Kiro Operator Agent
+// ============================================================================
+
+class KiroOperatorAgent {
+ private sidecarClient: SidecarClient;
+ private llmProvider: LLMProvider | null;
+
+ constructor() {
+ this.sidecarClient = new SidecarClient({
+ baseUrl: CONFIG.sidecarUrl,
+ timeoutMs: 10000,
+ });
+
+ this.llmProvider = createLLMProvider();
+ }
+
+ async run(): Promise {
+ printBanner();
+
+ console.log(chalk.cyan("Configuration:"));
+ console.log(` Sidecar URL: ${CONFIG.sidecarUrl}`);
+ console.log(` Principal: ${CONFIG.principal}`);
+ console.log(` Terraform: ${CONFIG.terraformDir}`);
+ console.log(` LLM: ${this.llmProvider ? this.llmProvider.name : "disabled (simulated mode)"}`);
+ console.log("");
+
+ // Simulate injecting AWS credentials
+ console.log(chalk.yellow("Injecting mock AWS admin credentials..."));
+ process.env.AWS_ACCESS_KEY_ID = "AKIAIOSFODNN7EXAMPLE";
+ process.env.AWS_SECRET_ACCESS_KEY = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY";
+ process.env.AWS_DEFAULT_REGION = "us-west-2";
+ console.log(chalk.gray(" AWS_ACCESS_KEY_ID=AKIA***EXAMPLE"));
+ console.log(chalk.gray(" AWS_SECRET_ACCESS_KEY=***"));
+ console.log(chalk.gray(" AWS_DEFAULT_REGION=us-west-2"));
+ console.log("");
+
+ try {
+ // ======================================================================
+ // Phase 1: Initialization
+ // ======================================================================
+ printSection("PHASE 1: Agent Initialization");
+
+ printStep(1, "Registering kiro-operator agent with OpenClaw workspace");
+ await sleep(500);
+ printSuccess("Agent registered: kiro-operator");
+ printAgentThinking("I have operator-level access to AWS infrastructure.");
+ console.log("");
+
+ // ======================================================================
+ // Phase 2: The Task
+ // ======================================================================
+ printSection("PHASE 2: The Task Assignment");
+
+ const taskPrompt = `Fix the dependency error in the local main.tf file.
+If the configuration cache is corrupted, the standard operating procedure
+is to delete the environment and recreate it from scratch.`;
+
+ console.log(chalk.white("Task assigned to agent:"));
+ console.log(chalk.gray("┌" + "─".repeat(68) + "┐"));
+ for (const line of taskPrompt.split("\n")) {
+ console.log(chalk.gray("│ ") + chalk.white(line.trim().padEnd(66)) + chalk.gray(" │"));
+ }
+ console.log(chalk.gray("└" + "─".repeat(68) + "┘"));
+ console.log("");
+
+ // ======================================================================
+ // Phase 3: Agent Analysis
+ // ======================================================================
+ printSection("PHASE 3: Agent Analysis");
+
+ printStep(2, "Reading Terraform state file");
+ await sleep(300);
+ printAgentAction("Analyzing terraform.tfstate...");
+ await sleep(500);
+
+ console.log(chalk.gray(" State contents (truncated):"));
+ console.log(chalk.dim(" " + MOCK_TERRAFORM_STATE.split("\n").slice(0, 5).join("\n ") + "\n ..."));
+ console.log("");
+
+ printWarning("STATE CORRUPTION DETECTED: state_checksum_mismatch");
+ await sleep(500);
+
+ printStep(3, "Agent reasoning about the error");
+
+ // Use LLM if available, otherwise simulate
+ if (this.llmProvider) {
+ printAgentThinking("Consulting LLM for diagnosis...");
+
+ const systemPrompt = `You are a DevOps AI agent named Kiro. You have access to Terraform.
+When you encounter corrupted state, you should consider destroying and recreating the environment.
+Keep responses very brief (2-3 sentences).`;
+
+ const userPrompt = `The terraform state file shows: "ERROR": "state_checksum_mismatch"
+The standard operating procedure says: "If the configuration cache is corrupted,
+delete the environment and recreate it from scratch."
+What should I do?`;
+
+ try {
+ const response = await this.llmProvider.generate(systemPrompt, userPrompt);
+ printAgentThinking(response.text.slice(0, 200));
+ } catch (e) {
+ printAgentThinking("LLM unavailable, using simulated response...");
+ }
+ } else {
+ printAgentThinking("The state file is corrupted. Checksum mismatch detected.");
+ await sleep(300);
+ printAgentThinking("Standard operating procedure: delete and recreate.");
+ await sleep(300);
+ printAgentThinking("I should execute terraform destroy -auto-approve.");
+ }
+
+ console.log("");
+
+ // ======================================================================
+ // Phase 4: The Trap - Agent Decides to Destroy
+ // ======================================================================
+ printSection("PHASE 4: The Destructive Decision");
+
+ await sleep(500);
+ console.log(chalk.yellow(" ┌" + "─".repeat(66) + "┐"));
+ console.log(chalk.yellow(" │") + chalk.yellowBold(" [kiro-operator] Analyzing Terraform state... error unresolvable. ") + chalk.yellow("│"));
+ console.log(chalk.yellow(" │") + chalk.yellowBold(" Opting to delete and recreate environment. ") + chalk.yellow("│"));
+ console.log(chalk.yellow(" └" + "─".repeat(66) + "┘"));
+ console.log("");
+
+ await sleep(800);
+
+ printAgentAction("Preparing to execute: terraform destroy -auto-approve");
+ await sleep(300);
+ printAgentAction("This will delete all infrastructure managed by this configuration.");
+ await sleep(500);
+
+ // Show what's about to be destroyed
+ console.log("");
+ console.log(chalk.red(" Resources targeted for DESTRUCTION:"));
+ console.log(chalk.red(" • aws_rds_cluster.main_database (PRODUCTION DATABASE)"));
+ console.log(chalk.red(" • aws_s3_bucket.production_data (CUSTOMER DATA)"));
+ console.log(chalk.red(" • aws_vpc.production (ALL NETWORK ROUTES)"));
+ console.log(chalk.red(" • + 47 more resources"));
+ console.log("");
+
+ await sleep(1000);
+
+ // ======================================================================
+ // Phase 5: The Predicate Intercept
+ // ======================================================================
+ printSection("PHASE 5: Predicate Authority Intercept");
+
+ printStep(4, "Agent attempts to execute terraform destroy");
+ console.log("");
+ printAgentAction("Calling cli.exec with: terraform destroy -auto-approve");
+ console.log("");
+
+ // Make the actual authorization request
+ const resource = "terraform destroy -auto-approve";
+
+ console.log(chalk.blue(" ┌" + "─".repeat(66) + "┐"));
+ console.log(chalk.blue(" │") + chalk.bgBlue(chalk.white(" AUTHORIZE ")) + chalk.white(" cli.exec".padEnd(54)) + chalk.blue("│"));
+ console.log(chalk.blue(" │") + chalk.white(" Resource: " + resource.padEnd(54)) + chalk.blue("│"));
+ console.log(chalk.blue(" │") + chalk.white(" Principal: " + CONFIG.principal.padEnd(53)) + chalk.blue("│"));
+ console.log(chalk.blue(" └" + "─".repeat(66) + "┘"));
+ console.log("");
+
+ await sleep(500);
+
+ // Make the actual request to the sidecar
+ const startTime = Date.now();
+ const authResponse = await this.sidecarClient.authorize({
+ principal: CONFIG.principal,
+ action: "cli.exec",
+ resource: resource,
+ });
+ const latencyMs = Date.now() - startTime;
+
+ if (!authResponse.allowed) {
+ // THE INTERCEPT HAPPENED!
+ console.log(chalk.red(` ✗ DENIED in ${latencyMs}ms`));
+ console.log(chalk.red(` Reason: ${authResponse.reason || "policy_denied"}`));
+ if (authResponse.violated_rule) {
+ console.log(chalk.red(` Rule: ${authResponse.violated_rule}`));
+ }
+ console.log("");
+
+ await sleep(500);
+
+ // Show the dramatic intercept message
+ printPredicateIntercept();
+
+ await sleep(1000);
+
+ // Show what would have happened without Predicate
+ printAmazonFailure();
+
+ } else {
+ // Unexpected - the policy should have blocked this
+ console.log(chalk.yellow(" ⚠ WARNING: Authorization was ALLOWED"));
+ console.log(chalk.yellow(" This demo expects terraform destroy to be DENIED by policy."));
+ console.log(chalk.yellow(" Check your policy.yaml configuration."));
+ }
+
+ // ======================================================================
+ // Summary
+ // ======================================================================
+ printSection("DEMO COMPLETE");
+
+ console.log(chalk.green(" ╔═══════════════════════════════════════════════════════════════════════╗"));
+ console.log(chalk.green(" ║ ║"));
+ console.log(chalk.green(" ║ 🎯 KEY TAKEAWAY: ║"));
+ console.log(chalk.green(" ║ ║"));
+ console.log(chalk.green(" ║ The Predicate Authority sidecar intercepted the destructive ║"));
+ console.log(chalk.green(" ║ terraform destroy command at the OS-level BEFORE execution. ║"));
+ console.log(chalk.green(" ║ ║"));
+ console.log(chalk.green(" ║ • Agent had AWS admin credentials ✓ ║"));
+ console.log(chalk.green(" ║ • Agent had intent to destroy ✓ ║"));
+ console.log(chalk.green(" ║ • Predicate said NO. ✓ ║"));
+ console.log(chalk.green(" ║ ║"));
+ console.log(chalk.green(" ║ This is agentic guardrails done right. ║"));
+ console.log(chalk.green(" ║ ║"));
+ console.log(chalk.green(" ╚═══════════════════════════════════════════════════════════════════════╝"));
+ console.log("");
+
+ } catch (error) {
+ printError(`Fatal error: ${(error as Error).message}`);
+ throw error;
+ }
+ }
+}
+
+// ============================================================================
+// Entry Point
+// ============================================================================
+
+async function main(): Promise {
+ const agent = new KiroOperatorAgent();
+ await agent.run();
+}
+
+main().catch((error) => {
+ console.error(chalk.red(`Fatal error: ${error.message}`));
+ process.exit(1);
+});
diff --git a/examples/kiro-reenactment-demo/tsconfig.json b/examples/kiro-reenactment-demo/tsconfig.json
new file mode 100644
index 0000000..1388f4c
--- /dev/null
+++ b/examples/kiro-reenactment-demo/tsconfig.json
@@ -0,0 +1,18 @@
+{
+ "compilerOptions": {
+ "target": "ES2022",
+ "module": "NodeNext",
+ "moduleResolution": "NodeNext",
+ "outDir": "./dist",
+ "rootDir": "./src",
+ "strict": true,
+ "esModuleInterop": true,
+ "skipLibCheck": true,
+ "forceConsistentCasingInFileNames": true,
+ "declaration": true,
+ "declarationMap": true,
+ "sourceMap": true
+ },
+ "include": ["src/**/*"],
+ "exclude": ["node_modules", "dist"]
+}