v0.15.0 — Espalier learns Codex AND Copilot: one guardrail tree, three platforms
0.15.0 — Copilot platform support
Minor: GitHub Copilot platform support — the wiring layer goes
three-platform. --platforms (and espalier-init's platform question) now
accepts any subset of claude, codex, copilot (shorthands both /
all); the espalier/ tree stays the single platform-neutral source of
truth. Additive as ever: espalier/.platforms unions, nothing unwires,
claude-only output stays byte-stable. Suites: bootstrap 117/117 (+3-platform,
copilot-only, idempotent-re-run fixtures), hooks 86/86 (+adapter payload
matrix); validation is 46/51/56 by platform set.
scripts/bootstrap-espalier.sh— new stages: 7c appends the
## Espaliersection to.github/copilot-instructions.md(grep-guarded;
always-read-rules instruction + Copilot platform-mapping table:
@harness-*custom agents, per-surface hook caveats); 8d writes
.github/agents/harness-{coder,reviewer,security}.agent.mdcustom agents
(write-if-absent; bodies point at the sameespalier/agents/*.md); 8e
writes.github/hooks/espalier-gates.json(own file — user hook files
untouched; write-if-absent; self-heals the adapter copy on wire-only runs).
Stage 5 symlinks the 12 skills into.github/skills/— the one Agent
Skills location ALL Copilot surfaces read (VS Code, CLI, cloud coding
agent). Validation: checks 52-56; totals 46/51/56 with codex's 47-51
skip-rendered when only copilot forces the range, keeping numbering
contiguous.hook-templates/copilot-hook-adapter.sh(new) — translates Copilot's
camelCase hook payload (toolName/toolArgs, incl.path/filePath→
file_path) into the Claude/Codex shape and dispatches to the shared
wrappers; exit codes pass through (Copilot fails non-zeropreToolUse
exits closed — the exit-2 contract carries over). Without python it passes
the raw payload through, preserving the push gate's grep fast-path and
fail-closed probe. Missing wrapper → exit 0, never bricks a session.skills/espalier-init/SKILL.md— Q4 becomes multiSelect across the
three platforms; Phase 3/Phase 4 and the "Running under Codex or Copilot"
fallback table extended (Copilot user-scope install via~/.copilot/skills).skills/espalier-migrate/SKILL.md+scripts/migrate-v0.14.0-to-v0.15.0.sh
— migration #22: always installs the adapter (one new file, no backups
needed);--with-copilot(asked in the skill's Step 4c) wires copilot
additively viabootstrap --wire-only.- Docs —
docs/copilot-integration.md(surfaces matrix incl. the
VS Code-runs-no-hooks gap, adapter contract, troubleshooting),
docs/migrating-v0.14-to-v0.15.md, README Copilot install section;
references/wiring.md+references/validation.mdextended.
0.14.0 — Codex platform support (released together under this tag)
Minor: Codex platform support — the same discovered guardrails wire into
OpenAI Codex as a first-class target. espalier-init gains a Phase 0 platform
question (Claude Code / Codex / Both) and bootstrap-espalier.sh a
--platforms= flag; the espalier/ tree stays platform-neutral, only wiring
differs. Additive + idempotent: espalier/.platforms records the set, re-runs
union (adding codex later never unwires claude), and a complete pre-v0.14
install is inferred as claude. Suites: bootstrap 97/97 (+3 codex tests),
hooks 73/73 (+payload matrix), validation 51 checks on codex installs while
claude-only output stays byte-stable at 46.
scripts/bootstrap-espalier.sh— new stages: 7b appends the## Espalier
section toAGENTS.md(grep-guarded; carries the always-read-rules
instruction — Codex has no auto-loaded rules dir — plus the platform-mapping
table:AskUserQuestion→ chat, sub-agent spawn →.codex/agents/,
/espalier*→$espalier*); 8b appends a marker-guarded hook block to
.codex/config.toml(PostToolUse ^(apply_patch|Edit|Write)$→
post-edit-wrapper,PreToolUse ^(Bash|shell|local_shell)$→
pre-push-gate-wrapper — Codex shares Claude Code's hook JSON schema and
exit-2-blocks contract, so the same wrappers serve both; backup + valid-TOML
append); 8c writes.codex/agents/harness-{coder,reviewer,security}.toml
(write-if-absent — user model tuning survives;developer_instructions
point at the sameespalier/agents/*.md). Stage 5 symlinks the 12 skills
into.agents/skills/(Codex repo-skill discovery; same folder-name ==
frontmatter-name invariant). Claude-only stages gate on the platform set;
codex-only installs create no.claude/litter.--wire-onlynow reuses a
persisted--merge-decisionand runsstage_mkdirs, so "add a platform
later" is one flag. Validation: checks 47-51 (codex wiring), dynamic totals,
claude checks skip (or swap toespalier/-source equivalents) when claude
is not targeted.hook-templates/post-edit-wrapper.sh— platform-neutral: uses
tool_input.file_pathwhen present, else extracts every
*** Add|Update File:path from the apply_patch body (string or argv
array); checks each file, exit 2 if any violates; repo root from
$CLAUDE_PROJECT_DIRelsegit rev-parse --show-toplevel.hook-templates/pre-push-gate-wrapper.sh— joins argv-array commands
before the push-pattern match (the Python-list rendering would have been
eaten by the quote-span stripper and failed OPEN);CLAUDE_PROJECT_DIR
fallback is now unset-safe.skills/espalier-init/SKILL.md— Phase 0 Q4 (platforms), Phase 3
--platforms=flag +${CLAUDE_SKILL_DIR}Codex fallback, Phase 4
codex trust steps in the completion message, and a "Running under Codex"
fallback table so$espalier-initruns from inside Codex itself.skills/espalier-migrate/SKILL.md+scripts/migrate-v0.13.2-to-v0.14.0.sh
— migration #21: always refreshes the two wrappers (backups
<file>.pre-v0.14.bak);--with-codex(asked in the skill's Step 4b)
wires codex additively viabootstrap --wire-only.- Docs —
docs/codex-integration.md(surfaces, trust model, degradations,
troubleshooting),docs/migrating-v0.13-to-v0.14.md, README Codex install
section;references/wiring.md+references/validation.mdextended.
Setup guides: docs/codex-integration.md · docs/copilot-integration.md · Existing installs: run /espalier-migrate.