ADLC
Integrations

pi

Native ADLC extension for the pi coding agent: in-session rail, scope, and suppression enforcement with git-diff revert, plus five phase skills.

ADLC in pi

A native pi TypeScript extension plus five skills. pi intentionally skips built-in orchestrators, so ADLC slots in through pi's Extension API: the extension enforces rails in-session while the skills route each phase to the deterministic adlc gates.

What you get

  • Proactive rail gate (tool_call). Blocks write/edit/bash before it touches disk when the target is a frozen rail, out of the ticket's scope, or the ADLC trust roots. Bash writes are gated here: redirects, tee, rm/mv/cp, in-place sed/perl, mutating git subcommands, and interpreter file-write APIs are recognized and rail-checked.
  • Reactive revert gate (tool_result). After any write/edit/bash, computes added lines against a pre-tool snapshot (never HEAD, so your own uncommitted edits are never destroyed); a rail violation restores the snapshot and replaces the tool result with a GATE FAILED error. Added lines are also scanned for undeclared suppression markers (@ts-ignore, eslint-disable, .skip(, # noqa, …) and reverted unless the ticket allows them. Operative-vs-inert classification is delegated to @adlc/rails-guard.
  • Build-gate + flail backstops. A degraded (context-rot) session on a high-risk ticket is denied its build until an audited override is recorded; repeated errors, scope churn, and oversized session logs surface as advisories.
  • Ticket doctrine injection (before_agent_start). The active ticket's scope, rails, and spec are appended to the system prompt every turn (sanitized; the ticket body is fenced as untrusted), which defends against premature satisfaction and context rot.
  • Native agent tools. adlc_prosecute runs the deterministic P5 review loop in-session (fan-out → verify → loop-until-dry over write-disabled child sessions); adlc_gate runs the LLM-backed gates keyless through your session model. A TICKET-DONE listener nudges prosecution at ticket completion.
  • Commands + footer status pill: /ticket, /adlc-ticket, /adlc-init, /adlc-approve-spec, /adlc-accept, /adlc-rollback, and a live pill showing the active enforcement context.
  • Skills: adlc (phase router), adlc-spec (P0–P2), adlc-rail-build (P3–P4), adlc-prosecute (P5–P6), adlc-distill (P7). Each wraps the deterministic adlc CLIs; hooks are assistive, adlc rails-guard is the proof.

Install

npm install -g @adlc/cli                       # the gate toolkit the skills wrap

# Per-project (lands in .pi/, auto-installs for every teammate on trusted startup):
pi install -l npm:@adlc/pi

# …or helper one-liner via npx:
npx adlc-pi install

# …or user-global (available in every repo you open):
pi install npm:@adlc/pi

Then run /adlc-init inside pi to finish the repo scaffold. @adlc/pi is published on npm, so pi install -l npm:@adlc/pi and npx adlc-pi install work today. Developing against a checkout? Load the extension directly instead:

pi --extension /path/to/adlc/plugins/adlc-pi/index.ts

Requires Node ≥ 22.19 (the pi floor). Peer dependency: @earendil-works/pi-coding-agent (manifest pins "*"; verified against 0.80.3, with a weekly version-matrix smoke tracking the latest published build).

Enforcement model

Enforcement is opt-in by activating a ticket: set ADLC_TICKET or write .adlc/current-ticket.json (tickets file overridable via ADLC_TICKETS). With no active ticket the extension is inert. Once a ticket id resolves, the extension fails closed: an unreadable or unparseable tickets file, or an unknown ticket id, blocks all tool calls until fixed (with a red status pill telling you why). Unlike the sibling integrations, this plugin does not use ADLC_P4_ENFORCEMENT; the active ticket is the switch.

.adlc/tickets.json and .adlc/current-ticket.json are unconditionally blocked from edits regardless of rails, so the agent can't rewrite its own constraints. An empty ticket scope means unrestricted; .adlc/ and .omo/ stay writable for evidence.

The commit-time backstop is the same harness-agnostic CI gate as every other integration: scripts/rails-guard-ci.mjs reads the frozen rail set from the trusted base ref and rejects any PR that edits a rail, however the edit was made. Make it a required check.

Formal ADLC coverage

Phasepi surface
P0–P2 Triage → Decomposeadlc-spec skill (parallax, spec-lint, premortem, coldstart, merge-forecast, model-router); ticket resolution on session_start; prompt templates (/adlc-spec, /adlc-decompose)
P3–P4 Rail & Buildthe extension: proactive tool_call block + reactive tool_result snapshot-scoped revert + operative-only suppression gate + build-gate + flail advisory + evidence rail + custom-tool coverage
P5 Prosecutenative adlc_prosecute tool: in-session fan-out → verify → loop-until-dry over write-disabled child sessions; TICKET-DONE completion nudge; plus the adlc-prosecute skill (prosecute, behavior-diff, adlc run p5)
P6 Integratenative adlc_gate tool + /adlc-accept command + rollback path; adlc behavior-diff / adlc run p6
P7 Distilladlc-distill skill (lesson-foundry, rejection-mining, skill-rot, model-ratchet); scheduled runs via CI cron

Command surface: /ticket, /adlc-ticket, /adlc-init, /adlc-approve-spec, /adlc-accept, /adlc-rollback, plus the adlc-* prompt templates. The footer widget renders the active ticket and last gate verdict.

Remaining gaps (design intent, not yet shipped): a session_shutdown auto-capture for P6 (accept is command-driven today), and an in-harness P7 scheduler (pi has no /schedule; CI cron is the substrate). @adlc/pi is published on npm, so the pi install one-liner above works today. A weekly version-matrix smoke tracks upstream pi drift.

Go deeper

Source: plugins/adlc-pi/ · design plan: docs/integrations/pi.md.

The rail-freeze gate this extension enforces in-session: Tests Are the Spec.

On this page