Skip to main content

Documentation Index

Fetch the complete documentation index at: https://hc.pillargtm.com/llms.txt

Use this file to discover all available pages before exploring further.

BUILDER’s biggest design constraint isn’t “what can it do” — it’s “what’s it prevented from doing without explicit human approval.” This page is the catalog.

Per-rule guardrails

Mandatory shadow mode

Every new rule starts in shadow mode. Cannot bypass this. The system enforces a 7-day minimum in shadow before promotion to propose, and a 14-day minimum in propose with an 80%+ approval rate before promotion to execute.

Per-account rate limit

Default: 1 fire per account per day per rule. Configurable per-rule (rate_limit_per_account_per_day). Prevents a runaway loop where Rule A fires Signal X which triggers Rule A again on the same account in the same minute.

Per-rule rate limit

Default: 50 fires per hour per rule. Configurable per-rule (rate_limit_per_hour). Prevents a single misconfigured rule from saturating the action pipeline org-wide.

Circuit breaker

Default: 5 errors in 10 minutes auto-disables the rule. Auto-disabled rules show a red AUTO-DISABLED badge with the failure reason. The customer’s Architect must manually re-enable after fixing the root cause — the system never auto-re-enables.

Postgres advisory locks

The action-executor takes a per-(rule_id, entity_id) advisory lock before executing. Two concurrent BUILDER cron ticks cannot act on the same rule + same account simultaneously.

Action idempotency keys

Each action invocation includes an idempotency key in builder_runs.provenance. If the same rule + entity + action fires twice within the dedup window, the second invocation no-ops with a stamped reason. Prevents double-charges, duplicate task creation, etc.

Org-level guardrails

Global kill switch

Admin-only emergency stop. From the /builder dashboard, an Admin clicks the red 🛑 Kill switch button, enters a reason (5+ chars), and every active rule in the org is set to is_active=false within ~1 second.

Approval expiry

Default: propose-mode actions expire 48h after creation if no human decides on them. Hard-coded for v1. Expired approvals stay in the queue with an EXPIRED status pill — the action does not execute.

High-impact action gating

Marking a rule is_high_impact = true requires Architect+ role to ever promote out of shadow. Subject to the Guarantee downgrade gate. Logged with severity: "high" in governance_log. Surfaced with a HIGH IMPACT pill in the UI.

Kill-switch reason audit

Each rule’s auto_disabled_reason is stamped with the kill-switch reason so the audit trail is preserved. Releasing the kill switch does NOT auto-re-enable rules — that’s intentional. It forces a triage step where someone has to look at each rule.

Guarantee runtime (Phase 8 §E)

The biggest safety feature. Every BUILDER execution passes through three verification gates before the action runs.

Pre-execution freshness check

Before the rule even evaluates, the engine checks underlying data freshness: scoring outputs ≤ 6 hours old, signals ≤ 2 hours old, CRM-synced fields ≤ 24 hours old. Configurable per-rule.

Real formula version stamping

Every rule that references a formula_name in its conditions gets the formula’s current version stamped on the run (sha256 hash of scoring_config rows). When formulas change, future runs carry the new version stamp.

Optimistic concurrency check

Right before BUILDER executes, it re-reads the target entity’s updated_at. If a human modified the account between when BUILDER decided to act and when it would have acted, BUILDER aborts with a state_changed log entry.
The downgrade rule: if freshness fails AND the action is high-impact, the rule’s verdict is guarantee_verified: false and the action is automatically downgraded from execute mode to propose mode. The downgraded proposal lands in the approval queue with the freshness reason stamped — a human has to confirm before it runs. Standard-impact actions on stale data still execute (logged as governance_status: "unverified") but get telemetry. Only high-impact gets the safety downgrade.

Audit trail

Every BUILDER run — matched or not — writes a row to builder_runs with full context:

Trigger source

Which event, which cron tick, which SLA breach.

Condition diagnostics

Every predicate’s verdict with the actual values that were tested.

Actions proposed + executed

The full action body for both proposed and executed actions.

Guarantee verification

guarantee_verified boolean + reason text + freshness check + formula versions used + concurrency-check timestamp.
Every executed action ALSO writes to governance_log with the rule, the run, the action body, and the Guarantee status. You can trace from “this email got sent” → “this run fired the rule” → “this evaluation said the conditions matched” → “this signal triggered it” → “this scoring formula said the account was at risk” → “this CRM field changed”. Full lineage. One click to audit.

What BUILDER will NOT do under any circumstance

These are the lines. If any of them are crossed, file a security ticket immediately.

Execute without writing to builder_runs

Every action is logged. No exceptions.

Execute while kill switch engaged

Every cron tick checks the org’s kill-switch state.

Execute the same (rule, entity) twice without idempotency

Advisory locks + idempotency keys both prevent this.

Bypass the 7-day shadow gate

Even on a rule that’s been deleted and re-authored.

Execute high-impact on stale data without a human

The Guarantee downgrade gate enforces this.

Cross-tenant access

Every query is org_id-scoped at SQL + RLS-enforced at Postgres.