diff --git a/.cursor/rules/devtrail.md b/.cursor/rules/devtrail.md new file mode 100644 index 0000000..2a94b2d --- /dev/null +++ b/.cursor/rules/devtrail.md @@ -0,0 +1,12 @@ +# 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 index c3ca1a1..7e465c6 100644 --- a/.cursorrules +++ b/.cursorrules @@ -1,8 +1,20 @@ -# DevTrail - Documentation Rules +# DevTrail - Cursor Configuration -> No significant change without a documented trace. +## Agent Identity -## Language Configuration +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: @@ -11,12 +23,15 @@ language: en # Options: en, es (default: en) ``` **Template paths based on language:** -- `en` (default): `.devtrail/templates/TEMPLATE-*.md` -- `es`: `.devtrail/templates/i18n/es/TEMPLATE-*.md` + +| 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. -## Documentation Reporting +## 3. Documentation Reporting At the end of each task, you MUST report your DevTrail documentation status: @@ -35,37 +50,66 @@ DevTrail: No documentation required (minor change / <10 lines) DevTrail: Documentation pending - review required ``` -This transparency helps users verify compliance with DevTrail rules. +## 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 -## Identity +## 5. Git Operations -You are an agent working on this project under DevTrail. -- Identify yourself as: `cursor-v1.0` -- Record your identification in the `agent:` field of metadata -- Declare confidence level: `high | medium | low` +> **CRITICAL: Never commit directly to `main` branch.** -## When to Document +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 business logic code | Create AILOG | -| Decision between alternatives | Create AIDEC | -| Security/authentication | AILOG + `risk_level: high` | -| Personal data (PII) | AILOG + request ETH | -| External integration | Create AILOG | -| Public API/DB change | Create AILOG | +| >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 -**DO NOT document**: whitespace, typos, credentials. +- Trivial changes (whitespace, typos, formatting) +- Sensitive information (credentials, tokens, API keys) -## Naming Convention +## 7. File Naming Convention ``` [TYPE]-[YYYY-MM-DD]-[NNN]-[description].md ``` -Example: `AILOG-2025-01-27-001-implement-oauth.md` +**Example**: `AILOG-2025-01-27-001-implement-oauth.md` -## Required Metadata +## 8. Minimum Metadata ```yaml --- @@ -73,44 +117,44 @@ id: AILOG-2025-01-27-001 title: Brief description status: accepted created: 2025-01-27 -agent: cursor-v1.0 +agent: your-agent-id-v1.0 confidence: high | medium | low review_required: true | false risk_level: low | medium | high | critical --- ``` -## Autonomy Limits +## 9. Autonomy Limits -| Type | Autonomy | -|------|----------| -| AILOG | Create freely | -| AIDEC | Create freely | -| ETH | Draft only → human approves | -| ADR | Create → requires review | -| REQ | Propose → human validates | -| TDE | Identify yes, prioritize no | +| 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 | -## Documentation Map (DevTrail) +## 10. Documentation Map ``` .devtrail/ -├── 00-governance/ ← Policies (load if in doubt) -│ ├── AGENT-RULES.md # Detailed rules -│ └── DOCUMENTATION-POLICY.md -├── 01-requirements/ ← REQ-*.md -├── 02-design/decisions/ ← ADR-*.md -├── 04-testing/ ← TES-*.md -├── 05-operations/incidents/← INC-*.md -├── 06-evolution/technical-debt/ ← TDE-*.md +├── 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 (create here) -│ ├── decisions/ ← AIDEC-*.md (create here) -│ └── ethical-reviews/ ← ETH-*.md -└── templates/ ← Templates (load when creating) +│ ├── agent-logs/ ← AILOG-*.md +│ ├── decisions/ ← AIDEC-*.md +│ └── ethical-reviews/ ← ETH-*.md +└── templates/ ← Templates (load when creating) ``` -## When to Load More +## 11. When to Load Templates | Need to | Load | |---------|------| @@ -120,14 +164,20 @@ risk_level: low | medium | high | critical | Naming questions | `.devtrail/00-governance/DOCUMENTATION-POLICY.md` | | Autonomy questions | `.devtrail/00-governance/AGENT-RULES.md` | -## Human Review +## 12. Quick Type Reference -Mark `review_required: true` when: -- `confidence: low` -- `risk_level: high | critical` -- Security decisions -- Irreversible changes +| 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 v1.0.0 | [Enigmora](https://enigmora.com)* +*DevTrail v2.0.0 | [Strange Days Tech](https://strangedays.tech) — Because every change tells a story.* diff --git a/.devtrail/00-governance/AGENT-RULES.md b/.devtrail/00-governance/AGENT-RULES.md index 3ef639b..134ee8b 100644 --- a/.devtrail/00-governance/AGENT-RULES.md +++ b/.devtrail/00-governance/AGENT-RULES.md @@ -179,4 +179,4 @@ If the agent makes an error: --- -*DevTrail v1.0.0 | [Enigmora](https://enigmora.com)* +*DevTrail v1.0.0 | [Strange Days Tech](https://strangedays.tech)* diff --git a/.devtrail/00-governance/DOCUMENTATION-POLICY.md b/.devtrail/00-governance/DOCUMENTATION-POLICY.md index 5081df0..cd2892c 100644 --- a/.devtrail/00-governance/DOCUMENTATION-POLICY.md +++ b/.devtrail/00-governance/DOCUMENTATION-POLICY.md @@ -150,4 +150,4 @@ See also [ADR-2025-01-20-001] for architectural context. --- -*DevTrail v1.0.0 | [Enigmora](https://enigmora.com)* +*DevTrail v1.0.0 | [Strange Days Tech](https://strangedays.tech)* diff --git a/.devtrail/00-governance/GIT-BRANCHING-STRATEGY.md b/.devtrail/00-governance/GIT-BRANCHING-STRATEGY.md index 9561103..7bbf409 100644 --- a/.devtrail/00-governance/GIT-BRANCHING-STRATEGY.md +++ b/.devtrail/00-governance/GIT-BRANCHING-STRATEGY.md @@ -91,4 +91,4 @@ git push -u origin fix/accidental-commits --- *DevTrail v1.0.0 | Last updated: 2025-01-30* -*[Enigmora](https://enigmora.com) — Because every change tells a story.* +*[Strange Days Tech](https://strangedays.tech) — Because every change tells a story.* diff --git a/.devtrail/00-governance/PRINCIPLES.md b/.devtrail/00-governance/PRINCIPLES.md index c253826..4a9638c 100644 --- a/.devtrail/00-governance/PRINCIPLES.md +++ b/.devtrail/00-governance/PRINCIPLES.md @@ -74,4 +74,4 @@ Certain types of changes **always** require human approval: --- -*DevTrail v1.0.0 | [Enigmora](https://enigmora.com)* +*DevTrail v1.0.0 | [Strange Days Tech](https://strangedays.tech)* diff --git a/.devtrail/00-governance/i18n/es/AGENT-RULES.md b/.devtrail/00-governance/i18n/es/AGENT-RULES.md index 11795bf..4a8d0bd 100644 --- a/.devtrail/00-governance/i18n/es/AGENT-RULES.md +++ b/.devtrail/00-governance/i18n/es/AGENT-RULES.md @@ -181,4 +181,4 @@ Si el agente comete un error: --- -*DevTrail v1.0.0 | [Enigmora](https://enigmora.com)* +*DevTrail v1.0.0 | [Strange Days Tech](https://strangedays.tech)* diff --git a/.devtrail/00-governance/i18n/es/DOCUMENTATION-POLICY.md b/.devtrail/00-governance/i18n/es/DOCUMENTATION-POLICY.md index 588ad9d..9ae19b3 100644 --- a/.devtrail/00-governance/i18n/es/DOCUMENTATION-POLICY.md +++ b/.devtrail/00-governance/i18n/es/DOCUMENTATION-POLICY.md @@ -152,4 +152,4 @@ Ver también [ADR-2025-01-20-001] para contexto arquitectónico. --- -*DevTrail v1.0.0 | [Enigmora](https://enigmora.com)* +*DevTrail v1.0.0 | [Strange Days Tech](https://strangedays.tech)* diff --git a/.devtrail/00-governance/i18n/es/GIT-BRANCHING-STRATEGY.md b/.devtrail/00-governance/i18n/es/GIT-BRANCHING-STRATEGY.md index c50546d..be2839f 100644 --- a/.devtrail/00-governance/i18n/es/GIT-BRANCHING-STRATEGY.md +++ b/.devtrail/00-governance/i18n/es/GIT-BRANCHING-STRATEGY.md @@ -91,4 +91,4 @@ git push -u origin fix/commits-accidentales --- *DevTrail v1.0.0 | Última actualización: 2025-01-30* -*[Enigmora](https://enigmora.com) — Porque cada cambio cuenta una historia.* +*[Strange Days Tech](https://strangedays.tech) — Porque cada cambio cuenta una historia.* diff --git a/.devtrail/00-governance/i18n/es/PRINCIPLES.md b/.devtrail/00-governance/i18n/es/PRINCIPLES.md index caf280c..d6d89b3 100644 --- a/.devtrail/00-governance/i18n/es/PRINCIPLES.md +++ b/.devtrail/00-governance/i18n/es/PRINCIPLES.md @@ -76,4 +76,4 @@ Ciertos tipos de cambios **siempre** requieren aprobación humana: --- -*DevTrail v1.0.0 | [Enigmora](https://enigmora.com)* +*DevTrail v1.0.0 | [Strange Days Tech](https://strangedays.tech)* diff --git a/.devtrail/00-governance/i18n/es/QUICK-REFERENCE.md b/.devtrail/00-governance/i18n/es/QUICK-REFERENCE.md index c3d0655..0243cca 100644 --- a/.devtrail/00-governance/i18n/es/QUICK-REFERENCE.md +++ b/.devtrail/00-governance/i18n/es/QUICK-REFERENCE.md @@ -151,4 +151,4 @@ Marcar `review_required: true` cuando: --- -*DevTrail v1.0.0 | [Enigmora](https://enigmora.com)* +*DevTrail v1.0.0 | [Strange Days Tech](https://strangedays.tech)* diff --git a/.devtrail/QUICK-REFERENCE.md b/.devtrail/QUICK-REFERENCE.md index 00884c1..aff3db4 100644 --- a/.devtrail/QUICK-REFERENCE.md +++ b/.devtrail/QUICK-REFERENCE.md @@ -167,4 +167,4 @@ Mark `review_required: true` when: --- -*DevTrail v2.0.0 | [Handbook](https://enigmora.github.io/devtrail/) | [Enigmora](https://enigmora.com)* +*DevTrail v2.0.0 | [GitHub](https://github.com/StrangeDaysTech/devtrail) | [Strange Days Tech](https://strangedays.tech)* diff --git a/.devtrail/config.yml b/.devtrail/config.yml index 771ba87..fe71d57 100644 --- a/.devtrail/config.yml +++ b/.devtrail/config.yml @@ -1,5 +1,5 @@ # DevTrail Configuration -# https://github.com/enigmora/devtrail-framework +# https://github.com/StrangeDaysTech/devtrail # Language setting for templates and documentation # Supported values: en, es diff --git a/.devtrail/templates/TEMPLATE-ADR.md b/.devtrail/templates/TEMPLATE-ADR.md index a0c8e69..bd74823 100644 --- a/.devtrail/templates/TEMPLATE-ADR.md +++ b/.devtrail/templates/TEMPLATE-ADR.md @@ -87,4 +87,4 @@ supersedes: [] |------|--------|--------| | YYYY-MM-DD | [agent/human] | Initial creation | - + diff --git a/.devtrail/templates/TEMPLATE-AIDEC.md b/.devtrail/templates/TEMPLATE-AIDEC.md index d31c3ea..890a545 100644 --- a/.devtrail/templates/TEMPLATE-AIDEC.md +++ b/.devtrail/templates/TEMPLATE-AIDEC.md @@ -81,4 +81,4 @@ related: [] --- - + diff --git a/.devtrail/templates/TEMPLATE-AILOG.md b/.devtrail/templates/TEMPLATE-AILOG.md index b460f7b..b18a4da 100644 --- a/.devtrail/templates/TEMPLATE-AILOG.md +++ b/.devtrail/templates/TEMPLATE-AILOG.md @@ -55,4 +55,4 @@ related: [] --- - + diff --git a/.devtrail/templates/TEMPLATE-ETH.md b/.devtrail/templates/TEMPLATE-ETH.md index 2e933ff..f8b3a12 100644 --- a/.devtrail/templates/TEMPLATE-ETH.md +++ b/.devtrail/templates/TEMPLATE-ETH.md @@ -103,4 +103,4 @@ approved_date: null | Decision | [APPROVED/REJECTED/CONDITIONAL] | | Conditions | [If applicable] | - + diff --git a/.devtrail/templates/TEMPLATE-INC.md b/.devtrail/templates/TEMPLATE-INC.md index 40c716e..6c63644 100644 --- a/.devtrail/templates/TEMPLATE-INC.md +++ b/.devtrail/templates/TEMPLATE-INC.md @@ -123,4 +123,4 @@ resolved_date: null | Review date | [YYYY-MM-DD] | | Status | [Draft/Reviewed/Closed] | - + diff --git a/.devtrail/templates/TEMPLATE-REQ.md b/.devtrail/templates/TEMPLATE-REQ.md index 2452c2d..85a0205 100644 --- a/.devtrail/templates/TEMPLATE-REQ.md +++ b/.devtrail/templates/TEMPLATE-REQ.md @@ -85,4 +85,4 @@ validated_date: null | Status | [Validated/Rejected/Modified] | | Comments | [Validator notes] | - + diff --git a/.devtrail/templates/TEMPLATE-TDE.md b/.devtrail/templates/TEMPLATE-TDE.md index db55168..13dc771 100644 --- a/.devtrail/templates/TEMPLATE-TDE.md +++ b/.devtrail/templates/TEMPLATE-TDE.md @@ -120,4 +120,4 @@ Impact │ │ │ | Assigned to | [Team/Person] | | Comments | [Notes] | - + diff --git a/.devtrail/templates/TEMPLATE-TES.md b/.devtrail/templates/TEMPLATE-TES.md index 4054a31..23c800f 100644 --- a/.devtrail/templates/TEMPLATE-TES.md +++ b/.devtrail/templates/TEMPLATE-TES.md @@ -98,4 +98,4 @@ related: [] | Date | [YYYY-MM-DD] | | Comments | [Notes] | - + diff --git a/.devtrail/templates/i18n/es/TEMPLATE-ADR.md b/.devtrail/templates/i18n/es/TEMPLATE-ADR.md index 366e51d..d760fd6 100644 --- a/.devtrail/templates/i18n/es/TEMPLATE-ADR.md +++ b/.devtrail/templates/i18n/es/TEMPLATE-ADR.md @@ -87,4 +87,4 @@ supersedes: [] |-------|-------|--------| | YYYY-MM-DD | [agente/humano] | Creación inicial | - + diff --git a/.devtrail/templates/i18n/es/TEMPLATE-AIDEC.md b/.devtrail/templates/i18n/es/TEMPLATE-AIDEC.md index 6c9222f..5f556c3 100644 --- a/.devtrail/templates/i18n/es/TEMPLATE-AIDEC.md +++ b/.devtrail/templates/i18n/es/TEMPLATE-AIDEC.md @@ -81,4 +81,4 @@ related: [] --- - + diff --git a/.devtrail/templates/i18n/es/TEMPLATE-AILOG.md b/.devtrail/templates/i18n/es/TEMPLATE-AILOG.md index 13bc041..3cec679 100644 --- a/.devtrail/templates/i18n/es/TEMPLATE-AILOG.md +++ b/.devtrail/templates/i18n/es/TEMPLATE-AILOG.md @@ -55,4 +55,4 @@ related: [] --- - + diff --git a/.devtrail/templates/i18n/es/TEMPLATE-ETH.md b/.devtrail/templates/i18n/es/TEMPLATE-ETH.md index b09a60c..ae46f5c 100644 --- a/.devtrail/templates/i18n/es/TEMPLATE-ETH.md +++ b/.devtrail/templates/i18n/es/TEMPLATE-ETH.md @@ -103,4 +103,4 @@ approved_date: null | Decisión | [APROBADO/RECHAZADO/CONDICIONAL] | | Condiciones | [Si aplica] | - + diff --git a/.devtrail/templates/i18n/es/TEMPLATE-INC.md b/.devtrail/templates/i18n/es/TEMPLATE-INC.md index 451655e..9d8154e 100644 --- a/.devtrail/templates/i18n/es/TEMPLATE-INC.md +++ b/.devtrail/templates/i18n/es/TEMPLATE-INC.md @@ -123,4 +123,4 @@ resolved_date: null | Fecha de revisión | [YYYY-MM-DD] | | Estado | [Borrador/Revisado/Cerrado] | - + diff --git a/.devtrail/templates/i18n/es/TEMPLATE-REQ.md b/.devtrail/templates/i18n/es/TEMPLATE-REQ.md index 13cb015..39c7c01 100644 --- a/.devtrail/templates/i18n/es/TEMPLATE-REQ.md +++ b/.devtrail/templates/i18n/es/TEMPLATE-REQ.md @@ -85,4 +85,4 @@ validated_date: null | Estado | [Validado/Rechazado/Modificado] | | Comentarios | [Notas del validador] | - + diff --git a/.devtrail/templates/i18n/es/TEMPLATE-TDE.md b/.devtrail/templates/i18n/es/TEMPLATE-TDE.md index 0004ca5..d2d1693 100644 --- a/.devtrail/templates/i18n/es/TEMPLATE-TDE.md +++ b/.devtrail/templates/i18n/es/TEMPLATE-TDE.md @@ -120,4 +120,4 @@ Impacto │ │ │ | Asignado a | [Equipo/Persona] | | Comentarios | [Notas] | - + diff --git a/.devtrail/templates/i18n/es/TEMPLATE-TES.md b/.devtrail/templates/i18n/es/TEMPLATE-TES.md index f86cb41..cd58c46 100644 --- a/.devtrail/templates/i18n/es/TEMPLATE-TES.md +++ b/.devtrail/templates/i18n/es/TEMPLATE-TES.md @@ -98,4 +98,4 @@ related: [] | Fecha | [YYYY-MM-DD] | | Comentarios | [Notas] | - + diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 7e85ec8..60a9ea8 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,159 +1,14 @@ -# DevTrail - Guidelines for GitHub Copilot +# DevTrail - GitHub Copilot Configuration -> This file configures GitHub Copilot CLI under DevTrail. + +> **Read and follow the rules in [DEVTRAIL.md](../DEVTRAIL.md).** +> That file contains all DevTrail documentation governance rules for this project. + -## Language Configuration +## Agent Identity -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. - -## 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 -``` - -This transparency helps users verify compliance with DevTrail rules. - -## Fundamental Principle - -> **"No significant change without a documented trace."** - -## Your Identity as an Agent - -When working on this project: - -- **Identify yourself** as: `copilot-cli-v1.0` -- **Declare** your confidence level in decisions: `high | medium | low` -- **Record** your identification in the `agent:` field of the metadata - -## 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) - -## File Naming Convention - -``` -[TYPE]-[YYYY-MM-DD]-[NNN]-[description].md -``` - -**Example**: `AILOG-2025-01-27-001-implement-oauth.md` - -## Required Metadata - -```yaml ---- -id: AILOG-2025-01-27-001 -title: Brief description -status: accepted -created: 2025-01-27 -agent: copilot-cli-v1.0 -confidence: high | medium | low -review_required: true | false -risk_level: low | medium | high | critical ---- -``` - -## Autonomy Limits - -| Type | Autonomy | -|------|----------| -| AILOG | Create freely | -| AIDEC | Create freely | -| ETH | Draft only → human approves | -| ADR | Create → requires review | -| REQ | Propose → human validates | -| TDE | Identify yes, prioritize no | - -## Documentation Map (DevTrail) - -``` -.devtrail/ -├── 00-governance/ ← Policies (load if in doubt) -│ ├── AGENT-RULES.md # Detailed rules -│ └── DOCUMENTATION-POLICY.md -├── 01-requirements/ ← REQ-*.md -├── 02-design/decisions/ ← ADR-*.md -├── 04-testing/ ← TES-*.md -├── 05-operations/incidents/← INC-*.md -├── 06-evolution/technical-debt/ ← TDE-*.md -├── 07-ai-audit/ -│ ├── agent-logs/ ← AILOG-*.md (create here) -│ ├── decisions/ ← AIDEC-*.md (create here) -│ └── ethical-reviews/ ← ETH-*.md -└── templates/ ← Templates (load when creating) -``` - -## 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` | - -## 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/` | - -## Human Review Required - -Mark `review_required: true` when: -- `confidence: low` -- `risk_level: high | critical` -- Security decisions -- Irreversible changes +When working on this project, identify yourself as: `copilot-cli-v1.0` (or your version). --- -*DevTrail v1.0.0 | [Enigmora](https://enigmora.com)* +*DevTrail v2.0.0 | [Strange Days Tech](https://strangedays.tech) — Because every change tells a story.* diff --git a/.github/workflows/docs-validation.yml b/.github/workflows/docs-validation.yml index 89f49bf..a0aaed1 100644 --- a/.github/workflows/docs-validation.yml +++ b/.github/workflows/docs-validation.yml @@ -3,7 +3,7 @@ # ============================================================================= # # This workflow validates documentation on each Pull Request and push to main. -# https://enigmora.com +# https://strangedays.tech # # Executes: # 1. File naming convention validation diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..177b5c3 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,163 @@ +name: Release + +on: + push: + tags: + - 'v*' + +permissions: + contents: write + +env: + CARGO_TERM_COLOR: always + +jobs: + # Job 1: Package distributable templates + package-templates: + name: Package Templates + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Read version from Cargo.toml + id: version + run: | + VERSION=$(grep '^version' cli/Cargo.toml | head -1 | sed 's/.*"\(.*\)".*/\1/') + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + + - 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/copilot-instructions.md dist-staging/.github/ 2>/dev/null || true + cp .github/workflows/docs-validation.yml dist-staging/.github/workflows/ 2>/dev/null || true + + cd dist-staging + zip -r "../devtrail-v${{ steps.version.outputs.version }}.zip" . + cd .. + + - name: Upload template artifact + uses: actions/upload-artifact@v4 + with: + name: templates + path: devtrail-v${{ steps.version.outputs.version }}.zip + + # Job 2: Build CLI binaries (cross-platform) + build-cli: + name: Build CLI (${{ matrix.target }}) + runs-on: ${{ matrix.os }} + strategy: + matrix: + include: + - target: x86_64-unknown-linux-gnu + os: ubuntu-latest + archive: tar.gz + - target: x86_64-apple-darwin + os: macos-latest + archive: tar.gz + - target: aarch64-apple-darwin + os: macos-latest + archive: tar.gz + - target: x86_64-pc-windows-msvc + os: windows-latest + archive: zip + + steps: + - uses: actions/checkout@v4 + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + with: + targets: ${{ matrix.target }} + + - name: Install OpenSSL (Linux) + if: matrix.os == 'ubuntu-latest' + run: sudo apt-get update && sudo apt-get install -y libssl-dev pkg-config + + - name: Read version + id: version + shell: bash + run: | + VERSION=$(grep '^version' cli/Cargo.toml | head -1 | sed 's/.*"\(.*\)".*/\1/') + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + + - name: Build release binary + run: cargo build --release --manifest-path cli/Cargo.toml --target ${{ matrix.target }} + + - name: Package (Unix) + if: matrix.archive == 'tar.gz' + shell: bash + run: | + BINARY=cli/target/${{ matrix.target }}/release/devtrail + ARCHIVE=devtrail-cli-v${{ steps.version.outputs.version }}-${{ matrix.target }}.tar.gz + tar czf "$ARCHIVE" -C "$(dirname "$BINARY")" "$(basename "$BINARY")" + echo "ARCHIVE=$ARCHIVE" >> "$GITHUB_ENV" + + - name: Package (Windows) + if: matrix.archive == 'zip' + shell: bash + run: | + BINARY=cli/target/${{ matrix.target }}/release/devtrail.exe + ARCHIVE=devtrail-cli-v${{ steps.version.outputs.version }}-${{ matrix.target }}.zip + 7z a "$ARCHIVE" "./$BINARY" + echo "ARCHIVE=$ARCHIVE" >> "$GITHUB_ENV" + + - name: Upload binary artifact + uses: actions/upload-artifact@v4 + with: + name: cli-${{ matrix.target }} + path: ${{ env.ARCHIVE }} + + # Job 3: Create GitHub Release + create-release: + name: Create Release + needs: [package-templates, build-cli] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Read version + id: version + run: | + VERSION=$(grep '^version' cli/Cargo.toml | head -1 | sed 's/.*"\(.*\)".*/\1/') + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + + - name: Download all artifacts + uses: actions/download-artifact@v4 + with: + path: release-artifacts + + - name: Collect release files + run: | + mkdir -p release + find release-artifacts -type f \( -name "*.zip" -o -name "*.tar.gz" \) -exec cp {} release/ \; + ls -la release/ + + - name: Create GitHub Release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh release create "${{ github.ref_name }}" \ + --title "DevTrail ${{ github.ref_name }}" \ + --generate-notes \ + release/* diff --git a/.gitignore b/.gitignore index b4fb4d5..23aaa7b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ -# Enigmora DevTrial - .gitignore +# DevTrail - .gitignore # ============================================================================= -# Desarrollo interno de Enigmora +# Desarrollo interno de Strange Days Tech # ============================================================================= copy-to-all-lnxdrive.sh @@ -70,15 +70,20 @@ yarn.lock *.bak # ============================================================================= -# Enigmora Chronicle Framework Specific +# DevTrail Framework Specific # ============================================================================= # Temporary validation files .markdownlint.json -# Generated index (if using auto-generation) -# Uncomment if you want to ignore the auto-generated index: -# .chronicle/INDEX.md +# ============================================================================= +# CLI Build Artifacts +# ============================================================================= + +cli/target/ +dist/ +*.tar.gz +release/ # ============================================================================= # Security - Never commit these diff --git a/ADOPTION-GUIDE.md b/ADOPTION-GUIDE.md index fe73222..6ae5e0c 100644 --- a/ADOPTION-GUIDE.md +++ b/ADOPTION-GUIDE.md @@ -2,7 +2,7 @@ **A comprehensive guide for adopting DevTrail in new or existing projects.** -[![Enigmora](https://img.shields.io/badge/by-Enigmora-purple.svg)](https://enigmora.com) +[![Strange Days Tech](https://img.shields.io/badge/by-Strange_Days_Tech-purple.svg)](https://strangedays.tech) --- @@ -153,68 +153,42 @@ DevTrail aligns with and supports compliance for: ## Adoption Path A: New Projects -### Option 1: Use as GitHub Template (Recommended) +### Option 1: CLI (Recommended) -1. **Create from template** - - Click "Use this template" on the [DevTrail repository](https://github.com/enigmora/devtrail-framework) to create a new repository. +```bash +# Install the CLI +cargo install devtrail-cli -2. **Clone your new repository** - ```bash - git clone https://github.com/your-username/your-new-project.git - cd your-new-project - ``` +# Initialize in your project +cd your-project +devtrail init . -3. **Remove example files (optional)** - ```bash - # Keep the structure, remove sample content - find .devtrail -name "*.md" -path "*-audit/*" -delete - find .devtrail -name "*.md" -path "*requirements/*" -delete - # etc. - ``` +# Commit +git add .devtrail/ DEVTRAIL.md scripts/ +git commit -m "chore: adopt DevTrail" +``` -4. **Customize agent configurations** +The CLI automatically: +- Downloads the latest DevTrail release from GitHub +- Sets up the `.devtrail/` directory structure +- Creates `DEVTRAIL.md` with governance rules +- Configures AI agent directives (`CLAUDE.md`, `GEMINI.md`, `.cursorrules`, etc.) +- Copies validation scripts and CI/CD workflows - Edit the agent configuration files to match your project context: - - `CLAUDE.md` - for Claude Code users - - `GEMINI.md` - for Gemini CLI users - - `.cursorrules` - for Cursor users - - `.github/copilot-instructions.md` - for Copilot CLI users +### Option 2: Manual Setup -5. **Initialize your documentation** - ```bash - # Create your first requirement - touch .devtrail/01-requirements/REQ-$(date +%Y-%m-%d)-001-initial-requirements.md - ``` +1. **Download the latest release** -### Option 2: Manual Setup + Go to [GitHub Releases](https://github.com/StrangeDaysTech/devtrail/releases/latest) and download the distribution ZIP. -1. **Download DevTrail** +2. **Extract to your project** ```bash - # Clone the repository - git clone https://github.com/enigmora/devtrail-framework.git devtrail-temp - - # Copy to your project - cp -r devtrail-temp/.devtrail your-project/ - cp devtrail-temp/CLAUDE.md your-project/ - cp devtrail-temp/GEMINI.md your-project/ - cp devtrail-temp/.cursorrules your-project/ - cp -r devtrail-temp/.github your-project/ - cp -r devtrail-temp/scripts your-project/ - - # Clean up - rm -rf devtrail-temp - ``` - -2. **Add to .gitignore (if needed)** - ```gitignore - # DevTrail - nothing to ignore by default - # Add patterns here if you generate temporary files + unzip devtrail-v*.zip -d your-project/ ``` 3. **Commit the structure** ```bash - git add .devtrail/ CLAUDE.md GEMINI.md .cursorrules .github/ scripts/ + git add .devtrail/ DEVTRAIL.md scripts/ git commit -m "chore: adopt DevTrail for documentation governance" ``` @@ -245,19 +219,11 @@ DevTrail aligns with and supports compliance for: 1. **Add DevTrail structure** ```bash - # Download and copy DevTrail files - git clone https://github.com/enigmora/devtrail-framework.git devtrail-temp - - # Copy structure (will not overwrite existing files) - cp -rn devtrail-temp/.devtrail ./ - cp -n devtrail-temp/CLAUDE.md ./ - cp -n devtrail-temp/GEMINI.md ./ - cp -n devtrail-temp/.cursorrules ./ - mkdir -p .github - cp -rn devtrail-temp/.github/* ./.github/ - cp -rn devtrail-temp/scripts ./ - - rm -rf devtrail-temp + # Using CLI (recommended) + devtrail init . + + # Or manually: download from GitHub Releases + # https://github.com/StrangeDaysTech/devtrail/releases/latest ``` 2. **Resolve conflicts with existing `docs/`** @@ -518,8 +484,8 @@ A: DevTrail rules are instructions, not enforcement. If an AI assistant creates ## Getting Help -- **Issues**: [GitHub Issues](https://github.com/enigmora/devtrail-framework/issues) -- **Discussions**: [GitHub Discussions](https://github.com/enigmora/devtrail-framework/discussions) +- **Issues**: [GitHub Issues](https://github.com/StrangeDaysTech/devtrail/issues) +- **Discussions**: [GitHub Discussions](https://github.com/StrangeDaysTech/devtrail/discussions) - **Contributing**: See [CONTRIBUTING.md](CONTRIBUTING.md) --- @@ -530,6 +496,6 @@ A: DevTrail rules are instructions, not enforcement. If an AI assistant creates **DevTrail** — Because every change tells a story. -[Back to README](README.md) • [Enigmora](https://enigmora.com) +[Back to README](README.md) • [Strange Days Tech](https://strangedays.tech) diff --git a/CLAUDE.md b/CLAUDE.md index cccc6a9..eb4207e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,287 +1,14 @@ -# DevTrail - Documentation Guidelines +# DevTrail - Claude Code Configuration -> **This file is automatically loaded at the start of each session.** -> It contains the essential rules of the DevTrail for development traceability. + +> **Read and follow the rules in [DEVTRAIL.md](DEVTRAIL.md).** +> That file contains all DevTrail documentation governance rules for this project. + ---- - -## 1. 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. - ---- - -## 2. 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 - use /devtrail-status to review -``` - -This transparency helps users verify compliance with DevTrail rules. - ---- - -## 3. Fundamental Principle - -> **"No significant change without a documented trace."** - ---- - -## 4. Your Identity as an Agent - -When working on this project: - -- **Identify yourself** as: `claude-code-v1.0` (or your 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 | - -### Quick Workflow - -```bash -git checkout main && git pull origin main -git checkout -b fix/descriptive-name -# ... make changes and commits ... -git push -u origin fix/descriptive-name -gh pr create --title "fix: description" --body "..." -``` - -> **Full details:** `.devtrail/00-governance/GIT-BRANCHING-STRATEGY.md` - ---- - -## 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: claude-code-v1.0 -confidence: high | medium | low -review_required: true | false -risk_level: low | medium | high | critical ---- -``` - ---- - -## 9. Autonomy Limits - -| Type | I 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) - -> **IMPORTANT**: This is the complete project structure. -> Not everything is loaded in this session, but I can access any document when needed. - -``` -.devtrail/ -├── 00-governance/ ← POLICIES AND RULES -│ ├── PRINCIPLES.md # Project guiding principles -│ ├── DOCUMENTATION-POLICY.md # Complete documentation policy -│ ├── AGENT-RULES.md # Detailed rules for AI agents -│ └── exceptions/ # Documented exceptions -│ -├── 01-requirements/ ← REQUIREMENTS (REQ) -│ └── [REQ-*.md] # System requirements -│ -├── 02-design/ ← DESIGN -│ └── decisions/ # ADRs (Architecture Decision Records) -│ └── [ADR-*.md] -│ -├── 03-implementation/ ← IMPLEMENTATION GUIDES -│ └── [technical guides] -│ -├── 04-testing/ ← TESTING (TES) -│ └── [TES-*.md] # Test strategies and plans -│ -├── 05-operations/ ← OPERATIONS -│ ├── [runbooks] -│ └── incidents/ # Post-mortems (INC) -│ └── [INC-*.md] -│ -├── 06-evolution/ ← EVOLUTION -│ └── technical-debt/ # Technical debt (TDE) -│ └── [TDE-*.md] -│ -├── 07-ai-audit/ ← AI AGENT AUDIT -│ ├── agent-logs/ # Action logs (AILOG) -│ │ └── [AILOG-*.md] -│ ├── decisions/ # Agent decisions (AIDEC) -│ │ └── [AIDEC-*.md] -│ └── ethical-reviews/ # Ethical reviews (ETH) -│ └── [ETH-*.md] -│ -├── templates/ ← TEMPLATES -│ ├── TEMPLATE-AILOG.md -│ ├── TEMPLATE-AIDEC.md -│ ├── TEMPLATE-ADR.md -│ ├── TEMPLATE-ETH.md -│ ├── TEMPLATE-REQ.md -│ ├── TEMPLATE-INC.md -│ └── TEMPLATE-TDE.md -│ -└── QUICK-REFERENCE.md ← 1-page quick reference -``` - ---- - -## 11. When to Load Additional Documents - -| Situation | Document to load | -|-----------|------------------| -| Going to create an AILOG | `.devtrail/templates/TEMPLATE-AILOG.md` | -| Going to create an AIDEC | `.devtrail/templates/TEMPLATE-AIDEC.md` | -| Going to create an ADR | `.devtrail/templates/TEMPLATE-ADR.md` | -| Going to create a REQ | `.devtrail/templates/TEMPLATE-REQ.md` | -| Questions about naming or metadata | `.devtrail/00-governance/DOCUMENTATION-POLICY.md` | -| Questions about my autonomy limits | `.devtrail/00-governance/AGENT-RULES.md` | -| Need to see existing requirements | List `.devtrail/01-requirements/` | -| Need to see existing ADRs | List `.devtrail/02-design/decisions/` | -| Need to see technical debt | List `.devtrail/06-evolution/technical-debt/` | - ---- - -## 12. Workflow - -``` -┌─────────────────────────────────────────────────────────────┐ -│ 1. EVALUATE if the change requires documentation │ -│ (see section 5) │ -└─────────────────────────────────────────────────────────────┘ - │ - ▼ -┌─────────────────────────────────────────────────────────────┐ -│ 2. LOAD the corresponding template │ -│ (see section 10) │ -└─────────────────────────────────────────────────────────────┘ - │ - ▼ -┌─────────────────────────────────────────────────────────────┐ -│ 3. CREATE the document with correct naming │ -│ [TYPE]-[YYYY-MM-DD]-[NNN]-[description].md │ -└─────────────────────────────────────────────────────────────┘ - │ - ▼ -┌─────────────────────────────────────────────────────────────┐ -│ 4. If risk_level: high/critical or confidence: low │ -│ → Mark review_required: true │ -└─────────────────────────────────────────────────────────────┘ -``` - ---- - -## 13. Quick Type Reference +## Agent Identity -| 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/` | +When working on this project, identify yourself as: `claude-code-v1.0` (or your version). --- -*DevTrail v1.0.0 | Last updated: 2025-01-27* -*For complete rules: `.devtrail/00-governance/AGENT-RULES.md`* -*[Enigmora](https://enigmora.com) — Because every change tells a story.* +*DevTrail v2.0.0 | [Strange Days Tech](https://strangedays.tech) — Because every change tells a story.* diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 2638fad..dea622c 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -51,7 +51,7 @@ This Code of Conduct also applies when an individual is officially representing If you experience or witness unacceptable behavior, or have any other concerns, please report it by contacting the project team at: -**Email**: [contacto@enigmora.com](mailto:contacto@enigmora.com) +**GitHub Issues**: [Report here](https://github.com/StrangeDaysTech/devtrail/issues) All reports will be reviewed and investigated promptly and fairly. @@ -99,7 +99,7 @@ Community leaders will follow these Community Impact Guidelines in determining t ## Appeals -If you believe you have been falsely or unfairly accused of violating this Code of Conduct, you may appeal by sending a detailed explanation to [contacto@enigmora.com](mailto:contacto@enigmora.com). Appeals will be reviewed by a different community leader than the one who made the original decision. +If you believe you have been falsely or unfairly accused of violating this Code of Conduct, you may appeal by opening a detailed issue at [GitHub Issues](https://github.com/StrangeDaysTech/devtrail/issues). Appeals will be reviewed by a different community leader than the one who made the original decision. ## Attribution @@ -127,5 +127,5 @@ For answers to common questions about this code of conduct, see the FAQ at [http

DevTrail
Building an inclusive community together
- Enigmora SC + Strange Days Tech, S.A.S.

diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b9a40b9..f480343 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -268,12 +268,57 @@ Templates should include: --- +## CLI Development + +The DevTrail CLI is written in Rust and located in the `cli/` directory. + +### Building + +```bash +cd cli +cargo build +``` + +### Running Tests + +```bash +cd cli +cargo test +``` + +### Release Build + +```bash +cd cli +cargo build --release +``` + +The release binary is optimized with LTO and stripped for minimal size. + +### Architecture + +``` +cli/src/ +├── main.rs # Entry point + clap CLI definition +├── commands/ +│ ├── init.rs # devtrail init [path] +│ ├── update.rs # devtrail update +│ └── remove.rs # devtrail remove [--full] +├── config.rs # Config and checksums management +├── download.rs # GitHub Releases download +├── inject.rs # Directive file injection (markers) +├── manifest.rs # dist-manifest.yml parsing +└── utils.rs # Helpers (hashing, colors, paths) +``` + +--- + ## Questions? If you have questions about contributing: -1. Check existing [Issues](https://github.com/enigmora/devtrail-framework/issues) -2. Check [Discussions](https://github.com/enigmora/devtrail-framework/discussions) +1. Check existing [Issues](https://github.com/StrangeDaysTech/devtrail/issues) +2. Check [Discussions](https://github.com/StrangeDaysTech/devtrail/discussions) 3. Open a new Discussion for general questions 4. Open an Issue for specific bugs or features @@ -293,4 +338,4 @@ Thank you for helping make DevTrail better! *DevTrail — Because every change tells a story.* -[Enigmora](https://enigmora.com) +[Strange Days Tech](https://strangedays.tech) diff --git a/DEVTRAIL.md b/DEVTRAIL.md new file mode 100644 index 0000000..91a9949 --- /dev/null +++ b/DEVTRAIL.md @@ -0,0 +1,278 @@ +# DevTrail - Documentation Governance Rules + +> **This file is automatically managed by DevTrail CLI.** +> 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 +``` + +This transparency helps users verify compliance with DevTrail rules. + +--- + +## 4. Agent Identity + +When working on this project: + +- **Identify yourself** with your platform and version (e.g., `claude-code-v1.0`, `gemini-cli-v1.0`, `copilot-cli-v1.0`) +- **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 | + +### Quick Workflow + +```bash +git checkout main && git pull origin main +git checkout -b fix/descriptive-name +# ... make changes and commits ... +git push -u origin fix/descriptive-name +gh pr create --title "fix: description" --body "..." +``` + +> **Full details:** `.devtrail/00-governance/GIT-BRANCHING-STRATEGY.md` + +--- + +## 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 + +> **IMPORTANT**: This is the complete project structure. +> Not everything is loaded in this session, but any document can be accessed when needed. + +``` +.devtrail/ +├── 00-governance/ ← POLICIES AND RULES +│ ├── PRINCIPLES.md # Project guiding principles +│ ├── DOCUMENTATION-POLICY.md # Complete documentation policy +│ ├── AGENT-RULES.md # Detailed rules for AI agents +│ └── exceptions/ # Documented exceptions +│ +├── 01-requirements/ ← REQUIREMENTS (REQ) +│ └── [REQ-*.md] # System requirements +│ +├── 02-design/ ← DESIGN +│ └── decisions/ # ADRs (Architecture Decision Records) +│ └── [ADR-*.md] +│ +├── 03-implementation/ ← IMPLEMENTATION GUIDES +│ └── [technical guides] +│ +├── 04-testing/ ← TESTING (TES) +│ └── [TES-*.md] # Test strategies and plans +│ +├── 05-operations/ ← OPERATIONS +│ ├── [runbooks] +│ └── incidents/ # Post-mortems (INC) +│ └── [INC-*.md] +│ +├── 06-evolution/ ← EVOLUTION +│ └── technical-debt/ # Technical debt (TDE) +│ └── [TDE-*.md] +│ +├── 07-ai-audit/ ← AI AGENT AUDIT +│ ├── agent-logs/ # Action logs (AILOG) +│ │ └── [AILOG-*.md] +│ ├── decisions/ # Agent decisions (AIDEC) +│ │ └── [AIDEC-*.md] +│ └── ethical-reviews/ # Ethical reviews (ETH) +│ └── [ETH-*.md] +│ +├── templates/ ← TEMPLATES +│ ├── TEMPLATE-AILOG.md +│ ├── TEMPLATE-AIDEC.md +│ ├── TEMPLATE-ADR.md +│ ├── TEMPLATE-ETH.md +│ ├── TEMPLATE-REQ.md +│ ├── TEMPLATE-INC.md +│ ├── TEMPLATE-TDE.md +│ └── TEMPLATE-TES.md +│ +└── QUICK-REFERENCE.md ← 1-page quick reference +``` + +--- + +## 11. When to Load Additional Documents + +| Situation | Document to load | +|-----------|------------------| +| Going to create an AILOG | `.devtrail/templates/TEMPLATE-AILOG.md` | +| Going to create an AIDEC | `.devtrail/templates/TEMPLATE-AIDEC.md` | +| Going to create an ADR | `.devtrail/templates/TEMPLATE-ADR.md` | +| Going to create a REQ | `.devtrail/templates/TEMPLATE-REQ.md` | +| Questions about naming or metadata | `.devtrail/00-governance/DOCUMENTATION-POLICY.md` | +| Questions about autonomy limits | `.devtrail/00-governance/AGENT-RULES.md` | +| Need to see existing requirements | List `.devtrail/01-requirements/` | +| Need to see existing ADRs | List `.devtrail/02-design/decisions/` | +| Need to see technical debt | List `.devtrail/06-evolution/technical-debt/` | + +--- + +## 12. Workflow + +``` +1. EVALUATE if the change requires documentation (see section 6) + | + v +2. LOAD the corresponding template (see section 11) + | + v +3. CREATE the document with correct naming + [TYPE]-[YYYY-MM-DD]-[NNN]-[description].md + | + v +4. If risk_level: high/critical or confidence: low + -> Mark review_required: true +``` + +--- + +## 13. 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 | [GitHub](https://github.com/StrangeDaysTech/devtrail)* +*[Strange Days Tech](https://strangedays.tech) — Because every change tells a story.* diff --git a/GEMINI.md b/GEMINI.md index 12e3345..5ce78bc 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -1,284 +1,14 @@ -# DevTrail - Documentation Guidelines +# DevTrail - Gemini CLI Configuration -> **This file is automatically loaded by Gemini CLI.** -> It contains the essential rules of the DevTrail for development traceability. + +> **Read and follow the rules in [DEVTRAIL.md](DEVTRAIL.md).** +> That file contains all DevTrail documentation governance rules for this project. + ---- - -## 1. 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. - ---- - -## 2. 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 -``` - -This transparency helps users verify compliance with DevTrail rules. - ---- - -## 3. Fundamental Principle - -> **"No significant change without a documented trace."** - ---- - -## 4. Your Identity as an Agent - -When working on this project: - -- **Identify yourself** as: `gemini-cli-v1.0` (or your 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 | - -### Quick Workflow - -```bash -git checkout main && git pull origin main -git checkout -b fix/descriptive-name -# ... make changes and commits ... -git push -u origin fix/descriptive-name -gh pr create --title "fix: description" --body "..." -``` - -> **Full details:** `.devtrail/00-governance/GIT-BRANCHING-STRATEGY.md` - ---- - -## 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: gemini-cli-v1.0 -confidence: high | medium | low -review_required: true | false -risk_level: low | medium | high | critical ---- -``` - ---- - -## 9. Autonomy Limits - -| Type | I 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) - -``` -.devtrail/ -├── 00-governance/ <- POLICIES AND RULES -│ ├── PRINCIPLES.md # Project guiding principles -│ ├── DOCUMENTATION-POLICY.md # Complete documentation policy -│ ├── AGENT-RULES.md # Detailed rules for AI agents -│ └── exceptions/ # Documented exceptions -│ -├── 01-requirements/ <- REQUIREMENTS (REQ) -│ └── [REQ-*.md] # System requirements -│ -├── 02-design/ <- DESIGN -│ └── decisions/ # ADRs (Architecture Decision Records) -│ └── [ADR-*.md] -│ -├── 03-implementation/ <- IMPLEMENTATION GUIDES -│ └── [technical guides] -│ -├── 04-testing/ <- TESTING (TES) -│ └── [TES-*.md] # Test strategies and plans -│ -├── 05-operations/ <- OPERATIONS -│ ├── [runbooks] -│ └── incidents/ # Post-mortems (INC) -│ └── [INC-*.md] -│ -├── 06-evolution/ <- EVOLUTION -│ └── technical-debt/ # Technical debt (TDE) -│ └── [TDE-*.md] -│ -├── 07-ai-audit/ <- AI AGENT AUDIT -│ ├── agent-logs/ # Action logs (AILOG) -│ │ └── [AILOG-*.md] -│ ├── decisions/ # Agent decisions (AIDEC) -│ │ └── [AIDEC-*.md] -│ └── ethical-reviews/ # Ethical reviews (ETH) -│ └── [ETH-*.md] -│ -├── templates/ <- TEMPLATES -│ ├── TEMPLATE-AILOG.md -│ ├── TEMPLATE-AIDEC.md -│ ├── TEMPLATE-ADR.md -│ ├── TEMPLATE-ETH.md -│ ├── TEMPLATE-REQ.md -│ ├── TEMPLATE-INC.md -│ └── TEMPLATE-TDE.md -│ -└── QUICK-REFERENCE.md <- 1-page quick reference -``` - ---- - -## 11. When to Load Additional Documents - -| Situation | Document to load | -|-----------|------------------| -| Going to create an AILOG | `.devtrail/templates/TEMPLATE-AILOG.md` | -| Going to create an AIDEC | `.devtrail/templates/TEMPLATE-AIDEC.md` | -| Going to create an ADR | `.devtrail/templates/TEMPLATE-ADR.md` | -| Going to create a REQ | `.devtrail/templates/TEMPLATE-REQ.md` | -| Questions about naming or metadata | `.devtrail/00-governance/DOCUMENTATION-POLICY.md` | -| Questions about my autonomy limits | `.devtrail/00-governance/AGENT-RULES.md` | -| Need to see existing requirements | List `.devtrail/01-requirements/` | -| Need to see existing ADRs | List `.devtrail/02-design/decisions/` | -| Need to see technical debt | List `.devtrail/06-evolution/technical-debt/` | - ---- - -## 12. Workflow - -``` -1. EVALUATE if the change requires documentation (see section 5) - | - v -2. LOAD the corresponding template (see section 10) - | - v -3. CREATE the document with correct naming - [TYPE]-[YYYY-MM-DD]-[NNN]-[description].md - | - v -4. If risk_level: high/critical or confidence: low - -> Mark review_required: true -``` - ---- - -## 13. 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/` | - ---- - -## 14. Human Review Required +## Agent Identity -Mark `review_required: true` when: -- `confidence: low` -- `risk_level: high | critical` -- Security decisions -- Irreversible changes +When working on this project, identify yourself as: `gemini-cli-v1.0` (or your version). --- -*DevTrail v1.0.0 | Last updated: 2025-01-27* -*For complete rules: `.devtrail/00-governance/AGENT-RULES.md`* -*[Enigmora](https://enigmora.com) — Because every change tells a story.* +*DevTrail v2.0.0 | [Strange Days Tech](https://strangedays.tech) — Because every change tells a story.* diff --git a/LICENSE b/LICENSE index 9504d74..d75379e 100644 --- a/LICENSE +++ b/LICENSE @@ -2,7 +2,7 @@ SPDX-License-Identifier: MIT MIT License -Copyright (c) 2025 Enigmora and DevTrail Contributors +Copyright (c) 2025 Strange Days Tech, S.A.S. and DevTrail Contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index c91c220..080dab1 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,8 @@ [![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)](https://enigmora.github.io/devtrail/) -[![Enigmora](https://img.shields.io/badge/by-Enigmora-purple.svg)](https://enigmora.com) +[![Handbook](https://img.shields.io/badge/docs-Handbook-orange.svg)](.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) • [Features](#features) • @@ -94,46 +94,40 @@ Automated validation tools: ## Getting Started -### Quick Start (New Project) +### Option 1: CLI (Recommended) -**Option 1: Use as Template** (Recommended) +```bash +# Install the CLI +cargo install devtrail-cli -Click the **"Use this template"** button above to create a new repository with DevTrail pre-configured. +# Initialize in your project +cd your-project +devtrail init . +``` -**Option 2: Clone and Copy** +The CLI downloads the latest DevTrail release, sets up the framework, and configures your AI agent directive files automatically. ```bash -# Clone DevTrail -git clone https://github.com/enigmora/devtrail-framework.git - -# Copy to your project -cp -r devtrail-framework/.devtrail your-project/ -cp devtrail-framework/CLAUDE.md your-project/ -cp devtrail-framework/GEMINI.md your-project/ -cp devtrail-framework/.cursorrules your-project/ -cp -r devtrail-framework/.github your-project/ -cp -r devtrail-framework/scripts your-project/ +# Update to latest version +devtrail update + +# Remove DevTrail +devtrail remove ``` -### Quick Start (Existing Project) +### Option 2: Manual Setup ```bash -# Download DevTrail -git clone https://github.com/enigmora/devtrail-framework.git devtrail-temp +# Download the latest release ZIP from GitHub +# https://github.com/StrangeDaysTech/devtrail/releases/latest -# Copy without overwriting (Linux/Mac) -cp -rn devtrail-temp/.devtrail ./ -cp -n devtrail-temp/CLAUDE.md ./ -cp -n devtrail-temp/GEMINI.md ./ -cp -n devtrail-temp/.cursorrules ./ -cp -rn devtrail-temp/.github ./ -cp -rn devtrail-temp/scripts ./ - -# Clean up -rm -rf devtrail-temp +# Extract and copy to your project +cp -r .devtrail your-project/ +cp DEVTRAIL.md your-project/ +cp -r scripts your-project/ # Commit -git add .devtrail/ CLAUDE.md GEMINI.md .cursorrules .github/ scripts/ +git add .devtrail/ DEVTRAIL.md scripts/ git commit -m "chore: adopt DevTrail" ``` @@ -173,10 +167,9 @@ Example: `ADR-2025-01-27-001-use-postgresql-for-persistence.md` | Document | Description | |----------|-------------| -| [**📘 Handbook**](https://enigmora.github.io/devtrail/) | Complete online documentation | +| [**📘 Quick Reference**](.devtrail/QUICK-REFERENCE.md) | One-page documentation overview | +| [DEVTRAIL.md](DEVTRAIL.md) | Unified governance rules (source of truth) | | [ADOPTION-GUIDE.md](ADOPTION-GUIDE.md) | Adoption guide for new/existing projects | -| [docs/cookbook.md](docs/cookbook.md) | Practical examples and scenarios | -| [.devtrail/QUICK-REFERENCE.md](.devtrail/QUICK-REFERENCE.md) | One-page reference card | --- @@ -429,15 +422,13 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file --- -## About Enigmora +## About Strange Days Tech, S.A.S.
-Enigmora Logo - -**[Enigmora](https://enigmora.com)** builds tools for responsible AI-assisted software development. +**[Strange Days Tech](https://strangedays.tech)** builds tools for responsible AI-assisted software development. DevTrail is one of our open-source projects. -[Website](https://enigmora.com) • [GitHub](https://github.com/enigmora) +[Website](https://strangedays.tech) • [GitHub](https://github.com/StrangeDaysTech)
@@ -447,6 +438,6 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file **DevTrail** — Because every change tells a story. -[⬆ Back to top](#enigmora-devtrail-framework) +[⬆ Back to top](#devtrail) diff --git a/TRANSLATION-GUIDE.md b/TRANSLATION-GUIDE.md index 4683c41..f2d4217 100644 --- a/TRANSLATION-GUIDE.md +++ b/TRANSLATION-GUIDE.md @@ -217,13 +217,13 @@ Basado en [REQ-2025-01-15-003]. # Keep reference format ### 9. URLs and Links ```markdown -[Enigmora](https://enigmora.com) # Keep URLs exactly +[Strange Days Tech](https://strangedays.tech) # Keep URLs exactly ``` ### 10. Brand Names ``` -Enigmora +Strange Days Tech DevTrail Claude Code Cursor @@ -353,4 +353,4 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for general contribution guidelines. *DevTrail — Because every change tells a story.* -[Enigmora](https://enigmora.com) +[Strange Days Tech](https://strangedays.tech) diff --git a/assets/logo-devtrail-OLD.svg b/assets/logo-devtrail-OLD.svg deleted file mode 100644 index fd10646..0000000 --- a/assets/logo-devtrail-OLD.svg +++ /dev/null @@ -1,10 +0,0 @@ - - DevTrail - - - - - - - - \ No newline at end of file diff --git a/assets/logo-enigmora.svg b/assets/logo-enigmora.svg deleted file mode 100644 index a78fc3d..0000000 --- a/assets/logo-enigmora.svg +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/cli/Cargo.lock b/cli/Cargo.lock new file mode 100644 index 0000000..bfbaccd --- /dev/null +++ b/cli/Cargo.lock @@ -0,0 +1,2769 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.61.2", +] + +[[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" +dependencies = [ + "derive_arbitrary", +] + +[[package]] +name = "assert_cmd" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c5bcfa8749ac45dd12cb11055aeeb6b27a3895560d60d71e3c23bf979e60514" +dependencies = [ + "anstyle", + "bstr", + "libc", + "predicates", + "predicates-core", + "predicates-tree", + "wait-timeout", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bitflags" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bstr" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" +dependencies = [ + "memchr", + "regex-automata", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" + +[[package]] +name = "bzip2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49ecfb22d906f800d4fe833b6282cf4dc1c298f5057ca0b5445e5c209735ca47" +dependencies = [ + "bzip2-sys", +] + +[[package]] +name = "bzip2-sys" +version = "0.1.13+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225bff33b2141874fe80d71e07d6eec4f85c5c216453dd96388240f96e1acc14" +dependencies = [ + "cc", + "pkg-config", +] + +[[package]] +name = "cc" +version = "1.2.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" +dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + +[[package]] +name = "clap" +version = "4.5.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2797f34da339ce31042b27d23607e051786132987f595b02ba4f6a6dffb7030a" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24a241312cea5059b13574bb9b3861cabf758b879c15190b37b6d6fd63ab6876" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + +[[package]] +name = "colored" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" +dependencies = [ + "lazy_static", + "windows-sys 0.59.0", +] + +[[package]] +name = "console" +version = "0.15.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "unicode-width", + "windows-sys 0.59.0", +] + +[[package]] +name = "constant_time_eq" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crc" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eb8a2a1cd12ab0d987a5d5e825195d372001a4094a0376319d5a0ad71c1ba0d" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "deflate64" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "807800ff3288b621186fe0a8f3392c4652068257302709c24efd918c3dffcdc2" + +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "derive_arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "devtrail-cli" +version = "2.0.0" +dependencies = [ + "anyhow", + "assert_cmd", + "clap", + "colored", + "dialoguer", + "indicatif", + "predicates", + "reqwest", + "serde", + "serde_json", + "serde_yaml", + "sha2", + "tempfile", + "zip", +] + +[[package]] +name = "dialoguer" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "658bce805d770f407bc62102fca7c2c64ceef2fbcb2b8bd19d2765ce093980de" +dependencies = [ + "console", + "shell-words", + "tempfile", + "thiserror 1.0.69", + "zeroize", +] + +[[package]] +name = "difflib" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "float-cmp" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b09cf3155332e944990140d967ff5eceb70df778b34f77d8075db46e4704e6d8" +dependencies = [ + "num-traits", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures-channel" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-io" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" + +[[package]] +name = "futures-sink" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi", + "wasip2", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", + "wasip3", +] + +[[package]] +name = "h2" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "http" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" +dependencies = [ + "bytes", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "hyper" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "h2", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "pin-utils", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", + "webpki-roots", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" +dependencies = [ + "base64", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2", + "system-configuration", + "tokio", + "tower-service", + "tracing", + "windows-registry", +] + +[[package]] +name = "icu_collections" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" + +[[package]] +name = "icu_properties" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" + +[[package]] +name = "icu_provider" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "indexmap" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +dependencies = [ + "equivalent", + "hashbrown 0.16.1", + "serde", + "serde_core", +] + +[[package]] +name = "indicatif" +version = "0.17.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "183b3088984b400f4cfac3620d5e076c84da5364016b4f49473de574b2586235" +dependencies = [ + "console", + "number_prefix", + "portable-atomic", + "unicode-width", + "web-time", +] + +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "generic-array", +] + +[[package]] +name = "ipnet" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "iri-string" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c91338f0783edbd6195decb37bae672fd3b165faffb89bf7b9e6942f8b1a731a" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + +[[package]] +name = "itoa" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" + +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + +[[package]] +name = "libc" +version = "0.2.182" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "litemap" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + +[[package]] +name = "lzma-rs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "297e814c836ae64db86b36cf2a557ba54368d03f6afcd7d947c266692f71115e" +dependencies = [ + "byteorder", + "crc", +] + +[[package]] +name = "lzma-sys" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fda04ab3764e6cde78b9974eec4f779acaba7c4e84b36eca3cf77c581b85d27" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "mio" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.61.2", +] + +[[package]] +name = "native-tls" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "normalize-line-endings" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" + +[[package]] +name = "num-conv" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + +[[package]] +name = "openssl" +version = "0.10.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" + +[[package]] +name = "openssl-sys" +version = "0.9.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "pbkdf2" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" +dependencies = [ + "digest", + "hmac", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "portable-atomic" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" + +[[package]] +name = "potential_utf" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +dependencies = [ + "zerovec", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "predicates" +version = "3.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ada8f2932f28a27ee7b70dd6c1c39ea0675c55a36879ab92f3a715eaa1e63cfe" +dependencies = [ + "anstyle", + "difflib", + "float-cmp", + "normalize-line-endings", + "predicates-core", + "regex", +] + +[[package]] +name = "predicates-core" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cad38746f3166b4031b1a0d39ad9f954dd291e7854fcc0eed52ee41a0b50d144" + +[[package]] +name = "predicates-tree" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0de1b847b39c8131db0467e9df1ff60e6d0562ab8e9a16e568ad0fdb372e2f2" +dependencies = [ + "predicates-core", + "termtree", +] + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quinn" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "socket2", + "thiserror 2.0.18", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +dependencies = [ + "bytes", + "getrandom 0.3.4", + "lru-slab", + "rand", + "ring", + "rustc-hash", + "rustls", + "rustls-pki-types", + "slab", + "thiserror 2.0.18", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.60.2", +] + +[[package]] +name = "quote" +version = "1.0.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "regex" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" + +[[package]] +name = "reqwest" +version = "0.12.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-tls", + "hyper-util", + "js-sys", + "log", + "mime", + "native-tls", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-native-tls", + "tokio-rustls", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.17", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls" +version = "0.23.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4" +dependencies = [ + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pki-types" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" +dependencies = [ + "web-time", + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" + +[[package]] +name = "schannel" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "security-framework" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" +dependencies = [ + "bitflags", + "core-foundation 0.10.1", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shell-words" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc6fe69c597f9c37bfeeeeeb33da3530379845f10be461a66d16d03eca2ded77" + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "simd-adler32" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "socket2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "system-configuration" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" +dependencies = [ + "bitflags", + "core-foundation 0.9.4", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tempfile" +version = "3.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82a72c767771b47409d2345987fda8628641887d5466101319899796367354a0" +dependencies = [ + "fastrand", + "getrandom 0.4.1", + "once_cell", + "rustix", + "windows-sys 0.61.2", +] + +[[package]] +name = "termtree" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl 2.0.18", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "time" +version = "0.3.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +dependencies = [ + "deranged", + "num-conv", + "powerfmt", + "serde_core", + "time-core", +] + +[[package]] +name = "time-core" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" + +[[package]] +name = "tinystr" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.49.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" +dependencies = [ + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-http" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" +dependencies = [ + "bitflags", + "bytes", + "futures-util", + "http", + "http-body", + "iri-string", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "typenum" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wait-timeout" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" +dependencies = [ + "libc", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.2+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9c5522b3a28661442748e09d40924dfb9ca614b21c00d3fd135720e48b67db8" +dependencies = [ + "cfg-if", + "futures-util", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags", + "hashbrown 0.15.5", + "indexmap", + "semver", +] + +[[package]] +name = "web-sys" +version = "0.3.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "854ba17bb104abfb26ba36da9729addc7ce7f06f5c0f90f3c391f8461cca21f9" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-registry" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" +dependencies = [ + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "prettyplease", + "syn", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + +[[package]] +name = "writeable" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" + +[[package]] +name = "xz2" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388c44dc09d76f1536602ead6d325eb532f5c122f17782bd57fb47baeeb767e2" +dependencies = [ + "lzma-sys", +] + +[[package]] +name = "yoke" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.8.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a789c6e490b576db9f7e6b6d661bcc9799f7c0ac8352f56ea20193b2681532e5" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f65c489a7071a749c849713807783f70672b28094011623e200cb86dcb835953" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zerotrie" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zip" +version = "2.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabe6324e908f85a1c52063ce7aa26b68dcb7eb6dbc83a2d148403c9bc3eba50" +dependencies = [ + "aes", + "arbitrary", + "bzip2", + "constant_time_eq", + "crc32fast", + "crossbeam-utils", + "deflate64", + "displaydoc", + "flate2", + "getrandom 0.3.4", + "hmac", + "indexmap", + "lzma-rs", + "memchr", + "pbkdf2", + "sha1", + "thiserror 2.0.18", + "time", + "xz2", + "zeroize", + "zopfli", + "zstd", +] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" + +[[package]] +name = "zopfli" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f05cd8797d63865425ff89b5c4a48804f35ba0ce8d125800027ad6017d2b5249" +dependencies = [ + "bumpalo", + "crc32fast", + "log", + "simd-adler32", +] + +[[package]] +name = "zstd" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.16+zstd.1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/cli/Cargo.toml b/cli/Cargo.toml new file mode 100644 index 0000000..b50ebc4 --- /dev/null +++ b/cli/Cargo.toml @@ -0,0 +1,40 @@ +[package] +name = "devtrail-cli" +version = "2.0.0" +edition = "2021" +description = "CLI tool for DevTrail - Documentation Governance for AI-Assisted Development" +license = "MIT" +repository = "https://github.com/StrangeDaysTech/devtrail" +homepage = "https://strangedays.tech" +readme = "../README.md" +keywords = ["devtrail", "documentation", "governance", "ai", "cli"] +categories = ["command-line-utilities", "development-tools"] +authors = ["Strange Days Tech, S.A.S."] + +[[bin]] +name = "devtrail" +path = "src/main.rs" + +[dependencies] +clap = { version = "4", features = ["derive"] } +reqwest = { version = "0.12", features = ["blocking", "rustls-tls", "json"] } +serde = { version = "1", features = ["derive"] } +serde_json = "1" +serde_yaml = "0.9" +zip = "2" +tempfile = "3" +colored = "2" +indicatif = "0.17" +dialoguer = "0.11" +sha2 = "0.10" +anyhow = "1" + +[dev-dependencies] +assert_cmd = "2" +predicates = "3" +tempfile = "3" + +[profile.release] +opt-level = "z" +lto = true +strip = true diff --git a/cli/src/commands/init.rs b/cli/src/commands/init.rs new file mode 100644 index 0000000..fdc3e54 --- /dev/null +++ b/cli/src/commands/init.rs @@ -0,0 +1,277 @@ +use anyhow::{bail, Context, Result}; +use colored::Colorize; +use std::path::{Path, PathBuf}; + +use crate::config::Checksums; +use crate::download; +use crate::inject; +use crate::manifest::DistManifest; +use crate::utils; + +pub fn run(path: &str) -> Result<()> { + let target = PathBuf::from(path) + .canonicalize() + .unwrap_or_else(|_| PathBuf::from(path)); + + println!( + "{} DevTrail in {}", + "Initializing".cyan().bold(), + target.display() + ); + + // Check if already initialized + if target.join(".devtrail").exists() { + bail!( + ".devtrail/ already exists. Use {} to update.", + "devtrail update".yellow() + ); + } + + // Download latest release + utils::info("Fetching latest release..."); + let release = download::get_latest_release()?; + println!( + " {} {}", + "Found version:".dimmed(), + release.tag_name.green() + ); + + // Download ZIP to temp file + let temp_dir = tempfile::tempdir().context("Failed to create temp directory")?; + let zip_path = temp_dir.path().join("devtrail.zip"); + + utils::info("Downloading..."); + download::download_zip(&release.zip_url, &zip_path)?; + + // Extract files according to manifest + utils::info("Extracting files..."); + 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)?; + + // Save checksums + save_initial_checksums(&target, &release.tag_name)?; + + // Print summary + println!(); + utils::success("DevTrail initialized successfully!"); + println!(); + println!(" {}", "Next steps:".bold()); + println!(" 1. Review .devtrail/config.yml for language settings"); + println!(" 2. Check DEVTRAIL.md for governance rules"); + println!( + " 3. Run {} to validate your setup", + "bash scripts/pre-commit-docs.sh".cyan() + ); + println!( + " 4. Commit: {}", + "git add .devtrail/ DEVTRAIL.md && git commit -m \"chore: adopt DevTrail\"".dimmed() + ); + + Ok(()) +} + +/// Extract distributable files from the release ZIP +fn extract_distribution(zip_path: &Path, target: &Path) -> Result<()> { + 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")?; + + // Find the manifest inside the ZIP (it may be in a subdirectory like devtrail-v2.0.0/) + let mut manifest_content = None; + let mut prefix = String::new(); + + // First pass: find the manifest entry index + let mut manifest_index = None; + for i in 0..archive.len() { + let entry = archive.by_index(i)?; + let name = entry.name().to_string(); + if name.ends_with("dist-manifest.yml") { + if let Some(pos) = name.find("dist-manifest.yml") { + prefix = name[..pos].to_string(); + } + manifest_index = Some(i); + break; + } + } + + // Second pass: read manifest content + if let Some(idx) = manifest_index { + let mut content = String::new(); + let mut entry = archive.by_index(idx)?; + std::io::Read::read_to_string(&mut entry, &mut content)?; + manifest_content = Some(content); + } + + let manifest_str = manifest_content.context("dist-manifest.yml not found in release ZIP")?; + let manifest = DistManifest::from_str(&manifest_str)?; + + // Extract each file listed in manifest + for pattern in &manifest.files { + extract_matching_files(&mut archive, &prefix, pattern, target)?; + } + + Ok(()) +} + +/// Extract files from ZIP matching a manifest pattern +fn extract_matching_files( + archive: &mut zip::ZipArchive, + prefix: &str, + pattern: &str, + target: &Path, +) -> Result<()> { + let pattern_with_prefix = format!("{}{}", prefix, pattern); + + for i in 0..archive.len() { + let mut entry = archive.by_index(i)?; + let name = entry.name().to_string(); + + // Check if this entry matches the pattern + let matches = if pattern.ends_with('/') { + // Directory pattern: match anything inside it + name.starts_with(&pattern_with_prefix) + } else { + // Exact file match + name == pattern_with_prefix + }; + + if matches && !entry.is_dir() { + // Compute relative path (strip the prefix) + let relative = &name[prefix.len()..]; + let dest = target.join(relative); + + // Create parent directories + if let Some(parent) = dest.parent() { + std::fs::create_dir_all(parent)?; + } + + // Write file + let mut outfile = std::fs::File::create(&dest)?; + std::io::copy(&mut entry, &mut outfile)?; + } + } + + Ok(()) +} + +/// Create the empty directory structure with .gitkeep files +fn create_empty_dirs(target: &Path) -> Result<()> { + let dirs = [ + ".devtrail/01-requirements", + ".devtrail/02-design/decisions", + ".devtrail/03-implementation", + ".devtrail/04-testing", + ".devtrail/05-operations/incidents", + ".devtrail/05-operations/runbooks", + ".devtrail/06-evolution/technical-debt", + ".devtrail/07-ai-audit/agent-logs", + ".devtrail/07-ai-audit/decisions", + ".devtrail/07-ai-audit/ethical-reviews", + ".devtrail/00-governance/exceptions", + ]; + + for dir in &dirs { + let dir_path = target.join(dir); + utils::ensure_dir(&dir_path)?; + let gitkeep = dir_path.join(".gitkeep"); + if !gitkeep.exists() { + std::fs::write(&gitkeep, "")?; + } + } + + 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"), + ]; + + 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)); + } + } + + // 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"); + } + + Ok(()) +} + +/// Save initial checksums for all framework files +fn save_initial_checksums(target: &Path, version: &str) -> Result<()> { + let mut checksums = Checksums { + version: version.to_string(), + files: std::collections::HashMap::new(), + }; + + // Walk .devtrail/ and hash all files + if let Ok(entries) = walkdir(target.join(".devtrail")) { + for entry in entries { + if let Some(hash) = utils::file_hash(&entry) { + let relative = entry + .strip_prefix(target) + .unwrap_or(&entry) + .display() + .to_string(); + checksums.files.insert(relative, hash); + } + } + } + + // Also hash DEVTRAIL.md + let devtrail_path = target.join("DEVTRAIL.md"); + if let Some(hash) = utils::file_hash(&devtrail_path) { + checksums.files.insert("DEVTRAIL.md".to_string(), hash); + } + + checksums.save(target)?; + Ok(()) +} + +/// Simple recursive directory walker +fn walkdir(dir: PathBuf) -> Result> { + let mut files = Vec::new(); + if !dir.is_dir() { + return Ok(files); + } + + for entry in std::fs::read_dir(&dir)? { + let entry = entry?; + let path = entry.path(); + if path.is_dir() { + files.extend(walkdir(path)?); + } else { + files.push(path); + } + } + + Ok(files) +} diff --git a/cli/src/commands/mod.rs b/cli/src/commands/mod.rs new file mode 100644 index 0000000..a4e9a6d --- /dev/null +++ b/cli/src/commands/mod.rs @@ -0,0 +1,3 @@ +pub mod init; +pub mod remove; +pub mod update; diff --git a/cli/src/commands/remove.rs b/cli/src/commands/remove.rs new file mode 100644 index 0000000..3f5d41d --- /dev/null +++ b/cli/src/commands/remove.rs @@ -0,0 +1,193 @@ +use anyhow::{bail, Context, Result}; +use colored::Colorize; +use dialoguer::{Confirm, theme::ColorfulTheme}; +use std::path::Path; + +use crate::inject; +use crate::utils; + +pub fn run(full: bool) -> Result<()> { + let target = std::env::current_dir().context("Failed to get current directory")?; + + if !target.join(".devtrail").exists() { + bail!("DevTrail is not installed in this directory."); + } + + if full { + println!( + "{} This will remove ALL DevTrail files including your documents!", + "WARNING:".red().bold() + ); + let confirmed = Confirm::with_theme(&ColorfulTheme::default()) + .with_prompt("Are you sure you want to remove everything?") + .default(false) + .interact()?; + + if !confirmed { + println!("Aborted."); + return Ok(()); + } + + let double_confirmed = Confirm::with_theme(&ColorfulTheme::default()) + .with_prompt("This will delete all your AILOG, AIDEC, ADR, and other documents. Really proceed?") + .default(false) + .interact()?; + + if !double_confirmed { + println!("Aborted."); + return Ok(()); + } + } + + println!("{} DevTrail...", "Removing".red().bold()); + + // Remove injections from directive files + utils::info("Cleaning AI agent directives..."); + clean_directives(&target)?; + + // Remove framework files + utils::info("Removing framework files..."); + + if full { + // Remove everything + remove_dir_if_exists(&target.join(".devtrail"))?; + } else { + // Selective removal: keep user documents, remove framework + remove_framework_files(&target)?; + } + + // Remove distributed files + remove_file_if_exists(&target.join("DEVTRAIL.md"))?; + + // Remove agent skills and workflows + remove_dir_if_exists(&target.join(".claude/skills"))?; + remove_dir_if_exists(&target.join(".gemini/skills"))?; + remove_dir_if_exists(&target.join(".agent/workflows"))?; + + // Clean up empty parent dirs + remove_empty_dir(&target.join(".claude"))?; + 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"))?; + remove_empty_dir(&target.join(".cursor/rules"))?; + remove_empty_dir(&target.join(".cursor"))?; + + // Remove scripts + let scripts = [ + "scripts/devtrail-new.sh", + "scripts/devtrail-status.sh", + "scripts/pre-commit-docs.sh", + "scripts/validate-docs.ps1", + ]; + for script in &scripts { + remove_file_if_exists(&target.join(script))?; + } + remove_empty_dir(&target.join("scripts"))?; + + println!(); + utils::success("DevTrail removed successfully."); + + if !full { + println!(); + println!( + " {} User-generated documents in .devtrail/ were preserved.", + "Note:".bold() + ); + println!( + " Use {} to remove everything.", + "devtrail remove --full".yellow() + ); + } + + Ok(()) +} + +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"), + ]; + + 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)); + } + } + + Ok(()) +} + +/// Remove framework files but keep user-generated documents +fn remove_framework_files(target: &Path) -> Result<()> { + let devtrail = target.join(".devtrail"); + + // Framework directories to remove entirely + let framework_dirs = [ + "00-governance", + "03-implementation", + "templates", + ]; + + for dir in &framework_dirs { + remove_dir_if_exists(&devtrail.join(dir))?; + } + + // Remove framework files but keep user documents in these dirs + let mixed_dirs = [ + "01-requirements", + "02-design/decisions", + "04-testing", + "05-operations/incidents", + "05-operations/runbooks", + "06-evolution/technical-debt", + "07-ai-audit/agent-logs", + "07-ai-audit/decisions", + "07-ai-audit/ethical-reviews", + ]; + + for dir in &mixed_dirs { + let dir_path = devtrail.join(dir); + if dir_path.is_dir() { + // Only remove .gitkeep, keep user documents + remove_file_if_exists(&dir_path.join(".gitkeep"))?; + } + } + + // Remove framework root files + 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"))?; + + Ok(()) +} + +fn remove_file_if_exists(path: &Path) -> Result<()> { + if path.exists() { + std::fs::remove_file(path).with_context(|| format!("Failed to remove {}", path.display()))?; + } + Ok(()) +} + +fn remove_dir_if_exists(path: &Path) -> Result<()> { + if path.exists() { + std::fs::remove_dir_all(path) + .with_context(|| format!("Failed to remove {}", path.display()))?; + } + Ok(()) +} + +fn remove_empty_dir(path: &Path) -> Result<()> { + if path.is_dir() { + if let Ok(mut entries) = std::fs::read_dir(path) { + if entries.next().is_none() { + std::fs::remove_dir(path).ok(); + } + } + } + Ok(()) +} diff --git a/cli/src/commands/update.rs b/cli/src/commands/update.rs new file mode 100644 index 0000000..1e60f06 --- /dev/null +++ b/cli/src/commands/update.rs @@ -0,0 +1,297 @@ +use anyhow::{bail, Context, Result}; +use colored::Colorize; +use dialoguer::{Select, theme::ColorfulTheme}; +use std::path::{Path, PathBuf}; + +use crate::config::Checksums; +use crate::download; +use crate::inject; +use crate::utils; + +pub fn run() -> Result<()> { + let target = std::env::current_dir().context("Failed to get current directory")?; + + // Verify DevTrail is installed + if !target.join(".devtrail").exists() { + bail!( + ".devtrail/ not found. Use {} to initialize first.", + "devtrail init".yellow() + ); + } + + println!("{} DevTrail...", "Updating".cyan().bold()); + + // Load current checksums + let current_checksums = Checksums::load(&target)?; + if !current_checksums.version.is_empty() { + println!( + " {} {}", + "Current version:".dimmed(), + current_checksums.version + ); + } + + // Fetch latest release + utils::info("Checking for updates..."); + let release = download::get_latest_release()?; + println!( + " {} {}", + "Latest version:".dimmed(), + release.tag_name.green() + ); + + // Download ZIP + let temp_dir = tempfile::tempdir().context("Failed to create temp directory")?; + let zip_path = temp_dir.path().join("devtrail.zip"); + + utils::info("Downloading..."); + download::download_zip(&release.zip_url, &zip_path)?; + + // Extract to temp directory for comparison + let extract_dir = temp_dir.path().join("extracted"); + std::fs::create_dir_all(&extract_dir)?; + extract_all(&zip_path, &extract_dir)?; + + // Update framework files + utils::info("Updating framework files..."); + let stats = update_files(&target, &extract_dir, ¤t_checksums)?; + + // Update directive injections + utils::info("Updating AI agent directives..."); + inject_directives(&target)?; + + // Save new checksums + save_checksums(&target, &release.tag_name)?; + + // Print summary + println!(); + utils::success("DevTrail updated successfully!"); + println!(" Files updated: {}", stats.updated); + println!(" Files skipped (user-modified): {}", stats.skipped); + println!(" Files added: {}", stats.added); + + Ok(()) +} + +struct UpdateStats { + updated: usize, + skipped: usize, + added: usize, +} + +/// Update files, respecting user modifications +fn update_files( + target: &Path, + extract_dir: &Path, + checksums: &Checksums, +) -> Result { + let mut stats = UpdateStats { + updated: 0, + skipped: 0, + 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())?; + + for source_path in entries { + let relative = source_path + .strip_prefix(&source_root) + .unwrap_or(&source_path) + .display() + .to_string(); + + // Skip user-generated documents + if utils::is_user_document(&source_path) { + continue; + } + + // Skip checksums file + if relative == ".devtrail/.checksums.json" { + continue; + } + + let target_path = target.join(&relative); + + if !target_path.exists() { + // New file — just copy it + if let Some(parent) = target_path.parent() { + utils::ensure_dir(parent)?; + } + std::fs::copy(&source_path, &target_path)?; + stats.added += 1; + continue; + } + + // File exists — check if user modified it + let current_hash = utils::file_hash(&target_path).unwrap_or_default(); + let original_hash = checksums + .files + .get(&relative) + .cloned() + .unwrap_or_default(); + + if current_hash == original_hash || original_hash.is_empty() { + // User hasn't modified it (or no previous hash) — safe to overwrite + std::fs::copy(&source_path, &target_path)?; + stats.updated += 1; + } else { + // User modified it — prompt for action + let new_hash = utils::file_hash(&source_path).unwrap_or_default(); + if current_hash == new_hash { + // Same content, no action needed + continue; + } + + utils::warn(&format!("User-modified file: {}", relative)); + let selection = Select::with_theme(&ColorfulTheme::default()) + .with_prompt("What would you like to do?") + .items(&["Keep my version", "Use new version", "Backup mine + use new"]) + .default(0) + .interact()?; + + match selection { + 0 => { + stats.skipped += 1; + } + 1 => { + std::fs::copy(&source_path, &target_path)?; + stats.updated += 1; + } + 2 => { + let backup = target_path.with_extension("md.bak"); + std::fs::copy(&target_path, &backup)?; + std::fs::copy(&source_path, &target_path)?; + stats.updated += 1; + utils::info(&format!("Backup saved: {}", backup.display())); + } + _ => { + stats.skipped += 1; + } + } + } + } + + 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"), + ]; + + for t in &reference_targets { + if t.exists() { + inject::inject_reference(t)?; + } + } + + 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 cursor_rules_dir = target.join(".cursor/rules"); + if cursor_rules_dir.exists() { + inject::inject_cursor_rules_dir(&cursor_rules_dir, &content)?; + } + } + + Ok(()) +} + +fn save_checksums(target: &Path, version: &str) -> Result<()> { + let mut checksums = Checksums { + version: version.to_string(), + files: std::collections::HashMap::new(), + }; + + if let Ok(entries) = walkdir(target.join(".devtrail")) { + for entry in entries { + if let Some(hash) = utils::file_hash(&entry) { + let relative = entry + .strip_prefix(target) + .unwrap_or(&entry) + .display() + .to_string(); + checksums.files.insert(relative, hash); + } + } + } + + let devtrail_path = target.join("DEVTRAIL.md"); + if let Some(hash) = utils::file_hash(&devtrail_path) { + checksums.files.insert("DEVTRAIL.md".to_string(), hash); + } + + checksums.save(target)?; + Ok(()) +} + +fn extract_all(zip_path: &Path, dest: &Path) -> Result<()> { + let file = std::fs::File::open(zip_path)?; + let mut archive = zip::ZipArchive::new(file)?; + + for i in 0..archive.len() { + let mut entry = archive.by_index(i)?; + let path = dest.join(entry.name()); + + if entry.is_dir() { + std::fs::create_dir_all(&path)?; + } else { + if let Some(parent) = path.parent() { + std::fs::create_dir_all(parent)?; + } + let mut outfile = std::fs::File::create(&path)?; + std::io::copy(&mut entry, &mut outfile)?; + } + } + + Ok(()) +} + +fn find_source_root(extract_dir: &Path) -> Result { + // Check if dist-manifest.yml is directly in extract_dir + if extract_dir.join("dist-manifest.yml").exists() { + return Ok(extract_dir.to_path_buf()); + } + + // Check one level deep (GitHub ZIP archives nest in a directory) + for entry in std::fs::read_dir(extract_dir)? { + let entry = entry?; + let path = entry.path(); + if path.is_dir() && path.join("dist-manifest.yml").exists() { + return Ok(path); + } + } + + bail!("Could not find dist-manifest.yml in extracted archive"); +} + +fn walkdir(dir: PathBuf) -> Result> { + let mut files = Vec::new(); + if !dir.is_dir() { + return Ok(files); + } + + for entry in std::fs::read_dir(&dir)? { + let entry = entry?; + let path = entry.path(); + if path.is_dir() { + files.extend(walkdir(path)?); + } else { + files.push(path); + } + } + + Ok(files) +} diff --git a/cli/src/config.rs b/cli/src/config.rs new file mode 100644 index 0000000..95d3b6c --- /dev/null +++ b/cli/src/config.rs @@ -0,0 +1,66 @@ +use anyhow::{Context, Result}; +use serde::{Deserialize, Serialize}; +use std::path::Path; + +/// DevTrail project configuration from .devtrail/config.yml +#[derive(Debug, Deserialize, Serialize)] +pub struct DevTrailConfig { + /// Language setting: "en" or "es" + #[serde(default = "default_language")] + pub language: String, +} + +fn default_language() -> String { + "en".to_string() +} + +impl Default for DevTrailConfig { + fn default() -> Self { + Self { + language: default_language(), + } + } +} + +impl DevTrailConfig { + /// Read config from .devtrail/config.yml at the given project root + pub fn load(project_root: &Path) -> Result { + let config_path = project_root.join(".devtrail/config.yml"); + if !config_path.exists() { + return Ok(Self::default()); + } + let contents = + std::fs::read_to_string(&config_path).context("Failed to read config.yml")?; + let config: Self = serde_yaml::from_str(&contents).context("Failed to parse config.yml")?; + Ok(config) + } +} + +/// Checksums tracking file for detecting user modifications +#[derive(Debug, Default, Deserialize, Serialize)] +pub struct Checksums { + pub version: String, + pub files: std::collections::HashMap, +} + +impl Checksums { + pub fn load(project_root: &Path) -> Result { + let path = project_root.join(".devtrail/.checksums.json"); + if !path.exists() { + return Ok(Self::default()); + } + let contents = + std::fs::read_to_string(&path).context("Failed to read .checksums.json")?; + let checksums: Self = + serde_json::from_str(&contents).context("Failed to parse .checksums.json")?; + Ok(checksums) + } + + pub fn save(&self, project_root: &Path) -> Result<()> { + let path = project_root.join(".devtrail/.checksums.json"); + let contents = + serde_json::to_string_pretty(self).context("Failed to serialize checksums")?; + std::fs::write(&path, contents).context("Failed to write .checksums.json")?; + Ok(()) + } +} diff --git a/cli/src/download.rs b/cli/src/download.rs new file mode 100644 index 0000000..7f0028d --- /dev/null +++ b/cli/src/download.rs @@ -0,0 +1,123 @@ +use anyhow::{bail, Context, Result}; +use indicatif::{ProgressBar, ProgressStyle}; +use std::io::Read; +use std::path::Path; + +const GITHUB_REPO: &str = "StrangeDaysTech/devtrail"; +const GITHUB_API_BASE: &str = "https://api.github.com"; + +/// Information about a GitHub release +#[derive(Debug)] +pub struct ReleaseInfo { + pub tag_name: String, + pub zip_url: String, +} + +/// Get the latest release info from GitHub +pub fn get_latest_release() -> Result { + let url = format!("{}/repos/{}/releases/latest", GITHUB_API_BASE, GITHUB_REPO); + + let client = reqwest::blocking::Client::builder() + .user_agent("devtrail-cli") + .build() + .context("Failed to create HTTP client")?; + + let response = client + .get(&url) + .send() + .context("Failed to fetch latest release from GitHub")?; + + if response.status() == reqwest::StatusCode::FORBIDDEN { + bail!( + "GitHub API rate limit exceeded. Set GITHUB_TOKEN environment variable to increase limits." + ); + } + + if response.status() == reqwest::StatusCode::NOT_FOUND { + bail!("No releases found for {}", GITHUB_REPO); + } + + if !response.status().is_success() { + bail!("GitHub API error: {}", response.status()); + } + + let body: serde_json::Value = response.json().context("Failed to parse release JSON")?; + + let tag_name = body["tag_name"] + .as_str() + .context("Missing tag_name in release")? + .to_string(); + + // Look for the devtrail distribution ZIP in release assets + let zip_url: Option = if let Some(assets) = body["assets"].as_array() { + let mut found = None; + for asset in assets { + if let Some(name) = asset["name"].as_str() { + if name.starts_with("devtrail-") && name.ends_with(".zip") { + if let Some(url) = asset["browser_download_url"].as_str() { + found = Some(url.to_string()); + break; + } + } + } + } + found + } else { + None + }; + + // Fallback to zipball if no distribution asset found + let zip_url = zip_url.unwrap_or_else(|| { + format!( + "https://github.com/{}/archive/refs/tags/{}.zip", + GITHUB_REPO, tag_name + ) + }); + + Ok(ReleaseInfo { tag_name, zip_url }) +} + +/// Download a ZIP file from a URL to a temporary file +pub fn download_zip(url: &str, dest: &Path) -> Result<()> { + let client = reqwest::blocking::Client::builder() + .user_agent("devtrail-cli") + .build() + .context("Failed to create HTTP client")?; + + let mut response = client + .get(url) + .send() + .context("Failed to download release ZIP")?; + + if !response.status().is_success() { + bail!("Download failed with status: {}", response.status()); + } + + let total_size = response.content_length().unwrap_or(0); + + let pb = ProgressBar::new(total_size); + pb.set_style( + ProgressStyle::default_bar() + .template("{spinner:.green} [{bar:40.cyan/blue}] {bytes}/{total_bytes} ({eta})") + .unwrap() + .progress_chars("#>-"), + ); + + let mut file = std::fs::File::create(dest).context("Failed to create temporary file")?; + let mut buffer = [0u8; 8192]; + let mut downloaded: u64 = 0; + + loop { + let bytes_read = response.read(&mut buffer).context("Failed to read response")?; + if bytes_read == 0 { + break; + } + std::io::Write::write_all(&mut file, &buffer[..bytes_read]) + .context("Failed to write to file")?; + downloaded += bytes_read as u64; + pb.set_position(downloaded); + } + + pb.finish_with_message("Download complete"); + Ok(()) +} diff --git a/cli/src/inject.rs b/cli/src/inject.rs new file mode 100644 index 0000000..64cfef7 --- /dev/null +++ b/cli/src/inject.rs @@ -0,0 +1,164 @@ +use anyhow::{Context, Result}; +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 + ); + + 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); + 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); + 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); + 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")?; + } + + 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() { + return Ok(false); + } + + let content = std::fs::read_to_string(target).context("Failed to read file")?; + + if !content.contains(MARKER_BEGIN) { + return Ok(false); + } + + let new_content = remove_between_markers(&content); + let trimmed = new_content.trim(); + + if trimmed.is_empty() { + // File is empty after removal — delete it + std::fs::remove_file(target).context("Failed to remove empty directive file")?; + } else { + std::fs::write(target, format!("{}\n", trimmed)) + .context("Failed to write updated file")?; + } + + Ok(true) +} + +/// Replace content between markers (inclusive) +fn replace_between_markers(content: &str, replacement: &str) -> String { + if let (Some(start), Some(end)) = (content.find(MARKER_BEGIN), content.find(MARKER_END)) { + let end = end + MARKER_END.len(); + format!("{}{}{}", &content[..start], replacement, &content[end..]) + } else { + content.to_string() + } +} + +/// Remove content between markers (inclusive), including surrounding blank lines +fn remove_between_markers(content: &str) -> String { + if let (Some(start), Some(end)) = (content.find(MARKER_BEGIN), content.find(MARKER_END)) { + let end = end + MARKER_END.len(); + let before = content[..start].trim_end(); + let after = content[end..].trim_start(); + if after.is_empty() { + before.to_string() + } else { + format!("{}\n\n{}", before, after) + } + } else { + content.to_string() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_replace_between_markers() { + let content = "before\n\nold\n\nafter"; + let result = replace_between_markers( + content, + "\nnew\n", + ); + assert!(result.contains("new")); + assert!(!result.contains("old")); + assert!(result.contains("before")); + assert!(result.contains("after")); + } + + #[test] + fn test_remove_between_markers() { + let content = "header\n\n\nstuff\n\n\nfooter"; + let result = remove_between_markers(content); + assert!(result.contains("header")); + assert!(result.contains("footer")); + assert!(!result.contains("stuff")); + } +} diff --git a/cli/src/main.rs b/cli/src/main.rs new file mode 100644 index 0000000..775f8fc --- /dev/null +++ b/cli/src/main.rs @@ -0,0 +1,51 @@ +use clap::{Parser, Subcommand}; +use colored::Colorize; + +mod commands; +mod config; +mod download; +mod inject; +mod manifest; +mod utils; + +/// DevTrail CLI - Documentation Governance for AI-Assisted Development +#[derive(Parser)] +#[command(name = "devtrail", version, about, long_about = None)] +#[command(propagate_version = true)] +struct Cli { + #[command(subcommand)] + command: Commands, +} + +#[derive(Subcommand)] +enum Commands { + /// Initialize DevTrail in a project directory + Init { + /// Target directory (default: current directory) + #[arg(default_value = ".")] + path: String, + }, + /// Update DevTrail to the latest version + Update, + /// Remove DevTrail from the project + Remove { + /// Remove everything including user-generated documents (requires confirmation) + #[arg(long)] + full: bool, + }, +} + +fn main() { + let cli = Cli::parse(); + + let result = match cli.command { + Commands::Init { path } => commands::init::run(&path), + Commands::Update => commands::update::run(), + Commands::Remove { full } => commands::remove::run(full), + }; + + if let Err(e) = result { + eprintln!("{} {}", "error:".red().bold(), e); + std::process::exit(1); + } +} diff --git a/cli/src/manifest.rs b/cli/src/manifest.rs new file mode 100644 index 0000000..579c099 --- /dev/null +++ b/cli/src/manifest.rs @@ -0,0 +1,37 @@ +use anyhow::{Context, Result}; +use serde::Deserialize; +use std::path::Path; + +/// Parsed dist-manifest.yml +#[derive(Debug, Deserialize)] +pub struct DistManifest { + pub version: String, + pub description: String, + pub files: Vec, + #[serde(default)] + pub injections: Option, +} + +#[derive(Debug, Deserialize)] +pub struct Injections { + #[serde(default)] + pub reference: Vec, + #[serde(default)] + pub inline: Vec, + #[serde(default)] + pub directory: Vec, +} + +impl DistManifest { + /// Load manifest from within a ZIP archive's extracted directory + pub fn from_str(content: &str) -> Result { + serde_yaml::from_str(content).context("Failed to parse dist-manifest.yml") + } + + /// Load manifest from a file path + pub fn load(path: &Path) -> Result { + let content = + std::fs::read_to_string(path).context("Failed to read dist-manifest.yml")?; + Self::from_str(&content) + } +} diff --git a/cli/src/utils.rs b/cli/src/utils.rs new file mode 100644 index 0000000..e2caf64 --- /dev/null +++ b/cli/src/utils.rs @@ -0,0 +1,49 @@ +use colored::Colorize; +use sha2::{Digest, Sha256}; +use std::path::Path; + +/// Print a success message +pub fn success(msg: &str) { + println!("{} {}", "✓".green().bold(), msg); +} + +/// Print an info message +pub fn info(msg: &str) { + println!("{} {}", "→".blue().bold(), msg); +} + +/// Print a warning message +pub fn warn(msg: &str) { + println!("{} {}", "!".yellow().bold(), msg); +} + +/// Compute SHA-256 hash of a file's contents +pub fn file_hash(path: &Path) -> Option { + let content = std::fs::read(path).ok()?; + let hash = Sha256::digest(&content); + Some(format!("{:x}", hash)) +} + +/// Check if a path looks like a user-generated DevTrail document +/// (matches pattern: *-YYYY-MM-DD-NNN-*.md) +pub fn is_user_document(path: &Path) -> bool { + let name = match path.file_name().and_then(|n| n.to_str()) { + Some(n) => n, + None => return false, + }; + + // Check for patterns like AILOG-2025-01-27-001-description.md + let prefixes = [ + "AILOG-", "AIDEC-", "ETH-", "ADR-", "REQ-", "TES-", "INC-", "TDE-", + ]; + + prefixes.iter().any(|p| name.starts_with(p)) +} + +/// Ensure a directory exists, creating it if needed +pub fn ensure_dir(path: &Path) -> std::io::Result<()> { + if !path.exists() { + std::fs::create_dir_all(path)?; + } + Ok(()) +} diff --git a/cli/tests/init_test.rs b/cli/tests/init_test.rs new file mode 100644 index 0000000..f4ee6f2 --- /dev/null +++ b/cli/tests/init_test.rs @@ -0,0 +1,34 @@ +use assert_cmd::Command; +use predicates::prelude::*; +use tempfile::TempDir; + +#[test] +fn test_init_shows_error_when_already_exists() { + let dir = TempDir::new().unwrap(); + std::fs::create_dir_all(dir.path().join(".devtrail")).unwrap(); + + let mut cmd = Command::cargo_bin("devtrail").unwrap(); + cmd.arg("init") + .arg(dir.path().to_str().unwrap()) + .assert() + .failure() + .stderr(predicate::str::contains("already exists")); +} + +#[test] +fn test_help_output() { + let mut cmd = Command::cargo_bin("devtrail").unwrap(); + cmd.arg("--help") + .assert() + .success() + .stdout(predicate::str::contains("DevTrail")); +} + +#[test] +fn test_version_output() { + let mut cmd = Command::cargo_bin("devtrail").unwrap(); + cmd.arg("--version") + .assert() + .success() + .stdout(predicate::str::contains("devtrail")); +} diff --git a/cli/tests/inject_test.rs b/cli/tests/inject_test.rs new file mode 100644 index 0000000..0997d9d --- /dev/null +++ b/cli/tests/inject_test.rs @@ -0,0 +1,60 @@ +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 = ""; + let end = ""; + + // Valid HTML comments + assert!(begin.starts_with("")); + assert!(end.starts_with("")); +} + +#[test] +fn test_remove_injection() { + let dir = TempDir::new().unwrap(); + let target = dir.path().join("test.md"); + + let content = "# My Config\n\nSome custom stuff\n\n\nDevTrail rules here\n\n\nMore custom stuff\n"; + fs::write(&target, content).unwrap(); + + // Simulate removal + let content = fs::read_to_string(&target).unwrap(); + let begin = ""; + let end = ""; + + if let (Some(start), Some(end_pos)) = (content.find(begin), content.find(end)) { + let end_pos = end_pos + end.len(); + let before = content[..start].trim_end(); + let after = content[end_pos..].trim_start(); + let new_content = format!("{}\n\n{}", before, after); + fs::write(&target, &new_content).unwrap(); + } + + let result = fs::read_to_string(&target).unwrap(); + assert!(!result.contains("devtrail:begin")); + assert!(result.contains("My Config")); + assert!(result.contains("More custom stuff")); +} diff --git a/cli/tests/update_test.rs b/cli/tests/update_test.rs new file mode 100644 index 0000000..48ca14e --- /dev/null +++ b/cli/tests/update_test.rs @@ -0,0 +1,26 @@ +use assert_cmd::Command; +use predicates::prelude::*; + +#[test] +fn test_update_shows_error_when_not_initialized() { + let dir = tempfile::TempDir::new().unwrap(); + + let mut cmd = Command::cargo_bin("devtrail").unwrap(); + cmd.current_dir(dir.path()) + .arg("update") + .assert() + .failure() + .stderr(predicate::str::contains("not found")); +} + +#[test] +fn test_remove_shows_error_when_not_initialized() { + let dir = tempfile::TempDir::new().unwrap(); + + let mut cmd = Command::cargo_bin("devtrail").unwrap(); + cmd.current_dir(dir.path()) + .arg("remove") + .assert() + .failure() + .stderr(predicate::str::contains("not installed")); +} diff --git a/copy-devtrail.sh b/copy-devtrail.sh deleted file mode 100644 index 8db0500..0000000 --- a/copy-devtrail.sh +++ /dev/null @@ -1,87 +0,0 @@ -#!/bin/bash -# -# copy-devtrail.sh - Copy DevTrail files to a destination folder -# -# Usage: ./copy-devtrail.sh -# -# Copies all files and folders from this repository to the destination, -# excluding public repository files (README, LICENSE, etc.) - -set -e - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -NC='\033[0m' # No Color - -# Get the script's directory (repo root) -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - -# Files and folders to exclude (public repo files in root) -EXCLUDES=( - "ADOPTION-GUIDE.md" - "CODE_OF_CONDUCT.md" - "CONTRIBUTING.md" - "devtrail.spdx" - "LICENSE" - "README.md" - "TRANSLATION-GUIDE.md" - "copy-devtrail.sh" - "copy-to-all-lnxdrive.sh" - "assets" - "docs" - "i18n" -) - -usage() { - echo "Usage: $0 " - echo "" - echo "Copies DevTrail files to the specified destination folder." - echo "Excludes public repository files: ${EXCLUDES[*]}" - exit 1 -} - -# Check arguments -if [ $# -ne 1 ]; then - echo -e "${RED}Error: Destination folder is required${NC}" - usage -fi - -DEST="$1" - -# Check if rsync is available -if ! command -v rsync &> /dev/null; then - echo -e "${RED}Error: rsync is not installed${NC}" - echo "Please install rsync and try again." - exit 1 -fi - -# Create destination if it doesn't exist -if [ ! -d "$DEST" ]; then - echo -e "${YELLOW}Creating destination folder: $DEST${NC}" - mkdir -p "$DEST" -fi - -# Build rsync exclude arguments -EXCLUDE_ARGS="" -for item in "${EXCLUDES[@]}"; do - EXCLUDE_ARGS="$EXCLUDE_ARGS --exclude=$item" -done - -# Also exclude .git folder -EXCLUDE_ARGS="$EXCLUDE_ARGS --exclude=.git" - -echo -e "${GREEN}Copying DevTrail files...${NC}" -echo " Source: $SCRIPT_DIR" -echo " Destination: $DEST" -echo "" - -# Run rsync -# -a: archive mode (preserves permissions, timestamps, etc.) -# -v: verbose -# --progress: show progress -rsync -av --progress $EXCLUDE_ARGS "$SCRIPT_DIR/" "$DEST/" - -echo "" -echo -e "${GREEN}Done! Files copied to: $DEST${NC}" diff --git a/devtrail.spdx b/devtrail.spdx index 4f36d91..3746f17 100644 --- a/devtrail.spdx +++ b/devtrail.spdx @@ -2,18 +2,18 @@ SPDXVersion: SPDX-2.3 DataLicense: CC0-1.0 SPDXID: SPDXRef-DOCUMENT DocumentName: devtrail -DocumentNamespace: https://github.com/Enigmora/devtrail -Creator: Organization: Enigmora +DocumentNamespace: https://github.com/StrangeDaysTech/devtrail +Creator: Organization: Strange Days Tech, S.A.S. Created: 2025-01-27T00:00:00Z PackageName: devtrail SPDXID: SPDXRef-Package PackageVersion: 1.0.0 -PackageDownloadLocation: https://github.com/Enigmora/devtrail -PackageHomePage: https://github.com/Enigmora/devtrail +PackageDownloadLocation: https://github.com/StrangeDaysTech/devtrail +PackageHomePage: https://github.com/StrangeDaysTech/devtrail PackageLicenseConcluded: MIT PackageLicenseDeclared: MIT -PackageCopyrightText: Copyright (c) 2025 Enigmora and DevTrail Contributors +PackageCopyrightText: Copyright (c) 2025 Strange Days Tech, S.A.S. and DevTrail Contributors PackageSummary: Documentation governance framework for AI-assisted software development. PackageDescription: DevTrail provides a documentation governance system that ensures traceability for all significant changes in software projects, whether made by humans or AI agents. Includes templates, validation scripts, and multi-agent support. diff --git a/dist-manifest.yml b/dist-manifest.yml new file mode 100644 index 0000000..1745f33 --- /dev/null +++ b/dist-manifest.yml @@ -0,0 +1,38 @@ +version: "2.0.0" +description: "DevTrail distribution manifest" +repository: "https://github.com/StrangeDaysTech/devtrail" + +# Files included when running `devtrail init` +files: + # Core framework + - .devtrail/ + + # Unified rules file + - DEVTRAIL.md + + # Agent skills + - .claude/skills/ + - .gemini/skills/ + - .agent/workflows/ + + # Scripts (bash + powershell) + - scripts/devtrail-new.sh + - scripts/devtrail-status.sh + - scripts/pre-commit-docs.sh + - scripts/validate-docs.ps1 + + # CI/CD + - .github/copilot-instructions.md + - .github/workflows/docs-validation.yml + +# 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 diff --git a/docs/_config.yml b/docs/_config.yml deleted file mode 100644 index 2264ef5..0000000 --- a/docs/_config.yml +++ /dev/null @@ -1,40 +0,0 @@ -title: DevTrail -description: Documentation Governance for AI-Assisted Software Development - -# Theme -remote_theme: just-the-docs/just-the-docs@v0.10.0 -plugins: - - jekyll-remote-theme - -# Site settings -baseurl: "/devtrail" -url: "https://enigmora.github.io" - -# Enable search -search_enabled: true -search: - heading_level: 2 - previews: 3 - -# Aux links (top right) -aux_links: - "GitHub": - - "https://github.com/Enigmora/devtrail" - -aux_links_new_tab: true - -# Footer -footer_content: 'Enigmora — Because every change tells a story.' - -# Color scheme (light/dark) -color_scheme: light - -# Back to top link -back_to_top: true -back_to_top_text: "Back to top" - -# Exclude from build -exclude: - - Gemfile - - Gemfile.lock - - README.md diff --git a/docs/cookbook.md b/docs/cookbook.md deleted file mode 100644 index 54b0090..0000000 --- a/docs/cookbook.md +++ /dev/null @@ -1,160 +0,0 @@ -# DevTrail Cookbook - -Quick reference for common documentation scenarios. - ---- - -## Quick Reference - -| Scenario | Document Type | Command | -|----------|---------------|---------| -| Implemented feature | AILOG | `/devtrail-ailog` | -| Chose between options | AIDEC | `/devtrail-aidec` | -| Security issue | AILOG (risk: high) | `/devtrail-ailog` | -| Technical debt | TDE | `/devtrail-new tde` | -| Personal data | AILOG + ETH | `/devtrail-new eth` | -| Production incident | INC | `/devtrail-new inc` | -| New requirement | REQ | `/devtrail-new req` | -| Architecture decision | ADR | `/devtrail-adr` | - ---- - -## Scenario 1: Implemented a Feature - -Created >10 lines of business logic? Create an AILOG: - -```yaml ---- -id: AILOG-2025-01-29-001 -title: Implement JWT authentication -agent: claude-code-v1.0 -confidence: high -risk_level: high -review_required: true -files_affected: - - src/auth/jwt.service.ts ---- - -## Summary -Implemented JWT-based authentication. - -## Changes -- Created JwtService for token handling -- Added route protection with JwtGuard -``` - ---- - -## Scenario 2: Choosing Between Options - -Deciding between libraries, approaches, or technologies? Create an AIDEC: - -```yaml ---- -id: AIDEC-2025-01-29-001 -title: Choose Zod over Yup for validation -agent: claude-code-v1.0 -confidence: high ---- - -## Decision -Use **Zod** for schema validation. - -## Alternatives -- **Zod**: TypeScript-first, smaller bundle ✓ -- **Yup**: Mature but requires separate types -``` - ---- - -## Scenario 3: Security Issue - -Found or fixed a vulnerability? Create AILOG with `risk_level: critical`: - -```yaml ---- -id: AILOG-2025-01-29-002 -title: Fix SQL injection vulnerability -risk_level: critical -review_required: true ---- - -## Vulnerability -User input was concatenated directly into SQL query. - -## Fix -Replaced with parameterized query. -``` - ---- - -## Scenario 4: Personal Data (GDPR) - -Handling PII? Create AILOG + ETH draft: - -```yaml -# ETH document (requires human approval) ---- -id: ETH-2025-01-29-001 -title: User profile PII handling -status: draft -gdpr_relevant: true ---- - -## Data Collected -- email (required) -- phone (optional) - -## GDPR Checklist -- [ ] Consent mechanism? -- [ ] Deletion capability? -``` - ---- - -## Scenario 5: AI Made a Mistake - -Document the error and fix: - -```yaml ---- -id: AILOG-2025-01-29-003 -title: Fix AI-generated pagination bug -tags: - - bugfix - - ai-error ---- - -## Error -Off-by-one in pagination (page 1 returned offset 10). - -## Fix -Changed `page * size` to `(page - 1) * size`. -``` - ---- - -## Scenario 6: Technical Debt - -Identify debt (human prioritizes later): - -```yaml ---- -id: TDE-2025-01-29-001 -title: Hardcoded configuration values -debt_type: code -estimated_effort: "1 sprint" ---- - -## Problem -Config values scattered across files. - -## Solution -Create centralized config module. -``` - ---- - -## Full Documentation - -See the [DevTrail Handbook](https://enigmora.github.io/devtrail/handbook/cookbook) for complete examples. diff --git a/docs/handbook/ai-configuration.md b/docs/handbook/ai-configuration.md deleted file mode 100644 index ff77f9d..0000000 --- a/docs/handbook/ai-configuration.md +++ /dev/null @@ -1,261 +0,0 @@ ---- -layout: default -parent: Handbook -nav_order: 5 -title: AI Configuration ---- - -# AI Agent Configuration - -How to configure different AI coding assistants to work with DevTrail. - ---- - -## Supported Platforms - -| Platform | Config File | Auto-loaded | -|----------|-------------|-------------| -| Claude Code | `CLAUDE.md` | ✅ Yes | -| Cursor | `.cursorrules` | ✅ Yes | -| Gemini CLI | `GEMINI.md` | ✅ Yes | -| GitHub Copilot | `.github/copilot-instructions.md` | ✅ Yes | - -All configurations are **pre-configured** in DevTrail. No additional setup required! - ---- - -## How It Works - -Each AI platform has a configuration file that: - -1. **Identifies the agent** — e.g., `claude-code-v1.0` -2. **Defines when to document** — >10 lines, security changes, etc. -3. **Sets autonomy limits** — What AI can do vs. what needs human review -4. **Specifies templates** — Where to find document templates -5. **Requires reporting** — AI must report documentation status -6. **Enforces Git workflow** — Branch naming and conventional commits - ---- - -## Claude Code - -**Configuration**: `CLAUDE.md` (project root) - -Claude Code automatically reads this file at session start. - -### Key Rules for Claude - -```markdown -- Identify as: claude-code-v1.0 -- Create AILOG for >10 lines of business logic -- Create AIDEC when choosing between alternatives -- Mark review_required: true for security changes -- Report documentation status after each task -- Never commit directly to main branch -- Use conventional commits (feat:, fix:, docs:, etc.) -``` - -### Customizing - -Edit `CLAUDE.md` to: -- Change agent identifier -- Adjust documentation thresholds -- Add project-specific rules - ---- - -## Cursor - -**Configuration**: `.cursorrules` (project root) - -Cursor reads this file automatically. - -### Key Rules for Cursor - -Same as Claude — the rules are functionally identical. - ---- - -## Gemini CLI - -**Configuration**: `GEMINI.md` (project root) - -Gemini CLI reads this file at session start. - -### Key Rules for Gemini - -Same as Claude — the rules are functionally identical. - ---- - -## GitHub Copilot - -**Configuration**: `.github/copilot-instructions.md` - -Copilot Chat reads this file for context. - -### Key Rules for Copilot - -Same as other platforms — adapted for Copilot's format. - ---- - -## Agent Identification - -All agents must identify themselves in documents: - -```yaml ---- -agent: claude-code-v1.0 -confidence: high ---- -``` - -### Agent Identifiers - -| Platform | Identifier | -|----------|------------| -| Claude Code | `claude-code-v1.0` | -| Cursor | `cursor-v1.0` | -| Gemini CLI | `gemini-cli-v1.0` | -| GitHub Copilot | `copilot-v1.0` | -| Human | `human` | - ---- - -## Confidence Levels - -Agents must declare confidence: - -| Level | Meaning | Action | -|-------|---------|--------| -| `high` | Agent is certain | Proceed normally | -| `medium` | Minor doubts | Document alternatives | -| `low` | Needs validation | Mark `review_required: true` | - ---- - -## Autonomy Limits - -What each document type allows: - -| Type | AI Can Do | Requires Human | -|------|-----------|----------------| -| AILOG | Create freely | — | -| AIDEC | Create freely | — | -| ETH | Create draft | Approval | -| ADR | Create draft | Review | -| REQ | Propose | Validation | -| TES | Propose | Validation | -| INC | Contribute | Conclusions | -| TDE | Identify | Prioritization | - ---- - -## Review Triggers - -Agents must mark `review_required: true` when: - -1. `confidence: low` -2. `risk_level: high` or `critical` -3. Security/authentication changes -4. Irreversible changes (migrations, deletions) -5. User-facing impact -6. Ethical concerns (privacy, bias) - ---- - -## Skills (Active Documentation) - -Beyond auto-documentation, you can actively invoke documentation: - -### Claude Code & Gemini CLI - -```bash -/devtrail-status # Check documentation compliance -/devtrail-new # Create any document (AI suggests type) -/devtrail-ailog # Quick AILOG creation -/devtrail-aidec # Quick AIDEC creation -/devtrail-adr # Quick ADR creation -``` - -### Shell Scripts (Any Platform) - -```bash -./scripts/devtrail-status.sh -./scripts/devtrail-new.sh -./scripts/devtrail-new.sh ailog -``` - ---- - -## Customizing Agent Configs - -To customize for your project: - -1. **Change agent version**: - ```yaml - agent: acme-claude-v2.0 - ``` - -2. **Adjust thresholds**: - ```markdown - Create AILOG for >20 lines (instead of 10) - ``` - -3. **Add project rules**: - ```markdown - ## Project-Specific Rules - - Always document database migrations - - Require review for payment-related code - ``` - ---- - -## Git Operations - -All agent configurations include a **Git Operations** section that enforces: - -### Branch Naming - -| 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 | - -### Critical Rule - -> **Never commit directly to `main` branch.** - -All changes must go through feature/fix branches and Pull Requests. - -Full details: `.devtrail/00-governance/GIT-BRANCHING-STRATEGY.md` - ---- - -## Multi-Agent Projects - -If using multiple AI platforms on the same project: - -- All agents read their respective config files -- All agents follow the same DevTrail rules -- Documents are interchangeable (same format) -- Use agent identifier to track who created what - ---- - -[← Document Types](document-types) | [Cookbook →](cookbook) diff --git a/docs/handbook/contributing.md b/docs/handbook/contributing.md deleted file mode 100644 index 24a2c31..0000000 --- a/docs/handbook/contributing.md +++ /dev/null @@ -1,232 +0,0 @@ ---- -layout: default -parent: Handbook -nav_order: 8 -title: Contributing ---- - -# Contributing to DevTrail - -How to contribute to the DevTrail. - ---- - -## Ways to Contribute - -| Type | Description | -|------|-------------| -| 🐛 **Bug Reports** | Found something broken? Report it! | -| 💡 **Features** | Have an idea? Suggest it! | -| 📖 **Documentation** | Improve docs, fix typos | -| 🔧 **Code** | Submit fixes or new features | -| 🌍 **Translations** | Add new languages | - ---- - -## Quick Start - -```bash -# Fork the repository on GitHub - -# Clone your fork -git clone https://github.com/your-username/devtrail.git -cd devtrail - -# Create a branch -git checkout -b feature/your-feature-name - -# Make changes, then commit -git add . -git commit -m "feat: your feature description" - -# Push and create PR -git push origin feature/your-feature-name -``` - ---- - -## Commit Messages - -Use [Conventional Commits](https://www.conventionalcommits.org/): - -``` -type(scope): description - -Examples: -feat(templates): add template for security reviews -fix(validation): correct regex for file naming -docs(readme): clarify installation steps -``` - -**Types**: -- `feat` — New feature -- `fix` — Bug fix -- `docs` — Documentation -- `chore` — Maintenance -- `refactor` — Code refactoring - ---- - -## Pull Request Process - -1. **Before submitting**: - - Run `bash scripts/pre-commit-docs.sh` - - Update documentation if needed - - Write clear PR description - -2. **PR template**: - ```markdown - ## Summary - Brief description - - ## Changes - - Change 1 - - Change 2 - - ## Testing - How were these tested? - ``` - -3. **Review**: A maintainer will review and may request changes - ---- - -## Adding Document Types - -To propose a new document type: - -1. Create `TEMPLATE-NEWTYPE.md` in `.devtrail/templates/` -2. Update governance docs: - - `DOCUMENTATION-POLICY.md` - - `AGENT-RULES.md` - - `QUICK-REFERENCE.md` -3. Update agent configs: - - `CLAUDE.md` - - `GEMINI.md` - - `.cursorrules` - - `.github/copilot-instructions.md` -4. Update validation scripts -5. Create an ADR explaining the new type - ---- - -## Adding Translations - -See [TRANSLATION-GUIDE.md](https://github.com/enigmora/devtrail/blob/main/TRANSLATION-GUIDE.md) for: - -- What to translate -- What NOT to translate (technical tokens) -- File structure -- Quality checklist - -**Quick start**: -```bash -# Copy structure -mkdir -p i18n/pt # Portuguese example -cp i18n/es/*.md i18n/pt/ - -# Translate files -# Keep: AILOG, AIDEC, status values, YAML keys -# Translate: Headers, descriptions, examples -``` - ---- - -## Code Style - -### Markdown - -- ATX-style headers (`#`, `##`) -- Fenced code blocks with language -- Tables for structured data -- Keep lines under 120 characters - -### YAML - -```yaml ---- -id: TYPE-YYYY-MM-DD-NNN -title: "Clear title" -status: draft | accepted ---- -``` - -### Scripts - -- Clear variable names -- Comments for complex logic -- Follow shell/PowerShell best practices - ---- - -## Development Setup - -```bash -# Prerequisites -# - Git -# - Node.js (optional, for markdownlint) -# - Bash or PowerShell - -# Install linting tools (optional) -npm install -g markdownlint-cli - -# Validate your changes -bash scripts/pre-commit-docs.sh - -# Run markdownlint -markdownlint '**/*.md' --ignore node_modules -``` - ---- - -## Testing Changes - -### Validation Scripts - -```bash -# Linux/Mac -bash scripts/pre-commit-docs.sh - -# Windows -.\scripts\validate-docs.ps1 -``` - -### Local Documentation Preview - -```bash -# If editing GitHub Pages docs -cd docs -bundle install -bundle exec jekyll serve -# Visit http://localhost:4000 -``` - ---- - -## Recognition - -Contributors are recognized in: -- GitHub's contributor graph -- Release notes -- CONTRIBUTORS.md (for recurring contributors) - ---- - -## Code of Conduct - -Be respectful, inclusive, and constructive. See [CODE_OF_CONDUCT.md](https://github.com/enigmora/devtrail/blob/main/CODE_OF_CONDUCT.md). - ---- - -## Getting Help - -- **Issues**: [GitHub Issues](https://github.com/enigmora/devtrail/issues) -- **Discussions**: [GitHub Discussions](https://github.com/enigmora/devtrail/discussions) - ---- - -Thank you for contributing! 🎉 - ---- - -[← Troubleshooting](troubleshooting) | [Back to Home](../) diff --git a/docs/handbook/cookbook.md b/docs/handbook/cookbook.md deleted file mode 100644 index 21ae68d..0000000 --- a/docs/handbook/cookbook.md +++ /dev/null @@ -1,431 +0,0 @@ ---- -layout: default -parent: Handbook -nav_order: 6 -title: Cookbook ---- - -# Cookbook: Practical Examples - -Real-world scenarios showing how to use DevTrail. - ---- - -## Scenario 1: I Just Implemented a New Feature - -**Situation**: You implemented JWT authentication (~50 lines of code). - -**Action**: Create an AILOG - -```bash -/devtrail-ailog -# or -./scripts/devtrail-new.sh ailog -``` - -**Document**: - -```yaml ---- -id: AILOG-2025-01-29-001 -title: Implement JWT authentication -status: accepted -created: 2025-01-29 -agent: claude-code-v1.0 -confidence: high -review_required: true -risk_level: high -tags: - - auth - - security -files_affected: - - src/auth/jwt.service.ts - - src/auth/jwt.guard.ts ---- - -## Summary - -Implemented JWT-based authentication using the `jsonwebtoken` library. - -## Changes - -- Created `JwtService` for token generation and validation -- Created `JwtGuard` for protecting routes -- Added token expiration (24 hours) - -## Security Considerations - -- Tokens are signed with RS256 -- Refresh tokens stored in httpOnly cookies -- See ETH-2025-01-29-001 for data handling review -``` - ---- - -## Scenario 2: I'm Choosing Between Two Libraries - -**Situation**: Need to pick between Zod and Yup for validation. - -**Action**: Create an AIDEC - -```bash -/devtrail-aidec -``` - -**Document**: - -```yaml ---- -id: AIDEC-2025-01-29-001 -title: Choose Zod over Yup for schema validation -status: accepted -created: 2025-01-29 -agent: claude-code-v1.0 -confidence: high -review_required: false -risk_level: low ---- - -## Decision - -Use **Zod** for schema validation. - -## Alternatives Considered - -### Zod (Chosen) -- ✅ TypeScript-first with excellent type inference -- ✅ Smaller bundle size -- ✅ Active development -- ❌ Newer, less ecosystem - -### Yup -- ✅ Mature, large ecosystem -- ✅ Good documentation -- ❌ Requires separate TypeScript types -- ❌ Larger bundle - -## Justification - -TypeScript type inference is critical for our codebase. Zod's first-class TypeScript support eliminates the need for duplicate type definitions. -``` - ---- - -## Scenario 3: I Found a Security Issue - -**Situation**: Discovered SQL injection vulnerability in user search. - -**Action**: Create AILOG with `risk_level: critical` - -```yaml ---- -id: AILOG-2025-01-29-002 -title: Fix SQL injection in user search -status: accepted -created: 2025-01-29 -agent: claude-code-v1.0 -confidence: high -review_required: true -risk_level: critical -tags: - - security - - vulnerability -files_affected: - - src/users/users.repository.ts ---- - -## Summary - -Fixed SQL injection vulnerability in user search endpoint. - -## Vulnerability - -The `searchUsers` function was concatenating user input directly: - -```typescript -// VULNERABLE - DON'T DO THIS -const query = `SELECT * FROM users WHERE name LIKE '%${input}%'`; -``` - -## Fix - -Replaced with parameterized query: - -```typescript -// SECURE -const query = `SELECT * FROM users WHERE name LIKE $1`; -const params = [`%${input}%`]; -``` - -## Impact - -- Severity: Critical -- Affected versions: All prior to this fix -- Exploitation: Could leak entire database -``` - ---- - -## Scenario 4: I Need to Document Technical Debt - -**Situation**: The codebase has hardcoded configuration values. - -**Action**: Create a TDE document - -```yaml ---- -id: TDE-2025-01-29-001 -title: Hardcoded configuration values throughout codebase -status: accepted -created: 2025-01-29 -agent: claude-code-v1.0 -confidence: medium -review_required: false -risk_level: medium -debt_type: code -estimated_effort: "1 sprint" -business_impact: medium ---- - -## Description - -Configuration values (API URLs, timeouts, limits) are hardcoded across multiple files. - -## Examples - -- `src/api/client.ts`: `baseURL: 'https://api.example.com'` -- `src/cache/redis.ts`: `ttl: 3600` -- `src/upload/limits.ts`: `maxSize: 10485760` - -## Proposed Solution - -1. Create centralized config module -2. Use environment variables -3. Implement config validation at startup - -## Consequences if Not Addressed - -- Difficult to deploy to different environments -- Configuration changes require code changes -- Risk of secrets in version control -``` - ---- - -## Scenario 5: The AI Made a Mistake - -**Situation**: AI generated code with a bug that made it to production. - -**Action**: Create AILOG documenting the error and fix - -```yaml ---- -id: AILOG-2025-01-29-003 -title: Fix AI-generated off-by-one error in pagination -status: accepted -created: 2025-01-29 -agent: claude-code-v1.0 -confidence: high -review_required: true -risk_level: medium -tags: - - bugfix - - ai-error ---- - -## Summary - -Fixed off-by-one error in pagination logic introduced by AI. - -## Original Error - -AI-generated code in AILOG-2025-01-28-005 had: - -```typescript -const offset = page * pageSize; // Wrong: page 1 returns offset 10 -``` - -## Correction - -```typescript -const offset = (page - 1) * pageSize; // Correct: page 1 returns offset 0 -``` - -## Lessons Learned - -- Pagination logic requires explicit testing -- AI should mark `review_required: true` for boundary conditions -``` - ---- - -## Scenario 6: I'm Handling User Personal Data - -**Situation**: Implementing user profile with email and phone storage. - -**Action**: Create AILOG + ETH draft - -```yaml -# AILOG-2025-01-29-004 ---- -id: AILOG-2025-01-29-004 -title: Implement user profile with PII storage -status: accepted -created: 2025-01-29 -agent: claude-code-v1.0 -confidence: high -review_required: true -risk_level: high -related: - - ETH-2025-01-29-001 ---- -``` - -```yaml -# ETH-2025-01-29-001 (separate document) ---- -id: ETH-2025-01-29-001 -title: User profile PII handling review -status: draft # Requires human approval -created: 2025-01-29 -agent: claude-code-v1.0 -review_required: true -gdpr_relevant: true ---- - -## Data Being Collected - -| Field | Type | Necessity | -|-------|------|-----------| -| email | PII | Required for auth | -| phone | PII | Optional | -| name | PII | Required for display | - -## GDPR Considerations - -- [ ] Consent mechanism implemented? -- [ ] Data deletion capability? -- [ ] Export capability? -- [ ] Encryption at rest? - -## Human Decision Required - -- Is phone number truly optional? -- What is the data retention period? -- Who has access to this data? -``` - ---- - -## Scenario 7: We Had a Production Incident - -**Situation**: Database connection pool exhaustion caused 30-minute outage. - -**Action**: Create INC document - -```yaml ---- -id: INC-2025-01-29-001 -title: Database connection pool exhaustion incident -status: accepted -created: 2025-01-29 -agent: human # Human-led, AI contributes -severity: SEV2 -duration_minutes: 30 ---- - -## Timeline - -| Time | Event | -|------|-------| -| 14:00 | Alerts triggered for slow API responses | -| 14:05 | Investigation started | -| 14:15 | Identified connection pool exhaustion | -| 14:20 | Increased pool size as temporary fix | -| 14:30 | Service restored | - -## Root Cause - -Long-running queries from new reporting feature were holding connections. - -## Resolution - -1. Immediate: Increased pool size from 10 to 50 -2. Short-term: Added query timeouts -3. Long-term: Move reporting to read replica - -## Lessons Learned - -- Load test new features with production-scale data -- Add connection pool monitoring -- Document expected query durations -``` - ---- - -## Scenario 8: I Want to Propose a New Requirement - -**Situation**: Business needs multi-language support. - -**Action**: Create REQ document - -```yaml ---- -id: REQ-2025-01-29-001 -title: Multi-language support (i18n) -status: draft # Pending human validation -created: 2025-01-29 -agent: claude-code-v1.0 -confidence: medium -review_required: true -type: functional -priority: should ---- - -## Description - -The application should support multiple languages for the user interface. - -## User Stories - -- As a user, I want to see the UI in my preferred language -- As an admin, I want to add new translations without code changes - -## Acceptance Criteria - -- [ ] Support for English (default) and Spanish -- [ ] Language selector in user settings -- [ ] All UI text externalized -- [ ] Date/number formatting by locale - -## Technical Notes - -- Consider using `react-i18next` or similar -- Translations stored in JSON files -- Server-side detection from `Accept-Language` header - -## Questions for Stakeholders - -- Which languages are priority? -- Should content (not just UI) be translatable? -- What is the timeline? -``` - ---- - -## Quick Reference - -| Scenario | Document Type | -|----------|---------------| -| Implemented feature | AILOG | -| Chose between options | AIDEC | -| Security issue | AILOG (risk: high/critical) | -| Technical debt | TDE | -| AI made a mistake | AILOG (documenting fix) | -| Personal data | AILOG + ETH | -| Production incident | INC | -| New requirement | REQ | - ---- - -[← AI Configuration](ai-configuration) | [Troubleshooting →](troubleshooting) diff --git a/docs/handbook/daily-usage.md b/docs/handbook/daily-usage.md deleted file mode 100644 index 5cc0243..0000000 --- a/docs/handbook/daily-usage.md +++ /dev/null @@ -1,211 +0,0 @@ ---- -layout: default -parent: Handbook -nav_order: 3 -title: Daily Usage ---- - -# Daily Usage - -How to use DevTrail in your day-to-day development workflow. - ---- - -## The Core Principle - -> **"No significant change without a documented trace."** - -But what counts as "significant"? And what doesn't? - ---- - -## Git Workflow - -Before documenting, follow the Git branching strategy: - -### Branch Naming - -| Prefix | Purpose | -|--------|---------| -| `feature/` or `feat/` | New features | -| `fix/` | Bug fixes | -| `hotfix/` | Urgent production fixes | -| `docs/` | Documentation only | - -### Quick Workflow - -```bash -# 1. Create branch from updated main -git checkout main && git pull origin main -git checkout -b fix/descriptive-name - -# 2. Make changes and commits (use conventional commits) -git commit -m "fix: resolve pagination issue" - -# 3. Push and create PR -git push -u origin fix/descriptive-name -gh pr create --title "fix: description" --body "..." -``` - -> **CRITICAL**: Never commit directly to `main`. Always use branches + PRs. -> -> Full details: `.devtrail/00-governance/GIT-BRANCHING-STRATEGY.md` - ---- - -## When to Document - -### ✅ MUST Document - -| Situation | Document Type | -|-----------|---------------| -| Changed >10 lines of business logic | AILOG | -| Decided between 2+ technical alternatives | AIDEC | -| Modified security/authentication | AILOG + `risk_level: high` | -| Handled personal data (PII/GDPR) | AILOG + ETH draft | -| Integrated with external service | AILOG | -| Changed public API or database schema | AILOG | - -### ❌ DON'T Document - -- Whitespace changes, formatting -- Typo fixes -- Code comments -- Minor refactoring (<10 lines) -- **NEVER**: Credentials, tokens, API keys - ---- - -## Creating Documents - -### Using AI Skills (Recommended) - -If using Claude Code or Gemini CLI: - -```bash -# Create any document (AI suggests type) -/devtrail-new - -# Create specific document types -/devtrail-ailog -/devtrail-aidec -/devtrail-adr - -# Check documentation status -/devtrail-status -``` - -### Using Shell Scripts - -```bash -# Interactive document creation -./scripts/devtrail-new.sh - -# Create specific type -./scripts/devtrail-new.sh ailog - -# Check status -./scripts/devtrail-status.sh -``` - -### Manual Creation - -1. Copy the template: - ```bash - cp .devtrail/templates/TEMPLATE-AILOG.md \ - .devtrail/07-ai-audit/agent-logs/AILOG-$(date +%Y-%m-%d)-001-description.md - ``` - -2. Fill in the metadata and content - -3. Commit with your code changes - ---- - -## Document Workflow - -``` -┌─────────────────────────────────────────┐ -│ 1. EVALUATE │ -│ Does this change need docs? │ -│ (See "When to Document" above) │ -└─────────────────────────────────────────┘ - │ - ▼ -┌─────────────────────────────────────────┐ -│ 2. CREATE │ -│ Use skill, script, or manual │ -│ Follow naming: TYPE-YYYY-MM-DD-NNN │ -└─────────────────────────────────────────┘ - │ - ▼ -┌─────────────────────────────────────────┐ -│ 3. REVIEW (if needed) │ -│ Mark review_required: true when: │ -│ - confidence: low │ -│ - risk_level: high/critical │ -│ - Security decisions │ -└─────────────────────────────────────────┘ - │ - ▼ -┌─────────────────────────────────────────┐ -│ 4. COMMIT │ -│ Include docs with your code changes │ -└─────────────────────────────────────────┘ -``` - ---- - -## File Naming Convention - -``` -[TYPE]-[YYYY-MM-DD]-[NNN]-[description].md -``` - -| Component | Description | Example | -|-----------|-------------|---------| -| TYPE | Document prefix | `AILOG`, `AIDEC`, `ADR` | -| YYYY-MM-DD | Creation date | `2025-01-29` | -| NNN | Sequential number | `001`, `002` | -| description | Brief kebab-case desc | `implement-oauth` | - -**Example**: `AILOG-2025-01-29-001-implement-oauth.md` - ---- - -## Status Reporting - -At the end of each task, report your documentation status: - -``` -DevTrail: Created AILOG-2025-01-29-001-implement-auth.md -``` - -or - -``` -DevTrail: No documentation required (minor change / <10 lines) -``` - ---- - -## Quick Reference - -Keep `.devtrail/QUICK-REFERENCE.md` handy for: -- Document type locations -- Minimum metadata fields -- When to mark `review_required: true` - ---- - -## Tips for Success - -1. **Document as you code** — Don't leave it for later -2. **Use templates** — They ensure consistency -3. **Be concise** — Minimum viable documentation -4. **Link related docs** — Use `[REQ-XXXX]` format -5. **Review regularly** — Run `/devtrail-status` weekly - ---- - -[← Getting Started](getting-started) | [Document Types →](document-types) diff --git a/docs/handbook/document-types.md b/docs/handbook/document-types.md deleted file mode 100644 index 58d6bf5..0000000 --- a/docs/handbook/document-types.md +++ /dev/null @@ -1,270 +0,0 @@ ---- -layout: default -parent: Handbook -nav_order: 4 -title: Document Types ---- - -# Document Types Reference - -DevTrail defines 8 document types covering the full development lifecycle. - ---- - -## Overview - -| Type | Name | Purpose | AI Autonomy | -|------|------|---------|-------------| -| **REQ** | Requirement | System requirements | Propose only | -| **ADR** | Architecture Decision Record | Technical/architectural decisions | Create draft | -| **TES** | Test Plan | Test strategies | Propose only | -| **INC** | Incident Post-mortem | Production incident analysis | Contribute | -| **TDE** | Technical Debt | Identified technical debt | Identify only | -| **AILOG** | AI Action Log | What AI did and why | Create freely | -| **AIDEC** | AI Decision | Choices AI made with alternatives | Create freely | -| **ETH** | Ethical Review | Privacy, bias, responsible AI | Draft only | - ---- - -## Document Locations - -``` -.devtrail/ -├── 01-requirements/ ← REQ documents -├── 02-design/decisions/ ← ADR documents -├── 04-testing/ ← TES documents -├── 05-operations/incidents/ ← INC documents -├── 06-evolution/technical-debt/ ← TDE documents -└── 07-ai-audit/ - ├── agent-logs/ ← AILOG documents - ├── decisions/ ← AIDEC documents - └── ethical-reviews/ ← ETH documents -``` - ---- - -## Detailed Reference - -### REQ — Requirement - -**Purpose**: Document system requirements, user stories, and constraints. - -**When to use**: -- Defining new features -- Capturing user needs -- Documenting constraints - -**AI autonomy**: Propose only (human validates) - -**Key fields**: -```yaml -type: functional | non-functional | constraint -priority: must | should | could | wont -``` - ---- - -### ADR — Architecture Decision Record - -**Purpose**: Record significant architectural or technical decisions. - -**When to use**: -- Choosing between technologies -- Defining system architecture -- Making irreversible decisions - -**AI autonomy**: Create draft (human reviews) - -**Key fields**: -```yaml -status: proposed | accepted | deprecated | superseded -decision: "We will use X because..." -alternatives: - - "Option A: ..." - - "Option B: ..." -consequences: - - "Good: ..." - - "Bad: ..." -``` - ---- - -### TES — Test Plan - -**Purpose**: Document test strategies, coverage goals, and test plans. - -**When to use**: -- Planning test coverage -- Defining test strategies -- Documenting test requirements - -**AI autonomy**: Propose only (human validates) - ---- - -### INC — Incident Post-mortem - -**Purpose**: Analyze production incidents and document lessons learned. - -**When to use**: -- After production incidents -- For root cause analysis -- To prevent recurrence - -**AI autonomy**: Contribute analysis (human concludes) - -**Key fields**: -```yaml -severity: SEV1 | SEV2 | SEV3 | SEV4 -duration_minutes: 45 -root_cause: "..." -lessons_learned: - - "..." -``` - ---- - -### TDE — Technical Debt - -**Purpose**: Track identified technical debt and remediation plans. - -**When to use**: -- Identifying code smells -- Documenting shortcuts taken -- Planning refactoring - -**AI autonomy**: Identify only (human prioritizes) - -**Key fields**: -```yaml -debt_type: code | architecture | infrastructure | documentation | testing -estimated_effort: "2 sprints" -business_impact: low | medium | high -``` - ---- - -### AILOG — AI Action Log - -**Purpose**: Record what AI agents did and why. - -**When to use**: -- After implementing features (>10 lines) -- After making security changes -- After integrating external services - -**AI autonomy**: Create freely - -**Key fields**: -```yaml -agent: claude-code-v1.0 -confidence: high | medium | low -risk_level: low | medium | high | critical -review_required: true | false -files_affected: - - path/to/file.ts -``` - ---- - -### AIDEC — AI Decision - -**Purpose**: Document choices made by AI with alternatives considered. - -**When to use**: -- When choosing between libraries -- When selecting implementation approach -- When making design decisions - -**AI autonomy**: Create freely - -**Key fields**: -```yaml -decision: "Use library X over Y" -alternatives_considered: - - name: "Library X" - pros: ["..."] - cons: ["..."] - - name: "Library Y" - pros: ["..."] - cons: ["..."] -justification: "X was chosen because..." -``` - ---- - -### ETH — Ethical Review - -**Purpose**: Document privacy, bias, and responsible AI considerations. - -**When to use**: -- Handling personal data (PII/GDPR) -- Implementing AI/ML features -- Making decisions with ethical implications - -**AI autonomy**: Draft only (human approves) - -**Key fields**: -```yaml -status: draft # Always starts as draft -concerns: - - privacy - - bias - - accessibility -gdpr_relevant: true -human_oversight_required: true -``` - ---- - -## Metadata Reference - -### Required Fields (All Documents) - -```yaml ---- -id: TYPE-YYYY-MM-DD-NNN -title: "Brief description" -status: draft | accepted | deprecated | superseded -created: YYYY-MM-DD -agent: claude-code-v1.0 # or "human" -confidence: high | medium | low -review_required: true | false -risk_level: low | medium | high | critical ---- -``` - -### Optional Fields - -```yaml -updated: YYYY-MM-DD -tags: - - auth - - security -related: - - ADR-2025-01-20-001 -supersedes: TYPE-PREV-ID -superseded_by: TYPE-NEW-ID -``` - ---- - -## Status Lifecycle - -``` -draft ──────► accepted ──────► deprecated - │ │ - │ ▼ - └──────► superseded -``` - -| Status | Meaning | -|--------|---------| -| `draft` | Work in progress, pending review | -| `accepted` | Approved and currently valid | -| `deprecated` | Obsolete but kept for reference | -| `superseded` | Replaced by another document | - ---- - -[← Daily Usage](daily-usage) | [AI Configuration →](ai-configuration) diff --git a/docs/handbook/getting-started.md b/docs/handbook/getting-started.md deleted file mode 100644 index 6295ea1..0000000 --- a/docs/handbook/getting-started.md +++ /dev/null @@ -1,147 +0,0 @@ ---- -layout: default -parent: Handbook -nav_order: 2 -title: Getting Started ---- - -# Getting Started with DevTrail - -This guide walks you through adopting DevTrail in your project. - ---- - -## Prerequisites - -- Git installed -- A project repository (new or existing) -- An AI coding assistant (optional but recommended): Claude Code, Cursor, Gemini CLI, or GitHub Copilot - ---- - -## Option 1: Use as GitHub Template (New Projects) - -The fastest way to start: - -1. **Go to the DevTrail repository** on GitHub -2. **Click "Use this template"** → "Create a new repository" -3. **Clone your new repository**: - ```bash - git clone https://github.com/your-username/your-new-project.git - cd your-new-project - ``` -4. **Start working!** The framework is already configured. - ---- - -## Option 2: Add to Existing Project - -For projects that already exist: - -```bash -# Clone DevTrail temporarily -git clone https://github.com/Enigmora/devtrail.git devtrail-temp - -# Copy the framework files (won't overwrite existing) -cp -rn devtrail-temp/.devtrail ./ -cp -n devtrail-temp/CLAUDE.md ./ -cp -n devtrail-temp/GEMINI.md ./ -cp -n devtrail-temp/.cursorrules ./ -mkdir -p .github -cp -rn devtrail-temp/.github/* ./.github/ -cp -rn devtrail-temp/scripts ./ - -# Clean up -rm -rf devtrail-temp - -# Commit -git add .devtrail/ CLAUDE.md GEMINI.md .cursorrules .github/ scripts/ -git commit -m "chore: adopt DevTrail" -``` - ---- - -## Verify Installation - -Run the validation script: - -```bash -# Linux/Mac -bash scripts/pre-commit-docs.sh - -# Windows PowerShell -.\scripts\validate-docs.ps1 -``` - -You should see: -``` -✓ DevTrail validation passed -``` - ---- - -## What's Included - -After installation, you'll have: - -``` -your-project/ -├── .devtrail/ # Documentation framework -│ ├── 00-governance/ # Policies and rules -│ ├── 01-requirements/ # REQ documents -│ ├── 02-design/decisions/ # ADR documents -│ ├── 03-implementation/ # Implementation guides (Git strategy) -│ ├── 07-ai-audit/ # AILOG, AIDEC, ETH documents -│ ├── templates/ # Document templates -│ └── QUICK-REFERENCE.md # Quick reference card -├── CLAUDE.md # Claude Code configuration -├── GEMINI.md # Gemini CLI configuration -├── .cursorrules # Cursor configuration -├── .github/ -│ ├── copilot-instructions.md # GitHub Copilot configuration -│ └── workflows/ # CI/CD validation -└── scripts/ # Validation scripts -``` - ---- - -## Configure Your AI Assistant - -Choose your AI platform and follow the setup: - -| Platform | Configuration | -|----------|---------------| -| Claude Code | Automatically reads `CLAUDE.md` | -| Cursor | Automatically reads `.cursorrules` | -| Gemini CLI | Automatically reads `GEMINI.md` | -| GitHub Copilot | Reads `.github/copilot-instructions.md` | - -**No additional configuration needed!** The AI will automatically: -- Identify itself in documents -- Create AILOG/AIDEC documents when appropriate -- Request human review for high-risk changes -- Follow Git branching strategy (never commit to `main` directly) -- Use conventional commits (`feat:`, `fix:`, `docs:`, etc.) - ---- - -## Set Language (Optional) - -By default, templates are in English. To use Spanish: - -Edit `.devtrail/config.yml`: -```yaml -language: es -``` - ---- - -## Next Steps - -- [Daily Usage](daily-usage) — Learn the day-to-day workflow -- [Document Types](document-types) — Understand the 8 document types -- [Cookbook](cookbook) — See practical examples - ---- - -[← Back to Home](../) | [Daily Usage →](daily-usage) diff --git a/docs/handbook/index.md b/docs/handbook/index.md deleted file mode 100644 index bac12e8..0000000 --- a/docs/handbook/index.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -layout: default -title: Handbook -nav_order: 2 -has_children: true -permalink: /handbook/ ---- - -# DevTrail Handbook - -Complete documentation for using DevTrail in your projects. - -{: .fs-6 .fw-300 } - -Browse the sections in the sidebar or use the links below: - -| Section | Description | -|---------|-------------| -| [Getting Started](getting-started) | Install and configure DevTrail | -| [Daily Usage](daily-usage) | How to use DevTrail day-to-day | -| [Document Types](document-types) | All 8 document types explained | -| [AI Configuration](ai-configuration) | Setting up AI agents | -| [Cookbook](cookbook) | Practical examples and scenarios | -| [Troubleshooting](troubleshooting) | Common issues and solutions | -| [Contributing](contributing) | How to contribute | diff --git a/docs/handbook/troubleshooting.md b/docs/handbook/troubleshooting.md deleted file mode 100644 index 0af28d1..0000000 --- a/docs/handbook/troubleshooting.md +++ /dev/null @@ -1,249 +0,0 @@ ---- -layout: default -parent: Handbook -nav_order: 7 -title: Troubleshooting ---- - -# Troubleshooting - -Common issues and solutions when using DevTrail. - ---- - -## Installation Issues - -### "scripts/pre-commit-docs.sh: Permission denied" - -**Solution**: -```bash -chmod +x scripts/pre-commit-docs.sh -chmod +x scripts/devtrail-*.sh -``` - ---- - -### "Command not found: devtrail-new.sh" - -**Solution**: Run with explicit path: -```bash -./scripts/devtrail-new.sh -# or -bash scripts/devtrail-new.sh -``` - ---- - -### Files not copied during installation - -**Problem**: `cp -n` doesn't work on some systems. - -**Solution**: Use explicit copy: -```bash -# Check if file exists before copying -[ ! -f CLAUDE.md ] && cp devtrail-temp/CLAUDE.md ./ -``` - ---- - -## Validation Errors - -### "Invalid file naming" - -**Error**: -``` -ERROR: Invalid naming: my-document.md -Expected: TYPE-YYYY-MM-DD-NNN-description.md -``` - -**Solution**: Rename to correct format: -```bash -mv my-document.md AILOG-2025-01-29-001-my-document.md -``` - ---- - -### "Missing required metadata" - -**Error**: -``` -ERROR: Missing field 'agent' in AILOG-2025-01-29-001.md -``` - -**Solution**: Add missing field to frontmatter: -```yaml ---- -id: AILOG-2025-01-29-001 -title: My document -agent: human # Add this line -confidence: high -# ... rest of metadata ---- -``` - ---- - -### "Potential sensitive data detected" - -**Warning**: -``` -WARNING: Possible API key in file -``` - -**Solution**: -1. Remove the sensitive data -2. If it's a false positive, the validation will still pass (it's a warning) -3. Never commit actual credentials - ---- - -## AI Agent Issues - -### AI not creating documents - -**Problem**: AI assistant isn't following DevTrail rules. - -**Solutions**: -1. Verify config file exists (`CLAUDE.md`, `GEMINI.md`, etc.) -2. Explicitly remind the AI: "Remember to follow DevTrail rules" -3. Use `/devtrail-status` to check compliance - ---- - -### AI creating wrong document type - -**Problem**: AI creates AILOG when AIDEC is more appropriate. - -**Solution**: Be explicit in your request: -``` -Implement feature X and create an AIDEC documenting -why you chose this approach over alternatives. -``` - ---- - -### "Agent not recognized" in document - -**Problem**: Unknown agent identifier. - -**Solution**: Use standard identifiers: -- `claude-code-v1.0` -- `cursor-v1.0` -- `gemini-cli-v1.0` -- `copilot-v1.0` -- `human` - ---- - -## Template Issues - -### "Template not found" - -**Error**: -``` -Template .devtrail/templates/TEMPLATE-XYZ.md not found -``` - -**Solutions**: -1. Check template name is correct (case-sensitive) -2. Verify `.devtrail/templates/` directory exists -3. Re-copy templates from DevTrail repository - ---- - -### Templates in wrong language - -**Problem**: Getting English templates when Spanish is configured. - -**Solution**: Check `.devtrail/config.yml`: -```yaml -language: es # Must be exactly 'es', not 'ES' or 'spanish' -``` - -And verify Spanish templates exist: -```bash -ls .devtrail/templates/i18n/es/ -``` - ---- - -## GitHub Actions Issues - -### Workflow not running - -**Problem**: `docs-validation.yml` not triggering. - -**Solutions**: -1. Check `.github/workflows/docs-validation.yml` exists -2. Verify file is valid YAML -3. Check if PR modifies `.devtrail/` files (default trigger) - ---- - -### Workflow fails with "file not found" - -**Problem**: Validation script not found. - -**Solution**: Ensure scripts are committed: -```bash -git add scripts/ -git commit -m "chore: add validation scripts" -``` - ---- - -## Document Issues - -### "Document ID mismatch" - -**Problem**: ID in frontmatter doesn't match filename. - -**Solution**: Make them match: -```yaml -# File: AILOG-2025-01-29-001-auth.md ---- -id: AILOG-2025-01-29-001 # Must match filename (without .md) ---- -``` - ---- - -### Broken cross-references - -**Problem**: `[REQ-2025-01-15-003]` reference doesn't resolve. - -**Solution**: -1. Verify referenced document exists -2. Check exact ID spelling -3. Cross-references are for context, not automatic links - ---- - -### "Status transition invalid" - -**Problem**: Trying to change status in wrong order. - -**Valid transitions**: -``` -draft → accepted -accepted → deprecated -accepted → superseded -``` - -**Invalid**: -``` -deprecated → accepted ❌ -superseded → draft ❌ -``` - ---- - -## Still Stuck? - -1. **Check existing issues**: [GitHub Issues](https://github.com/enigmora/devtrail/issues) -2. **Ask the community**: [GitHub Discussions](https://github.com/enigmora/devtrail/discussions) -3. **File a bug report**: Include error messages and steps to reproduce - ---- - -[← Cookbook](cookbook) | [Contributing →](contributing) diff --git a/docs/index.md b/docs/index.md deleted file mode 100644 index e522763..0000000 --- a/docs/index.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -layout: default -title: Home -nav_order: 1 -description: "Documentation Governance for AI-Assisted Software Development" -permalink: / ---- - -# DevTrail -{: .fs-9 } - -Documentation Governance for AI-Assisted Software Development -{: .fs-6 .fw-300 } - -[Get Started](handbook/getting-started){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 } -[View on GitHub](https://github.com/Enigmora/devtrail){: .btn .fs-5 .mb-4 .mb-md-0 } - ---- - -## Welcome - -DevTrail ensures that every significant change in your codebase—whether made by a human or AI—is **documented, attributed, and reviewable**. - -> **"No significant change without a documented trace."** - ---- - -## Why DevTrail? - -As AI coding assistants become integral to development, critical questions emerge: - -- **Who made this change?** Human or AI? -- **Why was this decision made?** What alternatives were considered? -- **Should this be reviewed?** Is human oversight needed? -- **What's the impact?** How risky is this change? - -DevTrail answers all of these with structured, traceable documentation. - ---- - -## Key Features - -| Feature | Description | -|---------|-------------| -| **8 Document Types** | From requirements (REQ) to ethical reviews (ETH) | -| **AI Agent Support** | Pre-configured for Claude, Cursor, Copilot, and Gemini | -| **Human Oversight** | Built-in review triggers for critical decisions | -| **Validation Tools** | Pre-commit hooks and CI/CD workflows | - ---- - -## Quick Navigation - -| Section | Description | -|---------|-------------| -| [Getting Started](handbook/getting-started) | Install and configure DevTrail | -| [Daily Usage](handbook/daily-usage) | Day-to-day workflow | -| [Document Types](handbook/document-types) | All 8 types explained | -| [AI Configuration](handbook/ai-configuration) | Configure AI agents | -| [Cookbook](handbook/cookbook) | Practical examples | -| [Troubleshooting](handbook/troubleshooting) | Common issues | -| [Contributing](handbook/contributing) | How to contribute | diff --git a/i18n/es/ADOPTION-GUIDE.md b/i18n/es/ADOPTION-GUIDE.md index 06fa63f..7b5b38a 100644 --- a/i18n/es/ADOPTION-GUIDE.md +++ b/i18n/es/ADOPTION-GUIDE.md @@ -2,7 +2,7 @@ **Una guía completa para adoptar DevTrail en proyectos nuevos o existentes.** -[![Enigmora](https://img.shields.io/badge/by-Enigmora-purple.svg)](https://enigmora.com) +[![Strange Days Tech](https://img.shields.io/badge/by-Strange_Days_Tech-purple.svg)](https://strangedays.tech) **Idiomas**: [English](../../ADOPTION-GUIDE.md) | Español @@ -155,68 +155,42 @@ DevTrail se alinea con y soporta cumplimiento para: ## Ruta de Adopción A: Proyectos Nuevos -### Opción 1: Usar como Plantilla de GitHub (Recomendado) +### Opción 1: CLI (Recomendado) -1. **Crear desde plantilla** - - Haz clic en "Use this template" en el [repositorio de DevTrail](https://github.com/enigmora/devtrail-framework) para crear un nuevo repositorio. +```bash +# Instalar el CLI +cargo install devtrail-cli -2. **Clonar tu nuevo repositorio** - ```bash - git clone https://github.com/tu-usuario/tu-nuevo-proyecto.git - cd tu-nuevo-proyecto - ``` +# Inicializar en tu proyecto +cd tu-proyecto +devtrail init . -3. **Eliminar archivos de ejemplo (opcional)** - ```bash - # Mantener la estructura, eliminar contenido de ejemplo - find .devtrail -name "*.md" -path "*-audit/*" -delete - find .devtrail -name "*.md" -path "*requirements/*" -delete - # etc. - ``` +# Commit +git add .devtrail/ DEVTRAIL.md scripts/ +git commit -m "chore: adoptar DevTrail" +``` -4. **Personalizar configuraciones de agente** +El CLI automáticamente: +- Descarga la última versión de DevTrail desde GitHub +- Configura la estructura de directorios `.devtrail/` +- Crea `DEVTRAIL.md` con las reglas de gobernanza +- Configura las directivas de agentes IA (`CLAUDE.md`, `GEMINI.md`, `.cursorrules`, etc.) +- Copia scripts de validación y workflows de CI/CD - Edita los archivos de configuración de agente para que coincidan con el contexto de tu proyecto: - - `CLAUDE.md` - para usuarios de Claude Code - - `GEMINI.md` - para usuarios de Gemini CLI - - `.cursorrules` - para usuarios de Cursor - - `.github/copilot-instructions.md` - para usuarios de Copilot CLI +### Opción 2: Configuración Manual -5. **Inicializar tu documentación** - ```bash - # Crear tu primer requisito - touch .devtrail/01-requirements/REQ-$(date +%Y-%m-%d)-001-requisitos-iniciales.md - ``` +1. **Descargar el último release** -### Opción 2: Configuración Manual + Ve a [GitHub Releases](https://github.com/StrangeDaysTech/devtrail/releases/latest) y descarga el ZIP de distribución. -1. **Descargar DevTrail** +2. **Extraer en tu proyecto** ```bash - # Clonar el repositorio - git clone https://github.com/enigmora/devtrail-framework.git devtrail-temp - - # Copiar a tu proyecto - cp -r devtrail-temp/.devtrail tu-proyecto/ - cp devtrail-temp/CLAUDE.md tu-proyecto/ - cp devtrail-temp/GEMINI.md tu-proyecto/ - cp devtrail-temp/.cursorrules tu-proyecto/ - cp -r devtrail-temp/.github tu-proyecto/ - cp -r devtrail-temp/scripts tu-proyecto/ - - # Limpiar - rm -rf devtrail-temp - ``` - -2. **Agregar a .gitignore (si es necesario)** - ```gitignore - # DevTrail - nada que ignorar por defecto - # Agrega patrones aquí si generas archivos temporales + unzip devtrail-v*.zip -d tu-proyecto/ ``` 3. **Commit de la estructura** ```bash - git add .devtrail/ CLAUDE.md GEMINI.md .cursorrules .github/ scripts/ + git add .devtrail/ DEVTRAIL.md scripts/ git commit -m "chore: adoptar DevTrail para gobernanza de documentación" ``` @@ -247,19 +221,11 @@ DevTrail se alinea con y soporta cumplimiento para: 1. **Agregar estructura DevTrail** ```bash - # Descargar y copiar archivos DevTrail - git clone https://github.com/enigmora/devtrail-framework.git devtrail-temp - - # Copiar estructura (no sobrescribirá archivos existentes) - cp -rn devtrail-temp/.devtrail ./ - cp -n devtrail-temp/CLAUDE.md ./ - cp -n devtrail-temp/GEMINI.md ./ - cp -n devtrail-temp/.cursorrules ./ - mkdir -p .github - cp -rn devtrail-temp/.github/* ./.github/ - cp -rn devtrail-temp/scripts ./ - - rm -rf devtrail-temp + # Usando CLI (recomendado) + devtrail init . + + # O manualmente: descargar desde GitHub Releases + # https://github.com/StrangeDaysTech/devtrail/releases/latest ``` 2. **Resolver conflictos con `docs/` existente** @@ -510,8 +476,8 @@ R: Las reglas de DevTrail son instrucciones, no cumplimiento forzado. Si un asis ## Obtener Ayuda -- **Issues**: [GitHub Issues](https://github.com/enigmora/devtrail-framework/issues) -- **Discusiones**: [GitHub Discussions](https://github.com/enigmora/devtrail-framework/discussions) +- **Issues**: [GitHub Issues](https://github.com/StrangeDaysTech/devtrail/issues) +- **Discusiones**: [GitHub Discussions](https://github.com/StrangeDaysTech/devtrail/discussions) - **Contribuir**: Ver [CONTRIBUTING.md](CONTRIBUTING.md) --- @@ -520,6 +486,6 @@ R: Las reglas de DevTrail son instrucciones, no cumplimiento forzado. Si un asis **DevTrail** — Porque cada cambio cuenta una historia. -[Volver al README](README.md) • [Enigmora](https://enigmora.com) +[Volver al README](README.md) • [Strange Days Tech](https://strangedays.tech) diff --git a/i18n/es/CODE_OF_CONDUCT.md b/i18n/es/CODE_OF_CONDUCT.md index f841687..1df57ed 100644 --- a/i18n/es/CODE_OF_CONDUCT.md +++ b/i18n/es/CODE_OF_CONDUCT.md @@ -53,7 +53,7 @@ Este Código de Conducta también aplica cuando un individuo representa oficialm Si experimentas o presencias comportamiento inaceptable, o tienes cualquier otra preocupación, por favor repórtalo contactando al equipo del proyecto en: -**Email**: [contacto@enigmora.com](mailto:contacto@enigmora.com) +**GitHub Issues**: [Reportar aquí](https://github.com/StrangeDaysTech/devtrail/issues) Todos los reportes serán revisados e investigados de manera pronta y justa. @@ -101,7 +101,7 @@ Los líderes de la comunidad seguirán estas Guías de Impacto Comunitario para ## Apelaciones -Si crees que has sido acusado falsa o injustamente de violar este Código de Conducta, puedes apelar enviando una explicación detallada a [contacto@enigmora.com](mailto:contacto@enigmora.com). Las apelaciones serán revisadas por un líder de la comunidad diferente al que tomó la decisión original. +Si crees que has sido acusado falsa o injustamente de violar este Código de Conducta, puedes apelar abriendo un issue detallado en [GitHub Issues](https://github.com/StrangeDaysTech/devtrail/issues). Las apelaciones serán revisadas por un líder de la comunidad diferente al que tomó la decisión original. ## Atribución @@ -129,5 +129,5 @@ Para respuestas a preguntas comunes sobre este código de conducta, ver las FAQ

DevTrail
Construyendo una comunidad inclusiva juntos
- Enigmora SC + Strange Days Tech, S.A.S.

diff --git a/i18n/es/CONTRIBUTING.md b/i18n/es/CONTRIBUTING.md index d190d49..c483655 100644 --- a/i18n/es/CONTRIBUTING.md +++ b/i18n/es/CONTRIBUTING.md @@ -270,12 +270,39 @@ Las plantillas deben incluir: --- +## Desarrollo del CLI + +El CLI de DevTrail está escrito en Rust y se encuentra en el directorio `cli/`. + +### Compilar + +```bash +cd cli +cargo build +``` + +### Ejecutar Tests + +```bash +cd cli +cargo test +``` + +### Build de Release + +```bash +cd cli +cargo build --release +``` + +--- + ## ¿Preguntas? Si tienes preguntas sobre contribuir: -1. Revisa [Issues](https://github.com/enigmora/devtrail-framework/issues) existentes -2. Revisa [Discussions](https://github.com/enigmora/devtrail-framework/discussions) +1. Revisa [Issues](https://github.com/StrangeDaysTech/devtrail/issues) existentes +2. Revisa [Discussions](https://github.com/StrangeDaysTech/devtrail/discussions) 3. Abre una nueva Discussion para preguntas generales 4. Abre un Issue para bugs o características específicas @@ -295,4 +322,4 @@ Los contribuidores son reconocidos en: *DevTrail — Porque cada cambio cuenta una historia.* -[Enigmora](https://enigmora.com) +[Strange Days Tech](https://strangedays.tech) diff --git a/i18n/es/README.md b/i18n/es/README.md index 6174322..c46e454 100644 --- a/i18n/es/README.md +++ b/i18n/es/README.md @@ -7,7 +7,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) [![Documentation](https://img.shields.io/badge/docs-ADOPTION--GUIDE-orange.svg)](ADOPTION-GUIDE.md) -[![Enigmora](https://img.shields.io/badge/by-Enigmora-purple.svg)](https://enigmora.com) +[![Strange Days Tech](https://img.shields.io/badge/by-Strange_Days_Tech-purple.svg)](https://strangedays.tech) [Inicio Rápido](#inicio-rápido) • [Características](#características) • @@ -93,46 +93,40 @@ Herramientas de validación automatizadas: ## Inicio Rápido -### Inicio Rápido (Proyecto Nuevo) +### Opción 1: CLI (Recomendado) -**Opción 1: Usar como Plantilla** (Recomendado) +```bash +# Instalar el CLI +cargo install devtrail-cli -Haz clic en el botón **"Use this template"** arriba para crear un nuevo repositorio con DevTrail pre-configurado. +# Inicializar en tu proyecto +cd tu-proyecto +devtrail init . +``` -**Opción 2: Clonar y Copiar** +El CLI descarga la última versión de DevTrail, configura el framework y los archivos de directivas de agentes IA automáticamente. ```bash -# Clonar DevTrail -git clone https://github.com/enigmora/devtrail-framework.git - -# Copiar a tu proyecto -cp -r devtrail-framework/.devtrail tu-proyecto/ -cp devtrail-framework/CLAUDE.md tu-proyecto/ -cp devtrail-framework/GEMINI.md tu-proyecto/ -cp devtrail-framework/.cursorrules tu-proyecto/ -cp -r devtrail-framework/.github tu-proyecto/ -cp -r devtrail-framework/scripts tu-proyecto/ +# Actualizar a la última versión +devtrail update + +# Eliminar DevTrail +devtrail remove ``` -### Inicio Rápido (Proyecto Existente) +### Opción 2: Configuración Manual ```bash -# Descargar DevTrail -git clone https://github.com/enigmora/devtrail-framework.git devtrail-temp +# Descargar el último release ZIP de GitHub +# https://github.com/StrangeDaysTech/devtrail/releases/latest -# Copiar sin sobrescribir (Linux/Mac) -cp -rn devtrail-temp/.devtrail ./ -cp -n devtrail-temp/CLAUDE.md ./ -cp -n devtrail-temp/GEMINI.md ./ -cp -n devtrail-temp/.cursorrules ./ -cp -rn devtrail-temp/.github ./ -cp -rn devtrail-temp/scripts ./ - -# Limpiar -rm -rf devtrail-temp +# Extraer y copiar a tu proyecto +cp -r .devtrail tu-proyecto/ +cp DEVTRAIL.md tu-proyecto/ +cp -r scripts tu-proyecto/ # Commit -git add .devtrail/ CLAUDE.md GEMINI.md .cursorrules .github/ scripts/ +git add .devtrail/ DEVTRAIL.md scripts/ git commit -m "chore: adoptar DevTrail" ``` @@ -427,15 +421,13 @@ Este proyecto está licenciado bajo la Licencia MIT - ver el archivo [LICENSE](. --- -## Acerca de Enigmora +## Acerca de Strange Days Tech, S.A.S.
-Enigmora Logo - -**[Enigmora](https://enigmora.com)** construye herramientas para desarrollo de software responsable asistido por IA. +**[Strange Days Tech](https://strangedays.tech)** construye herramientas para desarrollo de software responsable asistido por IA. DevTrail es uno de nuestros proyectos de código abierto. -[Sitio Web](https://enigmora.com) • [GitHub](https://github.com/enigmora) +[Sitio Web](https://strangedays.tech) • [GitHub](https://github.com/StrangeDaysTech)
@@ -445,6 +437,6 @@ Este proyecto está licenciado bajo la Licencia MIT - ver el archivo [LICENSE](. **DevTrail** — Porque cada cambio cuenta una historia. -[Volver arriba](#enigmora-devtrail-framework) +[Volver arriba](#devtrail) diff --git a/scripts/pre-commit-docs.sh b/scripts/pre-commit-docs.sh index ca7f5c3..9b50dde 100644 --- a/scripts/pre-commit-docs.sh +++ b/scripts/pre-commit-docs.sh @@ -2,7 +2,7 @@ # ============================================================================= # DevTrail - Pre-commit Hook for Documentation Validation -# https://enigmora.com +# https://strangedays.tech # ============================================================================= # # Installation: diff --git a/scripts/validate-docs.ps1 b/scripts/validate-docs.ps1 index c061775..ada8b78 100644 --- a/scripts/validate-docs.ps1 +++ b/scripts/validate-docs.ps1 @@ -1,6 +1,6 @@ # ============================================================================= # DevTrail - Documentation Validation Script (PowerShell) -# https://enigmora.com +# https://strangedays.tech # ============================================================================= # # Usage: