Skip to content

Commit dfc4d2e

Browse files
luiseimanclaude
andcommitted
docs: refresh README + ROADMAP for v3.4.0 + recompile verify-before-done
- README badge 3.1.1 → 3.4.0 - README "what's new" rewritten for v3.4 (33+ hook events, $defaults placeholder, find-tightening, native bfs/ugrep, TUI/recap, attribution settings, full CLI surface, audit item 14 enforcement, verify-before-done regex) - ROADMAP estado actual → v3.4.0; added v3.1.2/3.2.0/3.3.0/3.3.1/3.4.0 to "Completado"; renamed planned section (no version assigned) with v3.4.0 follow-up items - .claude/hooks/generated/verify-before-done__pretooluse__bash__0.sh recompiled from updated YAML so the new bash-test regex actually takes effect at runtime (the YAML edit alone was inert until recompile) Verified: 33/33 tests pass (19 skills + 8 runtime + 1 compiler + 5 behavior CLI). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent dcf5db0 commit dfc4d2e

3 files changed

Lines changed: 65 additions & 14 deletions

File tree

.claude/hooks/generated/verify-before-done__pretooluse__bash__0.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ if forge_behavior_session_is_disabled "$SESSION_ID" "$BEHAVIOR_ID"; then
4444
fi
4545

4646
# Conditions (logic: all)
47-
CONDITIONS_JSON='[{"field":"command","operator":"regex_match","value":"(^|[;&|\\s])(pytest|npm\\s+(test|run\\s+build)|yarn\\s+(test|build)|pnpm\\s+(test|build)|bun\\s+test|go\\s+test|cargo\\s+test|cargo\\s+build|mvn\\s+(test|package|verify)|gradle\\s+(test|build)|swift\\s+test|make\\s+(test|check|build)|vitest(\\s|$)|jest(\\s|$)|ruff\\s+check|mypy\\s+|tsc(\\s|$)|eslint\\s+)"}]'
47+
CONDITIONS_JSON='[{"field":"command","operator":"regex_match","value":"(^|[;&|\\s])(pytest|npm\\s+(test|run\\s+build)|yarn\\s+(test|build)|pnpm\\s+(test|build)|bun\\s+test|go\\s+test|cargo\\s+test|cargo\\s+build|mvn\\s+(test|package|verify)|gradle\\s+(test|build)|swift\\s+test|make\\s+(test|check|build)|vitest(\\s|$)|jest(\\s|$)|ruff\\s+check|mypy\\s+|tsc(\\s|$)|eslint\\s+|bash\\s+\\S*tests?/\\S+\\.sh|bash\\s+\\S*test[_-]\\S*\\.sh|\\./tests?/\\S+\\.sh|\\./\\S+test[_-]\\S+\\.sh)"}]'
4848
if ! python3 - "$CONDITIONS_JSON" 'all' "$TOOL_INPUT_JSON" <<'PYCOND'
4949
import sys, json, re
5050
conditions = json.loads(sys.argv[1])

README.md

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
[![GitHub stars](https://img.shields.io/github/stars/luiseiman/dotforge)](https://github.com/luiseiman/dotforge/stargazers)
1010
[![License: MIT](https://img.shields.io/github/license/luiseiman/dotforge)](LICENSE)
11-
[![Version](https://img.shields.io/badge/version-3.1.1-blue)](VERSION)
11+
[![Version](https://img.shields.io/badge/version-3.4.0-blue)](VERSION)
1212
[![Last commit](https://img.shields.io/github/last-commit/luiseiman/dotforge)](https://github.com/luiseiman/dotforge/commits/main)
1313

1414
**Behavior governance for [Claude Code](https://docs.anthropic.com/en/docs/claude-code).** Declare runtime policies on tool calls — "search before writing", "no destructive git", "verify before shipping" — and enforce them via compiled `PreToolUse` hooks that share a session-scoped state file. Escalates silently → nudge → warning → soft_block → hard_block, with a permanent override audit trail.
@@ -32,14 +32,21 @@ bootstrap → audit → sync → capture → propagate → behaviors
3232

3333
For people and teams managing more than one Claude Code project.
3434

35-
## v3.1 — what's new
35+
## v3.4 — what's new (2026-04-26)
3636

37-
- **Domain knowledge sync** to Claude Code v2.1.108: hook events corrected 27 → **31** (3 lifecycle cadences), `InstructionsLoaded` / `Elicitation` / blockable `PreCompact` documented, default `effort` change `medium → high` flagged across model-routing rules.
38-
- **Enterprise managed settings** documented: `managed-settings.d/` drop-in directory, `allowManagedHooksOnly`, `allowedChannelPlugins`, `forceRemoteSettingsRefresh`.
39-
- **Dynamic permissions API** from hooks: `addRules` / `replaceRules` / `removeRules` / `setMode` / `addDirectories` / `removeDirectories` via `hookSpecificOutput.decision.updatedPermissions`.
40-
- **`ask:` permission list in template**: 18 entries bridging the gap between unrestricted `allow:` and total `deny:` — covers `rm`, `chmod`, `npm/pip install`, `docker run`, `kubectl apply/delete`, `gcloud`/`aws`/`terraform apply/destroy`, `git push/rebase/cherry-pick`.
41-
- **Compound-bash safety verified** for `block-destructive.sh` against the v2.1.98 bypass class — hook uses `grep -qiE` over the full command string and catches `ls && rm -rf /`-style forms by design. Limitations and `sandbox.enabled` defense-in-depth documented.
42-
- **`showThinkingSummaries` corrected** in domain rules: it is purely cosmetic, does NOT reduce thinking token spend. Added missing `alwaysThinkingEnabled` entry as the actual cost knob.
37+
- **Hook event catalogue** updated to **33+**`UserPromptExpansion` (slash-command expansion, blockable) and `PostToolBatch` (end-of-batch validation, blockable) added; documented `mcp_tool` as a fifth hook type with `${tool_input.*}` substitution (v2.1.118+); `PostToolUse`/`PostToolUseFailure` now carry `duration_ms` (v2.1.119+).
38+
- **Auto mode `"$defaults"` placeholder** (v2.1.118+) — extends `autoMode.allow|soft_deny|environment` instead of replacing them. Removes the all-or-nothing trade-off when shipping custom rules.
39+
- **Permission tightening** (v2.1.113+): `Bash(find:*)` allow rules no longer auto-approve `-exec`/`-delete`; deny rules now match `env`/`sudo`/`watch`/`ionice`/`setsid` wrappers; on macOS `/private/{etc,var,tmp,home}` are dangerous removal targets under `Bash(rm:*)`.
40+
- **Native macOS/Linux builds** (v2.1.117+) replace `Glob`/`Grep` tools with embedded `bfs`/`ugrep` via `Bash`. `Glob(...)`/`Grep(...)` permission specifiers and hook matchers are now platform-dependent — flagged in domain rules.
41+
- **TUI + idle-return recap**: `tui` setting + `/tui` toggle (v2.1.110+); `awaySummaryEnabled` + `/recap` (v2.1.108+, default-on for telemetry-disabled deployments since v2.1.110). Coexists with dotforge's `last-compact.md` — different problems (idle return vs compaction survival).
42+
- **Git attribution refresh**: `attribution.commit`/`attribution.pr` supersede the deprecated `includeCoAuthoredBy`; `prUrlTemplate` for self-hosted GitHub/GitLab/Bitbucket.
43+
- **CLI surface fully documented**: `--name`/`-n`, `--tools`/`--allowedTools`/`--disallowedTools`, `--system-prompt[-file]`/`--append-system-prompt[-file]`, `--strict-mcp-config`, `--input-format`, `--include-partial-messages`, `--debug-file`, `--disable-slash-commands`, `--remote-control`/`--rc`, `--allow-dangerously-skip-permissions`, `--plugin-dir`, `--ide`, `--betas`, `--channels`. New CLI subcommands: `claude install`, `auth`, `agents`, `auto-mode`, `remote-control`, `setup-token`.
44+
- **Audit checklist item 14 fixed**: scoring v3 behavior coverage now requires ENFORCEMENT (compiled hook under `.claude/hooks/generated/` AND a `settings.json` reference), not just a `behaviors/index.yaml` declaration. Closes the false-positive that scored projects 1/1 with no runtime effect.
45+
- **`verify-before-done` regex extended**: now matches `bash tests/*.sh`, `bash <path>/test-*.sh`, `./tests/*.sh` patterns. Fixes legitimate `git push` from dotforge being soft-blocked after `bash tests/test-*.sh` runs.
46+
47+
## v3.3.1 — Session-report JSON bug (2026-04-21)
48+
49+
5-month silent bug: `session-report.sh` corrupted every metrics JSON across all 12 registered projects. Root cause: `grep -c ... || echo "0"` idiom that emitted `"0\n0"` on no-match, plus a cascade where the corrupted previous file made arithmetic fail on the next write. Fixed in 9 projects, 54 corrupt JSON files deleted.
4350

4451
## v3.0 — behavior governance layer
4552

ROADMAP.md

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,51 @@
11
# Roadmap dotforge
22

3-
Estado actual: **v3.1.1** (2026-04-15) — Domain knowledge sync con Claude Code v2.1.108 + `ask:` permission template + corrección `showThinkingSummaries`. v3 behaviors operativos en 4 proyectos piloto (dotforge, cotiza-api-cloud, TRADINGBOT, jira-nbch).
3+
Estado actual: **v3.4.0** (2026-04-26) — Sync con Claude Code v2.1.92 → v2.1.119 (12 prácticas upstream incorporadas) + dos fixes operativos (audit item 14 enforcement, verify-before-done regex `bash tests/*.sh`). v3 behaviors operativos en 4 proyectos piloto.
44

55
---
66

77
## Completado
88

9+
### v3.4.0 — Sync upstream + audit/behavior fixes (2026-04-26)
10+
11+
`/forge watch` pass contra code.claude.com cubriendo Claude Code **v2.1.92 → v2.1.119**. 14 prácticas aceptadas (12 upstream + 2 operativas), 6 rechazos auto-generados, 1 deferred.
12+
13+
#### Domain rules
14+
- `hook-architecture.md` / `hook-events.md`: catálogo de eventos a **33+** con `UserPromptExpansion` (blockable, slash command expansion) y `PostToolBatch` (blockable, fin de batch paralelo). Quinto tipo de hook `mcp_tool` con `${tool_input.*}` substitution. `PostToolUse`/`PostToolUseFailure` ahora reciben `duration_ms`. `UserPromptSubmit` puede setear `hookSpecificOutput.sessionTitle`.
15+
- `auto-mode.md`: placeholder `"$defaults"` para `autoMode.allow|soft_deny|environment` (extiende vs reemplaza built-in classifier). Nota sobre native macOS/Linux builds que pliegan `Glob`/`Grep` en `Bash`.
16+
- `permission-model.md`: tightening v2.1.113 (`Bash(find:*)` ya no auto-aprueba `-exec`/`-delete`; deny matching sobre wrappers `env`/`sudo`/`watch`/`ionice`/`setsid`; macOS `/private/{etc,var,tmp,home}` como targets peligrosos en `Bash(rm:*)`). PowerShell auto-approval (v2.1.119). `Glob(...)`/`Grep(...)` specifiers son platform-dependent.
17+
- `context-control-patterns.md`: TUI modes (`tui` setting, `/tui`, `autoScrollEnabled`); idle-return recap (`/recap`, `awaySummaryEnabled`, `CLAUDE_CODE_ENABLE_AWAY_SUMMARY`). Coexistencia documentada con `last-compact.md`.
18+
- `parallel-sessions.md`: superficie completa de CLI flags (`--name`, `--tools`, `--strict-mcp-config`, `--system-prompt[-file]`, `--input-format`, `--include-partial-messages`, `--debug-file`, `--disable-slash-commands`, `--remote-control`, `--allow-dangerously-skip-permissions`, `--plugin-dir`, `--ide`, `--betas`, `--channels`) + subcomandos (`claude install`, `auth`, `agents`, `auto-mode`, `remote-control`, `setup-token`).
19+
- `_common.md`: Git section actualiza con `attribution.commit/pr` (deprecates `includeCoAuthoredBy`) y `prUrlTemplate` para self-hosted.
20+
21+
#### Operativos
22+
- `behaviors/verify-before-done/behavior.yaml`: regex extiende a `bash tests/*.sh`, `bash <path>/test-*.sh`, `./tests/*.sh`. Resuelve `git push` desde dotforge soft-blocked tras `bash tests/test-*.sh` legítimo.
23+
- `audit/checklist.md` item 14: scoring requiere ENFORCEMENT (hook compilado en `.claude/hooks/generated/` AND referencia en `settings.json`), no solo declaración en `behaviors/index.yaml`. Cierra el falso positivo que premiaba a proyectos con 1/1 sin efecto runtime.
24+
- `docs/claude-vs-forge.md`: `/usage` como comando canónico; `/cost` y `/stats` son atajos desde v2.1.118.
25+
26+
#### Inbox lifecycle
27+
14 → `active/` (12 upstream + audit-item-14 + verify-before-done-regex). 6 capturas auto-generadas `*-session-changes` rechazadas. 1 diferida (`agent-memory-underused`, tag `needs-more-info`). `metrics.yml` con 14 entries nuevas + 8 monitoring bumps.
28+
29+
### v3.3.1 — Fix session-report.sh malformed JSON (2026-04-21)
30+
31+
Bug silencioso de 5 meses: el hook `session-report.sh` corrompía cada archivo JSON bajo `~/.claude/metrics/<slug>/*.json` en los 12 proyectos registrados (54 archivos corruptos desde 2026-03-22). `/forge insights` degradaba silenciosamente a análisis retroactivo de git-log.
32+
33+
Causa raíz (dos bugs encadenados): (1) `grep -c ... || echo "0"` emite `"0\n0"` cuando no hay match (GNU `grep -c` retorna `"0"` exit code 1 → `||` dispara → JSON queda con valores multi-línea); (2) cascada — un archivo corrupto previo hacía fallar la aritmética en el siguiente write, dejando `"sessions": ,`.
34+
35+
Fix: separación `grep -c` + sanitización `${var//[!0-9]/}` + default `${var:-0}`. Helper `_jq_num()` que valida output numérico antes de aritmética. Pre-validación con `jq -e .` y restart limpio si el archivo previo está corrupto. Propagador `scripts/fix-session-metrics.sh` aplicado a 9 proyectos.
36+
37+
### v3.3.0 — MEDIUM sync + integrations/channels (2026-04-21)
38+
39+
Watch pass del 2026-04-21. Seis prácticas incorporadas (dos security-relevant en `monitoring`, cuatro doc-drift). `/forge audit` script-version (`scripts/audit_all.py`) para batch.
40+
41+
### v3.2.0 — Domain sync v2.1.108 → v2.1.114 + block-destructive hardening (2026-04-19)
42+
43+
Watch pass cubriendo Claude Code v2.1.108 → v2.1.114. Hardening de `block-destructive.sh` contra compound bash y env-var prefix bypass. Six prácticas incorporadas.
44+
45+
### v3.1.2 — SSH/VPS persistence loop (2026-04-17)
46+
47+
`domain/infra.md` como rule canónica para persistir SSH host config + deploy commands + service names entre sesiones. Cierra el problema de "Claude no recuerda cómo deployar" tras `/clear`.
48+
949
### v3.1.1 — Doc fix `showThinkingSummaries` (2026-04-15)
1050

1151
Hotfix de domain rule: `showThinkingSummaries` se documentaba como si su toggle tuviera impacto operativo. Por spec oficial es puramente cosmético — no reduce gasto de thinking. Agregado `alwaysThinkingEnabled` como knob real de costo. Sin impacto en runtime.
@@ -221,9 +261,7 @@ Reverse engineering de 5 repositorios + alineación de dotforge con internals ve
221261

222262
---
223263

224-
## v3.2.0 — Próximo (planificado)
225-
226-
> El número v3.1.0 quedó tomado por el sync de domain knowledge del 2026-04-15. Las features originalmente planeadas para v3.1.0 se reagrupan acá.
264+
## Próximo (planificado, sin versión asignada)
227265

228266
### Nuevo stack: prompt-engineering
229267
- Para proyectos que configuran Claude Code (meta-configuración)
@@ -232,10 +270,12 @@ Reverse engineering de 5 repositorios + alineación de dotforge con internals ve
232270
- Estima costo en tokens de la configuración actual
233271

234272
### Hooks para eventos no usados
235-
- PostToolUseFailure → error tracking automático
273+
- PostToolUseFailure → error tracking automático (parcial: domain rules ya documentan `duration_ms` field desde v3.4.0)
236274
- FileChanged → auto-reload patterns
237275
- TaskCreated/TaskCompleted → métricas de orquestación
238276
- PermissionDenied → audit trail
277+
- PostToolBatch → end-of-batch validation (nuevo desde v3.4.0)
278+
- UserPromptExpansion → gate de expansión de slash commands (nuevo desde v3.4.0)
239279

240280
### Rollout v3 behaviors a los 8 proyectos restantes
241281
- Después del periodo de validación de los 4 pilotos (dotforge, cotiza-api-cloud, TRADINGBOT, jira-nbch)
@@ -244,6 +284,10 @@ Reverse engineering de 5 repositorios + alineación de dotforge con internals ve
244284
### Sandbox config para proyectos con secretos
245285
- TRADINGBOT, derup → habilitar `sandbox.enabled` con `filesystem.denyRead` sobre `.env`
246286

287+
### Hook follow-up de v3.4.0
288+
- `template/hooks/tool-latency.sh` — PostToolUse hook que bufferea `duration_ms` por tool a un archivo, leído por `session-report.sh` al final de la sesión
289+
- Auditoría de stacks por `Bash(find:*)`/`Bash(rm:*)` allow rules afectados por el tightening v2.1.113
290+
247291
### Cleanup
248292
- Redis section redundancy entre python-fastapi y redis
249293
- go-api permisos redundantes

0 commit comments

Comments
 (0)