
Implement Plan Preflight
- 115 installs
- 62 repo stars
- Updated August 3, 2026
- terrylica/cc-skills
Use implement-plan-preflight for development tasks
About
implement-plan-preflight: A skill for development. This provides functionality for development workflows.
- implement-plan-preflight
Implement Plan Preflight by the numbers
- 115 all-time installs (skills.sh)
- Ranked #2,898 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/terrylica/cc-skills --skill implement-plan-preflightAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 115 |
|---|---|
| repo stars | ★ 62 |
| Last updated | August 3, 2026 |
| Repository | terrylica/cc-skills ↗ |
What it does
Use implement-plan-preflight for development tasks
Files
Implement Plan Preflight
Execute the Preflight phase of the /itp:go workflow. Creates ADR and Design Spec artifacts with proper cross-linking and verification.
Self-Evolving Skill: This skill improves through use. If instructions are wrong, parameters drifted, or a workaround was needed — fix this file immediately, don't defer. Only update for real, reproducible issues.
When to Use This Skill
- Invoked by
/itp:gocommand during Preflight phase - User asks to create an ADR for a feature
- User mentions "design spec" or "MADR format"
- Manual preflight verification needed
Preflight Workflow Overview
P.1: Create Feature Branch (if -b flag)
│
▼
P.2: Create ADR File (MADR 4.0)
│
▼
P.3: Create Design Spec (from global plan)
│
▼
P.4: Verify Checkpoint (MANDATORY)CRITICAL: Do NOT proceed to Phase 1 implementation until ALL preflight steps are complete and verified.
---
Quick Reference
ADR ID Format
YYYY-MM-DD-slugExample: 2025-12-01-clickhouse-aws-ohlcv-ingestion
File Locations
| Artifact | Path |
|---|---|
| ADR | /docs/adr/$ADR_ID.md |
| Design Spec | /docs/design/$ADR_ID/spec.md |
| Global Plan | ~/.claude/plans/<adj-verb-noun>.md |
Cross-Links (MANDATORY)
In ADR header:
**Design Spec**: [Implementation Spec](/docs/design/YYYY-MM-DD-slug/spec.md)In spec.md header:
**ADR**: [Feature Name ADR](/docs/adr/YYYY-MM-DD-slug.md)---
Execution Steps
Step P.1: Create Feature Branch (Optional)
Only if -b flag specified. See Workflow Steps for details.
Step P.2: Create ADR File
1. Create /docs/adr/$ADR_ID.md 2. Use template from ADR Template 3. Populate frontmatter from session context 4. Select perspectives from Perspectives Taxonomy 5. Use Skill tool to invoke adr-graph-easy-architect for diagrams
Step P.3: Create Design Spec
1. Create folder: mkdir -p docs/design/$ADR_ID 2. Copy global plan: cp ~/.claude/plans/<adj-verb-noun>.md docs/design/$ADR_ID/spec.md 3. Add ADR backlink to spec header
Step P.4: Verify Checkpoint
Run validator or manual checklist:
uv run scripts/preflight_validator.py $ADR_IDChecklist (ALL must be true):
- [ ] ADR file exists at
/docs/adr/$ADR_ID.md - [ ] ADR has YAML frontmatter with all 7 required fields
- [ ] ADR has
**Design Spec**:link in header - [ ] DIAGRAM CHECK 1: ADR has Before/After diagram (Context section)
- [ ] DIAGRAM CHECK 2: ADR has Architecture diagram (Architecture section)
- [ ] Design spec exists at
/docs/design/$ADR_ID/spec.md - [ ] Design spec has
**ADR**:backlink in header
If any item is missing: Create it now. Do NOT proceed to Phase 1.
---
YAML Frontmatter Quick Reference
---
status: proposed
date: YYYY-MM-DD
decision-maker: [User Name]
consulted: [Agent-1, Agent-2]
research-method: single-agent
clarification-iterations: N
perspectives: [Perspective1, Perspective2]
---See ADR Template for full field descriptions.
---
Diagram Requirements (2 DIAGRAMS REQUIRED)
⛔ MANDATORY: Every ADR must include EXACTLY 2 diagrams:
| Diagram | Location | Purpose |
|---|---|---|
| Before/After | Context section | Shows system state change |
| Architecture | Architecture section | Shows component relationships |
SKILL INVOCATION: Invoke adr-graph-easy-architect skill NOW to create BOTH diagrams.
BLOCKING GATE: Do NOT proceed to design spec until BOTH diagrams are embedded in ADR.
---
Reference Documentation
- ADR Template - Complete MADR 4.0 template
- Perspectives Taxonomy - 11 perspective types
- Workflow Steps - Detailed step-by-step guide
---
Validation Script
# Verify preflight artifacts
uv run scripts/preflight_validator.py <adr-id>
# Example
uv run scripts/preflight_validator.py 2025-12-01-my-feature---
Troubleshooting
| Issue | Cause | Solution |
|---|---|---|
| Validator fails | Missing ADR or spec | Create both files before running validator |
| Frontmatter invalid | Missing required fields | Check all 7 ADR fields and 5 spec fields |
| Diagram not rendering | graph-easy not installed | Run brew install graph-easy |
| Spec phase mismatch | Wrong phase value | Use: preflight, phase-1, phase-2, or phase-3 |
| ADR status wrong | Manual status edit | Let workflow manage status transitions |
| Design folder missing | Wrong path structure | Use docs/design/YYYY-MM-DD-slug/spec.md |
Post-Execution Reflection
After this skill completes, check before closing:
1. Did the command succeed? — If not, fix the instruction or error table that caused the failure. 2. Did parameters or output change? — If the underlying tool's interface drifted, update Usage examples and Parameters table to match. 3. Was a workaround needed? — If you had to improvise (different flags, extra steps), update this SKILL.md so the next invocation doesn't need the same workaround.
Only update if the issue is real and reproducible — not speculative.
Skill: Implement Plan Preflight
ADR Template (MADR 4.0)
Complete template for Architecture Decision Records following MADR 4.0 standards.
YAML Frontmatter (MANDATORY)
Every ADR MUST begin with this frontmatter:
---
status: proposed | accepted | rejected | deprecated | superseded | implemented
date: YYYY-MM-DD
decision-maker: [User Name]
consulted: [Agent-Perspective-1, Agent-Perspective-2]
research-method: 9-agent-parallel-dctl | single-agent | human-only
clarification-iterations: N
perspectives: [PerspectiveType1, PerspectiveType2]
---Field Descriptions
| Field | Required | Description |
|---|---|---|
status | Yes | Current state (use implemented after release) |
date | Yes | Decision date (YYYY-MM-DD) |
decision-maker | Yes | Human who approved the plan (singular, accountable) |
consulted | Yes | Agent perspectives that researched in prior session (string[]) |
research-method | Yes | How prior research was conducted (enum) |
clarification-iterations | Yes | AskUserQuestion rounds before plan written to ~/.claude/plans/*.md |
perspectives | Yes | Decision context types (see Perspectives Taxonomy) |
---
Required Sections
| Section | Required | Content |
|---|---|---|
| Title (H1) | Yes | # ADR: Descriptive Title |
| Context and Problem Statement | Yes | Problem description + Before/After diagram |
| Research Summary | Yes | Agent perspectives and findings from prior session |
| Decision Log | Yes | Synthesized decisions table + trade-offs (from AskUserQuestion iterations) |
| Considered Options | Yes | Minimum 2 alternatives with descriptions |
| Decision Outcome | Yes | What was decided + rationale from AskUserQuestion iterations |
| Synthesis | Yes | How divergent agent findings were reconciled |
| Consequences | Yes | Positive/Negative trade-offs |
| Architecture | Yes | Use Skill tool to invoke adr-graph-easy-architect for diagrams |
| Decision Drivers | Optional | Forces influencing the choice |
| References | Optional | Related ADRs, external docs |
---
Formatting Rules
1. Blank lines: Required between all content blocks (prevents GitHub rendering issues) 2. Links: Use repository-relative format (/docs/adr/...), never ./ or ../ 3. Design spec link: Include in header: **Design Spec**: [Implementation Spec](/docs/design/YYYY-MM-DD-slug/spec.md)
---
Complete Template
---
status: proposed
date: YYYY-MM-DD
decision-maker: [User Name]
consulted: [Agent-Perspective-1, Agent-Perspective-2]
research-method: 9-agent-parallel-dctl
clarification-iterations: N
perspectives: [PerspectiveType1, PerspectiveType2]
---
# ADR: [Descriptive Title]
**Design Spec**: [Implementation Spec](/docs/design/YYYY-MM-DD-slug/spec.md)
## Context and Problem Statement
[What is the problem? Why does it need a decision?]
### Before/After
<!-- Use Skill tool to invoke adr-graph-easy-architect for Before/After visualization -->
## Research Summary
<!-- Extract from prior session: agent perspectives and material findings -->
| Agent Perspective | Key Finding | Confidence |
| ----------------- | ----------- | ------------ |
| [Perspective 1] | [Finding] | High/Med/Low |
| [Perspective 2] | [Finding] | High/Med/Low |
## Decision Log
<!-- Synthesize AskUserQuestion iterations into decision table -->
| Decision Area | Options Evaluated | Chosen | Rationale |
| ------------- | ----------------- | ------ | ----------------- |
| [Topic 1] | A, B, C | A | [Why A over B, C] |
| [Topic 2] | X, Y | Y | [Why Y over X] |
### Trade-offs Accepted
| Trade-off | Choice | Accepted Cost |
| --------- | ------ | -------------------------------- |
| [X vs Y] | X | [What Y offered that we gave up] |
## Decision Drivers
- [Driver 1]
- [Driver 2]
## Considered Options
- **Option A**: [Description]
- **Option B**: [Description]
- **Option C**: [Description] <- Selected
## Decision Outcome
Chosen option: **Option C**, because [rationale from AskUserQuestion iterations + synthesis].
## Synthesis
<!-- Summarize how agent findings were reconciled during prior session -->
**Convergent findings**: [What all perspectives agreed on]
**Divergent findings**: [Where perspectives differed]
**Resolution**: [How user resolved conflicts]
## Consequences
### Positive
- [Benefit 1]
### Negative
- [Trade-off 1]
## Architecture
<!-- Use Skill tool to invoke adr-graph-easy-architect for system architecture diagram -->
## References
- [Related ADR](/docs/adr/YYYY-MM-DD-related.md)
- [Upstream: github.com/org/repo] (if UpstreamIntegration perspective)---
ADR ID Convention
Format: YYYY-MM-DD-slug
Examples:
2025-12-01-clickhouse-aws-ohlcv-ingestion2025-11-28-telegram-bot-network-aware-supervision
File Path: /docs/adr/$ADR_ID.md
---
Slug Word Economy Rule
Each word in the slug MUST convey unique meaning. Avoid redundancy.
| Example | Verdict | Reason |
|---|---|---|
clickhouse-database-migration | Bad | "database" redundant (ClickHouse IS a database) |
clickhouse-aws-ohlcv-ingestion | Good | clickhouse=tech, aws=platform, ohlcv=data-type, ingestion=action |
user-auth-token-refresh | Good | user=scope, auth=domain, token=artifact, refresh=action |
api-endpoint-rate-limiting | Good | api=layer, endpoint=target, rate=metric, limiting=action |
Claude Code Ephemeral Context
This document explains the ephemeral nature of Claude Code's Plan Mode artifacts and why the /itp:go workflow exists to capture decisions before they're lost.
Plan File Location & Naming
Claude Code stores plan files in a global directory with randomly-generated names:
| Component | Behavior | Source |
|---|---|---|
| Directory | ~/.claude/plans/ | GitHub Issue #12707 |
| Filename | Random adjective-noun pattern (e.g., abstract-fluttering-unicorn.md) | Reddit Discussion |
Quote from Issue #12707: "The new plan mode... can ONLY use plan files in ~/.claude/plans... Read ../../../.claude/plans/abstract-fluttering-unicorn.md"
Why Random Names?
When asked why it chose glittery_bouncing_feather.md, Claude responded: "it just used a random name." This is not a bug—it's the default behavior. The names are not derived from your task description.
The Overwrite Problem
Plan files are overwritten when:
- You enter Plan Mode for a new task
- A new planning session begins
- Context is compacted and Claude regenerates the plan
This means any decisions made during planning (via AskUserQuestion flows) are lost unless explicitly captured in version-controlled artifacts.
AskUserQuestion Tool
The AskUserQuestion tool is the mechanism Claude uses to clarify requirements during planning. It's not officially documented but widely discussed:
| Aspect | Details | Source |
|---|---|---|
| Tool Name | AskUserQuestion | GitHub Issue #10346 |
| Added in | Version 2.0.21 | Changelog |
| Documentation | Missing from official docs | Issue #10346 |
| Tutorial | egghead.io | Community |
Why This Matters for ADRs
Decisions made via AskUserQuestion flows include:
- Architectural choices (which library, which pattern)
- Trade-off resolutions (performance vs simplicity)
- Scope clarifications (what's in/out of scope)
These decisions live only in the conversation context. When context compacts at ~95% capacity, they're summarized away. The /itp:go workflow captures these decisions in ADRs before they're lost.
References
- GitHub Issue #12707 - Plan files outside ~/.claude/plans
- GitHub Issue #10685 - Plan agent AskUserQuestion behavior
- GitHub Issue #10346 - Missing AskUserQuestion documentation
- Reddit Discussion - Random naming behavior
- egghead.io Tutorial - AskUserQuestion guide
- Anthropic Best Practices - Official guidance
Evolution Log
Convention: Reverse chronological order (newest on top, oldest at bottom). Prepend new entries.
---
2026-02-26: Initial Evolution Log
Status: Skill is in use and maintained. Track improvements here.
Purpose
This evolution log tracks updates to the skill. Each entry should note:
- What changed (content, structure, tooling)
- Why it changed (bug fix, feature request, best practice)
- Files affected
How to Use
1. When updating SKILL.md or references, add an entry here with the date 2. Keep entries reverse-chronological (newest first) 3. Link to ADRs or GitHub issues when relevant 4. Reference specific line changes when helpful
---
Skill: Implement Plan Preflight
Perspectives Taxonomy (11 Types)
Use perspectives in ADR frontmatter to describe how the ADR relates to the broader ecosystem.
Taxonomy Table
| Perspective | Description | Example Use Case |
|---|---|---|
ProviderToOtherComponents | Creating something for others to consume | Building a shared library or API |
HostPlatformForContributors | Building a framework others contribute to | Plugin system, extension architecture |
StandaloneComponent | Self-contained exploration, no external dependencies | Proof of concept, isolated experiment |
UpstreamIntegration | Consuming external frameworks/infrastructure | Integrating third-party API or SDK |
BoundaryInterface | Public APIs, adapters, contract definitions | REST API design, GraphQL schema |
OperationalService | Runtime, SRE, observability concerns | Monitoring setup, alerting configuration |
SecurityBoundary | Security, compliance, threat modeling | Auth implementation, data encryption |
ProductFeature | User-facing value, UX decisions | New feature for end users |
EcosystemArtifact | SDK, templates, reference implementations | CLI tool, starter template |
LifecycleMigration | Versioning, deprecation, migration strategies | Database migration, API version bump |
OwnershipGovernance | Organizational, process, ownership decisions | Team ownership, code review policy |
---
Usage in Frontmatter
---
perspectives: [UpstreamIntegration, BoundaryInterface]
---Multiple perspectives can apply to a single ADR.
---
Selection Guide
When to Use Each Perspective
ProviderToOtherComponents
- Building shared utilities consumed by multiple projects
- Creating internal libraries or packages
- Designing reusable components
HostPlatformForContributors
- Designing plugin/extension systems
- Building platforms that accept external contributions
- Framework development
StandaloneComponent
- Isolated experiments or proofs of concept
- Self-contained scripts or tools
- No integration with existing systems
UpstreamIntegration
- Consuming third-party APIs (Stripe, AWS, etc.)
- Integrating with external databases
- Using external SDKs or libraries
BoundaryInterface
- Designing public APIs
- Contract-first development
- Adapter patterns between systems
OperationalService
- Monitoring and alerting setup
- Log aggregation configuration
- SRE and DevOps concerns
SecurityBoundary
- Authentication/authorization changes
- Data encryption decisions
- Compliance requirements (GDPR, SOC2)
ProductFeature
- User-facing functionality
- UX/UI decisions
- Feature flags and rollout strategies
EcosystemArtifact
- CLI tools for developers
- Starter templates and boilerplates
- Reference implementations
LifecycleMigration
- Database schema migrations
- API versioning strategies
- Deprecation timelines
OwnershipGovernance
- Team ownership boundaries
- Code review policies
- Process changes
---
Related Repos Reference
When perspective implies external dependencies, reference related repos in ADR body:
## References
- [Upstream: github.com/Eon-Labs/alpha-forge](https://github.com/Eon-Labs/alpha-forge) (UpstreamIntegration)
- [Consumer: github.com/Eon-Labs/trading-bot](https://github.com/Eon-Labs/trading-bot) (ProviderToOtherComponents)Always use public GitHub URLs, never local paths.
Skill: Implement Plan Preflight
Preflight Workflow Steps
Sequential execution steps for the Preflight phase. Execute in order - do not skip steps.
---
Step P.0: Create Feature Branch (MUST BE FIRST)
Only execute if `-b` or `--branch` flag is specified.
CRITICAL: This step MUST happen BEFORE any file operations (ADR, design spec). Files created before git checkout -b stay on main/master branch.
Generate ADR ID
/usr/bin/env bash << 'WORKFLOW_STEPS_SCRIPT_EOF'
ADR_ID="$(date +%Y-%m-%d)-<slug>"
WORKFLOW_STEPS_SCRIPT_EOFDetect Primary Branch
/usr/bin/env bash << 'GIT_EOF'
PRIMARY=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@')
[ -z "$PRIMARY" ] && PRIMARY="main" # fallback
GIT_EOFCreate Branch
git checkout "$PRIMARY"
git pull origin "$PRIMARY"
git checkout -b "<type>/$ADR_ID" # e.g., feat/, fix/, refactor/, docs/, chore/Commit Uncommitted Changes
git add -A
git commit -m "wip: checkpoint before implementing <slug>" || trueBranch Type Selection
| Type | When |
|---|---|
feat | New capability or feature |
fix | Bug fix |
refactor | Code restructuring, no behavior change |
docs | Documentation only |
chore | Maintenance, tooling, dependencies |
perf | Performance improvement |
---
Step P.1: Create ADR File
Path: /docs/adr/$ADR_ID.md
Actions
1. Create directory if needed: mkdir -p docs/adr 2. Create ADR file using template from ADR Template 3. Populate frontmatter from session context 4. Add Design Spec link in header
Frontmatter Population
Extract from session context:
decision-maker: User who approved the planconsulted: Agent perspectives used in researchresearch-method: How research was conductedclarification-iterations: Number of AskUserQuestion roundsperspectives: Select from Perspectives Taxonomy
Diagram Requirements (2 DIAGRAMS REQUIRED)
⛔ MANDATORY: Every ADR must include EXACTLY 2 diagrams. Do NOT proceed without both.
| Diagram | Location | Purpose |
|---|---|---|
| Before/After | Context section | Shows system state change (what exists now vs. after implementation) |
| Architecture | Architecture section | Shows component relationships and data flow |
SKILL INVOCATION (REQUIRED):
1. Invoke Skill tool with `adr-graph-easy-architect` NOW 2. Create Before/After diagram first — embed in ## Context section 3. Create Architecture diagram second — embed in ## Architecture section 4. VERIFY: Search ADR for <!-- graph-easy source: — you must have TWO separate blocks
BLOCKING GATE: Do NOT proceed to Step P.2 until BOTH diagrams are embedded in ADR.
---
Step P.2: Create Design Spec
Create Design Folder
mkdir -p docs/design/$ADR_IDCRITICAL: Global Plan is Ephemeral
The file at ~/.claude/plans/<adj-verb-noun>.md:
- Replaced when a new plan is created (same session or new)
- Use full path when referencing:
~/.claude/plans/floating-plotting-valiant.md - After Preflight: spec.md becomes source-of-truth, not the global plan
The source field in spec frontmatter preserves the original filename for traceability, but the file itself may no longer exist.
Create Spec with YAML Frontmatter
1. Copy global plan content:
cp ~/.claude/plans/<adjective-verb-noun>.md docs/design/$ADR_ID/spec.md2. Prepend YAML frontmatter to the copied spec.md:
---
adr: YYYY-MM-DD-slug
source: ~/.claude/plans/<adjective-verb-noun>.md
implementation-status: in_progress
phase: preflight
last-updated: YYYY-MM-DD
---3. Add ADR backlink after frontmatter:
**ADR**: [Feature Name ADR](/docs/adr/YYYY-MM-DD-slug.md)Frontmatter Field Descriptions
| Field | Required | Description |
|---|---|---|
adr | Yes | ADR ID for programmatic linking |
source | Yes | Full path to global plan (ephemeral, for traceability) |
implementation-status | Yes | in_progress, blocked, completed, or abandoned |
phase | Yes | Current workflow phase |
last-updated | Yes | Date of last spec modification |
Link Format Rule
Use the form [descriptive text](/repo-root-relative/path), never ./ or ../ paths.
---
Step P.3: Verify Checkpoint (MANDATORY)
STOP. Verify artifacts exist before proceeding.
Verification Commands
# Verify ADR exists
[ -f "docs/adr/$ADR_ID.md" ] || { echo "ADR not created: docs/adr/$ADR_ID.md"; exit 1; }
# Verify design spec exists
[ -f "docs/design/$ADR_ID/spec.md" ] || { echo "Design spec not created: docs/design/$ADR_ID/spec.md"; exit 1; }
echo "Preflight complete: ADR and design spec created"Checklist (ALL must be true)
- [ ] ADR file exists at
/docs/adr/$ADR_ID.md - [ ] ADR has YAML frontmatter with all 7 required fields
- [ ] ADR has
status: proposed(initial state) - [ ] ADR has
**Design Spec**:link in header - [ ] DIAGRAM CHECK 1: ADR has Before/After diagram in Context section (graph-easy block)
- [ ] DIAGRAM CHECK 2: ADR has Architecture diagram in Architecture section (graph-easy block)
⛔ DIAGRAM VERIFICATION: If either diagram is missing, STOP and invoke adr-graph-easy-architect skill. Search for <!-- graph-easy source: — you need TWO separate blocks.
- [ ] Design spec exists at
/docs/design/$ADR_ID/spec.md - [ ] Design spec has YAML frontmatter with all 5 required fields
- [ ] Design spec has
implementation-status: in_progress - [ ] Design spec has
phase: preflight - [ ] Design spec has
**ADR**:backlink in header - [ ] Feature branch created with ADR ID naming (if
-bflag specified)
If any item is missing: Create it now. Do NOT proceed to Phase 1.
---
Folder Structure Reference
/docs/
adr/
YYYY-MM-DD-slug.md # ADR file
design/
YYYY-MM-DD-slug/ # Design folder (1:1 with ADR)
spec.md # Active implementation spec (SSoT)Naming Rule: Use exact same YYYY-MM-DD-slug for both ADR and Design folder.
---
Common Errors
| Error | Cause | Solution |
|---|---|---|
| ADR frontmatter missing fields | Incomplete template | Check all 7 required fields |
| Design spec missing backlink | Forgot to add header | Add **ADR**: [...] link |
| Diagrams not present | Skipped diagram step | Use Skill tool to invoke adr-graph-easy-architect |
| Wrong slug format | Contains redundant words | Apply word economy rule |
| Relative paths in links | Used ./ or ../ | Use /docs/adr/... format |
# /// script
# requires-python = ">=3.11"
# dependencies = []
# ///
"""
Preflight Validator - Verify ADR and Design Spec artifacts exist.
ADR: implement-plan-preflight skill
Usage:
uv run preflight_validator.py <adr-id>
Example:
uv run preflight_validator.py 2025-12-01-clickhouse-aws-ohlcv-ingestion
"""
import os
import re
import sys
from pathlib import Path
# ADR: 2025-12-08-mise-env-centralized-config
# Configuration via environment variables with defaults for backward compatibility
ADR_DIR = os.environ.get("ADR_DIR", "docs/adr")
DESIGN_DIR = os.environ.get("DESIGN_DIR", "docs/design")
DESIGN_SPEC_FILENAME = os.environ.get("DESIGN_SPEC_FILENAME", "spec.md")
# Emoji regex pattern for validation in graph labels
# Covers common emoji ranges: emoticons, symbols, dingbats, pictographs
EMOJI_PATTERN = re.compile(
r"[\U0001F300-\U0001F9FF" # Misc Symbols, Emoticons
r"\U00002600-\U000026FF" # Misc symbols (sun, cloud, etc.)
r"\U00002700-\U000027BF" # Dingbats
r"\U0001FA00-\U0001FAFF]" # Extended symbols
)
def validate_adr_frontmatter(adr_path: Path) -> list[str]:
"""Validate ADR has required YAML frontmatter fields."""
errors = []
required_fields = [
"status",
"date",
"decision-maker",
"consulted",
"research-method",
"clarification-iterations",
"perspectives",
]
content = adr_path.read_text()
# Check for frontmatter
if not content.startswith("---"):
errors.append("ADR missing YAML frontmatter (must start with ---)")
return errors
# Extract frontmatter
parts = content.split("---", 2)
if len(parts) < 3:
errors.append("ADR frontmatter not properly closed (missing closing ---)")
return errors
frontmatter = parts[1]
for field in required_fields:
if f"{field}:" not in frontmatter:
errors.append(f"ADR missing required frontmatter field: {field}")
return errors
def validate_adr_sections(adr_path: Path) -> list[str]:
"""Validate ADR has required sections."""
errors = []
required_sections = [
"Context and Problem Statement",
"Research Summary",
"Decision Log",
"Considered Options",
"Decision Outcome",
"Synthesis",
"Consequences",
"Architecture",
]
content = adr_path.read_text()
for section in required_sections:
if f"## {section}" not in content:
errors.append(f"ADR missing required section: ## {section}")
# Check for Design Spec link
if "**Design Spec**:" not in content:
errors.append("ADR missing Design Spec link in header")
return errors
def validate_graph_labels(file_path: Path) -> list[str]:
"""Validate all graph-easy diagrams have emoji + title in label.
Extracts graph-easy source from <details> blocks and validates each
has a `graph { label: "emoji Title"; }` pattern.
"""
errors = []
content = file_path.read_text()
# Pattern to extract graph-easy source from <details> blocks
# Matches: <details>...<summary>graph-easy source</summary>...```...graph content...```...</details>
details_pattern = re.compile(
r"<details>\s*<summary>graph-easy source</summary>\s*```\s*(.*?)```\s*</details>",
re.DOTALL | re.IGNORECASE,
)
# Find all graph-easy source blocks
matches = details_pattern.findall(content)
if not matches:
# No diagrams found - not an error (some files may not have diagrams)
return errors
for i, graph_source in enumerate(matches, 1):
# Check for graph { label: pattern
label_match = re.search(r'graph\s*\{[^}]*label:\s*"([^"]*)"', graph_source)
if not label_match:
errors.append(
f"Diagram #{i}: Missing `graph {{ label: \"emoji Title\"; }}` - "
"every diagram MUST have emoji + title"
)
continue
label_text = label_match.group(1)
# Check for emoji in label
if not EMOJI_PATTERN.search(label_text):
errors.append(
f'Diagram #{i}: Label "{label_text}" missing semantic emoji - '
"add emoji matching diagram purpose (see Emoji Selection Guide)"
)
return errors
def validate_spec_backlink(spec_path: Path, adr_id: str) -> list[str]:
"""Validate design spec has ADR backlink."""
errors = []
content = spec_path.read_text()
if "**ADR**:" not in content:
errors.append("Design spec missing ADR backlink in header")
if adr_id not in content:
errors.append(f"Design spec ADR link doesn't reference {adr_id}")
return errors
def validate_spec_frontmatter(spec_path: Path) -> list[str]:
"""Validate design spec has required YAML frontmatter fields."""
errors = []
required_fields = [
"adr",
"source",
"implementation-status",
"phase",
"last-updated",
]
content = spec_path.read_text()
# Check for frontmatter
if not content.startswith("---"):
errors.append("Spec missing YAML frontmatter (must start with ---)")
return errors
# Extract frontmatter
parts = content.split("---", 2)
if len(parts) < 3:
errors.append("Spec frontmatter not properly closed (missing closing ---)")
return errors
frontmatter = parts[1]
for field in required_fields:
if f"{field}:" not in frontmatter:
errors.append(f"Spec missing required frontmatter field: {field}")
# Validate implementation-status value
valid_statuses = ["in_progress", "blocked", "completed", "abandoned"]
if "implementation-status:" in frontmatter:
status_match = re.search(r"implementation-status:\s*(\S+)", frontmatter)
if status_match:
status = status_match.group(1)
if status not in valid_statuses:
errors.append(
f"Spec has invalid implementation-status: {status} "
f"(expected: {', '.join(valid_statuses)})"
)
# Validate phase value
valid_phases = ["preflight", "phase-1", "phase-2", "phase-3"]
if "phase:" in frontmatter:
phase_match = re.search(r"phase:\s*(\S+)", frontmatter)
if phase_match:
phase = phase_match.group(1)
if phase not in valid_phases:
errors.append(
f"Spec has invalid phase: {phase} "
f"(expected: {', '.join(valid_phases)})"
)
return errors
def main():
if len(sys.argv) != 2:
print("Usage: uv run preflight_validator.py <adr-id>")
print("Example: uv run preflight_validator.py 2025-12-01-my-feature")
sys.exit(1)
adr_id = sys.argv[1]
# Validate ADR ID format
if not re.match(r"^\d{4}-\d{2}-\d{2}-[\w-]+$", adr_id):
print(f"Invalid ADR ID format: {adr_id}")
print("Expected format: YYYY-MM-DD-slug")
sys.exit(1)
adr_path = Path(f"{ADR_DIR}/{adr_id}.md")
spec_path = Path(f"{DESIGN_DIR}/{adr_id}/{DESIGN_SPEC_FILENAME}")
all_errors = []
# Check file existence
print(f"Validating preflight artifacts for: {adr_id}")
print("-" * 50)
if not adr_path.exists():
all_errors.append(f"ADR file not found: {adr_path}")
else:
print(f"[OK] ADR file exists: {adr_path}")
all_errors.extend(validate_adr_frontmatter(adr_path))
all_errors.extend(validate_adr_sections(adr_path))
all_errors.extend(validate_graph_labels(adr_path))
if not spec_path.exists():
all_errors.append(f"Design spec not found: {spec_path}")
else:
print(f"[OK] Design spec exists: {spec_path}")
all_errors.extend(validate_spec_frontmatter(spec_path))
all_errors.extend(validate_spec_backlink(spec_path, adr_id))
all_errors.extend(validate_graph_labels(spec_path))
# Report results
print("-" * 50)
if all_errors:
print(f"\n[FAIL] Preflight validation failed with {len(all_errors)} error(s):\n")
for error in all_errors:
print(f" - {error}")
sys.exit(1)
else:
print("\n[PASS] Preflight validation successful!")
print("All artifacts exist and are properly formatted.")
sys.exit(0)
if __name__ == "__main__":
main()