ia_dev/ai_working_help/notary-ai/notary-ai-loop-n-cycles.sh
Nicolas Cantu e5e07741d3 chore: agents, deploy scripts, notary-ai helpers and samples
**Motivations:** Publish ia_dev workspace updates to remote dev_ia.

**Root causes:** N/A (accumulated local changes).

**Correctifs:** N/A.

**Evolutions:** SmartIde agent docs; deploy change-to-all-branches and deploy-by-script-to; ai_working_help package scripts and lockfile; notary-ai loop shell scripts; sample responded JSON under projects/kogus/data; .cursor/ssh_config stub; kogus Code-Standards doc.

**Pages affectées:** N/A.
2026-04-23 03:06:13 +02:00

93 lines
4.6 KiB
Bash
Executable File

#!/usr/bin/env bash
# Run N cycles of (list pending + optional Cursor agent notary-ai-process + inter-cycle sleep) in foreground.
# From ia_dev root. MAIL_TO or AI_AGENT_TOKEN must be set (see projects/README.md).
#
# Usage: cd <ia_dev_root> && ./ai_working_help/notary-ai/notary-ai-loop-n-cycles.sh [N]
# N = cycles (default 1). Each cycle: list-pending (full stdout/stderr) → if non-empty and
# NOTARY_AI_LOOP_RUN_AGENT=1 and `agent` in PATH, run agent with notary-ai-process prompt → if i<N sleep INTER_CYCLE_SLEEP.
#
# Env:
# NOTARY_AI_LOOP_RUN_AGENT default 1 — set 0 to only list/sleep (no agent invocation when pending).
# NOTARY_AI_AGENT_MODEL default claude-4.6-sonnet-medium (passed to `agent --model`).
# NOTARY_AI_LOOP_INTER_CYCLE_SLEEP_SEC default 15 — pause between cycles when N>1 (was 60).
#
set -euo pipefail
if [ -n "${HOME:-}" ] && [ -r "$HOME/.bashrc" ]; then
set +u
# shellcheck source=/dev/null
source "$HOME/.bashrc" 2>/dev/null || true
set -u
fi
[ -n "${HOME:-}" ] && [ -d "$HOME/.local/bin" ] && export PATH="$HOME/.local/bin:$PATH"
NOTARY_AI_DIR="${NOTARY_AI_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)}"
IA_DEV_ROOT="$(cd "${NOTARY_AI_DIR}/../.." && pwd)"
export NOTARY_AI_DIR
cd "$IA_DEV_ROOT"
N="${1:-1}"
if ! [[ "$N" =~ ^[0-9]+$ ]] || [ "$N" -lt 1 ]; then
echo "[notary-ai-loop-n-cycles] Usage: $0 [N] (N positive integer, default 1)" >&2
exit 1
fi
if [[ -z "${MAIL_TO:-}" && -z "${AI_AGENT_TOKEN:-}" ]]; then
echo "[notary-ai-loop-n-cycles] Set MAIL_TO or AI_AGENT_TOKEN (see projects/README.md)." >&2
exit 1
fi
RUN_AGENT="${NOTARY_AI_LOOP_RUN_AGENT:-1}"
MODEL="${NOTARY_AI_AGENT_MODEL:-claude-4.6-sonnet-medium}"
# Legacy alias from older installs / shell rc (Cursor CLI has no "sonnet-4.6" id).
if [[ "$MODEL" == "sonnet-4.6" ]]; then
MODEL="claude-4.6-sonnet-medium"
fi
INTER_CYCLE_SLEEP="${NOTARY_AI_LOOP_INTER_CYCLE_SLEEP_SEC:-15}"
AGENT_PROMPT="$(cat <<EOF
Tu es l'agent notary-ai-process. Répertoire de travail obligatoire : ${IA_DEV_ROOT}
1) Exécute : ./ai_working_help/notary-ai/list-pending-notary-ai.sh
2) Pour chaque fichier JSON listé : lis request_uid, user_id, user_role, user_office_role (si présent), user_type (si présent), folder_uid, office_uid, question (y compris le bloc « Rappel pour l'agent » lecture seule / périmètre dossier), folder_context. Tu es en lecture seule : tu ne peux pas modifier LeCoffre, la base, les fichiers ou l'état du dossier ; tu ne proposes pas d'actions d'écriture. Avant de rédiger la réponse, rappelle explicitement dans ton raisonnement interne ces identifiants (utilisateur, rôle, dossier, office) : la réponse doit être concise et strictement circonscrite à ce dossier et aux informations accessibles dans folder_context, dans les limites des droits implicites du rôle de l'utilisateur (pas d'extrapolation hors périmètre dossier).
3) Rédige les 4 champs answer, nextActionsTable, membersInfoSheet, synthesisRecommendation (périmètre dossier notarial, pas de RIB ni coordonnées bancaires). Sois **bref** : textes utiles et denses ; pas de redondance entre les champs.
4) Pour chaque entrée, appelle depuis ${IA_DEV_ROOT} :
./ai_working_help/notary-ai/write-response-notary-ai.sh --request-uid "<uid>" --answer "..." --next-actions-table "..." --members-info-sheet "..." --synthesis-recommendation "..."
Traite tous les pending du cycle ; ne pas court-circuiter write-response-notary-ai.sh.
EOF
)"
echo "[notary-ai-loop-n-cycles] $(date -Iseconds) — début ${N} cycles (IA_DEV_ROOT=${IA_DEV_ROOT}, RUN_AGENT=${RUN_AGENT})"
i=1
while [ "$i" -le "$N" ]; do
echo "[notary-ai-loop-n-cycles] $(date -Iseconds) — cycle ${i}/${N}"
tmp="$(mktemp)"
set +e
./ai_working_help/notary-ai/list-pending-notary-ai.sh >"$tmp" 2>&1
list_rc=$?
set -e
cat "$tmp"
if [ "$list_rc" -ne 0 ]; then
echo "[notary-ai-loop-n-cycles] list-pending-notary-ai.sh exit $list_rc (cycle $i)" >&2
rm -f "$tmp"
exit "$list_rc"
fi
if [ -s "$tmp" ] && [ "$RUN_AGENT" = "1" ] && command -v agent >/dev/null 2>&1; then
echo "[notary-ai-loop-n-cycles] $(date -Iseconds) — pending non vide : lancement agent (notary-ai-process)"
if agent -p "$AGENT_PROMPT" -f --model "$MODEL" 2>&1; then
:
else
echo "[notary-ai-loop-n-cycles] $(date -Iseconds) — agent terminé avec erreur ou interruption (cycle $i/$N)" >&2
fi
elif [ -s "$tmp" ]; then
echo "[notary-ai-loop-n-cycles] $(date -Iseconds) — pending non vide mais agent non invoqué (RUN_AGENT=${RUN_AGENT}, agent in PATH: $(command -v agent 2>/dev/null || echo non))" >&2
fi
rm -f "$tmp"
if [ "$i" -lt "$N" ]; then
sleep "$INTER_CYCLE_SLEEP"
fi
i=$((i + 1))
done
echo "[notary-ai-loop-n-cycles] $(date -Iseconds)${N} cycles terminés."