From 0cc4c429f2088b850d48562b28be9d72d558a6a8 Mon Sep 17 00:00:00 2001 From: Agent Date: Wed, 1 Apr 2026 09:39:57 +0000 Subject: [PATCH] fix: feat(20g): migrate all remaining agents to .profile + remove ops repo journal dirs (#90) --- AGENTS.md | 41 +++++++++++++++++++++++++++++++++--- bin/disinto | 5 ----- gardener/gardener-run.sh | 20 ++++++++++++++++-- predictor/predictor-run.sh | 23 +++++++++++++++++--- review/review-poll.sh | 8 +++++++ review/review-pr.sh | 19 +++++++++++++++++ supervisor/supervisor-run.sh | 20 ++++++++++++++++-- 7 files changed, 121 insertions(+), 15 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index a6ac1fd..ca1e538 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -38,9 +38,6 @@ disinto-ops/ (ops repo — {project}-ops) │ ├── approved/ approved vault items │ ├── fired/ executed vault items │ └── rejected/ rejected vault items -├── journal/ -│ ├── planner/ daily planning logs -│ └── supervisor/ operational health logs ├── knowledge/ shared agent knowledge + best practices ├── evidence/ engagement data, experiment results ├── portfolio.md addressables + observables @@ -48,6 +45,44 @@ disinto-ops/ (ops repo — {project}-ops) └── RESOURCES.md accounts, tokens (refs), infra inventory ``` +> **Note:** Journal directories (`journal/planner/` and `journal/supervisor/`) have been removed from the ops repo. Agent journals are now stored in each agent's `.profile` repo on Forgejo. + +## Agent .profile repos + +Each agent maintains a `.profile` repo on Forgejo that stores: +- `formula.toml` — Agent-specific formula (overrides local `formulas/` defaults) +- `knowledge/lessons-learned.md` — Aggregated lessons from journal digests +- `journal/` — Per-session reflection journals (archived after digestion) + +### Formula resolution + +Agents load their formula from `.profile` first, falling back to local `formulas/`: + +```bash +load_formula_or_profile "agent-role" "formulas/agent-role.toml" +``` + +### Lessons injection + +At session start, agents load `knowledge/lessons-learned.md` from `.profile` and inject it into the prompt: + +```bash +profile_load_lessons || true +LESSONS_INJECTION="${LESSONS_CONTEXT:-}" +``` + +### Journal writing + +After each session, agents write reflection journals to `.profile/journal/`: + +```bash +profile_write_journal "$ISSUE" "$ISSUE_TITLE" "$outcome" "$FILES_CHANGED" +``` + +Journals are automatically digested into `lessons-learned.md` when undigested count exceeds 10. + +See [lib/formula-session.sh](lib/formula-session.sh) for the full `.profile` API reference. + > **Terminology note:** "Formulas" in this repo are TOML issue templates in `formulas/` that > orchestrate multi-step agent tasks (e.g., `run-gardener.toml`, `run-planner.toml`). This is > distinct from "processes" described in `docs/EVIDENCE-ARCHITECTURE.md`, which are measurement diff --git a/bin/disinto b/bin/disinto index cc9a95d..5528f36 100755 --- a/bin/disinto +++ b/bin/disinto @@ -896,8 +896,6 @@ setup_ops_repo() { mkdir -p "${ops_root}/vault/approved" mkdir -p "${ops_root}/vault/fired" mkdir -p "${ops_root}/vault/rejected" - mkdir -p "${ops_root}/journal/planner" - mkdir -p "${ops_root}/journal/supervisor" mkdir -p "${ops_root}/knowledge" mkdir -p "${ops_root}/evidence/engagement" @@ -916,9 +914,6 @@ ${ops_name}/ │ ├── approved/ # approved vault items │ ├── fired/ # executed vault items │ └── rejected/ # rejected vault items -├── journal/ -│ ├── planner/ # daily planning logs -│ └── supervisor/ # operational health logs ├── knowledge/ # shared agent knowledge and best practices ├── evidence/ # engagement data, experiment results ├── portfolio.md # addressables + observables diff --git a/gardener/gardener-run.sh b/gardener/gardener-run.sh index 31aa8c0..9a83fc9 100755 --- a/gardener/gardener-run.sh +++ b/gardener/gardener-run.sh @@ -64,10 +64,20 @@ check_memory 2000 log "--- Gardener run start ---" +# ── Resolve agent identity for .profile repo ──────────────────────────── +if [ -z "${AGENT_IDENTITY:-}" ] && [ -n "${FORGE_GARDENER_TOKEN:-}" ]; then + AGENT_IDENTITY=$(curl -sf -H "Authorization: token ${FORGE_GARDENER_TOKEN}" \ + "${FORGE_URL:-http://localhost:3000}/api/v1/user" 2>/dev/null | jq -r '.login // empty' 2>/dev/null || true) +fi + # ── Load formula + context ─────────────────────────────────────────────── -load_formula "$FACTORY_ROOT/formulas/run-gardener.toml" +load_formula_or_profile "gardener" "$FACTORY_ROOT/formulas/run-gardener.toml" || exit 1 build_context_block AGENTS.md +# ── Load lessons from .profile repo (pre-session) ──────────────────────── +profile_load_lessons || true +LESSONS_INJECTION="${LESSONS_CONTEXT:-}" + # ── Read scratch file (compaction survival) ─────────────────────────────── SCRATCH_CONTEXT=$(read_scratch_context "$SCRATCH_FILE") SCRATCH_INSTRUCTION=$(build_scratch_instruction "$SCRATCH_FILE") @@ -105,7 +115,10 @@ You have full shell access and --dangerously-skip-permissions. Fix what you can. File vault items for what you cannot. Do NOT ask permission — act first, report after. ## Project context -${CONTEXT_BLOCK} +${CONTEXT_BLOCK}${LESSONS_INJECTION:+## Lessons learned +${LESSONS_INJECTION} + +} ${SCRATCH_CONTEXT:+${SCRATCH_CONTEXT} } ## Result file @@ -334,5 +347,8 @@ else rm -f "$SCRATCH_FILE" fi +# Write journal entry post-session +profile_write_journal "gardener-run" "Gardener run $(date -u +%Y-%m-%d)" "complete" "" || true + rm -f "$GARDENER_PR_FILE" log "--- Gardener run done ---" diff --git a/predictor/predictor-run.sh b/predictor/predictor-run.sh index fb9bf51..943a630 100755 --- a/predictor/predictor-run.sh +++ b/predictor/predictor-run.sh @@ -53,13 +53,23 @@ check_memory 2000 log "--- Predictor run start ---" +# ── Resolve agent identity for .profile repo ──────────────────────────── +if [ -z "${AGENT_IDENTITY:-}" ] && [ -n "${FORGE_PREDICTOR_TOKEN:-}" ]; then + AGENT_IDENTITY=$(curl -sf -H "Authorization: token ${FORGE_PREDICTOR_TOKEN}" \ + "${FORGE_URL:-http://localhost:3000}/api/v1/user" 2>/dev/null | jq -r '.login // empty' 2>/dev/null || true) +fi + # ── Load formula + context ─────────────────────────────────────────────── -load_formula "$FACTORY_ROOT/formulas/run-predictor.toml" +load_formula_or_profile "predictor" "$FACTORY_ROOT/formulas/run-predictor.toml" || exit 1 build_context_block AGENTS.md ops:RESOURCES.md VISION.md ops:prerequisites.md # ── Build structural analysis graph ────────────────────────────────────── build_graph_section +# ── Load lessons from .profile repo (pre-session) ──────────────────────── +profile_load_lessons || true +LESSONS_INJECTION="${LESSONS_CONTEXT:-}" + # ── Read scratch file (compaction survival) ─────────────────────────────── SCRATCH_CONTEXT=$(read_scratch_context "$SCRATCH_FILE") SCRATCH_INSTRUCTION=$(build_scratch_instruction "$SCRATCH_FILE") @@ -82,9 +92,13 @@ Use WebSearch for external signal scanning — be targeted (project dependencies and tools only, not general news). Limit to 3 web searches per run. ## Project context -${CONTEXT_BLOCK} +${CONTEXT_BLOCK}${LESSONS_INJECTION:+## Lessons learned +${LESSONS_INJECTION} + +} ${GRAPH_SECTION} -${SCRATCH_CONTEXT} +${SCRATCH_CONTEXT:+${SCRATCH_CONTEXT} +} ## Formula ${FORMULA_CONTENT} @@ -98,5 +112,8 @@ formula_worktree_setup "$WORKTREE" agent_run --worktree "$WORKTREE" "$PROMPT" log "agent_run complete" +# Write journal entry post-session +profile_write_journal "predictor-run" "Predictor run $(date -u +%Y-%m-%d)" "complete" "" || true + rm -f "$SCRATCH_FILE" log "--- Predictor run done ---" diff --git a/review/review-poll.sh b/review/review-poll.sh index 57a647c..4840b35 100755 --- a/review/review-poll.sh +++ b/review/review-poll.sh @@ -13,8 +13,16 @@ source "$(dirname "$0")/../lib/env.sh" source "$(dirname "$0")/../lib/ci-helpers.sh" # shellcheck source=../lib/guard.sh source "$(dirname "$0")/../lib/guard.sh" +# shellcheck source=../lib/formula-session.sh +source "$(dirname "$0")/../lib/formula-session.sh" check_active reviewer +# Resolve agent identity for .profile repo +if [ -z "${AGENT_IDENTITY:-}" ] && [ -n "${FORGE_TOKEN:-}" ]; then + AGENT_IDENTITY=$(curl -sf -H "Authorization: token ${FORGE_TOKEN}" \ + "${FORGE_URL:-http://localhost:3000}/api/v1/user" 2>/dev/null | jq -r '.login // empty' 2>/dev/null || true) +fi + REPO_ROOT="${PROJECT_REPO_ROOT}" SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" diff --git a/review/review-pr.sh b/review/review-pr.sh index 0ae0fdb..e1fbeb4 100755 --- a/review/review-pr.sh +++ b/review/review-pr.sh @@ -27,6 +27,7 @@ source "$(dirname "$0")/../lib/env.sh" source "$(dirname "$0")/../lib/ci-helpers.sh" source "$(dirname "$0")/../lib/worktree.sh" source "$(dirname "$0")/../lib/agent-sdk.sh" +source "$(dirname "$0")/../lib/formula-session.sh" # Auto-pull factory code to pick up merged fixes before any logic runs git -C "$FACTORY_ROOT" pull --ff-only origin main 2>/dev/null || true @@ -56,6 +57,14 @@ if [ -f "$LOGFILE" ] && [ "$(stat -c%s "$LOGFILE" 2>/dev/null || echo 0)" -gt 10 mv "$LOGFILE" "$LOGFILE.old" fi +# ============================================================================= +# RESOLVE AGENT IDENTITY FOR .PROFILE REPO +# ============================================================================= +if [ -z "${AGENT_IDENTITY:-}" ] && [ -n "${FORGE_TOKEN:-}" ]; then + AGENT_IDENTITY=$(curl -sf -H "Authorization: token ${FORGE_TOKEN}" \ + "${FORGE_URL:-http://localhost:3000}/api/v1/user" 2>/dev/null | jq -r '.login // empty' 2>/dev/null || true) +fi + # ============================================================================= # MEMORY GUARD # ============================================================================= @@ -180,6 +189,12 @@ else log "WARN: build-graph.py failed — continuing without structural analysis" fi +# ============================================================================= +# LOAD LESSONS FROM .PROFILE REPO (PRE-SESSION) +# ============================================================================= +profile_load_lessons || true +LESSONS_INJECTION="${LESSONS_CONTEXT:-}" + # ============================================================================= # BUILD PROMPT # ============================================================================= @@ -193,6 +208,7 @@ FORMULA=$(cat "${FACTORY_ROOT}/formulas/review-pr.toml") "$PR_BODY" "$FILES" "$DNOTE" "$DIFF" [ -n "$PREV_CONTEXT" ] && printf '%s\n' "$PREV_CONTEXT" [ -n "$GRAPH_SECTION" ] && printf '%s\n' "$GRAPH_SECTION" + [ -n "$LESSONS_INJECTION" ] && printf '\n## Lessons learned\n%s\n\n' "$LESSONS_INJECTION" printf '\n## Formula\n%s\n\n## Environment\nREVIEW_OUTPUT_FILE=%s\nFORGE_API=%s\nPR_NUMBER=%s\nFACTORY_ROOT=%s\n' \ "$FORMULA" "$OUTPUT_FILE" "$API" "$PR_NUMBER" "$FACTORY_ROOT" printf 'NEVER echo the actual token — always reference ${FORGE_TOKEN} or ${FORGE_REVIEW_TOKEN}.\n' @@ -298,4 +314,7 @@ case "$VERDICT" in ;; esac +# Write journal entry post-session +profile_write_journal "review-${PR_NUMBER}" "Review PR #${PR_NUMBER} (${VERDICT})" "${VERDICT,,}" "" || true + log "DONE: ${VERDICT} (re-review: ${IS_RE_REVIEW})" diff --git a/supervisor/supervisor-run.sh b/supervisor/supervisor-run.sh index 129666f..48e292e 100755 --- a/supervisor/supervisor-run.sh +++ b/supervisor/supervisor-run.sh @@ -58,6 +58,12 @@ log "--- Supervisor run start ---" # ── Housekeeping: clean up stale crashed worktrees (>24h) ──────────────── cleanup_stale_crashed_worktrees 24 +# ── Resolve agent identity for .profile repo ──────────────────────────── +if [ -z "${AGENT_IDENTITY:-}" ] && [ -n "${FORGE_SUPERVISOR_TOKEN:-}" ]; then + AGENT_IDENTITY=$(curl -sf -H "Authorization: token ${FORGE_SUPERVISOR_TOKEN}" \ + "${FORGE_URL:-http://localhost:3000}/api/v1/user" 2>/dev/null | jq -r '.login // empty' 2>/dev/null || true) +fi + # ── Collect pre-flight metrics ──────────────────────────────────────────── log "Running preflight.sh" PREFLIGHT_OUTPUT="" @@ -68,9 +74,13 @@ else fi # ── Load formula + context ─────────────────────────────────────────────── -load_formula "$FACTORY_ROOT/formulas/run-supervisor.toml" +load_formula_or_profile "supervisor" "$FACTORY_ROOT/formulas/run-supervisor.toml" || exit 1 build_context_block AGENTS.md +# ── Load lessons from .profile repo (pre-session) ──────────────────────── +profile_load_lessons || true +LESSONS_INJECTION="${LESSONS_CONTEXT:-}" + # ── Read scratch file (compaction survival) ─────────────────────────────── SCRATCH_CONTEXT=$(read_scratch_context "$SCRATCH_FILE") SCRATCH_INSTRUCTION=$(build_scratch_instruction "$SCRATCH_FILE") @@ -91,7 +101,10 @@ Fix what you can. File vault items for what you cannot. Do NOT ask permission ${PREFLIGHT_OUTPUT} ## Project context -${CONTEXT_BLOCK} +${CONTEXT_BLOCK}${LESSONS_INJECTION:+## Lessons learned +${LESSONS_INJECTION} + +} ${SCRATCH_CONTEXT:+${SCRATCH_CONTEXT} } Priority order: P0 memory > P1 disk > P2 stopped > P3 degraded > P4 housekeeping @@ -105,5 +118,8 @@ ${PROMPT_FOOTER}" agent_run --worktree "$WORKTREE" "$PROMPT" log "agent_run complete" +# Write journal entry post-session +profile_write_journal "supervisor-run" "Supervisor run $(date -u +%Y-%m-%d)" "complete" "" || true + rm -f "$SCRATCH_FILE" log "--- Supervisor run done ---"