From 89141c01a9b5b623b32d477ba210bee1e50edb31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Villase=C3=B1or=20Montfort?= <195970+montfort@users.noreply.github.com> Date: Mon, 2 Mar 2026 10:01:49 -0600 Subject: [PATCH 1/5] docs: update CONTRIBUTING guides with CLA section and revised dev setup Replace inline Code of Conduct standards with a summary linking to CODE_OF_CONDUCT.md, add CLA Assistant requirement section, fix dev setup commands (correct cd path, add pre-commit hook step, add Rust toolchain prerequisite), and sync Spanish translation. Co-Authored-By: Claude Opus 4.6 --- CONTRIBUTING.md | 56 +++++++++++++++++++++++------------- docs/i18n/es/CONTRIBUTING.md | 56 +++++++++++++++++++++++------------- 2 files changed, 72 insertions(+), 40 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d633079..e051976 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,6 +7,7 @@ Thank you for your interest in contributing to DevTrail! This document provides ## Table of Contents - [Code of Conduct](#code-of-conduct) +- [Contributor License Agreement (CLA)](#contributor-license-agreement-cla) - [How Can I Contribute?](#how-can-i-contribute) - [Development Setup](#development-setup) - [Pull Request Process](#pull-request-process) @@ -17,15 +18,24 @@ Thank you for your interest in contributing to DevTrail! This document provides ## Code of Conduct -This project adheres to a Code of Conduct that all contributors are expected to follow. Please be respectful, inclusive, and constructive in all interactions. +This project is governed by our [Contributor Covenant Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. -### Our Standards +In short: be respectful, inclusive, and constructive in all interactions. Harassment, discrimination, and trolling are not tolerated. Please read the [full Code of Conduct](CODE_OF_CONDUCT.md) before contributing. -- Be welcoming and inclusive -- Be respectful of differing viewpoints -- Accept constructive criticism gracefully -- Focus on what is best for the community -- Show empathy towards other community members +--- + +## Contributor License Agreement (CLA) + +This project requires all contributors to sign a **Contributor License Agreement (CLA)** before their pull requests can be merged. We use [CLA Assistant](https://cla-assistant.io/) to manage this process. + +### How it works + +1. When you open your first pull request, CLA Assistant will automatically post a comment asking you to sign the CLA. +2. Click the link in the comment to review and sign the agreement. +3. The CLA only needs to be signed once — it covers all future contributions to this project. +4. Once signed, CLA Assistant will update the PR check status and your contribution can proceed to review. + +If you have questions about the CLA, please open a [Discussion](https://github.com/StrangeDaysTech/devtrail/discussions). --- @@ -77,39 +87,45 @@ Code contributions should: ### Prerequisites -- Git -- A text editor (VS Code recommended) -- Bash (for Linux/Mac validation scripts) -- PowerShell (for Windows validation scripts) -- Node.js (optional, for markdownlint) +- **Git** +- **A text editor** (VS Code recommended) +- **Bash** (for Linux/Mac validation scripts) +- **PowerShell** (for Windows validation scripts) +- **Rust toolchain** (for CLI development — install via [rustup.rs](https://rustup.rs/)) +- **Node.js 20+** (optional, for markdownlint) ### Setup Steps 1. **Fork the repository** - Click "Fork" on the GitHub repository page. + Click "Fork" on the [GitHub repository page](https://github.com/StrangeDaysTech/devtrail). 2. **Clone your fork** ```bash git clone https://github.com/your-username/devtrail.git - cd devtrail-framework + cd devtrail ``` -3. **Create a branch** +3. **Install the pre-commit hook** ```bash - git checkout -b feature/your-feature-name - # or - git checkout -b fix/your-bug-fix + cp scripts/pre-commit-docs.sh .git/hooks/pre-commit + chmod +x .git/hooks/pre-commit ``` 4. **Install development tools (optional)** ```bash + # Markdown linting npm install -g markdownlint-cli ``` -5. **Make your changes** +5. **Create a branch** + ```bash + git checkout -b feature/your-feature-name + # or + git checkout -b fix/your-bug-fix + ``` -6. **Validate your changes** +6. **Make your changes and validate** ```bash # Linux/Mac bash scripts/pre-commit-docs.sh diff --git a/docs/i18n/es/CONTRIBUTING.md b/docs/i18n/es/CONTRIBUTING.md index 4237d69..0f1e7f6 100644 --- a/docs/i18n/es/CONTRIBUTING.md +++ b/docs/i18n/es/CONTRIBUTING.md @@ -7,6 +7,7 @@ ## Tabla de Contenidos - [Código de Conducta](#código-de-conducta) +- [Acuerdo de Licencia de Contribuidor (CLA)](#acuerdo-de-licencia-de-contribuidor-cla) - [¿Cómo Puedo Contribuir?](#cómo-puedo-contribuir) - [Configuración de Desarrollo](#configuración-de-desarrollo) - [Proceso de Pull Request](#proceso-de-pull-request) @@ -17,15 +18,24 @@ ## Código de Conducta -Este proyecto se adhiere a un Código de Conducta que todos los contribuidores deben seguir. Por favor sé respetuoso, inclusivo y constructivo en todas las interacciones. +Este proyecto se rige por nuestro [Código de Conducta del Pacto del Contribuidor](../../../CODE_OF_CONDUCT.md) ([Español](CODE_OF_CONDUCT.md)). Al participar, se espera que cumplas con este código. -### Nuestros Estándares +En resumen: sé respetuoso, inclusivo y constructivo en todas las interacciones. El acoso, la discriminación y el trolling no son tolerados. Por favor lee el [Código de Conducta completo](CODE_OF_CONDUCT.md) antes de contribuir. -- Sé acogedor e inclusivo -- Sé respetuoso con diferentes puntos de vista -- Acepta críticas constructivas con gracia -- Enfócate en lo mejor para la comunidad -- Muestra empatía hacia otros miembros de la comunidad +--- + +## Acuerdo de Licencia de Contribuidor (CLA) + +Este proyecto requiere que todos los contribuidores firmen un **Acuerdo de Licencia de Contribuidor (CLA)** antes de que sus pull requests puedan ser fusionados. Usamos [CLA Assistant](https://cla-assistant.io/) para gestionar este proceso. + +### Cómo funciona + +1. Cuando abras tu primer pull request, CLA Assistant publicará automáticamente un comentario pidiéndote que firmes el CLA. +2. Haz clic en el enlace del comentario para revisar y firmar el acuerdo. +3. El CLA solo necesita firmarse una vez — cubre todas las contribuciones futuras a este proyecto. +4. Una vez firmado, CLA Assistant actualizará el estado del check del PR y tu contribución podrá proceder a revisión. + +Si tienes preguntas sobre el CLA, por favor abre una [Discusión](https://github.com/StrangeDaysTech/devtrail/discussions). --- @@ -77,39 +87,45 @@ Las contribuciones de código deben: ### Prerrequisitos -- Git -- Un editor de texto (VS Code recomendado) -- Bash (para scripts de validación en Linux/Mac) -- PowerShell (para scripts de validación en Windows) -- Node.js (opcional, para markdownlint) +- **Git** +- **Un editor de texto** (VS Code recomendado) +- **Bash** (para scripts de validación en Linux/Mac) +- **PowerShell** (para scripts de validación en Windows) +- **Rust toolchain** (para desarrollo del CLI — instalar vía [rustup.rs](https://rustup.rs/)) +- **Node.js 20+** (opcional, para markdownlint) ### Pasos de Configuración 1. **Fork del repositorio** - Haz clic en "Fork" en la página del repositorio de GitHub. + Haz clic en "Fork" en la [página del repositorio de GitHub](https://github.com/StrangeDaysTech/devtrail). 2. **Clonar tu fork** ```bash git clone https://github.com/tu-usuario/devtrail.git - cd devtrail-framework + cd devtrail ``` -3. **Crear una rama** +3. **Instalar el hook de pre-commit** ```bash - git checkout -b feature/nombre-de-tu-caracteristica - # o - git checkout -b fix/tu-correccion-de-bug + cp scripts/pre-commit-docs.sh .git/hooks/pre-commit + chmod +x .git/hooks/pre-commit ``` 4. **Instalar herramientas de desarrollo (opcional)** ```bash + # Linting de Markdown npm install -g markdownlint-cli ``` -5. **Hacer tus cambios** +5. **Crear una rama** + ```bash + git checkout -b feature/nombre-de-tu-caracteristica + # o + git checkout -b fix/tu-correccion-de-bug + ``` -6. **Validar tus cambios** +6. **Hacer tus cambios y validar** ```bash # Linux/Mac bash scripts/pre-commit-docs.sh From 15db5be223ad10d12f624b573cbed8698ae1d648 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Villase=C3=B1or=20Montfort?= <195970+montfort@users.noreply.github.com> Date: Mon, 2 Mar 2026 12:28:40 -0600 Subject: [PATCH 2/5] refactor: separate dev directive files from distribution templates Root directive files (CLAUDE.md, GEMINI.md, .cursorrules, copilot-instructions.md) now serve dev-only purposes, with clean distribution templates moved to dist-templates/directives/. Updates release workflow to source copilot-instructions.md from the new location and removes the redundant file entry from dist-manifest.yml. Co-Authored-By: Claude Opus 4.6 --- .cursorrules | 2 ++ .github/copilot-instructions.md | 2 ++ .github/workflows/release.yml | 2 +- .gitignore | 2 +- CLAUDE.md | 2 ++ CONTRIBUTING.md | 9 +++++---- GEMINI.md | 2 ++ dist-manifest.yml | 1 - dist-templates/directives/CLAUDE.md | 10 ++++++++++ dist-templates/directives/GEMINI.md | 10 ++++++++++ dist-templates/directives/copilot-instructions.md | 10 ++++++++++ docs/i18n/es/CONTRIBUTING.md | 9 +++++---- 12 files changed, 50 insertions(+), 11 deletions(-) create mode 100644 dist-templates/directives/CLAUDE.md create mode 100644 dist-templates/directives/GEMINI.md create mode 100644 dist-templates/directives/copilot-instructions.md diff --git a/.cursorrules b/.cursorrules index 7e465c6..bb6c77d 100644 --- a/.cursorrules +++ b/.cursorrules @@ -181,3 +181,5 @@ risk_level: low | medium | high | critical --- *DevTrail v2.0.0 | [Strange Days Tech](https://strangedays.tech) — Because every change tells a story.* + + diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 60a9ea8..0b37494 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -12,3 +12,5 @@ When working on this project, identify yourself as: `copilot-cli-v1.0` (or your --- *DevTrail v2.0.0 | [Strange Days Tech](https://strangedays.tech) — Because every change tells a story.* + + diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fb73546..7495df0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -49,7 +49,7 @@ jobs: # CI/CD mkdir -p dist-staging/.github/workflows - cp .github/copilot-instructions.md dist-staging/.github/ 2>/dev/null || true + cp dist-templates/directives/copilot-instructions.md dist-staging/.github/copilot-instructions.md 2>/dev/null || true cp .github/workflows/docs-validation.yml dist-staging/.github/workflows/ 2>/dev/null || true cd dist-staging diff --git a/.gitignore b/.gitignore index 23aaa7b..94b833b 100644 --- a/.gitignore +++ b/.gitignore @@ -81,7 +81,7 @@ yarn.lock # ============================================================================= cli/target/ -dist/ +dist-staging/ *.tar.gz release/ diff --git a/CLAUDE.md b/CLAUDE.md index eb4207e..5aff14c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -12,3 +12,5 @@ When working on this project, identify yourself as: `claude-code-v1.0` (or your --- *DevTrail v2.0.0 | [Strange Days Tech](https://strangedays.tech) — Because every change tells a story.* + + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e051976..bc3fec8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -254,10 +254,11 @@ If you're proposing a new document type: - `.devtrail/QUICK-REFERENCE.md` 3. **Update agent configs** - - `CLAUDE.md` - - `GEMINI.md` - - `.cursorrules` - - `.github/copilot-instructions.md` + - `CLAUDE.md` (dev-only) + - `GEMINI.md` (dev-only) + - `.cursorrules` (dev-only) + - `.github/copilot-instructions.md` (dev-only) + - `dist-templates/directives/` (distribution templates) 4. **Update validation** - `scripts/pre-commit-docs.sh` diff --git a/GEMINI.md b/GEMINI.md index 5ce78bc..d0a02f7 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -12,3 +12,5 @@ When working on this project, identify yourself as: `gemini-cli-v1.0` (or your v --- *DevTrail v2.0.0 | [Strange Days Tech](https://strangedays.tech) — Because every change tells a story.* + + diff --git a/dist-manifest.yml b/dist-manifest.yml index 1745f33..0fb1dd6 100644 --- a/dist-manifest.yml +++ b/dist-manifest.yml @@ -22,7 +22,6 @@ files: - scripts/validate-docs.ps1 # CI/CD - - .github/copilot-instructions.md - .github/workflows/docs-validation.yml # Files that are injected into existing directive files diff --git a/dist-templates/directives/CLAUDE.md b/dist-templates/directives/CLAUDE.md new file mode 100644 index 0000000..2ccbaa2 --- /dev/null +++ b/dist-templates/directives/CLAUDE.md @@ -0,0 +1,10 @@ +# DevTrail - Claude Code Configuration + + +> **Read and follow the rules in [DEVTRAIL.md](DEVTRAIL.md).** +> That file contains all DevTrail documentation governance rules for this project. + + +--- + +*DevTrail v2.0.0 | [Strange Days Tech](https://strangedays.tech) — Because every change tells a story.* diff --git a/dist-templates/directives/GEMINI.md b/dist-templates/directives/GEMINI.md new file mode 100644 index 0000000..4d0fa84 --- /dev/null +++ b/dist-templates/directives/GEMINI.md @@ -0,0 +1,10 @@ +# DevTrail - Gemini CLI Configuration + + +> **Read and follow the rules in [DEVTRAIL.md](DEVTRAIL.md).** +> That file contains all DevTrail documentation governance rules for this project. + + +--- + +*DevTrail v2.0.0 | [Strange Days Tech](https://strangedays.tech) — Because every change tells a story.* diff --git a/dist-templates/directives/copilot-instructions.md b/dist-templates/directives/copilot-instructions.md new file mode 100644 index 0000000..316112a --- /dev/null +++ b/dist-templates/directives/copilot-instructions.md @@ -0,0 +1,10 @@ +# DevTrail - GitHub Copilot Configuration + + +> **Read and follow the rules in [../DEVTRAIL.md](../DEVTRAIL.md).** +> That file contains all DevTrail documentation governance rules for this project. + + +--- + +*DevTrail v2.0.0 | [Strange Days Tech](https://strangedays.tech) — Because every change tells a story.* diff --git a/docs/i18n/es/CONTRIBUTING.md b/docs/i18n/es/CONTRIBUTING.md index 0f1e7f6..c6a871e 100644 --- a/docs/i18n/es/CONTRIBUTING.md +++ b/docs/i18n/es/CONTRIBUTING.md @@ -254,10 +254,11 @@ Si estás proponiendo un nuevo tipo de documento: - `.devtrail/QUICK-REFERENCE.md` 3. **Actualizar configs de agente** - - `CLAUDE.md` - - `GEMINI.md` - - `.cursorrules` - - `.github/copilot-instructions.md` + - `CLAUDE.md` (solo desarrollo) + - `GEMINI.md` (solo desarrollo) + - `.cursorrules` (solo desarrollo) + - `.github/copilot-instructions.md` (solo desarrollo) + - `dist-templates/directives/` (plantillas de distribución) 4. **Actualizar validación** - `scripts/pre-commit-docs.sh` From 98b9052ea344db35571a95bdcfc44e3b2f2d02a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Villase=C3=B1or=20Montfort?= <195970+montfort@users.noreply.github.com> Date: Mon, 2 Mar 2026 13:21:37 -0600 Subject: [PATCH 3/5] refactor: CLI reads injection templates from files instead of hardcoded strings Replace hardcoded injection content in the CLI with a template-driven approach. The manifest now declares each injection as {target, template, embed?} and the CLI reads actual template files from the distribution ZIP. - Add cursorrules and cursor-rules-devtrail.md templates with empty markers - Restructure dist-manifest.yml injections from object to list format - New unified `inject_directive()` replaces three separate inject functions - init.rs reads templates from ZIP into memory, iterates manifest.injections - update.rs reads templates from extracted source, only updates existing targets - remove.rs loads local manifest for cleanup with legacy fallback - Save dist-manifest.yml locally in .devtrail/ for remove operations - Include dist-templates/ directory in release ZIP - Update unit tests (11) and integration tests (4) Co-Authored-By: Claude Opus 4.6 --- .github/workflows/release.yml | 4 +- cli/src/commands/init.rs | 112 ++++++---- cli/src/commands/remove.rs | 60 ++++-- cli/src/commands/update.rs | 96 ++++++--- cli/src/inject.rs | 202 ++++++++++++------ cli/src/manifest.rs | 23 +- cli/tests/inject_test.rs | 63 ++++-- dist-manifest.yml | 20 +- .../directives/cursor-rules-devtrail.md | 4 + dist-templates/directives/cursorrules | 4 + 10 files changed, 412 insertions(+), 176 deletions(-) create mode 100644 dist-templates/directives/cursor-rules-devtrail.md create mode 100644 dist-templates/directives/cursorrules diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7495df0..d3a507b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -49,9 +49,11 @@ jobs: # CI/CD mkdir -p dist-staging/.github/workflows - cp dist-templates/directives/copilot-instructions.md dist-staging/.github/copilot-instructions.md 2>/dev/null || true cp .github/workflows/docs-validation.yml dist-staging/.github/workflows/ 2>/dev/null || true + # Directive templates (used by CLI for injections) + cp -r dist-templates dist-staging/ 2>/dev/null || true + cd dist-staging zip -r "../devtrail-v${{ steps.version.outputs.version }}.zip" . cd .. diff --git a/cli/src/commands/init.rs b/cli/src/commands/init.rs index fdc3e54..41e4114 100644 --- a/cli/src/commands/init.rs +++ b/cli/src/commands/init.rs @@ -1,5 +1,6 @@ use anyhow::{bail, Context, Result}; use colored::Colorize; +use std::collections::HashMap; use std::path::{Path, PathBuf}; use crate::config::Checksums; @@ -45,14 +46,17 @@ pub fn run(path: &str) -> Result<()> { // Extract files according to manifest utils::info("Extracting files..."); - extract_distribution(&zip_path, &target)?; + let (manifest, templates) = extract_distribution(&zip_path, &target)?; // Create empty directory structure with .gitkeep create_empty_dirs(&target)?; // Inject into directive files utils::info("Configuring AI agent directives..."); - inject_directives(&target)?; + inject_directives(&target, &manifest, &templates)?; + + // Save manifest locally for future remove operations + save_local_manifest(&target, &manifest)?; // Save checksums save_initial_checksums(&target, &release.tag_name)?; @@ -76,8 +80,11 @@ pub fn run(path: &str) -> Result<()> { Ok(()) } -/// Extract distributable files from the release ZIP -fn extract_distribution(zip_path: &Path, target: &Path) -> Result<()> { +/// Extract distributable files from the release ZIP and read templates into memory +fn extract_distribution( + zip_path: &Path, + target: &Path, +) -> Result<(DistManifest, HashMap)> { let file = std::fs::File::open(zip_path).context("Failed to open ZIP file")?; let mut archive = zip::ZipArchive::new(file).context("Failed to read ZIP archive")?; @@ -115,7 +122,22 @@ fn extract_distribution(zip_path: &Path, target: &Path) -> Result<()> { extract_matching_files(&mut archive, &prefix, pattern, target)?; } - Ok(()) + // Read template files from ZIP into memory + let mut templates: HashMap = HashMap::new(); + for injection in &manifest.injections { + let zip_entry_name = format!("{}{}", prefix, injection.template); + for i in 0..archive.len() { + let mut entry = archive.by_index(i)?; + if entry.name() == zip_entry_name { + let mut content = String::new(); + std::io::Read::read_to_string(&mut entry, &mut content)?; + templates.insert(injection.template.clone(), content); + break; + } + } + } + + Ok((manifest, templates)) } /// Extract files from ZIP matching a manifest pattern @@ -187,44 +209,62 @@ fn create_empty_dirs(target: &Path) -> Result<()> { Ok(()) } -/// Inject DevTrail references into existing directive files -fn inject_directives(target: &Path) -> Result<()> { - // Reference-based injection - let reference_targets = [ - target.join("CLAUDE.md"), - target.join("GEMINI.md"), - target.join(".github/copilot-instructions.md"), - ]; +/// Inject DevTrail directives based on manifest and templates +fn inject_directives( + target: &Path, + manifest: &DistManifest, + templates: &HashMap, +) -> Result<()> { + for injection in &manifest.injections { + let template_content = match templates.get(&injection.template) { + Some(content) => content, + None => { + utils::warn(&format!( + "Template not found in ZIP: {}", + injection.template + )); + continue; + } + }; - for t in &reference_targets { - inject::inject_reference(t)?; - let name = t - .strip_prefix(target) - .unwrap_or(t) - .display() - .to_string(); - if t.exists() { - utils::success(&format!("Configured {}", name)); - } - } + let embed_content = if let Some(embed_file) = &injection.embed { + let embed_path = target.join(embed_file); + if embed_path.exists() { + Some(std::fs::read_to_string(&embed_path).with_context(|| { + format!("Failed to read embed file: {}", embed_path.display()) + })?) + } else { + utils::warn(&format!( + "Embed file not found: {} (skipping {})", + embed_file, injection.target + )); + continue; + } + } else { + None + }; - // Full content injection for .cursorrules - let devtrail_md = target.join("DEVTRAIL.md"); - if devtrail_md.exists() { - let content = std::fs::read_to_string(&devtrail_md)?; - let cursorrules = target.join(".cursorrules"); - inject::inject_full_content(&cursorrules, &content)?; - utils::success("Configured .cursorrules (inline)"); - - // .cursor/rules/ directory - let cursor_rules_dir = target.join(".cursor/rules"); - inject::inject_cursor_rules_dir(&cursor_rules_dir, &content)?; - utils::success("Configured .cursor/rules/devtrail.md"); + let target_path = target.join(&injection.target); + inject::inject_directive( + &target_path, + template_content, + embed_content.as_deref(), + )?; + utils::success(&format!("Configured {}", injection.target)); } Ok(()) } +/// Save the manifest locally for future remove operations +fn save_local_manifest(target: &Path, manifest: &DistManifest) -> Result<()> { + let manifest_path = target.join(".devtrail/dist-manifest.yml"); + let content = manifest.to_yaml()?; + std::fs::write(&manifest_path, content) + .context("Failed to save local dist-manifest.yml")?; + Ok(()) +} + /// Save initial checksums for all framework files fn save_initial_checksums(target: &Path, version: &str) -> Result<()> { let mut checksums = Checksums { diff --git a/cli/src/commands/remove.rs b/cli/src/commands/remove.rs index 3f5d41d..d29d83b 100644 --- a/cli/src/commands/remove.rs +++ b/cli/src/commands/remove.rs @@ -4,8 +4,19 @@ use dialoguer::{Confirm, theme::ColorfulTheme}; use std::path::Path; use crate::inject; +use crate::manifest::DistManifest; use crate::utils; +/// Legacy hardcoded targets for backwards compatibility with installations +/// that don't have a local dist-manifest.yml +const LEGACY_DIRECTIVE_TARGETS: &[&str] = &[ + "CLAUDE.md", + "GEMINI.md", + ".github/copilot-instructions.md", + ".cursorrules", + ".cursor/rules/devtrail.md", +]; + pub fn run(full: bool) -> Result<()> { let target = std::env::current_dir().context("Failed to get current directory")?; @@ -69,8 +80,7 @@ pub fn run(full: bool) -> Result<()> { remove_empty_dir(&target.join(".gemini"))?; remove_empty_dir(&target.join(".agent"))?; - // Remove cursor rules file (if we created it) - remove_file_if_exists(&target.join(".cursor/rules/devtrail.md"))?; + // Clean up .cursor directories (injections already handled by clean_directives) remove_empty_dir(&target.join(".cursor/rules"))?; remove_empty_dir(&target.join(".cursor"))?; @@ -105,17 +115,42 @@ pub fn run(full: bool) -> Result<()> { } fn clean_directives(target: &Path) -> Result<()> { - let files = [ - target.join("CLAUDE.md"), - target.join("GEMINI.md"), - target.join(".github/copilot-instructions.md"), - target.join(".cursorrules"), - ]; + // Try to load the local manifest for injection targets + let manifest_path = target.join(".devtrail/dist-manifest.yml"); + let directive_targets: Vec = if manifest_path.exists() { + match DistManifest::load(&manifest_path) { + Ok(manifest) => manifest + .injections + .iter() + .map(|inj| inj.target.clone()) + .collect(), + Err(_) => { + // Failed to parse — fall back to legacy list + LEGACY_DIRECTIVE_TARGETS + .iter() + .map(|s| s.to_string()) + .collect() + } + } + } else { + // No local manifest — legacy installation + LEGACY_DIRECTIVE_TARGETS + .iter() + .map(|s| s.to_string()) + .collect() + }; + + for directive_target in &directive_targets { + let path = target.join(directive_target); + if inject::remove_injection(&path)? { + utils::success(&format!("Cleaned {}", directive_target)); + } - for f in &files { - if inject::remove_injection(f)? { - let name = f.strip_prefix(target).unwrap_or(f).display().to_string(); - utils::success(&format!("Cleaned {}", name)); + // Clean up empty parent directories + if let Some(parent) = path.parent() { + if parent != target { + remove_empty_dir(parent)?; + } } } @@ -162,6 +197,7 @@ fn remove_framework_files(target: &Path) -> Result<()> { remove_file_if_exists(&devtrail.join("config.yml"))?; remove_file_if_exists(&devtrail.join("QUICK-REFERENCE.md"))?; remove_file_if_exists(&devtrail.join(".checksums.json"))?; + remove_file_if_exists(&devtrail.join("dist-manifest.yml"))?; Ok(()) } diff --git a/cli/src/commands/update.rs b/cli/src/commands/update.rs index 6a1af93..12605a1 100644 --- a/cli/src/commands/update.rs +++ b/cli/src/commands/update.rs @@ -6,6 +6,7 @@ use std::path::{Path, PathBuf}; use crate::config::Checksums; use crate::download; use crate::inject; +use crate::manifest::DistManifest; use crate::self_update; use crate::utils; @@ -53,13 +54,22 @@ pub fn run() -> Result<()> { std::fs::create_dir_all(&extract_dir)?; extract_all(&zip_path, &extract_dir)?; + // Find source root within extracted content + let source_root = find_source_root(&extract_dir)?; + + // Load manifest from extracted release + let manifest = DistManifest::load(&source_root.join("dist-manifest.yml"))?; + // Update framework files utils::info("Updating framework files..."); - let stats = update_files(&target, &extract_dir, ¤t_checksums)?; + let stats = update_files(&target, &source_root, ¤t_checksums)?; // Update directive injections utils::info("Updating AI agent directives..."); - inject_directives(&target)?; + inject_directives(&target, &source_root, &manifest)?; + + // Save manifest locally for future remove operations + save_local_manifest(&target, &manifest)?; // Save new checksums save_checksums(&target, &release.tag_name)?; @@ -86,7 +96,7 @@ struct UpdateStats { /// Update files, respecting user modifications fn update_files( target: &Path, - extract_dir: &Path, + source_root: &Path, checksums: &Checksums, ) -> Result { let mut stats = UpdateStats { @@ -95,15 +105,12 @@ fn update_files( added: 0, }; - // Find the root of the extracted content (may be nested) - let source_root = find_source_root(extract_dir)?; - // Walk extracted files - let entries = walkdir(source_root.clone())?; + let entries = walkdir(source_root.to_path_buf())?; for source_path in entries { let relative = source_path - .strip_prefix(&source_root) + .strip_prefix(source_root) .unwrap_or(&source_path) .display() .to_string(); @@ -118,6 +125,11 @@ fn update_files( continue; } + // Skip dist-manifest.yml (we save it separately) + if relative == ".devtrail/dist-manifest.yml" { + continue; + } + let target_path = target.join(&relative); if !target_path.exists() { @@ -182,37 +194,61 @@ fn update_files( Ok(stats) } -fn inject_directives(target: &Path) -> Result<()> { - let reference_targets = [ - target.join("CLAUDE.md"), - target.join("GEMINI.md"), - target.join(".github/copilot-instructions.md"), - ]; +/// Inject directives based on manifest and templates from the release +fn inject_directives(target: &Path, source_root: &Path, manifest: &DistManifest) -> Result<()> { + for injection in &manifest.injections { + let target_path = target.join(&injection.target); - for t in &reference_targets { - if t.exists() { - inject::inject_reference(t)?; + // In update mode, only update targets that already exist + if !target_path.exists() { + continue; } - } - - let devtrail_md = target.join("DEVTRAIL.md"); - if devtrail_md.exists() { - let content = std::fs::read_to_string(&devtrail_md)?; - let cursorrules = target.join(".cursorrules"); - if cursorrules.exists() { - inject::inject_full_content(&cursorrules, &content)?; - } + let template_path = source_root.join(&injection.template); + let template_content = match std::fs::read_to_string(&template_path) { + Ok(content) => content, + Err(_) => { + utils::warn(&format!( + "Template not found: {}", + injection.template + )); + continue; + } + }; + + let embed_content = if let Some(embed_file) = &injection.embed { + // Use the embed file from the release, not the local one + let embed_path = source_root.join(embed_file); + if embed_path.exists() { + Some(std::fs::read_to_string(&embed_path).with_context(|| { + format!("Failed to read embed file: {}", embed_path.display()) + })?) + } else { + utils::warn(&format!( + "Embed file not found in release: {} (skipping {})", + embed_file, injection.target + )); + continue; + } + } else { + None + }; - let cursor_rules_dir = target.join(".cursor/rules"); - if cursor_rules_dir.exists() { - inject::inject_cursor_rules_dir(&cursor_rules_dir, &content)?; - } + inject::inject_directive(&target_path, &template_content, embed_content.as_deref())?; } Ok(()) } +/// Save the manifest locally for future remove operations +fn save_local_manifest(target: &Path, manifest: &DistManifest) -> Result<()> { + let manifest_path = target.join(".devtrail/dist-manifest.yml"); + let content = manifest.to_yaml()?; + std::fs::write(&manifest_path, content) + .context("Failed to save local dist-manifest.yml")?; + Ok(()) +} + fn save_checksums(target: &Path, version: &str) -> Result<()> { let mut checksums = Checksums { version: version.to_string(), diff --git a/cli/src/inject.rs b/cli/src/inject.rs index 64cfef7..2a6d763 100644 --- a/cli/src/inject.rs +++ b/cli/src/inject.rs @@ -4,86 +4,69 @@ use std::path::Path; const MARKER_BEGIN: &str = ""; const MARKER_END: &str = ""; -/// Inject a lightweight reference into a directive file (CLAUDE.md, GEMINI.md, copilot-instructions.md) -pub fn inject_reference(target: &Path) -> Result<()> { - let reference_content = format!( - "{}\n> **Read and follow the rules in [DEVTRAIL.md](DEVTRAIL.md).**\n> That file contains all DevTrail documentation governance rules for this project.\n{}", - MARKER_BEGIN, MARKER_END - ); +/// Extract the marker block (begin marker through end marker, inclusive) from a template string. +/// Returns None if markers are not found. +fn extract_marker_block(template: &str) -> Option { + let start = template.find(MARKER_BEGIN)?; + let end = template.find(MARKER_END)?; + let end = end + MARKER_END.len(); + Some(template[start..end].to_string()) +} + +/// Build the marker block content for an injection. +/// +/// If `embed_content` is provided, wraps it between markers. +/// Otherwise, extracts the existing marker block from the template. +fn build_marker_block(template: &str, embed_content: Option<&str>) -> Result { + match embed_content { + Some(content) => Ok(format!("{}\n{}\n{}", MARKER_BEGIN, content.trim(), MARKER_END)), + None => extract_marker_block(template) + .context("Template is missing devtrail markers"), + } +} + +/// Build the full file content by replacing markers in the template with the marker block. +fn build_full_content(template: &str, marker_block: &str) -> String { + if let Some(original_block) = extract_marker_block(template) { + template.replace(&original_block, marker_block) + } else { + // Template has no markers — append block at the end + format!("{}\n\n{}\n", template.trim_end(), marker_block) + } +} + +/// Unified injection: apply a template (with optional embed content) to a target file. +/// +/// - If the target doesn't exist → create it with the full template content. +/// - If the target exists and has markers → replace the marker block. +/// - If the target exists without markers → append the marker block. +pub fn inject_directive(target: &Path, template_content: &str, embed_content: Option<&str>) -> Result<()> { + let marker_block = build_marker_block(template_content, embed_content)?; + let full_content = build_full_content(template_content, &marker_block); if target.exists() { let content = std::fs::read_to_string(target).context("Failed to read directive file")?; if content.contains(MARKER_BEGIN) { // Replace existing injection - let new_content = replace_between_markers(&content, &reference_content); + let new_content = replace_between_markers(&content, &marker_block); std::fs::write(target, new_content).context("Failed to write directive file")?; } else { // Append injection - let new_content = format!("{}\n\n{}\n", content.trim_end(), reference_content); + let new_content = format!("{}\n\n{}\n", content.trim_end(), marker_block); std::fs::write(target, new_content).context("Failed to write directive file")?; } } else { - // Create minimal file with just the injection - let filename = target - .file_name() - .and_then(|n| n.to_str()) - .unwrap_or("Unknown"); - let header = match filename { - "CLAUDE.md" => "# DevTrail - Claude Code Configuration", - "GEMINI.md" => "# DevTrail - Gemini CLI Configuration", - "copilot-instructions.md" => "# DevTrail - GitHub Copilot Configuration", - _ => "# DevTrail Configuration", - }; - let content = format!("{}\n\n{}\n", header, reference_content); + // Create new file with full template content if let Some(parent) = target.parent() { std::fs::create_dir_all(parent).context("Failed to create directory")?; } - std::fs::write(target, content).context("Failed to create directive file")?; - } - - Ok(()) -} - -/// Inject full DEVTRAIL.md content into .cursorrules (which doesn't support includes) -pub fn inject_full_content(target: &Path, devtrail_content: &str) -> Result<()> { - let inline_content = format!("{}\n{}\n{}", MARKER_BEGIN, devtrail_content.trim(), MARKER_END); - - if target.exists() { - let content = std::fs::read_to_string(target).context("Failed to read .cursorrules")?; - - if content.contains(MARKER_BEGIN) { - let new_content = replace_between_markers(&content, &inline_content); - std::fs::write(target, new_content).context("Failed to write .cursorrules")?; - } else { - let new_content = format!("{}\n\n{}\n", content.trim_end(), inline_content); - std::fs::write(target, new_content).context("Failed to write .cursorrules")?; - } - } else { - let content = format!( - "# DevTrail - Cursor Configuration\n\n{}\n", - inline_content - ); - std::fs::write(target, content).context("Failed to create .cursorrules")?; + std::fs::write(target, full_content).context("Failed to create directive file")?; } Ok(()) } -/// Create a devtrail.md file inside .cursor/rules/ directory -pub fn inject_cursor_rules_dir(target_dir: &Path, devtrail_content: &str) -> Result<()> { - std::fs::create_dir_all(target_dir).context("Failed to create .cursor/rules/ directory")?; - let target = target_dir.join("devtrail.md"); - let content = format!( - "# DevTrail - Cursor Rules\n\n{}\n{}\n{}\n", - MARKER_BEGIN, - devtrail_content.trim(), - MARKER_END - ); - std::fs::write(&target, content).context("Failed to write .cursor/rules/devtrail.md")?; - Ok(()) -} - /// Remove DevTrail injection from a directive file pub fn remove_injection(target: &Path) -> Result { if !target.exists() { @@ -139,6 +122,105 @@ fn remove_between_markers(content: &str) -> String { #[cfg(test)] mod tests { use super::*; + use tempfile::TempDir; + + #[test] + fn test_extract_marker_block() { + let template = "# Header\n\n\nsome content\n\n\nfooter"; + let block = extract_marker_block(template).unwrap(); + assert_eq!(block, "\nsome content\n"); + } + + #[test] + fn test_extract_marker_block_missing() { + let template = "# Header\n\nno markers here"; + assert!(extract_marker_block(template).is_none()); + } + + #[test] + fn test_build_marker_block_with_embed() { + let template = "# Header\n\n\n\n"; + let block = build_marker_block(template, Some("embedded content")).unwrap(); + assert_eq!(block, "\nembedded content\n"); + } + + #[test] + fn test_build_marker_block_without_embed() { + let template = "# Header\n\n\nstatic ref\n\n"; + let block = build_marker_block(template, None).unwrap(); + assert_eq!(block, "\nstatic ref\n"); + } + + #[test] + fn test_inject_directive_creates_file() { + let dir = TempDir::new().unwrap(); + let target = dir.path().join("CLAUDE.md"); + let template = "# DevTrail - Claude Code Configuration\n\n\n> **Read rules**\n\n"; + + inject_directive(&target, template, None).unwrap(); + + let content = std::fs::read_to_string(&target).unwrap(); + assert!(content.contains("# DevTrail - Claude Code Configuration")); + assert!(content.contains("")); + assert!(content.contains("> **Read rules**")); + assert!(content.contains("")); + } + + #[test] + fn test_inject_directive_with_embed_creates_file() { + let dir = TempDir::new().unwrap(); + let target = dir.path().join(".cursorrules"); + let template = "# DevTrail - Cursor Configuration\n\n\n\n"; + + inject_directive(&target, template, Some("# My Rules\nRule 1\nRule 2")).unwrap(); + + let content = std::fs::read_to_string(&target).unwrap(); + assert!(content.contains("# DevTrail - Cursor Configuration")); + assert!(content.contains("# My Rules")); + assert!(content.contains("Rule 1")); + } + + #[test] + fn test_inject_directive_appends_to_existing() { + let dir = TempDir::new().unwrap(); + let target = dir.path().join("CLAUDE.md"); + std::fs::write(&target, "# My Project\n\nCustom config here\n").unwrap(); + + let template = "# DevTrail\n\n\n> **Read rules**\n\n"; + inject_directive(&target, template, None).unwrap(); + + let content = std::fs::read_to_string(&target).unwrap(); + assert!(content.contains("# My Project")); + assert!(content.contains("Custom config here")); + assert!(content.contains("")); + assert!(content.contains("> **Read rules**")); + } + + #[test] + fn test_inject_directive_replaces_existing_markers() { + let dir = TempDir::new().unwrap(); + let target = dir.path().join("CLAUDE.md"); + std::fs::write(&target, "# My Project\n\n\nold content\n\n\nfooter\n").unwrap(); + + let template = "# DevTrail\n\n\nnew content\n\n"; + inject_directive(&target, template, None).unwrap(); + + let content = std::fs::read_to_string(&target).unwrap(); + assert!(content.contains("new content")); + assert!(!content.contains("old content")); + assert!(content.contains("# My Project")); + assert!(content.contains("footer")); + } + + #[test] + fn test_inject_directive_creates_parent_dirs() { + let dir = TempDir::new().unwrap(); + let target = dir.path().join(".github/copilot-instructions.md"); + let template = "# Config\n\n\nref\n\n"; + + inject_directive(&target, template, None).unwrap(); + assert!(target.exists()); + } #[test] fn test_replace_between_markers() { diff --git a/cli/src/manifest.rs b/cli/src/manifest.rs index 579c099..e163a3c 100644 --- a/cli/src/manifest.rs +++ b/cli/src/manifest.rs @@ -1,25 +1,23 @@ use anyhow::{Context, Result}; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; use std::path::Path; /// Parsed dist-manifest.yml -#[derive(Debug, Deserialize)] +#[derive(Debug, Deserialize, Serialize, Clone)] pub struct DistManifest { pub version: String, pub description: String, pub files: Vec, #[serde(default)] - pub injections: Option, + pub injections: Vec, } -#[derive(Debug, Deserialize)] -pub struct Injections { +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct Injection { + pub target: String, + pub template: String, #[serde(default)] - pub reference: Vec, - #[serde(default)] - pub inline: Vec, - #[serde(default)] - pub directory: Vec, + pub embed: Option, } impl DistManifest { @@ -34,4 +32,9 @@ impl DistManifest { std::fs::read_to_string(path).context("Failed to read dist-manifest.yml")?; Self::from_str(&content) } + + /// Serialize manifest to YAML string + pub fn to_yaml(&self) -> Result { + serde_yaml::to_string(self).context("Failed to serialize dist-manifest.yml") + } } diff --git a/cli/tests/inject_test.rs b/cli/tests/inject_test.rs index 0997d9d..7b7676c 100644 --- a/cli/tests/inject_test.rs +++ b/cli/tests/inject_test.rs @@ -1,25 +1,6 @@ use std::fs; use tempfile::TempDir; -#[test] -fn test_inject_reference_creates_file() { - let dir = TempDir::new().unwrap(); - let target = dir.path().join("CLAUDE.md"); - - // File doesn't exist yet - assert!(!target.exists()); - - // Run inject via the binary would require integration test setup. - // For now, test the marker format. - let content = "# DevTrail - Claude Code Configuration\n\n\n> **Read and follow the rules in [DEVTRAIL.md](DEVTRAIL.md).**\n\n"; - fs::write(&target, content).unwrap(); - - let result = fs::read_to_string(&target).unwrap(); - assert!(result.contains("")); - assert!(result.contains("")); - assert!(result.contains("DEVTRAIL.md")); -} - #[test] fn test_inject_markers_are_valid() { let begin = ""; @@ -32,6 +13,22 @@ fn test_inject_markers_are_valid() { assert!(end.ends_with("-->")); } +#[test] +fn test_inject_reference_creates_file() { + let dir = TempDir::new().unwrap(); + let target = dir.path().join("CLAUDE.md"); + + // Simulate what inject_directive does with a reference template + let template = "# DevTrail - Claude Code Configuration\n\n\n> **Read and follow the rules in [DEVTRAIL.md](DEVTRAIL.md).**\n> That file contains all DevTrail documentation governance rules for this project.\n\n"; + fs::write(&target, template).unwrap(); + + let result = fs::read_to_string(&target).unwrap(); + assert!(result.contains("")); + assert!(result.contains("")); + assert!(result.contains("DEVTRAIL.md")); + assert!(result.contains("# DevTrail - Claude Code Configuration")); +} + #[test] fn test_remove_injection() { let dir = TempDir::new().unwrap(); @@ -58,3 +55,31 @@ fn test_remove_injection() { assert!(result.contains("My Config")); assert!(result.contains("More custom stuff")); } + +#[test] +fn test_template_with_embed_markers() { + let dir = TempDir::new().unwrap(); + let target = dir.path().join(".cursorrules"); + + // Template with empty markers (embed-style) + let template = "# DevTrail - Cursor Configuration\n\n\n\n"; + let embed_content = "# DEVTRAIL Rules\nRule 1: Document everything\nRule 2: Follow conventions"; + + // Simulate inject_directive with embed: build marker block with embedded content + let marker_block = format!( + "\n{}\n", + embed_content.trim() + ); + let full_content = template.replace( + "\n", + &marker_block, + ); + fs::write(&target, &full_content).unwrap(); + + let result = fs::read_to_string(&target).unwrap(); + assert!(result.contains("# DevTrail - Cursor Configuration")); + assert!(result.contains("Rule 1: Document everything")); + assert!(result.contains("Rule 2: Follow conventions")); + assert!(result.contains("")); + assert!(result.contains("")); +} diff --git a/dist-manifest.yml b/dist-manifest.yml index 0fb1dd6..8aed148 100644 --- a/dist-manifest.yml +++ b/dist-manifest.yml @@ -27,11 +27,15 @@ files: # Files that are injected into existing directive files # (not copied, but merged via markers) injections: - reference: - - CLAUDE.md - - GEMINI.md - - .github/copilot-instructions.md - inline: - - .cursorrules - directory: - - .cursor/rules/devtrail.md + - target: CLAUDE.md + template: dist-templates/directives/CLAUDE.md + - target: GEMINI.md + template: dist-templates/directives/GEMINI.md + - target: .github/copilot-instructions.md + template: dist-templates/directives/copilot-instructions.md + - target: .cursorrules + template: dist-templates/directives/cursorrules + embed: DEVTRAIL.md + - target: .cursor/rules/devtrail.md + template: dist-templates/directives/cursor-rules-devtrail.md + embed: DEVTRAIL.md diff --git a/dist-templates/directives/cursor-rules-devtrail.md b/dist-templates/directives/cursor-rules-devtrail.md new file mode 100644 index 0000000..2cadea6 --- /dev/null +++ b/dist-templates/directives/cursor-rules-devtrail.md @@ -0,0 +1,4 @@ +# DevTrail - Cursor Rules + + + diff --git a/dist-templates/directives/cursorrules b/dist-templates/directives/cursorrules new file mode 100644 index 0000000..76a3822 --- /dev/null +++ b/dist-templates/directives/cursorrules @@ -0,0 +1,4 @@ +# DevTrail - Cursor Configuration + + + From 6bff671efb6b4da6445cad125089e59bac9e6bbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Villase=C3=B1or=20Montfort?= <195970+montfort@users.noreply.github.com> Date: Mon, 2 Mar 2026 13:26:23 -0600 Subject: [PATCH 4/5] chore: remove root directive files superseded by dist-templates These files were only serving as distribution examples and contained no project-specific development directives. The canonical templates now live in dist-templates/directives/ and are read by the CLI at runtime. Co-Authored-By: Claude Opus 4.6 --- .cursor/rules/devtrail.md | 12 --- .cursorrules | 185 -------------------------------- .github/copilot-instructions.md | 16 --- CLAUDE.md | 16 --- GEMINI.md | 16 --- 5 files changed, 245 deletions(-) delete mode 100644 .cursor/rules/devtrail.md delete mode 100644 .cursorrules delete mode 100644 .github/copilot-instructions.md delete mode 100644 CLAUDE.md delete mode 100644 GEMINI.md diff --git a/.cursor/rules/devtrail.md b/.cursor/rules/devtrail.md deleted file mode 100644 index 2a94b2d..0000000 --- a/.cursor/rules/devtrail.md +++ /dev/null @@ -1,12 +0,0 @@ -# DevTrail - Cursor Rules - -> **Read and follow the rules in [DEVTRAIL.md](../../DEVTRAIL.md).** -> That file contains all DevTrail documentation governance rules for this project. - -## Agent Identity - -When working on this project, identify yourself as: `cursor-v1.0` (or your version). - ---- - -*DevTrail v2.0.0 | [Strange Days Tech](https://strangedays.tech) — Because every change tells a story.* diff --git a/.cursorrules b/.cursorrules deleted file mode 100644 index bb6c77d..0000000 --- a/.cursorrules +++ /dev/null @@ -1,185 +0,0 @@ -# DevTrail - Cursor Configuration - -## Agent Identity - -When working on this project, identify yourself as: `cursor-v1.0` (or your version). - - -# DevTrail - Documentation Governance Rules - -> Read and follow these rules when working on this project. -> For complete rules: `.devtrail/00-governance/AGENT-RULES.md` - -## 1. Fundamental Principle - -> **"No significant change without a documented trace."** - -## 2. Language Configuration - -Check `.devtrail/config.yml` for the project's language setting: - -```yaml -language: en # Options: en, es (default: en) -``` - -**Template paths based on language:** - -| Language | Template Path | -|----------|---------------| -| `en` (default) | `.devtrail/templates/TEMPLATE-*.md` | -| `es` | `.devtrail/templates/i18n/es/TEMPLATE-*.md` | - -If the config file doesn't exist or `language` is not set, use English (`en`) as default. - -## 3. Documentation Reporting - -At the end of each task, you MUST report your DevTrail documentation status: - -**If you created documentation:** -``` -DevTrail: Created AILOG-2025-01-27-001-implement-auth.md -``` - -**If documentation was not needed:** -``` -DevTrail: No documentation required (minor change / <10 lines) -``` - -**If you should have documented but didn't:** -``` -DevTrail: Documentation pending - review required -``` - -## 4. Agent Identity - -- **Identify yourself** with your platform and version -- **Declare** your confidence level in decisions: `high | medium | low` -- **Record** your identification in the `agent:` field of the metadata - -## 5. Git Operations - -> **CRITICAL: Never commit directly to `main` branch.** - -All changes must go through feature/fix branches and Pull Requests. - -### Branch Prefixes - -| Prefix | Purpose | -|--------|---------| -| `feature/` or `feat/` | New features | -| `fix/` | Bug fixes | -| `hotfix/` | Urgent production fixes | -| `docs/` | Documentation only | -| `refactor/` | Code refactoring | -| `test/` | Test changes | - -### Conventional Commits - -| Prefix | Use Case | -|--------|----------| -| `feat:` | New feature | -| `fix:` | Bug fix | -| `docs:` | Documentation only | -| `refactor:` | No behavior change | -| `chore:` | Maintenance | - -## 6. When to Document - -### MANDATORY (create document) - -| Situation | Action | -|-----------|--------| -| >10 lines of code in business logic | Create AILOG | -| Decision between technical alternatives | Create AIDEC | -| Changes in security/authentication | Create AILOG + mark `risk_level: high` | -| Personal data (GDPR/PII) | Create AILOG + request ETH | -| Integration with external service | Create AILOG | -| Change in public API or DB schema | Create AILOG | - -### DO NOT DOCUMENT - -- Trivial changes (whitespace, typos, formatting) -- Sensitive information (credentials, tokens, API keys) - -## 7. File Naming Convention - -``` -[TYPE]-[YYYY-MM-DD]-[NNN]-[description].md -``` - -**Example**: `AILOG-2025-01-27-001-implement-oauth.md` - -## 8. Minimum Metadata - -```yaml ---- -id: AILOG-2025-01-27-001 -title: Brief description -status: accepted -created: 2025-01-27 -agent: your-agent-id-v1.0 -confidence: high | medium | low -review_required: true | false -risk_level: low | medium | high | critical ---- -``` - -## 9. Autonomy Limits - -| Type | Agent can do | Requires human | -|------|----------|----------------| -| **AILOG** | Create freely | - | -| **AIDEC** | Create freely | - | -| **ETH** | Create draft | Approval | -| **ADR** | Create draft | Review | -| **REQ** | Propose | Validation | -| **INC** | Contribute analysis | Conclusions | -| **TDE** | Identify | Prioritize | - -## 10. Documentation Map - -``` -.devtrail/ -├── 00-governance/ ← POLICIES AND RULES -├── 01-requirements/ ← REQ-*.md -├── 02-design/decisions/ ← ADR-*.md -├── 03-implementation/ ← Implementation guides -├── 04-testing/ ← TES-*.md -├── 05-operations/incidents/ ← INC-*.md -├── 06-evolution/technical-debt/← TDE-*.md -├── 07-ai-audit/ -│ ├── agent-logs/ ← AILOG-*.md -│ ├── decisions/ ← AIDEC-*.md -│ └── ethical-reviews/ ← ETH-*.md -└── templates/ ← Templates (load when creating) -``` - -## 11. When to Load Templates - -| Need to | Load | -|---------|------| -| Create AILOG | `.devtrail/templates/TEMPLATE-AILOG.md` | -| Create AIDEC | `.devtrail/templates/TEMPLATE-AIDEC.md` | -| Create ADR | `.devtrail/templates/TEMPLATE-ADR.md` | -| Naming questions | `.devtrail/00-governance/DOCUMENTATION-POLICY.md` | -| Autonomy questions | `.devtrail/00-governance/AGENT-RULES.md` | - -## 12. Quick Type Reference - -| Prefix | Name | Location | -|--------|------|----------| -| `AILOG` | AI Action Log | `.devtrail/07-ai-audit/agent-logs/` | -| `AIDEC` | AI Decision | `.devtrail/07-ai-audit/decisions/` | -| `ETH` | Ethical Review | `.devtrail/07-ai-audit/ethical-reviews/` | -| `ADR` | Architecture Decision Record | `.devtrail/02-design/decisions/` | -| `REQ` | Requirement | `.devtrail/01-requirements/` | -| `TES` | Test Plan | `.devtrail/04-testing/` | -| `INC` | Incident Post-mortem | `.devtrail/05-operations/incidents/` | -| `TDE` | Technical Debt | `.devtrail/06-evolution/technical-debt/` | - - ---- - -*DevTrail v2.0.0 | [Strange Days Tech](https://strangedays.tech) — Because every change tells a story.* - - diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md deleted file mode 100644 index 0b37494..0000000 --- a/.github/copilot-instructions.md +++ /dev/null @@ -1,16 +0,0 @@ -# DevTrail - GitHub Copilot Configuration - - -> **Read and follow the rules in [DEVTRAIL.md](../DEVTRAIL.md).** -> That file contains all DevTrail documentation governance rules for this project. - - -## Agent Identity - -When working on this project, identify yourself as: `copilot-cli-v1.0` (or your version). - ---- - -*DevTrail v2.0.0 | [Strange Days Tech](https://strangedays.tech) — Because every change tells a story.* - - diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index 5aff14c..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1,16 +0,0 @@ -# DevTrail - Claude Code Configuration - - -> **Read and follow the rules in [DEVTRAIL.md](DEVTRAIL.md).** -> That file contains all DevTrail documentation governance rules for this project. - - -## Agent Identity - -When working on this project, identify yourself as: `claude-code-v1.0` (or your version). - ---- - -*DevTrail v2.0.0 | [Strange Days Tech](https://strangedays.tech) — Because every change tells a story.* - - diff --git a/GEMINI.md b/GEMINI.md deleted file mode 100644 index d0a02f7..0000000 --- a/GEMINI.md +++ /dev/null @@ -1,16 +0,0 @@ -# DevTrail - Gemini CLI Configuration - - -> **Read and follow the rules in [DEVTRAIL.md](DEVTRAIL.md).** -> That file contains all DevTrail documentation governance rules for this project. - - -## Agent Identity - -When working on this project, identify yourself as: `gemini-cli-v1.0` (or your version). - ---- - -*DevTrail v2.0.0 | [Strange Days Tech](https://strangedays.tech) — Because every change tells a story.* - - From 38991e17041f402fc8084f43b1f69e2247396d9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Villase=C3=B1or=20Montfort?= <195970+montfort@users.noreply.github.com> Date: Mon, 2 Mar 2026 14:29:05 -0600 Subject: [PATCH 5/5] refactor: consolidate all distribution files under `dist/` Move .devtrail/, DEVTRAIL.md, dist-manifest.yml, dist-templates/, agent skills (.claude/skills, .gemini/skills, .agent/workflows), scripts/, and docs-validation.yml under dist/ so the repo root stays clean for contributor dev configs. Simplify release workflow to a single `cp -a dist/.` and add root-anchored gitignore rules for AI tool directories. Update all internal doc links accordingly. Co-Authored-By: Claude Opus 4.6 --- .github/workflows/release.yml | 27 +------------------ .gitignore | 10 +++++++ CONTRIBUTING.md | 26 ++++++++---------- README.md | 6 ++--- .../.agent}/workflows/devtrail-adr.md | 0 .../.agent}/workflows/devtrail-aidec.md | 0 .../.agent}/workflows/devtrail-ailog.md | 0 .../.agent}/workflows/devtrail-new.md | 0 .../.agent}/workflows/devtrail-status.md | 0 .../.claude}/skills/devtrail-adr/SKILL.md | 0 .../.claude}/skills/devtrail-aidec/SKILL.md | 0 .../.claude}/skills/devtrail-ailog/SKILL.md | 0 .../.claude}/skills/devtrail-new/SKILL.md | 0 .../.claude}/skills/devtrail-status/SKILL.md | 0 .../.devtrail}/00-governance/AGENT-RULES.md | 0 .../00-governance/DOCUMENTATION-POLICY.md | 0 .../00-governance/GIT-BRANCHING-STRATEGY.md | 0 .../.devtrail}/00-governance/PRINCIPLES.md | 0 .../00-governance/exceptions/.gitkeep | 0 .../00-governance/i18n/es/AGENT-RULES.md | 0 .../i18n/es/DOCUMENTATION-POLICY.md | 0 .../i18n/es/GIT-BRANCHING-STRATEGY.md | 0 .../00-governance/i18n/es/PRINCIPLES.md | 0 .../00-governance/i18n/es/QUICK-REFERENCE.md | 0 .../.devtrail}/01-requirements/.gitkeep | 0 .../.devtrail}/02-design/decisions/.gitkeep | 0 .../.devtrail}/03-implementation/.gitkeep | 0 .../.devtrail}/04-testing/.gitkeep | 0 .../05-operations/incidents/.gitkeep | 0 .../05-operations/runbooks/.gitkeep | 0 .../06-evolution/technical-debt/.gitkeep | 0 .../07-ai-audit/agent-logs/.gitkeep | 0 .../.devtrail}/07-ai-audit/decisions/.gitkeep | 0 .../07-ai-audit/ethical-reviews/.gitkeep | 0 .../.devtrail}/QUICK-REFERENCE.md | 0 {.devtrail => dist/.devtrail}/config.yml | 0 .../.devtrail}/templates/TEMPLATE-ADR.md | 0 .../.devtrail}/templates/TEMPLATE-AIDEC.md | 0 .../.devtrail}/templates/TEMPLATE-AILOG.md | 0 .../.devtrail}/templates/TEMPLATE-ETH.md | 0 .../.devtrail}/templates/TEMPLATE-INC.md | 0 .../.devtrail}/templates/TEMPLATE-REQ.md | 0 .../.devtrail}/templates/TEMPLATE-TDE.md | 0 .../.devtrail}/templates/TEMPLATE-TES.md | 0 .../templates/i18n/es/TEMPLATE-ADR.md | 0 .../templates/i18n/es/TEMPLATE-AIDEC.md | 0 .../templates/i18n/es/TEMPLATE-AILOG.md | 0 .../templates/i18n/es/TEMPLATE-ETH.md | 0 .../templates/i18n/es/TEMPLATE-INC.md | 0 .../templates/i18n/es/TEMPLATE-REQ.md | 0 .../templates/i18n/es/TEMPLATE-TDE.md | 0 .../templates/i18n/es/TEMPLATE-TES.md | 0 .../.gemini}/skills/devtrail-adr/SKILL.md | 0 .../.gemini}/skills/devtrail-aidec/SKILL.md | 0 .../.gemini}/skills/devtrail-ailog/SKILL.md | 0 .../.gemini}/skills/devtrail-new/SKILL.md | 0 .../.gemini}/skills/devtrail-status/SKILL.md | 0 .../.github}/workflows/docs-validation.yml | 0 DEVTRAIL.md => dist/DEVTRAIL.md | 0 dist-manifest.yml => dist/dist-manifest.yml | 0 .../dist-templates}/directives/CLAUDE.md | 0 .../dist-templates}/directives/GEMINI.md | 0 .../directives/copilot-instructions.md | 0 .../directives/cursor-rules-devtrail.md | 0 .../dist-templates}/directives/cursorrules | 0 {scripts => dist/scripts}/devtrail-new.sh | 0 {scripts => dist/scripts}/devtrail-status.sh | 0 {scripts => dist/scripts}/pre-commit-docs.sh | 0 {scripts => dist/scripts}/validate-docs.ps1 | 0 docs/README.md | 2 +- docs/i18n/es/CONTRIBUTING.md | 26 ++++++++---------- docs/i18n/es/README.md | 6 ++--- 72 files changed, 40 insertions(+), 63 deletions(-) rename {.agent => dist/.agent}/workflows/devtrail-adr.md (100%) rename {.agent => dist/.agent}/workflows/devtrail-aidec.md (100%) rename {.agent => dist/.agent}/workflows/devtrail-ailog.md (100%) rename {.agent => dist/.agent}/workflows/devtrail-new.md (100%) rename {.agent => dist/.agent}/workflows/devtrail-status.md (100%) rename {.claude => dist/.claude}/skills/devtrail-adr/SKILL.md (100%) rename {.claude => dist/.claude}/skills/devtrail-aidec/SKILL.md (100%) rename {.claude => dist/.claude}/skills/devtrail-ailog/SKILL.md (100%) rename {.claude => dist/.claude}/skills/devtrail-new/SKILL.md (100%) rename {.claude => dist/.claude}/skills/devtrail-status/SKILL.md (100%) rename {.devtrail => dist/.devtrail}/00-governance/AGENT-RULES.md (100%) rename {.devtrail => dist/.devtrail}/00-governance/DOCUMENTATION-POLICY.md (100%) rename {.devtrail => dist/.devtrail}/00-governance/GIT-BRANCHING-STRATEGY.md (100%) rename {.devtrail => dist/.devtrail}/00-governance/PRINCIPLES.md (100%) rename {.devtrail => dist/.devtrail}/00-governance/exceptions/.gitkeep (100%) rename {.devtrail => dist/.devtrail}/00-governance/i18n/es/AGENT-RULES.md (100%) rename {.devtrail => dist/.devtrail}/00-governance/i18n/es/DOCUMENTATION-POLICY.md (100%) rename {.devtrail => dist/.devtrail}/00-governance/i18n/es/GIT-BRANCHING-STRATEGY.md (100%) rename {.devtrail => dist/.devtrail}/00-governance/i18n/es/PRINCIPLES.md (100%) rename {.devtrail => dist/.devtrail}/00-governance/i18n/es/QUICK-REFERENCE.md (100%) rename {.devtrail => dist/.devtrail}/01-requirements/.gitkeep (100%) rename {.devtrail => dist/.devtrail}/02-design/decisions/.gitkeep (100%) rename {.devtrail => dist/.devtrail}/03-implementation/.gitkeep (100%) rename {.devtrail => dist/.devtrail}/04-testing/.gitkeep (100%) rename {.devtrail => dist/.devtrail}/05-operations/incidents/.gitkeep (100%) rename {.devtrail => dist/.devtrail}/05-operations/runbooks/.gitkeep (100%) rename {.devtrail => dist/.devtrail}/06-evolution/technical-debt/.gitkeep (100%) rename {.devtrail => dist/.devtrail}/07-ai-audit/agent-logs/.gitkeep (100%) rename {.devtrail => dist/.devtrail}/07-ai-audit/decisions/.gitkeep (100%) rename {.devtrail => dist/.devtrail}/07-ai-audit/ethical-reviews/.gitkeep (100%) rename {.devtrail => dist/.devtrail}/QUICK-REFERENCE.md (100%) rename {.devtrail => dist/.devtrail}/config.yml (100%) rename {.devtrail => dist/.devtrail}/templates/TEMPLATE-ADR.md (100%) rename {.devtrail => dist/.devtrail}/templates/TEMPLATE-AIDEC.md (100%) rename {.devtrail => dist/.devtrail}/templates/TEMPLATE-AILOG.md (100%) rename {.devtrail => dist/.devtrail}/templates/TEMPLATE-ETH.md (100%) rename {.devtrail => dist/.devtrail}/templates/TEMPLATE-INC.md (100%) rename {.devtrail => dist/.devtrail}/templates/TEMPLATE-REQ.md (100%) rename {.devtrail => dist/.devtrail}/templates/TEMPLATE-TDE.md (100%) rename {.devtrail => dist/.devtrail}/templates/TEMPLATE-TES.md (100%) rename {.devtrail => dist/.devtrail}/templates/i18n/es/TEMPLATE-ADR.md (100%) rename {.devtrail => dist/.devtrail}/templates/i18n/es/TEMPLATE-AIDEC.md (100%) rename {.devtrail => dist/.devtrail}/templates/i18n/es/TEMPLATE-AILOG.md (100%) rename {.devtrail => dist/.devtrail}/templates/i18n/es/TEMPLATE-ETH.md (100%) rename {.devtrail => dist/.devtrail}/templates/i18n/es/TEMPLATE-INC.md (100%) rename {.devtrail => dist/.devtrail}/templates/i18n/es/TEMPLATE-REQ.md (100%) rename {.devtrail => dist/.devtrail}/templates/i18n/es/TEMPLATE-TDE.md (100%) rename {.devtrail => dist/.devtrail}/templates/i18n/es/TEMPLATE-TES.md (100%) rename {.gemini => dist/.gemini}/skills/devtrail-adr/SKILL.md (100%) rename {.gemini => dist/.gemini}/skills/devtrail-aidec/SKILL.md (100%) rename {.gemini => dist/.gemini}/skills/devtrail-ailog/SKILL.md (100%) rename {.gemini => dist/.gemini}/skills/devtrail-new/SKILL.md (100%) rename {.gemini => dist/.gemini}/skills/devtrail-status/SKILL.md (100%) rename {.github => dist/.github}/workflows/docs-validation.yml (100%) rename DEVTRAIL.md => dist/DEVTRAIL.md (100%) rename dist-manifest.yml => dist/dist-manifest.yml (100%) rename {dist-templates => dist/dist-templates}/directives/CLAUDE.md (100%) rename {dist-templates => dist/dist-templates}/directives/GEMINI.md (100%) rename {dist-templates => dist/dist-templates}/directives/copilot-instructions.md (100%) rename {dist-templates => dist/dist-templates}/directives/cursor-rules-devtrail.md (100%) rename {dist-templates => dist/dist-templates}/directives/cursorrules (100%) rename {scripts => dist/scripts}/devtrail-new.sh (100%) rename {scripts => dist/scripts}/devtrail-status.sh (100%) rename {scripts => dist/scripts}/pre-commit-docs.sh (100%) rename {scripts => dist/scripts}/validate-docs.ps1 (100%) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d3a507b..ab1e610 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,33 +27,8 @@ jobs: - name: Create distribution ZIP run: | - # Read files from dist-manifest.yml and create ZIP mkdir -p dist-staging - - # Core framework - cp -r .devtrail dist-staging/ - cp DEVTRAIL.md dist-staging/ - cp dist-manifest.yml dist-staging/ - - # Agent skills - cp -r .claude/skills dist-staging/.claude/skills 2>/dev/null || true - cp -r .gemini/skills dist-staging/.gemini/skills 2>/dev/null || true - cp -r .agent/workflows dist-staging/.agent/workflows 2>/dev/null || true - - # Scripts - mkdir -p dist-staging/scripts - cp scripts/devtrail-new.sh dist-staging/scripts/ 2>/dev/null || true - cp scripts/devtrail-status.sh dist-staging/scripts/ 2>/dev/null || true - cp scripts/pre-commit-docs.sh dist-staging/scripts/ 2>/dev/null || true - cp scripts/validate-docs.ps1 dist-staging/scripts/ 2>/dev/null || true - - # CI/CD - mkdir -p dist-staging/.github/workflows - cp .github/workflows/docs-validation.yml dist-staging/.github/workflows/ 2>/dev/null || true - - # Directive templates (used by CLI for injections) - cp -r dist-templates dist-staging/ 2>/dev/null || true - + cp -a dist/. dist-staging/ cd dist-staging zip -r "../devtrail-v${{ steps.version.outputs.version }}.zip" . cd .. diff --git a/.gitignore b/.gitignore index 94b833b..635c8d9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,15 @@ # DevTrail - .gitignore +# ============================================================================= +# AI Tool Dev Configs (distribution content lives in dist/) +# ============================================================================= + +/.claude/ +/.gemini/ +/.agent/ +/.cursorrules +/.cursor/ + # ============================================================================= # Desarrollo interno de Strange Days Tech # ============================================================================= diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bc3fec8..fd6039b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -108,7 +108,7 @@ Code contributions should: 3. **Install the pre-commit hook** ```bash - cp scripts/pre-commit-docs.sh .git/hooks/pre-commit + cp dist/scripts/pre-commit-docs.sh .git/hooks/pre-commit chmod +x .git/hooks/pre-commit ``` @@ -128,10 +128,10 @@ Code contributions should: 6. **Make your changes and validate** ```bash # Linux/Mac - bash scripts/pre-commit-docs.sh + bash dist/scripts/pre-commit-docs.sh # Windows - .\scripts\validate-docs.ps1 + .\dist\scripts\validate-docs.ps1 ``` --- @@ -245,25 +245,21 @@ DevTrail documents: If you're proposing a new document type: 1. **Create the template** - - Add `TEMPLATE-NEWTYPE.md` to `.devtrail/templates/` + - Add `TEMPLATE-NEWTYPE.md` to `dist/.devtrail/templates/` - Follow existing template patterns 2. **Update governance docs** - - `.devtrail/00-governance/DOCUMENTATION-POLICY.md` - - `.devtrail/00-governance/AGENT-RULES.md` - - `.devtrail/QUICK-REFERENCE.md` + - `dist/.devtrail/00-governance/DOCUMENTATION-POLICY.md` + - `dist/.devtrail/00-governance/AGENT-RULES.md` + - `dist/.devtrail/QUICK-REFERENCE.md` 3. **Update agent configs** - - `CLAUDE.md` (dev-only) - - `GEMINI.md` (dev-only) - - `.cursorrules` (dev-only) - - `.github/copilot-instructions.md` (dev-only) - - `dist-templates/directives/` (distribution templates) + - `dist/dist-templates/directives/` (distribution templates) 4. **Update validation** - - `scripts/pre-commit-docs.sh` - - `scripts/validate-docs.ps1` - - `.github/workflows/docs-validation.yml` + - `dist/scripts/pre-commit-docs.sh` + - `dist/scripts/validate-docs.ps1` + - `dist/.github/workflows/docs-validation.yml` 5. **Document the change** - Create an ADR explaining the new type diff --git a/README.md b/README.md index e804c2f..515c1da 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](CONTRIBUTING.md) -[![Handbook](https://img.shields.io/badge/docs-Handbook-orange.svg)](.devtrail/QUICK-REFERENCE.md) +[![Handbook](https://img.shields.io/badge/docs-Handbook-orange.svg)](dist/.devtrail/QUICK-REFERENCE.md) [![Strange Days Tech](https://img.shields.io/badge/by-Strange_Days_Tech-purple.svg)](https://strangedays.tech) [Getting Started](#getting-started) • @@ -174,8 +174,8 @@ DevTrail documentation is organized by audience: | Document | Description | |----------|-------------| -| [**📘 Quick Reference**](.devtrail/QUICK-REFERENCE.md) | One-page overview of document types and naming | -| [DEVTRAIL.md](DEVTRAIL.md) | Unified governance rules (source of truth) | +| [**📘 Quick Reference**](dist/.devtrail/QUICK-REFERENCE.md) | One-page overview of document types and naming | +| [DEVTRAIL.md](dist/DEVTRAIL.md) | Unified governance rules (source of truth) | | [ADOPTION-GUIDE.md](docs/adopters/ADOPTION-GUIDE.md) | Adoption guide for new/existing projects | ### Internal Structure diff --git a/.agent/workflows/devtrail-adr.md b/dist/.agent/workflows/devtrail-adr.md similarity index 100% rename from .agent/workflows/devtrail-adr.md rename to dist/.agent/workflows/devtrail-adr.md diff --git a/.agent/workflows/devtrail-aidec.md b/dist/.agent/workflows/devtrail-aidec.md similarity index 100% rename from .agent/workflows/devtrail-aidec.md rename to dist/.agent/workflows/devtrail-aidec.md diff --git a/.agent/workflows/devtrail-ailog.md b/dist/.agent/workflows/devtrail-ailog.md similarity index 100% rename from .agent/workflows/devtrail-ailog.md rename to dist/.agent/workflows/devtrail-ailog.md diff --git a/.agent/workflows/devtrail-new.md b/dist/.agent/workflows/devtrail-new.md similarity index 100% rename from .agent/workflows/devtrail-new.md rename to dist/.agent/workflows/devtrail-new.md diff --git a/.agent/workflows/devtrail-status.md b/dist/.agent/workflows/devtrail-status.md similarity index 100% rename from .agent/workflows/devtrail-status.md rename to dist/.agent/workflows/devtrail-status.md diff --git a/.claude/skills/devtrail-adr/SKILL.md b/dist/.claude/skills/devtrail-adr/SKILL.md similarity index 100% rename from .claude/skills/devtrail-adr/SKILL.md rename to dist/.claude/skills/devtrail-adr/SKILL.md diff --git a/.claude/skills/devtrail-aidec/SKILL.md b/dist/.claude/skills/devtrail-aidec/SKILL.md similarity index 100% rename from .claude/skills/devtrail-aidec/SKILL.md rename to dist/.claude/skills/devtrail-aidec/SKILL.md diff --git a/.claude/skills/devtrail-ailog/SKILL.md b/dist/.claude/skills/devtrail-ailog/SKILL.md similarity index 100% rename from .claude/skills/devtrail-ailog/SKILL.md rename to dist/.claude/skills/devtrail-ailog/SKILL.md diff --git a/.claude/skills/devtrail-new/SKILL.md b/dist/.claude/skills/devtrail-new/SKILL.md similarity index 100% rename from .claude/skills/devtrail-new/SKILL.md rename to dist/.claude/skills/devtrail-new/SKILL.md diff --git a/.claude/skills/devtrail-status/SKILL.md b/dist/.claude/skills/devtrail-status/SKILL.md similarity index 100% rename from .claude/skills/devtrail-status/SKILL.md rename to dist/.claude/skills/devtrail-status/SKILL.md diff --git a/.devtrail/00-governance/AGENT-RULES.md b/dist/.devtrail/00-governance/AGENT-RULES.md similarity index 100% rename from .devtrail/00-governance/AGENT-RULES.md rename to dist/.devtrail/00-governance/AGENT-RULES.md diff --git a/.devtrail/00-governance/DOCUMENTATION-POLICY.md b/dist/.devtrail/00-governance/DOCUMENTATION-POLICY.md similarity index 100% rename from .devtrail/00-governance/DOCUMENTATION-POLICY.md rename to dist/.devtrail/00-governance/DOCUMENTATION-POLICY.md diff --git a/.devtrail/00-governance/GIT-BRANCHING-STRATEGY.md b/dist/.devtrail/00-governance/GIT-BRANCHING-STRATEGY.md similarity index 100% rename from .devtrail/00-governance/GIT-BRANCHING-STRATEGY.md rename to dist/.devtrail/00-governance/GIT-BRANCHING-STRATEGY.md diff --git a/.devtrail/00-governance/PRINCIPLES.md b/dist/.devtrail/00-governance/PRINCIPLES.md similarity index 100% rename from .devtrail/00-governance/PRINCIPLES.md rename to dist/.devtrail/00-governance/PRINCIPLES.md diff --git a/.devtrail/00-governance/exceptions/.gitkeep b/dist/.devtrail/00-governance/exceptions/.gitkeep similarity index 100% rename from .devtrail/00-governance/exceptions/.gitkeep rename to dist/.devtrail/00-governance/exceptions/.gitkeep diff --git a/.devtrail/00-governance/i18n/es/AGENT-RULES.md b/dist/.devtrail/00-governance/i18n/es/AGENT-RULES.md similarity index 100% rename from .devtrail/00-governance/i18n/es/AGENT-RULES.md rename to dist/.devtrail/00-governance/i18n/es/AGENT-RULES.md diff --git a/.devtrail/00-governance/i18n/es/DOCUMENTATION-POLICY.md b/dist/.devtrail/00-governance/i18n/es/DOCUMENTATION-POLICY.md similarity index 100% rename from .devtrail/00-governance/i18n/es/DOCUMENTATION-POLICY.md rename to dist/.devtrail/00-governance/i18n/es/DOCUMENTATION-POLICY.md diff --git a/.devtrail/00-governance/i18n/es/GIT-BRANCHING-STRATEGY.md b/dist/.devtrail/00-governance/i18n/es/GIT-BRANCHING-STRATEGY.md similarity index 100% rename from .devtrail/00-governance/i18n/es/GIT-BRANCHING-STRATEGY.md rename to dist/.devtrail/00-governance/i18n/es/GIT-BRANCHING-STRATEGY.md diff --git a/.devtrail/00-governance/i18n/es/PRINCIPLES.md b/dist/.devtrail/00-governance/i18n/es/PRINCIPLES.md similarity index 100% rename from .devtrail/00-governance/i18n/es/PRINCIPLES.md rename to dist/.devtrail/00-governance/i18n/es/PRINCIPLES.md diff --git a/.devtrail/00-governance/i18n/es/QUICK-REFERENCE.md b/dist/.devtrail/00-governance/i18n/es/QUICK-REFERENCE.md similarity index 100% rename from .devtrail/00-governance/i18n/es/QUICK-REFERENCE.md rename to dist/.devtrail/00-governance/i18n/es/QUICK-REFERENCE.md diff --git a/.devtrail/01-requirements/.gitkeep b/dist/.devtrail/01-requirements/.gitkeep similarity index 100% rename from .devtrail/01-requirements/.gitkeep rename to dist/.devtrail/01-requirements/.gitkeep diff --git a/.devtrail/02-design/decisions/.gitkeep b/dist/.devtrail/02-design/decisions/.gitkeep similarity index 100% rename from .devtrail/02-design/decisions/.gitkeep rename to dist/.devtrail/02-design/decisions/.gitkeep diff --git a/.devtrail/03-implementation/.gitkeep b/dist/.devtrail/03-implementation/.gitkeep similarity index 100% rename from .devtrail/03-implementation/.gitkeep rename to dist/.devtrail/03-implementation/.gitkeep diff --git a/.devtrail/04-testing/.gitkeep b/dist/.devtrail/04-testing/.gitkeep similarity index 100% rename from .devtrail/04-testing/.gitkeep rename to dist/.devtrail/04-testing/.gitkeep diff --git a/.devtrail/05-operations/incidents/.gitkeep b/dist/.devtrail/05-operations/incidents/.gitkeep similarity index 100% rename from .devtrail/05-operations/incidents/.gitkeep rename to dist/.devtrail/05-operations/incidents/.gitkeep diff --git a/.devtrail/05-operations/runbooks/.gitkeep b/dist/.devtrail/05-operations/runbooks/.gitkeep similarity index 100% rename from .devtrail/05-operations/runbooks/.gitkeep rename to dist/.devtrail/05-operations/runbooks/.gitkeep diff --git a/.devtrail/06-evolution/technical-debt/.gitkeep b/dist/.devtrail/06-evolution/technical-debt/.gitkeep similarity index 100% rename from .devtrail/06-evolution/technical-debt/.gitkeep rename to dist/.devtrail/06-evolution/technical-debt/.gitkeep diff --git a/.devtrail/07-ai-audit/agent-logs/.gitkeep b/dist/.devtrail/07-ai-audit/agent-logs/.gitkeep similarity index 100% rename from .devtrail/07-ai-audit/agent-logs/.gitkeep rename to dist/.devtrail/07-ai-audit/agent-logs/.gitkeep diff --git a/.devtrail/07-ai-audit/decisions/.gitkeep b/dist/.devtrail/07-ai-audit/decisions/.gitkeep similarity index 100% rename from .devtrail/07-ai-audit/decisions/.gitkeep rename to dist/.devtrail/07-ai-audit/decisions/.gitkeep diff --git a/.devtrail/07-ai-audit/ethical-reviews/.gitkeep b/dist/.devtrail/07-ai-audit/ethical-reviews/.gitkeep similarity index 100% rename from .devtrail/07-ai-audit/ethical-reviews/.gitkeep rename to dist/.devtrail/07-ai-audit/ethical-reviews/.gitkeep diff --git a/.devtrail/QUICK-REFERENCE.md b/dist/.devtrail/QUICK-REFERENCE.md similarity index 100% rename from .devtrail/QUICK-REFERENCE.md rename to dist/.devtrail/QUICK-REFERENCE.md diff --git a/.devtrail/config.yml b/dist/.devtrail/config.yml similarity index 100% rename from .devtrail/config.yml rename to dist/.devtrail/config.yml diff --git a/.devtrail/templates/TEMPLATE-ADR.md b/dist/.devtrail/templates/TEMPLATE-ADR.md similarity index 100% rename from .devtrail/templates/TEMPLATE-ADR.md rename to dist/.devtrail/templates/TEMPLATE-ADR.md diff --git a/.devtrail/templates/TEMPLATE-AIDEC.md b/dist/.devtrail/templates/TEMPLATE-AIDEC.md similarity index 100% rename from .devtrail/templates/TEMPLATE-AIDEC.md rename to dist/.devtrail/templates/TEMPLATE-AIDEC.md diff --git a/.devtrail/templates/TEMPLATE-AILOG.md b/dist/.devtrail/templates/TEMPLATE-AILOG.md similarity index 100% rename from .devtrail/templates/TEMPLATE-AILOG.md rename to dist/.devtrail/templates/TEMPLATE-AILOG.md diff --git a/.devtrail/templates/TEMPLATE-ETH.md b/dist/.devtrail/templates/TEMPLATE-ETH.md similarity index 100% rename from .devtrail/templates/TEMPLATE-ETH.md rename to dist/.devtrail/templates/TEMPLATE-ETH.md diff --git a/.devtrail/templates/TEMPLATE-INC.md b/dist/.devtrail/templates/TEMPLATE-INC.md similarity index 100% rename from .devtrail/templates/TEMPLATE-INC.md rename to dist/.devtrail/templates/TEMPLATE-INC.md diff --git a/.devtrail/templates/TEMPLATE-REQ.md b/dist/.devtrail/templates/TEMPLATE-REQ.md similarity index 100% rename from .devtrail/templates/TEMPLATE-REQ.md rename to dist/.devtrail/templates/TEMPLATE-REQ.md diff --git a/.devtrail/templates/TEMPLATE-TDE.md b/dist/.devtrail/templates/TEMPLATE-TDE.md similarity index 100% rename from .devtrail/templates/TEMPLATE-TDE.md rename to dist/.devtrail/templates/TEMPLATE-TDE.md diff --git a/.devtrail/templates/TEMPLATE-TES.md b/dist/.devtrail/templates/TEMPLATE-TES.md similarity index 100% rename from .devtrail/templates/TEMPLATE-TES.md rename to dist/.devtrail/templates/TEMPLATE-TES.md diff --git a/.devtrail/templates/i18n/es/TEMPLATE-ADR.md b/dist/.devtrail/templates/i18n/es/TEMPLATE-ADR.md similarity index 100% rename from .devtrail/templates/i18n/es/TEMPLATE-ADR.md rename to dist/.devtrail/templates/i18n/es/TEMPLATE-ADR.md diff --git a/.devtrail/templates/i18n/es/TEMPLATE-AIDEC.md b/dist/.devtrail/templates/i18n/es/TEMPLATE-AIDEC.md similarity index 100% rename from .devtrail/templates/i18n/es/TEMPLATE-AIDEC.md rename to dist/.devtrail/templates/i18n/es/TEMPLATE-AIDEC.md diff --git a/.devtrail/templates/i18n/es/TEMPLATE-AILOG.md b/dist/.devtrail/templates/i18n/es/TEMPLATE-AILOG.md similarity index 100% rename from .devtrail/templates/i18n/es/TEMPLATE-AILOG.md rename to dist/.devtrail/templates/i18n/es/TEMPLATE-AILOG.md diff --git a/.devtrail/templates/i18n/es/TEMPLATE-ETH.md b/dist/.devtrail/templates/i18n/es/TEMPLATE-ETH.md similarity index 100% rename from .devtrail/templates/i18n/es/TEMPLATE-ETH.md rename to dist/.devtrail/templates/i18n/es/TEMPLATE-ETH.md diff --git a/.devtrail/templates/i18n/es/TEMPLATE-INC.md b/dist/.devtrail/templates/i18n/es/TEMPLATE-INC.md similarity index 100% rename from .devtrail/templates/i18n/es/TEMPLATE-INC.md rename to dist/.devtrail/templates/i18n/es/TEMPLATE-INC.md diff --git a/.devtrail/templates/i18n/es/TEMPLATE-REQ.md b/dist/.devtrail/templates/i18n/es/TEMPLATE-REQ.md similarity index 100% rename from .devtrail/templates/i18n/es/TEMPLATE-REQ.md rename to dist/.devtrail/templates/i18n/es/TEMPLATE-REQ.md diff --git a/.devtrail/templates/i18n/es/TEMPLATE-TDE.md b/dist/.devtrail/templates/i18n/es/TEMPLATE-TDE.md similarity index 100% rename from .devtrail/templates/i18n/es/TEMPLATE-TDE.md rename to dist/.devtrail/templates/i18n/es/TEMPLATE-TDE.md diff --git a/.devtrail/templates/i18n/es/TEMPLATE-TES.md b/dist/.devtrail/templates/i18n/es/TEMPLATE-TES.md similarity index 100% rename from .devtrail/templates/i18n/es/TEMPLATE-TES.md rename to dist/.devtrail/templates/i18n/es/TEMPLATE-TES.md diff --git a/.gemini/skills/devtrail-adr/SKILL.md b/dist/.gemini/skills/devtrail-adr/SKILL.md similarity index 100% rename from .gemini/skills/devtrail-adr/SKILL.md rename to dist/.gemini/skills/devtrail-adr/SKILL.md diff --git a/.gemini/skills/devtrail-aidec/SKILL.md b/dist/.gemini/skills/devtrail-aidec/SKILL.md similarity index 100% rename from .gemini/skills/devtrail-aidec/SKILL.md rename to dist/.gemini/skills/devtrail-aidec/SKILL.md diff --git a/.gemini/skills/devtrail-ailog/SKILL.md b/dist/.gemini/skills/devtrail-ailog/SKILL.md similarity index 100% rename from .gemini/skills/devtrail-ailog/SKILL.md rename to dist/.gemini/skills/devtrail-ailog/SKILL.md diff --git a/.gemini/skills/devtrail-new/SKILL.md b/dist/.gemini/skills/devtrail-new/SKILL.md similarity index 100% rename from .gemini/skills/devtrail-new/SKILL.md rename to dist/.gemini/skills/devtrail-new/SKILL.md diff --git a/.gemini/skills/devtrail-status/SKILL.md b/dist/.gemini/skills/devtrail-status/SKILL.md similarity index 100% rename from .gemini/skills/devtrail-status/SKILL.md rename to dist/.gemini/skills/devtrail-status/SKILL.md diff --git a/.github/workflows/docs-validation.yml b/dist/.github/workflows/docs-validation.yml similarity index 100% rename from .github/workflows/docs-validation.yml rename to dist/.github/workflows/docs-validation.yml diff --git a/DEVTRAIL.md b/dist/DEVTRAIL.md similarity index 100% rename from DEVTRAIL.md rename to dist/DEVTRAIL.md diff --git a/dist-manifest.yml b/dist/dist-manifest.yml similarity index 100% rename from dist-manifest.yml rename to dist/dist-manifest.yml diff --git a/dist-templates/directives/CLAUDE.md b/dist/dist-templates/directives/CLAUDE.md similarity index 100% rename from dist-templates/directives/CLAUDE.md rename to dist/dist-templates/directives/CLAUDE.md diff --git a/dist-templates/directives/GEMINI.md b/dist/dist-templates/directives/GEMINI.md similarity index 100% rename from dist-templates/directives/GEMINI.md rename to dist/dist-templates/directives/GEMINI.md diff --git a/dist-templates/directives/copilot-instructions.md b/dist/dist-templates/directives/copilot-instructions.md similarity index 100% rename from dist-templates/directives/copilot-instructions.md rename to dist/dist-templates/directives/copilot-instructions.md diff --git a/dist-templates/directives/cursor-rules-devtrail.md b/dist/dist-templates/directives/cursor-rules-devtrail.md similarity index 100% rename from dist-templates/directives/cursor-rules-devtrail.md rename to dist/dist-templates/directives/cursor-rules-devtrail.md diff --git a/dist-templates/directives/cursorrules b/dist/dist-templates/directives/cursorrules similarity index 100% rename from dist-templates/directives/cursorrules rename to dist/dist-templates/directives/cursorrules diff --git a/scripts/devtrail-new.sh b/dist/scripts/devtrail-new.sh similarity index 100% rename from scripts/devtrail-new.sh rename to dist/scripts/devtrail-new.sh diff --git a/scripts/devtrail-status.sh b/dist/scripts/devtrail-status.sh similarity index 100% rename from scripts/devtrail-status.sh rename to dist/scripts/devtrail-status.sh diff --git a/scripts/pre-commit-docs.sh b/dist/scripts/pre-commit-docs.sh similarity index 100% rename from scripts/pre-commit-docs.sh rename to dist/scripts/pre-commit-docs.sh diff --git a/scripts/validate-docs.ps1 b/dist/scripts/validate-docs.ps1 similarity index 100% rename from scripts/validate-docs.ps1 rename to dist/scripts/validate-docs.ps1 diff --git a/docs/README.md b/docs/README.md index d7f7cb1..db70f30 100644 --- a/docs/README.md +++ b/docs/README.md @@ -39,4 +39,4 @@ docs/ --- -> **Note**: Development governance documentation (policies, templates, agent rules) lives in [`.devtrail/`](../.devtrail/) — not in this directory. See [QUICK-REFERENCE.md](../.devtrail/QUICK-REFERENCE.md) for an overview. +> **Note**: Development governance documentation (policies, templates, agent rules) lives in [`dist/.devtrail/`](../dist/.devtrail/) — not in this directory. See [QUICK-REFERENCE.md](../dist/.devtrail/QUICK-REFERENCE.md) for an overview. diff --git a/docs/i18n/es/CONTRIBUTING.md b/docs/i18n/es/CONTRIBUTING.md index c6a871e..6ecdd83 100644 --- a/docs/i18n/es/CONTRIBUTING.md +++ b/docs/i18n/es/CONTRIBUTING.md @@ -108,7 +108,7 @@ Las contribuciones de código deben: 3. **Instalar el hook de pre-commit** ```bash - cp scripts/pre-commit-docs.sh .git/hooks/pre-commit + cp dist/scripts/pre-commit-docs.sh .git/hooks/pre-commit chmod +x .git/hooks/pre-commit ``` @@ -128,10 +128,10 @@ Las contribuciones de código deben: 6. **Hacer tus cambios y validar** ```bash # Linux/Mac - bash scripts/pre-commit-docs.sh + bash dist/scripts/pre-commit-docs.sh # Windows - .\scripts\validate-docs.ps1 + .\dist\scripts\validate-docs.ps1 ``` --- @@ -245,25 +245,21 @@ Documentos DevTrail: Si estás proponiendo un nuevo tipo de documento: 1. **Crear la plantilla** - - Agregar `TEMPLATE-NUEVOTIPO.md` a `.devtrail/templates/` + - Agregar `TEMPLATE-NUEVOTIPO.md` a `dist/.devtrail/templates/` - Seguir patrones de plantillas existentes 2. **Actualizar docs de gobernanza** - - `.devtrail/00-governance/DOCUMENTATION-POLICY.md` - - `.devtrail/00-governance/AGENT-RULES.md` - - `.devtrail/QUICK-REFERENCE.md` + - `dist/.devtrail/00-governance/DOCUMENTATION-POLICY.md` + - `dist/.devtrail/00-governance/AGENT-RULES.md` + - `dist/.devtrail/QUICK-REFERENCE.md` 3. **Actualizar configs de agente** - - `CLAUDE.md` (solo desarrollo) - - `GEMINI.md` (solo desarrollo) - - `.cursorrules` (solo desarrollo) - - `.github/copilot-instructions.md` (solo desarrollo) - - `dist-templates/directives/` (plantillas de distribución) + - `dist/dist-templates/directives/` (plantillas de distribución) 4. **Actualizar validación** - - `scripts/pre-commit-docs.sh` - - `scripts/validate-docs.ps1` - - `.github/workflows/docs-validation.yml` + - `dist/scripts/pre-commit-docs.sh` + - `dist/scripts/validate-docs.ps1` + - `dist/.github/workflows/docs-validation.yml` 5. **Documentar el cambio** - Crear un ADR explicando el nuevo tipo diff --git a/docs/i18n/es/README.md b/docs/i18n/es/README.md index 8202544..c819698 100644 --- a/docs/i18n/es/README.md +++ b/docs/i18n/es/README.md @@ -6,7 +6,7 @@ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](../../../LICENSE) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](CONTRIBUTING.md) -[![Handbook](https://img.shields.io/badge/docs-Handbook-orange.svg)](../../../.devtrail/QUICK-REFERENCE.md) +[![Handbook](https://img.shields.io/badge/docs-Handbook-orange.svg)](../../../dist/.devtrail/QUICK-REFERENCE.md) [![Strange Days Tech](https://img.shields.io/badge/by-Strange_Days_Tech-purple.svg)](https://strangedays.tech) [Inicio Rápido](#inicio-rápido) • @@ -174,8 +174,8 @@ La documentación de DevTrail está organizada por audiencia: | Documento | Descripción | |-----------|-------------| -| [**📘 Referencia Rápida**](../../../.devtrail/QUICK-REFERENCE.md) | Resumen de tipos de documentos y nomenclatura | -| [DEVTRAIL.md](../../../DEVTRAIL.md) | Reglas de gobernanza unificadas (fuente de verdad) | +| [**📘 Referencia Rápida**](../../../dist/.devtrail/QUICK-REFERENCE.md) | Resumen de tipos de documentos y nomenclatura | +| [DEVTRAIL.md](../../../dist/DEVTRAIL.md) | Reglas de gobernanza unificadas (fuente de verdad) | | [ADOPTION-GUIDE.md](adopters/ADOPTION-GUIDE.md) | Guía de adopción para proyectos nuevos/existentes | ### Estructura Interna