@cristiancorreau/forge 2.9.6 → 2.9.8

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 (53) hide show
  1. package/README.md +1 -1
  2. package/dist/commands/doctor.d.ts.map +1 -1
  3. package/dist/commands/doctor.js +4 -3
  4. package/dist/commands/doctor.js.map +1 -1
  5. package/dist/commands/generate.js +1 -1
  6. package/dist/commands/generate.js.map +1 -1
  7. package/dist/commands/init.js +2 -2
  8. package/dist/commands/init.js.map +1 -1
  9. package/dist/lib/generators/codex.d.ts.map +1 -1
  10. package/dist/lib/generators/codex.js +10 -8
  11. package/dist/lib/generators/codex.js.map +1 -1
  12. package/dist/lib/generators/kiro.d.ts +1 -1
  13. package/dist/lib/generators/kiro.d.ts.map +1 -1
  14. package/dist/lib/generators/kiro.js +15 -16
  15. package/dist/lib/generators/kiro.js.map +1 -1
  16. package/dist/lib/generators/opencode.d.ts.map +1 -1
  17. package/dist/lib/generators/opencode.js +13 -12
  18. package/dist/lib/generators/opencode.js.map +1 -1
  19. package/dist/lib/paths.d.ts +1 -2
  20. package/dist/lib/paths.d.ts.map +1 -1
  21. package/dist/lib/paths.js +12 -16
  22. package/dist/lib/paths.js.map +1 -1
  23. package/dist/version.d.ts +1 -1
  24. package/dist/version.js +1 -1
  25. package/package.json +2 -2
  26. package/assets/adapters/claude-code/generate-claude-md.py +0 -304
  27. package/assets/adapters/codex/generate-codex-config.py +0 -269
  28. package/assets/adapters/codex/hooks/codex.yaml.tpl +0 -43
  29. package/assets/adapters/codex/hooks/forge-codex-finish.sh +0 -158
  30. package/assets/adapters/codex/hooks/forge-codex-start.sh +0 -186
  31. package/assets/adapters/kiro/generate-steering.py +0 -367
  32. package/assets/adapters/opencode/generate-agents-md.py +0 -262
  33. package/assets/core/hooks/pre-bash-check.py +0 -202
  34. package/assets/core/hooks/pre-edit-check.py +0 -317
  35. package/assets/forge.py +0 -1265
  36. package/assets/requirements.txt +0 -2
  37. package/assets/scripts/aitmpl-search.py +0 -808
  38. package/assets/scripts/forge-add-opportunities.py +0 -92
  39. package/assets/scripts/forge-audit.py +0 -1061
  40. package/assets/scripts/forge-generate-all.py +0 -283
  41. package/assets/scripts/forge-init.py +0 -900
  42. package/assets/scripts/forge-migrate-project-yaml.py +0 -397
  43. package/assets/scripts/forge-scaffold-profile.py +0 -181
  44. package/assets/scripts/forge-teardown.py +0 -193
  45. package/assets/scripts/forge-validate-project-yaml.py +0 -457
  46. package/assets/scripts/forge-wizard.py +0 -1003
  47. package/assets/scripts/setup-codex.sh +0 -229
  48. package/assets/scripts/team-install.sh +0 -147
  49. package/assets/scripts/token-stats.py +0 -201
  50. package/dist/lib/python.d.ts +0 -4
  51. package/dist/lib/python.d.ts.map +0 -1
  52. package/dist/lib/python.js +0 -46
  53. package/dist/lib/python.js.map +0 -1
@@ -1,158 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Forge v2 — Codex onFinish hook: forge-codex-finish.sh
3
- #
4
- # Se ejecuta al finalizar cada sesión de Codex CLI.
5
- # Equivalente al hook post-turn-check.sh de Claude Code (Stop event).
6
- #
7
- # DIFERENCIAS vs Claude Code:
8
- # - Claude Code: post-turn-check.sh corre después de CADA turno del agente.
9
- # - Codex CLI: forge-codex-finish.sh corre al FINALIZAR la sesión completa,
10
- # no después de cada mensaje individual. Codex no tiene un equivalente
11
- # granular de "Stop por turno".
12
- # - Claude Code Stop hook: puede imprimir al contexto del agente (el output
13
- # se muestra como resultado del hook).
14
- # - Codex CLI onFinish: el output se muestra en la terminal del usuario,
15
- # pero puede no ser visible en el contexto del agente dependiendo de la
16
- # versión de Codex.
17
- #
18
- # LIMITACIONES de Codex vs Claude Code:
19
- # - No hay PreToolUse/PostToolUse hooks para interceptar herramientas individuales.
20
- # - Los checks de este script son post-sesión, no post-turno.
21
- #
22
- # Instalación: este script debe copiarse o enlazarse en .codex/forge-codex-finish.sh
23
- # El setup-codex.sh lo hace automáticamente.
24
-
25
- set -uo pipefail
26
-
27
- # ---------------------------------------------------------------------------
28
- # Step 1 — Find modified files
29
- # ---------------------------------------------------------------------------
30
- MODIFIED=$(git diff --name-only HEAD 2>/dev/null || echo "")
31
- STAGED=$(git diff --name-only --cached 2>/dev/null || echo "")
32
- ALL_CHANGED="$MODIFIED $STAGED"
33
-
34
- if [ -z "$(echo "$ALL_CHANGED" | tr -d '[:space:]')" ]; then
35
- exit 0
36
- fi
37
-
38
- # ---------------------------------------------------------------------------
39
- # Step 2 — Read project config
40
- # ---------------------------------------------------------------------------
41
- PKG_MGR=""
42
- CUSTOM_CHECK=""
43
-
44
- if [ -f "project.yaml" ]; then
45
- PKG_MGR=$(python3 -c "
46
- import yaml, sys
47
- try:
48
- d = yaml.safe_load(open('project.yaml'))
49
- print(d.get('stack', {}).get('package_manager', ''))
50
- except:
51
- print('')
52
- " 2>/dev/null || echo "")
53
-
54
- CUSTOM_CHECK=$(python3 -c "
55
- import yaml, sys
56
- try:
57
- d = yaml.safe_load(open('project.yaml'))
58
- print(d.get('scripts', {}).get('check', ''))
59
- except:
60
- print('')
61
- " 2>/dev/null || echo "")
62
- fi
63
-
64
- CHECK_OUTPUT=""
65
-
66
- # ---------------------------------------------------------------------------
67
- # Step 3 — Run checks
68
- # ---------------------------------------------------------------------------
69
-
70
- # Helper: check if any changed file matches a glob pattern
71
- files_matching() {
72
- local pattern="$1"
73
- echo "$ALL_CHANGED" | tr ' ' '\n' | grep -E "$pattern" 2>/dev/null || true
74
- }
75
-
76
- if [ -n "$CUSTOM_CHECK" ]; then
77
- # Run user-defined check command
78
- CHECK_OUTPUT=$(eval "$CUSTOM_CHECK" 2>&1 | head -20 || true)
79
-
80
- else
81
- # Auto-detect by file type
82
-
83
- # TypeScript / JavaScript
84
- TS_FILES=$(files_matching '\.(ts|tsx)$')
85
- if [ -n "$TS_FILES" ]; then
86
- if [ -f "turbo.json" ] && command -v pnpm &>/dev/null; then
87
- TSC_OUTPUT=$(pnpm turbo typecheck 2>&1 | head -20 || pnpm tsc --noEmit 2>&1 | head -20 || true)
88
- elif command -v pnpm &>/dev/null; then
89
- TSC_OUTPUT=$(pnpm tsc --noEmit 2>&1 | head -20 || true)
90
- elif command -v npx &>/dev/null; then
91
- TSC_OUTPUT=$(npx tsc --noEmit 2>&1 | head -20 || true)
92
- else
93
- TSC_OUTPUT=""
94
- fi
95
- if [ -n "${TSC_OUTPUT:-}" ]; then
96
- CHECK_OUTPUT="${CHECK_OUTPUT:+$CHECK_OUTPUT$'\n'}[tsc] $TSC_OUTPUT"
97
- fi
98
- fi
99
-
100
- # PHP
101
- PHP_FILES=$(files_matching '\.php$')
102
- if [ -n "$PHP_FILES" ] && [ -f "composer.json" ]; then
103
- if command -v composer &>/dev/null; then
104
- PHP_OUTPUT=$(composer validate --no-check-publish 2>&1 | head -10 || true)
105
- if [ -n "$PHP_OUTPUT" ]; then
106
- CHECK_OUTPUT="${CHECK_OUTPUT:+$CHECK_OUTPUT$'\n'}[composer] $PHP_OUTPUT"
107
- fi
108
- fi
109
- fi
110
-
111
- # Python
112
- PY_FILES=$(files_matching '\.py$')
113
- if [ -n "$PY_FILES" ]; then
114
- PY_OUTPUT=""
115
- while IFS= read -r f; do
116
- [ -z "$f" ] && continue
117
- [ -f "$f" ] || continue
118
- RESULT=$(python3 -m py_compile "$f" 2>&1 || true)
119
- if [ -n "$RESULT" ]; then
120
- PY_OUTPUT="${PY_OUTPUT:+$PY_OUTPUT$'\n'}$f: $RESULT"
121
- fi
122
- done <<< "$PY_FILES"
123
- if [ -n "$PY_OUTPUT" ]; then
124
- CHECK_OUTPUT="${CHECK_OUTPUT:+$CHECK_OUTPUT$'\n'}[python] $PY_OUTPUT"
125
- fi
126
- fi
127
-
128
- # Ruby
129
- RB_FILES=$(files_matching '\.rb$')
130
- if [ -n "$RB_FILES" ] && [ -f "Gemfile" ]; then
131
- RB_OUTPUT=""
132
- if command -v bundle &>/dev/null; then
133
- while IFS= read -r f; do
134
- [ -z "$f" ] && continue
135
- [ -f "$f" ] || continue
136
- RESULT=$(bundle exec ruby -c "$f" 2>&1 | head -10 || true)
137
- if [ -n "$RESULT" ]; then
138
- RB_OUTPUT="${RB_OUTPUT:+$RB_OUTPUT$'\n'}$f: $RESULT"
139
- fi
140
- done <<< "$RB_FILES"
141
- fi
142
- if [ -n "$RB_OUTPUT" ]; then
143
- CHECK_OUTPUT="${CHECK_OUTPUT:+$CHECK_OUTPUT$'\n'}[ruby] $RB_OUTPUT"
144
- fi
145
- fi
146
- fi
147
-
148
- # ---------------------------------------------------------------------------
149
- # Step 4 — Report
150
- # ---------------------------------------------------------------------------
151
- if [ -n "$CHECK_OUTPUT" ]; then
152
- echo "── Forge Codex post-session check ───────────"
153
- echo "$CHECK_OUTPUT"
154
- echo "─────────────────────────────────────────────"
155
- fi
156
-
157
- # Siempre exit 0 — este hook nunca bloquea.
158
- exit 0
@@ -1,186 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Forge v2 — Codex onStart hook: forge-codex-start.sh
3
- #
4
- # Se ejecuta al inicio de cada sesión de Codex CLI.
5
- # Equivalente al hook session-start.sh de Claude Code (UserPromptSubmit).
6
- #
7
- # DIFERENCIAS vs Claude Code:
8
- # - Claude Code: session-start.sh corre en UserPromptSubmit (automático en cada sesión).
9
- # - Codex CLI: este script corre en onStart (automático también, pero el timing
10
- # exacto depende de la versión de Codex).
11
- # - Claude Code: puede bloquear (exit 2) para detener la sesión.
12
- # - Codex CLI: onStart no puede bloquear la sesión — solo puede imprimir advertencias.
13
- # Exit 2 aquí no impide que Codex continúe; es informacional.
14
- #
15
- # LIMITACIONES de Codex vs Claude Code:
16
- # - No hay PreToolUse: no se puede interceptar comandos individuales antes de ejecutarlos.
17
- # - No hay PostToolUse: no se puede inspeccionar el resultado de cada tool call.
18
- # - Las reglas de seguridad (pre-bash-check, branch guard) son instruccionales en
19
- # AGENTS.md, no mecánicas. El agente debe respetar las reglas voluntariamente.
20
- #
21
- # Instalación: este script debe copiarse o enlazarse en .codex/forge-codex-start.sh
22
- # El setup-codex.sh lo hace automáticamente.
23
-
24
- set -uo pipefail
25
-
26
- CHECKS_PASSED=0
27
- CHECKS_TOTAL=0
28
- OUTPUT=""
29
-
30
- check() {
31
- local name="$1"
32
- local result="$2" # "ok" | "warn: <msg>" | "error: <msg>"
33
- CHECKS_TOTAL=$((CHECKS_TOTAL + 1))
34
- if [[ "$result" == "ok" ]]; then
35
- CHECKS_PASSED=$((CHECKS_PASSED + 1))
36
- elif [[ "$result" == error:* ]]; then
37
- local msg="${result#error: }"
38
- OUTPUT+=" error: ${msg}\n"
39
- else
40
- local msg="${result#warn: }"
41
- OUTPUT+=" warn: ${msg}\n"
42
- fi
43
- }
44
-
45
- # ---------------------------------------------------------------------------
46
- # Check 1 — Herramientas básicas disponibles
47
- # ---------------------------------------------------------------------------
48
- if ! command -v git &>/dev/null; then
49
- check "git" "error: git no está instalado o no está en PATH"
50
- else
51
- check "git" "ok"
52
- fi
53
-
54
- if ! command -v python3 &>/dev/null; then
55
- check "python3" "error: python3 no está instalado o no está en PATH"
56
- else
57
- check "python3" "ok"
58
- fi
59
-
60
- # ---------------------------------------------------------------------------
61
- # Check 2 — Branch actual no es main/master
62
- # ---------------------------------------------------------------------------
63
- CURRENT_BRANCH="$(git branch --show-current 2>/dev/null || true)"
64
- if [[ "$CURRENT_BRANCH" == "main" || "$CURRENT_BRANCH" == "master" ]]; then
65
- check "branch" "warn: branch '${CURRENT_BRANCH}' — crea una feature branch antes de implementar: git checkout -b feature/<tema>-$(date +%Y-%m-%d)"
66
- else
67
- check "branch" "ok"
68
- fi
69
-
70
- # ---------------------------------------------------------------------------
71
- # Check 3 — Cambios sin commitear
72
- # ---------------------------------------------------------------------------
73
- GIT_STATUS="$(git status --short 2>/dev/null || true)"
74
- if [[ -n "$GIT_STATUS" ]]; then
75
- check "uncommitted" "warn: cambios sin commitear en el worktree"
76
- else
77
- check "uncommitted" "ok"
78
- fi
79
-
80
- # ---------------------------------------------------------------------------
81
- # Check 4 — project.yaml existe
82
- # ---------------------------------------------------------------------------
83
- PROJECT_YAML=""
84
- SEARCH_PATH="$(pwd)"
85
- for _i in 1 2 3 4 5 6; do
86
- if [[ -f "${SEARCH_PATH}/project.yaml" ]]; then
87
- PROJECT_YAML="${SEARCH_PATH}/project.yaml"
88
- break
89
- fi
90
- PARENT="$(dirname "$SEARCH_PATH")"
91
- [[ "$PARENT" == "$SEARCH_PATH" ]] && break
92
- SEARCH_PATH="$PARENT"
93
- done
94
-
95
- if [[ -z "$PROJECT_YAML" ]]; then
96
- check "project.yaml" "warn: project.yaml no encontrado — ejecutar forge-wizard.py o scripts/setup-codex.sh"
97
- else
98
- check "project.yaml" "ok"
99
-
100
- # Check 5 — project.yaml tiene campos requeridos
101
- YAML_VALID="$(python3 - "$PROJECT_YAML" <<'PYEOF'
102
- import sys, yaml
103
- path = sys.argv[1]
104
- try:
105
- with open(path) as f:
106
- data = yaml.safe_load(f)
107
- if not isinstance(data, dict):
108
- print("invalid")
109
- sys.exit(0)
110
- missing = []
111
- project = data.get("project", {})
112
- if not project.get("name"):
113
- missing.append("project.name")
114
- if not project.get("mode"):
115
- missing.append("project.mode")
116
- if missing:
117
- print("missing:" + ",".join(missing))
118
- else:
119
- print("ok")
120
- except Exception as e:
121
- print(f"error:{e}")
122
- PYEOF
123
- )"
124
- if [[ "$YAML_VALID" == "ok" ]]; then
125
- check "project.yaml.fields" "ok"
126
- elif [[ "$YAML_VALID" == missing:* ]]; then
127
- MISSING_FIELDS="${YAML_VALID#missing:}"
128
- check "project.yaml.fields" "warn: project.yaml faltan campos: ${MISSING_FIELDS}"
129
- else
130
- check "project.yaml.fields" "warn: project.yaml no se pudo parsear — verificar sintaxis"
131
- fi
132
-
133
- # Check 6 — Variables de entorno de producción activas
134
- HAS_DEPLOY="$(python3 - "$PROJECT_YAML" <<'PYEOF'
135
- import sys, yaml
136
- path = sys.argv[1]
137
- try:
138
- with open(path) as f:
139
- data = yaml.safe_load(f)
140
- if isinstance(data, dict) and data.get("deploy"):
141
- print("yes")
142
- else:
143
- print("no")
144
- except Exception:
145
- print("no")
146
- PYEOF
147
- )"
148
- if [[ "$HAS_DEPLOY" == "yes" ]]; then
149
- PROD_VARS=""
150
- while IFS='=' read -r key _value; do
151
- if [[ "$key" =~ ^(PROD_|PRODUCTION_|PROD$|PRODUCTION$) ]]; then
152
- PROD_VARS+="${key} "
153
- fi
154
- done < <(env)
155
- if [[ -n "$PROD_VARS" ]]; then
156
- check "prod-env" "warn: variables de producción activas en sesión: ${PROD_VARS// /, } — verificar que es intencional"
157
- else
158
- check "prod-env" "ok"
159
- fi
160
- else
161
- check "prod-env" "ok"
162
- fi
163
- fi
164
-
165
- # ---------------------------------------------------------------------------
166
- # Salida
167
- # ---------------------------------------------------------------------------
168
- WARNINGS=$((CHECKS_TOTAL - CHECKS_PASSED))
169
-
170
- if [[ $WARNINGS -eq 0 ]]; then
171
- # Silencioso — todo OK
172
- exit 0
173
- fi
174
-
175
- # Construir etiquetas para el resumen
176
- LABELS=""
177
- [[ "$CURRENT_BRANCH" == "main" || "$CURRENT_BRANCH" == "master" ]] && LABELS+="[branch ${CURRENT_BRANCH}] "
178
- [[ -n "$GIT_STATUS" ]] && LABELS+="[cambios sin commitear] "
179
- [[ -z "$PROJECT_YAML" ]] && LABELS+="[sin project.yaml] "
180
-
181
- printf "forge-codex session: %d advertencia(s) — %s\n" "$WARNINGS" "${LABELS%% }"
182
- printf "%b" "$OUTPUT"
183
-
184
- # Nota: en Codex CLI, onStart no puede bloquear la sesión.
185
- # Salimos con 0 siempre — las advertencias son informacionales.
186
- exit 0