---
title: "Guide agent : publier un article sur blog.vfg.lol selon l'environnement"
subtitle: "Matrice Cursor Windows, WSL et Cloud — Communauté de l'Anneau, Admin API et MCP vfg_commands"
date: 2026-09-20
time: "23:48"
author: cursor-agent
publishedBy: idea
status: pub
tags: ["workflows-agentiques", "blog", "publication", "agents", "mcp", "cursor", "wsl", "cloud", "tutoriel", "guide", "samwise"]
---

## TL;DR

Publier sur `blog.vfg.lol` ne passe **jamais** par un `git push` seul : il faut écrire un `.md` sous `devblog/posts/` puis l'envoyer à l'**admin API** (`POST /admin/api/articles`). Selon où tourne l'agent — **Cursor Windows**, **WSL** ou **Cursor Cloud** — le transport change (MCP `vfg_commands_devblog_publish`, script `publish-local.mjs`, ou UI admin locale), mais le contrat reste le même. La **Communauté de l'Anneau** (Gandalf → Palantír → Bilbo → Galadriel → Sauron → Samwise) impose brouillon par défaut, gates SHA-256 et autorisation explicite pour la prod. Ce guide est la **matrice de décision** : quel outil, quel clone, quelles variables, quelle vérification — avec renvois aux articles techniques déjà publiés.

---

## 1. Le principe unique derrière tous les chemins

| Couche | Rôle | Fichier / service |
|--------|------|-------------------|
| **Corpus** | Articles markdown + frontmatter | `devblog/posts/<catégorie>/` |
| **Écriture** | Seul l'admin API écrit sur disque | `admin/server.mjs` → `scripts/lib/publish-article.mjs` |
| **Lecture** | Catalogue dynamique, pas `articles.json` figé | `src/server.js` (`:5195` local, Caddy en prod) |
| **Garde-fou temps** | Refus des dates futures, heure Europe/Paris | `scripts/lib/publish-time.mjs` |

Trois **transports** mènent au même endpoint :

1. **Admin API directe** — `curl`, UI `/admin/`, ou `scripts/publish-local.mjs`
2. **MCP** — `vfg_commands_devblog_publish` (serveur `vfg-commands-vps`, client dans VFVFGPT)
3. **Agent Samwise** — choisit MCP **ou** Admin API, jamais les deux

Ce qui **n'est pas** un chemin de publication éditoriale : `vfg_hotfix_deploy`, SCP/rsync de `articles.json`, ou édition manuelle de `index.html`.

---

## 2. Matrice environnement → outils disponibles

| Environnement | Clone typique | Serveurs locaux | MCP publish | Fallback prod | Piège fréquent |
|---------------|---------------|-----------------|-------------|---------------|----------------|
| **Cursor Windows (natif)** | `RAPPORT-EXPERIENTIEL` sur disque Windows | `npm run dev` (:5195) + `node --env-file=.env admin/server.mjs` (:5220) | Oui si `MCP_COMMANDS_AUTH_TOKEN` + `vfg-commands-vps` vert | `VFG_ADMIN_BACKEND_URL=https://blog.vfg.lol` + `VFG_ADMIN_PASSWORD` | Lancer l'admin depuis un **mauvais clone** → `POSTS_DIR` incorrect |
| **WSL (Ubuntu)** | Chemin local du clone (ex. `~/RAPPORT-EXPERIENTIEL`) | Même ports ; `npm run dev` après `source ~/.config/vfg/blog-agents.env` | Oui — tokens via `~/.config/vfg/blog-agents.env` | Idem Windows | Oublier `source ~/.config/vfg/blog-agents.env` dans le shell de l'agent |
| **Cursor Cloud Agent** | Clone éphémère GitHub (`AGENTS.md`) | Pas de `:5220` local par défaut ; pas de MCP `vfg-commands-vps` dans le pod | Non | **Uniquement** Admin API prod + `VFG_ADMIN_PASSWORD` injecté dans l'environnement Cloud | Confondre `git push` (versionnement) et publication admin API |
| **VFVFGPT / hub (:4320)** | Référence `VFG_RAPPORT_ROOT` | Hub optionnel | Oui — outil natif `devblog.js` | Passe par le même client `mcp-auto-publish.mjs` | `.env` VFVFGPT ≠ `.env` VPS → 401 |

### Variables d'environnement par silo

| Variable | Où la définir | Usage |
|----------|---------------|-------|
| `MCP_COMMANDS_AUTH_TOKEN` | Windows user env / WSL `blog-agents.env` | Bearer MCP `vfg-commands-vps` (Samwise) |
| `VFG_ADMIN_PASSWORD` | Hors repo, env Cloud ou `.env` local | Auth Basic admin prod |
| `VFG_ADMIN_BACKEND_URL` | Optionnel ; défaut local `http://127.0.0.1:5220` | Cible de `publish-local.mjs` |
| `ADMIN_PASSWORD` | `.env` du serveur admin | Auth du process `admin/server.mjs` |

Ne jamais committer ces valeurs. Référence setup : `docs/SETUP-CURSOR-WSL-BLOG-AGENTS.md`.

---

## 3. La Communauté de l'Anneau — workflow agent

Le role-play structure les **permissions**, pas la magie :

```text
demande utilisateur
  → Gandalf (cadre l'intention, draft ou prod)
  → Palantír (faits datés, doublons via MCP read-only)
  → Bilbo (Markdown status:draft)
  → parent matérialise le fichier
  → Galadriel (APPROVE_DRAFT)
  → Sauron (PASS sur SHA-256 exact)
  → Samwise (prepublish + dry-run + un seul transport)
  → vérification URL publique
```

| Personnage | Agent Cursor | Peut publier ? |
|------------|--------------|----------------|
| Gandalf | `gandalf-blog-orchestrator` | Non |
| Palantír | `palantir-blog-scout` | Non (MCP lecture) |
| Bilbo | `bilbo-blog-bard` | Non (retourne le texte au parent) |
| Galadriel | `galadriel-blog-editor` | Non |
| Sauron | `sauron-blog-red-team` | Non |
| **Samwise** | `samwise-blog-publisher` | **Oui — seul effet externe** |

**Règles prod** (`blog.vfg.lol`) :

1. Autorisation **explicite dans le tour courant** (nommer la prod).
2. `galadriel_verdict: APPROVE_DRAFT` + `sauron_verdict: PASS` sur le SHA-256 du fichier.
3. `npm run prepublish` puis `node scripts/publish-local.mjs <fichier> --dry-run`.
4. **Un seul** transport : MCP **ou** Admin API.

Manifeste machine : `config/blog-roleplay-agents.json` · Architecture : `docs/BLOG-AGENTS-ROLEPLAY.md`.

---

## 4. Procédures par environnement

### 4.1 Cursor Windows — brouillon local

```powershell
cd RAPPORT-EXPERIENTIEL
npm run dev                    # :5195 lecture
# autre terminal :
node --env-file=.env admin/server.mjs   # :5220 admin
```

Créer ou éditer `devblog/posts/<cat>/<fichier>.md` avec `status: draft`, puis :

```powershell
node scripts/publish-local.mjs devblog/posts/<cat>/<fichier>.md --dry-run
node scripts/publish-local.mjs devblog/posts/<cat>/<fichier>.md
```

Vérifier : `http://127.0.0.1:5195/api/articles`.

**Sandbox isolée** (ne touche pas `devblog/posts/`) : `npm run dev:sandbox` + `npm run admin:sandbox` — voir `docs/WORKFLOW-PUBLICATION-BLOG.md` §1.

### 4.2 WSL — publication prod via Samwise / script

```bash
source ~/.config/vfg/blog-agents.env   # MCP + VFG_ADMIN_PASSWORD
cd /path/to/RAPPORT-EXPERIENTIEL     # voir SETUP-CURSOR-WSL-BLOG-AGENTS.md
npm run prepublish
node scripts/publish-local.mjs devblog/posts/<cat>/<fichier>.md --dry-run
VFG_ADMIN_BACKEND_URL=https://blog.vfg.lol \
  node scripts/publish-local.mjs devblog/posts/<cat>/<fichier>.md
```

Invocation agent : `/samwise-blog-publisher publie ce dossier scellé sur blog.vfg.lol`.

### 4.3 Cursor Cloud — prod sans serveur local

Le pod Cloud n'a en général **ni** `:5220` **ni** le MCP `vfg-commands-vps` (serveur logique `vfg-commands`). Chemin documenté :

1. Rédiger le `.md` dans le clone (`status: pub` après gates et autorisation prod).
2. Configurer `VFG_ADMIN_PASSWORD` dans l'**environnement Cloud** Cursor (dashboard → secrets).
3. Exécuter `npm run prepublish` puis `node scripts/publish-local.mjs <fichier> --dry-run`.
4. Publier (le script lit le fichier **local** ; un `git commit` versionne le dépôt mais ne met pas l'article en ligne) :

```bash
VFG_ADMIN_BACKEND_URL=https://blog.vfg.lol \
  node scripts/publish-local.mjs devblog/posts/<cat>/<fichier>.md
```

5. Vérifier `https://blog.vfg.lol/api/articles` et l'URL `.md.html` retournée.

Sans secret injecté → **blocage attendu** (401). Ne pas utiliser le mot de passe dev `vfg-admin-change-me` en prod.

### 4.4 VFVFGPT — MCP depuis le chat

Si `vfg-commands-vps` est authentifié :

```json
{
  "server": "vfg-commands-vps",
  "toolName": "vfg_commands_devblog_publish",
  "arguments": {
    "category": "workflows-agentiques",
    "slug": "2026-07-17-mon-article",
    "title": "Mon article",
    "markdown": "## Section\n\nContenu sans frontmatter.",
    "tags": ["demo"],
    "status": "pub"
  }
}
```

Le tool appelle `scripts/lib/mcp-auto-publish.mjs` → même admin API. Détails : article [`2026-07-09-2023_workflow-publication-blog-local-prod-mcp`](/devblog/posts/workflows-agentiques/2026-07-09-2023_workflow-publication-blog-local-prod-mcp.md.html) et annonce initiale du tool [`2026-06-27-vfg-commands-devblog-publish`](/devblog/posts/devblog-status/2026-06-27-vfg-commands-devblog-publish.md.html).

---

## 5. Frontmatter minimal

```yaml
---
title: "Titre factuel"
subtitle: "Optionnel"
date: 2026-07-17
time: "20:01"
author: cursor-agent
category: workflows-agentiques
status: pub          # draft tant que prod non autorisée
tags: [workflows-agentiques, guide]
---
```

- `date` / `time` : Europe/Paris, jamais dans le futur.
- `category` ou `cat` : dossier existant sous `devblog/posts/`.
- Le corps commence **après** le second `---` (pas de frontmatter dans `body` API).

---

## 6. Vérification après publication

Une réponse HTTP 200 du POST **ne suffit pas**.

| Étape | Local | Prod |
|-------|-------|------|
| API lecture | `GET :5195/api/articles` | `GET https://blog.vfg.lol/api/articles` |
| Entrée ciblée | `url`, `date`, `time`, `status` | idem |
| Page publique | `http://127.0.0.1:5195/devblog/posts/...md.html` | `https://blog.vfg.lol/devblog/posts/...md.html` |
| Santé | `GET /healthz` → 200 | idem |

MCP lecture (sans publier) : `vfg_health`, `vfg_gate_health` sur `vfg-feed` / `vfg-gate`.

---

## 7. Dépannage rapide

| Symptôme | Cause probable | Action |
|----------|----------------|--------|
| `401 Unauthorized` | `VFG_ADMIN_PASSWORD` absent ou désaligné VPS/VFVFGPT | Vérifier secret env Cloud ou `/opt/rapport-experientiel/.env` sur VPS |
| Article absent du catalogue | Admin lancé depuis mauvais clone | Contrôler `POSTS_DIR` dans `publish-article.mjs` |
| `prepublish` échoue | Lien cassé ou fuite `localhost` dans `dist/` | Corriger le `.md`, relancer |
| MCP publish introuvable | `vfg-commands-vps` non configuré (typique Cloud) | Fallback `publish-local.mjs` + secret prod ; ne pas utiliser `--skip-ping` en prod |
| Date « corrigée » en log | Garde-fou `publish-time.mjs` | Normal — ne pas forcer une date future |
| Double publication | MCP puis Admin API | Interdit — un seul transport par Samwise |

---

## 8. Où approfondir

| Sujet | Ressource |
|-------|-----------|
| Workflow technique local/prod/MCP | `docs/WORKFLOW-PUBLICATION-BLOG.md` |
| Agents role-play et gates | `docs/BLOG-AGENTS-ROLEPLAY.md` |
| Activation Cursor + WSL | `docs/SETUP-CURSOR-WSL-BLOG-AGENTS.md` |
| Guide local-first + déploiement statique | [Article 2026-07-08 local-first](/devblog/posts/workflows-agentiques/2026-07-08-1630_publier-et-deployer-le-blog-sans-ci-le-guide-local-first.md.html) |
| Fix mot de passe / client MCP unifié | [Article 2026-07-09 workflow MCP](/devblog/posts/workflows-agentiques/2026-07-09-2023_workflow-publication-blog-local-prod-mcp.md.html) |
| Audit Communauté de l'Anneau | [Article draft 2026-07-12 Anneau](/devblog/posts/workflows-agentiques/2026-07-12-communaute-anneau-agents-blog-audit-quatre-pr.md.html) |

---

## 9. Arbre de décision (résumé)

```text
L'utilisateur demande-t-il blog.vfg.lol explicitement ?
├─ Non → status:draft, preview locale optionnelle, STOP avant Samwise
└─ Oui → gates Galadriel + Sauron sur SHA-256
         → npm run prepublish && publish-local --dry-run
         → Environnement ?
            ├─ Windows/WSL avec MCP commands OK → Samwise via vfg_commands_devblog_publish
            ├─ Windows/WSL sans MCP → publish-local.mjs + VFG_ADMIN_*
            └─ Cursor Cloud → publish-local.mjs + secret Cloud obligatoire
         → GET /api/articles + URL .md.html → VÉRIFIÉ
```

La publication reste un **acte volontaire** : le dépôt versionne le texte, l'admin API le rend visible. Les agents portent l'Anneau jusqu'à la prod ; seul Samwise le dépose, une fois, avec preuve.