The five-layer governance stack from CLAUDE.md Is Not Enough: The Governance Stack for Agentic Development, as a drop-in starter kit. Copy the templates below into your project, customize the placeholders, and you have the document foundation, the runtime-enforcement hook, and the external-validation CI workflow described in the article. These are starting points, not policy — read them, edit them, and treat the placeholders as prompts for project-specific decisions.

Install order

  1. CONSTITUTION.md — Defines the project's governing principles and the decision order that resolves conflicts between them.
  2. DIRECTIVES.md — Converts the constitution's principles into enforceable rules at three severity levels: Critical, Important, Recommended.
  3. SECURITY.md — Defines vulnerability scope, reporting, severity, and response targets — including agent-specific concerns like prompt injection and hook bypass.
  4. AGENTS.md — Open-standard project orientation for AI coding agents — file map, commands, working rules, precedence.
  5. CLAUDE.md — Claude-specific orientation that supplements AGENTS.
  6. .claude/hooks/pre-tool-use.js — PreToolUse:Bash hook that blocks direct commits and pushes to the protected branch, including nested shell bypasses.
  7. .claude/settings.json — Registers the pre-tool-use hook against PreToolUse:Bash and declares the project's Bash permission allow/deny rules.
  8. .githooks/pre-push — Git pre-push hook that closes the bare-push gap the Claude PreToolUse hook cannot see.
  9. .github/workflows/governance.yml — Three-job CI workflow — lint and test, static analysis, dependency scan — with every third-party action pinned to a commit SHA to defend against mutable-tag supply-chain risk.
  10. agentic-governance-stack/README.md — Step-by-step install instructions written for a coding agent.

Quick start: hand this prompt to your agent

Paste the prompt below into a fresh Claude Code (or compatible agent) session inside the project you want to govern. The agent will fetch this page, walk through the templates in order, customize the placeholders with you, and open a pull request with the stack installed.

agent-install-prompt.txt — Hand to your agent




You are installing the EthereaLogic Agentic Governance Stack into the current project. Templates and instructions live at https://etherealogic.ai/agentic-governance-stack-templates/

Steps:
1. Read the article first: https://etherealogic.ai/claude-md-is-not-enough-the-governance-stack-for-agentic-development/
2. Open https://etherealogic.ai/agentic-governance-stack-templates/. Each template on that page is wrapped in <figure class="codeblock"> with data-template-path indicating where it belongs in the project tree.
3. For each template (in the order they appear on the page), copy the exact contents of the inner <pre><code> element into a file at the path given by data-template-path, relative to the project root. Mark .claude/hooks/pre-tool-use.js and .githooks/pre-push as executable.
4. Wire the git pre-push hook:
   git config --local core.hooksPath .githooks
5. Customize the placeholders in CONSTITUTION.md, DIRECTIVES.md, SECURITY.md, AGENTS.md, and CLAUDE.md for this project. Do not leave the contact email or stack tables as-is.
6. Replace the SHA placeholders in .github/workflows/governance.yml with current SHAs from each action's release page.
7. Verify the Claude hook is wired by running:
   echo '{"tool_name":"Bash","tool_input":{"command":"git push origin main"}}' \
     | node .claude/hooks/pre-tool-use.js
   The expected exit code is 2 with a BLOCKED message on stderr.
8. Verify the git pre-push hook by running:
   printf 'refs/heads/feature abc123 refs/heads/main 000\n' \
     | bash .githooks/pre-push
   The expected exit code is 1 with a BLOCKED message on stderr.
9. Confirm with the operator that server-side branch protection is configured on the remote (e.g., GitHub branch protection on main).
10. Open a pull request with the templates installed. Do not push directly to main; the hooks you just installed will block it, and branch protection will reject it on the remote regardless.
11. Report back to the operator with the PR URL and a one-paragraph summary of what was installed and what was customized.

One-shot installation prompt. Paste into a fresh agent session inside your project root and the agent will install the full stack from the templates below.

The templates

Each template below is a self-contained file. The figure caption shows the destination path relative to your project root. The Copy button copies the body to your clipboard; Download saves it as a file with the correct extension. Both pull from the same source — what you see is exactly what your agent or you will install.

CONSTITUTION.md

CONSTITUTION.md — Layer 2 — Constitutional governance




# Constitution

The constitution defines the governing principles of this project and the
**decision order** in which conflicts between them are resolved.

When two principles disagree, the higher-numbered one wins. This is the
statement; the principles below are scoped to it.

## Article I — Decision Order

When principles conflict, the agent and the team apply them in this order,
top to bottom:

1. **Safety.** No action that risks data loss, credential exposure, or
   destructive change to shared systems is acceptable, regardless of
   downstream cost.
2. **Evidence traceability.** A claim must be verifiable from artifacts the
   reviewer can re-run. Speed gains do not justify unverified claims.
3. **Correctness.** A working incorrect answer is worse than a slower correct
   one.
4. **Determinism.** Repeated runs from the same starting state should
   produce the same result.
5. **Throughput.** Where the four principles above are satisfied, prefer the
   shortest path to a working change.
6. **Aesthetics.** Naming, formatting, and layout matter, but not at the cost
   of any principle above.

## Article II — Principles

The decision order operates on the following principles. Each principle is
brief on purpose; specific enforcement lives in `DIRECTIVES.md`.

- **Reproducibility.** Every result a contributor reports must be reproducible
  from the repository state at that moment, by another contributor or by CI,
  without privileged access.
- **Evidence over assertion.** A test report that says "PASS" without machine-
  verifiable output and a human-readable artifact does not satisfy any review
  requirement of this project.
- **Production-first.** The default state of any file shipped from this
  repository is production-ready. Placeholder content, mocked values, and
  TODOs are not acceptable in the production scan root.
- **Least privilege.** Tools and humans operate with the minimum permissions
  required for the task.
- **Reviewability.** Changes are introduced in increments small enough to be
  reviewed end-to-end by another contributor.
- **Documented intent.** A change that is not obvious from the diff is
  explained in the commit message, the PR description, or both.

## Article III — Scope

This constitution governs work performed inside this repository, by humans,
agents, automated tooling, and CI. It does not bind external systems or
upstream dependencies.

## Article IV — Amendment

The constitution may be amended only by a pull request that:

1. Modifies this file.
2. Includes a written rationale in the PR description.
3. Receives review from at least one human maintainer.

Agents may propose amendments. Agents may not merge them.

---

*Adapted from the Agentic Governance Stack templates published at
[etherealogic.ai](https://etherealogic.ai/). Customize for your project's
constraints — the decision order matters more than the specific principles.*

Defines the project's governing principles and the decision order that resolves conflicts between them.

DIRECTIVES.md

DIRECTIVES.md — Layer 2 — Constitutional governance




# Directives

Directives convert the principles in `CONSTITUTION.md` into enforceable rules
at three severity levels. The constitution states what we believe; this file
states what we will and will not do.

Severity:

- **Critical** — blocking. Violations stop the change from landing. No bypass
  without an explicit waiver recorded in the PR.
- **Important** — requires written justification to bypass, in the PR
  description.
- **Recommended** — good practice. Skipping is allowed without justification
  but should be rare.

Each directive carries an ID. Cite the ID in commit messages or PR comments
when a directive is involved.

## Critical

- **CRIT-001 — No direct commits or pushes to `main` / `master`.** All
  changes land via pull request. Enforced by **three independent layers**,
  none of which is sufficient on its own:
  1. The Claude Code `PreToolUse:Bash` hook
     (`.claude/hooks/pre-tool-use.js`) catches Bash invocations whose
     refspec explicitly names a protected branch — including nested
     shell wrappers (`bash -c "git push origin main"`) and compound
     commands. It cannot catch bare `git push` or `git commit`,
     because the hook surface does not expose the working-tree branch.
  2. The local git pre-push hook (`.githooks/pre-push`, wired with
     `git config --local core.hooksPath .githooks`) catches every push
     that resolves to a protected branch on the remote, including the
     bare-push case the Claude hook misses.
  3. Server-side branch protection rules on the hosted remote
     (e.g., GitHub branch protection on `main`) is the final
     authoritative gate. Configure it on the remote and require pull
     requests for the protected branch.
- **CRIT-002 — No fabricated metrics.** A reported number must trace to a
  reproducible artifact in the repository or in CI. "Approximately X"
  language is not a substitute for measurement.
- **CRIT-003 — No placeholder content in production paths.** Files in the
  production scan root must not contain `TODO`, `FIXME`, `XXX`, lorem-ipsum
  text, or stubbed function bodies that return constants.
- **CRIT-004 — Dual evidence for PASS claims.** Any test or check claimed as
  passing must produce both a machine-verifiable artifact (exit code, JSON
  report, log file) and a human-readable summary. One without the other does
  not satisfy this directive.
- **CRIT-005 — No secrets in the repository.** Credentials, tokens, API
  keys, and private keys are not committed. Detected secrets must be
  rotated, not just removed from history.
- **CRIT-006 — No bypassing pre-commit / pre-push hooks.** `--no-verify`,
  `--no-gpg-sign`, and equivalent flags are not used unless the operator has
  explicitly authorized it for a single commit, with the rationale recorded
  in the commit message.

## Important

- **IMP-001 — Conventional commit format.** Commit subjects use the
  `type(scope): summary` form. Types: `feat`, `fix`, `chore`, `docs`,
  `test`, `refactor`, `perf`, `build`, `ci`.
- **IMP-002 — Tests live alongside the code they validate.** Each new
  module ships with at least one test exercising its public surface.
- **IMP-003 — Dependencies are pinned.** Lockfiles are committed. Floating
  version specifiers (`^`, `~`, `*`) require justification.
- **IMP-004 — GitHub Actions are pinned to a commit SHA.** Version tags are
  mutable and a documented supply-chain attack surface. See
  `.github/workflows/governance.yml` for the pinning convention.
- **IMP-005 — Public-facing code passes static analysis.** Lint, type
  check, and security scan must pass on every PR.

## Recommended

- **REC-001 — Prefer pure functions and explicit dependencies.** Side effects
  are isolated at boundaries.
- **REC-002 — Document the WHY in commit messages, not the WHAT.** The diff
  shows what changed; the message explains why.
- **REC-003 — Small, focused PRs.** A single PR addresses a single concern.
- **REC-004 — Update documentation in the same PR as the change.** Stale
  docs are worse than no docs.
- **REC-005 — Annotate non-obvious code with one-line comments only when
  the WHY is non-obvious.** Avoid restating the WHAT.

## Bypass and waiver

A directive may be waived for a single change by:

1. Citing the directive ID in the PR description.
2. Stating the rationale.
3. Receiving review from a human maintainer who explicitly approves the
   waiver.

Waivers are not retroactive. A change that violates a directive without a
recorded waiver is reverted, not patched.

---

*Adapted from the Agentic Governance Stack templates published at
[etherealogic.ai](https://etherealogic.ai/). Tune severity to your context —
some teams promote `CRIT-006` to a hard policy enforced by branch
protection, others keep it advisory.*

Converts the constitution's principles into enforceable rules at three severity levels: Critical, Important, Recommended.

SECURITY.md

SECURITY.md — Layer 2 — Constitutional governance




# Security Policy

This file defines what counts as a security vulnerability in this project,
how to report one, how the project will respond, and what is out of scope.

## Reporting a vulnerability

Email **security@example.com** with:

1. A clear description of the issue.
2. Reproduction steps or a proof of concept.
3. The affected version, branch, or commit.
4. Whether the issue is currently being exploited.

Do not file public issues for vulnerabilities. We will acknowledge receipt
within two business days and provide a status update within five.

If you prefer encrypted communication, our PGP key is at:
**https://example.com/.well-known/security.pgp**

## What is in scope

The following are treated as vulnerabilities subject to this policy:

- Remote code execution against the build, deploy, or runtime surface.
- Credential leakage — committed secrets, secrets exposed via logs, or
  secrets exfiltrable via crafted input.
- Authentication or authorization bypass.
- Injection (SQL, command, prompt, template) into any code path that
  reaches a privileged operation.
- Supply-chain compromise — including dependency tampering, registry
  takeover, and unverified action invocation.
- Denial of service against shared infrastructure operated by the project.
- **Prompt injection that causes an agent to violate a CRIT-level
  directive.** Agentic projects treat prompt-injection attacks that bypass
  governance as in-scope security issues, not feature requests.
- **Hook bypass.** Any input or shell construction that allows a tool call
  to land despite a registered enforcement hook (e.g., `PreToolUse:Bash`)
  is in scope.

## What is out of scope

- Theoretical issues without a working proof of concept.
- Findings against unsupported or end-of-life versions.
- Self-XSS that requires the victim to paste the payload into their own
  console.
- Rate-limiting and brute-force issues against public, unauthenticated
  endpoints (these are addressed at infrastructure layers).
- Issues in third-party dependencies that have not yet been published. We
  monitor dependency advisories and will respond once an upstream fix is
  available.

## Severity

Severity is assigned at triage by the maintainer who acknowledges the
report. Targets below are best-effort — high-volume periods or upstream
dependencies may extend them.

| Severity   | Definition                                             | Acknowledgement | Initial response | Patched in supported branches |
|------------|--------------------------------------------------------|-----------------|------------------|-------------------------------|
| Critical   | Active exploitation possible against production users  | 24 hours        | 72 hours         | 7 days                        |
| High       | Exploitable with low complexity, no active exploitation| 48 hours        | 7 days           | 30 days                       |
| Medium     | Exploitable with elevated complexity or preconditions  | 5 days          | 14 days          | 60 days                       |
| Low        | Limited impact, defense-in-depth improvement           | 5 days          | 30 days          | next release                  |

## Disclosure

We coordinate disclosure with the reporter. The default is:

1. Reporter notifies the project privately.
2. Project triages, assigns a severity, and produces a fix.
3. Fix is released; an advisory is published referencing the reporter (with
   their consent) and the affected versions.
4. Public disclosure occurs after the advisory, typically 7 to 30 days
   after the fix lands, depending on severity.

If the reporter requires a faster public timeline, we will negotiate in
good faith. We do not pursue legal action against good-faith researchers
who comply with this policy.

## Hall of fame

Researchers whose reports lead to a published advisory are credited in the
project's `THANKS.md` file (with their consent). This project does not
operate a paid bounty program at this time.

---

*Adapted from the Agentic Governance Stack templates published at
[etherealogic.ai](https://etherealogic.ai/). Replace the contact, response
targets, and the supported-version table with values that match your
team's actual capacity.*

Defines vulnerability scope, reporting, severity, and response targets — including agent-specific concerns like prompt injection and hook bypass.

AGENTS.md

AGENTS.md — Layer 1 — Navigation files




# AGENTS.md

This file is the project orientation layer for AI coding agents. It covers
where things live, what commands run, and how the project expects agents to
behave. It is the open-standard counterpart to `CLAUDE.md`.

## Read order

Before substantive work, read in this order:

1. `CONSTITUTION.md` — governing principles and decision order.
2. `DIRECTIVES.md` — enforceable rules at three severity levels.
3. `SECURITY.md` — what counts as a vulnerability and how to report one.
4. This file — orientation, commands, conventions.
5. `CLAUDE.md` (Claude only) — Claude-specific notes that supplement this
   file rather than replace it.

When this file and a higher-priority file disagree, the higher-priority
file wins.

## File map

| Path                        | Purpose                                          |
|-----------------------------|--------------------------------------------------|
| `src/`                      | Production source code                           |
| `tests/`                    | Test suite                                       |
| `docs/`                     | Documentation, including ADRs                    |
| `scripts/`                  | Build, verify, and deploy scripts                |
| `.claude/`                  | Claude-specific configuration (if applicable)    |
| `.github/workflows/`        | CI workflows                                     |
| `CONSTITUTION.md`           | Governing principles                             |
| `DIRECTIVES.md`             | Enforceable rules                                |
| `SECURITY.md`               | Vulnerability policy                             |
| `AGENTS.md`                 | This file                                        |
| `CLAUDE.md`                 | Claude-specific orientation                      |

## Tech stack

Replace this section with your project's stack. Keep it brief — agents need
the headline, not a tutorial.

| Layer       | Technology     |
|-------------|----------------|
| Runtime     | (e.g., Node 20)|
| Language    | (e.g., TS 5.4) |
| Framework   | (e.g., Next 15)|
| Test runner | (e.g., Vitest) |
| Lint        | (e.g., ESLint) |

## Commands

| Command           | Purpose                                |
|-------------------|----------------------------------------|
| `make install`    | Install dependencies (or `npm ci`)     |
| `make test`       | Run the full test suite                |
| `make lint`       | Lint and type-check                    |
| `make build`      | Produce a deployable artifact          |
| `make verify`     | Run the local guardrails check         |

Replace these with the actual commands for your project. Agents will assume
the entries here are authoritative.

## Working rules

These rules apply to every change, by humans and agents alike.

- Edit existing files in preference to creating new ones.
- Do not introduce a new dependency without justifying it in the PR.
- Do not regenerate lockfiles unless the dependency change is intentional.
- All PASS claims require dual evidence (`DIRECTIVES.md` CRIT-004).
- All commits use conventional commit format (`DIRECTIVES.md` IMP-001).
- Run `make verify` before submitting a PR.

## Agent specialization

If the project uses scoped sub-agents (e.g., a test automator, a security
reviewer, a UX specialist), document each one's scope and evidence
requirements here. The default is to use the general-purpose agent.

## Precedence

When patterns conflict, resolve in this order:

1. `CONSTITUTION.md`
2. `DIRECTIVES.md`
3. `SECURITY.md`
4. This file
5. `CLAUDE.md` and other agent-specific files
6. Inline code comments
7. Commit history

## Ground rules for agents

- An agent may propose changes to any file in this list. An agent may not
  merge changes to `CONSTITUTION.md`, `DIRECTIVES.md`, or `SECURITY.md`
  without human review.
- An agent that produces an output it cannot verify must say so explicitly
  rather than claiming success.
- An agent that hits a runtime barrier (a hook exit, a CI failure, a
  permission denial) investigates the underlying cause rather than working
  around the barrier.

---

*Adapted from the Agentic Governance Stack templates published at
[etherealogic.ai](https://etherealogic.ai/). The AGENTS.md format is an
open standard governed by the Linux Foundation's Agentic AI Foundation;
this file is compatible with that standard.*

Open-standard project orientation for AI coding agents — file map, commands, working rules, precedence.

CLAUDE.md

CLAUDE.md — Layer 1 — Navigation files




# CLAUDE.md

This file is the Claude-specific orientation layer. It supplements
`AGENTS.md` with Claude-specific notes — slash commands, hook reference,
sub-agent definitions — without replacing the open-standard content there.

If a Claude session sees both files, read `AGENTS.md` first, then this one.
When the two disagree, `AGENTS.md` wins.

## Slash command catalog

The project ships the following slash commands under `.claude/commands/`.
Each is a policy-encoded workflow, not a shortcut.

| Command         | Purpose                                                         |
|-----------------|-----------------------------------------------------------------|
| `/prime`        | Read the governance files and orient before substantive work    |
| `/implement`    | Implement a specified change with required evidence             |
| `/review`       | Review a change against the constitution and directives         |
| `/verify`       | Run the full verification suite and report dual evidence        |
| `/audit`        | Independent compliance audit of the most recent change          |
| `/commit`       | Stage and commit using the project's conventional format        |
| `/pull-request` | Open a PR with the structured description the project requires  |

## Hook reference

The project registers the following hooks in `.claude/settings.json`. Each
hook either blocks an action with a non-zero exit, or passes the action
through unchanged.

| Hook event           | Script                              | Scope                                                     |
|----------------------|-------------------------------------|-----------------------------------------------------------|
| `PreToolUse:Bash`    | `.claude/hooks/pre-tool-use.js`     | Catch Bash calls that explicitly name a protected branch  |

A blocked tool call exits with status 2 and prints a one-line explanation.
The agent does not retry the same call after a hook block — it investigates
the cause.

The `PreToolUse:Bash` hook covers explicit-refspec pushes
(`git push origin main`) and nested shell wrappers
(`bash -c "git push origin main"`). It does **not** cover bare pushes
(`git push`, `git push origin`) or commits on the protected branch,
because the working-tree branch is not visible in the Bash payload. Those
cases are covered by the companion `.githooks/pre-push` git-side hook
shipped alongside this template kit. See `DIRECTIVES.md` CRIT-001 for the
full three-layer enforcement contract.

## Sub-agents

Replace this section with your project's sub-agent definitions. The
default Claude Code installation does not require any.

If you use sub-agents, document each one's:

- **Scope** — what work it owns.
- **Evidence requirement** — what artifacts it must produce.
- **Forbidden actions** — what it cannot do regardless of prompt.

## Context conventions

- The `.claude/` directory is Claude-specific. Agents that are not Claude
  should ignore it.
- The `.claude/agents/`, `.claude/commands/`, and `.claude/hooks/`
  subdirectories are read by Claude Code automatically. Do not move or
  rename them.
- The `.claude/settings.json` file is the single source of truth for which
  hooks and permissions are active. Hooks present in `.claude/hooks/` but
  not registered in `settings.json` do **not** run.

## When in doubt

A Claude session that finds itself uncertain should:

1. Stop and read `CONSTITUTION.md` again.
2. Identify which decision-order principle is in tension.
3. Apply the higher-priority principle.
4. Document the resolution in the commit message or PR description.

Asking the human operator is preferable to guessing in any case where the
constitution does not produce a clear answer.

---

*Adapted from the Agentic Governance Stack templates published at
[etherealogic.ai](https://etherealogic.ai/). This file is intentionally
short — Claude-specific knowledge belongs here, project-wide knowledge
belongs in `AGENTS.md`.*

Claude-specific orientation that supplements AGENTS.md with the slash command catalog and hook reference.

.claude/hooks/pre-tool-use.js

.claude/hooks/pre-tool-use.js — Layer 4 — Runtime enforcement




#!/usr/bin/env node
/**
 * PreToolUse:Bash guard
 *
 * Scope: catches Bash tool calls that *explicitly name* a protected branch
 * in the push refspec, including nested shell wrappers. Specifically:
 *
 *   blocks (exit 2):
 *     - git push origin main
 *     - git push origin HEAD:main
 *     - git push --force origin master
 *     - bash -c "git push origin main" (and sh / zsh variants)
 *     - git push origin main && echo done (and other compound forms)
 *     - git reset --hard origin/main
 *
 *   does NOT block on its own (out of scope for a Bash-payload hook):
 *     - git push     (no remote / refspec — current branch is unknown
 *                     from inside this hook)
 *     - git push origin    (no refspec)
 *     - git commit -m "..."   (the hook cannot tell which branch HEAD is on)
 *
 * The unhandled cases are covered by the companion git-side pre-push hook
 * shipped in `.githooks/pre-push` of this template kit. The two layers
 * compose: the Claude hook closes the explicit-refspec class (which can
 * arrive via any agent-driven Bash invocation), and the git pre-push
 * hook closes the bare-push class (which depends on the working-tree
 * state). Install both for end-to-end coverage of `DIRECTIVES.md`
 * CRIT-001.
 *
 * Exits 2 when blocked, 0 when allowed. Reads the tool payload as JSON
 * from stdin. The Claude Code runtime provides the payload in this shape:
 *
 *   {
 *     "tool_name": "Bash",
 *     "tool_input": { "command": "<the shell string>", ... }
 *   }
 *
 * Register this hook in `.claude/settings.json` under
 * `hooks.PreToolUse.Bash`. See the companion `settings.json` template for
 * the exact shape.
 *
 * Adapted from the Agentic Governance Stack templates published at
 * https://etherealogic.ai/agentic-governance-stack-templates/
 */

'use strict';

const PROTECTED_BRANCHES = ['main', 'master'];

function readStdin() {
  return new Promise((resolve, reject) => {
    let data = '';
    process.stdin.setEncoding('utf8');
    process.stdin.on('data', (chunk) => { data += chunk; });
    process.stdin.on('end', () => resolve(data));
    process.stdin.on('error', reject);
  });
}

function block(reason) {
  process.stderr.write(`[pre-tool-use] BLOCKED: ${reason}\n`);
  process.exit(2);
}

function allow() {
  process.exit(0);
}

/**
 * Recursively unwrap nested shell invocations of the form
 *   bash -c "<inner>"
 *   sh -lc '<inner>'
 *   zsh -c $'<inner>'
 * so we evaluate the actual command being run, not the wrapper.
 */
function unwrapShellWrappers(command) {
  let current = command;
  for (let i = 0; i < 8; i++) {
    const m = current.match(
      /^\s*(?:bash|sh|zsh|dash|ash)\s+(?:-[a-z]*c|--command)\s+(['"$])([\s\S]+)\1\s*$/,
    );
    if (!m) return current;
    current = m[2];
  }
  return current;
}

function splitCompound(command) {
  // Split on shell separators that introduce another command in the same
  // invocation: ;, &&, ||, |, & (background). Quotes inside the command
  // are not perfectly respected here — we err on the side of evaluating
  // every fragment.
  return command
    .split(/(?:;|&&|\|\||(?<!\|)\|(?!\|)|(?<!&)&(?!&))/)
    .map((fragment) => fragment.trim())
    .filter(Boolean);
}

function isProtectedRef(ref) {
  if (!ref) return false;
  const bare = ref.replace(/^origin\//, '').replace(/^refs\/heads\//, '');
  return PROTECTED_BRANCHES.includes(bare);
}

function checkGitFragment(fragment) {
  // Match `git commit ... -m ...` or `git push origin main` patterns.
  const tokens = fragment.match(/("[^"]*"|'[^']*'|\S+)/g) || [];
  if (tokens[0] !== 'git') return null;

  const sub = tokens[1];

  if (sub === 'push') {
    // Look for an explicit refspec on the push line.
    const refTokens = tokens.slice(2).filter((t) => !t.startsWith('-'));
    // refTokens may be [], [remote], [remote, ref], or [remote, src:dst]
    if (refTokens.length === 0) {
      // `git push` with no args targets the current branch. We do not know
      // the current branch from this hook surface, so we fall back to a
      // conservative warning rather than a hard block.
      return null;
    }
    const refSpec = refTokens[1];
    if (!refSpec) return null;
    const dst = refSpec.includes(':') ? refSpec.split(':').pop() : refSpec;
    if (isProtectedRef(dst)) {
      return `git push to protected branch "${dst}" — open a pull request instead.`;
    }
    return null;
  }

  if (sub === 'commit') {
    // Detect commit-on-protected-branch by reading HEAD if available.
    // We cannot reliably know the current branch from inside this hook,
    // so the strict guard is on the push step. A separate pre-commit
    // hook in the repository should reject commits authored on main.
    return null;
  }

  if (sub === 'reset' || sub === 'rebase') {
    if (fragment.includes('--hard') && /\borigin\/(main|master)\b/.test(fragment)) {
      return `destructive ${sub} against protected branch — investigate before forcing.`;
    }
    return null;
  }

  if (sub === 'checkout' && /\b(--|-)\s*$/.test(fragment)) {
    // `git checkout --` discards uncommitted changes. Warn aggressively.
    return 'git checkout -- discards local changes; confirm intent.';
  }

  return null;
}

async function main() {
  const raw = await readStdin();
  if (!raw) allow();

  let payload;
  try {
    payload = JSON.parse(raw);
  } catch (err) {
    // If we cannot parse the payload, fail open with a warning so the
    // agent is not blocked by a runtime contract change.
    process.stderr.write(`[pre-tool-use] could not parse payload: ${err.message}\n`);
    allow();
  }

  if (payload.tool_name !== 'Bash') allow();

  const command = (payload.tool_input && payload.tool_input.command) || '';
  if (!command) allow();

  const inner = unwrapShellWrappers(command);
  const fragments = splitCompound(inner);

  for (const fragment of fragments) {
    const reason = checkGitFragment(fragment);
    if (reason) block(reason);
  }

  allow();
}

main().catch((err) => {
  process.stderr.write(`[pre-tool-use] hook error: ${err.message}\n`);
  // Fail open on hook crash so a misconfigured hook does not lock the
  // agent out of every Bash call.
  process.exit(0);
});

PreToolUse:Bash hook that blocks direct commits and pushes to the protected branch, including nested shell bypasses. Exits with status 2 to halt the tool call before it lands.

.claude/settings.json

.claude/settings.json — Layer 4 — Runtime enforcement




{
  "$schema": "https://www.claude.com/schemas/claude-code-settings.json",
  "permissions": {
    "allow": [
      "Bash(make:*)",
      "Bash(npm:*)",
      "Bash(pnpm:*)",
      "Bash(git status*)",
      "Bash(git diff*)",
      "Bash(git log*)",
      "Bash(git branch*)"
    ],
    "deny": [
      "Bash(git push origin main*)",
      "Bash(git push origin master*)",
      "Bash(git push --force*)"
    ]
  },
  "hooks": {
    "PreToolUse": {
      "Bash": [
        {
          "command": "node",
          "args": [".claude/hooks/pre-tool-use.js"]
        }
      ]
    }
  }
}

Registers the pre-tool-use hook against PreToolUse:Bash and declares the project's Bash permission allow/deny rules. The hook is inert without this registration.

.githooks/pre-push

.githooks/pre-push — Layer 4 — Runtime enforcement (git companion)




#!/usr/bin/env bash
# Git pre-push hook — protected-branch guard.
#
# Rejects any push that lands on a protected branch on the remote,
# including bare pushes (`git push`, `git push origin`) where the
# Claude Code Bash hook cannot determine the destination branch.
#
# The git hook system passes the local and remote refs being pushed on
# stdin, one push per line:
#
#   <local ref> <local sha> <remote ref> <remote sha>
#
# Exit non-zero to abort the push.
#
# Adapted from the Agentic Governance Stack templates published at
# https://etherealogic.ai/agentic-governance-stack-templates/
#
# Install:
#   chmod +x .githooks/pre-push
#   git config --local core.hooksPath .githooks
#
# Verify:
#   git push origin HEAD:main      # should be rejected
#   git push origin HEAD:feature   # should be allowed

set -euo pipefail

PROTECTED_REGEX='^refs/heads/(main|master)$'

while read -r local_ref local_sha remote_ref remote_sha; do
  # Skip deletions — `git push --delete` arrives with a zero local sha.
  # Deleting a protected branch is also a destructive op; block it too.
  if [[ "$remote_ref" =~ $PROTECTED_REGEX ]]; then
    branch="${remote_ref#refs/heads/}"
    if [[ "$local_sha" =~ ^0+$ ]]; then
      echo "[pre-push] BLOCKED: refusing to delete protected branch '$branch'." >&2
    else
      echo "[pre-push] BLOCKED: push to protected branch '$branch' refused." >&2
      echo "[pre-push] Open a pull request instead." >&2
    fi
    exit 1
  fi
done

exit 0

Git pre-push hook that closes the bare-push gap the Claude PreToolUse hook cannot see. Wire with `git config –local core.hooksPath .githooks`.

.github/workflows/governance.yml

.github/workflows/governance.yml — Layer 5 — External validation




# Governance CI workflow
#
# Runs three independent jobs on every push and pull request:
#   1. lint-and-test  — quality (lint + unit tests)
#   2. security       — static analysis
#   3. dependencies   — vulnerability scan against the lockfile
#
# Every third-party action is pinned to a specific commit SHA, not a
# version tag, to defend against the mutable-tag supply-chain attack
# class. Replace each SHA below with the current pinned SHA from the
# action's release page when adopting this template.
#
# Adapted from the Agentic Governance Stack templates published at
# https://etherealogic.ai/agentic-governance-stack-templates/

name: governance

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

permissions:
  contents: read

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  lint-and-test:
    name: Lint and test
    runs-on: ubuntu-latest
    timeout-minutes: 15
    steps:
      # actions/checkout@v4 — replace with the pinned SHA for v4
      - name: Checkout repository
        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11

      # actions/setup-node@v4 — replace with the pinned SHA for v4
      - name: Setup Node
        uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a
        with:
          node-version: '20'
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Lint
        run: npm run lint

      - name: Unit tests
        run: npm test -- --reporter=verbose

      # codecov/codecov-action@v4 — replace with the pinned SHA for v4
      - name: Upload coverage
        if: success()
        uses: codecov/codecov-action@b9fd7d16f6d7d1b5d2bec1a2887e65ceed900238
        with:
          fail_ci_if_error: true
          files: ./coverage/lcov.info

  security:
    name: Static analysis
    runs-on: ubuntu-latest
    timeout-minutes: 10
    steps:
      - name: Checkout repository
        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11

      # github/codeql-action/init@v3 — replace with the pinned SHA for v3
      - name: Initialize CodeQL
        uses: github/codeql-action/init@4675d51de96d1d4dafabf81f93475a83fe7710e7
        with:
          languages: javascript-typescript

      - name: Build
        run: |
          if [ -f package.json ]; then npm ci && npm run build --if-present; fi

      # github/codeql-action/analyze@v3 — replace with the pinned SHA for v3
      - name: Analyze
        uses: github/codeql-action/analyze@4675d51de96d1d4dafabf81f93475a83fe7710e7

  dependencies:
    name: Dependency scan
    runs-on: ubuntu-latest
    timeout-minutes: 10
    steps:
      - name: Checkout repository
        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11

      # snyk/actions/node@v0.4.0 — replace with the pinned SHA you intend to use
      - name: Run Snyk
        uses: snyk/actions/node@b98d498629f1c368650224d6d212bf7dfa89e4bf
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
        with:
          args: --severity-threshold=high

Three-job CI workflow — lint and test, static analysis, dependency scan — with every third-party action pinned to a commit SHA to defend against mutable-tag supply-chain risk.

agentic-governance-stack/README.md

agentic-governance-stack/README.md — Layer 0 — Agent-facing instructions




# Agentic Governance Stack — Templates

A drop-in starter kit for the five-layer governance pattern described in
[*CLAUDE.md Is Not Enough: The Governance Stack for Agentic
Development*](https://etherealogic.ai/claude-md-is-not-enough-the-governance-stack-for-agentic-development/).

These templates are starting points, not policy. Read them, customize them,
and treat the placeholders as prompts for project-specific decisions.

## What is in this directory

| File                                | Layer                         |
|-------------------------------------|-------------------------------|
| `CONSTITUTION.md`                   | 2 — Constitutional governance |
| `DIRECTIVES.md`                     | 2 — Constitutional governance |
| `SECURITY.md`                       | 2 — Constitutional governance |
| `AGENTS.md`                         | 1 — Navigation                |
| `CLAUDE.md`                         | 1 — Navigation (Claude)       |
| `.claude/hooks/pre-tool-use.js`     | 4 — Runtime enforcement       |
| `.claude/settings.json`             | 4 — Runtime enforcement       |
| `.githooks/pre-push`                | 4 — Runtime enforcement (git) |
| `.github/workflows/governance.yml`  | 5 — External validation       |

## Install instructions for an AI coding agent

If you are an AI coding agent reading this README, your operator has asked
you to install this governance stack into the current project. Follow these
steps in order.

1. **Read the article first.** Open
   <https://etherealogic.ai/claude-md-is-not-enough-the-governance-stack-for-agentic-development/>
   and read it end to end before proceeding. The templates only make sense
   in context.

2. **Confirm the project root.** Run `pwd` and verify with the operator
   that you are in the correct directory before writing any files.

3. **Copy the document foundation** to the project root. Create or
   overwrite, in this order:
   - `CONSTITUTION.md`
   - `DIRECTIVES.md`
   - `SECURITY.md`
   - `AGENTS.md`
   - `CLAUDE.md`

   If any of these already exist, do **not** silently overwrite. Surface
   the conflict to the operator and ask which version to keep.

4. **Customize placeholders.** Replace, at minimum:
   - The contact email in `SECURITY.md`.
   - The tech-stack and command tables in `AGENTS.md`.
   - The principle ordering in `CONSTITUTION.md` if it does not match your
     project's actual priorities. Do not leave the ordering unread — the
     order is the statement.

5. **Install the Claude runtime hook.** Create the directory and copy:
   - `.claude/hooks/pre-tool-use.js`
   - `.claude/settings.json` (merge with any existing `settings.json` —
     do not overwrite a populated file)

6. **Install the git pre-push hook.** This is the companion guard that
   covers the bare-push case the Claude hook cannot see. Copy
   `.githooks/pre-push` into the project's `.githooks/` directory, mark
   it executable, and point the local git config at it:

   ```sh
   chmod +x .githooks/pre-push
   git config --local core.hooksPath .githooks
   ```

7. **Install the CI workflow.** Copy
   `.github/workflows/governance.yml` into the project's
   `.github/workflows/` directory. Replace each pinned SHA with the
   current pinned SHA for the matching action version. Run the workflow
   on a draft PR before merging it to confirm it passes.

8. **Verify the Claude hook is wired.** From the project root:

   ```sh
   cat .claude/settings.json | jq '.hooks.PreToolUse.Bash'
   ```

   The output must list `pre-tool-use.js`. If it does not, the hook is
   not active and CRIT-001's first layer is unenforced.

9. **Test the Claude hook.** Attempt a dry run that should be blocked:

   ```sh
   echo '{"tool_name":"Bash","tool_input":{"command":"git push origin main"}}' \
     | node .claude/hooks/pre-tool-use.js
   echo "exit=$?"
   ```

   Expected output:

   ```text
   [pre-tool-use] BLOCKED: git push to protected branch "main" — ...
   exit=2
   ```

   If you see anything else, the hook is misconfigured. Stop and surface
   the failure to the operator.

10. **Test the git pre-push hook.** Simulate a push payload to confirm
    the hook rejects pushes to a protected branch. The git hook system
    receives the local and remote refs on stdin:

    ```sh
    printf 'refs/heads/feature abc123 refs/heads/main 000\n' \
      | bash .githooks/pre-push
    echo "exit=$?"
    ```

    Expected output:

    ```text
    [pre-push] BLOCKED: push to protected branch 'main' refused.
    [pre-push] Open a pull request instead.
    exit=1
    ```

11. **Commit the templates** as a single, focused commit:

    ```text
    chore: install agentic governance stack templates

    Adds CONSTITUTION, DIRECTIVES, SECURITY, AGENTS, CLAUDE, the
    Claude PreToolUse:Bash hook, the git pre-push companion, and the
    governance CI workflow.

    Source: https://etherealogic.ai/agentic-governance-stack-templates/
    ```

    Open a pull request rather than pushing directly to `main`. The
    layered hooks will block a direct push regardless.

12. **Report dual evidence to the operator** once the PR opens:
    - The PR URL (machine-verifiable artifact).
    - A one-paragraph summary of what was installed and what was
      customized (human-readable artifact).

## Install instructions for a human

If you are a human reading this:

1. Read the article: <https://etherealogic.ai/claude-md-is-not-enough-the-governance-stack-for-agentic-development/>.
2. Copy the files into your project root with the layout above.
3. Customize the placeholders. The decision order in `CONSTITUTION.md`
   matters more than the specific principles.
4. Wire the git pre-push hook with
   `git config --local core.hooksPath .githooks` and confirm it is
   executable.
5. Pin the GitHub Actions in `governance.yml` to current SHAs from each
   action's releases page.
6. Configure server-side branch protection on the remote (e.g., GitHub
   branch protection rules requiring a pull request to `main`). The
   hooks are best-effort local guards; branch protection is the
   authoritative gate.
7. Open a draft PR with the templates and run CI before merging.

## Customizing the templates

The templates are intentionally generic. Common customizations:

- **Tighten or loosen severity in `DIRECTIVES.md`.** Some teams promote
  `CRIT-006` (no `--no-verify`) to a hard branch-protection rule. Others
  treat it as advisory.
- **Add domain-specific sub-agents in `CLAUDE.md`.** Teams shipping data
  pipelines often add a data-quality reviewer. Teams shipping web apps
  often add a UX reviewer.
- **Extend the protected-branch hook in `pre-tool-use.js`.** The default
  guards `main` and `master`. Add your release branches if you have them.
- **Replace the CI scanner trio in `governance.yml`.** The template uses
  Codecov, CodeQL, and Snyk as illustrative choices. Substitute the
  scanners your organization already runs.

## License

These templates are released for unrestricted use. Attribution to
EthereaLogic is appreciated but not required.

Step-by-step install instructions written for a coding agent. Drop this into a vendor folder and point your agent at it to install the stack autonomously.

What to do once the templates are in place

The document foundation is necessary but not sufficient on its own. Once the files are in your repository, the next two steps move the stack from orientation to governance:

  1. Verify the hook is registered. The pre-tool-use.js hook is inert unless registered in .claude/settings.json under hooks.PreToolUse.Bash. Both files are above; install both.
  2. Pin every GitHub Action to a SHA. The CI workflow above ships with placeholder SHAs. Replace each one with the current pinned SHA from the corresponding action’s release page before merging.
  3. Open a draft PR. The hook will block any direct push to main; that’s the point. Open a draft PR with the templates installed and let CI confirm the workflow runs cleanly.

Found a bug, a missing case, or a refinement worth contributing back? The article includes a follow-up series; updates land at https://etherealogic.ai/agentic-governance-stack-templates/.