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). Blockswrite/edit/bashbefore 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-placesed/perl, mutatinggitsubcommands, 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 (neverHEAD, so your own uncommitted edits are never destroyed); a rail violation restores the snapshot and replaces the tool result with aGATE FAILEDerror. 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_prosecuteruns the deterministic P5 review loop in-session (fan-out → verify → loop-until-dry over write-disabled child sessions);adlc_gateruns the LLM-backed gates keyless through your session model. ATICKET-DONElistener 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 deterministicadlcCLIs; hooks are assistive,adlc rails-guardis 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/piThen 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.tsRequires 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
| Phase | pi surface |
|---|---|
| P0–P2 Triage → Decompose | adlc-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 & Build | the 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 Prosecute | native 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 Integrate | native adlc_gate tool + /adlc-accept command + rollback path; adlc behavior-diff / adlc run p6 |
| P7 Distill | adlc-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.
opencode
Native ADLC integration for the opencode terminal agent: an enforce-by-default rails-guard hook, nine lifecycle commands, native adlc_gate/adlc_prosecute tools, and a deterministic P5 prosecution loop (5 lenses + verifier) plus a prosecutor meta-agent.
Antigravity
Native ADLC integration for Google Antigravity (agy): an in-session rails-guard hook plus the unbypassable CI diff gate that is the real enforcement layer.