feat(doctor): add fn doctor CLI + 14 functions for system management
Adds `fn doctor` read-only diagnostic command with subcommands artefacts, services, sync, uses-functions, unused, and --json flag for agents. Each subcommand wraps a registry function in functions/infra/. New functions: - artefact_doctor, services_status, pc_locations_drift, audit_uses_functions, find_unused_functions (Go diagnostics) - backup_sqlite_db, rotate_backups, wait_for_http, wait_for_port, port_kill, tail_journal, pre_commit_hook_install (bash utilities) - notify_telegram (Go HTTP) - backup_all pipeline (tag launcher) Plus prior session leftovers (scan_secrets_in_dirty, append_diary_entry, git utilities, http_session_cookie_middleware, compile/full-git pipelines). Fixes pc_locations_drift filepath.Join bug with absolute dir_path. Documents fn doctor in CLAUDE.md, .claude/rules/fn_doctor.md (rule 23), docs/architecture.md, CHANGELOG.md (2026-05-07), and diary entry. First fn doctor uses-functions run found drift in 7/12 apps (deuda para sincronizar app.md con imports reales). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,124 +1,28 @@
|
||||
# /full-git-pull — Pull automático de fn_registry + sub-repos + submodules + fn sync
|
||||
|
||||
Trae los últimos cambios del remote para el repo principal `fn_registry`, todos los sub-repos git anidados que **ya existan localmente**, y los submodules de `cpp/vendor/`. Después regenera `registry.db` y corre `fn sync` para tirar de la metadata del `registry_api`.
|
||||
|
||||
**Modo automático (preferencia del usuario):** este comando NO pregunta. Auto-stashea dirty trees antes de pullear y hace `pop` después. Sigue con el resto de repos aunque uno falle. Solo se detiene si detecta riesgo serio (conflicto en stash pop que requiere intervención humana).
|
||||
|
||||
**No clona repos que falten.** Cada PC tiene solo el subset de apps/analyses que le interesa. Si en este PC necesitas un sub-repo que aún no tienes, clónalo a mano:
|
||||
Wrapper sobre el pipeline `full_git_pull_bash_pipelines`. Toda la lógica vive en el registry. Este comando solo ejecuta:
|
||||
|
||||
```bash
|
||||
git clone https://<user>:<token>@<gitea-host>/dataforge/<name>.git <path>
|
||||
cd /home/lucas/fn_registry
|
||||
./fn run full_git_pull_bash_pipelines
|
||||
```
|
||||
|
||||
Consulta `pc_locations` para ver dónde lo tiene otro PC y reproduce el path.
|
||||
|
||||
## Argumento
|
||||
|
||||
`$ARGUMENTS` — sin uso, ignorar.
|
||||
|
||||
## Pasos
|
||||
## Qué hace el pipeline
|
||||
|
||||
### 1. Descubrir repos locales
|
||||
|
||||
```bash
|
||||
cd /home/lucas/fn_registry
|
||||
|
||||
REPOS=$(find . -name ".git" -type d \
|
||||
-not -path "./.git" -not -path "./.git/*" \
|
||||
-not -path "*/node_modules/*" -not -path "*/.venv/*" \
|
||||
-not -path "*/cpp/vendor/*" -not -path "*/cpp/build/*" \
|
||||
-not -path "*/sources/*" -not -path "*/temp/*" -not -path "*/subrepos/*" 2>/dev/null \
|
||||
| sed 's|/.git$||')
|
||||
REPOS=". $REPOS"
|
||||
```
|
||||
|
||||
Solo se actualizan los sub-repos que ya tengan `.git/` localmente.
|
||||
|
||||
### 2. Para cada repo: stash si dirty, pull --ff-only, pop
|
||||
|
||||
```bash
|
||||
for r in $REPOS; do
|
||||
( cd "$r" \
|
||||
&& DIRTY=$(git status --porcelain | wc -l) \
|
||||
&& if [ "$DIRTY" -gt 0 ]; then
|
||||
git stash push -m "auto-stash before /full-git-pull" --include-untracked >/dev/null
|
||||
STASHED=1
|
||||
else
|
||||
STASHED=0
|
||||
fi \
|
||||
&& git fetch origin 2>&1 | tail -1 \
|
||||
&& git pull --ff-only 2>&1 | tail -3 \
|
||||
&& if [ "$STASHED" = "1" ]; then
|
||||
git stash pop 2>&1 | tail -3
|
||||
fi
|
||||
)
|
||||
done
|
||||
```
|
||||
|
||||
- Si `--ff-only` falla por divergencia → reportar ese repo, seguir con el resto. **No** rebasear ni mergear.
|
||||
- Si `stash pop` produce conflictos → **avisar al usuario al final** y dejar el conflicto sin tocar; seguir con los demás repos.
|
||||
|
||||
### 3. Submodules del repo principal
|
||||
|
||||
```bash
|
||||
git submodule update --init --recursive 2>&1 | tail -10
|
||||
```
|
||||
|
||||
### 4. Regenerar registry.db local
|
||||
|
||||
```bash
|
||||
CGO_ENABLED=1 ./fn index 2>&1 | tail -3
|
||||
```
|
||||
|
||||
### 5. Pull del repo de pass (`~/.password-store`)
|
||||
|
||||
El password store es su propio repo Git en Gitea (`dataforge/pass-secrets`). `pass insert/edit/rm` commitea automaticamente, asi que aqui SOLO hay que pullear los commits remotos.
|
||||
|
||||
```bash
|
||||
PASS_DIR="$HOME/.password-store"
|
||||
if [ -d "$PASS_DIR/.git" ]; then
|
||||
( cd "$PASS_DIR" \
|
||||
&& DIRTY=$(git status --porcelain | wc -l) \
|
||||
&& if [ "$DIRTY" -gt 0 ]; then
|
||||
git stash push -m "auto-stash before /full-git-pull" --include-untracked >/dev/null
|
||||
STASHED=1
|
||||
else
|
||||
STASHED=0
|
||||
fi \
|
||||
&& git fetch origin 2>&1 | tail -1 \
|
||||
&& git pull --ff-only 2>&1 | tail -3 \
|
||||
&& if [ "$STASHED" = "1" ]; then
|
||||
git stash pop 2>&1 | tail -3
|
||||
fi
|
||||
)
|
||||
fi
|
||||
```
|
||||
|
||||
Reglas:
|
||||
- Mismo patron que el resto de repos: stash → fetch → pull --ff-only → pop.
|
||||
- Si `--ff-only` falla por divergencia, reportar y seguir; no resolver a mano.
|
||||
- Si `stash pop` da conflicto, avisar al final.
|
||||
|
||||
### 6. fn sync
|
||||
|
||||
```bash
|
||||
USER=$(pass registry/basicauth-user | head -1)
|
||||
PASSWD=$(pass registry/basicauth-pass | head -1)
|
||||
TOKEN=$(pass registry/api-token | head -1)
|
||||
export FN_REGISTRY_API="https://${USER}:${PASSWD}@registry.organic-machine.com"
|
||||
export REGISTRY_API_TOKEN="$TOKEN"
|
||||
./fn sync
|
||||
```
|
||||
|
||||
Si `pass` falla → gpg-agent bloqueado, pedir al usuario `pass show unlock` en su terminal real (entrada dummy que devuelve "Desbloqueada!" sin exponer API keys).
|
||||
|
||||
### 7. Resumen
|
||||
|
||||
Tabla concisa: por repo, commits pulleados o "ya estaba al día"; estado de `pass-secrets`; submodules actualizados; resultado de `fn index`; resultado de `fn sync`. Si algún repo quedó con conflicto de stash o divergencia, listarlos al final con la acción sugerida.
|
||||
1. `discover_git_repos_bash_infra` — lista repos locales (mismas exclusiones que push).
|
||||
2. `git_pull_with_stash_bash_infra` por repo: stash si dirty → fetch → pull --ff-only → pop. Estados posibles por repo: `[pulled]`, `[up-to-date]`, `[diverged]`, `[stash-conflict]`.
|
||||
3. `git submodule update --init --recursive` en root.
|
||||
4. `git_pull_with_stash` sobre `~/.password-store`.
|
||||
5. `CGO_ENABLED=1 ./fn index` para regenerar `registry.db`.
|
||||
6. `./fn sync` con credenciales de `pass`.
|
||||
|
||||
## Notas
|
||||
|
||||
- **Modo no-interactivo por diseño.** El usuario prefiere flujos rápidos sin confirmaciones.
|
||||
- Pull solo es fast-forward — nunca rebase ni merge automático.
|
||||
- Auto-stash incluye untracked (`--include-untracked`) para no perder archivos nuevos.
|
||||
- `fn index` se corre **antes** de `fn sync` para que las locations locales reflejen el estado actual.
|
||||
- **Modo no-interactivo.** Auto-stash con `--include-untracked`.
|
||||
- **Solo fast-forward.** Nunca rebase ni merge automático. Si un repo diverge, se reporta y sigue con el resto.
|
||||
- **No clona repos faltantes.** Cada PC tiene su subset. Para añadir uno, clonarlo a mano y mirar `pc_locations` para reproducir el path.
|
||||
- Para tocar la lógica: editar las funciones del registry, no este wrapper.
|
||||
|
||||
Reference in New Issue
Block a user