/journal-review Workflow
Inputs
User provides:
- Review period: "this week", "last week", "last N days", "this sprint", a date range (YYYY-MM-DD to YYYY-MM-DD), or omitted (defaults to "this week")
- Optional: category filter (decisions, learnings, actions, themes, or all)
Scope parameters:
JOURNAL_BASE:~/journal/(hardcoded, matches /journal and /journal-recall skills)REVIEW_CATEGORIES: decisions, learnings, actions, themesDECISION_SIGNALS: "decided", "chose", "went with", "opted for", "tradeoff", "picked", "selected", "decision:"LEARNING_SIGNALS: "learned", "discovered", "figured out", "TIL", "gotcha", "insight", "realization", "aha"ACTION_SIGNALS: "- [ ]", "TODO", "follow up", "need to", "action item", "next step"- Default review period: "this week" (Monday of current week through today)
Step 0 — Configure Review Period
Action: Parse user input to determine the date range for the review.
Date resolution rules:
- "this week" (or omitted): Monday of current week through today (inclusive)
- "last week": Monday through Sunday of previous week
- "last N days": Today minus N through today (inclusive)
- "this sprint": Last 14 days (2-week sprint default)
- Date range (YYYY-MM-DD to YYYY-MM-DD): Exact range specified
- Single date: That date only
Validation:
- Start date must not be in the future
- End date must be >= start date
- Range must not exceed 90 days (safety limit)
- If validation fails, report error and FAIL
Category filter:
- If user specifies a category, only scan for that category
- Default: all categories (decisions, learnings, actions, themes)
Tool declarations: Bash (date calculations)
Checkpoint: Review period resolved to concrete start/end dates, categories determined
Step 1 — Scan Daily and Meeting Entries
Action: Read all daily and meeting entries within the review period.
File discovery:
- Use Glob to find daily entries:
$JOURNAL_BASE/daily/*.md - Filter by date range: parse
YYYY-MM-DDfrom filename, include if within [start, end] - Use Glob to find meeting entries:
$JOURNAL_BASE/meetings/*.md - Filter meetings by date: parse
YYYY-MM-DDprefix from filename - Read all matching files
If no entries found:
- Report: "No daily or meeting entries found for {date range}. Nothing to review."
- Verdict:
PASS: no entries found for review period (searched daily/ and meetings/) - STOP (do not proceed to Step 2)
Content extraction per file:
- Store full content indexed by file path and date
- Extract section content for targeted scanning in Step 2
Tool declarations: Glob (find files), Read (file content), Bash (date filtering)
Checkpoint: All entries for review period loaded into working memory
Step 2 — Extract Candidates
Action: Scan loaded entries for each active category using signal-word matching and contextual analysis.
Resilience note: Scan the full file content for signal words using grep-style matching across the entire entry text, not only named sections. Section-scoped matches (e.g., content found under ## Decisions Made) are treated as higher-confidence candidates, but signal matches anywhere in the file are included. If an entry is missing expected sections (e.g., no ## Learnings heading), log a warning but still scan the full content.
2a — Unlogged Decisions
Scan strategy:
- Search the full entry content for decision-signal language: "decided", "chose", "went with", "opted for", "tradeoff", "picked", "selected", and variations (case-insensitive)
- Also scan
## Decisions Madesections in daily entries for inline decisions not linked todecisions/files (matches here are higher-confidence) - For each match, extract:
- Source file and date
- Decision text: the sentence or bullet containing the signal word, plus 1-2 lines of surrounding context
- Inferred topic: a short descriptive name for the decision (e.g., "Use contrib/ directory for personal skills")
- Exclude matches that are:
- Inside wikilinks to existing decision files (e.g.,
[[decisions/2026-02-23-worktree-isolation]]) - Clearly referencing past decisions already recorded (e.g., "as we decided in the ADR...")
- Inside wikilinks to existing decision files (e.g.,
2b — Unlogged Learnings
Scan strategy:
- Search entry content for learning-signal language: "learned", "discovered", "figured out", "TIL", "gotcha", "insight", "realization", and variations
- Also scan
## Learningssections and**Learning:**fields in work session blocks - For each match, extract:
- Source file and date
- Learning text: the sentence or bullet containing the signal word, plus context
- Inferred topic: a short descriptive name (e.g., "Git worktrees are lightweight")
- Exclude matches that:
- Link to existing learning files (e.g.,
[[learnings/project-recovery-strategy]]) - Are trivial observations (single words, vague statements)
- Link to existing learning files (e.g.,
2c — Untracked Action Items
Scan strategy:
- Search for unchecked checkboxes:
- [ ](not- [x]) - Search for TODO markers: "TODO", "FIXME", "HACK" (case-insensitive)
- Search for follow-up language: "follow up", "need to", "action item", "next step"
- Also scan
## Tomorrow's Priorities,## Action Items,## Follow-up,## Next Stepssections - For each match, extract:
- Source file and date
- Action text: the specific action item or TODO
- Assignee: if present (e.g.,
@personin meeting notes) - Due date: if mentioned
- Cross-reference: check if the same action item text appears as
- [x](completed) in a later daily entry within the vault. If so, mark as "completed" and exclude from candidates.
2d — Recurring Themes
Scan strategy:
- Analyze all loaded entries for recurring topics:
- Project names: Extract from YAML frontmatter
projects:field and**Project:**lines - Technologies/tools: Mentioned multiple times across entries
- Problem patterns: Similar blockers, challenges, or concerns appearing in multiple entries
- People/teams: Recurring collaborators or stakeholders
- Project names: Extract from YAML frontmatter
- A theme is "recurring" if it appears in 2+ entries within the review period
- For each theme, extract:
- Theme name: descriptive label
- Frequency: number of entries mentioning it
- Dates: which entries
- Context snippets: representative excerpts from each mention
Tool declarations: Grep (signal-word search), Read (section extraction — files already loaded from Step 1)
Checkpoint: All candidates extracted and categorized
Step 3 — Cross-Reference Existing Entries
Action: For decision and learning candidates, check whether a formal entry already exists that covers the same topic.
Decisions cross-reference:
- Use Glob to list all files in
$JOURNAL_BASE/decisions/ - Read the title (from
# ADR:heading or YAMLtitle:field) of each existing decision file - For each decision candidate from Step 2a, compare the candidate's inferred topic against existing decision titles and content summaries
- Semantic matching: The candidate topic and existing entry title/context describe the same decision, even if worded differently. For example, candidate "chose contrib/ over skills/ for journal" matches existing ADR titled "Journal Distribution Model" if the content discusses the same choice.
- If a confident semantic match is found, move the candidate to the Filtered candidates list (not silently dropped — reported in Step 4). Record the matched existing entry and the reason for filtering.
- If uncertain whether a candidate matches an existing entry, keep the candidate but annotate it: "Possible duplicate of: {existing entry title}."
- If no match, keep the candidate
Learnings cross-reference:
- Use Glob to list all files in
$JOURNAL_BASE/learnings/ - Read the title (from
# Learning:heading or YAMLtitle:field) of each existing