phasegate
v0.112.0
Published
Phasegate — AI-agnostic quality defense toolkit. Enforces structural integrity between design intent and code.
Maintainers
Readme
Phasegate
Phasegate -- AI-agnostic quality defense toolkit.
Enforces structural integrity between design intent and code, regardless of which AI agent you use.
Why Phasegate?
AI coding agents are fast but unconstrained. They skip design steps, violate layer boundaries, and produce code that drifts from intent. Phasegate solves this with a portable, agent-independent defense layer that makes it physically impossible to implement without design, commit without validation, or merge without traceability.
Works with Claude Code, Codex, Cursor, Copilot, or any other AI agent.
Features
| Feature | Description |
|---|---|
| 5-Layer Defense Model | L0 through L4 validators from editor time to scheduled audits |
| 28 AIDLC Skills | Full coverage from product architecture to story implementation |
| Phase Dependency Model | Blocks implementation when required design documents are missing |
| Quick Mode | Lightweight gate for bugfixes, docs, tests, and config changes |
| Claude Code Hooks | Native PreToolUse / PostToolUse / Stop hook integration |
| Codex CLI Hooks | PreToolUse(Bash) / PostToolUse(Bash) / Stop hook integration (native apply_patch falls back to pre-commit) |
| HarnessError Format | Every error includes ADR references and fix examples for AI self-correction |
| Configurable Phase Gates | Define custom gates with gates[] in config. Default uses AIDLC phase dependencies |
| Protected File Control | Configure which files are protected from AI writes via protectedFiles.exclude |
| Bash Write Detection | Detects and blocks shell-based file writes (sed -i, tee, cp, mv, redirects) |
| Presets | minimal, standard, and strict -- choose your quality level |
Quick Start
1. Install
npm install --save-dev phasegate2. Initialize
npx phasegate init --name my-projectThis deploys 28 skills to skills/, creates agent-specific links such as .claude/skills or .codex/skills, installs design principles docs (docs/principles/*.md, docs/folder_management_rules.md), and generates phasegate.config.json.
init does NOT generate: docs/inception/ work item directories or docs/product/ design documents. Those are produced later by AIDLC skills (/product-architect, /domain-designer, etc.) — that is the whole point of "no design, no code."
Optional: add --with-husky to also install a .husky/pre-commit hook that runs L2 validators.
3. Start the AIDLC
Launch your AI agent and run the /product-architect skill to begin.
5-Layer Defense Model
+------------------------------------------------------------------+
| L0 AGENT RUNTIME HOOKS Claude Code / Codex hooks |
| PreToolUse (Write/Edit/Bash block + guide), PostToolUse |
| (auto lint/format), Stop (ReentryGuard + complete-check), |
| SessionStart, UserPromptSubmit. Plus Husky .husky/pre-commit |
| and .husky/commit-msg (Work-Item trailer enforcement). |
+------------------------------------------------------------------+
| L1 EDITOR TIME Biome AST rules |
| require-unit-comment, no-layer-violation, no-any-abuse, |
| enforce-folder-structure, no-ghost-file, no-code-duplication |
+------------------------------------------------------------------+
| L2 PRE-COMMIT Validators |
| phase-gate, metadata completeness, story-reflection, |
| test-quality (AAA pattern) |
+------------------------------------------------------------------+
| L3 CI/CD Validators |
| security, performance, coverage threshold, nyquist traceability |
+------------------------------------------------------------------+
| L4 SCHEDULED Validators (default off) |
| drift-detection, consistency-check, dead-code analysis, |
| doc-freshness, pointer-validation |
+------------------------------------------------------------------+| Layer | Trigger | Key Checks |
|---|---|---|
| L0 | AI agent runtime (.claude/settings.json / .codex/hooks.json) + Husky git hooks | PreToolUse blocks Write/Edit/Bash that violate gates; PostToolUse runs lint/format; Stop enforces ReentryGuard + complete-check; .husky/pre-commit runs phasegate pre-commit; .husky/commit-msg enforces Work-Item: WI-XXX trailer |
| L1 | Editor save / phasegate lint | @unit / @layer metadata, layer violations, AI anti-patterns, dead code |
| L2 | Pre-commit (also evaluated inside PreToolUse at L0) | Phase gate, metadata completeness, @work-item-id reflection (L2-STORY-REFLECTION), test quality |
| L3 | CI/CD pipeline | Security, performance, coverage (90%/95%), requirements traceability |
| L4 | Scheduled (weekly). Currently layers.L4.enabled: false by default — opt-in per project | Design-code drift, cross-document consistency, dead code, doc freshness, pointer validation |
The
L0-001/L0-002validators that appear inlist-errors --layer L0output are legacy definitions from an earlier design and are disabled by default (layers.L0.enabled: false). The runtime L0 enforcement happens via the agent-integration hook scripts and Husky git hooks listed above, not via those validators.
28 Skills
Skills cover the full AIDLC (AI-Driven Development Life Cycle), enforcing phase dependencies so that implementation cannot begin without design.
Foundation (4)
| Skill | Purpose |
|---|---|
| /product-architect | Define product vision, domains, architecture, and constraints |
| /story-writer | Create Who/What/Why user stories with acceptance criteria |
| /story-mapper | Prioritize stories and define MVP scope |
| /unit-designer | Group stories into independently buildable Units |
Design (5)
| Skill | Purpose |
|---|---|
| /domain-designer | DDD tactical design -- aggregates, entities, value objects, events |
| /logical-designer | Hexagonal architecture design (ports and adapters) |
| /mock-designer | UI mockup design for early validation |
| /uiux-designer | Final UI/UX definition from test cases and logical design |
| /environment-designer | Local dev environment and infrastructure design |
Test Engineering (7)
| Skill | Purpose |
|---|---|
| /unit-test-designer | Unit test case design from domain models |
| /it-test-designer | Integration test case design from logical design |
| /scenario-test-designer | E2E scenario test case design |
| /unit-test-logic-designer | Vitest implementation logic with pseudocode |
| /it-test-logic-designer | Integration test Vitest implementation logic |
| /scenario-test-logic-designer | Playwright E2E implementation logic |
| /test-coverage-checker | Coverage verification and Nyquist validation |
Implementation (4)
| Skill | Purpose |
|---|---|
| /story-implementor | TDD implementation (Red-Green-Refactor) with atomic commits |
| /quick-implementor | Lightweight implementation for bugfixes, docs, tests, config |
| /implementation-planner | Implementation plan from Unit specs and domain models |
| /implementation-readiness-checker | Pre-implementation readiness verification |
Verification (8)
| Skill | Purpose |
|---|---|
| /consistency-checker | Cross-layer consistency check across design documents |
| /cascade-updater | Propagate lower-phase discoveries to upstream design docs |
| /codex-delegator | Delegate tasks to Codex CLI with quality oversight |
| /codebase-mapper | Generate structure map from @unit/@layer annotations |
| /doc-freshness-checker | Design document staleness detection (L4 extension) |
| /pointer-validator | Validate file path references in design documents |
| /engineering-perspective | Multi-perspective design review (Beck, Fowler, Martin, Evans) |
| /skill-creator | Create or update agent skills |
Document Lifecycle
Phasegate enforces a single-direction data flow: inception → product → src. Each step has a designated location and a corresponding PhaseGate behavior.
Three-tier model
docs/inception/{unit}/{WI-XXX}/ ← transient planning/design (per WI, fluid)
↓ reflection (with @work-item-id, accumulated update)
docs/product/construction/{unit}/ ← canonical design (per Unit, persistent)
↕ phase gate
scripts/harness/{unit}/(domain|application|infrastructure|presentation)/*.tsWork Item (WI) layout
WIs are placed in one of three buckets based on scope:
| Path | Use |
|---|---|
| docs/inception/_shared/ | Cross-cutting plans/strategy/research not tied to a WI |
| docs/inception/_cross/{WI-XXX}/ | Cross-cutting WI affecting multiple Units |
| docs/inception/{unit}/{WI-XXX}/ | WI owned by a single Unit |
Removed in v0.104.0:
docs/inception/issues/,docs/inception/{unit}/issues/,docs/inception/{unit}/{US-XXX}/. Existing assets are migrated vianpx phasegate migrate work-items --apply. Legacy IDs are retained vialegacy_idfor grep compatibility.
WI frontmatter (required)
Each WI's description.md must start with:
---
id: WI-042
type: story | issue | fix | refactor | chore # see below
severity: trivial | normal | high
status: drafted | reflected | implemented | tested # auto-updated by PhaseGate
affects: [unit-a, unit-b] # cross-unit only
legacy_id: ISSUE-XXX | US-XXX | H{NN}-{NN} # optional
---L2 metadata validator verifies the frontmatter shape.
Required artifacts by type
| type | inception artifacts | product reflection | Use |
|---|---|---|---|
| story | description + logical_design + domain_model + test designs | All categories accumulated | New feature |
| issue | description + logical_design + domain_model + relevant test designs | Relevant categories | Bug / spec mismatch |
| refactor | description + logical_design | logical_design update | Refactor |
| fix | description + PR link | @work-item-id annotation in relevant category | Typo / dep update |
| chore | description.md (1 line) + PR link | None | Chore |
fix / chore are lightweight paths — fixes too small for a formal story still get audit trail.
State machine
DRAFTED (inception artifacts present per `type`)
↓ Phase 0/2 reflection
REFLECTED (product carries @work-item-id WI-XXX)
↓ Phase 3 implementation
IMPLEMENTED (src exists / lint+type+test green)
↓ Phase 4 test
TESTED (test files annotated with @work-item-id, all green)type: chore ends at DRAFTED. type: fix shortcuts via DRAFTED → REFLECTED → IMPLEMENTED. PhaseGate auto-updates status.
Full spec: docs/folder_management_rules.md
Metadata Conventions
Each source file declares its @unit / @layer. Tests add @story or @work-item-id for traceability.
// @unit config-foundation
// @layer domain
// @work-item-id WI-042 ← optional (boosts traceability)
// @story US-001 ← test files only (legacy)
export class ConfigSchema { ... }| Tag | Value | Required |
|---|---|---|
| @unit | Unit name from /unit-designer (e.g., config-foundation) | Yes (L1-001) |
| @layer | Layer name from architecture.preset | Yes (L1-002) |
| @work-item-id | WI driving this file change (e.g., WI-042) | Optional |
| @story | US/WI being verified by tests (legacy) | Recommended for tests |
In product docs, declare reflection per section using HTML-comment annotations:
## Port Definitions
<!-- @work-item-id WI-042 -->
### OrderRepository Port
- findById(id: OrderId): Promise<Order>
<!-- @work-item-id WI-042, WI-051 -->
### PaymentGateway Port
- charge(amount: Money): Promise<Receipt>L2-STORY-REFLECTION uses these annotations to verify inception design has been cascaded into product. Legacy @story-id US-XXX / @story-id H##-## / @issue-id ISSUE-XXX are still resolved via WI legacy_id — no bulk replacement needed for existing docs.
Configuration
phasegate.config.json is the Single Source of Truth for quality settings.
Presets
Phasegate has two orthogonal preset families — defense and architecture. See the note at the end of this section for naming conventions.
Defense preset (project.preset) -- overall layer strictness:
| Preset | Layers | Coverage | Use Case |
|---|---|---|---|
| minimal | L1 + L2 | -- | Prototyping, early exploration |
| standard | L1 - L3 | 90% | Production development (default) |
| strict | L1 - L4 | 95% | Mission-critical systems |
Architecture preset (architecture.preset) -- layer names and dependency directions used by L1-003 / L1-004:
| Preset | Layers | Use Case |
|---|---|---|
| clean (default) | domain / application / infrastructure / presentation | Clean Architecture / AIDLC full harness |
| strict-ddd | clean layers + stricter cycle detection | DDD-focused new projects |
| onion | domain / application / interface | Onion Architecture |
| hexagonal | core / ports / adapters | Hexagonal / Ports-and-Adapters |
| layered | presentation / business / data | Classic 3-tier layered |
| flat | No layers | Small scripts / CLI tools / retrofit start |
| custom | User-defined layers + allowedDependencies | Any other shape |
For selection guidance and config examples see Preset Selection Guide.
Naming convention: "defense preset" refers to CI strictness (
strict/standard/minimal). "architecture preset" refers to layer topology (clean/onion/hexagonal/layered/flat/strict-ddd/custom). They are set independently.
phaseDependencies.preset -- phase-gate shape and storyReflection defaults (independent of project.preset):
| Preset | Phase 3 gates | storyReflection default | Use Case |
|---|---|---|---|
| full | All AIDLC gates | Enabled -- logical_design + domain_model required, uiux optional | AIDLC full ceremony (alias for legacy default) |
| standard | Core gates | Enabled -- logical_design required, domain_model optional | Production development with moderate rigor |
| minimal | None | Disabled -- no inception -> product enforcement | Prototyping / exploration |
| custom | User-defined via gates[] array | User-defined via storyReflection.mappings | Full control (requires override: true) |
storyReflection blocks writes to src/{unit}/* when an inception US/issue design exists but has not been cascaded into docs/product/construction/{unit}/. See ADR-013 and the Configuration guide.
Key Configuration Sections
{
"project": { "name": "my-project", "preset": "standard" },
"layers": {
"L0": { "enabled": false },
"L1": { "enabled": true },
"L2": { "enabled": true },
"L3": { "enabled": true },
"L4": { "enabled": false }
},
"quickMode": {
"allowedCategories": ["bugfix", "docs", "test", "config"],
"maintainedLayers": ["L1", "L2"],
"relaxedGates": ["phase-gate", "2-phase-execution"],
"fullModeRequiredWhen": {
"mixedCategories": true,
"newDomainFile": true,
"apiContractChange": true
}
},
"phaseDependencies": {
"preset": "standard",
"storyReflection": { "enabled": true }
},
"protectedFiles": {
"exclude": ["tsconfig.json", "package.json"]
},
"baseline": {
"enabled": true,
"path": ".phasegate/baseline.json"
}
}quickMode.fullModeRequiredWhen declares which conditions force a Quick Mode change to escalate to the full /story-implementor flow. All three triggers default to true so retrofits stay safe; flip individual flags to false only when a project intentionally accepts the risk.
baseline opts in to the Phase A-2 retrofit grandfather: pre-existing files captured in .phasegate/baseline.json are exempted from phase-gate until they are structurally modified. Generate the snapshot with npx phasegate baseline before introducing the harness to an existing repository. Since v0.71.0 the baseline.enabled flag defaults to true, so simply running npx phasegate baseline after init is enough — no manual config edit needed. For a step-by-step retrofit walkthrough see Retrofit Adoption Guide.
Configurable Phase Gates
By default, Phasegate enforces the AIDLC phase dependency model -- implementation files cannot be written without prerequisite design documents. This works out of the box with the standard or full preset.
For projects that don't follow AIDLC, you can define custom gates using the gates[] array in phasegate.config.json:
{
"phaseDependencies": {
"preset": "custom",
"override": true,
"gates": [
{
"name": "schema-first",
"level": 3,
"blocks": ["src/api/**/*.ts"],
"requires": ["docs/api/openapi.yaml"],
"description": "API implementation requires OpenAPI schema"
}
]
}
}| Field | Type | Description |
|---|---|---|
| name | string | Unique gate identifier |
| level | 1 | 2 | 3 | Phase level (higher levels require lower-level gates to pass first) |
| blocks | string[] | Glob patterns for files this gate protects |
| requires | string[] | Files that must exist before writing to blocked paths |
| dependsOn | string[] | Other gate names that must pass first |
| description | string | Human-readable gate description |
Gates form a DAG (Directed Acyclic Graph). Circular dependencies are rejected at config load time.
Claude Code Hooks Integration
Phasegate integrates natively with Claude Code via hooks in .claude/settings.json:
| Hook | Trigger | Behavior |
|---|---|---|
| PreToolUse | Write, Edit, or Bash (write operations detected) | Blocks writes to source files without design docs; enforces quickMode.fullModeRequiredWhen (escalates Quick Mode → Full when triggered); skips files captured in the .phasegate/baseline.json snapshot until they are modified; protects configured files; detects Bash write operations (sed -i, tee, cp, etc.) |
| PostToolUse | Write or Edit | Auto-formats and validates metadata |
| Stop | Session end | Runs full test suite to ensure all tests pass |
All hook errors use the HarnessError format with ADR references and fix examples, enabling AI agents to self-correct without human intervention.
Codex CLI Integration
Phasegate also integrates with OpenAI Codex CLI via hooks in .codex/hooks.json. The CLI itself is agent-agnostic, so the same npx phasegate hook <event> commands power both Claude Code and Codex.
Quick setup
# 1. Initialize the project for Codex (creates project-local files such as .codex/hooks.json and .codex/skills)
npx phasegate init --name my-project --agent codex --with-husky
# 2. Enable the Codex CLI feature flag manually on your machine
codex features enable codex_hooksFor dual-agent projects (Claude + Codex), use --agent both.
init sets up files inside the project. The Codex CLI user-level setting (codex_hooks) remains an explicit manual step.
Coverage and known limitation
Because Codex's native apply_patch tool is routed through an internal ApplyPatchHandler and does not emit hook events (openai/codex#16732), pre-edit hard-block coverage is limited to Bash-based writes. Native apply_patch violations are caught at commit time by the pre-commit layer.
| Path | Pre-edit hard block | Commit-time block |
|---|---|---|
| Shell writes (sed -i, tee, heredoc, cat >) | ✅ PreToolUse(Bash) | ✅ pre-commit |
| Bash-invoked apply_patch <<'PATCH' | ✅ PreToolUse(Bash) (via BashWriteTargetExtractor) | ✅ pre-commit |
| Native apply_patch tool call | ❌ not intercepted by Codex today | ✅ pre-commit |
Recommended mitigation: commit frequently (e.g., after each logical change) so native apply_patch violations surface quickly. See the full guide for details.
CLI Reference
npx phasegate <command> [options]| Command | Description |
|---|---|
| init --name <name> | Initialize project, deploy skills, generate config |
| lint | Run L1 Biome AST checks |
| validate --layer <L1-L4\|all> | Run validators for specified layer |
| ci-check | Full CI check (L2-L4) |
| update-skills | Update skills to latest version |
| phasegate:status | Display overall harness health summary |
| phasegate:check-phase --unit <id> | Check current phase for a Unit |
| check-change-category --paths <csv> | Classify changed files into Quick Mode categories and report whether Full Mode is required (--format json, --fail-on-full-required) |
| baseline | Create .phasegate/baseline.json snapshot for Phase A-2 retrofit grandfather (--dry-run, --force, --paths <glob,glob,...>, --json). baseline.enabled defaults to true since v0.71.0. |
| scaffold-design --unit <id> --phase <logical\|domain\|uiux\|unit-test\|it-test> | Generate minimum viable design doc from templates/*.template.md into docs/product/construction/{unit}/*.md (--force, --json). Materializes the scaffold: ... line emitted by phase-gate errors. |
| list-errors --layer <L0-L4> | List error definitions with fix examples |
| hook <pre-tool-use\|post-tool-use\|stop> | Run a Claude Code hook (reads JSON from stdin) |
| pre-commit | Run L2 pre-commit validators on staged files |
| delegate-sonnet [...args] | Delegate task to Sonnet 4.6 (transparent wrapper) |
| migrate work-items --dry-run / --apply | Migrate legacy ISSUE-XXX / H{NN}-{NN} directories under docs/inception/ to the unified WI-XXX layout (frontmatter type / legacy_id / affects injected). Sequential allocator skips numbers already used by existing WIs. See CLI Reference -- Work Item Migration. |
| migrate --schema v3 | Upgrade phasegate.config.json to v3 schema by adding the architecture key (idempotent). |
See the Japanese README for the complete CLI reference.
Documentation
Detailed guides are available under docs/guide/:
- Installation -- Detailed install and setup instructions
- Configuration --
phasegate.config.jsonfull reference - CLI Reference -- All CLI commands and options
- Skills Overview -- 28 skills with AIDLC execution order
- 5-Layer Defense Model -- L0-L4 layer details and HarnessError format
- Hooks Integration -- Claude Code Hooks setup and behavior
- Codex Integration -- Codex CLI setup, coverage matrix, and native
apply_patchlimitation - Quick Mode vs Full Mode -- When to use
/story-implementorvs/quick-implementor, with decision flow and case studies - Retrofit Adoption Guide -- Onboard an existing project without getting blocked:
init→baseline→scaffold-designin 4 steps
Additional resources:
docs/principles/architecture-philosophy.md-- Architecture philosophydocs/principles/testing-rules.md-- Testing conventionsdocs/ADR/-- Architecture Decision Records
Roadmap (Planned but not yet implemented)
The following are documented behaviors that are partially implemented or rely on user-side wiring. Each is tracked as a Work Item and will land in a future minor release. Inception docs live under docs/inception/_cross/WI-XXX/description.md.
| Work Item | Title | Why it matters |
|---|---|---|
| WI-031 | CI template unification + phasegate init --with-ci | Today the bundled YAML and the ci:generate-template output diverge (different cron schedule, only the bundled one creates GitHub Issues). phasegate init does not deploy the workflow, so L4 only runs after the user manually copies the file. WI-031 unifies the two paths and adds an opt-in deploy flag. |
| WI-032 | AGENTS.md / CLAUDE.md auto-refresh pipeline | ci:migrate-agents-md exists as a one-shot CLI but there is no scheduled job, and CLAUDE.md is fully hand-maintained. WI-032 adds an auto-refresh-agent-context workflow plus a template-driven CLAUDE.md regenerator that preserves user-owned sections. |
| WI-033 | Promote doc-freshness / pointer-validation to L4 validators | Both capabilities exist as p2:check-freshness / p2:validate-pointers CLI commands but are not registered as L4 validators, so validate --layer L4 skips them. WI-033 plumbs them through validator-system so they run via the standard L4 path and presets. |
| WI-034 | Retire legacy L0 validators (L0-001 / L0-002) | The fuse-hook-config / fuse-mount-status validator IDs are leftovers from an earlier FUSE-based design. They are disabled by default and have no actual implementation behind them. WI-034 removes them and lets the agent-integration runtime hooks be the sole L0 surface. |
requirement-test-matrix.json auto-generation for L3 Nyquist Validation is also a known gap; see the L3 section above.
Contributing
Contributions are welcome. See DEVELOPMENT.md for internal architecture, regression tests, and release procedures.
