feat: generic journal aspect — post-session reflection + lessons-learned context injection #97

Closed
opened 2026-04-01 08:15:53 +00:00 by dev-bot · 0 comments
Collaborator

Problem

Journaling is currently planner-specific (hardcoded in formulas/run-planner.toml step 3). The .profile issue chain (#86, #89) proposed journal writing and digestion as separate features. But journaling, digestion, and learning are one cross-cutting concern — every agent benefits from reflecting on what it learned, and the digestion should happen lazily before the next session, not via a separate agent.

Proposed design

Three functions in lib/formula-session.sh, opt-in by .profile repo existence:

1. Pre-session: profile_load_lessons

Hook point: During prompt construction, before the main session starts (in dev-agent.sh, *-run.sh, etc.)

What it does:

  1. Check if the agent has a .profile repo (Forgejo API: GET /repos/<login>/.profile). If not, return silently.
  2. Clone/pull .profile to a cache dir (/home/agent/data/.profile/)
  3. Check journal accumulation: count files in journal/ (exclude archive/). If >10 undigested entries:
    a. Run a claude -p one-shot (same model as the agent, max_tokens 1000) with:
    • All journal entries as input
    • Existing knowledge/lessons-learned.md (if any)
    • Prompt: "Condense these journal entries into abstract, transferable lessons. Rewrite lessons-learned.md entirely. Hard cap: 2KB. Drop the least transferable lessons if over limit. No specific issue numbers, file paths, or one-off details — only patterns and heuristics that help with work you have never seen before."
      b. Write the response to knowledge/lessons-learned.md (full rewrite)
      c. Move digested journals to journal/archive/
      d. Commit and push to .profile repo
  4. Read knowledge/lessons-learned.md (hard cap at 2KB, truncate if larger) and set LESSONS_CONTEXT
  5. The calling script includes LESSONS_CONTEXT in the prompt

Key: Digestion is lazy — it only happens when the agent is about to run anyway, and only if enough journals have accumulated. No separate cron, no gardener, no coordinator. The phase handler does it in-line before handing off to the main session.

2. Post-session: profile_write_journal

Hook point:

  • dev-agent.sh: after PR merge/block, before worktree_cleanup
  • run_formula_and_monitor(): after PHASE:done, before remove_formula_worktree

What it does:

  1. Check if the agent has a .profile repo. If not, return silently.
  2. Pull .profile cache
  3. Invoke a claude -p one-shot (same model as the agent, max_tokens 500) with:
    • The issue/task that was worked on (number, title, outcome)
    • A brief session summary (files changed, PR number, pass/fail)
    • Prompt: "What did you learn from this session that would help you do similar work better next time? Write a concise journal entry focused on transferable lessons, not a summary of what you did."
  4. Write the response to .profile/journal/issue-<N>.md (append if exists)
  5. Commit and push to .profile repo

Important: This is a reflection prompt, not a log. The agent extracts lessons, not narrates actions.

3. Opt-in mechanism

The .profile repo existence is the flag. No config, no env var, no state file. If hire-an-agent was run for this agent, it has a .profile. If not, both functions are silent no-ops.

Lessons-learned constraints

knowledge/lessons-learned.md must be:

  • Hard capped at 2KB — digestion must stay within this. If over, drop least transferable lessons.
  • Abstract — patterns and heuristics, not specific issues or file paths.
  • Transferable — must help with future unseen work, not just recall past work.
  • Full rewrite on each digestion (not append). The file is always a clean, current summary.

Model

Both one-shot calls (journal + digestion) use the same model the agent is already running. The reflection should be done by the same mind that did the work. No model switching.

Relationship to existing issues

  • Supersedes #86 (journal writing — closed)
  • Absorbs #89 (journal digestion — closed, folded into profile_load_lessons)
  • Simplifies planner — planner step 3 journaling replaced by generic profile_write_journal

Affected files

  • lib/formula-session.sh — add profile_load_lessons() and profile_write_journal()
  • dev/dev-agent.sh — call both functions at appropriate hook points
  • planner/planner-run.sh — call profile_load_lessons during prompt setup, profile_write_journal post-session
  • formulas/run-planner.toml — simplify step 3, remove planner-specific journaling

Acceptance criteria

  • profile_load_lessons checks journal count and triggers digestion when >10
  • Digestion runs as claude -p one-shot before main session (same model, max_tokens 1000)
  • Digestion rewrites knowledge/lessons-learned.md (full rewrite, not append)
  • lessons-learned.md hard capped at 2KB, abstract, no specific issue/file references
  • Digested journals archived to journal/archive/
  • profile_load_lessons injects lessons into agent context when available
  • profile_load_lessons is a no-op when agent has no .profile repo
  • profile_write_journal writes a reflection entry after each session (same model, max_tokens 500)
  • profile_write_journal is a no-op when agent has no .profile repo
  • Planner custom journaling replaced by generic function
  • CI green

Dependencies

Depends on #84 (hire-an-agent — .profile repo must exist for dev-qwen).
Supersedes #86 (closed). Absorbs #89 (closed).

## Problem Journaling is currently planner-specific (hardcoded in `formulas/run-planner.toml` step 3). The .profile issue chain (#86, #89) proposed journal writing and digestion as separate features. But journaling, digestion, and learning are one cross-cutting concern — every agent benefits from reflecting on what it learned, and the digestion should happen lazily before the next session, not via a separate agent. ## Proposed design Three functions in `lib/formula-session.sh`, opt-in by `.profile` repo existence: ### 1. Pre-session: `profile_load_lessons` **Hook point:** During prompt construction, before the main session starts (in `dev-agent.sh`, `*-run.sh`, etc.) **What it does:** 1. Check if the agent has a `.profile` repo (Forgejo API: `GET /repos/<login>/.profile`). If not, return silently. 2. Clone/pull `.profile` to a cache dir (`/home/agent/data/.profile/`) 3. **Check journal accumulation:** count files in `journal/` (exclude `archive/`). If >10 undigested entries: a. Run a `claude -p` one-shot (same model as the agent, max_tokens 1000) with: - All journal entries as input - Existing `knowledge/lessons-learned.md` (if any) - Prompt: "Condense these journal entries into abstract, transferable lessons. Rewrite lessons-learned.md entirely. Hard cap: 2KB. Drop the least transferable lessons if over limit. No specific issue numbers, file paths, or one-off details — only patterns and heuristics that help with work you have never seen before." b. Write the response to `knowledge/lessons-learned.md` (full rewrite) c. Move digested journals to `journal/archive/` d. Commit and push to `.profile` repo 4. Read `knowledge/lessons-learned.md` (hard cap at 2KB, truncate if larger) and set `LESSONS_CONTEXT` 5. The calling script includes `LESSONS_CONTEXT` in the prompt **Key:** Digestion is lazy — it only happens when the agent is about to run anyway, and only if enough journals have accumulated. No separate cron, no gardener, no coordinator. The phase handler does it in-line before handing off to the main session. ### 2. Post-session: `profile_write_journal` **Hook point:** - `dev-agent.sh`: after PR merge/block, before `worktree_cleanup` - `run_formula_and_monitor()`: after PHASE:done, before `remove_formula_worktree` **What it does:** 1. Check if the agent has a `.profile` repo. If not, return silently. 2. Pull `.profile` cache 3. Invoke a `claude -p` one-shot (same model as the agent, max_tokens 500) with: - The issue/task that was worked on (number, title, outcome) - A brief session summary (files changed, PR number, pass/fail) - Prompt: "What did you learn from this session that would help you do similar work better next time? Write a concise journal entry focused on transferable lessons, not a summary of what you did." 4. Write the response to `.profile/journal/issue-<N>.md` (append if exists) 5. Commit and push to `.profile` repo **Important:** This is a reflection prompt, not a log. The agent extracts lessons, not narrates actions. ### 3. Opt-in mechanism The `.profile` repo existence is the flag. No config, no env var, no state file. If `hire-an-agent` was run for this agent, it has a `.profile`. If not, both functions are silent no-ops. ### Lessons-learned constraints `knowledge/lessons-learned.md` must be: - **Hard capped at 2KB** — digestion must stay within this. If over, drop least transferable lessons. - **Abstract** — patterns and heuristics, not specific issues or file paths. - **Transferable** — must help with future unseen work, not just recall past work. - **Full rewrite** on each digestion (not append). The file is always a clean, current summary. ### Model Both one-shot calls (journal + digestion) use the **same model** the agent is already running. The reflection should be done by the same mind that did the work. No model switching. ### Relationship to existing issues - **Supersedes #86** (journal writing — closed) - **Absorbs #89** (journal digestion — closed, folded into `profile_load_lessons`) - **Simplifies planner** — planner step 3 journaling replaced by generic `profile_write_journal` ## Affected files - `lib/formula-session.sh` — add `profile_load_lessons()` and `profile_write_journal()` - `dev/dev-agent.sh` — call both functions at appropriate hook points - `planner/planner-run.sh` — call `profile_load_lessons` during prompt setup, `profile_write_journal` post-session - `formulas/run-planner.toml` — simplify step 3, remove planner-specific journaling ## Acceptance criteria - [ ] `profile_load_lessons` checks journal count and triggers digestion when >10 - [ ] Digestion runs as `claude -p` one-shot before main session (same model, max_tokens 1000) - [ ] Digestion rewrites `knowledge/lessons-learned.md` (full rewrite, not append) - [ ] lessons-learned.md hard capped at 2KB, abstract, no specific issue/file references - [ ] Digested journals archived to `journal/archive/` - [ ] `profile_load_lessons` injects lessons into agent context when available - [ ] `profile_load_lessons` is a no-op when agent has no `.profile` repo - [ ] `profile_write_journal` writes a reflection entry after each session (same model, max_tokens 500) - [ ] `profile_write_journal` is a no-op when agent has no `.profile` repo - [ ] Planner custom journaling replaced by generic function - [ ] CI green ## Dependencies Depends on #84 (hire-an-agent — .profile repo must exist for dev-qwen). Supersedes #86 (closed). Absorbs #89 (closed).
dev-bot added the
backlog
label 2026-04-01 08:39:45 +00:00
dev-qwen self-assigned this 2026-04-01 09:10:36 +00:00
dev-qwen added
in-progress
and removed
backlog
labels 2026-04-01 09:10:36 +00:00
dev-qwen removed their assignment 2026-04-01 09:34:30 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: johba/disinto#97
No description provided.