Enforcement Layer Reference

This page is a Reference. It describes the enforcement machinery. Consult it when you need to know exactly what a guard checks, what a gate validates, or what the audit log schema contains. For background on why enforcement works the way it does, see Understanding the VECTOR Architecture.


Enforcement Components

VECTOR's enforcement layer has four components:

Component Stage Description
Dispatch Guard Pre-spawn Hierarchy compliance, mode check, scope validation
Gate System During task Quality checkpoints at planning, code review, and integration
Schema Validators On config/belief write Structure and integrity checks
Audit Trail Continuous Immutable append-only log of all system actions

Dispatch Guard

The Dispatch Guard runs before any PM or worker session is spawned. A spawn request that fails the Dispatch Guard is rejected. No spawn occurs.

Checks

Mode check

Reads state/vector-mode.json. Allowed spawn types per mode:

Mode Autonomous spawns Manual spawns
autonomous Allowed Allowed
directed Blocked Allowed (Chief-initiated only)
emergency Blocked Blocked

Hierarchy check

From May spawn May not spawn
VECTOR (Tier 0) PMs (Tier 1) Workers (Tier 2), other VECTOR instances
PM (Tier 1) Workers (Tier 2) Other PMs, VECTOR
Worker (Tier 2) Nothing Anything

A Tier 1 PM attempting to spawn another PM is a Dispatch Guard violation. The spawn is rejected and the violation is logged to audit_log.

Ticket existence check

Every spawn must reference a valid ticket ID in state/vector.db. A spawn request with no corresponding tickets record is rejected.

OS scope check

Any spawn that requests browser, terminal, Peekaboo, or system configuration access is rejected unless the spawner is VECTOR (Tier 0).

Mode State File

Location: state/vector-mode.json

{
  "mode": "autonomous",
  "changed_at": "2026-02-27T00:00:00Z",
  "changed_by": "chief",
  "reason": null
}
Field Type Values
mode string autonomous | directed | emergency
changed_at ISO 8601 datetime
changed_by string chief | vector | system
reason string | null Human-readable reason for mode change

Failsafe Triggers

Trigger phrase Effect Mode set
stop No new autonomous spawns directed
emergency stop Kill all active workers immediately emergency
resume Resume autonomous operation autonomous

State is preserved on all mode transitions. In-flight worker output is not discarded.


Gate System

Quality gates are checkpoints in the task lifecycle. Gates are not optional. A task that cannot present a gate ID for a required stage is not accepted as complete.

Gate A — Plan Review

When: Before any worker is spawned.

Inputs required:

Checks performed:

Check Pass condition
Spec file exists File at spec_path is readable
Spec is non-empty More than 100 bytes
Scope is bounded No scope phrases like "rewrite entire codebase", "migrate all data" without explicit Chief approval flag
Risk documented Spec contains a risk section
No file conflicts No in-flight tasks in tickets table working on same files

Output on pass: Gate ID in format GATE-A-YYYYMMDD-NNN

Output on fail:

Gate A FAILED for [task description]:
  - [specific failure reason 1]
  - [specific failure reason 2]
Action: Address failures and resubmit.

Required usage: Gate ID must be embedded in the worker task spec as [GATE:GATE-A-YYYYMMDD-NNN]. Worker spawns without a Gate A ID are rejected by the Dispatch Guard.


Gate B — Code Review

When: After worker completes, before merge.

Inputs required:

Review method: git diff main..task/TASK-xxx — the PM reviews the actual diff, not the worker's self-report or PTY output.

Checks performed:

Check Pass condition
Scope compliance All changed files are within the declared task scope
No regressions Existing test suite passes
Security scan No plaintext secrets, no injection vectors in changed files
Coverage New functionality has corresponding test coverage
Readability Code quality meets PM judgment threshold

Output on pass: Gate ID in format GATE-B-YYYYMMDD-NNN

Output on fail:

Gate B FAILED for [task description]:
  - [specific failure: file, line, reason]
  - [specific failure: file, line, reason]
Action: Address failures, resubmit Gate B.

Loop behavior: On Gate B failure, the PM sends specific fix requirements to the same Codex worker session. The loop continues until Gate B passes or timeout is reached (15 minutes per worker session).


Gate C — Integration Check

When: Before merge to main branch.

Inputs required:

Checks performed:

Check Pass condition
Branch is clean No uncommitted changes on branch
No merge conflicts git merge-base --is-ancestor succeeds
Dependent services healthy SENTINEL health check returns green
CUSTOM_PATCHES.md review Changed files not listed as NEVER-AUTO-MERGE in CUSTOM_PATCHES.md
Build succeeds npm run build exits 0 on branch

Output on pass: Gate ID in format GATE-C-YYYYMMDD-NNN

CUSTOM_PATCHES.md conflict behavior: Any file listed in CUSTOM_PATCHES.md is automatically classified as DANGER. Gate C will not pass for a branch containing DANGER-classified changes without explicit Chief approval recorded in the ticket.


Gate ID Format

GATE-{TYPE}-{YYYYMMDD}-{NNN}

Examples:
  GATE-A-20260227-001
  GATE-B-20260227-014
  GATE-C-20260227-007
Segment Format Description
TYPE A | B | C Gate type
YYYYMMDD 8-digit date UTC date of gate check
NNN 3-digit zero-padded integer Sequential counter per day per type

Gate IDs are unique across the system. They are stored in audit_log.gate_id for traceability.


Schema Validators

openclaw.json Validator

Location: scripts/validate-openclaw-config.js

When to run: Before any change to openclaw.json is saved. The gateway has no fallback on invalid config — a malformed config crashes the daemon on next restart.

Checks performed:

Field Valid values Invalid examples
agent.model String starting with anthropic/ or openai/ claude-opus (missing provider prefix)
auth.profiles[*].mode api_key | oauth | token api-key (hyphens not underscores)
gateway.port Integer 1024–65535 "18789" (string not integer)
plugins.entries[*].enabled Boolean "true" (string not boolean)
Credential values Must not be present Any field containing sk-, Bearer , or 40+ char strings

Output on pass:

✓ openclaw.json is valid
✓ No credentials detected in config
✓ All required keys present

Output on fail:

✗ Validation failed:
  - auth.profiles.anthropic.mode: "api-key" is not a valid mode. Use "api_key".
  - gateway.port: must be an integer, got string "18789"

BEE Belief Validator

When: Before any belief is written to state/vector.db.

Required fields:

Field Type Constraints
content string Non-empty, max 2000 chars
scope enum private | shared | global
type string Non-empty
confidence float 0.0–1.0 inclusive
source string Must match an existing ticket ID in tickets table
status enum Always provisional on creation — never active

Rejected conditions:


Audit Trail

Table: audit_log in state/vector.db

CREATE TABLE audit_log (
  id          INTEGER PRIMARY KEY AUTOINCREMENT,
  timestamp   TEXT    NOT NULL DEFAULT (datetime('now')),
  actor       TEXT    NOT NULL,
  action      TEXT    NOT NULL,
  target      TEXT,
  result      TEXT,
  detail      TEXT,
  gate_id     TEXT
);
Column Type Description
id integer Auto-incrementing primary key
timestamp ISO 8601 text UTC timestamp of action
actor text VECTOR | FORGE | GHOST | ORACLE | SENTINEL | COMPASS | SAGE | SYSTEM
action text See action types below
target text | null Ticket ID, file path, belief ID, or PM name
result text | null passed | failed | error | skipped
detail JSON text | null Context blob — contents vary by action type
gate_id text | null Linked gate check ID if action involves a gate

Action Types

Action Actor Description
spawn_pm VECTOR PM session created
spawn_worker PM Worker session created
gate_check PM | VECTOR Gate A/B/C check submitted
belief_write VECTOR Belief written to beliefs table
belief_promote VECTOR Belief promoted from provisional to active
belief_reject VECTOR Belief rejected from pending_shared
ticket_create VECTOR Ticket created in tickets table
ticket_close VECTOR Ticket marked complete
mode_change VECTOR | SYSTEM vector-mode.json updated
dispatch_violation SYSTEM Dispatch Guard rejected a spawn
config_validate VECTOR openclaw.json validation run

Retention

Audit log records are never deleted. Monthly archival (midnight UTC, first of month) compresses records older than 90 days to state/audit_archive_YYYYMM.db. The primary audit_log table retains the trailing 90 days for fast queries.

Example Queries

# Last 20 actions
sqlite3 state/vector.db \
  "SELECT timestamp, actor, action, result FROM audit_log ORDER BY id DESC LIMIT 20;"

# All gate failures in the last 7 days
sqlite3 state/vector.db \
  "SELECT timestamp, actor, target, detail FROM audit_log
   WHERE action = 'gate_check' AND result = 'failed'
   AND timestamp > datetime('now', '-7 days');"

# All actions on a specific task
sqlite3 state/vector.db \
  "SELECT timestamp, actor, action, result FROM audit_log
   WHERE target LIKE '%TASK-20260226-010%'
   ORDER BY id ASC;"

# Dispatch violations this month
sqlite3 state/vector.db \
  "SELECT timestamp, detail FROM audit_log
   WHERE action = 'dispatch_violation'
   AND timestamp > datetime('now', 'start of month');"