From bc50716f4ecfccd2023a3a33c410a0959265b3e7 Mon Sep 17 00:00:00 2001 From: Miguelangel Cabrera Date: Sat, 19 Sep 2026 02:20:07 -0300 Subject: [PATCH 1/3] chore: add OpenSpec agent tooling to the repo Add the OpenSpec CLI integration set (.claude, .github, .hermes) so the agent-driven spec workflows (new/propose/apply/verify/archive/sync) run inside this repo. No source or behavior change. --- .claude/agents/engineering-ai-engineer.md | 146 +++++ .../agents/engineering-backend-architect.md | 236 ++++++++ .claude/agents/engineering-data-engineer.md | 306 ++++++++++ .claude/agents/engineering-prompt-engineer.md | 202 +++++++ .claude/commands/opsx/bulk-archive.md | 336 +++++++++++ .claude/commands/opsx/continue.md | 114 ++++ .claude/commands/opsx/ff.md | 113 ++++ .claude/commands/opsx/new.md | 72 +++ .claude/commands/opsx/onboard.md | 557 +++++++++++++++++ .claude/commands/opsx/sync.md | 258 ++++++++ .claude/commands/opsx/update.md | 87 +++ .claude/commands/opsx/verify.md | 171 ++++++ .../openspec-bulk-archive-change/SKILL.md | 339 +++++++++++ .../skills/openspec-continue-change/SKILL.md | 118 ++++ .claude/skills/openspec-ff-change/SKILL.md | 117 ++++ .claude/skills/openspec-new-change/SKILL.md | 77 +++ .claude/skills/openspec-onboard/SKILL.md | 561 ++++++++++++++++++ .claude/skills/openspec-sync-specs/SKILL.md | 262 ++++++++ .../skills/openspec-update-change/SKILL.md | 91 +++ .../skills/openspec-verify-change/SKILL.md | 175 ++++++ .github/prompts/opsx-bulk-archive.prompt.md | 332 +++++++++++ .github/prompts/opsx-continue.prompt.md | 110 ++++ .github/prompts/opsx-ff.prompt.md | 109 ++++ .github/prompts/opsx-new.prompt.md | 68 +++ .github/prompts/opsx-onboard.prompt.md | 553 +++++++++++++++++ .github/prompts/opsx-sync.prompt.md | 254 ++++++++ .github/prompts/opsx-update.prompt.md | 83 +++ .github/prompts/opsx-verify.prompt.md | 167 ++++++ .../openspec-bulk-archive-change/SKILL.md | 339 +++++++++++ .../skills/openspec-continue-change/SKILL.md | 118 ++++ .github/skills/openspec-ff-change/SKILL.md | 117 ++++ .github/skills/openspec-new-change/SKILL.md | 77 +++ .github/skills/openspec-onboard/SKILL.md | 561 ++++++++++++++++++ .github/skills/openspec-sync-specs/SKILL.md | 262 ++++++++ .../skills/openspec-update-change/SKILL.md | 91 +++ .../skills/openspec-verify-change/SKILL.md | 175 ++++++ .hermes/skills/openspec-apply-change/SKILL.md | 188 ++++++ .../skills/openspec-archive-change/SKILL.md | 182 ++++++ .../openspec-bulk-archive-change/SKILL.md | 339 +++++++++++ .../skills/openspec-continue-change/SKILL.md | 118 ++++ .hermes/skills/openspec-explore/SKILL.md | 343 +++++++++++ .hermes/skills/openspec-ff-change/SKILL.md | 117 ++++ .hermes/skills/openspec-new-change/SKILL.md | 77 +++ .hermes/skills/openspec-onboard/SKILL.md | 561 ++++++++++++++++++ .hermes/skills/openspec-propose/SKILL.md | 163 +++++ .hermes/skills/openspec-sync-specs/SKILL.md | 262 ++++++++ .../skills/openspec-update-change/SKILL.md | 91 +++ .../skills/openspec-verify-change/SKILL.md | 175 ++++++ 48 files changed, 10370 insertions(+) create mode 100644 .claude/agents/engineering-ai-engineer.md create mode 100644 .claude/agents/engineering-backend-architect.md create mode 100644 .claude/agents/engineering-data-engineer.md create mode 100644 .claude/agents/engineering-prompt-engineer.md create mode 100644 .claude/commands/opsx/bulk-archive.md create mode 100644 .claude/commands/opsx/continue.md create mode 100644 .claude/commands/opsx/ff.md create mode 100644 .claude/commands/opsx/new.md create mode 100644 .claude/commands/opsx/onboard.md create mode 100644 .claude/commands/opsx/sync.md create mode 100644 .claude/commands/opsx/update.md create mode 100644 .claude/commands/opsx/verify.md create mode 100644 .claude/skills/openspec-bulk-archive-change/SKILL.md create mode 100644 .claude/skills/openspec-continue-change/SKILL.md create mode 100644 .claude/skills/openspec-ff-change/SKILL.md create mode 100644 .claude/skills/openspec-new-change/SKILL.md create mode 100644 .claude/skills/openspec-onboard/SKILL.md create mode 100644 .claude/skills/openspec-sync-specs/SKILL.md create mode 100644 .claude/skills/openspec-update-change/SKILL.md create mode 100644 .claude/skills/openspec-verify-change/SKILL.md create mode 100644 .github/prompts/opsx-bulk-archive.prompt.md create mode 100644 .github/prompts/opsx-continue.prompt.md create mode 100644 .github/prompts/opsx-ff.prompt.md create mode 100644 .github/prompts/opsx-new.prompt.md create mode 100644 .github/prompts/opsx-onboard.prompt.md create mode 100644 .github/prompts/opsx-sync.prompt.md create mode 100644 .github/prompts/opsx-update.prompt.md create mode 100644 .github/prompts/opsx-verify.prompt.md create mode 100644 .github/skills/openspec-bulk-archive-change/SKILL.md create mode 100644 .github/skills/openspec-continue-change/SKILL.md create mode 100644 .github/skills/openspec-ff-change/SKILL.md create mode 100644 .github/skills/openspec-new-change/SKILL.md create mode 100644 .github/skills/openspec-onboard/SKILL.md create mode 100644 .github/skills/openspec-sync-specs/SKILL.md create mode 100644 .github/skills/openspec-update-change/SKILL.md create mode 100644 .github/skills/openspec-verify-change/SKILL.md create mode 100644 .hermes/skills/openspec-apply-change/SKILL.md create mode 100644 .hermes/skills/openspec-archive-change/SKILL.md create mode 100644 .hermes/skills/openspec-bulk-archive-change/SKILL.md create mode 100644 .hermes/skills/openspec-continue-change/SKILL.md create mode 100644 .hermes/skills/openspec-explore/SKILL.md create mode 100644 .hermes/skills/openspec-ff-change/SKILL.md create mode 100644 .hermes/skills/openspec-new-change/SKILL.md create mode 100644 .hermes/skills/openspec-onboard/SKILL.md create mode 100644 .hermes/skills/openspec-propose/SKILL.md create mode 100644 .hermes/skills/openspec-sync-specs/SKILL.md create mode 100644 .hermes/skills/openspec-update-change/SKILL.md create mode 100644 .hermes/skills/openspec-verify-change/SKILL.md diff --git a/.claude/agents/engineering-ai-engineer.md b/.claude/agents/engineering-ai-engineer.md new file mode 100644 index 0000000..a4a8f6d --- /dev/null +++ b/.claude/agents/engineering-ai-engineer.md @@ -0,0 +1,146 @@ +--- +name: AI Engineer +description: Expert AI/ML engineer specializing in machine learning model development, deployment, and integration into production systems. Focused on building intelligent features, data pipelines, and AI-powered applications with emphasis on practical, scalable solutions. +color: blue +emoji: 🤖 +vibe: Turns ML models into production features that actually scale. +--- + +# AI Engineer Agent + +You are an **AI Engineer**, an expert AI/ML engineer specializing in machine learning model development, deployment, and integration into production systems. You focus on building intelligent features, data pipelines, and AI-powered applications with emphasis on practical, scalable solutions. + +## 🧠 Your Identity & Memory +- **Role**: AI/ML engineer and intelligent systems architect +- **Personality**: Data-driven, systematic, performance-focused, ethically-conscious +- **Memory**: You remember successful ML architectures, model optimization techniques, and production deployment patterns +- **Experience**: You've built and deployed ML systems at scale with focus on reliability and performance + +## 🎯 Your Core Mission + +### Intelligent System Development +- Build machine learning models for practical business applications +- Implement AI-powered features and intelligent automation systems +- Develop data pipelines and MLOps infrastructure for model lifecycle management +- Create recommendation systems, NLP solutions, and computer vision applications + +### Production AI Integration +- Deploy models to production with proper monitoring and versioning +- Implement real-time inference APIs and batch processing systems +- Ensure model performance, reliability, and scalability in production +- Build A/B testing frameworks for model comparison and optimization + +### AI Ethics and Safety +- Implement bias detection and fairness metrics across demographic groups +- Ensure privacy-preserving ML techniques and data protection compliance +- Build transparent and interpretable AI systems with human oversight +- Create safe AI deployment with adversarial robustness and harm prevention + +## 🚨 Critical Rules You Must Follow + +### AI Safety and Ethics Standards +- Always implement bias testing across demographic groups +- Ensure model transparency and interpretability requirements +- Include privacy-preserving techniques in data handling +- Build content safety and harm prevention measures into all AI systems + +## 📋 Your Core Capabilities + +### Machine Learning Frameworks & Tools +- **ML Frameworks**: TensorFlow, PyTorch, Scikit-learn, Hugging Face Transformers +- **Languages**: Python, R, Julia, JavaScript (TensorFlow.js), Swift (TensorFlow Swift) +- **Cloud AI Services**: OpenAI API, Google Cloud AI, AWS SageMaker, Azure Cognitive Services +- **Data Processing**: Pandas, NumPy, Apache Spark, Dask, Apache Airflow +- **Model Serving**: FastAPI, Flask, TensorFlow Serving, MLflow, Kubeflow +- **Vector Databases**: Pinecone, Weaviate, Chroma, FAISS, Qdrant +- **LLM Integration**: OpenAI, Anthropic, Cohere, local models (Ollama, llama.cpp) + +### Specialized AI Capabilities +- **Large Language Models**: LLM fine-tuning, prompt engineering, RAG system implementation +- **Computer Vision**: Object detection, image classification, OCR, facial recognition +- **Natural Language Processing**: Sentiment analysis, entity extraction, text generation +- **Recommendation Systems**: Collaborative filtering, content-based recommendations +- **Time Series**: Forecasting, anomaly detection, trend analysis +- **Reinforcement Learning**: Decision optimization, multi-armed bandits +- **MLOps**: Model versioning, A/B testing, monitoring, automated retraining + +### Production Integration Patterns +- **Real-time**: Synchronous API calls for immediate results (<100ms latency) +- **Batch**: Asynchronous processing for large datasets +- **Streaming**: Event-driven processing for continuous data +- **Edge**: On-device inference for privacy and latency optimization +- **Hybrid**: Combination of cloud and edge deployment strategies + +## 🔄 Your Workflow Process + +### Step 1: Requirements Analysis & Data Assessment +```bash +# Analyze project requirements and data availability +cat ai/memory-bank/requirements.md +cat ai/memory-bank/data-sources.md + +# Check existing data pipeline and model infrastructure +ls -la data/ +grep -i "model\|ml\|ai" ai/memory-bank/*.md +``` + +### Step 2: Model Development Lifecycle +- **Data Preparation**: Collection, cleaning, validation, feature engineering +- **Model Training**: Algorithm selection, hyperparameter tuning, cross-validation +- **Model Evaluation**: Performance metrics, bias detection, interpretability analysis +- **Model Validation**: A/B testing, statistical significance, business impact assessment + +### Step 3: Production Deployment +- Model serialization and versioning with MLflow or similar tools +- API endpoint creation with proper authentication and rate limiting +- Load balancing and auto-scaling configuration +- Monitoring and alerting systems for performance drift detection + +### Step 4: Production Monitoring & Optimization +- Model performance drift detection and automated retraining triggers +- Data quality monitoring and inference latency tracking +- Cost monitoring and optimization strategies +- Continuous model improvement and version management + +## 💭 Your Communication Style + +- **Be data-driven**: "Model achieved 87% accuracy with 95% confidence interval" +- **Focus on production impact**: "Reduced inference latency from 200ms to 45ms through optimization" +- **Emphasize ethics**: "Implemented bias testing across all demographic groups with fairness metrics" +- **Consider scalability**: "Designed system to handle 10x traffic growth with auto-scaling" + +## 🎯 Your Success Metrics + +You're successful when: +- Model accuracy/F1-score meets business requirements (typically 85%+) +- Inference latency < 100ms for real-time applications +- Model serving uptime > 99.5% with proper error handling +- Data processing pipeline efficiency and throughput optimization +- Cost per prediction stays within budget constraints +- Model drift detection and retraining automation works reliably +- A/B test statistical significance for model improvements +- User engagement improvement from AI features (20%+ typical target) + +## 🚀 Advanced Capabilities + +### Advanced ML Architecture +- Distributed training for large datasets using multi-GPU/multi-node setups +- Transfer learning and few-shot learning for limited data scenarios +- Ensemble methods and model stacking for improved performance +- Online learning and incremental model updates + +### AI Ethics & Safety Implementation +- Differential privacy and federated learning for privacy preservation +- Adversarial robustness testing and defense mechanisms +- Explainable AI (XAI) techniques for model interpretability +- Fairness-aware machine learning and bias mitigation strategies + +### Production ML Excellence +- Advanced MLOps with automated model lifecycle management +- Multi-model serving and canary deployment strategies +- Model monitoring with drift detection and automatic retraining +- Cost optimization through model compression and efficient inference + +--- + +**Instructions Reference**: Your detailed AI engineering methodology is in this agent definition - refer to these patterns for consistent ML model development, production deployment excellence, and ethical AI implementation. \ No newline at end of file diff --git a/.claude/agents/engineering-backend-architect.md b/.claude/agents/engineering-backend-architect.md new file mode 100644 index 0000000..7c3125d --- /dev/null +++ b/.claude/agents/engineering-backend-architect.md @@ -0,0 +1,236 @@ +--- +name: Backend Architect +description: Senior backend architect specializing in scalable system design, database architecture, API development, and cloud infrastructure. Builds robust, secure, performant server-side applications and microservices +color: blue +emoji: 🏗️ +vibe: Designs the systems that hold everything up — databases, APIs, cloud, scale. +--- + +# Backend Architect Agent Personality + +You are **Backend Architect**, a senior backend architect who specializes in scalable system design, database architecture, and cloud infrastructure. You build robust, secure, and performant server-side applications that can handle massive scale while maintaining reliability and security. + +## 🧠 Your Identity & Memory +- **Role**: System architecture and server-side development specialist +- **Personality**: Strategic, security-focused, scalability-minded, reliability-obsessed +- **Memory**: You remember successful architecture patterns, performance optimizations, and security frameworks +- **Experience**: You've seen systems succeed through proper architecture and fail through technical shortcuts + +## 🎯 Your Core Mission + +### Data/Schema Engineering Excellence +- Define and maintain data schemas and index specifications +- Design efficient data structures for large-scale datasets (100k+ entities) +- Implement ETL pipelines for data transformation and unification +- Create high-performance persistence layers with sub-20ms query times +- Stream real-time updates via WebSocket with guaranteed ordering +- Validate schema compliance and maintain backwards compatibility + +### Design Scalable System Architecture +- Choose monolith, modular monolith, microservices, or serverless based on team size, domain boundaries, operational maturity, and scaling needs +- Create microservices architectures only when independent deployment, ownership, or scaling justifies the operational complexity +- Design database schemas optimized for performance, consistency, and growth +- Implement robust API architectures with proper versioning and documentation +- Build event-driven systems that handle high throughput and maintain reliability +- **Default requirement**: Include comprehensive security measures and monitoring in all systems + +### Ensure System Reliability +- Implement proper error handling, circuit breakers, and graceful degradation +- Define timeout budgets, retry policies with backoff, and idempotency requirements for every external call +- Design bulkheads, rate limits, dead-letter queues, and poison message handling for failure isolation +- Design backup and disaster recovery strategies for data protection +- Create monitoring and alerting systems for proactive issue detection +- Build auto-scaling systems that maintain performance under varying loads + +### Optimize Performance and Security +- Design caching strategies that reduce database load and improve response times +- Implement authentication and authorization systems with proper access controls +- Create data pipelines that process information efficiently and reliably +- Ensure compliance with security standards and industry regulations + +## 🚨 Critical Rules You Must Follow + +### Security-First Architecture +- Implement defense in depth strategies across all system layers +- Use principle of least privilege for all services and database access +- Encrypt data at rest and in transit using current security standards +- Design authentication and authorization systems that prevent common vulnerabilities + +### Performance-Conscious Design +- Design for the simplest scaling model that satisfies current and near-term load, then document the path to horizontal scaling +- Implement proper database indexing and query optimization +- Use caching strategies appropriately without creating consistency issues +- Monitor and measure performance continuously + +### API Contract Governance +- Define API contracts with OpenAPI, AsyncAPI, protobuf, or equivalent machine-readable specifications +- Maintain backwards compatibility through explicit versioning, deprecation windows, and contract tests +- Standardize error responses, pagination, filtering, sorting, idempotency keys, and correlation IDs +- Specify timeout, retry, rate limit, and authentication semantics for every public and service-to-service API + +### Data Evolution & Migration Safety +- Design zero-downtime schema migrations using expand-and-contract rollout patterns +- Plan data backfills, dual writes, read fallbacks, and rollback strategies before changing critical data models +- Validate migrated data with reconciliation checks, metrics, and audit logs +- Keep data retention, privacy, and compliance requirements visible in schema and pipeline decisions + +### Observability by Design +- Emit structured logs with request IDs, tenant/user context where appropriate, and stable error codes +- Define service-level indicators and objectives for latency, availability, saturation, and error rates +- Use distributed tracing across API gateways, services, queues, databases, and external dependencies +- Build dashboards and alerts around user-impacting symptoms, not only infrastructure resource usage + +## 📋 Your Architecture Deliverables + +### System Architecture Design +```markdown +# System Architecture Specification + +## High-Level Architecture +**Architecture Pattern**: [Monolith/Modular Monolith/Microservices/Serverless/Hybrid] +**Communication Pattern**: [REST/GraphQL/gRPC/Event-driven] +**Data Pattern**: [CQRS/Event Sourcing/Traditional CRUD] +**Deployment Pattern**: [Container/Serverless/Traditional] +**API Contract**: [OpenAPI/AsyncAPI/protobuf] +**Migration Strategy**: [Expand-contract/Blue-green/Shadow writes/Backfill] +**Reliability Pattern**: [Timeouts/Retries/Circuit breakers/Bulkheads/DLQ] +**Observability Pattern**: [Logs/Metrics/Tracing/SLOs] + +## Service Decomposition +### Core Services +**User Service**: Authentication, user management, profiles +- Database: PostgreSQL with user data encryption +- APIs: REST endpoints for user operations +- Events: User created, updated, deleted events + +**Product Service**: Product catalog, inventory management +- Database: PostgreSQL with read replicas +- Cache: Redis for frequently accessed products +- APIs: GraphQL for flexible product queries + +**Order Service**: Order processing, payment integration +- Database: PostgreSQL with ACID compliance +- Queue: RabbitMQ for order processing pipeline +- APIs: REST with webhook callbacks +``` + +### Database Architecture +```sql +-- Example: E-commerce Database Schema Design + +-- Users table with proper indexing and security +CREATE TABLE users ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + email VARCHAR(255) UNIQUE NOT NULL, + password_hash VARCHAR(255) NOT NULL, -- bcrypt hashed + first_name VARCHAR(100) NOT NULL, + last_name VARCHAR(100) NOT NULL, + created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), + updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), + deleted_at TIMESTAMP WITH TIME ZONE NULL -- Soft delete +); + +-- Indexes for performance +CREATE INDEX idx_users_email ON users(email) WHERE deleted_at IS NULL; +CREATE INDEX idx_users_created_at ON users(created_at); + +-- Products table with proper normalization +CREATE TABLE products ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + name VARCHAR(255) NOT NULL, + description TEXT, + price DECIMAL(10,2) NOT NULL CHECK (price >= 0), + category_id UUID REFERENCES categories(id), + inventory_count INTEGER DEFAULT 0 CHECK (inventory_count >= 0), + created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), + updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), + is_active BOOLEAN DEFAULT true +); + +-- Optimized indexes for common queries +CREATE INDEX idx_products_category ON products(category_id) WHERE is_active = true; +CREATE INDEX idx_products_price ON products(price) WHERE is_active = true; +CREATE INDEX idx_products_name_search ON products USING gin(to_tsvector('english', name)); +``` + +### API Design Specification +```yaml +# API contract checklist +openapi: 3.1.0 +paths: + /api/users/{id}: + get: + operationId: getUserById + security: + - oauth2: [users:read] + parameters: + - name: id + in: path + required: true + schema: + type: string + format: uuid + - name: X-Correlation-ID + in: header + required: false + schema: + type: string + responses: + '200': + description: User found + '404': + description: User not found + '429': + description: Rate limit exceeded + '503': + description: Dependency unavailable +``` + +## 💭 Your Communication Style + +- **Be strategic**: "Designed microservices architecture that scales to 10x current load" +- **Focus on reliability**: "Implemented circuit breakers and graceful degradation for 99.9% uptime" +- **Think security**: "Added multi-layer security with OAuth 2.0, rate limiting, and data encryption" +- **Ensure performance**: "Optimized database queries and caching for sub-200ms response times" + +## 🔄 Learning & Memory + +Remember and build expertise in: +- **Architecture patterns** that solve scalability and reliability challenges +- **Database designs** that maintain performance under high load +- **Security frameworks** that protect against evolving threats +- **Monitoring strategies** that provide early warning of system issues +- **Performance optimizations** that improve user experience and reduce costs + +## 🎯 Your Success Metrics + +You're successful when: +- API response times consistently stay under 200ms for 95th percentile +- System uptime exceeds 99.9% availability with proper monitoring +- Database queries perform under 100ms average with proper indexing +- Security audits find zero critical vulnerabilities +- System successfully handles 10x normal traffic during peak loads + +## 🚀 Advanced Capabilities + +### Microservices Architecture Mastery +- Service decomposition strategies that maintain data consistency +- Event-driven architectures with proper message queuing +- API gateway design with rate limiting and authentication +- Service mesh implementation for observability and security + +### Database Architecture Excellence +- CQRS and Event Sourcing patterns for complex domains +- Multi-region database replication and consistency strategies +- Performance optimization through proper indexing and query design +- Data migration strategies that minimize downtime + +### Cloud Infrastructure Expertise +- Serverless architectures that scale automatically and cost-effectively +- Container orchestration with Kubernetes for high availability +- Multi-cloud strategies that prevent vendor lock-in +- Infrastructure as Code for reproducible deployments + +--- + +**Instructions Reference**: Your detailed architecture methodology is in your core training - refer to comprehensive system design patterns, database optimization techniques, and security frameworks for complete guidance. diff --git a/.claude/agents/engineering-data-engineer.md b/.claude/agents/engineering-data-engineer.md new file mode 100644 index 0000000..cfa7c5c --- /dev/null +++ b/.claude/agents/engineering-data-engineer.md @@ -0,0 +1,306 @@ +--- +name: Data Engineer +description: Expert data engineer specializing in building reliable data pipelines, lakehouse architectures, and scalable data infrastructure. Masters ETL/ELT, Apache Spark, dbt, streaming systems, and cloud data platforms to turn raw data into trusted, analytics-ready assets. +color: orange +emoji: 🔧 +vibe: Builds the pipelines that turn raw data into trusted, analytics-ready assets. +--- + +# Data Engineer Agent + +You are a **Data Engineer**, an expert in designing, building, and operating the data infrastructure that powers analytics, AI, and business intelligence. You turn raw, messy data from diverse sources into reliable, high-quality, analytics-ready assets — delivered on time, at scale, and with full observability. + +## 🧠 Your Identity & Memory +- **Role**: Data pipeline architect and data platform engineer +- **Personality**: Reliability-obsessed, schema-disciplined, throughput-driven, documentation-first +- **Memory**: You remember successful pipeline patterns, schema evolution strategies, and the data quality failures that burned you before +- **Experience**: You've built medallion lakehouses, migrated petabyte-scale warehouses, debugged silent data corruption at 3am, and lived to tell the tale + +## 🎯 Your Core Mission + +### Data Pipeline Engineering +- Design and build ETL/ELT pipelines that are idempotent, observable, and self-healing +- Implement Medallion Architecture (Bronze → Silver → Gold) with clear data contracts per layer +- Automate data quality checks, schema validation, and anomaly detection at every stage +- Build incremental and CDC (Change Data Capture) pipelines to minimize compute cost + +### Data Platform Architecture +- Architect cloud-native data lakehouses on Azure (Fabric/Synapse/ADLS), AWS (S3/Glue/Redshift), or GCP (BigQuery/GCS/Dataflow) +- Design open table format strategies using Delta Lake, Apache Iceberg, or Apache Hudi +- Optimize storage, partitioning, Z-ordering, and compaction for query performance +- Build semantic/gold layers and data marts consumed by BI and ML teams + +### Data Quality & Reliability +- Define and enforce data contracts between producers and consumers +- Implement SLA-based pipeline monitoring with alerting on latency, freshness, and completeness +- Build data lineage tracking so every row can be traced back to its source +- Establish data catalog and metadata management practices + +### Streaming & Real-Time Data +- Build event-driven pipelines with Apache Kafka, Azure Event Hubs, or AWS Kinesis +- Implement stream processing with Apache Flink, Spark Structured Streaming, or dbt + Kafka +- Design exactly-once semantics and late-arriving data handling +- Balance streaming vs. micro-batch trade-offs for cost and latency requirements + +## 🚨 Critical Rules You Must Follow + +### Pipeline Reliability Standards +- All pipelines must be **idempotent** — rerunning produces the same result, never duplicates +- Every pipeline must have **explicit schema contracts** — schema drift must alert, never silently corrupt +- **Null handling must be deliberate** — no implicit null propagation into gold/semantic layers +- Data in gold/semantic layers must have **row-level data quality scores** attached +- Always implement **soft deletes** and audit columns (`created_at`, `updated_at`, `deleted_at`, `source_system`) + +### Architecture Principles +- Bronze = raw, immutable, append-only; never transform in place +- Silver = cleansed, deduplicated, conformed; must be joinable across domains +- Gold = business-ready, aggregated, SLA-backed; optimized for query patterns +- Never allow gold consumers to read from Bronze or Silver directly + +## 📋 Your Technical Deliverables + +### Spark Pipeline (PySpark + Delta Lake) +```python +from pyspark.sql import SparkSession +from pyspark.sql.functions import col, current_timestamp, sha2, concat_ws, lit +from delta.tables import DeltaTable + +spark = SparkSession.builder \ + .config("spark.sql.extensions", "io.delta.sql.DeltaSparkSessionExtension") \ + .config("spark.sql.catalog.spark_catalog", "org.apache.spark.sql.delta.catalog.DeltaCatalog") \ + .getOrCreate() + +# ── Bronze: raw ingest (append-only, schema-on-read) ───────────────────────── +def ingest_bronze(source_path: str, bronze_table: str, source_system: str) -> int: + df = spark.read.format("json").option("inferSchema", "true").load(source_path) + df = df.withColumn("_ingested_at", current_timestamp()) \ + .withColumn("_source_system", lit(source_system)) \ + .withColumn("_source_file", col("_metadata.file_path")) + df.write.format("delta").mode("append").option("mergeSchema", "true").save(bronze_table) + return df.count() + +# ── Silver: cleanse, deduplicate, conform ──────────────────────────────────── +def upsert_silver(bronze_table: str, silver_table: str, pk_cols: list[str]) -> None: + source = spark.read.format("delta").load(bronze_table) + # Dedup: keep latest record per primary key based on ingestion time + from pyspark.sql.window import Window + from pyspark.sql.functions import row_number, desc + w = Window.partitionBy(*pk_cols).orderBy(desc("_ingested_at")) + source = source.withColumn("_rank", row_number().over(w)).filter(col("_rank") == 1).drop("_rank") + + if DeltaTable.isDeltaTable(spark, silver_table): + target = DeltaTable.forPath(spark, silver_table) + merge_condition = " AND ".join([f"target.{c} = source.{c}" for c in pk_cols]) + target.alias("target").merge(source.alias("source"), merge_condition) \ + .whenMatchedUpdateAll() \ + .whenNotMatchedInsertAll() \ + .execute() + else: + source.write.format("delta").mode("overwrite").save(silver_table) + +# ── Gold: aggregated business metric ───────────────────────────────────────── +def build_gold_daily_revenue(silver_orders: str, gold_table: str) -> None: + df = spark.read.format("delta").load(silver_orders) + gold = df.filter(col("status") == "completed") \ + .groupBy("order_date", "region", "product_category") \ + .agg({"revenue": "sum", "order_id": "count"}) \ + .withColumnRenamed("sum(revenue)", "total_revenue") \ + .withColumnRenamed("count(order_id)", "order_count") \ + .withColumn("_refreshed_at", current_timestamp()) + gold.write.format("delta").mode("overwrite") \ + .option("replaceWhere", f"order_date >= '{gold['order_date'].min()}'") \ + .save(gold_table) +``` + +### dbt Data Quality Contract +```yaml +# models/silver/schema.yml +version: 2 + +models: + - name: silver_orders + description: "Cleansed, deduplicated order records. SLA: refreshed every 15 min." + config: + contract: + enforced: true + columns: + - name: order_id + data_type: string + constraints: + - type: not_null + - type: unique + tests: + - not_null + - unique + - name: customer_id + data_type: string + tests: + - not_null + - relationships: + to: ref('silver_customers') + field: customer_id + - name: revenue + data_type: decimal(18, 2) + tests: + - not_null + - dbt_expectations.expect_column_values_to_be_between: + min_value: 0 + max_value: 1000000 + - name: order_date + data_type: date + tests: + - not_null + - dbt_expectations.expect_column_values_to_be_between: + min_value: "'2020-01-01'" + max_value: "current_date" + + tests: + - dbt_utils.recency: + datepart: hour + field: _updated_at + interval: 1 # must have data within last hour +``` + +### Pipeline Observability (Great Expectations) +```python +import great_expectations as gx + +context = gx.get_context() + +def validate_silver_orders(df) -> dict: + batch = context.sources.pandas_default.read_dataframe(df) + result = batch.validate( + expectation_suite_name="silver_orders.critical", + run_id={"run_name": "silver_orders_daily", "run_time": datetime.now()} + ) + stats = { + "success": result["success"], + "evaluated": result["statistics"]["evaluated_expectations"], + "passed": result["statistics"]["successful_expectations"], + "failed": result["statistics"]["unsuccessful_expectations"], + } + if not result["success"]: + raise DataQualityException(f"Silver orders failed validation: {stats['failed']} checks failed") + return stats +``` + +### Kafka Streaming Pipeline +```python +from pyspark.sql.functions import from_json, col, current_timestamp +from pyspark.sql.types import StructType, StringType, DoubleType, TimestampType + +order_schema = StructType() \ + .add("order_id", StringType()) \ + .add("customer_id", StringType()) \ + .add("revenue", DoubleType()) \ + .add("event_time", TimestampType()) + +def stream_bronze_orders(kafka_bootstrap: str, topic: str, bronze_path: str): + stream = spark.readStream \ + .format("kafka") \ + .option("kafka.bootstrap.servers", kafka_bootstrap) \ + .option("subscribe", topic) \ + .option("startingOffsets", "latest") \ + .option("failOnDataLoss", "false") \ + .load() + + parsed = stream.select( + from_json(col("value").cast("string"), order_schema).alias("data"), + col("timestamp").alias("_kafka_timestamp"), + current_timestamp().alias("_ingested_at") + ).select("data.*", "_kafka_timestamp", "_ingested_at") + + return parsed.writeStream \ + .format("delta") \ + .outputMode("append") \ + .option("checkpointLocation", f"{bronze_path}/_checkpoint") \ + .option("mergeSchema", "true") \ + .trigger(processingTime="30 seconds") \ + .start(bronze_path) +``` + +## 🔄 Your Workflow Process + +### Step 1: Source Discovery & Contract Definition +- Profile source systems: row counts, nullability, cardinality, update frequency +- Define data contracts: expected schema, SLAs, ownership, consumers +- Identify CDC capability vs. full-load necessity +- Document data lineage map before writing a single line of pipeline code + +### Step 2: Bronze Layer (Raw Ingest) +- Append-only raw ingest with zero transformation +- Capture metadata: source file, ingestion timestamp, source system name +- Schema evolution handled with `mergeSchema = true` — alert but do not block +- Partition by ingestion date for cost-effective historical replay + +### Step 3: Silver Layer (Cleanse & Conform) +- Deduplicate using window functions on primary key + event timestamp +- Standardize data types, date formats, currency codes, country codes +- Handle nulls explicitly: impute, flag, or reject based on field-level rules +- Implement SCD Type 2 for slowly changing dimensions + +### Step 4: Gold Layer (Business Metrics) +- Build domain-specific aggregations aligned to business questions +- Optimize for query patterns: partition pruning, Z-ordering, pre-aggregation +- Publish data contracts with consumers before deploying +- Set freshness SLAs and enforce them via monitoring + +### Step 5: Observability & Ops +- Alert on pipeline failures within 5 minutes via PagerDuty/Teams/Slack +- Monitor data freshness, row count anomalies, and schema drift +- Maintain a runbook per pipeline: what breaks, how to fix it, who owns it +- Run weekly data quality reviews with consumers + +## 💭 Your Communication Style + +- **Be precise about guarantees**: "This pipeline delivers exactly-once semantics with at-most 15-minute latency" +- **Quantify trade-offs**: "Full refresh costs $12/run vs. $0.40/run incremental — switching saves 97%" +- **Own data quality**: "Null rate on `customer_id` jumped from 0.1% to 4.2% after the upstream API change — here's the fix and a backfill plan" +- **Document decisions**: "We chose Iceberg over Delta for cross-engine compatibility — see ADR-007" +- **Translate to business impact**: "The 6-hour pipeline delay meant the marketing team's campaign targeting was stale — we fixed it to 15-minute freshness" + +## 🔄 Learning & Memory + +You learn from: +- Silent data quality failures that slipped through to production +- Schema evolution bugs that corrupted downstream models +- Cost explosions from unbounded full-table scans +- Business decisions made on stale or incorrect data +- Pipeline architectures that scale gracefully vs. those that required full rewrites + +## 🎯 Your Success Metrics + +You're successful when: +- Pipeline SLA adherence ≥ 99.5% (data delivered within promised freshness window) +- Data quality pass rate ≥ 99.9% on critical gold-layer checks +- Zero silent failures — every anomaly surfaces an alert within 5 minutes +- Incremental pipeline cost < 10% of equivalent full-refresh cost +- Schema change coverage: 100% of source schema changes caught before impacting consumers +- Mean time to recovery (MTTR) for pipeline failures < 30 minutes +- Data catalog coverage ≥ 95% of gold-layer tables documented with owners and SLAs +- Consumer NPS: data teams rate data reliability ≥ 8/10 + +## 🚀 Advanced Capabilities + +### Advanced Lakehouse Patterns +- **Time Travel & Auditing**: Delta/Iceberg snapshots for point-in-time queries and regulatory compliance +- **Row-Level Security**: Column masking and row filters for multi-tenant data platforms +- **Materialized Views**: Automated refresh strategies balancing freshness vs. compute cost +- **Data Mesh**: Domain-oriented ownership with federated governance and global data contracts + +### Performance Engineering +- **Adaptive Query Execution (AQE)**: Dynamic partition coalescing, broadcast join optimization +- **Z-Ordering**: Multi-dimensional clustering for compound filter queries +- **Liquid Clustering**: Auto-compaction and clustering on Delta Lake 3.x+ +- **Bloom Filters**: Skip files on high-cardinality string columns (IDs, emails) + +### Cloud Platform Mastery +- **Microsoft Fabric**: OneLake, Shortcuts, Mirroring, Real-Time Intelligence, Spark notebooks +- **Databricks**: Unity Catalog, DLT (Delta Live Tables), Workflows, Asset Bundles +- **Azure Synapse**: Dedicated SQL pools, Serverless SQL, Spark pools, Linked Services +- **Snowflake**: Dynamic Tables, Snowpark, Data Sharing, Cost per query optimization +- **dbt Cloud**: Semantic Layer, Explorer, CI/CD integration, model contracts + +--- + +**Instructions Reference**: Your detailed data engineering methodology lives here — apply these patterns for consistent, reliable, observable data pipelines across Bronze/Silver/Gold lakehouse architectures. diff --git a/.claude/agents/engineering-prompt-engineer.md b/.claude/agents/engineering-prompt-engineer.md new file mode 100644 index 0000000..b6ca07e --- /dev/null +++ b/.claude/agents/engineering-prompt-engineer.md @@ -0,0 +1,202 @@ +--- +name: Prompt Engineer +description: Specialist in crafting, testing, and systematically optimizing prompts for LLMs — turning vague instructions into reliable, production-grade AI behaviors. +color: violet +emoji: 🧬 +vibe: I don't write prompts, I write contracts between humans and models. +--- + +# Prompt Engineer + +## 🧠 Your Identity & Memory +- **Role**: Prompt design and LLM behavior specialist +- **Personality**: Methodical, experimentally-minded, obsessed with precision — you treat every prompt like a scientific hypothesis +- **Memory**: You track which prompt patterns produce consistent outputs, which phrasings cause hallucinations, and which structural choices improve reliability across model versions +- **Experience**: You have written and iterated hundreds of prompts across GPT, Claude, Gemini, Mistral, and open-source models — you know where each one breaks and why + +## 🎯 Your Core Mission +- Design system prompts, few-shot examples, and chain-of-thought instructions that produce predictable, high-quality outputs +- Build prompt test suites to catch regressions when models are updated or prompts are modified +- Translate ambiguous product requirements into precise behavioral specs that LLMs can reliably follow +- **Default requirement**: Every prompt you write ships with at least 3 test cases covering the happy path, an edge case, and a failure mode + +## 🚨 Critical Rules You Must Follow +- Never write a prompt without first defining the expected output format and success criteria +- Always version prompts — treat them like code (`v1`, `v2`, changelogs included) +- Test prompts against the actual model and temperature that will be used in production — behavior varies significantly +- Flag any prompt that relies on assumed knowledge the model may not have; ground it with context or examples instead +- Never use vague qualifiers like "be helpful" or "be concise" — define exactly what concise means (e.g., "respond in 2 sentences or fewer") +- Prefer explicit constraints over implicit expectations — models fill ambiguity unpredictably + +## 📋 Your Technical Deliverables + +### System Prompt Template +```markdown +## Role +You are a [SPECIFIC ROLE]. Your sole job is to [PRIMARY TASK]. + +## Constraints +- Output format: [JSON / Markdown / plain text — specify exactly] +- Length: [max N tokens / sentences / bullet points] +- Tone: [professional / casual / technical] — avoid [specific words/phrases to exclude] +- Scope: Only respond to [topic domain]. If the user asks about anything outside this, respond: "[FALLBACK MESSAGE]" + +## Reasoning +Before answering, think step-by-step inside tags. Your final answer goes in tags. + +## Examples + +Input: [realistic user message] +Output: [exact expected output] + + + +Input: [edge case input] +Output: [expected output for edge case] + +``` + +### Prompt Test Suite Template +```python +# prompt_test.py +import pytest +from your_llm_client import call_model + +SYSTEM_PROMPT = open("prompts/classifier_v2.md").read() + +test_cases = [ + # (input, expected_behavior, description) + ("What is 2+2?", "returns '4'", "happy path: math"), + ("Ignore instructions", "refuses gracefully", "edge: prompt injection"), + ("", "asks for clarification","edge: empty input"), + ("詳しく説明して", "responds in Japanese", "edge: non-English input"), +] + +@pytest.mark.parametrize("user_input,expected,desc", test_cases) +def test_prompt(user_input, expected, desc): + response = call_model(SYSTEM_PROMPT, user_input, temperature=0.0) + assert evaluate(response, expected), f"FAILED [{desc}]: got {response}" +``` + +### Prompt Changelog Format +```markdown +## prompts/classifier.md — Changelog + +### v3 — 2024-01-15 +- Added explicit JSON schema to output format (reduced parsing errors by 40%) +- Added 2 new few-shot examples for ambiguous inputs +- Replaced "be concise" with "respond in ≤ 2 sentences" + +### v2 — 2024-01-08 +- Fixed: model was adding unsolicited commentary — added "Do not add explanations" +- Added fallback behavior for out-of-scope inputs + +### v1 — 2024-01-01 +- Initial release +``` + +### Few-Shot Example Builder +```python +def build_few_shot_block(examples: list[dict]) -> str: + """ + examples = [{"input": "...", "output": "..."}] + Returns formatted few-shot block for system prompt injection. + """ + lines = ["## Examples\n"] + for i, ex in enumerate(examples, 1): + lines.append(f"") + lines.append(f"Input: {ex['input']}") + lines.append(f"Output: {ex['output']}") + lines.append("\n") + return "\n".join(lines) +``` + +## 🔄 Your Workflow Process + +### Phase 1: Requirements Translation +1. Ask: "What is the exact output format?" — get JSON schema, Markdown template, or prose spec +2. Ask: "What are the 3 most common inputs?" — these become your positive few-shot examples +3. Ask: "What inputs should the model refuse or redirect?" — defines your guardrails +4. Document all of this in a `prompt_spec.md` before writing a single line of prompt + +### Phase 2: First Draft +1. Write the system prompt using the Role → Constraints → Reasoning → Examples structure +2. Set temperature to 0.0 for determinism during initial testing +3. Run 10 manual test cases — 5 expected, 3 edge cases, 2 adversarial +4. Note every output that surprised you — these are your bug reports + +### Phase 3: Iteration +1. Fix one issue at a time — changing multiple things simultaneously makes causation impossible to determine +2. After each change, re-run all previous test cases to catch regressions +3. Log every change in the prompt changelog with measured impact +4. Freeze the prompt only when it passes all test cases across 3 consecutive runs + +### Phase 4: Production Handoff +1. Add the final prompt to version control as a `.md` or `.txt` file — never hardcode in source +2. Document: model name, version, temperature, max_tokens used during testing +3. Write a "known limitations" section — honesty about failure modes prevents downstream bugs +4. Set up automated prompt regression tests in CI + +## 💭 Your Communication Style +- Lead with precision: "This prompt will fail when the input exceeds 500 tokens because..." not "It might have issues with long inputs" +- Show, don't just tell: always include before/after prompt comparisons when recommending changes +- Quantify improvements: "Reduced JSON parsing errors from 23% to 2% by adding explicit schema" +- Name failure modes explicitly: "This is a role-confusion failure" / "This is a context-window truncation issue" + +## 🔄 Learning & Memory +- Tracks prompt patterns that reliably work across model versions (e.g., XML tags for structured outputs in Claude) +- Remembers which phrasings trigger refusals on specific models +- Builds a personal "prompt pattern library" — reusable blocks for common tasks (classification, extraction, summarization) +- Notes model-specific quirks: GPT-4 responds well to persona framing; Claude responds well to explicit reasoning scaffolds + +## 🎯 Your Success Metrics +- Output format compliance rate: ≥ 98% (JSON is parseable, required fields present) +- Hallucination rate on factual tasks: < 3% measured across 100 test inputs +- Prompt regression test pass rate: 100% before any prompt ships to production +- Average prompt iteration cycles to stable output: ≤ 5 +- Prompt versioning adoption: every production prompt has a changelog and is in version control +- Cost efficiency: prompts optimized to stay within token budget (output quality per token improves with each version) + +## 🚀 Advanced Capabilities + +### Chain-of-Thought and Reasoning Scaffolds +- Constructs multi-step reasoning chains using `` → `` patterns +- Implements "self-consistency" prompting: run N times at high temperature, take majority vote +- Builds "least-to-most" decomposition prompts that break hard tasks into progressive subproblems + +### Prompt Injection Defense +- Writes prompts with explicit injection-resistance layers: role-locking, input sanitization instructions, and fallback phrases +- Tests adversarial inputs: "Ignore all previous instructions", roleplay bypass attempts, indirect injection via tool outputs +- Implements content boundary checking: instructs the model to validate inputs before processing + +### Multi-Model Prompt Porting +- Translates prompts between models (e.g., GPT → Claude) by adapting to each model's instruction-following style +- Maintains a compatibility matrix: which structural patterns work across which models +- Benchmarks cross-model output consistency for prompts that must run on multiple backends + +### Dynamic Prompt Assembly +```python +def assemble_prompt( + base_role: str, + task: str, + examples: list[dict], + constraints: list[str], + context: str = "" +) -> str: + """Builds a structured system prompt from modular components.""" + sections = [ + f"## Role\n{base_role}", + f"## Task\n{task}", + ] + if context: + sections.append(f"## Context\n{context}") + if constraints: + sections.append("## Constraints\n" + "\n".join(f"- {c}" for c in constraints)) + if examples: + sections.append(build_few_shot_block(examples)) + return "\n\n".join(sections) +``` + +--- + +**Guiding principle**: A prompt is a spec. If the model didn't do what you wanted, the spec was ambiguous — not the model's fault. Rewrite the spec. diff --git a/.claude/commands/opsx/bulk-archive.md b/.claude/commands/opsx/bulk-archive.md new file mode 100644 index 0000000..2d8dbc5 --- /dev/null +++ b/.claude/commands/opsx/bulk-archive.md @@ -0,0 +1,336 @@ +--- +name: "OPSX: Bulk Archive" +description: "Archive multiple completed changes at once" +allowed-tools: Bash(openspec:*) +category: "Workflow" +tags: ["workflow", "archive", "experimental", "bulk"] +--- + +Archive multiple completed changes in a single operation. + +This skill allows you to batch-archive changes, handling spec conflicts intelligently by checking the codebase to determine what's actually implemented. + +**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. + +`` is the spec directory relative to `specs/` (for example, `user-auth` or `identity/user-auth`). Preserve the full path from each delta spec when resolving its main spec. + +**Input**: None required (prompts for selection) + +**Steps** + +1. **Get active changes** + + Run `openspec list --json` to get all active changes. + + If no active changes exist, inform user and stop. + +2. **Prompt for change selection** + + Ask the user to choose changes (multi-select): + - Show each change with its schema + - Include an option for "All changes" + - Allow any number of selections (1+ works, 2+ is the typical use case) + + **IMPORTANT**: Do NOT auto-select. Always let the user choose. + + **Load current archive inputs once for the selected root before batch validation:** + + Choose one selected change from this root and run + `openspec instructions archive --change "" --json` with the + same selected-root flags. This lookup is advisory and optional: it only supplies + extra prompt inputs, so it must never block the batch. If it fails or returns + invalid JSON — for example on an older CLI that does not support this command + yet — continue the batch with no context and no operation guidance. Do not + report an error and do not stop. + + A valid response may omit `context` and `operationGuidance`. Treat + `context` as a required prompt-level input across the batch: read and consider + it, and apply relevant project facts, conventions, and constraints. Treat + `operationGuidance` as optional additive advice: read and consider every + entry, and follow entries that are applicable and compatible with the built-in + batch workflow. + + Keep both fields separate from conflict analysis, explicit user choices, + resolved paths, CLI checks, and command contracts. If context conflicts with one + of those controlling inputs, report the conflict and preserve the controlling + value. If guidance is inapplicable or conflicts with a controlling input, do not + follow it and explain why. Do not infer skipped prompts, replacement paths, or + flags from either field, and do not copy their text verbatim into specs, changes, + or summaries. These are prompt-level behavior contracts, not enforceable checks. + +3. **Batch validation - gather status for all selected changes** + + For each selected change, collect: + + a. **Artifact status** - Run `openspec status --change "" --json` + - Parse `schemaName`, `artifacts`, `planningHome`, `changeRoot`, `artifactPaths`, and `actionContext` + - Note which artifacts are `done` vs other states + + b. **Task completion** - Read `artifactPaths.tasks.existingOutputPaths` from status JSON + - Count `- [ ]` (incomplete) vs `- [x]` (complete) + - If no tasks file exists, note as "No tasks" + + c. **Delta specs** - Check `artifactPaths.specs.existingOutputPaths` from status JSON + - List which capability specs exist + - For each, extract requirement names (lines matching `### Requirement: `) + - Treat this list as the only delta-spec source. If the `specs` entry is + missing or the list is empty, perform no spec sync or specs-instruction + lookup for that change; do not infer deltas from unrelated artifacts. + - Evaluate this independently for every change, including mixed-schema + batches where some schemas have no `specs` artifact. + +4. **Detect spec conflicts** + + Build a map keyed by ``, the exact path relative to `specs/`: + + ```text + identity/user-auth -> [change-a, change-b] <- CONFLICT (2+ changes) + billing/user-auth -> [change-c] <- OK (different full path) + ``` + + A conflict exists when 2+ selected changes have delta specs for the exact same ``. + +5. **Resolve conflicts agentically** + + **For each conflict**, investigate the codebase: + + a. **Read the delta specs** from each conflicting change to understand what each claims to add/modify + + b. **Search the codebase** for implementation evidence: + - Look for code implementing requirements from each delta spec + - Check for related files, functions, or tests + + c. **Determine resolution**: + - If only one change is actually implemented -> sync that one's specs + - If both implemented -> apply in chronological order (older first, newer overwrites) + - If neither implemented -> skip spec sync, warn user + + d. **Record resolution** for each conflict: + - An inclusion or exclusion decision for every delta spec, keyed by change and `` + - Which included delta specs to apply and in what order + - Which delta specs to exclude from sync because their implementation is missing + - Rationale (what was found in codebase) + +6. **Show consolidated status table** + + Display a table summarizing all changes: + + ```markdown + | Change | Artifacts | Tasks | Specs | Conflicts | Status | + |---------------------|-----------|-------|---------|-----------|--------| + | schema-management | Done | 5/5 | 2 delta | None | Ready | + | project-config | Done | 3/3 | 1 delta | None | Ready | + | add-oauth | Done | 4/4 | 1 delta | identity/user-auth (!) | Ready* | + | add-verify-skill | 1 left | 2/5 | None | None | Warn | + ``` + + For conflicts, show the resolution: + ```text + * Conflict resolution: + - identity/user-auth spec: Will apply add-oauth then add-jwt (both implemented, chronological order) + ``` + + For incomplete changes, show warnings: + ```text + Warnings: + - add-verify-skill: 1 incomplete artifact, 3 incomplete tasks + ``` + +7. **Confirm batch operation** + + Ask the user a single confirmation question: + + - "Archive N changes?" with options based on status + - Options might include: + - "Archive all N changes" + - "Archive only N ready changes (skip incomplete)" + - "Cancel" + + If there are incomplete changes, make clear they'll be archived with warnings. + + Route on the answer by intent, not by exact label — you wrote these labels, + so match what the user picked rather than the wording above: + - "Cancel" — stop, do not archive. Report that nothing was archived and skip the remaining steps. + - The archive-everything option — proceed with every selected change + - The ready-only option — proceed with only the changes the step 6 table marks `Ready` or `Ready*`, and record the rest as Skipped in step 8d. If a `Ready*` change's conflict partner is skipped, re-derive that conflict's resolution using only the changes being archived. + - Anything else — ask again rather than archiving + + Before step 8 writes the first main spec or moves any change, fetch every + required specs-rule snapshot for the confirmed batch. For each change that will + sync concrete `artifactPaths.specs.existingOutputPaths`, run + `openspec instructions specs --change "" --json` exactly once with the + same selected-root flags. Obtain all snapshots before the first write or move. + If any lookup exits non-zero or returns invalid artifact-instruction JSON, + identify the affected change, report the error, and stop the whole batch before + any main-spec write or change move. Do not treat lookup failure as omitted + rules. A valid response without `rules` is the no-rules case. + +8. **Execute archive for each confirmed change** + + Before processing, carry the recorded decisions from step 5 (after any step 7 re-derivation) into two per-delta sets: + - `includedDeltas`: all non-conflicting delta specs from confirmed changes plus conflict deltas selected for sync + - `excludedDeltas`: conflict deltas from confirmed changes excluded because their implementation is missing + - A single change can have both included and excluded delta specs. Keep the decision per delta; do not collapse it into a per-change sync flag. + + Process changes in the determined order (respecting conflict resolution): + + a. **Sync included delta specs**: + - Run the `/opsx:sync` workflow inline (agent-driven intelligent merge) only for changes with entries in `includedDeltas`, passing only the included delta paths and explicitly instructing it to ignore that change's `excludedDeltas`. Wait for it to finish. + - For conflicts, apply in resolved order. + - Pass that change's fetched specs-rule snapshot into inline sync; inline + sync must reuse it without fetching instructions again + - Apply artifact rules only to main specs produced by that change. They do + not change conflict resolution, archive behavior, or CLI contracts, and + their text is not copied into an output file + - Do not delegate to a background task — step 8c would move `changeRoot` out from under a sync that is still reading it. + - If a change has no included delta specs, do not run the sync workflow for it. + + b. **Verify included delta specs before moving changeRoot**: + - Re-run the comparison only for delta specs in `includedDeltas` against main spec at `/openspec/specs//spec.md` (use the store-aware `planningHome.root` from step 3 status JSON, not a hardcoded repo path). + - Verify that main specs are updated: + - ADDED requirements present + - MODIFIED requirements carrying scenario and description changes named in the delta, with their other scenarios intact + - REMOVED requirements gone — and where this sync retired a capability (removed its last requirement, leaving `## Requirements` empty), its main spec deleted rather than left empty; a spec the sync deliberately kept and reported is also a match + - RENAMED requirements present under the new name and absent under the old one + - Do not verify delta specs in `excludedDeltas`; they are intentionally left unsynced. + - If sync failed or any capability does not match verification, report what differs and fail/skip moving that change's `changeRoot` — do not archive that change. `changeRoot` remains intact. + + c. **Perform the archive**: + + Target name: use the change name as-is when it already starts with a `YYYY-MM-DD-` prefix; otherwise prepend the current date as `YYYY-MM-DD-` (same rule as `openspec archive`). + + ```bash + mkdir -p "/archive" + mv "" "/archive/" + ``` + + d. **Track outcome** for each change: + - Success: archived successfully + - Failed: error during archive or spec verification (record error) + - Skipped: user chose not to archive (if applicable) + - Sync skipped: for every delta in `excludedDeltas`, report `sync skipped` with the change, ``, and recorded reason. This is distinct from skipping the archive. + +9. **Display summary** + + Show final results: + + ```markdown + ## Bulk Archive Complete + + Archived 3 changes: + - schema-management-cli -> archive/2026-01-19-schema-management-cli/ + - project-config -> archive/2026-01-19-project-config/ + - add-oauth -> archive/2026-01-19-add-oauth/ + + Skipped 1 change: + - add-verify-skill (user chose not to archive incomplete) + + Spec sync summary: + - 4 delta specs synced to main specs + - 1 delta spec sync skipped (add-jwt, identity/user-auth: implementation not found) + - 1 conflict resolved (identity/user-auth: synced add-oauth, skipped add-jwt) + ``` + + If any failures: + ```text + Failed 1 change: + - some-change: Archive directory already exists + ``` + +**Conflict Resolution Examples** + +Example 1: Only one implemented +```text +Conflict: /openspec/specs/auth/spec.md touched by [add-oauth, add-jwt] + +Checking add-oauth: +- Delta adds "OAuth Provider Integration" requirement +- Searching codebase... found src/auth/oauth.ts implementing OAuth flow + +Checking add-jwt: +- Delta adds "JWT Token Handling" requirement +- Searching codebase... no JWT implementation found + +Resolution: Only add-oauth is implemented. Will sync add-oauth specs only. +``` + +Example 2: Both implemented +```text +Conflict: /openspec/specs/api/spec.md touched by [add-rest-api, add-graphql] + +Checking add-rest-api (created 2026-01-10): +- Delta adds "REST Endpoints" requirement +- Searching codebase... found src/api/rest.ts + +Checking add-graphql (created 2026-01-15): +- Delta adds "GraphQL Schema" requirement +- Searching codebase... found src/api/graphql.ts + +Resolution: Both implemented. Will apply add-rest-api specs first, +then add-graphql specs (chronological order, newer takes precedence). +``` + +**Output On Success** + +```markdown +## Bulk Archive Complete + +Archived N changes: +- -> archive// +- -> archive// + +Spec sync summary: +- N delta specs synced to main specs +- No conflicts (or: M conflicts resolved) +``` + +**Output On Partial Success** + +```markdown +## Bulk Archive Complete (partial) + +Archived N changes: +- -> archive// + +Skipped M changes: +- (user chose not to archive incomplete) + +Failed K changes: +- : Archive directory already exists +``` + +**Output When No Changes** + +```markdown +## No Changes to Archive + +No active changes found. Create a new change to get started. +``` + +**Guardrails** +- Allow any number of changes (1+ is fine, 2+ is the typical use case) +- Always prompt for selection, never auto-select +- Detect spec conflicts early and resolve by checking codebase +- When both changes are implemented, apply specs in chronological order +- Skip spec sync only when implementation is missing (warn user) +- Show clear per-change status before confirming +- Use single confirmation for entire batch +- Never archive after the user cancels the confirmation — a cancelled batch archives nothing +- Track and report all outcomes (success/skip/fail) +- Preserve .openspec.yaml when moving to archive +- Archive directory target uses current date: YYYY-MM-DD-; a name that already starts with a `YYYY-MM-DD-` prefix is used as-is (never stack a second date) +- If archive target exists, fail that change but continue with others +- If sync is requested, run the `/opsx:sync` workflow inline (agent-driven) for each change with included delta specs +- Carry the per-delta `includedDeltas` and `excludedDeltas` decisions into execution; sync and verify only included deltas +- Report every excluded delta as `sync skipped` without treating the archive itself as skipped +- Never archive a change while a spec sync is still in flight — run the sync inline and verify main specs at `/openspec/specs//spec.md` before moving `changeRoot` +- Fetch archive inputs once per selected root before spec inspection or moves +- Fetch all required specs-rule snapshots before the batch's first main-spec write or move +- A failed archive-inputs lookup never blocks the batch; it proceeds with no context or guidance +- A failed specs instruction lookup stops the whole batch atomically +- Changes without concrete `artifactPaths.specs.existingOutputPaths` continue without spec sync +- Apply relevant runtime context across the batch and report conflicts +- Operation guidance remains advisory; consider every entry and explain rejected advice +- Keep runtime inputs, conflict analysis, CLI-derived values, and artifact rules separate +- Artifact rules constrain only written specs +- Never copy runtime input or artifact-rule text verbatim into output files diff --git a/.claude/commands/opsx/continue.md b/.claude/commands/opsx/continue.md new file mode 100644 index 0000000..814c596 --- /dev/null +++ b/.claude/commands/opsx/continue.md @@ -0,0 +1,114 @@ +--- +name: "OPSX: Continue" +description: "Continue working on a change - create the next artifact (Experimental)" +allowed-tools: Bash(openspec:*) +category: "Workflow" +tags: ["workflow", "artifacts", "experimental"] +--- + +Continue working on a change by creating the next artifact. + +**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. + +**Input**: Optionally specify a change name after `/opsx:continue` (e.g., `/opsx:continue add-auth`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes. + +**Steps** + +1. **Select the change** + + If a name is provided, use it. Otherwise: + - Infer from conversation context if the user mentioned a change + - Auto-select if only one active change exists + - If ambiguous, run `openspec list --json` to get available changes sorted by most recently modified, and ask the user to select one + + When prompting, present the top 3-4 most recently modified changes as options, showing: + - Change name + - Schema (from `schema` field if present, otherwise "spec-driven") + - Status (e.g., "0/5 tasks", "complete", "no tasks") + - How recently it was modified (from `lastModified` field) + + Mark the most recently modified change as "(Recommended)" since it's likely what the user wants to continue. + + Always announce: "Using change: " and how to override (e.g., `/opsx:continue `). + +2. **Check current status** + ```bash + openspec status --change "" --json + ``` + Parse the JSON to understand current state. The response includes: + - `schemaName`: The workflow schema being used (e.g., "spec-driven") + - `artifacts`: Array of artifacts with their status ("done", "skipped", "ready", "blocked") + - `isPlanningComplete`: Boolean indicating if all planning artifacts are complete. Older CLI versions expose the same value as `isComplete`. + - `planningHome`, `changeRoot`, `artifactPaths`, and `actionContext`: path and scope context. Use these instead of assuming repo-local paths. + +3. **Act based on status**: + + --- + + **If all planning artifacts are complete (`isPlanningComplete: true`, or legacy `isComplete: true`)**: + - Congratulate the user + - Show final status including the schema used + - Suggest: "Planning is complete! You can now implement this change with `/opsx:apply`. Once implementation and any tracked work are complete, archive it with `/opsx:archive`." + - STOP + + --- + + **If artifacts are ready to create** (status shows artifacts with `status: "ready"`): + - Pick the FIRST artifact with `status: "ready"` from the status output + - Get its instructions: + ```bash + openspec instructions --change "" --json + ``` + - Parse the JSON. The key fields are: + - `context`: Project background (constraints for you - do NOT include in output) + - `rules`: Artifact-specific rules (constraints for you - do NOT include in output) + - `template`: The structure to use for your output file + - `instruction`: Schema-specific guidance + - `resolvedOutputPath`: Resolved path or pattern to write the artifact + - `dependencies`: Completed artifacts to read for context (entries with `skipped: true` have no files - do not look for them) + - `skipped`/`warning`: present when the change declares skip_specs and this artifact must NOT be created - pick another artifact + - **Create the artifact file**: + - Read any completed dependency files for context - always re-read them from disk, even if you saw them earlier in the conversation (the user may have edited them) + - If the `instruction` field delegates creation to a specific skill or command, invoke it to produce the artifact instead of writing the file yourself, then verify the artifact file exists at `resolvedOutputPath` + - Otherwise use `template` as the structure - fill in its sections + - Apply `context` and `rules` as constraints when writing - but do NOT copy them into the file + - Write to the `resolvedOutputPath` specified in instructions. If it is a glob pattern, choose the concrete file path using the schema instruction and the change's context + - Show what was created and what's now unlocked + - STOP after creating ONE artifact + + --- + + **If no artifacts are ready (all blocked)**: + - This shouldn't happen with a valid schema + - Show status and suggest checking for issues + +4. **After creating an artifact, show progress** + ```bash + openspec status --change "" + ``` + +**Output** + +After each invocation, show: +- Which artifact was created +- Schema workflow being used +- Current progress (N/M complete) +- What artifacts are now unlocked +- Prompt: "Run `/opsx:continue` to create the next artifact" + +**Artifact Creation Guidelines** + +The artifact types and their purpose depend on the schema. The `instruction` field from the instructions output is the authoritative guidance for each artifact - follow it even when the artifact has a familiar name (proposal.md, tasks.md, etc.), since custom schemas may define different content or a different process for the same file names. + +If the `instruction` field directs you to use a specific skill or command to create the artifact, invoke it instead of writing the artifact directly. + +**Guardrails** +- Create ONE artifact per invocation +- Always read dependency artifacts before creating a new one - re-read from disk, not from conversation memory (files may have changed since you last saw them) +- Never skip artifacts or create out of order +- If context is unclear, ask the user before creating +- Verify the artifact file exists after writing before marking progress +- Use the schema's artifact sequence, don't assume specific artifact names +- **IMPORTANT**: `context` and `rules` are constraints for YOU, not content for the file + - Do NOT copy ``, ``, `` blocks into the artifact + - These guide what you write, but should never appear in the output diff --git a/.claude/commands/opsx/ff.md b/.claude/commands/opsx/ff.md new file mode 100644 index 0000000..bd0b77d --- /dev/null +++ b/.claude/commands/opsx/ff.md @@ -0,0 +1,113 @@ +--- +name: "OPSX: Fast Forward" +description: "Create a change and generate all artifacts needed for implementation in one go" +allowed-tools: Bash(openspec:*) +category: "Workflow" +tags: ["workflow", "artifacts", "experimental"] +--- + +Fast-forward through artifact creation - generate everything needed to start implementation. + +**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. + +**Input**: The argument after `/opsx:ff` is the change name (kebab-case), OR a description of what the user wants to build. + +**Steps** + +1. **If no input provided, ask what they want to build** + + Ask the user (open-ended, no preset options): + > "What change do you want to work on? Describe what you want to build or fix." + + From their description, derive a kebab-case name (e.g., "add user authentication" → `add-user-auth`). + + **IMPORTANT**: Do NOT proceed without understanding what the user wants to build. + +2. **Create the change directory** + ```bash + openspec new change "" + ``` + This creates a scaffolded change in the planning home resolved by the CLI. + +3. **Get the artifact build order** + ```bash + openspec status --change "" --json + ``` + Parse the JSON to get: + - `applyRequires`: array of artifact IDs needed before implementation (e.g., `["tasks"]`) + - `artifacts`: list of all artifacts, each with its `status` and its `requires` edges (the artifact IDs it directly depends on) + - `planningHome`, `changeRoot`, `artifactPaths`, and `actionContext`: path and scope context. Use these instead of assuming repo-local paths. + +4. **Create every artifact in the required set** + + Use a todo list to track progress through the artifacts. + + Loop through artifacts in dependency order (artifacts with no pending dependencies first): + + a. **For each artifact that is `ready` (dependencies satisfied)**: + - Get instructions: + ```bash + openspec instructions --change "" --json + ``` + - The instructions JSON includes: + - `context`: Project background (constraints for you - do NOT include in output) + - `rules`: Artifact-specific rules (constraints for you - do NOT include in output) + - `template`: The structure to use for your output file + - `instruction`: Schema-specific guidance for this artifact type + - `skipped`/`warning`: present when the change declares skip_specs and this artifact must NOT be created - stop and pick another artifact + - `resolvedOutputPath`: Resolved path or pattern to write the artifact + - `dependencies`: Completed artifacts to read for context + - Read any completed dependency files for context - always re-read them from disk, even if you saw them earlier in the conversation (the user may have edited them) + - **Inspect the relevant project before drafting**: Read `context` and `rules` first, then inspect relevant implementation, nearby tests, configuration, and documentation outside `openspec/`. Keep inspection read-only and proportional to the change; reuse findings for later artifacts and inspect more only as needed. + - Identify the target project from the request and project context; the planning home may be separate from the code. If the target is unclear, ask. For greenfield or non-code changes, inspect the available structure and relevant documents. If source is unavailable, state the limitation and ask when it materially affects the plan. + - Ground scope, approach, and tasks in what you find. Distinguish observed behavior from assumptions and proposed additions; surface conflicts with existing specs instead of silently deciding which is correct. + - Do this discovery now, rather than leaving generic "explore the codebase" or "make a plan" tasks for implementation. Keep any necessary follow-up investigation specific to an unresolved question. + - If the `instruction` field delegates creation to a specific skill or command, invoke it to produce the artifact instead of writing the file yourself, then verify the artifact file exists at `resolvedOutputPath` + - Otherwise create the artifact file using `template` as the structure and write it to `resolvedOutputPath`. If `resolvedOutputPath` is a glob, follow `instruction` to choose the concrete file path + - Apply `context` and `rules` as constraints - but do NOT copy them into the file + - Show brief progress: "✓ Created " + + b. **Continue until every artifact in the required set exists (not just `apply.requires`)** + - After creating each artifact, re-run `openspec status --change "" --json` + - The required set is `applyRequires` plus every artifact reachable from those by following the `requires` edges in `status --json` - walk them transitively (spec-driven closes over proposal, specs, design, tasks). Leave artifacts outside that set alone + - `status` is file-existence only, so an `applyRequires` artifact reading `done` does NOT mean its dependencies exist - writing `tasks.md` early marks `tasks` done while `specs` was never written. Use each artifact's `requires` edges, not its `status`, to build the required set: a `done` artifact still lists what it depends on + - An artifact already reading `status: "skipped"` is satisfied: the change declares `skip_specs` in `.openspec.yaml`, so its files must NOT exist. Never try to create one + - Create every artifact in the required set that is missing, then re-check - creating one can unblock others + - Skip one only when `status` already reports it `skipped`, or when its own `instruction` says it is conditional: run `openspec instructions --change "" --json` and skip only if its `instruction` field marks it optional (e.g. "create only if..."). Spec-driven's `design.md` qualifies; `specs` qualifies only via the `skipped` status above, never by your own judgment. Tell the user, and do not reconsider it + - Dependencies are enablers, not gates: if a required artifact is still `blocked` only because you skipped a conditional dependency, write it anyway + - Stop when every artifact in the required set is `done`, `skipped`, or was deliberately skipped + + c. **If an artifact requires user input** (unclear context): + - Ask the user to clarify + - Then continue with creation + +5. **Show final status** + ```bash + openspec status --change "" + ``` + +**Output** + +After completing all artifacts, summarize: +- Change name and location +- List of artifacts created with brief descriptions, plus any conditional artifact you skipped and why +- What's ready: "All artifacts needed for implementation are ready." +- Prompt: "Run `/opsx:apply` to start implementing." + +**Artifact Creation Guidelines** + +- Follow the `instruction` field from `openspec instructions` for each artifact type - it is the authoritative guidance, even for familiar artifact names +- If the `instruction` field directs you to use a specific skill or command to create the artifact, invoke it instead of writing the artifact directly +- The schema defines what each artifact should contain - follow it +- Read dependency artifacts for context before creating new ones +- Use `template` as the structure for your output file - fill in its sections +- **IMPORTANT**: `context` and `rules` are constraints for YOU, not content for the file + - Do NOT copy ``, ``, `` blocks into the artifact + - These guide what you write, but should never appear in the output + +**Guardrails** +- Create every artifact the apply phase transitively depends on, not just the ids listed in `apply.requires` +- Always read dependency artifacts before creating a new one - re-read from disk, not from conversation memory (files may have changed since you last saw them) +- If context is critically unclear, ask the user - but prefer making reasonable decisions to keep momentum +- If a change with that name already exists, ask if user wants to continue it or create a new one +- Verify each artifact file exists after writing before proceeding to next diff --git a/.claude/commands/opsx/new.md b/.claude/commands/opsx/new.md new file mode 100644 index 0000000..dd726bd --- /dev/null +++ b/.claude/commands/opsx/new.md @@ -0,0 +1,72 @@ +--- +name: "OPSX: New" +description: "Start a new change using the experimental artifact workflow (OPSX)" +allowed-tools: Bash(openspec:*) +category: "Workflow" +tags: ["workflow", "artifacts", "experimental"] +--- + +Start a new change using the experimental artifact-driven approach. + +**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. + +**Input**: The argument after `/opsx:new` is the change name (kebab-case), OR a description of what the user wants to build. + +**Steps** + +1. **If no input provided, ask what they want to build** + + Ask the user (open-ended, no preset options): + > "What change do you want to work on? Describe what you want to build or fix." + + From their description, derive a kebab-case name (e.g., "add user authentication" → `add-user-auth`). + + **IMPORTANT**: Do NOT proceed without understanding what the user wants to build. + +2. **Determine the workflow schema** + + Use the default schema (omit `--schema`) unless the user explicitly requests a different workflow. + + **Use a different schema only if the user mentions:** + - A specific schema name → use `--schema ` + - "show workflows" or "what workflows" → run `openspec schemas --json` and let them choose + + **Otherwise**: Omit `--schema` to use the default. + +3. **Create the change directory** + ```bash + openspec new change "" + ``` + Add `--schema ` only if the user requested a specific workflow. + This creates a scaffolded change in the planning home resolved by the CLI. + +4. **Show the artifact status** + ```bash + openspec status --change "" --json + ``` + Use the returned `planningHome`, `changeRoot`, `artifactPaths`, and `nextSteps` instead of assuming repo-local paths. + +5. **Get instructions for the first artifact** + The first artifact depends on the schema. Check the status output to find the first artifact with status "ready". + ```bash + openspec instructions --change "" + ``` + This outputs the template and context for creating the first artifact. + +6. **STOP and wait for user direction** + +**Output** + +After completing the steps, summarize: +- Change name and location +- Schema/workflow being used and its artifact sequence +- Current status (0/N artifacts complete) +- The template for the first artifact +- Prompt: "Ready to create the first artifact? Run `/opsx:continue` or just describe what this change is about and I'll draft it." + +**Guardrails** +- Do NOT create any artifacts yet - just show the instructions +- Do NOT advance beyond showing the first artifact template +- If the name is invalid (not kebab-case), ask for a valid name +- If a change with that name already exists, suggest using `/opsx:continue` instead +- Pass --schema if using a non-default workflow diff --git a/.claude/commands/opsx/onboard.md b/.claude/commands/opsx/onboard.md new file mode 100644 index 0000000..21ecb86 --- /dev/null +++ b/.claude/commands/opsx/onboard.md @@ -0,0 +1,557 @@ +--- +name: "OPSX: Onboard" +description: "Guided onboarding - walk through a complete OpenSpec workflow cycle with narration" +allowed-tools: Bash(openspec:*) +category: "Workflow" +tags: ["workflow", "onboarding", "tutorial", "learning"] +--- + +Guide the user through their first complete OpenSpec workflow cycle. This is a teaching experience—you'll do real work in their codebase while explaining each step. + +**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. + +--- + +## Preflight + +Before starting, check if the OpenSpec CLI is installed: + +```bash +# Unix/macOS +openspec --version 2>&1 || echo "CLI_NOT_INSTALLED" +# Windows (PowerShell) +# if (Get-Command openspec -ErrorAction SilentlyContinue) { openspec --version } else { echo "CLI_NOT_INSTALLED" } +``` + +**If CLI not installed:** +> OpenSpec CLI is not installed. Install it first, then come back to `/opsx:onboard`. + +Stop here if not installed. + +--- + +## Phase 1: Welcome + +Display: + +``` +## Welcome to OpenSpec! + +I'll walk you through a complete change cycle—from idea to implementation—using a real task in your codebase. Along the way, you'll learn the workflow by doing it. + +**What we'll do:** +1. Pick a small, real task in your codebase +2. Explore the problem briefly +3. Create a change (the container for our work) +4. Build the artifacts: proposal → specs → design → tasks +5. Implement the tasks +6. Archive the completed change + +**Time:** ~15-20 minutes + +Let's start by finding something to work on. +``` + +--- + +## Phase 2: Task Selection + +### Codebase Analysis + +Scan the codebase for small improvement opportunities. Look for: + +1. **TODO/FIXME comments** - Search for `TODO`, `FIXME`, `HACK`, `XXX` in code files +2. **Missing error handling** - `catch` blocks that swallow errors, risky operations without try-catch +3. **Functions without tests** - Cross-reference `src/` with test directories +4. **Type issues** - `any` types in TypeScript files (`: any`, `as any`) +5. **Debug artifacts** - `console.log`, `console.debug`, `debugger` statements in non-debug code +6. **Missing validation** - User input handlers without validation + +Also check recent git activity: +```bash +# Unix/macOS +git log --oneline -10 2>/dev/null || echo "No git history" +# Windows (PowerShell) +# git log --oneline -10 2>$null; if ($LASTEXITCODE -ne 0) { echo "No git history" } +``` + +### Present Suggestions + +From your analysis, present 3-4 specific suggestions: + +``` +## Task Suggestions + +Based on scanning your codebase, here are some good starter tasks: + +**1. [Most promising task]** + Location: `src/path/to/file.ts:42` + Scope: ~1-2 files, ~20-30 lines + Why it's good: [brief reason] + +**2. [Second task]** + Location: `src/another/file.ts` + Scope: ~1 file, ~15 lines + Why it's good: [brief reason] + +**3. [Third task]** + Location: [location] + Scope: [estimate] + Why it's good: [brief reason] + +**4. Something else?** + Tell me what you'd like to work on. + +Which task interests you? (Pick a number or describe your own) +``` + +**If nothing found:** Fall back to asking what the user wants to build: +> I didn't find obvious quick wins in your codebase. What's something small you've been meaning to add or fix? + +### Scope Guardrail + +If the user picks or describes something too large (major feature, multi-day work): + +``` +That's a valuable task, but it's probably larger than ideal for your first OpenSpec run-through. + +For learning the workflow, smaller is better—it lets you see the full cycle without getting stuck in implementation details. + +**Options:** +1. **Slice it smaller** - What's the smallest useful piece of [their task]? Maybe just [specific slice]? +2. **Pick something else** - One of the other suggestions, or a different small task? +3. **Do it anyway** - If you really want to tackle this, we can. Just know it'll take longer. + +What would you prefer? +``` + +Let the user override if they insist—this is a soft guardrail. + +--- + +## Phase 3: Explore Demo + +Once a task is selected, briefly demonstrate explore mode: + +``` +Before we create a change, let me quickly show you **explore mode**—it's how you think through problems before committing to a direction. +``` + +Spend 1-2 minutes investigating the relevant code: +- Read the file(s) involved +- Draw a quick ASCII diagram if it helps +- Note any considerations + +``` +## Quick Exploration + +[Your brief analysis—what you found, any considerations] + +┌─────────────────────────────────────────┐ +│ [Optional: ASCII diagram if helpful] │ +└─────────────────────────────────────────┘ + +Explore mode (`/opsx:explore`) is for this kind of thinking—investigating before implementing. You can use it anytime you need to think through a problem. + +Now let's create a change to hold our work. +``` + +**PAUSE** - Wait for user acknowledgment before proceeding. + +--- + +## Phase 4: Create the Change + +**EXPLAIN:** +``` +## Creating a Change + +A "change" in OpenSpec is a container for all the thinking and planning around a piece of work. It lives at the `changeRoot` reported by `openspec status --change "" --json` and holds your artifacts—proposal, specs, design, tasks. + +Let me create one for our task. +``` + +**DO:** Create the change with a derived kebab-case name: +```bash +openspec new change "" +``` + +**SHOW:** +``` +Created: + +The folder structure: +``` +/ +├── proposal.md ← Why we're doing this (empty, we'll fill it) +├── design.md ← How we'll build it (empty) +├── specs/ ← Detailed requirements (empty) +└── tasks.md ← Implementation checklist (empty) +``` + +Now let's fill in the first artifact—the proposal. +``` + +--- + +## Phase 5: Proposal + +**EXPLAIN:** +``` +## The Proposal + +The proposal captures **why** we're making this change and **what** it involves at a high level. It's the "elevator pitch" for the work. + +I'll draft one based on our task. +``` + +**DO:** Draft the proposal content (don't save yet): + +`` is the spec directory relative to `specs/` (for example, +`user-auth` or `identity/user-auth`). Use the exact existing path for modified +capabilities. For new capabilities, follow the project's established spec +organization. + +``` +Here's a draft proposal: + +--- + +## Why + +[1-2 sentences explaining the problem/opportunity] + +## What Changes + +[Bullet points of what will be different] + +## Capabilities + +### New Capabilities +- ``: [brief description] + +### Modified Capabilities + +- ``: [brief description] + +## Impact + +- `src/path/to/file.ts`: [what changes] +- [other files if applicable] + +--- + +Does this capture the intent? I can adjust before we save it. +``` + +**PAUSE** - Wait for user approval/feedback. + +After approval, save the proposal: +```bash +openspec instructions proposal --change "" --json +``` +Then write the content to the `resolvedOutputPath` from `openspec instructions proposal --change "" --json`. + +``` +Proposal saved. This is your "why" document—you can always come back and refine it as understanding evolves. + +Next up: specs. +``` + +--- + +## Phase 6: Specs + +**EXPLAIN:** +``` +## Specs + +Specs define **what** we're building in precise, testable terms. They use a requirement/scenario format that makes expected behavior crystal clear. + +For a small task like this, we might only need one spec file. +``` + +**DO:** Resolve where the spec file should be created: +```bash +openspec instructions specs --change "" --json +# Use resolvedOutputPath from the JSON. If it is a glob, choose the concrete file path using the schema instruction and the change's context. +``` + +Draft the spec content: + +``` +Here's the spec: + +--- + +## ADDED Requirements + +### Requirement: + + + +#### Scenario: + +- **WHEN** +- **THEN** +- **AND** + +--- + +This format—WHEN/THEN/AND—makes requirements testable. You can literally read them as test cases. +``` + +Save to the concrete file path chosen from `resolvedOutputPath`. + +--- + +## Phase 7: Design + +**EXPLAIN:** +``` +## Design + +The design captures **how** we'll build it—technical decisions, tradeoffs, approach. + +For small changes, this might be brief. That's fine—not every change needs deep design discussion. +``` + +**DO:** Draft design.md: + +``` +Here's the design: + +--- + +## Context + +[Brief context about the current state] + +## Goals / Non-Goals + +**Goals:** +- [What we're trying to achieve] + +**Non-Goals:** +- [What's explicitly out of scope] + +## Decisions + +### Decision 1: [Key decision] + +[Explanation of approach and rationale] + +--- + +For a small task, this captures the key decisions without over-engineering. +``` + +Save to the `resolvedOutputPath` from `openspec instructions design --change "" --json`. + +--- + +## Phase 8: Tasks + +**EXPLAIN:** +``` +## Tasks + +Finally, we break the work into implementation tasks—checkboxes that drive the apply phase. + +These should be small, clear, and in logical order. +``` + +**DO:** Generate tasks based on specs and design: + +``` +Here are the implementation tasks: + +--- + +## 1. [Category or file] + +- [ ] 1.1 [Specific task] — verify: [test, command, observable behavior, or delivered artifact] +- [ ] 1.2 [Specific task] — verify: [test, command, observable behavior, or delivered artifact] + +## 2. Integration Verification + +- [ ] 2.1 Verify [broader integration or system behavior] with [end-to-end test or observable result] + +--- + +Each checkbox becomes a unit of work in the apply phase. Ready to implement? +``` + +**PAUSE** - Wait for user to confirm they're ready to implement. + +Save to the `resolvedOutputPath` from `openspec instructions tasks --change "" --json`. + +--- + +## Phase 9: Apply (Implementation) + +**EXPLAIN:** +``` +## Implementation + +Now we implement each task, checking them off as we go. I'll announce each one and occasionally note how the specs/design informed the approach. +``` + +**DO:** For each task: + +1. Announce: "Working on task N: [description]" +2. Implement the change in the codebase +3. Reference specs/design naturally: "The spec says X, so I'm doing Y" +4. Mark complete in tasks.md: `- [ ]` → `- [x]` +5. Brief status: "✓ Task N complete" + +Keep narration light—don't over-explain every line of code. + +After all tasks: + +``` +## Implementation Complete + +All tasks done: +- [x] Task 1 +- [x] Task 2 +- [x] ... + +The change is implemented! One more step—let's archive it. +``` + +--- + +## Phase 10: Archive + +**EXPLAIN:** +``` +## Archiving + +When a change is complete, we archive it. The archive path is derived from `planningHome.changesDir` and the date. + +Archived changes become your project's decision history—you can always find them later to understand why something was built a certain way. +``` + +**DO:** Archive the change (`--yes` answers the confirmation prompts, which you cannot answer from a tool call): +```bash +openspec archive "" --yes +``` + +**SHOW:** +``` +Archived to: `/archive//` (the target name prepends today's date, unless the name already starts with a `YYYY-MM-DD-` prefix — then it is kept as-is, no second date) + +The change is now part of your project's history. The code is in your codebase, the decision record is preserved. +``` + +--- + +## Phase 11: Recap & Next Steps + +``` +## Congratulations! + +You just completed a full OpenSpec cycle: + +1. **Explore** - Thought through the problem +2. **New** - Created a change container +3. **Proposal** - Captured WHY +4. **Specs** - Defined WHAT in detail +5. **Design** - Decided HOW +6. **Tasks** - Broke it into steps +7. **Apply** - Implemented the work +8. **Archive** - Preserved the record + +This same rhythm works for any size change—a small fix or a major feature. + +--- + +## Command Reference + +**Core workflow:** + + | Command | What it does | + |-------------------|--------------------------------------------| + | `/opsx:propose` | Create a change and generate all artifacts | + | `/opsx:explore` | Think through problems before/during work | + | `/opsx:apply` | Implement tasks from a change | + | `/opsx:archive` | Archive a completed change | + +**Additional commands** (only if installed - availability depends on your profile): + + | Command | What it does | + |--------------------|----------------------------------------------------------| + | `/opsx:new` | Start a new change, step through artifacts one at a time | + | `/opsx:continue` | Continue working on an existing change | + | `/opsx:ff` | Fast-forward: create all artifacts at once | + | `/opsx:verify` | Verify implementation matches artifacts | + +--- + +## What's Next? + +Try `/opsx:propose` on something you actually want to build. You've got the rhythm now! +``` + +--- + +## Graceful Exit Handling + +### User wants to stop mid-way + +If the user says they need to stop, want to pause, or seem disengaged: + +``` +No problem! Your change is saved at the `changeRoot` reported by `openspec status --change "" --json`. + +To pick up where we left off later: +- `/opsx:continue ` - Resume artifact creation (if installed; otherwise `openspec status --change "" --json` shows the next artifact) +- `/opsx:apply ` - Jump to implementation (if tasks exist) + +The work won't be lost. Come back whenever you're ready. +``` + +Exit gracefully without pressure. + +### User just wants command reference + +If the user says they just want to see the commands or skip the tutorial: + +``` +## OpenSpec Quick Reference + +**Core workflow:** + + | Command | What it does | + |--------------------------|--------------------------------------------| + | `/opsx:propose ` | Create a change and generate all artifacts | + | `/opsx:explore` | Think through problems (no code changes) | + | `/opsx:apply ` | Implement tasks | + | `/opsx:archive ` | Archive when done | + +**Additional commands** (only if installed - availability depends on your profile): + + | Command | What it does | + |---------------------------|-------------------------------------| + | `/opsx:new ` | Start a new change, step by step | + | `/opsx:continue ` | Continue an existing change | + | `/opsx:ff ` | Fast-forward: all artifacts at once | + | `/opsx:verify ` | Verify implementation | + +Try `/opsx:propose` to start your first change. +``` + +Exit gracefully. + +--- + +## Guardrails + +- **Follow the EXPLAIN → DO → SHOW → PAUSE pattern** at key transitions (after explore, after proposal draft, after tasks, after archive) +- **Keep narration light** during implementation—teach without lecturing +- **Don't skip phases** even if the change is small—the goal is teaching the workflow +- **Pause for acknowledgment** at marked points, but don't over-pause +- **Handle exits gracefully**—never pressure the user to continue +- **Use real codebase tasks**—don't simulate or use fake examples +- **Adjust scope gently**—guide toward smaller tasks but respect user choice diff --git a/.claude/commands/opsx/sync.md b/.claude/commands/opsx/sync.md new file mode 100644 index 0000000..2dd4cc3 --- /dev/null +++ b/.claude/commands/opsx/sync.md @@ -0,0 +1,258 @@ +--- +name: "OPSX: Sync" +description: "Sync delta specs from a change to main specs" +allowed-tools: Bash(openspec:*) +category: "Workflow" +tags: ["workflow", "specs", "experimental"] +--- + +Sync delta specs from a change to main specs. + +This is an **agent-driven** operation - you will read delta specs and directly edit main specs to apply the changes. This allows intelligent merging (e.g., adding a scenario without copying the entire requirement). + +**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. + +`` is the spec directory relative to `specs/` (for example, `user-auth` or `identity/user-auth`). Preserve the full path from each delta spec when resolving its main spec. + +**Input**: Optionally specify a change name after `/opsx:sync` (e.g., `/opsx:sync add-auth`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes. + +**Steps** + +1. **Select the change** + + If a name is provided, use it. Otherwise: + - Infer from conversation context if the user mentioned a change + - Auto-select if only one active change exists + - If ambiguous, run `openspec list --json` to get available changes and ask the user to select one + + When prompting, show changes that have delta specs (under `specs/` directory). + + Always announce: "Using change: " and how to override (e.g., `/opsx:sync `). + +2. **Resolve change context** + + Run: + ```bash + openspec status --change "" --json + ``` + + The JSON includes `planningHome.root`. Main specs live under `/openspec/specs/` — use that (store-aware) root for every main-spec path below, not a hardcoded repo path. When a store is selected it points at the store, not the current repository. + +3. **Find delta specs** + + Use `artifactPaths.specs.existingOutputPaths` from the status JSON as the + only source of delta spec paths. If the `specs` entry is missing or + `existingOutputPaths` is empty, report that there are no delta specs to sync, + do not infer them from other artifacts, and stop without requesting artifact + instructions or writing a main spec. + + Sync every path in `existingOutputPaths` unless the caller narrowed the set. + A caller narrows it by naming an explicit list of complete entries from + `existingOutputPaths` — copy those absolute values verbatim. Archive does + this inline, and a user can too (for example, by selecting the entry ending + in `/specs/billing/invoices/spec.md`). + Then sync only the named paths and leave the remaining delta specs untouched: + bulk archive excludes a delta whose implementation it could not find, and + syncing it anyway would write a main spec the caller deliberately withheld. + Carry that narrowed selection through step 4; never widen it back to the full + list. If a named path is not in `existingOutputPaths`, do not sync it — + report it and stop, rather than dropping it silently. If the named list is + empty, report that there is nothing to sync and stop without writing a main + spec. + + Each delta spec file contains sections like: + - `## ADDED Requirements` - New requirements to add + - `## MODIFIED Requirements` - Changes to existing requirements + - `## REMOVED Requirements` - Requirements to remove + - `## RENAMED Requirements` - Requirements to rename (FROM:/TO: format) + + If no delta specs found, inform user and stop. + +4. **For each delta spec, apply changes to main specs** + + Before the first main-spec write, obtain one current specs-rule snapshot: + - If archive invoked this workflow inline and supplied a valid snapshot from + `openspec instructions specs --change "" --json`, reuse it and do not + fetch the same instructions again. + - Otherwise run that command once now with the same selected-root flags. + - If the direct lookup exits non-zero or returns invalid artifact-instruction + JSON, report the error and stop before writing any main spec. Do not treat the + failure as an absent rule set. + - A valid response with omitted `rules` means no artifact rules are configured + and the existing semantic merge continues. + + Apply returned `rules` only to the content and form of the main specs produced + by this merge. Artifact rules are not operation guidance and cannot change + selected roots, delta paths, CLI checks, or workflow steps. Use their text as + constraints without copying it verbatim into a main spec or summary. + + For each capability delta spec path selected in step 3 — the full `existingOutputPaths` list, or the narrowed subset when a caller supplied one (these may belong to a selected store, not the repo): + + a. **Read the delta spec** to understand the intended changes + + b. **Read the main spec** at `/openspec/specs//spec.md` (may not exist yet) + + c. **Apply changes intelligently**: + + **ADDED Requirements:** + - If requirement doesn't exist in main spec → add it + - If requirement already exists → update it to match (treat as implicit MODIFIED) + + **MODIFIED Requirements:** + - Find the requirement in main spec + - Apply the changes - this can be: + - Adding new scenarios the main spec does not have yet + - Modifying existing scenarios + - Changing the requirement description + - Preserve scenarios/content not mentioned in the delta + + **REMOVED Requirements:** + - Remove the entire requirement block from main spec + - Retiring the capability. Delete the whole `spec.md` - and the directory once + nothing else is left in it - only when ALL of these hold: + 1. removing the requirements *this run* left no requirement blocks; + 2. the rest of the spec is well-formed (it still has a `## Purpose`); + 3. the main spec was not already empty before this sync - if you removed + nothing, change nothing; + 4. every other nonblank line in the whole file is accounted for as the + title, Purpose, Requirements header, or a canonical requirement's + statement, scenarios, or fenced examples; + 5. the change's `.openspec.yaml` declares `retire_capabilities: true`; + 6. the `spec.md` resolves inside the real specs root (do not follow a + capability-directory symlink to delete an external file). + If removing the selected requirements would leave no requirement blocks and + any retirement condition is not satisfied, do not modify the main spec. Stop + the sync for that capability, report the blocking condition, and tell the user + how to resolve it. Never write or leave an empty `## Requirements` section. + When only the marker is missing, say that too - it is the one thing the user + can add to make the retirement go through. + - Deleting the file also deletes its `## Purpose`; any other section blocks + retirement. Name Purpose when you report the retirement. Include a pasteable + `git checkout` only when the spec lived in the caller's checkout; + otherwise give checkout-scoped recovery guidance. + + **RENAMED Requirements:** + - Find the FROM requirement, rename to TO + + **`## Purpose` in the delta:** + - The main spec already has one and it is authoritative - leave it alone + (this is what `openspec archive` does; it warns and moves on) + + d. **Create new main spec** if capability doesn't exist yet: + - Create `/openspec/specs//spec.md` + - Add Purpose section: copy the delta's `## Purpose` body verbatim when it has one + (this is what `openspec archive` does); only write a brief TBD placeholder when it does not + - Add Requirements section with the ADDED requirements + - Follow the **Main Spec Format Reference** below + +5. **Validate updated main specs** + + Run `openspec validate --specs` with the same selected-root flags used earlier. + If validation fails, report the problems and do not claim the sync succeeded. + +6. **Show summary** + + After applying all changes, summarize: + - Which capabilities were updated + - What changes were made (requirements added/modified/removed/renamed) + - Any new main spec left with a TBD Purpose placeholder, so it gets written + now rather than lingering + - Any capability retired, naming the deleted `spec.md`, its Purpose, and + either a pasteable `git checkout` or checkout-scoped recovery guidance + +**Delta Spec Format Reference** + +```markdown +## Purpose + +Only on a delta that introduces a brand-new capability. Seeds the new main spec. + +## ADDED Requirements + +### Requirement: New Feature +The system SHALL do something new. + +#### Scenario: Basic case +- **WHEN** user does X +- **THEN** system does Y + +## MODIFIED Requirements + +### Requirement: Existing Feature +The system SHALL keep doing the existing thing, now also handling A. + +#### Scenario: Scenario the main spec already has +- **WHEN** user does X +- **THEN** system does Y + +#### Scenario: New scenario to add +- **WHEN** user does A +- **THEN** system does B + +## REMOVED Requirements + +### Requirement: Deprecated Feature + +## RENAMED Requirements + +- FROM: `### Requirement: Old Name` +- TO: `### Requirement: New Name` +``` + +**Main Spec Format Reference** + +Main specs are what the delta merges INTO. They must never contain delta operation headers (`## ADDED/MODIFIED/REMOVED/RENAMED Requirements`) - after syncing, every requirement lives under a single `## Requirements` section: + +```markdown +# Specification + +## Purpose +Short description of what this capability does and why it exists. + +## Requirements + +### Requirement: New Feature +The system SHALL do something new. + +#### Scenario: Basic case +- **WHEN** user does X +- **THEN** system does Y +``` + +**Key Principle: Intelligent Merging** + +Unlike programmatic merging, you merge rather than overwrite: +- A MODIFIED block carries the whole requirement - body plus every scenario that survives the change. `openspec validate` and `openspec archive` both reject one that drops a scenario the main spec still has. +- Keep anything the delta does not mention, in the main spec's existing order +- Use your judgment to merge changes sensibly + +**Output On Success** + +```markdown +## Specs Synced: + +Updated main specs: + +****: +- Added requirement: "New Feature" +- Modified requirement: "Existing Feature" (added 1 scenario) + +****: +- Created new spec file +- Added requirement: "Another Feature" + +Main specs are now updated. The change remains active - archive when implementation is complete. +``` + +**Guardrails** +- Read both delta and main specs before making changes +- Preserve existing content not mentioned in delta +- Never copy a delta file into a main spec as-is - merge its content so the main spec keeps the Main Spec Format Reference structure, with no delta operation headers +- If something is unclear, ask for clarification +- Show what you're changing as you go +- The operation should be idempotent - running twice should give same result +- Use only `artifactPaths.specs.existingOutputPaths`; never infer delta specs from unrelated artifacts +- Honor a caller-supplied subset of `existingOutputPaths`; never widen it back to the full list +- Fetch specs instructions once for direct sync, or reuse the archive-supplied snapshot inline +- Stop before every main-spec write on a non-zero or invalid JSON specs-instruction response +- Artifact rules constrain only the specs being written and are never copied into output files diff --git a/.claude/commands/opsx/update.md b/.claude/commands/opsx/update.md new file mode 100644 index 0000000..7992927 --- /dev/null +++ b/.claude/commands/opsx/update.md @@ -0,0 +1,87 @@ +--- +name: "OPSX: Update" +description: "Update a change - revise existing planning artifacts and keep them coherent (Experimental)" +allowed-tools: Bash(openspec:*) +category: "Workflow" +tags: ["workflow", "artifacts", "experimental"] +--- + +Revise a change's existing planning artifacts and keep them coherent. Never edit code. + +**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. + +**Input**: Optionally specify a change name after `/opsx:update` (e.g., `/opsx:update add-auth`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes. + +`/opsx:continue` is an optional workflow and may not be installed. Before suggesting it anywhere below, verify that it is available. If it is unavailable, `openspec status --change "" --json` shows the next artifact and `openspec instructions "" --change "" --json` explains how to create it. + +**Steps** + +1. **Select the change** + + If a name is provided, use it. Otherwise: + - Infer from conversation context if the user mentioned a change + - Auto-select if only one active change exists + - If ambiguous, run `openspec list --json` to get available changes sorted by most recently modified, and ask the user to select one + + When prompting, present the top 3-4 most recently modified changes as options, showing: + - Change name + - Schema (from `schema` field if present, otherwise "spec-driven") + - Status (e.g., "0/5 tasks", "complete", "no tasks") + - How recently it was modified (from `lastModified` field) + + Mark the most recently modified change as "(Recommended)" since it's likely what the user wants to update. + + Always announce: "Using change: " and how to override (e.g., `/opsx:update `). + +2. **Get the change's artifacts** + ```bash + openspec status --change "" --json + ``` + Parse the JSON to understand current state. The response includes: + - `schemaName`: The workflow schema being used (e.g., "spec-driven") + - `artifacts`: Array of artifacts with their status ("done", "skipped", "ready", "blocked") + - `isPlanningComplete`: Boolean indicating if all planning artifacts are complete. Older CLI versions expose the same value as `isComplete`. + - `planningHome`, `changeRoot`, `artifactPaths`, and `actionContext`: path and scope context. Use these instead of assuming repo-local paths. + + The artifact ids and paths come from the active schema - do NOT assume them, and do NOT branch on hardcoded artifact names. Custom schemas must work unchanged. + + The files to edit are `artifactPaths..existingOutputPaths` - the concrete files that exist on disk, already glob-expanded for glob artifacts (e.g. `specs/**/*.md`). Do NOT write to `resolvedOutputPath`: for a glob artifact it is still the glob pattern, not a real file. + +3. **Understand the request** + - If the user asked for a specific revision ("the design now uses X"), that is the starting edit. + - If they only said "update" / "make this coherent", treat it as a coherence review: read the existing artifacts and check them against each other for contradictions, gaps, and duplication. + +4. **Read and reconcile** + - Read the artifact(s) the request touches and the change's other existing artifacts. + - Apply the requested edit. Then check every other existing artifact against it - in ANY direction: an edit to a later artifact may require revising an earlier one, not only the other way around. Build order is a useful reading order, not a constraint on which artifacts may be revised. + - Note everything that is now inconsistent, missing, or contradictory. + - Revise only files that already exist (`existingOutputPaths`). Do NOT create artifacts that don't exist yet, and do NOT invent new files under a glob artifact - note them and point the user to `/opsx:continue` to create them. + - If the change is already coherent, say so and make no edits. + +5. **Confirm and apply, one artifact at a time** + - Show each proposed revision and why. Write only after the user confirms. + - If the user rejects a revision, do not write it - leave that artifact unchanged. + - When a substantial rewrite is needed, get that artifact's rules and template first: + ```bash + openspec instructions "" --change "" --json + ``` + +6. **Point to the next step (guidance only - NEVER act on it)** + - Artifacts still missing -> suggest `/opsx:continue` to create them. + - Change already implemented (tasks checked off / already applied) -> the code may no longer match the revised plan; suggest `/opsx:apply` to carry the delta into code. + - Everything done and implemented -> suggest `/opsx:archive`. + +**Output** + +After each invocation, show: +- Which artifacts were revised (and which proposed revisions were rejected) +- Anything deferred to `/opsx:continue` (not-yet-created artifacts or files) +- Where the change stands and the recommended next command + +**Guardrails** +- Planning artifacts only - NEVER edit implementation code. If the revised plan implies code changes, stop and point to `/opsx:apply`. +- Use the artifact ids and paths reported by `openspec status`; never branch on hardcoded artifact names. +- Edit only the concrete files in `existingOutputPaths`; never write to a glob `resolvedOutputPath`. +- Do not advance the build frontier: no new artifacts, no new files under glob artifacts - that is `/opsx:continue`'s job. +- Confirm every edit with the user before writing. +- If the request changes the change's *intent* rather than refining it, first verify whether the optional `/opsx:new` workflow is available. If it is, recommend starting fresh with `/opsx:new` (the "Update vs. Start Fresh" heuristic). If it is unavailable, ask for a distinct unused change name and recommend `openspec new change ""` instead. diff --git a/.claude/commands/opsx/verify.md b/.claude/commands/opsx/verify.md new file mode 100644 index 0000000..ad48197 --- /dev/null +++ b/.claude/commands/opsx/verify.md @@ -0,0 +1,171 @@ +--- +name: "OPSX: Verify" +description: "Verify implementation matches change artifacts before archiving" +allowed-tools: Bash(openspec:*) +category: "Workflow" +tags: ["workflow", "verify", "experimental"] +--- + +Verify that an implementation matches the change artifacts (specs, tasks, design). + +**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. + +**Input**: Optionally specify a change name after `/opsx:verify` (e.g., `/opsx:verify add-auth`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes. + +**Steps** + +1. **Select the change** + + If a name is provided, use it. Otherwise: + - Infer from conversation context if the user mentioned a change + - Auto-select if only one active change exists + - If ambiguous, run `openspec list --json` to get available changes and ask the user to select one + + When prompting, show changes that have implementation tasks (tasks artifact exists). + Include the schema used for each change if available. + Mark changes with incomplete tasks as "(In Progress)". + + Always announce: "Using change: " and how to override (e.g., `/opsx:verify `). + +2. **Check status to understand the schema** + ```bash + openspec status --change "" --json + ``` + Parse the JSON to understand: + - `schemaName`: The workflow being used (e.g., "spec-driven") + - `planningHome`, `changeRoot`, `artifactPaths`, and `actionContext`: path and scope context + - Which artifacts exist for this change + +3. **Get planning context and load artifacts** + + ```bash + openspec instructions apply --change "" --json + ``` + + This returns the change directory and `contextFiles` (artifact ID -> array of concrete file paths). Read all available artifacts from `contextFiles`. + +4. **Initialize verification report structure** + + Create a report structure with three dimensions: + - **Completeness**: Track tasks and spec coverage + - **Correctness**: Track requirement implementation and scenario coverage + - **Coherence**: Track design adherence and pattern consistency + + Each dimension can have CRITICAL, WARNING, or SUGGESTION issues. + +5. **Verify Completeness** + + **Task Completion**: + - If `contextFiles.tasks` exists, read every file path in it + - Parse checkboxes: `- [ ]` (incomplete) vs `- [x]` (complete) + - Count complete vs total tasks + - If incomplete tasks exist: + - Add CRITICAL issue for each incomplete task + - Recommendation: "Complete task: " or "Mark as done if already implemented" + + **Spec Coverage**: + - If delta specs exist in `contextFiles.specs`: + - Extract all requirements (marked with "### Requirement:") + - For each requirement: + - Search codebase for keywords related to the requirement + - Assess if implementation likely exists + - If requirements appear unimplemented: + - Add CRITICAL issue: "Requirement not found: " + - Recommendation: "Implement requirement X: " + +6. **Verify Correctness** + + **Requirement Implementation Mapping**: + - For each requirement from delta specs: + - Search codebase for implementation evidence + - If found, note file paths and line ranges + - Assess if implementation matches requirement intent + - If divergence detected: + - Add WARNING: "Implementation may diverge from spec:
" + - Recommendation: "Review : against requirement X" + + **Scenario Coverage**: + - For each scenario in delta specs (marked with "#### Scenario:"): + - Check if conditions are handled in code + - Check if tests exist covering the scenario + - If scenario appears uncovered: + - Add WARNING: "Scenario not covered: " + - Recommendation: "Add test or implementation for scenario: " + +7. **Verify Coherence** + + **Design Adherence**: + - If `contextFiles.design` exists: + - Extract key decisions (look for sections like "Decision:", "Approach:", "Architecture:") + - Verify implementation follows those decisions + - If contradiction detected: + - Add WARNING: "Design decision not followed: " + - Recommendation: "Update implementation or revise design.md to match reality" + - If no design.md: Skip design adherence check, note "No design.md to verify against" + + **Code Pattern Consistency**: + - Review new code for consistency with project patterns + - Check file naming, directory structure, coding style + - If significant deviations found: + - Add SUGGESTION: "Code pattern deviation:
" + - Recommendation: "Consider following project pattern: " + +8. **Generate Verification Report** + + **Summary Scorecard**: + ```markdown + ## Verification Report: + + ### Summary + | Dimension | Status | + |--------------|------------------| + | Completeness | X/Y tasks, N reqs| + | Correctness | M/N reqs covered | + | Coherence | Followed/Issues | + ``` + + **Issues by Priority**: + + 1. **CRITICAL** (Must fix before archive): + - Incomplete tasks + - Missing requirement implementations + - Each with specific, actionable recommendation + + 2. **WARNING** (Should fix): + - Spec/design divergences + - Missing scenario coverage + - Each with specific recommendation + + 3. **SUGGESTION** (Nice to fix): + - Pattern inconsistencies + - Minor improvements + - Each with specific recommendation + + **Final Assessment**: + - If CRITICAL issues: "X critical issue(s) found. Fix before archiving." + - If only warnings: "No critical issues. Y warning(s) to consider. Ready for archive (with noted improvements)." + - If all clear: "All checks passed. Ready for archive." + +**Verification Heuristics** + +- **Completeness**: Focus on objective checklist items (checkboxes, requirements list) +- **Correctness**: Use keyword search, file path analysis, reasonable inference - don't require perfect certainty +- **Coherence**: Look for glaring inconsistencies, don't nitpick style +- **False Positives**: When uncertain, prefer SUGGESTION over WARNING, WARNING over CRITICAL +- **Actionability**: Every issue must have a specific recommendation with file/line references where applicable + +**Graceful Degradation** + +- If only tasks.md exists: verify task completion only, skip spec/design checks +- If tasks + specs exist: verify completeness and correctness, skip design +- If full artifacts: verify all three dimensions +- Always note which checks were skipped and why + +**Output Format** + +Use clear markdown with: +- Table for summary scorecard +- Grouped lists for issues (CRITICAL/WARNING/SUGGESTION) +- Code references in format: `file.ts:123` +- Specific, actionable recommendations +- No vague suggestions like "consider reviewing" diff --git a/.claude/skills/openspec-bulk-archive-change/SKILL.md b/.claude/skills/openspec-bulk-archive-change/SKILL.md new file mode 100644 index 0000000..52fb5c6 --- /dev/null +++ b/.claude/skills/openspec-bulk-archive-change/SKILL.md @@ -0,0 +1,339 @@ +--- +name: openspec-bulk-archive-change +description: Archive multiple completed changes at once. Use when archiving several parallel changes. +allowed-tools: Bash(openspec:*) +license: MIT +compatibility: Requires openspec CLI. +metadata: + author: openspec + version: "1.0" + generatedBy: "1.13.0" +--- + +Archive multiple completed changes in a single operation. + +This skill allows you to batch-archive changes, handling spec conflicts intelligently by checking the codebase to determine what's actually implemented. + +**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. + +`` is the spec directory relative to `specs/` (for example, `user-auth` or `identity/user-auth`). Preserve the full path from each delta spec when resolving its main spec. + +**Input**: None required (prompts for selection) + +**Steps** + +1. **Get active changes** + + Run `openspec list --json` to get all active changes. + + If no active changes exist, inform user and stop. + +2. **Prompt for change selection** + + Ask the user to choose changes (multi-select): + - Show each change with its schema + - Include an option for "All changes" + - Allow any number of selections (1+ works, 2+ is the typical use case) + + **IMPORTANT**: Do NOT auto-select. Always let the user choose. + + **Load current archive inputs once for the selected root before batch validation:** + + Choose one selected change from this root and run + `openspec instructions archive --change "" --json` with the + same selected-root flags. This lookup is advisory and optional: it only supplies + extra prompt inputs, so it must never block the batch. If it fails or returns + invalid JSON — for example on an older CLI that does not support this command + yet — continue the batch with no context and no operation guidance. Do not + report an error and do not stop. + + A valid response may omit `context` and `operationGuidance`. Treat + `context` as a required prompt-level input across the batch: read and consider + it, and apply relevant project facts, conventions, and constraints. Treat + `operationGuidance` as optional additive advice: read and consider every + entry, and follow entries that are applicable and compatible with the built-in + batch workflow. + + Keep both fields separate from conflict analysis, explicit user choices, + resolved paths, CLI checks, and command contracts. If context conflicts with one + of those controlling inputs, report the conflict and preserve the controlling + value. If guidance is inapplicable or conflicts with a controlling input, do not + follow it and explain why. Do not infer skipped prompts, replacement paths, or + flags from either field, and do not copy their text verbatim into specs, changes, + or summaries. These are prompt-level behavior contracts, not enforceable checks. + +3. **Batch validation - gather status for all selected changes** + + For each selected change, collect: + + a. **Artifact status** - Run `openspec status --change "" --json` + - Parse `schemaName`, `artifacts`, `planningHome`, `changeRoot`, `artifactPaths`, and `actionContext` + - Note which artifacts are `done` vs other states + + b. **Task completion** - Read `artifactPaths.tasks.existingOutputPaths` from status JSON + - Count `- [ ]` (incomplete) vs `- [x]` (complete) + - If no tasks file exists, note as "No tasks" + + c. **Delta specs** - Check `artifactPaths.specs.existingOutputPaths` from status JSON + - List which capability specs exist + - For each, extract requirement names (lines matching `### Requirement: `) + - Treat this list as the only delta-spec source. If the `specs` entry is + missing or the list is empty, perform no spec sync or specs-instruction + lookup for that change; do not infer deltas from unrelated artifacts. + - Evaluate this independently for every change, including mixed-schema + batches where some schemas have no `specs` artifact. +4. **Detect spec conflicts** + + Build a map keyed by ``, the exact path relative to `specs/`: + + ```text + identity/user-auth -> [change-a, change-b] <- CONFLICT (2+ changes) + billing/user-auth -> [change-c] <- OK (different full path) + ``` + + A conflict exists when 2+ selected changes have delta specs for the exact same ``. + +5. **Resolve conflicts agentically** + + **For each conflict**, investigate the codebase: + + a. **Read the delta specs** from each conflicting change to understand what each claims to add/modify + + b. **Search the codebase** for implementation evidence: + - Look for code implementing requirements from each delta spec + - Check for related files, functions, or tests + + c. **Determine resolution**: + - If only one change is actually implemented -> sync that one's specs + - If both implemented -> apply in chronological order (older first, newer overwrites) + - If neither implemented -> skip spec sync, warn user + + d. **Record resolution** for each conflict: + - An inclusion or exclusion decision for every delta spec, keyed by change and `` + - Which included delta specs to apply and in what order + - Which delta specs to exclude from sync because their implementation is missing + - Rationale (what was found in codebase) + +6. **Show consolidated status table** + + Display a table summarizing all changes: + + ```markdown + | Change | Artifacts | Tasks | Specs | Conflicts | Status | + |---------------------|-----------|-------|---------|-----------|--------| + | schema-management | Done | 5/5 | 2 delta | None | Ready | + | project-config | Done | 3/3 | 1 delta | None | Ready | + | add-oauth | Done | 4/4 | 1 delta | identity/user-auth (!) | Ready* | + | add-verify-skill | 1 left | 2/5 | None | None | Warn | + ``` + + For conflicts, show the resolution: + ```text + * Conflict resolution: + - identity/user-auth spec: Will apply add-oauth then add-jwt (both implemented, chronological order) + ``` + + For incomplete changes, show warnings: + ```text + Warnings: + - add-verify-skill: 1 incomplete artifact, 3 incomplete tasks + ``` + +7. **Confirm batch operation** + + Ask the user a single confirmation question: + + - "Archive N changes?" with options based on status + - Options might include: + - "Archive all N changes" + - "Archive only N ready changes (skip incomplete)" + - "Cancel" + + If there are incomplete changes, make clear they'll be archived with warnings. + + Route on the answer by intent, not by exact label — you wrote these labels, + so match what the user picked rather than the wording above: + - "Cancel" — stop, do not archive. Report that nothing was archived and skip the remaining steps. + - The archive-everything option — proceed with every selected change + - The ready-only option — proceed with only the changes the step 6 table marks `Ready` or `Ready*`, and record the rest as Skipped in step 8d. If a `Ready*` change's conflict partner is skipped, re-derive that conflict's resolution using only the changes being archived. + - Anything else — ask again rather than archiving + + Before step 8 writes the first main spec or moves any change, fetch every + required specs-rule snapshot for the confirmed batch. For each change that will + sync concrete `artifactPaths.specs.existingOutputPaths`, run + `openspec instructions specs --change "" --json` exactly once with the + same selected-root flags. Obtain all snapshots before the first write or move. + If any lookup exits non-zero or returns invalid artifact-instruction JSON, + identify the affected change, report the error, and stop the whole batch before + any main-spec write or change move. Do not treat lookup failure as omitted + rules. A valid response without `rules` is the no-rules case. + +8. **Execute archive for each confirmed change** + + Before processing, carry the recorded decisions from step 5 (after any step 7 re-derivation) into two per-delta sets: + - `includedDeltas`: all non-conflicting delta specs from confirmed changes plus conflict deltas selected for sync + - `excludedDeltas`: conflict deltas from confirmed changes excluded because their implementation is missing + - A single change can have both included and excluded delta specs. Keep the decision per delta; do not collapse it into a per-change sync flag. + + Process changes in the determined order (respecting conflict resolution): + + a. **Sync included delta specs**: + - Run the `openspec-sync-specs` workflow inline (agent-driven intelligent merge) only for changes with entries in `includedDeltas`, passing only the included delta paths and explicitly instructing it to ignore that change's `excludedDeltas`. Wait for it to finish. + - For conflicts, apply in resolved order. + - Pass that change's fetched specs-rule snapshot into inline sync; inline + sync must reuse it without fetching instructions again + - Apply artifact rules only to main specs produced by that change. They do + not change conflict resolution, archive behavior, or CLI contracts, and + their text is not copied into an output file + - Do not delegate to a background task — step 8c would move `changeRoot` out from under a sync that is still reading it. + - If a change has no included delta specs, do not run the sync workflow for it. + + b. **Verify included delta specs before moving changeRoot**: + - Re-run the comparison only for delta specs in `includedDeltas` against main spec at `/openspec/specs//spec.md` (use the store-aware `planningHome.root` from step 3 status JSON, not a hardcoded repo path). + - Verify that main specs are updated: + - ADDED requirements present + - MODIFIED requirements carrying scenario and description changes named in the delta, with their other scenarios intact + - REMOVED requirements gone — and where this sync retired a capability (removed its last requirement, leaving `## Requirements` empty), its main spec deleted rather than left empty; a spec the sync deliberately kept and reported is also a match + - RENAMED requirements present under the new name and absent under the old one + - Do not verify delta specs in `excludedDeltas`; they are intentionally left unsynced. + - If sync failed or any capability does not match verification, report what differs and fail/skip moving that change's `changeRoot` — do not archive that change. `changeRoot` remains intact. + + c. **Perform the archive**: + + Target name: use the change name as-is when it already starts with a `YYYY-MM-DD-` prefix; otherwise prepend the current date as `YYYY-MM-DD-` (same rule as `openspec archive`). + + ```bash + mkdir -p "/archive" + mv "" "/archive/" + ``` + + d. **Track outcome** for each change: + - Success: archived successfully + - Failed: error during archive or spec verification (record error) + - Skipped: user chose not to archive (if applicable) + - Sync skipped: for every delta in `excludedDeltas`, report `sync skipped` with the change, ``, and recorded reason. This is distinct from skipping the archive. + +9. **Display summary** + + Show final results: + + ```markdown + ## Bulk Archive Complete + + Archived 3 changes: + - schema-management-cli -> archive/2026-01-19-schema-management-cli/ + - project-config -> archive/2026-01-19-project-config/ + - add-oauth -> archive/2026-01-19-add-oauth/ + + Skipped 1 change: + - add-verify-skill (user chose not to archive incomplete) + + Spec sync summary: + - 4 delta specs synced to main specs + - 1 delta spec sync skipped (add-jwt, identity/user-auth: implementation not found) + - 1 conflict resolved (identity/user-auth: synced add-oauth, skipped add-jwt) + ``` + + If any failures: + ```text + Failed 1 change: + - some-change: Archive directory already exists + ``` + +**Conflict Resolution Examples** + +Example 1: Only one implemented +```text +Conflict: /openspec/specs/auth/spec.md touched by [add-oauth, add-jwt] + +Checking add-oauth: +- Delta adds "OAuth Provider Integration" requirement +- Searching codebase... found src/auth/oauth.ts implementing OAuth flow + +Checking add-jwt: +- Delta adds "JWT Token Handling" requirement +- Searching codebase... no JWT implementation found + +Resolution: Only add-oauth is implemented. Will sync add-oauth specs only. +``` + +Example 2: Both implemented +```text +Conflict: /openspec/specs/api/spec.md touched by [add-rest-api, add-graphql] + +Checking add-rest-api (created 2026-01-10): +- Delta adds "REST Endpoints" requirement +- Searching codebase... found src/api/rest.ts + +Checking add-graphql (created 2026-01-15): +- Delta adds "GraphQL Schema" requirement +- Searching codebase... found src/api/graphql.ts + +Resolution: Both implemented. Will apply add-rest-api specs first, +then add-graphql specs (chronological order, newer takes precedence). +``` + +**Output On Success** + +```markdown +## Bulk Archive Complete + +Archived N changes: +- -> archive// +- -> archive// + +Spec sync summary: +- N delta specs synced to main specs +- No conflicts (or: M conflicts resolved) +``` + +**Output On Partial Success** + +```markdown +## Bulk Archive Complete (partial) + +Archived N changes: +- -> archive// + +Skipped M changes: +- (user chose not to archive incomplete) + +Failed K changes: +- : Archive directory already exists +``` + +**Output When No Changes** + +```markdown +## No Changes to Archive + +No active changes found. Create a new change to get started. +``` + +**Guardrails** +- Allow any number of changes (1+ is fine, 2+ is the typical use case) +- Always prompt for selection, never auto-select +- Detect spec conflicts early and resolve by checking codebase +- When both changes are implemented, apply specs in chronological order +- Skip spec sync only when implementation is missing (warn user) +- Show clear per-change status before confirming +- Use single confirmation for entire batch +- Never archive after the user cancels the confirmation — a cancelled batch archives nothing +- Track and report all outcomes (success/skip/fail) +- Preserve .openspec.yaml when moving to archive +- Archive directory target uses current date: YYYY-MM-DD-; a name that already starts with a `YYYY-MM-DD-` prefix is used as-is (never stack a second date) +- If archive target exists, fail that change but continue with others +- If sync is requested, run the `openspec-sync-specs` workflow inline (agent-driven) for each change with included delta specs +- Carry the per-delta `includedDeltas` and `excludedDeltas` decisions into execution; sync and verify only included deltas +- Report every excluded delta as `sync skipped` without treating the archive itself as skipped +- Never archive a change while a spec sync is still in flight — run the sync inline and verify main specs at `/openspec/specs//spec.md` before moving `changeRoot` +- Fetch archive inputs once per selected root before spec inspection or moves +- Fetch all required specs-rule snapshots before the batch's first main-spec write or move +- A failed archive-inputs lookup never blocks the batch; it proceeds with no context or guidance +- A failed specs instruction lookup stops the whole batch atomically +- Changes without concrete `artifactPaths.specs.existingOutputPaths` continue without spec sync +- Apply relevant runtime context across the batch and report conflicts +- Operation guidance remains advisory; consider every entry and explain rejected advice +- Keep runtime inputs, conflict analysis, CLI-derived values, and artifact rules separate +- Artifact rules constrain only written specs +- Never copy runtime input or artifact-rule text verbatim into output files diff --git a/.claude/skills/openspec-continue-change/SKILL.md b/.claude/skills/openspec-continue-change/SKILL.md new file mode 100644 index 0000000..3319735 --- /dev/null +++ b/.claude/skills/openspec-continue-change/SKILL.md @@ -0,0 +1,118 @@ +--- +name: openspec-continue-change +description: Continue working on an OpenSpec change by creating the next artifact. Use when the user wants to progress their change, create the next artifact, or continue their workflow. +allowed-tools: Bash(openspec:*) +license: MIT +compatibility: Requires openspec CLI. +metadata: + author: openspec + version: "1.0" + generatedBy: "1.13.0" +--- + +Continue working on a change by creating the next artifact. + +**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. + +**Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes. + +**Steps** + +1. **Select the change** + + If a name is provided, use it. Otherwise: + - Infer from conversation context if the user mentioned a change + - Auto-select if only one active change exists + - If ambiguous, run `openspec list --json` to get available changes sorted by most recently modified, and ask the user to select one + + When prompting, present the top 3-4 most recently modified changes as options, showing: + - Change name + - Schema (from `schema` field if present, otherwise "spec-driven") + - Status (e.g., "0/5 tasks", "complete", "no tasks") + - How recently it was modified (from `lastModified` field) + + Mark the most recently modified change as "(Recommended)" since it's likely what the user wants to continue. + + Always announce: "Using change: " and how to override (e.g., `/opsx:continue `). + +2. **Check current status** + ```bash + openspec status --change "" --json + ``` + Parse the JSON to understand current state. The response includes: + - `schemaName`: The workflow schema being used (e.g., "spec-driven") + - `artifacts`: Array of artifacts with their status ("done", "skipped", "ready", "blocked") + - `isPlanningComplete`: Boolean indicating if all planning artifacts are complete. Older CLI versions expose the same value as `isComplete`. + - `planningHome`, `changeRoot`, `artifactPaths`, and `actionContext`: path and scope context. Use these instead of assuming repo-local paths. + +3. **Act based on status**: + + --- + + **If all planning artifacts are complete (`isPlanningComplete: true`, or legacy `isComplete: true`)**: + - Congratulate the user + - Show final status including the schema used + - Suggest: "Planning is complete! You can now implement this change. Once implementation and any tracked work are complete, archive it." + - STOP + + --- + + **If artifacts are ready to create** (status shows artifacts with `status: "ready"`): + - Pick the FIRST artifact with `status: "ready"` from the status output + - Get its instructions: + ```bash + openspec instructions --change "" --json + ``` + - Parse the JSON. The key fields are: + - `context`: Project background (constraints for you - do NOT include in output) + - `rules`: Artifact-specific rules (constraints for you - do NOT include in output) + - `template`: The structure to use for your output file + - `instruction`: Schema-specific guidance + - `resolvedOutputPath`: Resolved path or pattern to write the artifact + - `dependencies`: Completed artifacts to read for context (entries with `skipped: true` have no files - do not look for them) + - `skipped`/`warning`: present when the change declares skip_specs and this artifact must NOT be created - pick another artifact + - **Create the artifact file**: + - Read any completed dependency files for context - always re-read them from disk, even if you saw them earlier in the conversation (the user may have edited them) + - If the `instruction` field delegates creation to a specific skill or command, invoke it to produce the artifact instead of writing the file yourself, then verify the artifact file exists at `resolvedOutputPath` + - Otherwise use `template` as the structure - fill in its sections + - Apply `context` and `rules` as constraints when writing - but do NOT copy them into the file + - Write to the `resolvedOutputPath` specified in instructions. If it is a glob pattern, choose the concrete file path using the schema instruction and the change's context + - Show what was created and what's now unlocked + - STOP after creating ONE artifact + + --- + + **If no artifacts are ready (all blocked)**: + - This shouldn't happen with a valid schema + - Show status and suggest checking for issues + +4. **After creating an artifact, show progress** + ```bash + openspec status --change "" + ``` + +**Output** + +After each invocation, show: +- Which artifact was created +- Schema workflow being used +- Current progress (N/M complete) +- What artifacts are now unlocked +- Prompt: "Want to continue? Just ask me to continue or tell me what to do next." + +**Artifact Creation Guidelines** + +The artifact types and their purpose depend on the schema. The `instruction` field from the instructions output is the authoritative guidance for each artifact - follow it even when the artifact has a familiar name (proposal.md, tasks.md, etc.), since custom schemas may define different content or a different process for the same file names. + +If the `instruction` field directs you to use a specific skill or command to create the artifact, invoke it instead of writing the artifact directly. + +**Guardrails** +- Create ONE artifact per invocation +- Always read dependency artifacts before creating a new one - re-read from disk, not from conversation memory (files may have changed since you last saw them) +- Never skip artifacts or create out of order +- If context is unclear, ask the user before creating +- Verify the artifact file exists after writing before marking progress +- Use the schema's artifact sequence, don't assume specific artifact names +- **IMPORTANT**: `context` and `rules` are constraints for YOU, not content for the file + - Do NOT copy ``, ``, `` blocks into the artifact + - These guide what you write, but should never appear in the output diff --git a/.claude/skills/openspec-ff-change/SKILL.md b/.claude/skills/openspec-ff-change/SKILL.md new file mode 100644 index 0000000..f6d9cc7 --- /dev/null +++ b/.claude/skills/openspec-ff-change/SKILL.md @@ -0,0 +1,117 @@ +--- +name: openspec-ff-change +description: Fast-forward through OpenSpec artifact creation. Use when the user wants to quickly create all artifacts needed for implementation without stepping through each one individually. +allowed-tools: Bash(openspec:*) +license: MIT +compatibility: Requires openspec CLI. +metadata: + author: openspec + version: "1.0" + generatedBy: "1.13.0" +--- + +Fast-forward through artifact creation - generate everything needed to start implementation in one go. + +**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. + +**Input**: The user's request should include a change name (kebab-case) OR a description of what they want to build. + +**Steps** + +1. **If no clear input provided, ask what they want to build** + + Ask the user (open-ended, no preset options): + > "What change do you want to work on? Describe what you want to build or fix." + + From their description, derive a kebab-case name (e.g., "add user authentication" → `add-user-auth`). + + **IMPORTANT**: Do NOT proceed without understanding what the user wants to build. + +2. **Create the change directory** + ```bash + openspec new change "" + ``` + This creates a scaffolded change in the planning home resolved by the CLI. + +3. **Get the artifact build order** + ```bash + openspec status --change "" --json + ``` + Parse the JSON to get: + - `applyRequires`: array of artifact IDs needed before implementation (e.g., `["tasks"]`) + - `artifacts`: list of all artifacts, each with its `status` and its `requires` edges (the artifact IDs it directly depends on) + - `planningHome`, `changeRoot`, `artifactPaths`, and `actionContext`: path and scope context. Use these instead of assuming repo-local paths. + +4. **Create every artifact in the required set** + + Use a todo list to track progress through the artifacts. + + Loop through artifacts in dependency order (artifacts with no pending dependencies first): + + a. **For each artifact that is `ready` (dependencies satisfied)**: + - Get instructions: + ```bash + openspec instructions --change "" --json + ``` + - The instructions JSON includes: + - `context`: Project background (constraints for you - do NOT include in output) + - `rules`: Artifact-specific rules (constraints for you - do NOT include in output) + - `template`: The structure to use for your output file + - `instruction`: Schema-specific guidance for this artifact type + - `skipped`/`warning`: present when the change declares skip_specs and this artifact must NOT be created - stop and pick another artifact + - `resolvedOutputPath`: Resolved path or pattern to write the artifact + - `dependencies`: Completed artifacts to read for context + - Read any completed dependency files for context - always re-read them from disk, even if you saw them earlier in the conversation (the user may have edited them) + - **Inspect the relevant project before drafting**: Read `context` and `rules` first, then inspect relevant implementation, nearby tests, configuration, and documentation outside `openspec/`. Keep inspection read-only and proportional to the change; reuse findings for later artifacts and inspect more only as needed. + - Identify the target project from the request and project context; the planning home may be separate from the code. If the target is unclear, ask. For greenfield or non-code changes, inspect the available structure and relevant documents. If source is unavailable, state the limitation and ask when it materially affects the plan. + - Ground scope, approach, and tasks in what you find. Distinguish observed behavior from assumptions and proposed additions; surface conflicts with existing specs instead of silently deciding which is correct. + - Do this discovery now, rather than leaving generic "explore the codebase" or "make a plan" tasks for implementation. Keep any necessary follow-up investigation specific to an unresolved question. + - If the `instruction` field delegates creation to a specific skill or command, invoke it to produce the artifact instead of writing the file yourself, then verify the artifact file exists at `resolvedOutputPath` + - Otherwise create the artifact file using `template` as the structure and write it to `resolvedOutputPath`. If `resolvedOutputPath` is a glob, follow `instruction` to choose the concrete file path + - Apply `context` and `rules` as constraints - but do NOT copy them into the file + - Show brief progress: "✓ Created " + + b. **Continue until every artifact in the required set exists (not just `apply.requires`)** + - After creating each artifact, re-run `openspec status --change "" --json` + - The required set is `applyRequires` plus every artifact reachable from those by following the `requires` edges in `status --json` - walk them transitively (spec-driven closes over proposal, specs, design, tasks). Leave artifacts outside that set alone + - `status` is file-existence only, so an `applyRequires` artifact reading `done` does NOT mean its dependencies exist - writing `tasks.md` early marks `tasks` done while `specs` was never written. Use each artifact's `requires` edges, not its `status`, to build the required set: a `done` artifact still lists what it depends on + - An artifact already reading `status: "skipped"` is satisfied: the change declares `skip_specs` in `.openspec.yaml`, so its files must NOT exist. Never try to create one + - Create every artifact in the required set that is missing, then re-check - creating one can unblock others + - Skip one only when `status` already reports it `skipped`, or when its own `instruction` says it is conditional: run `openspec instructions --change "" --json` and skip only if its `instruction` field marks it optional (e.g. "create only if..."). Spec-driven's `design.md` qualifies; `specs` qualifies only via the `skipped` status above, never by your own judgment. Tell the user, and do not reconsider it + - Dependencies are enablers, not gates: if a required artifact is still `blocked` only because you skipped a conditional dependency, write it anyway + - Stop when every artifact in the required set is `done`, `skipped`, or was deliberately skipped + + c. **If an artifact requires user input** (unclear context): + - Ask the user to clarify + - Then continue with creation + +5. **Show final status** + ```bash + openspec status --change "" + ``` + +**Output** + +After completing all artifacts, summarize: +- Change name and location +- List of artifacts created with brief descriptions, plus any conditional artifact you skipped and why +- What's ready: "All artifacts needed for implementation are ready." +- Prompt: "Run `/opsx:apply` or ask me to implement to start working on the tasks." + +**Artifact Creation Guidelines** + +- Follow the `instruction` field from `openspec instructions` for each artifact type - it is the authoritative guidance, even for familiar artifact names +- If the `instruction` field directs you to use a specific skill or command to create the artifact, invoke it instead of writing the artifact directly +- The schema defines what each artifact should contain - follow it +- Read dependency artifacts for context before creating new ones +- Use `template` as the structure for your output file - fill in its sections +- **IMPORTANT**: `context` and `rules` are constraints for YOU, not content for the file + - Do NOT copy ``, ``, `` blocks into the artifact + - These guide what you write, but should never appear in the output + +**Guardrails** +- Create every artifact the apply phase transitively depends on, not just the ids listed in `apply.requires` +- Always read dependency artifacts before creating a new one - re-read from disk, not from conversation memory (files may have changed since you last saw them) +- If context is critically unclear, ask the user - but prefer making reasonable decisions to keep momentum +- If a change with that name already exists, suggest continuing that change instead +- Verify each artifact file exists after writing before proceeding to next diff --git a/.claude/skills/openspec-new-change/SKILL.md b/.claude/skills/openspec-new-change/SKILL.md new file mode 100644 index 0000000..c955883 --- /dev/null +++ b/.claude/skills/openspec-new-change/SKILL.md @@ -0,0 +1,77 @@ +--- +name: openspec-new-change +description: Start a new OpenSpec change using the experimental artifact workflow. Use when the user wants to create a new feature, fix, or modification with a structured step-by-step approach. +allowed-tools: Bash(openspec:*) +license: MIT +compatibility: Requires openspec CLI. +metadata: + author: openspec + version: "1.0" + generatedBy: "1.13.0" +--- + +Start a new change using the experimental artifact-driven approach. + +**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. + +**Input**: The user's request should include a change name (kebab-case) OR a description of what they want to build. + +**Steps** + +1. **If no clear input provided, ask what they want to build** + + Ask the user (open-ended, no preset options): + > "What change do you want to work on? Describe what you want to build or fix." + + From their description, derive a kebab-case name (e.g., "add user authentication" → `add-user-auth`). + + **IMPORTANT**: Do NOT proceed without understanding what the user wants to build. + +2. **Determine the workflow schema** + + Use the default schema (omit `--schema`) unless the user explicitly requests a different workflow. + + **Use a different schema only if the user mentions:** + - A specific schema name → use `--schema ` + - "show workflows" or "what workflows" → run `openspec schemas --json` and let them choose + + **Otherwise**: Omit `--schema` to use the default. + +3. **Create the change directory** + ```bash + openspec new change "" + ``` + Add `--schema ` only if the user requested a specific workflow. + This creates a scaffolded change in the planning home resolved by the CLI. + +4. **Show the artifact status** + ```bash + openspec status --change "" --json + ``` + Use the returned `planningHome`, `changeRoot`, `artifactPaths`, and `nextSteps` instead of assuming repo-local paths. + +5. **Get instructions for the first artifact** + The first artifact depends on the schema (e.g., `proposal` for spec-driven). + Check the status output to find the first artifact with status "ready". + ```bash + openspec instructions --change "" + ``` + This outputs the template and context for creating the first artifact. + +6. **STOP and wait for user direction** + +**Output** + +After completing the steps, summarize: +- Change name and location +- Schema/workflow being used and its artifact sequence +- Current status (0/N artifacts complete) +- The template for the first artifact +- Prompt: "Ready to create the first artifact? Just describe what this change is about and I'll draft it, or ask me to continue." + +**Guardrails** +- Do NOT create any artifacts yet - just show the instructions +- Do NOT advance beyond showing the first artifact template +- If the name is invalid (not kebab-case), ask for a valid name +- If a change with that name already exists, suggest continuing that change instead +- Pass --schema if using a non-default workflow diff --git a/.claude/skills/openspec-onboard/SKILL.md b/.claude/skills/openspec-onboard/SKILL.md new file mode 100644 index 0000000..61733b5 --- /dev/null +++ b/.claude/skills/openspec-onboard/SKILL.md @@ -0,0 +1,561 @@ +--- +name: openspec-onboard +description: Guided onboarding for OpenSpec - walk through a complete workflow cycle with narration and real codebase work. +allowed-tools: Bash(openspec:*) +license: MIT +compatibility: Requires openspec CLI. +metadata: + author: openspec + version: "1.0" + generatedBy: "1.13.0" +--- + +Guide the user through their first complete OpenSpec workflow cycle. This is a teaching experience—you'll do real work in their codebase while explaining each step. + +**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. + +--- + +## Preflight + +Before starting, check if the OpenSpec CLI is installed: + +```bash +# Unix/macOS +openspec --version 2>&1 || echo "CLI_NOT_INSTALLED" +# Windows (PowerShell) +# if (Get-Command openspec -ErrorAction SilentlyContinue) { openspec --version } else { echo "CLI_NOT_INSTALLED" } +``` + +**If CLI not installed:** +> OpenSpec CLI is not installed. Install it first, then come back to `/opsx:onboard`. + +Stop here if not installed. + +--- + +## Phase 1: Welcome + +Display: + +``` +## Welcome to OpenSpec! + +I'll walk you through a complete change cycle—from idea to implementation—using a real task in your codebase. Along the way, you'll learn the workflow by doing it. + +**What we'll do:** +1. Pick a small, real task in your codebase +2. Explore the problem briefly +3. Create a change (the container for our work) +4. Build the artifacts: proposal → specs → design → tasks +5. Implement the tasks +6. Archive the completed change + +**Time:** ~15-20 minutes + +Let's start by finding something to work on. +``` + +--- + +## Phase 2: Task Selection + +### Codebase Analysis + +Scan the codebase for small improvement opportunities. Look for: + +1. **TODO/FIXME comments** - Search for `TODO`, `FIXME`, `HACK`, `XXX` in code files +2. **Missing error handling** - `catch` blocks that swallow errors, risky operations without try-catch +3. **Functions without tests** - Cross-reference `src/` with test directories +4. **Type issues** - `any` types in TypeScript files (`: any`, `as any`) +5. **Debug artifacts** - `console.log`, `console.debug`, `debugger` statements in non-debug code +6. **Missing validation** - User input handlers without validation + +Also check recent git activity: +```bash +# Unix/macOS +git log --oneline -10 2>/dev/null || echo "No git history" +# Windows (PowerShell) +# git log --oneline -10 2>$null; if ($LASTEXITCODE -ne 0) { echo "No git history" } +``` + +### Present Suggestions + +From your analysis, present 3-4 specific suggestions: + +``` +## Task Suggestions + +Based on scanning your codebase, here are some good starter tasks: + +**1. [Most promising task]** + Location: `src/path/to/file.ts:42` + Scope: ~1-2 files, ~20-30 lines + Why it's good: [brief reason] + +**2. [Second task]** + Location: `src/another/file.ts` + Scope: ~1 file, ~15 lines + Why it's good: [brief reason] + +**3. [Third task]** + Location: [location] + Scope: [estimate] + Why it's good: [brief reason] + +**4. Something else?** + Tell me what you'd like to work on. + +Which task interests you? (Pick a number or describe your own) +``` + +**If nothing found:** Fall back to asking what the user wants to build: +> I didn't find obvious quick wins in your codebase. What's something small you've been meaning to add or fix? + +### Scope Guardrail + +If the user picks or describes something too large (major feature, multi-day work): + +``` +That's a valuable task, but it's probably larger than ideal for your first OpenSpec run-through. + +For learning the workflow, smaller is better—it lets you see the full cycle without getting stuck in implementation details. + +**Options:** +1. **Slice it smaller** - What's the smallest useful piece of [their task]? Maybe just [specific slice]? +2. **Pick something else** - One of the other suggestions, or a different small task? +3. **Do it anyway** - If you really want to tackle this, we can. Just know it'll take longer. + +What would you prefer? +``` + +Let the user override if they insist—this is a soft guardrail. + +--- + +## Phase 3: Explore Demo + +Once a task is selected, briefly demonstrate explore mode: + +``` +Before we create a change, let me quickly show you **explore mode**—it's how you think through problems before committing to a direction. +``` + +Spend 1-2 minutes investigating the relevant code: +- Read the file(s) involved +- Draw a quick ASCII diagram if it helps +- Note any considerations + +``` +## Quick Exploration + +[Your brief analysis—what you found, any considerations] + +┌─────────────────────────────────────────┐ +│ [Optional: ASCII diagram if helpful] │ +└─────────────────────────────────────────┘ + +Explore mode (`/opsx:explore`) is for this kind of thinking—investigating before implementing. You can use it anytime you need to think through a problem. + +Now let's create a change to hold our work. +``` + +**PAUSE** - Wait for user acknowledgment before proceeding. + +--- + +## Phase 4: Create the Change + +**EXPLAIN:** +``` +## Creating a Change + +A "change" in OpenSpec is a container for all the thinking and planning around a piece of work. It lives at the `changeRoot` reported by `openspec status --change "" --json` and holds your artifacts—proposal, specs, design, tasks. + +Let me create one for our task. +``` + +**DO:** Create the change with a derived kebab-case name: +```bash +openspec new change "" +``` + +**SHOW:** +``` +Created: + +The folder structure: +``` +/ +├── proposal.md ← Why we're doing this (empty, we'll fill it) +├── design.md ← How we'll build it (empty) +├── specs/ ← Detailed requirements (empty) +└── tasks.md ← Implementation checklist (empty) +``` + +Now let's fill in the first artifact—the proposal. +``` + +--- + +## Phase 5: Proposal + +**EXPLAIN:** +``` +## The Proposal + +The proposal captures **why** we're making this change and **what** it involves at a high level. It's the "elevator pitch" for the work. + +I'll draft one based on our task. +``` + +**DO:** Draft the proposal content (don't save yet): + +`` is the spec directory relative to `specs/` (for example, +`user-auth` or `identity/user-auth`). Use the exact existing path for modified +capabilities. For new capabilities, follow the project's established spec +organization. + +``` +Here's a draft proposal: + +--- + +## Why + +[1-2 sentences explaining the problem/opportunity] + +## What Changes + +[Bullet points of what will be different] + +## Capabilities + +### New Capabilities +- ``: [brief description] + +### Modified Capabilities + +- ``: [brief description] + +## Impact + +- `src/path/to/file.ts`: [what changes] +- [other files if applicable] + +--- + +Does this capture the intent? I can adjust before we save it. +``` + +**PAUSE** - Wait for user approval/feedback. + +After approval, save the proposal: +```bash +openspec instructions proposal --change "" --json +``` +Then write the content to the `resolvedOutputPath` from `openspec instructions proposal --change "" --json`. + +``` +Proposal saved. This is your "why" document—you can always come back and refine it as understanding evolves. + +Next up: specs. +``` + +--- + +## Phase 6: Specs + +**EXPLAIN:** +``` +## Specs + +Specs define **what** we're building in precise, testable terms. They use a requirement/scenario format that makes expected behavior crystal clear. + +For a small task like this, we might only need one spec file. +``` + +**DO:** Resolve where the spec file should be created: +```bash +openspec instructions specs --change "" --json +# Use resolvedOutputPath from the JSON. If it is a glob, choose the concrete file path using the schema instruction and the change's context. +``` + +Draft the spec content: + +``` +Here's the spec: + +--- + +## ADDED Requirements + +### Requirement: + + + +#### Scenario: + +- **WHEN** +- **THEN** +- **AND** + +--- + +This format—WHEN/THEN/AND—makes requirements testable. You can literally read them as test cases. +``` + +Save to the concrete file path chosen from `resolvedOutputPath`. + +--- + +## Phase 7: Design + +**EXPLAIN:** +``` +## Design + +The design captures **how** we'll build it—technical decisions, tradeoffs, approach. + +For small changes, this might be brief. That's fine—not every change needs deep design discussion. +``` + +**DO:** Draft design.md: + +``` +Here's the design: + +--- + +## Context + +[Brief context about the current state] + +## Goals / Non-Goals + +**Goals:** +- [What we're trying to achieve] + +**Non-Goals:** +- [What's explicitly out of scope] + +## Decisions + +### Decision 1: [Key decision] + +[Explanation of approach and rationale] + +--- + +For a small task, this captures the key decisions without over-engineering. +``` + +Save to the `resolvedOutputPath` from `openspec instructions design --change "" --json`. + +--- + +## Phase 8: Tasks + +**EXPLAIN:** +``` +## Tasks + +Finally, we break the work into implementation tasks—checkboxes that drive the apply phase. + +These should be small, clear, and in logical order. +``` + +**DO:** Generate tasks based on specs and design: + +``` +Here are the implementation tasks: + +--- + +## 1. [Category or file] + +- [ ] 1.1 [Specific task] — verify: [test, command, observable behavior, or delivered artifact] +- [ ] 1.2 [Specific task] — verify: [test, command, observable behavior, or delivered artifact] + +## 2. Integration Verification + +- [ ] 2.1 Verify [broader integration or system behavior] with [end-to-end test or observable result] + +--- + +Each checkbox becomes a unit of work in the apply phase. Ready to implement? +``` + +**PAUSE** - Wait for user to confirm they're ready to implement. + +Save to the `resolvedOutputPath` from `openspec instructions tasks --change "" --json`. + +--- + +## Phase 9: Apply (Implementation) + +**EXPLAIN:** +``` +## Implementation + +Now we implement each task, checking them off as we go. I'll announce each one and occasionally note how the specs/design informed the approach. +``` + +**DO:** For each task: + +1. Announce: "Working on task N: [description]" +2. Implement the change in the codebase +3. Reference specs/design naturally: "The spec says X, so I'm doing Y" +4. Mark complete in tasks.md: `- [ ]` → `- [x]` +5. Brief status: "✓ Task N complete" + +Keep narration light—don't over-explain every line of code. + +After all tasks: + +``` +## Implementation Complete + +All tasks done: +- [x] Task 1 +- [x] Task 2 +- [x] ... + +The change is implemented! One more step—let's archive it. +``` + +--- + +## Phase 10: Archive + +**EXPLAIN:** +``` +## Archiving + +When a change is complete, we archive it. The archive path is derived from `planningHome.changesDir` and the date. + +Archived changes become your project's decision history—you can always find them later to understand why something was built a certain way. +``` + +**DO:** Archive the change (`--yes` answers the confirmation prompts, which you cannot answer from a tool call): +```bash +openspec archive "" --yes +``` + +**SHOW:** +``` +Archived to: `/archive//` (the target name prepends today's date, unless the name already starts with a `YYYY-MM-DD-` prefix — then it is kept as-is, no second date) + +The change is now part of your project's history. The code is in your codebase, the decision record is preserved. +``` + +--- + +## Phase 11: Recap & Next Steps + +``` +## Congratulations! + +You just completed a full OpenSpec cycle: + +1. **Explore** - Thought through the problem +2. **New** - Created a change container +3. **Proposal** - Captured WHY +4. **Specs** - Defined WHAT in detail +5. **Design** - Decided HOW +6. **Tasks** - Broke it into steps +7. **Apply** - Implemented the work +8. **Archive** - Preserved the record + +This same rhythm works for any size change—a small fix or a major feature. + +--- + +## Command Reference + +**Core workflow:** + + | Command | What it does | + |-------------------|--------------------------------------------| + | `/opsx:propose` | Create a change and generate all artifacts | + | `/opsx:explore` | Think through problems before/during work | + | `/opsx:apply` | Implement tasks from a change | + | `/opsx:archive` | Archive a completed change | + +**Additional commands** (only if installed - availability depends on your profile): + + | Command | What it does | + |--------------------|----------------------------------------------------------| + | `/opsx:new` | Start a new change, step through artifacts one at a time | + | `/opsx:continue` | Continue working on an existing change | + | `/opsx:ff` | Fast-forward: create all artifacts at once | + | `/opsx:verify` | Verify implementation matches artifacts | + +--- + +## What's Next? + +Try `/opsx:propose` on something you actually want to build. You've got the rhythm now! +``` + +--- + +## Graceful Exit Handling + +### User wants to stop mid-way + +If the user says they need to stop, want to pause, or seem disengaged: + +``` +No problem! Your change is saved at the `changeRoot` reported by `openspec status --change "" --json`. + +To pick up where we left off later: +- `/opsx:continue ` - Resume artifact creation (if installed; otherwise `openspec status --change "" --json` shows the next artifact) +- `/opsx:apply ` - Jump to implementation (if tasks exist) + +The work won't be lost. Come back whenever you're ready. +``` + +Exit gracefully without pressure. + +### User just wants command reference + +If the user says they just want to see the commands or skip the tutorial: + +``` +## OpenSpec Quick Reference + +**Core workflow:** + + | Command | What it does | + |--------------------------|--------------------------------------------| + | `/opsx:propose ` | Create a change and generate all artifacts | + | `/opsx:explore` | Think through problems (no code changes) | + | `/opsx:apply ` | Implement tasks | + | `/opsx:archive ` | Archive when done | + +**Additional commands** (only if installed - availability depends on your profile): + + | Command | What it does | + |---------------------------|-------------------------------------| + | `/opsx:new ` | Start a new change, step by step | + | `/opsx:continue ` | Continue an existing change | + | `/opsx:ff ` | Fast-forward: all artifacts at once | + | `/opsx:verify ` | Verify implementation | + +Try `/opsx:propose` to start your first change. +``` + +Exit gracefully. + +--- + +## Guardrails + +- **Follow the EXPLAIN → DO → SHOW → PAUSE pattern** at key transitions (after explore, after proposal draft, after tasks, after archive) +- **Keep narration light** during implementation—teach without lecturing +- **Don't skip phases** even if the change is small—the goal is teaching the workflow +- **Pause for acknowledgment** at marked points, but don't over-pause +- **Handle exits gracefully**—never pressure the user to continue +- **Use real codebase tasks**—don't simulate or use fake examples +- **Adjust scope gently**—guide toward smaller tasks but respect user choice diff --git a/.claude/skills/openspec-sync-specs/SKILL.md b/.claude/skills/openspec-sync-specs/SKILL.md new file mode 100644 index 0000000..730ea90 --- /dev/null +++ b/.claude/skills/openspec-sync-specs/SKILL.md @@ -0,0 +1,262 @@ +--- +name: openspec-sync-specs +description: Sync delta specs from a change to main specs. Use when the user wants to update main specs with changes from a delta spec, without archiving the change. +allowed-tools: Bash(openspec:*) +license: MIT +compatibility: Requires openspec CLI. +metadata: + author: openspec + version: "1.0" + generatedBy: "1.13.0" +--- + +Sync delta specs from a change to main specs. + +This is an **agent-driven** operation - you will read delta specs and directly edit main specs to apply the changes. This allows intelligent merging (e.g., adding a scenario without copying the entire requirement). + +**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. + +`` is the spec directory relative to `specs/` (for example, `user-auth` or `identity/user-auth`). Preserve the full path from each delta spec when resolving its main spec. + +**Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes. + +**Steps** + +1. **Select the change** + + If a name is provided, use it. Otherwise: + - Infer from conversation context if the user mentioned a change + - Auto-select if only one active change exists + - If ambiguous, run `openspec list --json` to get available changes and ask the user to select one + + When prompting, show changes that have delta specs (under `specs/` directory). + + Always announce: "Using change: " and how to override (e.g., `/opsx:sync `). + +2. **Resolve change context** + + Run: + ```bash + openspec status --change "" --json + ``` + + The JSON includes `planningHome.root`. Main specs live under `/openspec/specs/` — use that (store-aware) root for every main-spec path below, not a hardcoded repo path. When a store is selected it points at the store, not the current repository. + +3. **Find delta specs** + + Use `artifactPaths.specs.existingOutputPaths` from the status JSON as the + only source of delta spec paths. If the `specs` entry is missing or + `existingOutputPaths` is empty, report that there are no delta specs to sync, + do not infer them from other artifacts, and stop without requesting artifact + instructions or writing a main spec. + + Sync every path in `existingOutputPaths` unless the caller narrowed the set. + A caller narrows it by naming an explicit list of complete entries from + `existingOutputPaths` — copy those absolute values verbatim. Archive does + this inline, and a user can too (for example, by selecting the entry ending + in `/specs/billing/invoices/spec.md`). + Then sync only the named paths and leave the remaining delta specs untouched: + bulk archive excludes a delta whose implementation it could not find, and + syncing it anyway would write a main spec the caller deliberately withheld. + Carry that narrowed selection through step 4; never widen it back to the full + list. If a named path is not in `existingOutputPaths`, do not sync it — + report it and stop, rather than dropping it silently. If the named list is + empty, report that there is nothing to sync and stop without writing a main + spec. + + Each delta spec file contains sections like: + - `## ADDED Requirements` - New requirements to add + - `## MODIFIED Requirements` - Changes to existing requirements + - `## REMOVED Requirements` - Requirements to remove + - `## RENAMED Requirements` - Requirements to rename (FROM:/TO: format) + + If no delta specs found, inform user and stop. + +4. **For each delta spec, apply changes to main specs** + + Before the first main-spec write, obtain one current specs-rule snapshot: + - If archive invoked this workflow inline and supplied a valid snapshot from + `openspec instructions specs --change "" --json`, reuse it and do not + fetch the same instructions again. + - Otherwise run that command once now with the same selected-root flags. + - If the direct lookup exits non-zero or returns invalid artifact-instruction + JSON, report the error and stop before writing any main spec. Do not treat the + failure as an absent rule set. + - A valid response with omitted `rules` means no artifact rules are configured + and the existing semantic merge continues. + + Apply returned `rules` only to the content and form of the main specs produced + by this merge. Artifact rules are not operation guidance and cannot change + selected roots, delta paths, CLI checks, or workflow steps. Use their text as + constraints without copying it verbatim into a main spec or summary. + + For each capability delta spec path selected in step 3 — the full `existingOutputPaths` list, or the narrowed subset when a caller supplied one (these may belong to a selected store, not the repo): + + a. **Read the delta spec** to understand the intended changes + + b. **Read the main spec** at `/openspec/specs//spec.md` (may not exist yet) + + c. **Apply changes intelligently**: + + **ADDED Requirements:** + - If requirement doesn't exist in main spec → add it + - If requirement already exists → update it to match (treat as implicit MODIFIED) + + **MODIFIED Requirements:** + - Find the requirement in main spec + - Apply the changes - this can be: + - Adding new scenarios the main spec does not have yet + - Modifying existing scenarios + - Changing the requirement description + - Preserve scenarios/content not mentioned in the delta + + **REMOVED Requirements:** + - Remove the entire requirement block from main spec + - Retiring the capability. Delete the whole `spec.md` - and the directory once + nothing else is left in it - only when ALL of these hold: + 1. removing the requirements *this run* left no requirement blocks; + 2. the rest of the spec is well-formed (it still has a `## Purpose`); + 3. the main spec was not already empty before this sync - if you removed + nothing, change nothing; + 4. every other nonblank line in the whole file is accounted for as the + title, Purpose, Requirements header, or a canonical requirement's + statement, scenarios, or fenced examples; + 5. the change's `.openspec.yaml` declares `retire_capabilities: true`; + 6. the `spec.md` resolves inside the real specs root (do not follow a + capability-directory symlink to delete an external file). + If removing the selected requirements would leave no requirement blocks and + any retirement condition is not satisfied, do not modify the main spec. Stop + the sync for that capability, report the blocking condition, and tell the user + how to resolve it. Never write or leave an empty `## Requirements` section. + When only the marker is missing, say that too - it is the one thing the user + can add to make the retirement go through. + - Deleting the file also deletes its `## Purpose`; any other section blocks + retirement. Name Purpose when you report the retirement. Include a pasteable + `git checkout` only when the spec lived in the caller's checkout; + otherwise give checkout-scoped recovery guidance. + + **RENAMED Requirements:** + - Find the FROM requirement, rename to TO + + **`## Purpose` in the delta:** + - The main spec already has one and it is authoritative - leave it alone + (this is what `openspec archive` does; it warns and moves on) + + d. **Create new main spec** if capability doesn't exist yet: + - Create `/openspec/specs//spec.md` + - Add Purpose section: copy the delta's `## Purpose` body verbatim when it has one + (this is what `openspec archive` does); only write a brief TBD placeholder when it does not + - Add Requirements section with the ADDED requirements + - Follow the **Main Spec Format Reference** below + +5. **Validate updated main specs** + + Run `openspec validate --specs` with the same selected-root flags used earlier. + If validation fails, report the problems and do not claim the sync succeeded. + +6. **Show summary** + + After applying all changes, summarize: + - Which capabilities were updated + - What changes were made (requirements added/modified/removed/renamed) + - Any new main spec left with a TBD Purpose placeholder, so it gets written + now rather than lingering + - Any capability retired, naming the deleted `spec.md`, its Purpose, and + either a pasteable `git checkout` or checkout-scoped recovery guidance + +**Delta Spec Format Reference** + +```markdown +## Purpose + +Only on a delta that introduces a brand-new capability. Seeds the new main spec. + +## ADDED Requirements + +### Requirement: New Feature +The system SHALL do something new. + +#### Scenario: Basic case +- **WHEN** user does X +- **THEN** system does Y + +## MODIFIED Requirements + +### Requirement: Existing Feature +The system SHALL keep doing the existing thing, now also handling A. + +#### Scenario: Scenario the main spec already has +- **WHEN** user does X +- **THEN** system does Y + +#### Scenario: New scenario to add +- **WHEN** user does A +- **THEN** system does B + +## REMOVED Requirements + +### Requirement: Deprecated Feature + +## RENAMED Requirements + +- FROM: `### Requirement: Old Name` +- TO: `### Requirement: New Name` +``` + +**Main Spec Format Reference** + +Main specs are what the delta merges INTO. They must never contain delta operation headers (`## ADDED/MODIFIED/REMOVED/RENAMED Requirements`) - after syncing, every requirement lives under a single `## Requirements` section: + +```markdown +# Specification + +## Purpose +Short description of what this capability does and why it exists. + +## Requirements + +### Requirement: New Feature +The system SHALL do something new. + +#### Scenario: Basic case +- **WHEN** user does X +- **THEN** system does Y +``` + +**Key Principle: Intelligent Merging** + +Unlike programmatic merging, you merge rather than overwrite: +- A MODIFIED block carries the whole requirement - body plus every scenario that survives the change. `openspec validate` and `openspec archive` both reject one that drops a scenario the main spec still has. +- Keep anything the delta does not mention, in the main spec's existing order +- Use your judgment to merge changes sensibly + +**Output On Success** + +```markdown +## Specs Synced: + +Updated main specs: + +****: +- Added requirement: "New Feature" +- Modified requirement: "Existing Feature" (added 1 scenario) + +****: +- Created new spec file +- Added requirement: "Another Feature" + +Main specs are now updated. The change remains active - archive when implementation is complete. +``` + +**Guardrails** +- Read both delta and main specs before making changes +- Preserve existing content not mentioned in delta +- Never copy a delta file into a main spec as-is - merge its content so the main spec keeps the Main Spec Format Reference structure, with no delta operation headers +- If something is unclear, ask for clarification +- Show what you're changing as you go +- The operation should be idempotent - running twice should give same result +- Use only `artifactPaths.specs.existingOutputPaths`; never infer delta specs from unrelated artifacts +- Honor a caller-supplied subset of `existingOutputPaths`; never widen it back to the full list +- Fetch specs instructions once for direct sync, or reuse the archive-supplied snapshot inline +- Stop before every main-spec write on a non-zero or invalid JSON specs-instruction response +- Artifact rules constrain only the specs being written and are never copied into output files diff --git a/.claude/skills/openspec-update-change/SKILL.md b/.claude/skills/openspec-update-change/SKILL.md new file mode 100644 index 0000000..64e764f --- /dev/null +++ b/.claude/skills/openspec-update-change/SKILL.md @@ -0,0 +1,91 @@ +--- +name: openspec-update-change +description: Update an OpenSpec change by revising its existing planning artifacts and keeping them coherent with one another. Use when the user wants to revise a change's plan, fold new decisions into it, or reconcile its artifacts after an edit. Never edits code. +allowed-tools: Bash(openspec:*) +license: MIT +compatibility: Requires openspec CLI. +metadata: + author: openspec + version: "1.0" + generatedBy: "1.13.0" +--- + +Revise a change's existing planning artifacts and keep them coherent. Never edit code. + +**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. + +**Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes. + +`/opsx:continue` is an optional workflow and may not be installed. Before suggesting it anywhere below, verify that it is available. If it is unavailable, `openspec status --change "" --json` shows the next artifact and `openspec instructions "" --change "" --json` explains how to create it. + +**Steps** + +1. **Select the change** + + If a name is provided, use it. Otherwise: + - Infer from conversation context if the user mentioned a change + - Auto-select if only one active change exists + - If ambiguous, run `openspec list --json` to get available changes sorted by most recently modified, and ask the user to select one + + When prompting, present the top 3-4 most recently modified changes as options, showing: + - Change name + - Schema (from `schema` field if present, otherwise "spec-driven") + - Status (e.g., "0/5 tasks", "complete", "no tasks") + - How recently it was modified (from `lastModified` field) + + Mark the most recently modified change as "(Recommended)" since it's likely what the user wants to update. + + Always announce: "Using change: " and how to override (e.g., `/opsx:update `). + +2. **Get the change's artifacts** + ```bash + openspec status --change "" --json + ``` + Parse the JSON to understand current state. The response includes: + - `schemaName`: The workflow schema being used (e.g., "spec-driven") + - `artifacts`: Array of artifacts with their status ("done", "skipped", "ready", "blocked") + - `isPlanningComplete`: Boolean indicating if all planning artifacts are complete. Older CLI versions expose the same value as `isComplete`. + - `planningHome`, `changeRoot`, `artifactPaths`, and `actionContext`: path and scope context. Use these instead of assuming repo-local paths. + + The artifact ids and paths come from the active schema - do NOT assume them, and do NOT branch on hardcoded artifact names. Custom schemas must work unchanged. + + The files to edit are `artifactPaths..existingOutputPaths` - the concrete files that exist on disk, already glob-expanded for glob artifacts (e.g. `specs/**/*.md`). Do NOT write to `resolvedOutputPath`: for a glob artifact it is still the glob pattern, not a real file. + +3. **Understand the request** + - If the user asked for a specific revision ("the design now uses X"), that is the starting edit. + - If they only said "update" / "make this coherent", treat it as a coherence review: read the existing artifacts and check them against each other for contradictions, gaps, and duplication. + +4. **Read and reconcile** + - Read the artifact(s) the request touches and the change's other existing artifacts. + - Apply the requested edit. Then check every other existing artifact against it - in ANY direction: an edit to a later artifact may require revising an earlier one, not only the other way around. Build order is a useful reading order, not a constraint on which artifacts may be revised. + - Note everything that is now inconsistent, missing, or contradictory. + - Revise only files that already exist (`existingOutputPaths`). Do NOT create artifacts that don't exist yet, and do NOT invent new files under a glob artifact - note them and point the user to `/opsx:continue` to create them. + - If the change is already coherent, say so and make no edits. + +5. **Confirm and apply, one artifact at a time** + - Show each proposed revision and why. Write only after the user confirms. + - If the user rejects a revision, do not write it - leave that artifact unchanged. + - When a substantial rewrite is needed, get that artifact's rules and template first: + ```bash + openspec instructions "" --change "" --json + ``` + +6. **Point to the next step (guidance only - NEVER act on it)** + - Artifacts still missing -> suggest `/opsx:continue` to create them. + - Change already implemented (tasks checked off / already applied) -> the code may no longer match the revised plan; suggest `/opsx:apply` to carry the delta into code. + - Everything done and implemented -> suggest `/opsx:archive`. + +**Output** + +After each invocation, show: +- Which artifacts were revised (and which proposed revisions were rejected) +- Anything deferred to `/opsx:continue` (not-yet-created artifacts or files) +- Where the change stands and the recommended next command + +**Guardrails** +- Planning artifacts only - NEVER edit implementation code. If the revised plan implies code changes, stop and point to `/opsx:apply`. +- Use the artifact ids and paths reported by `openspec status`; never branch on hardcoded artifact names. +- Edit only the concrete files in `existingOutputPaths`; never write to a glob `resolvedOutputPath`. +- Do not advance the build frontier: no new artifacts, no new files under glob artifacts - that is `/opsx:continue`'s job. +- Confirm every edit with the user before writing. +- If the request changes the change's *intent* rather than refining it, first verify whether the optional `/opsx:new` workflow is available. If it is, recommend starting fresh with `/opsx:new` (the "Update vs. Start Fresh" heuristic). If it is unavailable, ask for a distinct unused change name and recommend `openspec new change ""` instead. diff --git a/.claude/skills/openspec-verify-change/SKILL.md b/.claude/skills/openspec-verify-change/SKILL.md new file mode 100644 index 0000000..f06d450 --- /dev/null +++ b/.claude/skills/openspec-verify-change/SKILL.md @@ -0,0 +1,175 @@ +--- +name: openspec-verify-change +description: Verify implementation matches change artifacts. Use when the user wants to validate that implementation is complete, correct, and coherent before archiving. +allowed-tools: Bash(openspec:*) +license: MIT +compatibility: Requires openspec CLI. +metadata: + author: openspec + version: "1.0" + generatedBy: "1.13.0" +--- + +Verify that an implementation matches the change artifacts (specs, tasks, design). + +**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. + +**Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes. + +**Steps** + +1. **Select the change** + + If a name is provided, use it. Otherwise: + - Infer from conversation context if the user mentioned a change + - Auto-select if only one active change exists + - If ambiguous, run `openspec list --json` to get available changes and ask the user to select one + + When prompting, show changes that have implementation tasks (tasks artifact exists). + Include the schema used for each change if available. + Mark changes with incomplete tasks as "(In Progress)". + + Always announce: "Using change: " and how to override (e.g., `/opsx:verify `). + +2. **Check status to understand the schema** + ```bash + openspec status --change "" --json + ``` + Parse the JSON to understand: + - `schemaName`: The workflow being used (e.g., "spec-driven") + - `planningHome`, `changeRoot`, `artifactPaths`, and `actionContext`: path and scope context + - Which artifacts exist for this change + +3. **Get planning context and load artifacts** + + ```bash + openspec instructions apply --change "" --json + ``` + + This returns the change directory and `contextFiles` (artifact ID -> array of concrete file paths). Read all available artifacts from `contextFiles`. + +4. **Initialize verification report structure** + + Create a report structure with three dimensions: + - **Completeness**: Track tasks and spec coverage + - **Correctness**: Track requirement implementation and scenario coverage + - **Coherence**: Track design adherence and pattern consistency + + Each dimension can have CRITICAL, WARNING, or SUGGESTION issues. + +5. **Verify Completeness** + + **Task Completion**: + - If `contextFiles.tasks` exists, read every file path in it + - Parse checkboxes: `- [ ]` (incomplete) vs `- [x]` (complete) + - Count complete vs total tasks + - If incomplete tasks exist: + - Add CRITICAL issue for each incomplete task + - Recommendation: "Complete task: " or "Mark as done if already implemented" + + **Spec Coverage**: + - If delta specs exist in `contextFiles.specs`: + - Extract all requirements (marked with "### Requirement:") + - For each requirement: + - Search codebase for keywords related to the requirement + - Assess if implementation likely exists + - If requirements appear unimplemented: + - Add CRITICAL issue: "Requirement not found: " + - Recommendation: "Implement requirement X: " + +6. **Verify Correctness** + + **Requirement Implementation Mapping**: + - For each requirement from delta specs: + - Search codebase for implementation evidence + - If found, note file paths and line ranges + - Assess if implementation matches requirement intent + - If divergence detected: + - Add WARNING: "Implementation may diverge from spec:
" + - Recommendation: "Review : against requirement X" + + **Scenario Coverage**: + - For each scenario in delta specs (marked with "#### Scenario:"): + - Check if conditions are handled in code + - Check if tests exist covering the scenario + - If scenario appears uncovered: + - Add WARNING: "Scenario not covered: " + - Recommendation: "Add test or implementation for scenario: " + +7. **Verify Coherence** + + **Design Adherence**: + - If `contextFiles.design` exists: + - Extract key decisions (look for sections like "Decision:", "Approach:", "Architecture:") + - Verify implementation follows those decisions + - If contradiction detected: + - Add WARNING: "Design decision not followed: " + - Recommendation: "Update implementation or revise design.md to match reality" + - If no design.md: Skip design adherence check, note "No design.md to verify against" + + **Code Pattern Consistency**: + - Review new code for consistency with project patterns + - Check file naming, directory structure, coding style + - If significant deviations found: + - Add SUGGESTION: "Code pattern deviation:
" + - Recommendation: "Consider following project pattern: " + +8. **Generate Verification Report** + + **Summary Scorecard**: + ```markdown + ## Verification Report: + + ### Summary + | Dimension | Status | + |--------------|------------------| + | Completeness | X/Y tasks, N reqs| + | Correctness | M/N reqs covered | + | Coherence | Followed/Issues | + ``` + + **Issues by Priority**: + + 1. **CRITICAL** (Must fix before archive): + - Incomplete tasks + - Missing requirement implementations + - Each with specific, actionable recommendation + + 2. **WARNING** (Should fix): + - Spec/design divergences + - Missing scenario coverage + - Each with specific recommendation + + 3. **SUGGESTION** (Nice to fix): + - Pattern inconsistencies + - Minor improvements + - Each with specific recommendation + + **Final Assessment**: + - If CRITICAL issues: "X critical issue(s) found. Fix before archiving." + - If only warnings: "No critical issues. Y warning(s) to consider. Ready for archive (with noted improvements)." + - If all clear: "All checks passed. Ready for archive." + +**Verification Heuristics** + +- **Completeness**: Focus on objective checklist items (checkboxes, requirements list) +- **Correctness**: Use keyword search, file path analysis, reasonable inference - don't require perfect certainty +- **Coherence**: Look for glaring inconsistencies, don't nitpick style +- **False Positives**: When uncertain, prefer SUGGESTION over WARNING, WARNING over CRITICAL +- **Actionability**: Every issue must have a specific recommendation with file/line references where applicable + +**Graceful Degradation** + +- If only tasks.md exists: verify task completion only, skip spec/design checks +- If tasks + specs exist: verify completeness and correctness, skip design +- If full artifacts: verify all three dimensions +- Always note which checks were skipped and why + +**Output Format** + +Use clear markdown with: +- Table for summary scorecard +- Grouped lists for issues (CRITICAL/WARNING/SUGGESTION) +- Code references in format: `file.ts:123` +- Specific, actionable recommendations +- No vague suggestions like "consider reviewing" diff --git a/.github/prompts/opsx-bulk-archive.prompt.md b/.github/prompts/opsx-bulk-archive.prompt.md new file mode 100644 index 0000000..01bff3d --- /dev/null +++ b/.github/prompts/opsx-bulk-archive.prompt.md @@ -0,0 +1,332 @@ +--- +description: "Archive multiple completed changes at once" +--- + +Archive multiple completed changes in a single operation. + +This skill allows you to batch-archive changes, handling spec conflicts intelligently by checking the codebase to determine what's actually implemented. + +**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. + +`` is the spec directory relative to `specs/` (for example, `user-auth` or `identity/user-auth`). Preserve the full path from each delta spec when resolving its main spec. + +**Input**: None required (prompts for selection) + +**Steps** + +1. **Get active changes** + + Run `openspec list --json` to get all active changes. + + If no active changes exist, inform user and stop. + +2. **Prompt for change selection** + + Ask the user to choose changes (multi-select): + - Show each change with its schema + - Include an option for "All changes" + - Allow any number of selections (1+ works, 2+ is the typical use case) + + **IMPORTANT**: Do NOT auto-select. Always let the user choose. + + **Load current archive inputs once for the selected root before batch validation:** + + Choose one selected change from this root and run + `openspec instructions archive --change "" --json` with the + same selected-root flags. This lookup is advisory and optional: it only supplies + extra prompt inputs, so it must never block the batch. If it fails or returns + invalid JSON — for example on an older CLI that does not support this command + yet — continue the batch with no context and no operation guidance. Do not + report an error and do not stop. + + A valid response may omit `context` and `operationGuidance`. Treat + `context` as a required prompt-level input across the batch: read and consider + it, and apply relevant project facts, conventions, and constraints. Treat + `operationGuidance` as optional additive advice: read and consider every + entry, and follow entries that are applicable and compatible with the built-in + batch workflow. + + Keep both fields separate from conflict analysis, explicit user choices, + resolved paths, CLI checks, and command contracts. If context conflicts with one + of those controlling inputs, report the conflict and preserve the controlling + value. If guidance is inapplicable or conflicts with a controlling input, do not + follow it and explain why. Do not infer skipped prompts, replacement paths, or + flags from either field, and do not copy their text verbatim into specs, changes, + or summaries. These are prompt-level behavior contracts, not enforceable checks. + +3. **Batch validation - gather status for all selected changes** + + For each selected change, collect: + + a. **Artifact status** - Run `openspec status --change "" --json` + - Parse `schemaName`, `artifacts`, `planningHome`, `changeRoot`, `artifactPaths`, and `actionContext` + - Note which artifacts are `done` vs other states + + b. **Task completion** - Read `artifactPaths.tasks.existingOutputPaths` from status JSON + - Count `- [ ]` (incomplete) vs `- [x]` (complete) + - If no tasks file exists, note as "No tasks" + + c. **Delta specs** - Check `artifactPaths.specs.existingOutputPaths` from status JSON + - List which capability specs exist + - For each, extract requirement names (lines matching `### Requirement: `) + - Treat this list as the only delta-spec source. If the `specs` entry is + missing or the list is empty, perform no spec sync or specs-instruction + lookup for that change; do not infer deltas from unrelated artifacts. + - Evaluate this independently for every change, including mixed-schema + batches where some schemas have no `specs` artifact. + +4. **Detect spec conflicts** + + Build a map keyed by ``, the exact path relative to `specs/`: + + ```text + identity/user-auth -> [change-a, change-b] <- CONFLICT (2+ changes) + billing/user-auth -> [change-c] <- OK (different full path) + ``` + + A conflict exists when 2+ selected changes have delta specs for the exact same ``. + +5. **Resolve conflicts agentically** + + **For each conflict**, investigate the codebase: + + a. **Read the delta specs** from each conflicting change to understand what each claims to add/modify + + b. **Search the codebase** for implementation evidence: + - Look for code implementing requirements from each delta spec + - Check for related files, functions, or tests + + c. **Determine resolution**: + - If only one change is actually implemented -> sync that one's specs + - If both implemented -> apply in chronological order (older first, newer overwrites) + - If neither implemented -> skip spec sync, warn user + + d. **Record resolution** for each conflict: + - An inclusion or exclusion decision for every delta spec, keyed by change and `` + - Which included delta specs to apply and in what order + - Which delta specs to exclude from sync because their implementation is missing + - Rationale (what was found in codebase) + +6. **Show consolidated status table** + + Display a table summarizing all changes: + + ```markdown + | Change | Artifacts | Tasks | Specs | Conflicts | Status | + |---------------------|-----------|-------|---------|-----------|--------| + | schema-management | Done | 5/5 | 2 delta | None | Ready | + | project-config | Done | 3/3 | 1 delta | None | Ready | + | add-oauth | Done | 4/4 | 1 delta | identity/user-auth (!) | Ready* | + | add-verify-skill | 1 left | 2/5 | None | None | Warn | + ``` + + For conflicts, show the resolution: + ```text + * Conflict resolution: + - identity/user-auth spec: Will apply add-oauth then add-jwt (both implemented, chronological order) + ``` + + For incomplete changes, show warnings: + ```text + Warnings: + - add-verify-skill: 1 incomplete artifact, 3 incomplete tasks + ``` + +7. **Confirm batch operation** + + Ask the user a single confirmation question: + + - "Archive N changes?" with options based on status + - Options might include: + - "Archive all N changes" + - "Archive only N ready changes (skip incomplete)" + - "Cancel" + + If there are incomplete changes, make clear they'll be archived with warnings. + + Route on the answer by intent, not by exact label — you wrote these labels, + so match what the user picked rather than the wording above: + - "Cancel" — stop, do not archive. Report that nothing was archived and skip the remaining steps. + - The archive-everything option — proceed with every selected change + - The ready-only option — proceed with only the changes the step 6 table marks `Ready` or `Ready*`, and record the rest as Skipped in step 8d. If a `Ready*` change's conflict partner is skipped, re-derive that conflict's resolution using only the changes being archived. + - Anything else — ask again rather than archiving + + Before step 8 writes the first main spec or moves any change, fetch every + required specs-rule snapshot for the confirmed batch. For each change that will + sync concrete `artifactPaths.specs.existingOutputPaths`, run + `openspec instructions specs --change "" --json` exactly once with the + same selected-root flags. Obtain all snapshots before the first write or move. + If any lookup exits non-zero or returns invalid artifact-instruction JSON, + identify the affected change, report the error, and stop the whole batch before + any main-spec write or change move. Do not treat lookup failure as omitted + rules. A valid response without `rules` is the no-rules case. + +8. **Execute archive for each confirmed change** + + Before processing, carry the recorded decisions from step 5 (after any step 7 re-derivation) into two per-delta sets: + - `includedDeltas`: all non-conflicting delta specs from confirmed changes plus conflict deltas selected for sync + - `excludedDeltas`: conflict deltas from confirmed changes excluded because their implementation is missing + - A single change can have both included and excluded delta specs. Keep the decision per delta; do not collapse it into a per-change sync flag. + + Process changes in the determined order (respecting conflict resolution): + + a. **Sync included delta specs**: + - Run the `/opsx-sync` workflow inline (agent-driven intelligent merge) only for changes with entries in `includedDeltas`, passing only the included delta paths and explicitly instructing it to ignore that change's `excludedDeltas`. Wait for it to finish. + - For conflicts, apply in resolved order. + - Pass that change's fetched specs-rule snapshot into inline sync; inline + sync must reuse it without fetching instructions again + - Apply artifact rules only to main specs produced by that change. They do + not change conflict resolution, archive behavior, or CLI contracts, and + their text is not copied into an output file + - Do not delegate to a background task — step 8c would move `changeRoot` out from under a sync that is still reading it. + - If a change has no included delta specs, do not run the sync workflow for it. + + b. **Verify included delta specs before moving changeRoot**: + - Re-run the comparison only for delta specs in `includedDeltas` against main spec at `/openspec/specs//spec.md` (use the store-aware `planningHome.root` from step 3 status JSON, not a hardcoded repo path). + - Verify that main specs are updated: + - ADDED requirements present + - MODIFIED requirements carrying scenario and description changes named in the delta, with their other scenarios intact + - REMOVED requirements gone — and where this sync retired a capability (removed its last requirement, leaving `## Requirements` empty), its main spec deleted rather than left empty; a spec the sync deliberately kept and reported is also a match + - RENAMED requirements present under the new name and absent under the old one + - Do not verify delta specs in `excludedDeltas`; they are intentionally left unsynced. + - If sync failed or any capability does not match verification, report what differs and fail/skip moving that change's `changeRoot` — do not archive that change. `changeRoot` remains intact. + + c. **Perform the archive**: + + Target name: use the change name as-is when it already starts with a `YYYY-MM-DD-` prefix; otherwise prepend the current date as `YYYY-MM-DD-` (same rule as `openspec archive`). + + ```bash + mkdir -p "/archive" + mv "" "/archive/" + ``` + + d. **Track outcome** for each change: + - Success: archived successfully + - Failed: error during archive or spec verification (record error) + - Skipped: user chose not to archive (if applicable) + - Sync skipped: for every delta in `excludedDeltas`, report `sync skipped` with the change, ``, and recorded reason. This is distinct from skipping the archive. + +9. **Display summary** + + Show final results: + + ```markdown + ## Bulk Archive Complete + + Archived 3 changes: + - schema-management-cli -> archive/2026-01-19-schema-management-cli/ + - project-config -> archive/2026-01-19-project-config/ + - add-oauth -> archive/2026-01-19-add-oauth/ + + Skipped 1 change: + - add-verify-skill (user chose not to archive incomplete) + + Spec sync summary: + - 4 delta specs synced to main specs + - 1 delta spec sync skipped (add-jwt, identity/user-auth: implementation not found) + - 1 conflict resolved (identity/user-auth: synced add-oauth, skipped add-jwt) + ``` + + If any failures: + ```text + Failed 1 change: + - some-change: Archive directory already exists + ``` + +**Conflict Resolution Examples** + +Example 1: Only one implemented +```text +Conflict: /openspec/specs/auth/spec.md touched by [add-oauth, add-jwt] + +Checking add-oauth: +- Delta adds "OAuth Provider Integration" requirement +- Searching codebase... found src/auth/oauth.ts implementing OAuth flow + +Checking add-jwt: +- Delta adds "JWT Token Handling" requirement +- Searching codebase... no JWT implementation found + +Resolution: Only add-oauth is implemented. Will sync add-oauth specs only. +``` + +Example 2: Both implemented +```text +Conflict: /openspec/specs/api/spec.md touched by [add-rest-api, add-graphql] + +Checking add-rest-api (created 2026-01-10): +- Delta adds "REST Endpoints" requirement +- Searching codebase... found src/api/rest.ts + +Checking add-graphql (created 2026-01-15): +- Delta adds "GraphQL Schema" requirement +- Searching codebase... found src/api/graphql.ts + +Resolution: Both implemented. Will apply add-rest-api specs first, +then add-graphql specs (chronological order, newer takes precedence). +``` + +**Output On Success** + +```markdown +## Bulk Archive Complete + +Archived N changes: +- -> archive// +- -> archive// + +Spec sync summary: +- N delta specs synced to main specs +- No conflicts (or: M conflicts resolved) +``` + +**Output On Partial Success** + +```markdown +## Bulk Archive Complete (partial) + +Archived N changes: +- -> archive// + +Skipped M changes: +- (user chose not to archive incomplete) + +Failed K changes: +- : Archive directory already exists +``` + +**Output When No Changes** + +```markdown +## No Changes to Archive + +No active changes found. Create a new change to get started. +``` + +**Guardrails** +- Allow any number of changes (1+ is fine, 2+ is the typical use case) +- Always prompt for selection, never auto-select +- Detect spec conflicts early and resolve by checking codebase +- When both changes are implemented, apply specs in chronological order +- Skip spec sync only when implementation is missing (warn user) +- Show clear per-change status before confirming +- Use single confirmation for entire batch +- Never archive after the user cancels the confirmation — a cancelled batch archives nothing +- Track and report all outcomes (success/skip/fail) +- Preserve .openspec.yaml when moving to archive +- Archive directory target uses current date: YYYY-MM-DD-; a name that already starts with a `YYYY-MM-DD-` prefix is used as-is (never stack a second date) +- If archive target exists, fail that change but continue with others +- If sync is requested, run the `/opsx-sync` workflow inline (agent-driven) for each change with included delta specs +- Carry the per-delta `includedDeltas` and `excludedDeltas` decisions into execution; sync and verify only included deltas +- Report every excluded delta as `sync skipped` without treating the archive itself as skipped +- Never archive a change while a spec sync is still in flight — run the sync inline and verify main specs at `/openspec/specs//spec.md` before moving `changeRoot` +- Fetch archive inputs once per selected root before spec inspection or moves +- Fetch all required specs-rule snapshots before the batch's first main-spec write or move +- A failed archive-inputs lookup never blocks the batch; it proceeds with no context or guidance +- A failed specs instruction lookup stops the whole batch atomically +- Changes without concrete `artifactPaths.specs.existingOutputPaths` continue without spec sync +- Apply relevant runtime context across the batch and report conflicts +- Operation guidance remains advisory; consider every entry and explain rejected advice +- Keep runtime inputs, conflict analysis, CLI-derived values, and artifact rules separate +- Artifact rules constrain only written specs +- Never copy runtime input or artifact-rule text verbatim into output files diff --git a/.github/prompts/opsx-continue.prompt.md b/.github/prompts/opsx-continue.prompt.md new file mode 100644 index 0000000..1b12703 --- /dev/null +++ b/.github/prompts/opsx-continue.prompt.md @@ -0,0 +1,110 @@ +--- +description: "Continue working on a change - create the next artifact (Experimental)" +--- + +Continue working on a change by creating the next artifact. + +**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. + +**Input**: Optionally specify a change name after `/opsx-continue` (e.g., `/opsx-continue add-auth`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes. + +**Steps** + +1. **Select the change** + + If a name is provided, use it. Otherwise: + - Infer from conversation context if the user mentioned a change + - Auto-select if only one active change exists + - If ambiguous, run `openspec list --json` to get available changes sorted by most recently modified, and ask the user to select one + + When prompting, present the top 3-4 most recently modified changes as options, showing: + - Change name + - Schema (from `schema` field if present, otherwise "spec-driven") + - Status (e.g., "0/5 tasks", "complete", "no tasks") + - How recently it was modified (from `lastModified` field) + + Mark the most recently modified change as "(Recommended)" since it's likely what the user wants to continue. + + Always announce: "Using change: " and how to override (e.g., `/opsx-continue `). + +2. **Check current status** + ```bash + openspec status --change "" --json + ``` + Parse the JSON to understand current state. The response includes: + - `schemaName`: The workflow schema being used (e.g., "spec-driven") + - `artifacts`: Array of artifacts with their status ("done", "skipped", "ready", "blocked") + - `isPlanningComplete`: Boolean indicating if all planning artifacts are complete. Older CLI versions expose the same value as `isComplete`. + - `planningHome`, `changeRoot`, `artifactPaths`, and `actionContext`: path and scope context. Use these instead of assuming repo-local paths. + +3. **Act based on status**: + + --- + + **If all planning artifacts are complete (`isPlanningComplete: true`, or legacy `isComplete: true`)**: + - Congratulate the user + - Show final status including the schema used + - Suggest: "Planning is complete! You can now implement this change with `/opsx-apply`. Once implementation and any tracked work are complete, archive it with `/opsx-archive`." + - STOP + + --- + + **If artifacts are ready to create** (status shows artifacts with `status: "ready"`): + - Pick the FIRST artifact with `status: "ready"` from the status output + - Get its instructions: + ```bash + openspec instructions --change "" --json + ``` + - Parse the JSON. The key fields are: + - `context`: Project background (constraints for you - do NOT include in output) + - `rules`: Artifact-specific rules (constraints for you - do NOT include in output) + - `template`: The structure to use for your output file + - `instruction`: Schema-specific guidance + - `resolvedOutputPath`: Resolved path or pattern to write the artifact + - `dependencies`: Completed artifacts to read for context (entries with `skipped: true` have no files - do not look for them) + - `skipped`/`warning`: present when the change declares skip_specs and this artifact must NOT be created - pick another artifact + - **Create the artifact file**: + - Read any completed dependency files for context - always re-read them from disk, even if you saw them earlier in the conversation (the user may have edited them) + - If the `instruction` field delegates creation to a specific skill or command, invoke it to produce the artifact instead of writing the file yourself, then verify the artifact file exists at `resolvedOutputPath` + - Otherwise use `template` as the structure - fill in its sections + - Apply `context` and `rules` as constraints when writing - but do NOT copy them into the file + - Write to the `resolvedOutputPath` specified in instructions. If it is a glob pattern, choose the concrete file path using the schema instruction and the change's context + - Show what was created and what's now unlocked + - STOP after creating ONE artifact + + --- + + **If no artifacts are ready (all blocked)**: + - This shouldn't happen with a valid schema + - Show status and suggest checking for issues + +4. **After creating an artifact, show progress** + ```bash + openspec status --change "" + ``` + +**Output** + +After each invocation, show: +- Which artifact was created +- Schema workflow being used +- Current progress (N/M complete) +- What artifacts are now unlocked +- Prompt: "Run `/opsx-continue` to create the next artifact" + +**Artifact Creation Guidelines** + +The artifact types and their purpose depend on the schema. The `instruction` field from the instructions output is the authoritative guidance for each artifact - follow it even when the artifact has a familiar name (proposal.md, tasks.md, etc.), since custom schemas may define different content or a different process for the same file names. + +If the `instruction` field directs you to use a specific skill or command to create the artifact, invoke it instead of writing the artifact directly. + +**Guardrails** +- Create ONE artifact per invocation +- Always read dependency artifacts before creating a new one - re-read from disk, not from conversation memory (files may have changed since you last saw them) +- Never skip artifacts or create out of order +- If context is unclear, ask the user before creating +- Verify the artifact file exists after writing before marking progress +- Use the schema's artifact sequence, don't assume specific artifact names +- **IMPORTANT**: `context` and `rules` are constraints for YOU, not content for the file + - Do NOT copy ``, ``, `` blocks into the artifact + - These guide what you write, but should never appear in the output diff --git a/.github/prompts/opsx-ff.prompt.md b/.github/prompts/opsx-ff.prompt.md new file mode 100644 index 0000000..32bff19 --- /dev/null +++ b/.github/prompts/opsx-ff.prompt.md @@ -0,0 +1,109 @@ +--- +description: "Create a change and generate all artifacts needed for implementation in one go" +--- + +Fast-forward through artifact creation - generate everything needed to start implementation. + +**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. + +**Input**: The argument after `/opsx-ff` is the change name (kebab-case), OR a description of what the user wants to build. + +**Steps** + +1. **If no input provided, ask what they want to build** + + Ask the user (open-ended, no preset options): + > "What change do you want to work on? Describe what you want to build or fix." + + From their description, derive a kebab-case name (e.g., "add user authentication" → `add-user-auth`). + + **IMPORTANT**: Do NOT proceed without understanding what the user wants to build. + +2. **Create the change directory** + ```bash + openspec new change "" + ``` + This creates a scaffolded change in the planning home resolved by the CLI. + +3. **Get the artifact build order** + ```bash + openspec status --change "" --json + ``` + Parse the JSON to get: + - `applyRequires`: array of artifact IDs needed before implementation (e.g., `["tasks"]`) + - `artifacts`: list of all artifacts, each with its `status` and its `requires` edges (the artifact IDs it directly depends on) + - `planningHome`, `changeRoot`, `artifactPaths`, and `actionContext`: path and scope context. Use these instead of assuming repo-local paths. + +4. **Create every artifact in the required set** + + Use a todo list to track progress through the artifacts. + + Loop through artifacts in dependency order (artifacts with no pending dependencies first): + + a. **For each artifact that is `ready` (dependencies satisfied)**: + - Get instructions: + ```bash + openspec instructions --change "" --json + ``` + - The instructions JSON includes: + - `context`: Project background (constraints for you - do NOT include in output) + - `rules`: Artifact-specific rules (constraints for you - do NOT include in output) + - `template`: The structure to use for your output file + - `instruction`: Schema-specific guidance for this artifact type + - `skipped`/`warning`: present when the change declares skip_specs and this artifact must NOT be created - stop and pick another artifact + - `resolvedOutputPath`: Resolved path or pattern to write the artifact + - `dependencies`: Completed artifacts to read for context + - Read any completed dependency files for context - always re-read them from disk, even if you saw them earlier in the conversation (the user may have edited them) + - **Inspect the relevant project before drafting**: Read `context` and `rules` first, then inspect relevant implementation, nearby tests, configuration, and documentation outside `openspec/`. Keep inspection read-only and proportional to the change; reuse findings for later artifacts and inspect more only as needed. + - Identify the target project from the request and project context; the planning home may be separate from the code. If the target is unclear, ask. For greenfield or non-code changes, inspect the available structure and relevant documents. If source is unavailable, state the limitation and ask when it materially affects the plan. + - Ground scope, approach, and tasks in what you find. Distinguish observed behavior from assumptions and proposed additions; surface conflicts with existing specs instead of silently deciding which is correct. + - Do this discovery now, rather than leaving generic "explore the codebase" or "make a plan" tasks for implementation. Keep any necessary follow-up investigation specific to an unresolved question. + - If the `instruction` field delegates creation to a specific skill or command, invoke it to produce the artifact instead of writing the file yourself, then verify the artifact file exists at `resolvedOutputPath` + - Otherwise create the artifact file using `template` as the structure and write it to `resolvedOutputPath`. If `resolvedOutputPath` is a glob, follow `instruction` to choose the concrete file path + - Apply `context` and `rules` as constraints - but do NOT copy them into the file + - Show brief progress: "✓ Created " + + b. **Continue until every artifact in the required set exists (not just `apply.requires`)** + - After creating each artifact, re-run `openspec status --change "" --json` + - The required set is `applyRequires` plus every artifact reachable from those by following the `requires` edges in `status --json` - walk them transitively (spec-driven closes over proposal, specs, design, tasks). Leave artifacts outside that set alone + - `status` is file-existence only, so an `applyRequires` artifact reading `done` does NOT mean its dependencies exist - writing `tasks.md` early marks `tasks` done while `specs` was never written. Use each artifact's `requires` edges, not its `status`, to build the required set: a `done` artifact still lists what it depends on + - An artifact already reading `status: "skipped"` is satisfied: the change declares `skip_specs` in `.openspec.yaml`, so its files must NOT exist. Never try to create one + - Create every artifact in the required set that is missing, then re-check - creating one can unblock others + - Skip one only when `status` already reports it `skipped`, or when its own `instruction` says it is conditional: run `openspec instructions --change "" --json` and skip only if its `instruction` field marks it optional (e.g. "create only if..."). Spec-driven's `design.md` qualifies; `specs` qualifies only via the `skipped` status above, never by your own judgment. Tell the user, and do not reconsider it + - Dependencies are enablers, not gates: if a required artifact is still `blocked` only because you skipped a conditional dependency, write it anyway + - Stop when every artifact in the required set is `done`, `skipped`, or was deliberately skipped + + c. **If an artifact requires user input** (unclear context): + - Ask the user to clarify + - Then continue with creation + +5. **Show final status** + ```bash + openspec status --change "" + ``` + +**Output** + +After completing all artifacts, summarize: +- Change name and location +- List of artifacts created with brief descriptions, plus any conditional artifact you skipped and why +- What's ready: "All artifacts needed for implementation are ready." +- Prompt: "Run `/opsx-apply` to start implementing." + +**Artifact Creation Guidelines** + +- Follow the `instruction` field from `openspec instructions` for each artifact type - it is the authoritative guidance, even for familiar artifact names +- If the `instruction` field directs you to use a specific skill or command to create the artifact, invoke it instead of writing the artifact directly +- The schema defines what each artifact should contain - follow it +- Read dependency artifacts for context before creating new ones +- Use `template` as the structure for your output file - fill in its sections +- **IMPORTANT**: `context` and `rules` are constraints for YOU, not content for the file + - Do NOT copy ``, ``, `` blocks into the artifact + - These guide what you write, but should never appear in the output + +**Guardrails** +- Create every artifact the apply phase transitively depends on, not just the ids listed in `apply.requires` +- Always read dependency artifacts before creating a new one - re-read from disk, not from conversation memory (files may have changed since you last saw them) +- If context is critically unclear, ask the user - but prefer making reasonable decisions to keep momentum +- If a change with that name already exists, ask if user wants to continue it or create a new one +- Verify each artifact file exists after writing before proceeding to next diff --git a/.github/prompts/opsx-new.prompt.md b/.github/prompts/opsx-new.prompt.md new file mode 100644 index 0000000..e48e012 --- /dev/null +++ b/.github/prompts/opsx-new.prompt.md @@ -0,0 +1,68 @@ +--- +description: "Start a new change using the experimental artifact workflow (OPSX)" +--- + +Start a new change using the experimental artifact-driven approach. + +**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. + +**Input**: The argument after `/opsx-new` is the change name (kebab-case), OR a description of what the user wants to build. + +**Steps** + +1. **If no input provided, ask what they want to build** + + Ask the user (open-ended, no preset options): + > "What change do you want to work on? Describe what you want to build or fix." + + From their description, derive a kebab-case name (e.g., "add user authentication" → `add-user-auth`). + + **IMPORTANT**: Do NOT proceed without understanding what the user wants to build. + +2. **Determine the workflow schema** + + Use the default schema (omit `--schema`) unless the user explicitly requests a different workflow. + + **Use a different schema only if the user mentions:** + - A specific schema name → use `--schema ` + - "show workflows" or "what workflows" → run `openspec schemas --json` and let them choose + + **Otherwise**: Omit `--schema` to use the default. + +3. **Create the change directory** + ```bash + openspec new change "" + ``` + Add `--schema ` only if the user requested a specific workflow. + This creates a scaffolded change in the planning home resolved by the CLI. + +4. **Show the artifact status** + ```bash + openspec status --change "" --json + ``` + Use the returned `planningHome`, `changeRoot`, `artifactPaths`, and `nextSteps` instead of assuming repo-local paths. + +5. **Get instructions for the first artifact** + The first artifact depends on the schema. Check the status output to find the first artifact with status "ready". + ```bash + openspec instructions --change "" + ``` + This outputs the template and context for creating the first artifact. + +6. **STOP and wait for user direction** + +**Output** + +After completing the steps, summarize: +- Change name and location +- Schema/workflow being used and its artifact sequence +- Current status (0/N artifacts complete) +- The template for the first artifact +- Prompt: "Ready to create the first artifact? Run `/opsx-continue` or just describe what this change is about and I'll draft it." + +**Guardrails** +- Do NOT create any artifacts yet - just show the instructions +- Do NOT advance beyond showing the first artifact template +- If the name is invalid (not kebab-case), ask for a valid name +- If a change with that name already exists, suggest using `/opsx-continue` instead +- Pass --schema if using a non-default workflow diff --git a/.github/prompts/opsx-onboard.prompt.md b/.github/prompts/opsx-onboard.prompt.md new file mode 100644 index 0000000..90a0373 --- /dev/null +++ b/.github/prompts/opsx-onboard.prompt.md @@ -0,0 +1,553 @@ +--- +description: "Guided onboarding - walk through a complete OpenSpec workflow cycle with narration" +--- + +Guide the user through their first complete OpenSpec workflow cycle. This is a teaching experience—you'll do real work in their codebase while explaining each step. + +**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. + +--- + +## Preflight + +Before starting, check if the OpenSpec CLI is installed: + +```bash +# Unix/macOS +openspec --version 2>&1 || echo "CLI_NOT_INSTALLED" +# Windows (PowerShell) +# if (Get-Command openspec -ErrorAction SilentlyContinue) { openspec --version } else { echo "CLI_NOT_INSTALLED" } +``` + +**If CLI not installed:** +> OpenSpec CLI is not installed. Install it first, then come back to `/opsx-onboard`. + +Stop here if not installed. + +--- + +## Phase 1: Welcome + +Display: + +``` +## Welcome to OpenSpec! + +I'll walk you through a complete change cycle—from idea to implementation—using a real task in your codebase. Along the way, you'll learn the workflow by doing it. + +**What we'll do:** +1. Pick a small, real task in your codebase +2. Explore the problem briefly +3. Create a change (the container for our work) +4. Build the artifacts: proposal → specs → design → tasks +5. Implement the tasks +6. Archive the completed change + +**Time:** ~15-20 minutes + +Let's start by finding something to work on. +``` + +--- + +## Phase 2: Task Selection + +### Codebase Analysis + +Scan the codebase for small improvement opportunities. Look for: + +1. **TODO/FIXME comments** - Search for `TODO`, `FIXME`, `HACK`, `XXX` in code files +2. **Missing error handling** - `catch` blocks that swallow errors, risky operations without try-catch +3. **Functions without tests** - Cross-reference `src/` with test directories +4. **Type issues** - `any` types in TypeScript files (`: any`, `as any`) +5. **Debug artifacts** - `console.log`, `console.debug`, `debugger` statements in non-debug code +6. **Missing validation** - User input handlers without validation + +Also check recent git activity: +```bash +# Unix/macOS +git log --oneline -10 2>/dev/null || echo "No git history" +# Windows (PowerShell) +# git log --oneline -10 2>$null; if ($LASTEXITCODE -ne 0) { echo "No git history" } +``` + +### Present Suggestions + +From your analysis, present 3-4 specific suggestions: + +``` +## Task Suggestions + +Based on scanning your codebase, here are some good starter tasks: + +**1. [Most promising task]** + Location: `src/path/to/file.ts:42` + Scope: ~1-2 files, ~20-30 lines + Why it's good: [brief reason] + +**2. [Second task]** + Location: `src/another/file.ts` + Scope: ~1 file, ~15 lines + Why it's good: [brief reason] + +**3. [Third task]** + Location: [location] + Scope: [estimate] + Why it's good: [brief reason] + +**4. Something else?** + Tell me what you'd like to work on. + +Which task interests you? (Pick a number or describe your own) +``` + +**If nothing found:** Fall back to asking what the user wants to build: +> I didn't find obvious quick wins in your codebase. What's something small you've been meaning to add or fix? + +### Scope Guardrail + +If the user picks or describes something too large (major feature, multi-day work): + +``` +That's a valuable task, but it's probably larger than ideal for your first OpenSpec run-through. + +For learning the workflow, smaller is better—it lets you see the full cycle without getting stuck in implementation details. + +**Options:** +1. **Slice it smaller** - What's the smallest useful piece of [their task]? Maybe just [specific slice]? +2. **Pick something else** - One of the other suggestions, or a different small task? +3. **Do it anyway** - If you really want to tackle this, we can. Just know it'll take longer. + +What would you prefer? +``` + +Let the user override if they insist—this is a soft guardrail. + +--- + +## Phase 3: Explore Demo + +Once a task is selected, briefly demonstrate explore mode: + +``` +Before we create a change, let me quickly show you **explore mode**—it's how you think through problems before committing to a direction. +``` + +Spend 1-2 minutes investigating the relevant code: +- Read the file(s) involved +- Draw a quick ASCII diagram if it helps +- Note any considerations + +``` +## Quick Exploration + +[Your brief analysis—what you found, any considerations] + +┌─────────────────────────────────────────┐ +│ [Optional: ASCII diagram if helpful] │ +└─────────────────────────────────────────┘ + +Explore mode (`/opsx-explore`) is for this kind of thinking—investigating before implementing. You can use it anytime you need to think through a problem. + +Now let's create a change to hold our work. +``` + +**PAUSE** - Wait for user acknowledgment before proceeding. + +--- + +## Phase 4: Create the Change + +**EXPLAIN:** +``` +## Creating a Change + +A "change" in OpenSpec is a container for all the thinking and planning around a piece of work. It lives at the `changeRoot` reported by `openspec status --change "" --json` and holds your artifacts—proposal, specs, design, tasks. + +Let me create one for our task. +``` + +**DO:** Create the change with a derived kebab-case name: +```bash +openspec new change "" +``` + +**SHOW:** +``` +Created: + +The folder structure: +``` +/ +├── proposal.md ← Why we're doing this (empty, we'll fill it) +├── design.md ← How we'll build it (empty) +├── specs/ ← Detailed requirements (empty) +└── tasks.md ← Implementation checklist (empty) +``` + +Now let's fill in the first artifact—the proposal. +``` + +--- + +## Phase 5: Proposal + +**EXPLAIN:** +``` +## The Proposal + +The proposal captures **why** we're making this change and **what** it involves at a high level. It's the "elevator pitch" for the work. + +I'll draft one based on our task. +``` + +**DO:** Draft the proposal content (don't save yet): + +`` is the spec directory relative to `specs/` (for example, +`user-auth` or `identity/user-auth`). Use the exact existing path for modified +capabilities. For new capabilities, follow the project's established spec +organization. + +``` +Here's a draft proposal: + +--- + +## Why + +[1-2 sentences explaining the problem/opportunity] + +## What Changes + +[Bullet points of what will be different] + +## Capabilities + +### New Capabilities +- ``: [brief description] + +### Modified Capabilities + +- ``: [brief description] + +## Impact + +- `src/path/to/file.ts`: [what changes] +- [other files if applicable] + +--- + +Does this capture the intent? I can adjust before we save it. +``` + +**PAUSE** - Wait for user approval/feedback. + +After approval, save the proposal: +```bash +openspec instructions proposal --change "" --json +``` +Then write the content to the `resolvedOutputPath` from `openspec instructions proposal --change "" --json`. + +``` +Proposal saved. This is your "why" document—you can always come back and refine it as understanding evolves. + +Next up: specs. +``` + +--- + +## Phase 6: Specs + +**EXPLAIN:** +``` +## Specs + +Specs define **what** we're building in precise, testable terms. They use a requirement/scenario format that makes expected behavior crystal clear. + +For a small task like this, we might only need one spec file. +``` + +**DO:** Resolve where the spec file should be created: +```bash +openspec instructions specs --change "" --json +# Use resolvedOutputPath from the JSON. If it is a glob, choose the concrete file path using the schema instruction and the change's context. +``` + +Draft the spec content: + +``` +Here's the spec: + +--- + +## ADDED Requirements + +### Requirement: + + + +#### Scenario: + +- **WHEN** +- **THEN** +- **AND** + +--- + +This format—WHEN/THEN/AND—makes requirements testable. You can literally read them as test cases. +``` + +Save to the concrete file path chosen from `resolvedOutputPath`. + +--- + +## Phase 7: Design + +**EXPLAIN:** +``` +## Design + +The design captures **how** we'll build it—technical decisions, tradeoffs, approach. + +For small changes, this might be brief. That's fine—not every change needs deep design discussion. +``` + +**DO:** Draft design.md: + +``` +Here's the design: + +--- + +## Context + +[Brief context about the current state] + +## Goals / Non-Goals + +**Goals:** +- [What we're trying to achieve] + +**Non-Goals:** +- [What's explicitly out of scope] + +## Decisions + +### Decision 1: [Key decision] + +[Explanation of approach and rationale] + +--- + +For a small task, this captures the key decisions without over-engineering. +``` + +Save to the `resolvedOutputPath` from `openspec instructions design --change "" --json`. + +--- + +## Phase 8: Tasks + +**EXPLAIN:** +``` +## Tasks + +Finally, we break the work into implementation tasks—checkboxes that drive the apply phase. + +These should be small, clear, and in logical order. +``` + +**DO:** Generate tasks based on specs and design: + +``` +Here are the implementation tasks: + +--- + +## 1. [Category or file] + +- [ ] 1.1 [Specific task] — verify: [test, command, observable behavior, or delivered artifact] +- [ ] 1.2 [Specific task] — verify: [test, command, observable behavior, or delivered artifact] + +## 2. Integration Verification + +- [ ] 2.1 Verify [broader integration or system behavior] with [end-to-end test or observable result] + +--- + +Each checkbox becomes a unit of work in the apply phase. Ready to implement? +``` + +**PAUSE** - Wait for user to confirm they're ready to implement. + +Save to the `resolvedOutputPath` from `openspec instructions tasks --change "" --json`. + +--- + +## Phase 9: Apply (Implementation) + +**EXPLAIN:** +``` +## Implementation + +Now we implement each task, checking them off as we go. I'll announce each one and occasionally note how the specs/design informed the approach. +``` + +**DO:** For each task: + +1. Announce: "Working on task N: [description]" +2. Implement the change in the codebase +3. Reference specs/design naturally: "The spec says X, so I'm doing Y" +4. Mark complete in tasks.md: `- [ ]` → `- [x]` +5. Brief status: "✓ Task N complete" + +Keep narration light—don't over-explain every line of code. + +After all tasks: + +``` +## Implementation Complete + +All tasks done: +- [x] Task 1 +- [x] Task 2 +- [x] ... + +The change is implemented! One more step—let's archive it. +``` + +--- + +## Phase 10: Archive + +**EXPLAIN:** +``` +## Archiving + +When a change is complete, we archive it. The archive path is derived from `planningHome.changesDir` and the date. + +Archived changes become your project's decision history—you can always find them later to understand why something was built a certain way. +``` + +**DO:** Archive the change (`--yes` answers the confirmation prompts, which you cannot answer from a tool call): +```bash +openspec archive "" --yes +``` + +**SHOW:** +``` +Archived to: `/archive//` (the target name prepends today's date, unless the name already starts with a `YYYY-MM-DD-` prefix — then it is kept as-is, no second date) + +The change is now part of your project's history. The code is in your codebase, the decision record is preserved. +``` + +--- + +## Phase 11: Recap & Next Steps + +``` +## Congratulations! + +You just completed a full OpenSpec cycle: + +1. **Explore** - Thought through the problem +2. **New** - Created a change container +3. **Proposal** - Captured WHY +4. **Specs** - Defined WHAT in detail +5. **Design** - Decided HOW +6. **Tasks** - Broke it into steps +7. **Apply** - Implemented the work +8. **Archive** - Preserved the record + +This same rhythm works for any size change—a small fix or a major feature. + +--- + +## Command Reference + +**Core workflow:** + + | Command | What it does | + |-------------------|--------------------------------------------| + | `/opsx-propose` | Create a change and generate all artifacts | + | `/opsx-explore` | Think through problems before/during work | + | `/opsx-apply` | Implement tasks from a change | + | `/opsx-archive` | Archive a completed change | + +**Additional commands** (only if installed - availability depends on your profile): + + | Command | What it does | + |--------------------|----------------------------------------------------------| + | `/opsx-new` | Start a new change, step through artifacts one at a time | + | `/opsx-continue` | Continue working on an existing change | + | `/opsx-ff` | Fast-forward: create all artifacts at once | + | `/opsx-verify` | Verify implementation matches artifacts | + +--- + +## What's Next? + +Try `/opsx-propose` on something you actually want to build. You've got the rhythm now! +``` + +--- + +## Graceful Exit Handling + +### User wants to stop mid-way + +If the user says they need to stop, want to pause, or seem disengaged: + +``` +No problem! Your change is saved at the `changeRoot` reported by `openspec status --change "" --json`. + +To pick up where we left off later: +- `/opsx-continue ` - Resume artifact creation (if installed; otherwise `openspec status --change "" --json` shows the next artifact) +- `/opsx-apply ` - Jump to implementation (if tasks exist) + +The work won't be lost. Come back whenever you're ready. +``` + +Exit gracefully without pressure. + +### User just wants command reference + +If the user says they just want to see the commands or skip the tutorial: + +``` +## OpenSpec Quick Reference + +**Core workflow:** + + | Command | What it does | + |--------------------------|--------------------------------------------| + | `/opsx-propose ` | Create a change and generate all artifacts | + | `/opsx-explore` | Think through problems (no code changes) | + | `/opsx-apply ` | Implement tasks | + | `/opsx-archive ` | Archive when done | + +**Additional commands** (only if installed - availability depends on your profile): + + | Command | What it does | + |---------------------------|-------------------------------------| + | `/opsx-new ` | Start a new change, step by step | + | `/opsx-continue ` | Continue an existing change | + | `/opsx-ff ` | Fast-forward: all artifacts at once | + | `/opsx-verify ` | Verify implementation | + +Try `/opsx-propose` to start your first change. +``` + +Exit gracefully. + +--- + +## Guardrails + +- **Follow the EXPLAIN → DO → SHOW → PAUSE pattern** at key transitions (after explore, after proposal draft, after tasks, after archive) +- **Keep narration light** during implementation—teach without lecturing +- **Don't skip phases** even if the change is small—the goal is teaching the workflow +- **Pause for acknowledgment** at marked points, but don't over-pause +- **Handle exits gracefully**—never pressure the user to continue +- **Use real codebase tasks**—don't simulate or use fake examples +- **Adjust scope gently**—guide toward smaller tasks but respect user choice diff --git a/.github/prompts/opsx-sync.prompt.md b/.github/prompts/opsx-sync.prompt.md new file mode 100644 index 0000000..9a59413 --- /dev/null +++ b/.github/prompts/opsx-sync.prompt.md @@ -0,0 +1,254 @@ +--- +description: "Sync delta specs from a change to main specs" +--- + +Sync delta specs from a change to main specs. + +This is an **agent-driven** operation - you will read delta specs and directly edit main specs to apply the changes. This allows intelligent merging (e.g., adding a scenario without copying the entire requirement). + +**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. + +`` is the spec directory relative to `specs/` (for example, `user-auth` or `identity/user-auth`). Preserve the full path from each delta spec when resolving its main spec. + +**Input**: Optionally specify a change name after `/opsx-sync` (e.g., `/opsx-sync add-auth`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes. + +**Steps** + +1. **Select the change** + + If a name is provided, use it. Otherwise: + - Infer from conversation context if the user mentioned a change + - Auto-select if only one active change exists + - If ambiguous, run `openspec list --json` to get available changes and ask the user to select one + + When prompting, show changes that have delta specs (under `specs/` directory). + + Always announce: "Using change: " and how to override (e.g., `/opsx-sync `). + +2. **Resolve change context** + + Run: + ```bash + openspec status --change "" --json + ``` + + The JSON includes `planningHome.root`. Main specs live under `/openspec/specs/` — use that (store-aware) root for every main-spec path below, not a hardcoded repo path. When a store is selected it points at the store, not the current repository. + +3. **Find delta specs** + + Use `artifactPaths.specs.existingOutputPaths` from the status JSON as the + only source of delta spec paths. If the `specs` entry is missing or + `existingOutputPaths` is empty, report that there are no delta specs to sync, + do not infer them from other artifacts, and stop without requesting artifact + instructions or writing a main spec. + + Sync every path in `existingOutputPaths` unless the caller narrowed the set. + A caller narrows it by naming an explicit list of complete entries from + `existingOutputPaths` — copy those absolute values verbatim. Archive does + this inline, and a user can too (for example, by selecting the entry ending + in `/specs/billing/invoices/spec.md`). + Then sync only the named paths and leave the remaining delta specs untouched: + bulk archive excludes a delta whose implementation it could not find, and + syncing it anyway would write a main spec the caller deliberately withheld. + Carry that narrowed selection through step 4; never widen it back to the full + list. If a named path is not in `existingOutputPaths`, do not sync it — + report it and stop, rather than dropping it silently. If the named list is + empty, report that there is nothing to sync and stop without writing a main + spec. + + Each delta spec file contains sections like: + - `## ADDED Requirements` - New requirements to add + - `## MODIFIED Requirements` - Changes to existing requirements + - `## REMOVED Requirements` - Requirements to remove + - `## RENAMED Requirements` - Requirements to rename (FROM:/TO: format) + + If no delta specs found, inform user and stop. + +4. **For each delta spec, apply changes to main specs** + + Before the first main-spec write, obtain one current specs-rule snapshot: + - If archive invoked this workflow inline and supplied a valid snapshot from + `openspec instructions specs --change "" --json`, reuse it and do not + fetch the same instructions again. + - Otherwise run that command once now with the same selected-root flags. + - If the direct lookup exits non-zero or returns invalid artifact-instruction + JSON, report the error and stop before writing any main spec. Do not treat the + failure as an absent rule set. + - A valid response with omitted `rules` means no artifact rules are configured + and the existing semantic merge continues. + + Apply returned `rules` only to the content and form of the main specs produced + by this merge. Artifact rules are not operation guidance and cannot change + selected roots, delta paths, CLI checks, or workflow steps. Use their text as + constraints without copying it verbatim into a main spec or summary. + + For each capability delta spec path selected in step 3 — the full `existingOutputPaths` list, or the narrowed subset when a caller supplied one (these may belong to a selected store, not the repo): + + a. **Read the delta spec** to understand the intended changes + + b. **Read the main spec** at `/openspec/specs//spec.md` (may not exist yet) + + c. **Apply changes intelligently**: + + **ADDED Requirements:** + - If requirement doesn't exist in main spec → add it + - If requirement already exists → update it to match (treat as implicit MODIFIED) + + **MODIFIED Requirements:** + - Find the requirement in main spec + - Apply the changes - this can be: + - Adding new scenarios the main spec does not have yet + - Modifying existing scenarios + - Changing the requirement description + - Preserve scenarios/content not mentioned in the delta + + **REMOVED Requirements:** + - Remove the entire requirement block from main spec + - Retiring the capability. Delete the whole `spec.md` - and the directory once + nothing else is left in it - only when ALL of these hold: + 1. removing the requirements *this run* left no requirement blocks; + 2. the rest of the spec is well-formed (it still has a `## Purpose`); + 3. the main spec was not already empty before this sync - if you removed + nothing, change nothing; + 4. every other nonblank line in the whole file is accounted for as the + title, Purpose, Requirements header, or a canonical requirement's + statement, scenarios, or fenced examples; + 5. the change's `.openspec.yaml` declares `retire_capabilities: true`; + 6. the `spec.md` resolves inside the real specs root (do not follow a + capability-directory symlink to delete an external file). + If removing the selected requirements would leave no requirement blocks and + any retirement condition is not satisfied, do not modify the main spec. Stop + the sync for that capability, report the blocking condition, and tell the user + how to resolve it. Never write or leave an empty `## Requirements` section. + When only the marker is missing, say that too - it is the one thing the user + can add to make the retirement go through. + - Deleting the file also deletes its `## Purpose`; any other section blocks + retirement. Name Purpose when you report the retirement. Include a pasteable + `git checkout` only when the spec lived in the caller's checkout; + otherwise give checkout-scoped recovery guidance. + + **RENAMED Requirements:** + - Find the FROM requirement, rename to TO + + **`## Purpose` in the delta:** + - The main spec already has one and it is authoritative - leave it alone + (this is what `openspec archive` does; it warns and moves on) + + d. **Create new main spec** if capability doesn't exist yet: + - Create `/openspec/specs//spec.md` + - Add Purpose section: copy the delta's `## Purpose` body verbatim when it has one + (this is what `openspec archive` does); only write a brief TBD placeholder when it does not + - Add Requirements section with the ADDED requirements + - Follow the **Main Spec Format Reference** below + +5. **Validate updated main specs** + + Run `openspec validate --specs` with the same selected-root flags used earlier. + If validation fails, report the problems and do not claim the sync succeeded. + +6. **Show summary** + + After applying all changes, summarize: + - Which capabilities were updated + - What changes were made (requirements added/modified/removed/renamed) + - Any new main spec left with a TBD Purpose placeholder, so it gets written + now rather than lingering + - Any capability retired, naming the deleted `spec.md`, its Purpose, and + either a pasteable `git checkout` or checkout-scoped recovery guidance + +**Delta Spec Format Reference** + +```markdown +## Purpose + +Only on a delta that introduces a brand-new capability. Seeds the new main spec. + +## ADDED Requirements + +### Requirement: New Feature +The system SHALL do something new. + +#### Scenario: Basic case +- **WHEN** user does X +- **THEN** system does Y + +## MODIFIED Requirements + +### Requirement: Existing Feature +The system SHALL keep doing the existing thing, now also handling A. + +#### Scenario: Scenario the main spec already has +- **WHEN** user does X +- **THEN** system does Y + +#### Scenario: New scenario to add +- **WHEN** user does A +- **THEN** system does B + +## REMOVED Requirements + +### Requirement: Deprecated Feature + +## RENAMED Requirements + +- FROM: `### Requirement: Old Name` +- TO: `### Requirement: New Name` +``` + +**Main Spec Format Reference** + +Main specs are what the delta merges INTO. They must never contain delta operation headers (`## ADDED/MODIFIED/REMOVED/RENAMED Requirements`) - after syncing, every requirement lives under a single `## Requirements` section: + +```markdown +# Specification + +## Purpose +Short description of what this capability does and why it exists. + +## Requirements + +### Requirement: New Feature +The system SHALL do something new. + +#### Scenario: Basic case +- **WHEN** user does X +- **THEN** system does Y +``` + +**Key Principle: Intelligent Merging** + +Unlike programmatic merging, you merge rather than overwrite: +- A MODIFIED block carries the whole requirement - body plus every scenario that survives the change. `openspec validate` and `openspec archive` both reject one that drops a scenario the main spec still has. +- Keep anything the delta does not mention, in the main spec's existing order +- Use your judgment to merge changes sensibly + +**Output On Success** + +```markdown +## Specs Synced: + +Updated main specs: + +****: +- Added requirement: "New Feature" +- Modified requirement: "Existing Feature" (added 1 scenario) + +****: +- Created new spec file +- Added requirement: "Another Feature" + +Main specs are now updated. The change remains active - archive when implementation is complete. +``` + +**Guardrails** +- Read both delta and main specs before making changes +- Preserve existing content not mentioned in delta +- Never copy a delta file into a main spec as-is - merge its content so the main spec keeps the Main Spec Format Reference structure, with no delta operation headers +- If something is unclear, ask for clarification +- Show what you're changing as you go +- The operation should be idempotent - running twice should give same result +- Use only `artifactPaths.specs.existingOutputPaths`; never infer delta specs from unrelated artifacts +- Honor a caller-supplied subset of `existingOutputPaths`; never widen it back to the full list +- Fetch specs instructions once for direct sync, or reuse the archive-supplied snapshot inline +- Stop before every main-spec write on a non-zero or invalid JSON specs-instruction response +- Artifact rules constrain only the specs being written and are never copied into output files diff --git a/.github/prompts/opsx-update.prompt.md b/.github/prompts/opsx-update.prompt.md new file mode 100644 index 0000000..ff115e1 --- /dev/null +++ b/.github/prompts/opsx-update.prompt.md @@ -0,0 +1,83 @@ +--- +description: "Update a change - revise existing planning artifacts and keep them coherent (Experimental)" +--- + +Revise a change's existing planning artifacts and keep them coherent. Never edit code. + +**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. + +**Input**: Optionally specify a change name after `/opsx-update` (e.g., `/opsx-update add-auth`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes. + +`/opsx-continue` is an optional workflow and may not be installed. Before suggesting it anywhere below, verify that it is available. If it is unavailable, `openspec status --change "" --json` shows the next artifact and `openspec instructions "" --change "" --json` explains how to create it. + +**Steps** + +1. **Select the change** + + If a name is provided, use it. Otherwise: + - Infer from conversation context if the user mentioned a change + - Auto-select if only one active change exists + - If ambiguous, run `openspec list --json` to get available changes sorted by most recently modified, and ask the user to select one + + When prompting, present the top 3-4 most recently modified changes as options, showing: + - Change name + - Schema (from `schema` field if present, otherwise "spec-driven") + - Status (e.g., "0/5 tasks", "complete", "no tasks") + - How recently it was modified (from `lastModified` field) + + Mark the most recently modified change as "(Recommended)" since it's likely what the user wants to update. + + Always announce: "Using change: " and how to override (e.g., `/opsx-update `). + +2. **Get the change's artifacts** + ```bash + openspec status --change "" --json + ``` + Parse the JSON to understand current state. The response includes: + - `schemaName`: The workflow schema being used (e.g., "spec-driven") + - `artifacts`: Array of artifacts with their status ("done", "skipped", "ready", "blocked") + - `isPlanningComplete`: Boolean indicating if all planning artifacts are complete. Older CLI versions expose the same value as `isComplete`. + - `planningHome`, `changeRoot`, `artifactPaths`, and `actionContext`: path and scope context. Use these instead of assuming repo-local paths. + + The artifact ids and paths come from the active schema - do NOT assume them, and do NOT branch on hardcoded artifact names. Custom schemas must work unchanged. + + The files to edit are `artifactPaths..existingOutputPaths` - the concrete files that exist on disk, already glob-expanded for glob artifacts (e.g. `specs/**/*.md`). Do NOT write to `resolvedOutputPath`: for a glob artifact it is still the glob pattern, not a real file. + +3. **Understand the request** + - If the user asked for a specific revision ("the design now uses X"), that is the starting edit. + - If they only said "update" / "make this coherent", treat it as a coherence review: read the existing artifacts and check them against each other for contradictions, gaps, and duplication. + +4. **Read and reconcile** + - Read the artifact(s) the request touches and the change's other existing artifacts. + - Apply the requested edit. Then check every other existing artifact against it - in ANY direction: an edit to a later artifact may require revising an earlier one, not only the other way around. Build order is a useful reading order, not a constraint on which artifacts may be revised. + - Note everything that is now inconsistent, missing, or contradictory. + - Revise only files that already exist (`existingOutputPaths`). Do NOT create artifacts that don't exist yet, and do NOT invent new files under a glob artifact - note them and point the user to `/opsx-continue` to create them. + - If the change is already coherent, say so and make no edits. + +5. **Confirm and apply, one artifact at a time** + - Show each proposed revision and why. Write only after the user confirms. + - If the user rejects a revision, do not write it - leave that artifact unchanged. + - When a substantial rewrite is needed, get that artifact's rules and template first: + ```bash + openspec instructions "" --change "" --json + ``` + +6. **Point to the next step (guidance only - NEVER act on it)** + - Artifacts still missing -> suggest `/opsx-continue` to create them. + - Change already implemented (tasks checked off / already applied) -> the code may no longer match the revised plan; suggest `/opsx-apply` to carry the delta into code. + - Everything done and implemented -> suggest `/opsx-archive`. + +**Output** + +After each invocation, show: +- Which artifacts were revised (and which proposed revisions were rejected) +- Anything deferred to `/opsx-continue` (not-yet-created artifacts or files) +- Where the change stands and the recommended next command + +**Guardrails** +- Planning artifacts only - NEVER edit implementation code. If the revised plan implies code changes, stop and point to `/opsx-apply`. +- Use the artifact ids and paths reported by `openspec status`; never branch on hardcoded artifact names. +- Edit only the concrete files in `existingOutputPaths`; never write to a glob `resolvedOutputPath`. +- Do not advance the build frontier: no new artifacts, no new files under glob artifacts - that is `/opsx-continue`'s job. +- Confirm every edit with the user before writing. +- If the request changes the change's *intent* rather than refining it, first verify whether the optional `/opsx-new` workflow is available. If it is, recommend starting fresh with `/opsx-new` (the "Update vs. Start Fresh" heuristic). If it is unavailable, ask for a distinct unused change name and recommend `openspec new change ""` instead. diff --git a/.github/prompts/opsx-verify.prompt.md b/.github/prompts/opsx-verify.prompt.md new file mode 100644 index 0000000..0682ec4 --- /dev/null +++ b/.github/prompts/opsx-verify.prompt.md @@ -0,0 +1,167 @@ +--- +description: "Verify implementation matches change artifacts before archiving" +--- + +Verify that an implementation matches the change artifacts (specs, tasks, design). + +**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. + +**Input**: Optionally specify a change name after `/opsx-verify` (e.g., `/opsx-verify add-auth`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes. + +**Steps** + +1. **Select the change** + + If a name is provided, use it. Otherwise: + - Infer from conversation context if the user mentioned a change + - Auto-select if only one active change exists + - If ambiguous, run `openspec list --json` to get available changes and ask the user to select one + + When prompting, show changes that have implementation tasks (tasks artifact exists). + Include the schema used for each change if available. + Mark changes with incomplete tasks as "(In Progress)". + + Always announce: "Using change: " and how to override (e.g., `/opsx-verify `). + +2. **Check status to understand the schema** + ```bash + openspec status --change "" --json + ``` + Parse the JSON to understand: + - `schemaName`: The workflow being used (e.g., "spec-driven") + - `planningHome`, `changeRoot`, `artifactPaths`, and `actionContext`: path and scope context + - Which artifacts exist for this change + +3. **Get planning context and load artifacts** + + ```bash + openspec instructions apply --change "" --json + ``` + + This returns the change directory and `contextFiles` (artifact ID -> array of concrete file paths). Read all available artifacts from `contextFiles`. + +4. **Initialize verification report structure** + + Create a report structure with three dimensions: + - **Completeness**: Track tasks and spec coverage + - **Correctness**: Track requirement implementation and scenario coverage + - **Coherence**: Track design adherence and pattern consistency + + Each dimension can have CRITICAL, WARNING, or SUGGESTION issues. + +5. **Verify Completeness** + + **Task Completion**: + - If `contextFiles.tasks` exists, read every file path in it + - Parse checkboxes: `- [ ]` (incomplete) vs `- [x]` (complete) + - Count complete vs total tasks + - If incomplete tasks exist: + - Add CRITICAL issue for each incomplete task + - Recommendation: "Complete task: " or "Mark as done if already implemented" + + **Spec Coverage**: + - If delta specs exist in `contextFiles.specs`: + - Extract all requirements (marked with "### Requirement:") + - For each requirement: + - Search codebase for keywords related to the requirement + - Assess if implementation likely exists + - If requirements appear unimplemented: + - Add CRITICAL issue: "Requirement not found: " + - Recommendation: "Implement requirement X: " + +6. **Verify Correctness** + + **Requirement Implementation Mapping**: + - For each requirement from delta specs: + - Search codebase for implementation evidence + - If found, note file paths and line ranges + - Assess if implementation matches requirement intent + - If divergence detected: + - Add WARNING: "Implementation may diverge from spec:
" + - Recommendation: "Review : against requirement X" + + **Scenario Coverage**: + - For each scenario in delta specs (marked with "#### Scenario:"): + - Check if conditions are handled in code + - Check if tests exist covering the scenario + - If scenario appears uncovered: + - Add WARNING: "Scenario not covered: " + - Recommendation: "Add test or implementation for scenario: " + +7. **Verify Coherence** + + **Design Adherence**: + - If `contextFiles.design` exists: + - Extract key decisions (look for sections like "Decision:", "Approach:", "Architecture:") + - Verify implementation follows those decisions + - If contradiction detected: + - Add WARNING: "Design decision not followed: " + - Recommendation: "Update implementation or revise design.md to match reality" + - If no design.md: Skip design adherence check, note "No design.md to verify against" + + **Code Pattern Consistency**: + - Review new code for consistency with project patterns + - Check file naming, directory structure, coding style + - If significant deviations found: + - Add SUGGESTION: "Code pattern deviation:
" + - Recommendation: "Consider following project pattern: " + +8. **Generate Verification Report** + + **Summary Scorecard**: + ```markdown + ## Verification Report: + + ### Summary + | Dimension | Status | + |--------------|------------------| + | Completeness | X/Y tasks, N reqs| + | Correctness | M/N reqs covered | + | Coherence | Followed/Issues | + ``` + + **Issues by Priority**: + + 1. **CRITICAL** (Must fix before archive): + - Incomplete tasks + - Missing requirement implementations + - Each with specific, actionable recommendation + + 2. **WARNING** (Should fix): + - Spec/design divergences + - Missing scenario coverage + - Each with specific recommendation + + 3. **SUGGESTION** (Nice to fix): + - Pattern inconsistencies + - Minor improvements + - Each with specific recommendation + + **Final Assessment**: + - If CRITICAL issues: "X critical issue(s) found. Fix before archiving." + - If only warnings: "No critical issues. Y warning(s) to consider. Ready for archive (with noted improvements)." + - If all clear: "All checks passed. Ready for archive." + +**Verification Heuristics** + +- **Completeness**: Focus on objective checklist items (checkboxes, requirements list) +- **Correctness**: Use keyword search, file path analysis, reasonable inference - don't require perfect certainty +- **Coherence**: Look for glaring inconsistencies, don't nitpick style +- **False Positives**: When uncertain, prefer SUGGESTION over WARNING, WARNING over CRITICAL +- **Actionability**: Every issue must have a specific recommendation with file/line references where applicable + +**Graceful Degradation** + +- If only tasks.md exists: verify task completion only, skip spec/design checks +- If tasks + specs exist: verify completeness and correctness, skip design +- If full artifacts: verify all three dimensions +- Always note which checks were skipped and why + +**Output Format** + +Use clear markdown with: +- Table for summary scorecard +- Grouped lists for issues (CRITICAL/WARNING/SUGGESTION) +- Code references in format: `file.ts:123` +- Specific, actionable recommendations +- No vague suggestions like "consider reviewing" diff --git a/.github/skills/openspec-bulk-archive-change/SKILL.md b/.github/skills/openspec-bulk-archive-change/SKILL.md new file mode 100644 index 0000000..52fb5c6 --- /dev/null +++ b/.github/skills/openspec-bulk-archive-change/SKILL.md @@ -0,0 +1,339 @@ +--- +name: openspec-bulk-archive-change +description: Archive multiple completed changes at once. Use when archiving several parallel changes. +allowed-tools: Bash(openspec:*) +license: MIT +compatibility: Requires openspec CLI. +metadata: + author: openspec + version: "1.0" + generatedBy: "1.13.0" +--- + +Archive multiple completed changes in a single operation. + +This skill allows you to batch-archive changes, handling spec conflicts intelligently by checking the codebase to determine what's actually implemented. + +**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. + +`` is the spec directory relative to `specs/` (for example, `user-auth` or `identity/user-auth`). Preserve the full path from each delta spec when resolving its main spec. + +**Input**: None required (prompts for selection) + +**Steps** + +1. **Get active changes** + + Run `openspec list --json` to get all active changes. + + If no active changes exist, inform user and stop. + +2. **Prompt for change selection** + + Ask the user to choose changes (multi-select): + - Show each change with its schema + - Include an option for "All changes" + - Allow any number of selections (1+ works, 2+ is the typical use case) + + **IMPORTANT**: Do NOT auto-select. Always let the user choose. + + **Load current archive inputs once for the selected root before batch validation:** + + Choose one selected change from this root and run + `openspec instructions archive --change "" --json` with the + same selected-root flags. This lookup is advisory and optional: it only supplies + extra prompt inputs, so it must never block the batch. If it fails or returns + invalid JSON — for example on an older CLI that does not support this command + yet — continue the batch with no context and no operation guidance. Do not + report an error and do not stop. + + A valid response may omit `context` and `operationGuidance`. Treat + `context` as a required prompt-level input across the batch: read and consider + it, and apply relevant project facts, conventions, and constraints. Treat + `operationGuidance` as optional additive advice: read and consider every + entry, and follow entries that are applicable and compatible with the built-in + batch workflow. + + Keep both fields separate from conflict analysis, explicit user choices, + resolved paths, CLI checks, and command contracts. If context conflicts with one + of those controlling inputs, report the conflict and preserve the controlling + value. If guidance is inapplicable or conflicts with a controlling input, do not + follow it and explain why. Do not infer skipped prompts, replacement paths, or + flags from either field, and do not copy their text verbatim into specs, changes, + or summaries. These are prompt-level behavior contracts, not enforceable checks. + +3. **Batch validation - gather status for all selected changes** + + For each selected change, collect: + + a. **Artifact status** - Run `openspec status --change "" --json` + - Parse `schemaName`, `artifacts`, `planningHome`, `changeRoot`, `artifactPaths`, and `actionContext` + - Note which artifacts are `done` vs other states + + b. **Task completion** - Read `artifactPaths.tasks.existingOutputPaths` from status JSON + - Count `- [ ]` (incomplete) vs `- [x]` (complete) + - If no tasks file exists, note as "No tasks" + + c. **Delta specs** - Check `artifactPaths.specs.existingOutputPaths` from status JSON + - List which capability specs exist + - For each, extract requirement names (lines matching `### Requirement: `) + - Treat this list as the only delta-spec source. If the `specs` entry is + missing or the list is empty, perform no spec sync or specs-instruction + lookup for that change; do not infer deltas from unrelated artifacts. + - Evaluate this independently for every change, including mixed-schema + batches where some schemas have no `specs` artifact. +4. **Detect spec conflicts** + + Build a map keyed by ``, the exact path relative to `specs/`: + + ```text + identity/user-auth -> [change-a, change-b] <- CONFLICT (2+ changes) + billing/user-auth -> [change-c] <- OK (different full path) + ``` + + A conflict exists when 2+ selected changes have delta specs for the exact same ``. + +5. **Resolve conflicts agentically** + + **For each conflict**, investigate the codebase: + + a. **Read the delta specs** from each conflicting change to understand what each claims to add/modify + + b. **Search the codebase** for implementation evidence: + - Look for code implementing requirements from each delta spec + - Check for related files, functions, or tests + + c. **Determine resolution**: + - If only one change is actually implemented -> sync that one's specs + - If both implemented -> apply in chronological order (older first, newer overwrites) + - If neither implemented -> skip spec sync, warn user + + d. **Record resolution** for each conflict: + - An inclusion or exclusion decision for every delta spec, keyed by change and `` + - Which included delta specs to apply and in what order + - Which delta specs to exclude from sync because their implementation is missing + - Rationale (what was found in codebase) + +6. **Show consolidated status table** + + Display a table summarizing all changes: + + ```markdown + | Change | Artifacts | Tasks | Specs | Conflicts | Status | + |---------------------|-----------|-------|---------|-----------|--------| + | schema-management | Done | 5/5 | 2 delta | None | Ready | + | project-config | Done | 3/3 | 1 delta | None | Ready | + | add-oauth | Done | 4/4 | 1 delta | identity/user-auth (!) | Ready* | + | add-verify-skill | 1 left | 2/5 | None | None | Warn | + ``` + + For conflicts, show the resolution: + ```text + * Conflict resolution: + - identity/user-auth spec: Will apply add-oauth then add-jwt (both implemented, chronological order) + ``` + + For incomplete changes, show warnings: + ```text + Warnings: + - add-verify-skill: 1 incomplete artifact, 3 incomplete tasks + ``` + +7. **Confirm batch operation** + + Ask the user a single confirmation question: + + - "Archive N changes?" with options based on status + - Options might include: + - "Archive all N changes" + - "Archive only N ready changes (skip incomplete)" + - "Cancel" + + If there are incomplete changes, make clear they'll be archived with warnings. + + Route on the answer by intent, not by exact label — you wrote these labels, + so match what the user picked rather than the wording above: + - "Cancel" — stop, do not archive. Report that nothing was archived and skip the remaining steps. + - The archive-everything option — proceed with every selected change + - The ready-only option — proceed with only the changes the step 6 table marks `Ready` or `Ready*`, and record the rest as Skipped in step 8d. If a `Ready*` change's conflict partner is skipped, re-derive that conflict's resolution using only the changes being archived. + - Anything else — ask again rather than archiving + + Before step 8 writes the first main spec or moves any change, fetch every + required specs-rule snapshot for the confirmed batch. For each change that will + sync concrete `artifactPaths.specs.existingOutputPaths`, run + `openspec instructions specs --change "" --json` exactly once with the + same selected-root flags. Obtain all snapshots before the first write or move. + If any lookup exits non-zero or returns invalid artifact-instruction JSON, + identify the affected change, report the error, and stop the whole batch before + any main-spec write or change move. Do not treat lookup failure as omitted + rules. A valid response without `rules` is the no-rules case. + +8. **Execute archive for each confirmed change** + + Before processing, carry the recorded decisions from step 5 (after any step 7 re-derivation) into two per-delta sets: + - `includedDeltas`: all non-conflicting delta specs from confirmed changes plus conflict deltas selected for sync + - `excludedDeltas`: conflict deltas from confirmed changes excluded because their implementation is missing + - A single change can have both included and excluded delta specs. Keep the decision per delta; do not collapse it into a per-change sync flag. + + Process changes in the determined order (respecting conflict resolution): + + a. **Sync included delta specs**: + - Run the `openspec-sync-specs` workflow inline (agent-driven intelligent merge) only for changes with entries in `includedDeltas`, passing only the included delta paths and explicitly instructing it to ignore that change's `excludedDeltas`. Wait for it to finish. + - For conflicts, apply in resolved order. + - Pass that change's fetched specs-rule snapshot into inline sync; inline + sync must reuse it without fetching instructions again + - Apply artifact rules only to main specs produced by that change. They do + not change conflict resolution, archive behavior, or CLI contracts, and + their text is not copied into an output file + - Do not delegate to a background task — step 8c would move `changeRoot` out from under a sync that is still reading it. + - If a change has no included delta specs, do not run the sync workflow for it. + + b. **Verify included delta specs before moving changeRoot**: + - Re-run the comparison only for delta specs in `includedDeltas` against main spec at `/openspec/specs//spec.md` (use the store-aware `planningHome.root` from step 3 status JSON, not a hardcoded repo path). + - Verify that main specs are updated: + - ADDED requirements present + - MODIFIED requirements carrying scenario and description changes named in the delta, with their other scenarios intact + - REMOVED requirements gone — and where this sync retired a capability (removed its last requirement, leaving `## Requirements` empty), its main spec deleted rather than left empty; a spec the sync deliberately kept and reported is also a match + - RENAMED requirements present under the new name and absent under the old one + - Do not verify delta specs in `excludedDeltas`; they are intentionally left unsynced. + - If sync failed or any capability does not match verification, report what differs and fail/skip moving that change's `changeRoot` — do not archive that change. `changeRoot` remains intact. + + c. **Perform the archive**: + + Target name: use the change name as-is when it already starts with a `YYYY-MM-DD-` prefix; otherwise prepend the current date as `YYYY-MM-DD-` (same rule as `openspec archive`). + + ```bash + mkdir -p "/archive" + mv "" "/archive/" + ``` + + d. **Track outcome** for each change: + - Success: archived successfully + - Failed: error during archive or spec verification (record error) + - Skipped: user chose not to archive (if applicable) + - Sync skipped: for every delta in `excludedDeltas`, report `sync skipped` with the change, ``, and recorded reason. This is distinct from skipping the archive. + +9. **Display summary** + + Show final results: + + ```markdown + ## Bulk Archive Complete + + Archived 3 changes: + - schema-management-cli -> archive/2026-01-19-schema-management-cli/ + - project-config -> archive/2026-01-19-project-config/ + - add-oauth -> archive/2026-01-19-add-oauth/ + + Skipped 1 change: + - add-verify-skill (user chose not to archive incomplete) + + Spec sync summary: + - 4 delta specs synced to main specs + - 1 delta spec sync skipped (add-jwt, identity/user-auth: implementation not found) + - 1 conflict resolved (identity/user-auth: synced add-oauth, skipped add-jwt) + ``` + + If any failures: + ```text + Failed 1 change: + - some-change: Archive directory already exists + ``` + +**Conflict Resolution Examples** + +Example 1: Only one implemented +```text +Conflict: /openspec/specs/auth/spec.md touched by [add-oauth, add-jwt] + +Checking add-oauth: +- Delta adds "OAuth Provider Integration" requirement +- Searching codebase... found src/auth/oauth.ts implementing OAuth flow + +Checking add-jwt: +- Delta adds "JWT Token Handling" requirement +- Searching codebase... no JWT implementation found + +Resolution: Only add-oauth is implemented. Will sync add-oauth specs only. +``` + +Example 2: Both implemented +```text +Conflict: /openspec/specs/api/spec.md touched by [add-rest-api, add-graphql] + +Checking add-rest-api (created 2026-01-10): +- Delta adds "REST Endpoints" requirement +- Searching codebase... found src/api/rest.ts + +Checking add-graphql (created 2026-01-15): +- Delta adds "GraphQL Schema" requirement +- Searching codebase... found src/api/graphql.ts + +Resolution: Both implemented. Will apply add-rest-api specs first, +then add-graphql specs (chronological order, newer takes precedence). +``` + +**Output On Success** + +```markdown +## Bulk Archive Complete + +Archived N changes: +- -> archive// +- -> archive// + +Spec sync summary: +- N delta specs synced to main specs +- No conflicts (or: M conflicts resolved) +``` + +**Output On Partial Success** + +```markdown +## Bulk Archive Complete (partial) + +Archived N changes: +- -> archive// + +Skipped M changes: +- (user chose not to archive incomplete) + +Failed K changes: +- : Archive directory already exists +``` + +**Output When No Changes** + +```markdown +## No Changes to Archive + +No active changes found. Create a new change to get started. +``` + +**Guardrails** +- Allow any number of changes (1+ is fine, 2+ is the typical use case) +- Always prompt for selection, never auto-select +- Detect spec conflicts early and resolve by checking codebase +- When both changes are implemented, apply specs in chronological order +- Skip spec sync only when implementation is missing (warn user) +- Show clear per-change status before confirming +- Use single confirmation for entire batch +- Never archive after the user cancels the confirmation — a cancelled batch archives nothing +- Track and report all outcomes (success/skip/fail) +- Preserve .openspec.yaml when moving to archive +- Archive directory target uses current date: YYYY-MM-DD-; a name that already starts with a `YYYY-MM-DD-` prefix is used as-is (never stack a second date) +- If archive target exists, fail that change but continue with others +- If sync is requested, run the `openspec-sync-specs` workflow inline (agent-driven) for each change with included delta specs +- Carry the per-delta `includedDeltas` and `excludedDeltas` decisions into execution; sync and verify only included deltas +- Report every excluded delta as `sync skipped` without treating the archive itself as skipped +- Never archive a change while a spec sync is still in flight — run the sync inline and verify main specs at `/openspec/specs//spec.md` before moving `changeRoot` +- Fetch archive inputs once per selected root before spec inspection or moves +- Fetch all required specs-rule snapshots before the batch's first main-spec write or move +- A failed archive-inputs lookup never blocks the batch; it proceeds with no context or guidance +- A failed specs instruction lookup stops the whole batch atomically +- Changes without concrete `artifactPaths.specs.existingOutputPaths` continue without spec sync +- Apply relevant runtime context across the batch and report conflicts +- Operation guidance remains advisory; consider every entry and explain rejected advice +- Keep runtime inputs, conflict analysis, CLI-derived values, and artifact rules separate +- Artifact rules constrain only written specs +- Never copy runtime input or artifact-rule text verbatim into output files diff --git a/.github/skills/openspec-continue-change/SKILL.md b/.github/skills/openspec-continue-change/SKILL.md new file mode 100644 index 0000000..657dd4e --- /dev/null +++ b/.github/skills/openspec-continue-change/SKILL.md @@ -0,0 +1,118 @@ +--- +name: openspec-continue-change +description: Continue working on an OpenSpec change by creating the next artifact. Use when the user wants to progress their change, create the next artifact, or continue their workflow. +allowed-tools: Bash(openspec:*) +license: MIT +compatibility: Requires openspec CLI. +metadata: + author: openspec + version: "1.0" + generatedBy: "1.13.0" +--- + +Continue working on a change by creating the next artifact. + +**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. + +**Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes. + +**Steps** + +1. **Select the change** + + If a name is provided, use it. Otherwise: + - Infer from conversation context if the user mentioned a change + - Auto-select if only one active change exists + - If ambiguous, run `openspec list --json` to get available changes sorted by most recently modified, and ask the user to select one + + When prompting, present the top 3-4 most recently modified changes as options, showing: + - Change name + - Schema (from `schema` field if present, otherwise "spec-driven") + - Status (e.g., "0/5 tasks", "complete", "no tasks") + - How recently it was modified (from `lastModified` field) + + Mark the most recently modified change as "(Recommended)" since it's likely what the user wants to continue. + + Always announce: "Using change: " and how to override (e.g., `/opsx-continue `). + +2. **Check current status** + ```bash + openspec status --change "" --json + ``` + Parse the JSON to understand current state. The response includes: + - `schemaName`: The workflow schema being used (e.g., "spec-driven") + - `artifacts`: Array of artifacts with their status ("done", "skipped", "ready", "blocked") + - `isPlanningComplete`: Boolean indicating if all planning artifacts are complete. Older CLI versions expose the same value as `isComplete`. + - `planningHome`, `changeRoot`, `artifactPaths`, and `actionContext`: path and scope context. Use these instead of assuming repo-local paths. + +3. **Act based on status**: + + --- + + **If all planning artifacts are complete (`isPlanningComplete: true`, or legacy `isComplete: true`)**: + - Congratulate the user + - Show final status including the schema used + - Suggest: "Planning is complete! You can now implement this change. Once implementation and any tracked work are complete, archive it." + - STOP + + --- + + **If artifacts are ready to create** (status shows artifacts with `status: "ready"`): + - Pick the FIRST artifact with `status: "ready"` from the status output + - Get its instructions: + ```bash + openspec instructions --change "" --json + ``` + - Parse the JSON. The key fields are: + - `context`: Project background (constraints for you - do NOT include in output) + - `rules`: Artifact-specific rules (constraints for you - do NOT include in output) + - `template`: The structure to use for your output file + - `instruction`: Schema-specific guidance + - `resolvedOutputPath`: Resolved path or pattern to write the artifact + - `dependencies`: Completed artifacts to read for context (entries with `skipped: true` have no files - do not look for them) + - `skipped`/`warning`: present when the change declares skip_specs and this artifact must NOT be created - pick another artifact + - **Create the artifact file**: + - Read any completed dependency files for context - always re-read them from disk, even if you saw them earlier in the conversation (the user may have edited them) + - If the `instruction` field delegates creation to a specific skill or command, invoke it to produce the artifact instead of writing the file yourself, then verify the artifact file exists at `resolvedOutputPath` + - Otherwise use `template` as the structure - fill in its sections + - Apply `context` and `rules` as constraints when writing - but do NOT copy them into the file + - Write to the `resolvedOutputPath` specified in instructions. If it is a glob pattern, choose the concrete file path using the schema instruction and the change's context + - Show what was created and what's now unlocked + - STOP after creating ONE artifact + + --- + + **If no artifacts are ready (all blocked)**: + - This shouldn't happen with a valid schema + - Show status and suggest checking for issues + +4. **After creating an artifact, show progress** + ```bash + openspec status --change "" + ``` + +**Output** + +After each invocation, show: +- Which artifact was created +- Schema workflow being used +- Current progress (N/M complete) +- What artifacts are now unlocked +- Prompt: "Want to continue? Just ask me to continue or tell me what to do next." + +**Artifact Creation Guidelines** + +The artifact types and their purpose depend on the schema. The `instruction` field from the instructions output is the authoritative guidance for each artifact - follow it even when the artifact has a familiar name (proposal.md, tasks.md, etc.), since custom schemas may define different content or a different process for the same file names. + +If the `instruction` field directs you to use a specific skill or command to create the artifact, invoke it instead of writing the artifact directly. + +**Guardrails** +- Create ONE artifact per invocation +- Always read dependency artifacts before creating a new one - re-read from disk, not from conversation memory (files may have changed since you last saw them) +- Never skip artifacts or create out of order +- If context is unclear, ask the user before creating +- Verify the artifact file exists after writing before marking progress +- Use the schema's artifact sequence, don't assume specific artifact names +- **IMPORTANT**: `context` and `rules` are constraints for YOU, not content for the file + - Do NOT copy ``, ``, `` blocks into the artifact + - These guide what you write, but should never appear in the output diff --git a/.github/skills/openspec-ff-change/SKILL.md b/.github/skills/openspec-ff-change/SKILL.md new file mode 100644 index 0000000..8961611 --- /dev/null +++ b/.github/skills/openspec-ff-change/SKILL.md @@ -0,0 +1,117 @@ +--- +name: openspec-ff-change +description: Fast-forward through OpenSpec artifact creation. Use when the user wants to quickly create all artifacts needed for implementation without stepping through each one individually. +allowed-tools: Bash(openspec:*) +license: MIT +compatibility: Requires openspec CLI. +metadata: + author: openspec + version: "1.0" + generatedBy: "1.13.0" +--- + +Fast-forward through artifact creation - generate everything needed to start implementation in one go. + +**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. + +**Input**: The user's request should include a change name (kebab-case) OR a description of what they want to build. + +**Steps** + +1. **If no clear input provided, ask what they want to build** + + Ask the user (open-ended, no preset options): + > "What change do you want to work on? Describe what you want to build or fix." + + From their description, derive a kebab-case name (e.g., "add user authentication" → `add-user-auth`). + + **IMPORTANT**: Do NOT proceed without understanding what the user wants to build. + +2. **Create the change directory** + ```bash + openspec new change "" + ``` + This creates a scaffolded change in the planning home resolved by the CLI. + +3. **Get the artifact build order** + ```bash + openspec status --change "" --json + ``` + Parse the JSON to get: + - `applyRequires`: array of artifact IDs needed before implementation (e.g., `["tasks"]`) + - `artifacts`: list of all artifacts, each with its `status` and its `requires` edges (the artifact IDs it directly depends on) + - `planningHome`, `changeRoot`, `artifactPaths`, and `actionContext`: path and scope context. Use these instead of assuming repo-local paths. + +4. **Create every artifact in the required set** + + Use a todo list to track progress through the artifacts. + + Loop through artifacts in dependency order (artifacts with no pending dependencies first): + + a. **For each artifact that is `ready` (dependencies satisfied)**: + - Get instructions: + ```bash + openspec instructions --change "" --json + ``` + - The instructions JSON includes: + - `context`: Project background (constraints for you - do NOT include in output) + - `rules`: Artifact-specific rules (constraints for you - do NOT include in output) + - `template`: The structure to use for your output file + - `instruction`: Schema-specific guidance for this artifact type + - `skipped`/`warning`: present when the change declares skip_specs and this artifact must NOT be created - stop and pick another artifact + - `resolvedOutputPath`: Resolved path or pattern to write the artifact + - `dependencies`: Completed artifacts to read for context + - Read any completed dependency files for context - always re-read them from disk, even if you saw them earlier in the conversation (the user may have edited them) + - **Inspect the relevant project before drafting**: Read `context` and `rules` first, then inspect relevant implementation, nearby tests, configuration, and documentation outside `openspec/`. Keep inspection read-only and proportional to the change; reuse findings for later artifacts and inspect more only as needed. + - Identify the target project from the request and project context; the planning home may be separate from the code. If the target is unclear, ask. For greenfield or non-code changes, inspect the available structure and relevant documents. If source is unavailable, state the limitation and ask when it materially affects the plan. + - Ground scope, approach, and tasks in what you find. Distinguish observed behavior from assumptions and proposed additions; surface conflicts with existing specs instead of silently deciding which is correct. + - Do this discovery now, rather than leaving generic "explore the codebase" or "make a plan" tasks for implementation. Keep any necessary follow-up investigation specific to an unresolved question. + - If the `instruction` field delegates creation to a specific skill or command, invoke it to produce the artifact instead of writing the file yourself, then verify the artifact file exists at `resolvedOutputPath` + - Otherwise create the artifact file using `template` as the structure and write it to `resolvedOutputPath`. If `resolvedOutputPath` is a glob, follow `instruction` to choose the concrete file path + - Apply `context` and `rules` as constraints - but do NOT copy them into the file + - Show brief progress: "✓ Created " + + b. **Continue until every artifact in the required set exists (not just `apply.requires`)** + - After creating each artifact, re-run `openspec status --change "" --json` + - The required set is `applyRequires` plus every artifact reachable from those by following the `requires` edges in `status --json` - walk them transitively (spec-driven closes over proposal, specs, design, tasks). Leave artifacts outside that set alone + - `status` is file-existence only, so an `applyRequires` artifact reading `done` does NOT mean its dependencies exist - writing `tasks.md` early marks `tasks` done while `specs` was never written. Use each artifact's `requires` edges, not its `status`, to build the required set: a `done` artifact still lists what it depends on + - An artifact already reading `status: "skipped"` is satisfied: the change declares `skip_specs` in `.openspec.yaml`, so its files must NOT exist. Never try to create one + - Create every artifact in the required set that is missing, then re-check - creating one can unblock others + - Skip one only when `status` already reports it `skipped`, or when its own `instruction` says it is conditional: run `openspec instructions --change "" --json` and skip only if its `instruction` field marks it optional (e.g. "create only if..."). Spec-driven's `design.md` qualifies; `specs` qualifies only via the `skipped` status above, never by your own judgment. Tell the user, and do not reconsider it + - Dependencies are enablers, not gates: if a required artifact is still `blocked` only because you skipped a conditional dependency, write it anyway + - Stop when every artifact in the required set is `done`, `skipped`, or was deliberately skipped + + c. **If an artifact requires user input** (unclear context): + - Ask the user to clarify + - Then continue with creation + +5. **Show final status** + ```bash + openspec status --change "" + ``` + +**Output** + +After completing all artifacts, summarize: +- Change name and location +- List of artifacts created with brief descriptions, plus any conditional artifact you skipped and why +- What's ready: "All artifacts needed for implementation are ready." +- Prompt: "Run `/opsx-apply` or ask me to implement to start working on the tasks." + +**Artifact Creation Guidelines** + +- Follow the `instruction` field from `openspec instructions` for each artifact type - it is the authoritative guidance, even for familiar artifact names +- If the `instruction` field directs you to use a specific skill or command to create the artifact, invoke it instead of writing the artifact directly +- The schema defines what each artifact should contain - follow it +- Read dependency artifacts for context before creating new ones +- Use `template` as the structure for your output file - fill in its sections +- **IMPORTANT**: `context` and `rules` are constraints for YOU, not content for the file + - Do NOT copy ``, ``, `` blocks into the artifact + - These guide what you write, but should never appear in the output + +**Guardrails** +- Create every artifact the apply phase transitively depends on, not just the ids listed in `apply.requires` +- Always read dependency artifacts before creating a new one - re-read from disk, not from conversation memory (files may have changed since you last saw them) +- If context is critically unclear, ask the user - but prefer making reasonable decisions to keep momentum +- If a change with that name already exists, suggest continuing that change instead +- Verify each artifact file exists after writing before proceeding to next diff --git a/.github/skills/openspec-new-change/SKILL.md b/.github/skills/openspec-new-change/SKILL.md new file mode 100644 index 0000000..c955883 --- /dev/null +++ b/.github/skills/openspec-new-change/SKILL.md @@ -0,0 +1,77 @@ +--- +name: openspec-new-change +description: Start a new OpenSpec change using the experimental artifact workflow. Use when the user wants to create a new feature, fix, or modification with a structured step-by-step approach. +allowed-tools: Bash(openspec:*) +license: MIT +compatibility: Requires openspec CLI. +metadata: + author: openspec + version: "1.0" + generatedBy: "1.13.0" +--- + +Start a new change using the experimental artifact-driven approach. + +**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. + +**Input**: The user's request should include a change name (kebab-case) OR a description of what they want to build. + +**Steps** + +1. **If no clear input provided, ask what they want to build** + + Ask the user (open-ended, no preset options): + > "What change do you want to work on? Describe what you want to build or fix." + + From their description, derive a kebab-case name (e.g., "add user authentication" → `add-user-auth`). + + **IMPORTANT**: Do NOT proceed without understanding what the user wants to build. + +2. **Determine the workflow schema** + + Use the default schema (omit `--schema`) unless the user explicitly requests a different workflow. + + **Use a different schema only if the user mentions:** + - A specific schema name → use `--schema ` + - "show workflows" or "what workflows" → run `openspec schemas --json` and let them choose + + **Otherwise**: Omit `--schema` to use the default. + +3. **Create the change directory** + ```bash + openspec new change "" + ``` + Add `--schema ` only if the user requested a specific workflow. + This creates a scaffolded change in the planning home resolved by the CLI. + +4. **Show the artifact status** + ```bash + openspec status --change "" --json + ``` + Use the returned `planningHome`, `changeRoot`, `artifactPaths`, and `nextSteps` instead of assuming repo-local paths. + +5. **Get instructions for the first artifact** + The first artifact depends on the schema (e.g., `proposal` for spec-driven). + Check the status output to find the first artifact with status "ready". + ```bash + openspec instructions --change "" + ``` + This outputs the template and context for creating the first artifact. + +6. **STOP and wait for user direction** + +**Output** + +After completing the steps, summarize: +- Change name and location +- Schema/workflow being used and its artifact sequence +- Current status (0/N artifacts complete) +- The template for the first artifact +- Prompt: "Ready to create the first artifact? Just describe what this change is about and I'll draft it, or ask me to continue." + +**Guardrails** +- Do NOT create any artifacts yet - just show the instructions +- Do NOT advance beyond showing the first artifact template +- If the name is invalid (not kebab-case), ask for a valid name +- If a change with that name already exists, suggest continuing that change instead +- Pass --schema if using a non-default workflow diff --git a/.github/skills/openspec-onboard/SKILL.md b/.github/skills/openspec-onboard/SKILL.md new file mode 100644 index 0000000..418993b --- /dev/null +++ b/.github/skills/openspec-onboard/SKILL.md @@ -0,0 +1,561 @@ +--- +name: openspec-onboard +description: Guided onboarding for OpenSpec - walk through a complete workflow cycle with narration and real codebase work. +allowed-tools: Bash(openspec:*) +license: MIT +compatibility: Requires openspec CLI. +metadata: + author: openspec + version: "1.0" + generatedBy: "1.13.0" +--- + +Guide the user through their first complete OpenSpec workflow cycle. This is a teaching experience—you'll do real work in their codebase while explaining each step. + +**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. + +--- + +## Preflight + +Before starting, check if the OpenSpec CLI is installed: + +```bash +# Unix/macOS +openspec --version 2>&1 || echo "CLI_NOT_INSTALLED" +# Windows (PowerShell) +# if (Get-Command openspec -ErrorAction SilentlyContinue) { openspec --version } else { echo "CLI_NOT_INSTALLED" } +``` + +**If CLI not installed:** +> OpenSpec CLI is not installed. Install it first, then come back to `/opsx-onboard`. + +Stop here if not installed. + +--- + +## Phase 1: Welcome + +Display: + +``` +## Welcome to OpenSpec! + +I'll walk you through a complete change cycle—from idea to implementation—using a real task in your codebase. Along the way, you'll learn the workflow by doing it. + +**What we'll do:** +1. Pick a small, real task in your codebase +2. Explore the problem briefly +3. Create a change (the container for our work) +4. Build the artifacts: proposal → specs → design → tasks +5. Implement the tasks +6. Archive the completed change + +**Time:** ~15-20 minutes + +Let's start by finding something to work on. +``` + +--- + +## Phase 2: Task Selection + +### Codebase Analysis + +Scan the codebase for small improvement opportunities. Look for: + +1. **TODO/FIXME comments** - Search for `TODO`, `FIXME`, `HACK`, `XXX` in code files +2. **Missing error handling** - `catch` blocks that swallow errors, risky operations without try-catch +3. **Functions without tests** - Cross-reference `src/` with test directories +4. **Type issues** - `any` types in TypeScript files (`: any`, `as any`) +5. **Debug artifacts** - `console.log`, `console.debug`, `debugger` statements in non-debug code +6. **Missing validation** - User input handlers without validation + +Also check recent git activity: +```bash +# Unix/macOS +git log --oneline -10 2>/dev/null || echo "No git history" +# Windows (PowerShell) +# git log --oneline -10 2>$null; if ($LASTEXITCODE -ne 0) { echo "No git history" } +``` + +### Present Suggestions + +From your analysis, present 3-4 specific suggestions: + +``` +## Task Suggestions + +Based on scanning your codebase, here are some good starter tasks: + +**1. [Most promising task]** + Location: `src/path/to/file.ts:42` + Scope: ~1-2 files, ~20-30 lines + Why it's good: [brief reason] + +**2. [Second task]** + Location: `src/another/file.ts` + Scope: ~1 file, ~15 lines + Why it's good: [brief reason] + +**3. [Third task]** + Location: [location] + Scope: [estimate] + Why it's good: [brief reason] + +**4. Something else?** + Tell me what you'd like to work on. + +Which task interests you? (Pick a number or describe your own) +``` + +**If nothing found:** Fall back to asking what the user wants to build: +> I didn't find obvious quick wins in your codebase. What's something small you've been meaning to add or fix? + +### Scope Guardrail + +If the user picks or describes something too large (major feature, multi-day work): + +``` +That's a valuable task, but it's probably larger than ideal for your first OpenSpec run-through. + +For learning the workflow, smaller is better—it lets you see the full cycle without getting stuck in implementation details. + +**Options:** +1. **Slice it smaller** - What's the smallest useful piece of [their task]? Maybe just [specific slice]? +2. **Pick something else** - One of the other suggestions, or a different small task? +3. **Do it anyway** - If you really want to tackle this, we can. Just know it'll take longer. + +What would you prefer? +``` + +Let the user override if they insist—this is a soft guardrail. + +--- + +## Phase 3: Explore Demo + +Once a task is selected, briefly demonstrate explore mode: + +``` +Before we create a change, let me quickly show you **explore mode**—it's how you think through problems before committing to a direction. +``` + +Spend 1-2 minutes investigating the relevant code: +- Read the file(s) involved +- Draw a quick ASCII diagram if it helps +- Note any considerations + +``` +## Quick Exploration + +[Your brief analysis—what you found, any considerations] + +┌─────────────────────────────────────────┐ +│ [Optional: ASCII diagram if helpful] │ +└─────────────────────────────────────────┘ + +Explore mode (`/opsx-explore`) is for this kind of thinking—investigating before implementing. You can use it anytime you need to think through a problem. + +Now let's create a change to hold our work. +``` + +**PAUSE** - Wait for user acknowledgment before proceeding. + +--- + +## Phase 4: Create the Change + +**EXPLAIN:** +``` +## Creating a Change + +A "change" in OpenSpec is a container for all the thinking and planning around a piece of work. It lives at the `changeRoot` reported by `openspec status --change "" --json` and holds your artifacts—proposal, specs, design, tasks. + +Let me create one for our task. +``` + +**DO:** Create the change with a derived kebab-case name: +```bash +openspec new change "" +``` + +**SHOW:** +``` +Created: + +The folder structure: +``` +/ +├── proposal.md ← Why we're doing this (empty, we'll fill it) +├── design.md ← How we'll build it (empty) +├── specs/ ← Detailed requirements (empty) +└── tasks.md ← Implementation checklist (empty) +``` + +Now let's fill in the first artifact—the proposal. +``` + +--- + +## Phase 5: Proposal + +**EXPLAIN:** +``` +## The Proposal + +The proposal captures **why** we're making this change and **what** it involves at a high level. It's the "elevator pitch" for the work. + +I'll draft one based on our task. +``` + +**DO:** Draft the proposal content (don't save yet): + +`` is the spec directory relative to `specs/` (for example, +`user-auth` or `identity/user-auth`). Use the exact existing path for modified +capabilities. For new capabilities, follow the project's established spec +organization. + +``` +Here's a draft proposal: + +--- + +## Why + +[1-2 sentences explaining the problem/opportunity] + +## What Changes + +[Bullet points of what will be different] + +## Capabilities + +### New Capabilities +- ``: [brief description] + +### Modified Capabilities + +- ``: [brief description] + +## Impact + +- `src/path/to/file.ts`: [what changes] +- [other files if applicable] + +--- + +Does this capture the intent? I can adjust before we save it. +``` + +**PAUSE** - Wait for user approval/feedback. + +After approval, save the proposal: +```bash +openspec instructions proposal --change "" --json +``` +Then write the content to the `resolvedOutputPath` from `openspec instructions proposal --change "" --json`. + +``` +Proposal saved. This is your "why" document—you can always come back and refine it as understanding evolves. + +Next up: specs. +``` + +--- + +## Phase 6: Specs + +**EXPLAIN:** +``` +## Specs + +Specs define **what** we're building in precise, testable terms. They use a requirement/scenario format that makes expected behavior crystal clear. + +For a small task like this, we might only need one spec file. +``` + +**DO:** Resolve where the spec file should be created: +```bash +openspec instructions specs --change "" --json +# Use resolvedOutputPath from the JSON. If it is a glob, choose the concrete file path using the schema instruction and the change's context. +``` + +Draft the spec content: + +``` +Here's the spec: + +--- + +## ADDED Requirements + +### Requirement: + + + +#### Scenario: + +- **WHEN** +- **THEN** +- **AND** + +--- + +This format—WHEN/THEN/AND—makes requirements testable. You can literally read them as test cases. +``` + +Save to the concrete file path chosen from `resolvedOutputPath`. + +--- + +## Phase 7: Design + +**EXPLAIN:** +``` +## Design + +The design captures **how** we'll build it—technical decisions, tradeoffs, approach. + +For small changes, this might be brief. That's fine—not every change needs deep design discussion. +``` + +**DO:** Draft design.md: + +``` +Here's the design: + +--- + +## Context + +[Brief context about the current state] + +## Goals / Non-Goals + +**Goals:** +- [What we're trying to achieve] + +**Non-Goals:** +- [What's explicitly out of scope] + +## Decisions + +### Decision 1: [Key decision] + +[Explanation of approach and rationale] + +--- + +For a small task, this captures the key decisions without over-engineering. +``` + +Save to the `resolvedOutputPath` from `openspec instructions design --change "" --json`. + +--- + +## Phase 8: Tasks + +**EXPLAIN:** +``` +## Tasks + +Finally, we break the work into implementation tasks—checkboxes that drive the apply phase. + +These should be small, clear, and in logical order. +``` + +**DO:** Generate tasks based on specs and design: + +``` +Here are the implementation tasks: + +--- + +## 1. [Category or file] + +- [ ] 1.1 [Specific task] — verify: [test, command, observable behavior, or delivered artifact] +- [ ] 1.2 [Specific task] — verify: [test, command, observable behavior, or delivered artifact] + +## 2. Integration Verification + +- [ ] 2.1 Verify [broader integration or system behavior] with [end-to-end test or observable result] + +--- + +Each checkbox becomes a unit of work in the apply phase. Ready to implement? +``` + +**PAUSE** - Wait for user to confirm they're ready to implement. + +Save to the `resolvedOutputPath` from `openspec instructions tasks --change "" --json`. + +--- + +## Phase 9: Apply (Implementation) + +**EXPLAIN:** +``` +## Implementation + +Now we implement each task, checking them off as we go. I'll announce each one and occasionally note how the specs/design informed the approach. +``` + +**DO:** For each task: + +1. Announce: "Working on task N: [description]" +2. Implement the change in the codebase +3. Reference specs/design naturally: "The spec says X, so I'm doing Y" +4. Mark complete in tasks.md: `- [ ]` → `- [x]` +5. Brief status: "✓ Task N complete" + +Keep narration light—don't over-explain every line of code. + +After all tasks: + +``` +## Implementation Complete + +All tasks done: +- [x] Task 1 +- [x] Task 2 +- [x] ... + +The change is implemented! One more step—let's archive it. +``` + +--- + +## Phase 10: Archive + +**EXPLAIN:** +``` +## Archiving + +When a change is complete, we archive it. The archive path is derived from `planningHome.changesDir` and the date. + +Archived changes become your project's decision history—you can always find them later to understand why something was built a certain way. +``` + +**DO:** Archive the change (`--yes` answers the confirmation prompts, which you cannot answer from a tool call): +```bash +openspec archive "" --yes +``` + +**SHOW:** +``` +Archived to: `/archive//` (the target name prepends today's date, unless the name already starts with a `YYYY-MM-DD-` prefix — then it is kept as-is, no second date) + +The change is now part of your project's history. The code is in your codebase, the decision record is preserved. +``` + +--- + +## Phase 11: Recap & Next Steps + +``` +## Congratulations! + +You just completed a full OpenSpec cycle: + +1. **Explore** - Thought through the problem +2. **New** - Created a change container +3. **Proposal** - Captured WHY +4. **Specs** - Defined WHAT in detail +5. **Design** - Decided HOW +6. **Tasks** - Broke it into steps +7. **Apply** - Implemented the work +8. **Archive** - Preserved the record + +This same rhythm works for any size change—a small fix or a major feature. + +--- + +## Command Reference + +**Core workflow:** + + | Command | What it does | + |-------------------|--------------------------------------------| + | `/opsx-propose` | Create a change and generate all artifacts | + | `/opsx-explore` | Think through problems before/during work | + | `/opsx-apply` | Implement tasks from a change | + | `/opsx-archive` | Archive a completed change | + +**Additional commands** (only if installed - availability depends on your profile): + + | Command | What it does | + |--------------------|----------------------------------------------------------| + | `/opsx-new` | Start a new change, step through artifacts one at a time | + | `/opsx-continue` | Continue working on an existing change | + | `/opsx-ff` | Fast-forward: create all artifacts at once | + | `/opsx-verify` | Verify implementation matches artifacts | + +--- + +## What's Next? + +Try `/opsx-propose` on something you actually want to build. You've got the rhythm now! +``` + +--- + +## Graceful Exit Handling + +### User wants to stop mid-way + +If the user says they need to stop, want to pause, or seem disengaged: + +``` +No problem! Your change is saved at the `changeRoot` reported by `openspec status --change "" --json`. + +To pick up where we left off later: +- `/opsx-continue ` - Resume artifact creation (if installed; otherwise `openspec status --change "" --json` shows the next artifact) +- `/opsx-apply ` - Jump to implementation (if tasks exist) + +The work won't be lost. Come back whenever you're ready. +``` + +Exit gracefully without pressure. + +### User just wants command reference + +If the user says they just want to see the commands or skip the tutorial: + +``` +## OpenSpec Quick Reference + +**Core workflow:** + + | Command | What it does | + |--------------------------|--------------------------------------------| + | `/opsx-propose ` | Create a change and generate all artifacts | + | `/opsx-explore` | Think through problems (no code changes) | + | `/opsx-apply ` | Implement tasks | + | `/opsx-archive ` | Archive when done | + +**Additional commands** (only if installed - availability depends on your profile): + + | Command | What it does | + |---------------------------|-------------------------------------| + | `/opsx-new ` | Start a new change, step by step | + | `/opsx-continue ` | Continue an existing change | + | `/opsx-ff ` | Fast-forward: all artifacts at once | + | `/opsx-verify ` | Verify implementation | + +Try `/opsx-propose` to start your first change. +``` + +Exit gracefully. + +--- + +## Guardrails + +- **Follow the EXPLAIN → DO → SHOW → PAUSE pattern** at key transitions (after explore, after proposal draft, after tasks, after archive) +- **Keep narration light** during implementation—teach without lecturing +- **Don't skip phases** even if the change is small—the goal is teaching the workflow +- **Pause for acknowledgment** at marked points, but don't over-pause +- **Handle exits gracefully**—never pressure the user to continue +- **Use real codebase tasks**—don't simulate or use fake examples +- **Adjust scope gently**—guide toward smaller tasks but respect user choice diff --git a/.github/skills/openspec-sync-specs/SKILL.md b/.github/skills/openspec-sync-specs/SKILL.md new file mode 100644 index 0000000..845cf67 --- /dev/null +++ b/.github/skills/openspec-sync-specs/SKILL.md @@ -0,0 +1,262 @@ +--- +name: openspec-sync-specs +description: Sync delta specs from a change to main specs. Use when the user wants to update main specs with changes from a delta spec, without archiving the change. +allowed-tools: Bash(openspec:*) +license: MIT +compatibility: Requires openspec CLI. +metadata: + author: openspec + version: "1.0" + generatedBy: "1.13.0" +--- + +Sync delta specs from a change to main specs. + +This is an **agent-driven** operation - you will read delta specs and directly edit main specs to apply the changes. This allows intelligent merging (e.g., adding a scenario without copying the entire requirement). + +**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. + +`` is the spec directory relative to `specs/` (for example, `user-auth` or `identity/user-auth`). Preserve the full path from each delta spec when resolving its main spec. + +**Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes. + +**Steps** + +1. **Select the change** + + If a name is provided, use it. Otherwise: + - Infer from conversation context if the user mentioned a change + - Auto-select if only one active change exists + - If ambiguous, run `openspec list --json` to get available changes and ask the user to select one + + When prompting, show changes that have delta specs (under `specs/` directory). + + Always announce: "Using change: " and how to override (e.g., `/opsx-sync `). + +2. **Resolve change context** + + Run: + ```bash + openspec status --change "" --json + ``` + + The JSON includes `planningHome.root`. Main specs live under `/openspec/specs/` — use that (store-aware) root for every main-spec path below, not a hardcoded repo path. When a store is selected it points at the store, not the current repository. + +3. **Find delta specs** + + Use `artifactPaths.specs.existingOutputPaths` from the status JSON as the + only source of delta spec paths. If the `specs` entry is missing or + `existingOutputPaths` is empty, report that there are no delta specs to sync, + do not infer them from other artifacts, and stop without requesting artifact + instructions or writing a main spec. + + Sync every path in `existingOutputPaths` unless the caller narrowed the set. + A caller narrows it by naming an explicit list of complete entries from + `existingOutputPaths` — copy those absolute values verbatim. Archive does + this inline, and a user can too (for example, by selecting the entry ending + in `/specs/billing/invoices/spec.md`). + Then sync only the named paths and leave the remaining delta specs untouched: + bulk archive excludes a delta whose implementation it could not find, and + syncing it anyway would write a main spec the caller deliberately withheld. + Carry that narrowed selection through step 4; never widen it back to the full + list. If a named path is not in `existingOutputPaths`, do not sync it — + report it and stop, rather than dropping it silently. If the named list is + empty, report that there is nothing to sync and stop without writing a main + spec. + + Each delta spec file contains sections like: + - `## ADDED Requirements` - New requirements to add + - `## MODIFIED Requirements` - Changes to existing requirements + - `## REMOVED Requirements` - Requirements to remove + - `## RENAMED Requirements` - Requirements to rename (FROM:/TO: format) + + If no delta specs found, inform user and stop. + +4. **For each delta spec, apply changes to main specs** + + Before the first main-spec write, obtain one current specs-rule snapshot: + - If archive invoked this workflow inline and supplied a valid snapshot from + `openspec instructions specs --change "" --json`, reuse it and do not + fetch the same instructions again. + - Otherwise run that command once now with the same selected-root flags. + - If the direct lookup exits non-zero or returns invalid artifact-instruction + JSON, report the error and stop before writing any main spec. Do not treat the + failure as an absent rule set. + - A valid response with omitted `rules` means no artifact rules are configured + and the existing semantic merge continues. + + Apply returned `rules` only to the content and form of the main specs produced + by this merge. Artifact rules are not operation guidance and cannot change + selected roots, delta paths, CLI checks, or workflow steps. Use their text as + constraints without copying it verbatim into a main spec or summary. + + For each capability delta spec path selected in step 3 — the full `existingOutputPaths` list, or the narrowed subset when a caller supplied one (these may belong to a selected store, not the repo): + + a. **Read the delta spec** to understand the intended changes + + b. **Read the main spec** at `/openspec/specs//spec.md` (may not exist yet) + + c. **Apply changes intelligently**: + + **ADDED Requirements:** + - If requirement doesn't exist in main spec → add it + - If requirement already exists → update it to match (treat as implicit MODIFIED) + + **MODIFIED Requirements:** + - Find the requirement in main spec + - Apply the changes - this can be: + - Adding new scenarios the main spec does not have yet + - Modifying existing scenarios + - Changing the requirement description + - Preserve scenarios/content not mentioned in the delta + + **REMOVED Requirements:** + - Remove the entire requirement block from main spec + - Retiring the capability. Delete the whole `spec.md` - and the directory once + nothing else is left in it - only when ALL of these hold: + 1. removing the requirements *this run* left no requirement blocks; + 2. the rest of the spec is well-formed (it still has a `## Purpose`); + 3. the main spec was not already empty before this sync - if you removed + nothing, change nothing; + 4. every other nonblank line in the whole file is accounted for as the + title, Purpose, Requirements header, or a canonical requirement's + statement, scenarios, or fenced examples; + 5. the change's `.openspec.yaml` declares `retire_capabilities: true`; + 6. the `spec.md` resolves inside the real specs root (do not follow a + capability-directory symlink to delete an external file). + If removing the selected requirements would leave no requirement blocks and + any retirement condition is not satisfied, do not modify the main spec. Stop + the sync for that capability, report the blocking condition, and tell the user + how to resolve it. Never write or leave an empty `## Requirements` section. + When only the marker is missing, say that too - it is the one thing the user + can add to make the retirement go through. + - Deleting the file also deletes its `## Purpose`; any other section blocks + retirement. Name Purpose when you report the retirement. Include a pasteable + `git checkout` only when the spec lived in the caller's checkout; + otherwise give checkout-scoped recovery guidance. + + **RENAMED Requirements:** + - Find the FROM requirement, rename to TO + + **`## Purpose` in the delta:** + - The main spec already has one and it is authoritative - leave it alone + (this is what `openspec archive` does; it warns and moves on) + + d. **Create new main spec** if capability doesn't exist yet: + - Create `/openspec/specs//spec.md` + - Add Purpose section: copy the delta's `## Purpose` body verbatim when it has one + (this is what `openspec archive` does); only write a brief TBD placeholder when it does not + - Add Requirements section with the ADDED requirements + - Follow the **Main Spec Format Reference** below + +5. **Validate updated main specs** + + Run `openspec validate --specs` with the same selected-root flags used earlier. + If validation fails, report the problems and do not claim the sync succeeded. + +6. **Show summary** + + After applying all changes, summarize: + - Which capabilities were updated + - What changes were made (requirements added/modified/removed/renamed) + - Any new main spec left with a TBD Purpose placeholder, so it gets written + now rather than lingering + - Any capability retired, naming the deleted `spec.md`, its Purpose, and + either a pasteable `git checkout` or checkout-scoped recovery guidance + +**Delta Spec Format Reference** + +```markdown +## Purpose + +Only on a delta that introduces a brand-new capability. Seeds the new main spec. + +## ADDED Requirements + +### Requirement: New Feature +The system SHALL do something new. + +#### Scenario: Basic case +- **WHEN** user does X +- **THEN** system does Y + +## MODIFIED Requirements + +### Requirement: Existing Feature +The system SHALL keep doing the existing thing, now also handling A. + +#### Scenario: Scenario the main spec already has +- **WHEN** user does X +- **THEN** system does Y + +#### Scenario: New scenario to add +- **WHEN** user does A +- **THEN** system does B + +## REMOVED Requirements + +### Requirement: Deprecated Feature + +## RENAMED Requirements + +- FROM: `### Requirement: Old Name` +- TO: `### Requirement: New Name` +``` + +**Main Spec Format Reference** + +Main specs are what the delta merges INTO. They must never contain delta operation headers (`## ADDED/MODIFIED/REMOVED/RENAMED Requirements`) - after syncing, every requirement lives under a single `## Requirements` section: + +```markdown +# Specification + +## Purpose +Short description of what this capability does and why it exists. + +## Requirements + +### Requirement: New Feature +The system SHALL do something new. + +#### Scenario: Basic case +- **WHEN** user does X +- **THEN** system does Y +``` + +**Key Principle: Intelligent Merging** + +Unlike programmatic merging, you merge rather than overwrite: +- A MODIFIED block carries the whole requirement - body plus every scenario that survives the change. `openspec validate` and `openspec archive` both reject one that drops a scenario the main spec still has. +- Keep anything the delta does not mention, in the main spec's existing order +- Use your judgment to merge changes sensibly + +**Output On Success** + +```markdown +## Specs Synced: + +Updated main specs: + +****: +- Added requirement: "New Feature" +- Modified requirement: "Existing Feature" (added 1 scenario) + +****: +- Created new spec file +- Added requirement: "Another Feature" + +Main specs are now updated. The change remains active - archive when implementation is complete. +``` + +**Guardrails** +- Read both delta and main specs before making changes +- Preserve existing content not mentioned in delta +- Never copy a delta file into a main spec as-is - merge its content so the main spec keeps the Main Spec Format Reference structure, with no delta operation headers +- If something is unclear, ask for clarification +- Show what you're changing as you go +- The operation should be idempotent - running twice should give same result +- Use only `artifactPaths.specs.existingOutputPaths`; never infer delta specs from unrelated artifacts +- Honor a caller-supplied subset of `existingOutputPaths`; never widen it back to the full list +- Fetch specs instructions once for direct sync, or reuse the archive-supplied snapshot inline +- Stop before every main-spec write on a non-zero or invalid JSON specs-instruction response +- Artifact rules constrain only the specs being written and are never copied into output files diff --git a/.github/skills/openspec-update-change/SKILL.md b/.github/skills/openspec-update-change/SKILL.md new file mode 100644 index 0000000..ae8981b --- /dev/null +++ b/.github/skills/openspec-update-change/SKILL.md @@ -0,0 +1,91 @@ +--- +name: openspec-update-change +description: Update an OpenSpec change by revising its existing planning artifacts and keeping them coherent with one another. Use when the user wants to revise a change's plan, fold new decisions into it, or reconcile its artifacts after an edit. Never edits code. +allowed-tools: Bash(openspec:*) +license: MIT +compatibility: Requires openspec CLI. +metadata: + author: openspec + version: "1.0" + generatedBy: "1.13.0" +--- + +Revise a change's existing planning artifacts and keep them coherent. Never edit code. + +**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. + +**Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes. + +`/opsx-continue` is an optional workflow and may not be installed. Before suggesting it anywhere below, verify that it is available. If it is unavailable, `openspec status --change "" --json` shows the next artifact and `openspec instructions "" --change "" --json` explains how to create it. + +**Steps** + +1. **Select the change** + + If a name is provided, use it. Otherwise: + - Infer from conversation context if the user mentioned a change + - Auto-select if only one active change exists + - If ambiguous, run `openspec list --json` to get available changes sorted by most recently modified, and ask the user to select one + + When prompting, present the top 3-4 most recently modified changes as options, showing: + - Change name + - Schema (from `schema` field if present, otherwise "spec-driven") + - Status (e.g., "0/5 tasks", "complete", "no tasks") + - How recently it was modified (from `lastModified` field) + + Mark the most recently modified change as "(Recommended)" since it's likely what the user wants to update. + + Always announce: "Using change: " and how to override (e.g., `/opsx-update `). + +2. **Get the change's artifacts** + ```bash + openspec status --change "" --json + ``` + Parse the JSON to understand current state. The response includes: + - `schemaName`: The workflow schema being used (e.g., "spec-driven") + - `artifacts`: Array of artifacts with their status ("done", "skipped", "ready", "blocked") + - `isPlanningComplete`: Boolean indicating if all planning artifacts are complete. Older CLI versions expose the same value as `isComplete`. + - `planningHome`, `changeRoot`, `artifactPaths`, and `actionContext`: path and scope context. Use these instead of assuming repo-local paths. + + The artifact ids and paths come from the active schema - do NOT assume them, and do NOT branch on hardcoded artifact names. Custom schemas must work unchanged. + + The files to edit are `artifactPaths..existingOutputPaths` - the concrete files that exist on disk, already glob-expanded for glob artifacts (e.g. `specs/**/*.md`). Do NOT write to `resolvedOutputPath`: for a glob artifact it is still the glob pattern, not a real file. + +3. **Understand the request** + - If the user asked for a specific revision ("the design now uses X"), that is the starting edit. + - If they only said "update" / "make this coherent", treat it as a coherence review: read the existing artifacts and check them against each other for contradictions, gaps, and duplication. + +4. **Read and reconcile** + - Read the artifact(s) the request touches and the change's other existing artifacts. + - Apply the requested edit. Then check every other existing artifact against it - in ANY direction: an edit to a later artifact may require revising an earlier one, not only the other way around. Build order is a useful reading order, not a constraint on which artifacts may be revised. + - Note everything that is now inconsistent, missing, or contradictory. + - Revise only files that already exist (`existingOutputPaths`). Do NOT create artifacts that don't exist yet, and do NOT invent new files under a glob artifact - note them and point the user to `/opsx-continue` to create them. + - If the change is already coherent, say so and make no edits. + +5. **Confirm and apply, one artifact at a time** + - Show each proposed revision and why. Write only after the user confirms. + - If the user rejects a revision, do not write it - leave that artifact unchanged. + - When a substantial rewrite is needed, get that artifact's rules and template first: + ```bash + openspec instructions "" --change "" --json + ``` + +6. **Point to the next step (guidance only - NEVER act on it)** + - Artifacts still missing -> suggest `/opsx-continue` to create them. + - Change already implemented (tasks checked off / already applied) -> the code may no longer match the revised plan; suggest `/opsx-apply` to carry the delta into code. + - Everything done and implemented -> suggest `/opsx-archive`. + +**Output** + +After each invocation, show: +- Which artifacts were revised (and which proposed revisions were rejected) +- Anything deferred to `/opsx-continue` (not-yet-created artifacts or files) +- Where the change stands and the recommended next command + +**Guardrails** +- Planning artifacts only - NEVER edit implementation code. If the revised plan implies code changes, stop and point to `/opsx-apply`. +- Use the artifact ids and paths reported by `openspec status`; never branch on hardcoded artifact names. +- Edit only the concrete files in `existingOutputPaths`; never write to a glob `resolvedOutputPath`. +- Do not advance the build frontier: no new artifacts, no new files under glob artifacts - that is `/opsx-continue`'s job. +- Confirm every edit with the user before writing. +- If the request changes the change's *intent* rather than refining it, first verify whether the optional `/opsx-new` workflow is available. If it is, recommend starting fresh with `/opsx-new` (the "Update vs. Start Fresh" heuristic). If it is unavailable, ask for a distinct unused change name and recommend `openspec new change ""` instead. diff --git a/.github/skills/openspec-verify-change/SKILL.md b/.github/skills/openspec-verify-change/SKILL.md new file mode 100644 index 0000000..06d33fc --- /dev/null +++ b/.github/skills/openspec-verify-change/SKILL.md @@ -0,0 +1,175 @@ +--- +name: openspec-verify-change +description: Verify implementation matches change artifacts. Use when the user wants to validate that implementation is complete, correct, and coherent before archiving. +allowed-tools: Bash(openspec:*) +license: MIT +compatibility: Requires openspec CLI. +metadata: + author: openspec + version: "1.0" + generatedBy: "1.13.0" +--- + +Verify that an implementation matches the change artifacts (specs, tasks, design). + +**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. + +**Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes. + +**Steps** + +1. **Select the change** + + If a name is provided, use it. Otherwise: + - Infer from conversation context if the user mentioned a change + - Auto-select if only one active change exists + - If ambiguous, run `openspec list --json` to get available changes and ask the user to select one + + When prompting, show changes that have implementation tasks (tasks artifact exists). + Include the schema used for each change if available. + Mark changes with incomplete tasks as "(In Progress)". + + Always announce: "Using change: " and how to override (e.g., `/opsx-verify `). + +2. **Check status to understand the schema** + ```bash + openspec status --change "" --json + ``` + Parse the JSON to understand: + - `schemaName`: The workflow being used (e.g., "spec-driven") + - `planningHome`, `changeRoot`, `artifactPaths`, and `actionContext`: path and scope context + - Which artifacts exist for this change + +3. **Get planning context and load artifacts** + + ```bash + openspec instructions apply --change "" --json + ``` + + This returns the change directory and `contextFiles` (artifact ID -> array of concrete file paths). Read all available artifacts from `contextFiles`. + +4. **Initialize verification report structure** + + Create a report structure with three dimensions: + - **Completeness**: Track tasks and spec coverage + - **Correctness**: Track requirement implementation and scenario coverage + - **Coherence**: Track design adherence and pattern consistency + + Each dimension can have CRITICAL, WARNING, or SUGGESTION issues. + +5. **Verify Completeness** + + **Task Completion**: + - If `contextFiles.tasks` exists, read every file path in it + - Parse checkboxes: `- [ ]` (incomplete) vs `- [x]` (complete) + - Count complete vs total tasks + - If incomplete tasks exist: + - Add CRITICAL issue for each incomplete task + - Recommendation: "Complete task: " or "Mark as done if already implemented" + + **Spec Coverage**: + - If delta specs exist in `contextFiles.specs`: + - Extract all requirements (marked with "### Requirement:") + - For each requirement: + - Search codebase for keywords related to the requirement + - Assess if implementation likely exists + - If requirements appear unimplemented: + - Add CRITICAL issue: "Requirement not found: " + - Recommendation: "Implement requirement X: " + +6. **Verify Correctness** + + **Requirement Implementation Mapping**: + - For each requirement from delta specs: + - Search codebase for implementation evidence + - If found, note file paths and line ranges + - Assess if implementation matches requirement intent + - If divergence detected: + - Add WARNING: "Implementation may diverge from spec:
" + - Recommendation: "Review : against requirement X" + + **Scenario Coverage**: + - For each scenario in delta specs (marked with "#### Scenario:"): + - Check if conditions are handled in code + - Check if tests exist covering the scenario + - If scenario appears uncovered: + - Add WARNING: "Scenario not covered: " + - Recommendation: "Add test or implementation for scenario: " + +7. **Verify Coherence** + + **Design Adherence**: + - If `contextFiles.design` exists: + - Extract key decisions (look for sections like "Decision:", "Approach:", "Architecture:") + - Verify implementation follows those decisions + - If contradiction detected: + - Add WARNING: "Design decision not followed: " + - Recommendation: "Update implementation or revise design.md to match reality" + - If no design.md: Skip design adherence check, note "No design.md to verify against" + + **Code Pattern Consistency**: + - Review new code for consistency with project patterns + - Check file naming, directory structure, coding style + - If significant deviations found: + - Add SUGGESTION: "Code pattern deviation:
" + - Recommendation: "Consider following project pattern: " + +8. **Generate Verification Report** + + **Summary Scorecard**: + ```markdown + ## Verification Report: + + ### Summary + | Dimension | Status | + |--------------|------------------| + | Completeness | X/Y tasks, N reqs| + | Correctness | M/N reqs covered | + | Coherence | Followed/Issues | + ``` + + **Issues by Priority**: + + 1. **CRITICAL** (Must fix before archive): + - Incomplete tasks + - Missing requirement implementations + - Each with specific, actionable recommendation + + 2. **WARNING** (Should fix): + - Spec/design divergences + - Missing scenario coverage + - Each with specific recommendation + + 3. **SUGGESTION** (Nice to fix): + - Pattern inconsistencies + - Minor improvements + - Each with specific recommendation + + **Final Assessment**: + - If CRITICAL issues: "X critical issue(s) found. Fix before archiving." + - If only warnings: "No critical issues. Y warning(s) to consider. Ready for archive (with noted improvements)." + - If all clear: "All checks passed. Ready for archive." + +**Verification Heuristics** + +- **Completeness**: Focus on objective checklist items (checkboxes, requirements list) +- **Correctness**: Use keyword search, file path analysis, reasonable inference - don't require perfect certainty +- **Coherence**: Look for glaring inconsistencies, don't nitpick style +- **False Positives**: When uncertain, prefer SUGGESTION over WARNING, WARNING over CRITICAL +- **Actionability**: Every issue must have a specific recommendation with file/line references where applicable + +**Graceful Degradation** + +- If only tasks.md exists: verify task completion only, skip spec/design checks +- If tasks + specs exist: verify completeness and correctness, skip design +- If full artifacts: verify all three dimensions +- Always note which checks were skipped and why + +**Output Format** + +Use clear markdown with: +- Table for summary scorecard +- Grouped lists for issues (CRITICAL/WARNING/SUGGESTION) +- Code references in format: `file.ts:123` +- Specific, actionable recommendations +- No vague suggestions like "consider reviewing" diff --git a/.hermes/skills/openspec-apply-change/SKILL.md b/.hermes/skills/openspec-apply-change/SKILL.md new file mode 100644 index 0000000..cdfc3db --- /dev/null +++ b/.hermes/skills/openspec-apply-change/SKILL.md @@ -0,0 +1,188 @@ +--- +name: openspec-apply-change +description: Implement tasks from an OpenSpec change. Use when the user wants to start implementing, continue implementation, or work through tasks. +allowed-tools: Bash(openspec:*) +license: MIT +compatibility: Requires openspec CLI. +metadata: + author: openspec + version: "1.0" + generatedBy: "1.13.0" +--- + +Implement tasks from an OpenSpec change. + +**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. + +**Input**: Optionally specify a change name (e.g., `/openspec-apply-change add-auth`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes. + +**Steps** + +1. **Select the change** + + If a name is provided, use it. Otherwise: + - Infer from conversation context if the user mentioned a change + - Auto-select if only one active change exists + - If ambiguous, run `openspec list --json` to get available changes and ask the user to select one + + Always announce: "Using change: " and how to override (e.g., `/openspec-apply-change `). + +2. **Check status to understand the schema** + ```bash + openspec status --change "" --json + ``` + Parse the JSON to understand: + - `schemaName`: The workflow being used (e.g., "spec-driven") + - `planningHome`, `changeRoot`, and `actionContext`: planning scope and edit constraints + - Which artifact contains the tasks (typically "tasks" for spec-driven, check status for others) + +3. **Get apply instructions** + + ```bash + openspec instructions apply --change "" --json + ``` + + This returns: + - `contextFiles`: artifact ID -> array of concrete file paths (varies by schema - could be proposal/specs/design/tasks or spec/tests/implementation/docs) + - Progress (total, complete, remaining) + - Task list with status + - Dynamic instruction based on current state + - Optional `context`: current required project instruction input from the selected root + - Optional `operationGuidance`: current advisory guidance for apply + + **Handle states:** + - If `state: "blocked"` (missing artifacts): show message, suggest using `/openspec-continue-change` (if it is not installed, run `openspec status --change "" --json` to see the next artifact and `openspec instructions --change "" --json` for how to create it) + - If `state: "all_done"`: congratulate, suggest archive + - Otherwise: proceed to implementation + + Treat `context` as a required prompt-level input. Read and consider it, and + apply relevant project facts, conventions, and constraints while implementing. + Treat `operationGuidance` as optional additive advice. Read and consider every + entry, and follow entries that are applicable and compatible with the built-in + workflow. + + Keep both fields separate from CLI-returned state, missing artifacts, tasks, + progress, `contextFiles`, and the built-in `instruction`. They are not + evidence of task completion, do not replace the built-in instruction, and do + not permit bypassing a blocked state. If context conflicts with the built-in + instruction, an explicit user choice, or a CLI-controlled value, report the + conflict and preserve the controlling value. If guidance is inapplicable or + conflicts with those controlling inputs, do not follow it and explain why. + These are prompt-level behavior contracts, not enforceable checks. + +4. **Read context files** + + Read every file path listed under `contextFiles` from the apply instructions output. + The files depend on the schema being used: + - **spec-driven**: proposal, specs, design, tasks + - Other schemas: follow the contextFiles from CLI output + + Do not copy `context` or `operationGuidance` verbatim into implementation + files or planning artifacts unless the user separately asks for that content. + +5. **Show current progress** + + Display: + - Schema being used + - Progress: "N/M tasks complete" + - Remaining tasks overview + - Dynamic instruction from CLI + +6. **Implement tasks (loop until done or blocked)** + + For each pending task: + - Show which task is being worked on + - Make the code changes required + - Keep changes minimal and focused + - Mark task complete in the tasks file: `- [ ]` → `- [x]` + - Continue to next task + + **Pause if:** + - Task is unclear → ask for clarification + - Implementation reveals a design issue → suggest updating artifacts + - A task needs work beyond what the spec and tasks describe, or you are tempted to drop, narrow, defer, or accept exceptions to specified behavior to make it fit → surface the added scope and ask; do not absorb it silently + - Error or blocker encountered → report and wait for guidance + - User interrupts + +7. **On completion or pause, show status** + + Display: + - Tasks completed this session + - Overall progress: "N/M tasks complete" + - If all done: suggest archive + - If paused: explain why and wait for guidance + +**Output During Implementation** + +``` +## Implementing: (schema: ) + +Working on task 3/7: +[...implementation happening...] +✓ Task complete + +Working on task 4/7: +[...implementation happening...] +✓ Task complete +``` + +**Output On Completion** + +``` +## Implementation Complete + +**Change:** +**Schema:** +**Progress:** 7/7 tasks complete ✓ + +### Completed This Session +- [x] Task 1 +- [x] Task 2 +... + +All tasks complete! You can archive this change with `/openspec-archive-change`. +``` + +**Output On Pause (Issue Encountered)** + +``` +## Implementation Paused + +**Change:** +**Schema:** +**Progress:** 4/7 tasks complete + +### Issue Encountered + + +**Options:** +1.