create-quiver 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +15 -0
  2. package/.github/ISSUE_TEMPLATE/feature_request.md +15 -0
  3. package/.github/pull_request_template.md +4 -0
  4. package/.github/workflows/ci.yml +74 -0
  5. package/CHANGELOG.md +24 -0
  6. package/CODE_OF_CONDUCT.md +12 -0
  7. package/CONTRIBUTING.md +15 -0
  8. package/LICENSE +21 -0
  9. package/README.md +118 -0
  10. package/README_FOR_AI.md +90 -0
  11. package/ROADMAP.md +20 -0
  12. package/SECURITY.md +12 -0
  13. package/TEMPLATE.md +108 -0
  14. package/bin/create-quiver.js +8 -0
  15. package/docs/CONTEXTO.md.template +45 -0
  16. package/docs/DOCUMENTATION_GUIDE.md.template +34 -0
  17. package/docs/GITFLOW_PR_GUIDE.md.template +52 -0
  18. package/docs/INDEX.md.template +41 -0
  19. package/docs/MOCK_DATA_GUIDE.md.template +31 -0
  20. package/docs/MULTI_AGENT_WORKFLOW.md.template +31 -0
  21. package/docs/STATUS.md.template +26 -0
  22. package/docs/SUPPORT_MATRIX.md.template +31 -0
  23. package/docs/TESTING_GUIDE_FOR_AI.md.template +42 -0
  24. package/docs/TROUBLESHOOTING.md.template +70 -0
  25. package/docs/UI_STANDARDS.md.template +31 -0
  26. package/docs/WORKFLOW.md.template +56 -0
  27. package/docs/ai/LESSONS.md.template +24 -0
  28. package/docs/ai/PRINCIPLES.md +25 -0
  29. package/docs/ai/RULES.yaml +33 -0
  30. package/i18n/es/README.md +15 -0
  31. package/i18n/es/README_FOR_AI.md +6 -0
  32. package/i18n/es/TEMPLATE.md +18 -0
  33. package/i18n/es/docs/CONTEXTO.md.template +9 -0
  34. package/i18n/es/docs/DOCUMENTATION_GUIDE.md.template +4 -0
  35. package/i18n/es/docs/GITFLOW_PR_GUIDE.md.template +4 -0
  36. package/i18n/es/docs/INDEX.md.template +10 -0
  37. package/i18n/es/docs/MOCK_DATA_GUIDE.md.template +4 -0
  38. package/i18n/es/docs/MULTI_AGENT_WORKFLOW.md.template +4 -0
  39. package/i18n/es/docs/STATUS.md.template +9 -0
  40. package/i18n/es/docs/TESTING_GUIDE_FOR_AI.md.template +7 -0
  41. package/i18n/es/docs/UI_STANDARDS.md.template +4 -0
  42. package/i18n/es/docs/WORKFLOW.md.template +6 -0
  43. package/i18n/es/docs/ai/LESSONS.md.template +3 -0
  44. package/i18n/es/docs/ai/PRINCIPLES.md +7 -0
  45. package/i18n/es/docs/ai/RULES.yaml +7 -0
  46. package/package.json +19 -0
  47. package/package.template.json +10 -0
  48. package/scripts/check-pr-readiness.sh +138 -0
  49. package/scripts/check-scope.sh +150 -0
  50. package/scripts/check-slice-readiness.sh +319 -0
  51. package/scripts/cleanup-slice.sh +177 -0
  52. package/scripts/init-docs.sh +368 -0
  53. package/scripts/migrate-project.sh +218 -0
  54. package/scripts/package-quiver.sh +124 -0
  55. package/scripts/refresh-active-slices.sh +232 -0
  56. package/scripts/release-quiver.sh +77 -0
  57. package/scripts/start-slice.sh +429 -0
  58. package/specs/[project-name]/EVIDENCE_REPORT.md.template +15 -0
  59. package/specs/[project-name]/SPEC.md.template +39 -0
  60. package/specs/[project-name]/STATUS.md.template +22 -0
  61. package/specs/[project-name]/slices/pr.md.template +97 -0
  62. package/specs/[project-name]/slices/slice-template/slice.json +69 -0
  63. package/specs/quiver-v05-readme-adoption-contract/EVIDENCE_REPORT.md +21 -0
  64. package/specs/quiver-v05-readme-adoption-contract/SPEC.md +40 -0
  65. package/specs/quiver-v05-readme-adoption-contract/STATUS.md +24 -0
  66. package/specs/quiver-v05-readme-adoption-contract/slices/slice-01-readme-adoption-contract/slice.json +68 -0
  67. package/specs/quiver-v06-release-readiness/EVIDENCE_REPORT.md +23 -0
  68. package/specs/quiver-v06-release-readiness/SPEC.md +40 -0
  69. package/specs/quiver-v06-release-readiness/STATUS.md +24 -0
  70. package/specs/quiver-v06-release-readiness/slices/slice-01-first-npm-release-readiness/slice.json +71 -0
  71. package/src/create-quiver/index.js +329 -0
@@ -0,0 +1,218 @@
1
+ #!/bin/bash
2
+
3
+ # Script de Migración de Proyecto Existente
4
+ # Uso: ./migrate-project.sh
5
+ # Propósito: Migrar proyecto existente a la nueva estructura de docs-template
6
+
7
+ set -e
8
+
9
+ # Colores para output
10
+ RED='\033[0;31m'
11
+ GREEN='\033[0;32m'
12
+ YELLOW='\033[1;33m'
13
+ BLUE='\033[0;34m'
14
+ NC='\033[0m' # No Color
15
+
16
+ # Función para imprimir mensajes
17
+ print_info() {
18
+ echo -e "${BLUE}ℹ️ $1${NC}"
19
+ }
20
+
21
+ print_success() {
22
+ echo -e "${GREEN}✅ $1${NC}"
23
+ }
24
+
25
+ print_warning() {
26
+ echo -e "${YELLOW}⚠️ $1${NC}"
27
+ }
28
+
29
+ print_error() {
30
+ echo -e "${RED}❌ $1${NC}"
31
+ }
32
+
33
+ # Verificar que existe docs/ y docs-template/
34
+ if [ ! -d "docs" ]; then
35
+ print_error "No se encontró docs/"
36
+ print_error "Este script es para migrar proyectos existentes"
37
+ exit 1
38
+ fi
39
+
40
+ if [ ! -d "docs-template" ]; then
41
+ print_error "No se encontró docs-template/"
42
+ print_error "Asegurate de estar en el directorio correcto"
43
+ exit 1
44
+ fi
45
+
46
+ print_info "Iniciando migración de documentación..."
47
+
48
+ # Crear backup
49
+ BACKUP_DIR="docs-backup-$(date +%Y%m%d-%H%M%S)"
50
+ print_info "Creando backup en: $BACKUP_DIR"
51
+ cp -r docs "$BACKUP_DIR"
52
+ print_success "Backup creado: $BACKUP_DIR"
53
+
54
+ # Crear directorios necesarios
55
+ print_info "Creando nueva estructura..."
56
+ mkdir -p "docs/tools/playwright"
57
+ mkdir -p "docs/archive"
58
+ mkdir -p "docs/archive/analysis"
59
+
60
+ # ==========================================
61
+ # FASE 1: Mover documentación de herramientas a docs/tools/
62
+ # ==========================================
63
+ print_info "Fase 1: Moviendo documentación de herramientas..."
64
+
65
+ # Mover archivos de Playwright
66
+ if [ -f "docs/PLAYWRIGHT_CLI_COMMANDS.md" ]; then
67
+ mv "docs/PLAYWRIGHT_CLI_COMMANDS.md" "docs/tools/playwright/CLI_COMMANDS.md"
68
+ print_success "Movido: PLAYWRIGHT_CLI_COMMANDS.md → tools/playwright/CLI_COMMANDS.md"
69
+ fi
70
+
71
+ if [ -f "docs/PLAYWRIGHT_CLI_QWEN_CODE.md" ]; then
72
+ mv "docs/PLAYWRIGHT_CLI_QWEN_CODE.md" "docs/tools/playwright/QWEN_CODE.md"
73
+ print_success "Movido: PLAYWRIGHT_CLI_QWEN_CODE.md → tools/playwright/QWEN_CODE.md"
74
+ fi
75
+
76
+ if [ -f "docs/PLAYWRIGHT_CLI_SKILL.md" ]; then
77
+ mv "docs/PLAYWRIGHT_CLI_SKILL.md" "docs/tools/playwright/SKILL.md"
78
+ print_success "Movido: PLAYWRIGHT_CLI_SKILL.md → tools/playwright/SKILL.md"
79
+ fi
80
+
81
+ if [ -f "docs/PLAYWRIGHT_BEST_PRACTICES.md" ]; then
82
+ mv "docs/PLAYWRIGHT_BEST_PRACTICES.md" "docs/tools/playwright/BEST_PRACTICES.md"
83
+ print_success "Movido: PLAYWRIGHT_BEST_PRACTICES.md → tools/playwright/BEST_PRACTICES.md"
84
+ fi
85
+
86
+ if [ -f "docs/PLAYWRIGHT_CLI_IMPLEMENTATION_PLAN.md" ]; then
87
+ mv "docs/PLAYWRIGHT_CLI_IMPLEMENTATION_PLAN.md" "docs/archive/PLAYWRIGHT_CLI_IMPLEMENTATION_PLAN.md"
88
+ print_success "Movido: PLAYWRIGHT_CLI_IMPLEMENTATION_PLAN.md → archive/"
89
+ fi
90
+
91
+ if [ -f "docs/PLAYWRIGHT_CLI_STATUS.md" ]; then
92
+ mv "docs/PLAYWRIGHT_CLI_STATUS.md" "docs/archive/PLAYWRIGHT_CLI_STATUS.md"
93
+ print_success "Movido: PLAYWRIGHT_CLI_STATUS.md → archive/"
94
+ fi
95
+
96
+ # ==========================================
97
+ # FASE 2: Mover archivos históricos a archive/
98
+ # ==========================================
99
+ print_info "Fase 2: Moviendo archivos históricos a archive/..."
100
+
101
+ if [ -f "docs/DOCUMENTATION_AUDIT.md" ]; then
102
+ mv "docs/DOCUMENTATION_AUDIT.md" "docs/archive/DOCUMENTATION_AUDIT.md"
103
+ print_success "Movido: DOCUMENTATION_AUDIT.md → archive/"
104
+ fi
105
+
106
+ if [ -f "docs/CLEANUP_SUMMARY.md" ]; then
107
+ mv "docs/CLEANUP_SUMMARY.md" "docs/archive/CLEANUP_SUMMARY.md"
108
+ print_success "Movido: CLEANUP_SUMMARY.md → archive/"
109
+ fi
110
+
111
+ # ==========================================
112
+ # FASE 3: Actualizar INDEX.md con nueva estructura
113
+ # ==========================================
114
+ print_info "Fase 3: Actualizando INDEX.md..."
115
+
116
+ if [ -f "docs/INDEX.md" ]; then
117
+ # Agregar sección de tools si no existe
118
+ if ! grep -q "Tools" "docs/INDEX.md"; then
119
+ # Buscar la línea de "Histórico" y agregar Tools antes
120
+ sed -i.bak '/Histórico/i\
121
+ ### Herramientas\
122
+ \
123
+ - **[Tools](./tools/)** - Documentación de herramientas (Playwright, ESLint, etc.)\
124
+ ' "docs/INDEX.md"
125
+ rm "docs/INDEX.md.bak" 2>/dev/null || true
126
+ print_success "Actualizado: INDEX.md (agregada sección Tools)"
127
+ fi
128
+ fi
129
+
130
+ # ==========================================
131
+ # FASE 4: Crear README en tools/
132
+ # ==========================================
133
+ print_info "Fase 4: Creando README en tools/..."
134
+
135
+ if [ ! -f "docs/tools/README.md" ]; then
136
+ cat > "docs/tools/README.md" << 'EOF'
137
+ # Tools Documentation
138
+
139
+ Documentación de herramientas específicas del proyecto.
140
+
141
+ ## Herramientas
142
+
143
+ - **[Playwright](./playwright/)** - Testing E2E
144
+
145
+ ## Agregar Nueva Herramienta
146
+
147
+ 1. Crear directorio: `mkdir docs/tools/[nombre]`
148
+ 2. Agregar README.md con documentación
149
+ 3. Actualizar este archivo
150
+
151
+ EOF
152
+ print_success "Creado: docs/tools/README.md"
153
+ fi
154
+
155
+ # ==========================================
156
+ # FASE 5: Crear README en archive/
157
+ # ==========================================
158
+ print_info "Fase 5: Creando README en archive/..."
159
+
160
+ if [ ! -f "docs/archive/README.md" ]; then
161
+ cat > "docs/archive/README.md" << 'EOF'
162
+ # Archive
163
+
164
+ Documentación histórica y planes que ya no están activos.
165
+
166
+ **No leer a menos que sea necesario para contexto histórico.**
167
+
168
+ ## Contenido
169
+
170
+ - **Analysis** - Análisis y auditorías históricas
171
+ - **Plans** - Planes que ya se ejecutaron o cancelaron
172
+ - **Old Specs** - Specs viejos reemplazados
173
+
174
+ EOF
175
+ print_success "Creado: docs/archive/README.md"
176
+ fi
177
+
178
+ # ==========================================
179
+ # FASE 6: Validar estructura
180
+ # ==========================================
181
+ print_info "Fase 6: Validando estructura..."
182
+
183
+ echo ""
184
+ print_info "Estructura final:"
185
+ echo ""
186
+ echo "docs/"
187
+ echo "├── Core (activos)"
188
+ echo "│ ├── INDEX.md"
189
+ echo "│ ├── CONTEXTO.md"
190
+ echo "│ ├── STATUS.md"
191
+ echo "│ ├── WORKFLOW.md"
192
+ echo "│ └── ai/"
193
+ echo "├── Tools (herramientas)"
194
+ echo "│ └── playwright/"
195
+ echo "├── Archive (histórico)"
196
+ echo "│ ├── analysis/"
197
+ echo "│ └── [archivos históricos]"
198
+ echo "└── [otros archivos específicos del proyecto]"
199
+ echo ""
200
+
201
+ # ==========================================
202
+ # Resumen
203
+ # ==========================================
204
+ echo ""
205
+ print_success "¡Migración completada!"
206
+ echo ""
207
+ echo "📁 Resumen de cambios:"
208
+ echo " - Documentación de herramientas → docs/tools/"
209
+ echo " - Archivos históricos → docs/archive/"
210
+ echo " - Backup creado → $BACKUP_DIR"
211
+ echo ""
212
+ echo "📝 Próximos pasos:"
213
+ echo " 1. Verificar que todos los links en INDEX.md funcionen"
214
+ echo " 2. Actualizar referencias a archivos movidos"
215
+ echo " 3. Eliminar backup cuando estés seguro: rm -rf $BACKUP_DIR"
216
+ echo ""
217
+ print_warning "Importante: Verificar que no haya links rotos"
218
+ echo ""
@@ -0,0 +1,124 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -euo pipefail
4
+
5
+ repo_root="$(git rev-parse --show-toplevel)"
6
+ temp_root="$(mktemp -d "${TMPDIR:-/tmp}/quiver-pack.XXXXXX")"
7
+ pack_dir="$temp_root/pack"
8
+ npm_cache="$temp_root/npm-cache"
9
+
10
+ cleanup() {
11
+ rm -rf "$temp_root"
12
+ }
13
+
14
+ trap cleanup EXIT
15
+
16
+ mkdir -p "$pack_dir"
17
+ mkdir -p "$npm_cache"
18
+
19
+ pack_json="$(
20
+ cd "$repo_root" && npm_config_cache="$npm_cache" npm pack --json --pack-destination "$pack_dir"
21
+ )"
22
+
23
+ tarball_name="$(
24
+ node -e 'const data = JSON.parse(process.argv[1]); process.stdout.write(data[0].filename);' "$pack_json"
25
+ )"
26
+ tarball_path="$pack_dir/$tarball_name"
27
+
28
+ if [[ ! -f "$tarball_path" ]]; then
29
+ echo "FAIL: no se encontró el tarball generado en $tarball_path" >&2
30
+ exit 1
31
+ fi
32
+
33
+ contents="$(
34
+ tar -tzf "$tarball_path"
35
+ )"
36
+
37
+ require_present() {
38
+ local path="$1"
39
+
40
+ if ! printf '%s\n' "$contents" | grep -Fxq "$path"; then
41
+ echo "FAIL: falta '$path' en el paquete" >&2
42
+ exit 1
43
+ fi
44
+ }
45
+
46
+ require_absent() {
47
+ local path="$1"
48
+
49
+ if printf '%s\n' "$contents" | grep -Fxq "$path"; then
50
+ echo "FAIL: '$path' no debería publicarse en el paquete" >&2
51
+ exit 1
52
+ fi
53
+ }
54
+
55
+ required_paths=(
56
+ "package/package.json"
57
+ "package/bin/create-quiver.js"
58
+ "package/src/create-quiver/index.js"
59
+ "package/README.md"
60
+ "package/README_FOR_AI.md"
61
+ "package/TEMPLATE.md"
62
+ "package/LICENSE"
63
+ "package/CONTRIBUTING.md"
64
+ "package/CODE_OF_CONDUCT.md"
65
+ "package/SECURITY.md"
66
+ "package/CHANGELOG.md"
67
+ "package/ROADMAP.md"
68
+ "package/.github/pull_request_template.md"
69
+ "package/.github/ISSUE_TEMPLATE/bug_report.md"
70
+ "package/.github/ISSUE_TEMPLATE/feature_request.md"
71
+ "package/.github/workflows/ci.yml"
72
+ "package/docs/INDEX.md.template"
73
+ "package/docs/DOCUMENTATION_GUIDE.md.template"
74
+ "package/docs/WORKFLOW.md.template"
75
+ "package/docs/SUPPORT_MATRIX.md.template"
76
+ "package/docs/TROUBLESHOOTING.md.template"
77
+ "package/docs/TESTING_GUIDE_FOR_AI.md.template"
78
+ "package/docs/ai/PRINCIPLES.md"
79
+ "package/docs/ai/RULES.yaml"
80
+ "package/docs/ai/LESSONS.md.template"
81
+ "package/specs/[project-name]/SPEC.md.template"
82
+ "package/specs/[project-name]/STATUS.md.template"
83
+ "package/specs/[project-name]/EVIDENCE_REPORT.md.template"
84
+ "package/specs/[project-name]/slices/pr.md.template"
85
+ "package/specs/[project-name]/slices/slice-template/slice.json"
86
+ "package/scripts/init-docs.sh"
87
+ "package/scripts/start-slice.sh"
88
+ "package/scripts/check-slice-readiness.sh"
89
+ "package/scripts/check-pr-readiness.sh"
90
+ "package/scripts/check-scope.sh"
91
+ "package/scripts/cleanup-slice.sh"
92
+ "package/scripts/release-quiver.sh"
93
+ "package/scripts/refresh-active-slices.sh"
94
+ "package/scripts/migrate-project.sh"
95
+ "package/scripts/package-quiver.sh"
96
+ "package/i18n/es/README.md"
97
+ "package/i18n/es/README_FOR_AI.md"
98
+ "package/i18n/es/TEMPLATE.md"
99
+ )
100
+
101
+ for path in "${required_paths[@]}"; do
102
+ require_present "$path"
103
+ done
104
+
105
+ excluded_paths=(
106
+ "package/package-lock.json"
107
+ "package/tests/"
108
+ "package/examples/"
109
+ "package/.worktrees/"
110
+ "package/specs/quiver-v01/"
111
+ "package/specs/quiver-v02-bootstrap-hardening/"
112
+ "package/specs/quiver-v03-adoption-verification/"
113
+ "package/specs/quiver-v04-zero-friction-installation/"
114
+ "package/scripts/ci/"
115
+ )
116
+
117
+ for path in "${excluded_paths[@]}"; do
118
+ if printf '%s\n' "$contents" | grep -Fq "$path"; then
119
+ echo "FAIL: el paquete incluye contenido fuera del contrato: $path" >&2
120
+ exit 1
121
+ fi
122
+ done
123
+
124
+ printf 'Package smoke passed: %s\n' "$tarball_name"
@@ -0,0 +1,232 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -euo pipefail
4
+
5
+ repo_root="$(git rev-parse --show-toplevel)"
6
+ output_path="$repo_root/ACTIVE_SLICES.md"
7
+
8
+ append_unique_line() {
9
+ local file_path="$1"
10
+ local line="$2"
11
+
12
+ touch "$file_path"
13
+
14
+ if ! grep -Fxq "$line" "$file_path"; then
15
+ printf '%s\n' "$line" >> "$file_path"
16
+ fi
17
+ }
18
+
19
+ exclude_path="$(git -C "$repo_root" rev-parse --git-path info/exclude)"
20
+ append_unique_line "$exclude_path" "ACTIVE_SLICES.md"
21
+
22
+ node - "$repo_root" "$output_path" <<'NODE'
23
+ const fs = require('fs');
24
+ const path = require('path');
25
+ const cp = require('child_process');
26
+
27
+ const [repoRoot, outputPath] = process.argv.slice(2);
28
+
29
+ function run(cmd) {
30
+ return cp.execSync(cmd, {
31
+ cwd: repoRoot,
32
+ encoding: 'utf8',
33
+ stdio: ['ignore', 'pipe', 'pipe']
34
+ });
35
+ }
36
+
37
+ function walkSlices(rootDir, acc) {
38
+ if (!fs.existsSync(rootDir)) {
39
+ return;
40
+ }
41
+
42
+ for (const entry of fs.readdirSync(rootDir, { withFileTypes: true })) {
43
+ const fullPath = path.join(rootDir, entry.name);
44
+ if (entry.isDirectory()) {
45
+ walkSlices(fullPath, acc);
46
+ continue;
47
+ }
48
+
49
+ if (entry.isFile() && entry.name === 'slice.json' && fullPath.includes(`${path.sep}slices${path.sep}`)) {
50
+ const json = JSON.parse(fs.readFileSync(fullPath, 'utf8'));
51
+ const relPath = path.relative(repoRoot, fullPath);
52
+ const parts = relPath.split(path.sep);
53
+ const specFamily = parts[0];
54
+ const specSlug = parts[1];
55
+ const branchName = json.git?.branch_name;
56
+ if (!branchName) {
57
+ continue;
58
+ }
59
+
60
+ acc.set(branchName, {
61
+ specFamily,
62
+ specSlug,
63
+ relPath,
64
+ sliceId: json.slice_id || path.basename(path.dirname(fullPath)),
65
+ title: json.title || json.slice_id || path.basename(path.dirname(fullPath)),
66
+ ticket: json.ticket || '',
67
+ status: json.status || 'pending'
68
+ });
69
+ }
70
+ }
71
+ }
72
+
73
+ function parseWorktrees(text) {
74
+ const entries = [];
75
+ const chunks = text.trim().split('\n\n').filter(Boolean);
76
+ for (const chunk of chunks) {
77
+ const lines = chunk.split('\n');
78
+ const entry = {};
79
+ for (const line of lines) {
80
+ const idx = line.indexOf(' ');
81
+ if (idx === -1) {
82
+ continue;
83
+ }
84
+ const key = line.slice(0, idx);
85
+ const value = line.slice(idx + 1);
86
+ entry[key] = value;
87
+ }
88
+ entries.push(entry);
89
+ }
90
+ return entries;
91
+ }
92
+
93
+ function toAlias(ticket) {
94
+ const parts = String(ticket || '').split('-').filter(Boolean);
95
+ const prefix = (parts[0] || 'GEN').replace(/[^A-Za-z0-9]/g, '').toUpperCase();
96
+ const suffix = (parts[parts.length - 1] || '00').replace(/[^A-Za-z0-9]/g, '').toUpperCase();
97
+ const short = prefix.length <= 3 ? prefix : prefix.slice(0, 3);
98
+ return `${short || 'GEN'}-${suffix || '00'}`;
99
+ }
100
+
101
+ function mdEscape(value) {
102
+ return String(value ?? '').replace(/\|/g, '\\|');
103
+ }
104
+
105
+ const sliceMap = new Map();
106
+ walkSlices(path.join(repoRoot, 'specs'), sliceMap);
107
+ walkSlices(path.join(repoRoot, 'specs-fix'), sliceMap);
108
+
109
+ const worktrees = parseWorktrees(run('git worktree list --porcelain'));
110
+
111
+ const primary = [];
112
+ const active = [];
113
+ const frozen = [];
114
+ const auxiliary = [];
115
+
116
+ for (const entry of worktrees) {
117
+ const worktreePath = entry.worktree;
118
+ const branchRef = entry.branch || '';
119
+ const branchName = branchRef.replace('refs/heads/', '');
120
+
121
+ if (worktreePath === repoRoot) {
122
+ primary.push({
123
+ branch: branchName || '(detached)',
124
+ path: worktreePath
125
+ });
126
+ continue;
127
+ }
128
+
129
+ const slice = sliceMap.get(branchName);
130
+ if (!slice) {
131
+ auxiliary.push({
132
+ branch: branchName || '(detached)',
133
+ path: worktreePath
134
+ });
135
+ continue;
136
+ }
137
+
138
+ let liveStatus = slice.status;
139
+ const liveSlicePath = path.join(worktreePath, slice.relPath);
140
+ if (fs.existsSync(liveSlicePath)) {
141
+ try {
142
+ const liveJson = JSON.parse(fs.readFileSync(liveSlicePath, 'utf8'));
143
+ liveStatus = liveJson.status || liveStatus;
144
+ } catch {}
145
+ }
146
+
147
+ const row = {
148
+ alias: toAlias(slice.ticket),
149
+ spec: slice.specSlug,
150
+ slice: slice.sliceId,
151
+ branch: branchName,
152
+ path: worktreePath,
153
+ status: liveStatus,
154
+ title: slice.title
155
+ };
156
+
157
+ if (slice.sliceId.startsWith('slice-00')) {
158
+ frozen.push(row);
159
+ } else {
160
+ active.push(row);
161
+ }
162
+ }
163
+
164
+ active.sort((a, b) => a.alias.localeCompare(b.alias));
165
+ frozen.sort((a, b) => a.alias.localeCompare(b.alias));
166
+ auxiliary.sort((a, b) => a.branch.localeCompare(b.branch));
167
+
168
+ const lines = [
169
+ '# Active Slices',
170
+ '',
171
+ '> Archivo local generado por `tools/scripts/refresh-active-slices.sh`.',
172
+ '> No se trackea en git.',
173
+ '',
174
+ `**Actualizado:** ${new Date().toISOString()}`,
175
+ '',
176
+ '## Convencion',
177
+ '',
178
+ '- `Alias`: identificador corto para hablar del slice sin ambiguedad',
179
+ '- `Spec`: directorio del spec',
180
+ '- `slice-00`: baseline congelado, solo referencia',
181
+ '- `slice-01+`: implementacion o revalidacion',
182
+ '',
183
+ '## Checkout Principal',
184
+ '',
185
+ '| Branch | Path |',
186
+ '|--------|------|'
187
+ ];
188
+
189
+ for (const row of primary) {
190
+ lines.push(`| ${mdEscape(row.branch)} | ${mdEscape(row.path)} |`);
191
+ }
192
+
193
+ lines.push('', '## Implementacion Activa', '', '| Alias | Spec | Slice | Branch | Estado | Path |', '|-------|------|-------|--------|--------|------|');
194
+ if (active.length === 0) {
195
+ lines.push('| - | - | - | - | - | - |');
196
+ } else {
197
+ for (const row of active) {
198
+ lines.push(`| ${mdEscape(row.alias)} | ${mdEscape(row.spec)} | ${mdEscape(row.slice)} | ${mdEscape(row.branch)} | ${mdEscape(row.status)} | ${mdEscape(row.path)} |`);
199
+ }
200
+ }
201
+
202
+ lines.push('', '## Baselines Congelados', '', '| Alias | Spec | Slice | Branch | Estado | Path |', '|-------|------|-------|--------|--------|------|');
203
+ if (frozen.length === 0) {
204
+ lines.push('| - | - | - | - | - | - |');
205
+ } else {
206
+ for (const row of frozen) {
207
+ lines.push(`| ${mdEscape(row.alias)} | ${mdEscape(row.spec)} | ${mdEscape(row.slice)} | ${mdEscape(row.branch)} | congelado | ${mdEscape(row.path)} |`);
208
+ }
209
+ }
210
+
211
+ lines.push('', '## Worktrees Auxiliares', '', '| Branch | Path |', '|--------|------|');
212
+ if (auxiliary.length === 0) {
213
+ lines.push('| - | - |');
214
+ } else {
215
+ for (const row of auxiliary) {
216
+ lines.push(`| ${mdEscape(row.branch)} | ${mdEscape(row.path)} |`);
217
+ }
218
+ }
219
+
220
+ lines.push(
221
+ '',
222
+ '## Recomendacion Operativa',
223
+ '',
224
+ '- En VS Code, dejar visibles solo `develop` y la tabla de `Implementacion Activa`.',
225
+ '- Tratar la tabla de `Baselines Congelados` como solo lectura.',
226
+ '- Cerrar visualmente los `Worktrees Auxiliares` salvo cuando estes trabajando ese PR o esa tarea de proceso.'
227
+ );
228
+
229
+ fs.writeFileSync(outputPath, `${lines.join('\n')}\n`);
230
+ NODE
231
+
232
+ printf 'Active slices refreshed: %s\n' "$output_path"
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -euo pipefail
4
+
5
+ release_type="patch"
6
+ publish="false"
7
+ publish_current="false"
8
+
9
+ usage() {
10
+ cat <<'EOF'
11
+ Usage: scripts/release-quiver.sh [patch|minor|major|x.y.z] [--publish | --publish-current]
12
+
13
+ By default the script performs a release dry run:
14
+ - validates the installer smoke
15
+ - validates the package artifact
16
+ - prints the versioning and publish commands to run next
17
+
18
+ Pass --publish to run npm version and npm publish after the smoke checks pass.
19
+ Pass --publish-current to publish the current package version without forcing a patch bump.
20
+ EOF
21
+ }
22
+
23
+ while [[ $# -gt 0 ]]; do
24
+ case "$1" in
25
+ --publish)
26
+ publish="true"
27
+ shift
28
+ ;;
29
+ --publish-current)
30
+ publish_current="true"
31
+ publish="true"
32
+ shift
33
+ ;;
34
+ -h|--help)
35
+ usage
36
+ exit 0
37
+ ;;
38
+ *)
39
+ release_type="$1"
40
+ shift
41
+ ;;
42
+ esac
43
+ done
44
+
45
+ repo_root="$(git rev-parse --show-toplevel)"
46
+ cd "$repo_root"
47
+
48
+ if [[ -n "$(git status --porcelain)" ]]; then
49
+ echo "FAIL: release requires a clean worktree" >&2
50
+ exit 1
51
+ fi
52
+
53
+ bash scripts/ci/smoke-create-quiver.sh
54
+ bash scripts/package-quiver.sh
55
+
56
+ if [[ "$publish" == "false" ]]; then
57
+ echo "Release dry run passed."
58
+ echo "Next commands:"
59
+ if [[ "$publish_current" == "true" ]]; then
60
+ echo " npm publish --access public"
61
+ else
62
+ echo " npm version $release_type -m \"chore(release): %s\""
63
+ echo " npm publish --access public"
64
+ fi
65
+ echo " git push origin HEAD --tags"
66
+ exit 0
67
+ fi
68
+
69
+ if [[ "$publish_current" == "true" ]]; then
70
+ npm publish --access public
71
+ git push origin HEAD --tags
72
+ exit 0
73
+ fi
74
+
75
+ npm version "$release_type" -m "chore(release): %s"
76
+ npm publish --access public
77
+ git push origin HEAD --tags