From ai-os-lite
Process a morning journal entry — extract AI summary, mood, priorities, gratitude, and people mentioned. Full insights go to the journal entry; all priorities grouped as Must do / Focus work / If time go to the daily hub. Extracted priorities become Todoist tasks (with dedup and batch approval). Use when the user says "process journal", "process today's journal", or "/process-journal".
How this skill is triggered — by the user, by Claude, or both
Slash command
/ai-os-lite:process-journalThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Extract structured insights from a raw morning journal transcript. Write the full AI analysis to the **journal entry** (private) and a grouped priority list to the **daily hub** (visible).
Extract structured insights from a raw morning journal transcript. Write the full AI analysis to the journal entry (private) and a grouped priority list to the daily hub (visible).
## Morning and ## Evening is never modified.### AI Summary section (with mood, all priorities, gratitude) replaces the placeholder at the bottom of the journal entry (nested under ## Morning). This is the private reflection space.vault-config/references/source-manifest.md.Track all source calls per vault-config/references/source-manifest.md. This skill uses:
| Source | Used For | Criticality |
|---|---|---|
| Obsidian CLI | Read journal transcript, write AI Summary | REQUIRED |
| Obsidian MCP | Patch sections, create task notes | REQUIRED |
| QMD Search | People lookup in vault contacts | LOW |
| Todoist CLI | Task creation, dedup check | HIGH |
/process-journal → process today's entry
/process-journal 2026-03-08 → process a specific date
/process-journal 2026-05-18 --dry-run → render to stdout/tmpfile, do not write the vault
Dry-run mode (--dry-run flag):
/tmp/process-journal-dryrun-$today.md instead of patching the vault.Pass --dry-run as the second argument after any date: /process-journal 2026-05-18 --dry-run.
Reference: vault-config/references/tool-selection.md CLI for reads, writes, graph traversal, and property operations. MCP only for semantic search and section-level patching. DO NOT use mcp__obsidian-mcp-tools__get_vault_file for reads.
YYYY-MM-DDUse Obsidian CLI (NOT MCP) for reads:
# Journal entry (raw transcript)
obsidian read path="5. Resources/Personal/Journal/Morning Entries/YYYY-MM-DD.md"
# Daily note hub (target for Today's priorities)
obsidian read path="1. Daily/YYYY-MM-DD.md"
DO NOT use mcp__obsidian-mcp-tools__get_vault_file — use obsidian read per the Tool Rules above.
If journal entry doesn't exist: Report "No journal entry found for YYYY-MM-DD" and stop.
If daily note doesn't exist: Report "No daily note found for YYYY-MM-DD. Create one first with Cmd+Shift+D in Obsidian." and stop.
Read all habit_* properties present in the journal entry's frontmatter — do not assume a fixed set. The habit schema is owned by the journal template (system-settings/Templates/Journal Entry Template.md); this skill reads whatever habit_* fields the entry actually carries. They are the single source of truth — the user sets them via Obsidian's Properties panel.
Extract every habit_* line from the frontmatter block:
obsidian read path="5. Resources/Personal/Journal/Morning Entries/YYYY-MM-DD.md" \
| awk '/^---$/{c++; next} c==1 && /^habit_/'
This lists each habit_*: value pair the entry carries (currently habit_workout, habit_meditation, habit_gratitude, habit_vitamins — but read what's there, don't hardcode). habit_gratitude may be set to true during Step 6 if 3 gratitude items are extracted.
No parsing or syncing needed — frontmatter IS the data.
Store the values for use in the Step 9 report (habits summary).
Scan the journal entry body for a bottom marker line matching:
*Processed YYYYMMDDHHMM · N tasks created in Todoist*
Search command:
obsidian read path="5. Resources/Personal/Journal/Morning Entries/YYYY-MM-DD.md" | grep -E '^\*Processed [0-9]{12}'
If no marker found: this is a first run — proceed normally. Step 7 will append a marker at the end.
If a marker is found: this is a re-run. Extract the timestamp and Todoist count from the marker. Warn the user:
This journal was already processed on YYYY-MM-DD at HH:MM ({N} Todoist tasks created).
Re-processing will refresh the AI Summary, mood, and grouped priorities.
Task notes and Todoist tasks that were already created will be preserved (not duplicated).
Would you like to re-process? [y/N]
Wait for confirmation. If the user declines, stop with a short message.
On re-run (user confirmed): extract the existing priorities from the current ### AI Summary and the daily hub's **Today's priorities:** section before re-extracting in Step 5. These will be merged (dedup by description) in Step 8.
Frontmatter flag: the old todoist_tasks_created frontmatter flag is no longer used. If present on an old entry, ignore it — the marker line is the sole idempotency source.
Extraction is no longer transcript-only. It runs five reads in parallel and merges the outputs into a unified "candidate priorities" list with provenance. Each candidate carries {text, source, project_hint, lane_hint, context, ai_capability} so Step 7 (task-note creation) and Step 8 (render) can set the right frontmatter tags and capability markers respectively.
| # | Source | How |
|---|---|---|
| 1 | Today's transcript (## Morning section) | obsidian read path="5. Resources/Personal/Journal/Morning Entries/$today.md" then extract under ## Morning |
| 2 | Prior-day hub | bash ${CLAUDE_PLUGIN_ROOT}/skills/process-journal/scripts/parse_prior_hub.sh $yesterday |
| 3 | /start-day's in-journal Warm/Cold recap | bash ${CLAUDE_PLUGIN_ROOT}/skills/process-journal/scripts/parse_startday_recap.sh $today |
| 4 | Project hub Current Status snapshots (only for projects named in transcript) | obsidian read path="<hub>" then locate ## Current Status |
| 5 | Contact context for each named person | bash ${CLAUDE_PLUGIN_ROOT}/skills/process-journal/scripts/resolve_contact.sh "<name>" per name |
Run sources 2, 3, and 5 unconditionally. Run source 4 only for projects the transcript explicitly names. Source 1 is the spine.
For every bullet in source #2 (parse_prior_hub.sh output):
wikilink_target that resolves to a task note via read_task_status.sh:
status == "done" → drop. The work shipped; do not carry forward.status in {"todo", "in-progress", "on-hold"} → carry as a candidate with lane_hint: "carry-forward".status empty / found: false → carry as a candidate with lane_hint: "carry-forward" and a (no task note) marker.(no task note) and lane_hint: "carry-forward".context field (e.g. "was p1 due TODAY"). Step 8's render uses this for the (carry-forward from <date>) marker on the absorbing lane.(carry-forward from <date>) marker. Items with no concrete today-action go to "Also on the radar" with (carry-forward p2 from <date>; no concrete edge today — stay aware) per Decision 9.Caveat on blocked_by parsing: read_task_status.sh reads blocked_by as a scalar via fm_value. When the task's blocked_by: frontmatter is an empty list [], the script returns the literal string "[]". Treat both "" and "[]" as "not blocked" in 5d below.
/start-day recap)For each entry in source #3 (parse_startday_recap.sh output):
lane_hint: "sub-project-under-<parent>".lane_hint: "also-on-radar" and context: "{band}, {days_silent}d".also-on-radar (no sub-project promotion).Parent-resolution heuristic: a warm project is a "child" of a transcript priority when (a) they share an area, AND (b) the transcript priority's text contains a phrase like "re-orient on", "catch up on", "audit", or "review" referencing the area — the kind of meta-priority that naturally umbrellas sub-projects. When uncertain, render as standalone "Also on the radar".
For each candidate priority surfaced by 5a/5b/5c that has an associated project slug:
blocked_by frontmatter via read_task_status.sh.
none → user has confirmed no blockers. Skip inference. Render normally."[]" / no task note → run inference (next step).bash ${CLAUDE_PLUGIN_ROOT}/skills/process-journal/scripts/scan_blockers.sh "<priority text>" "<project slug>" "<transcript path>"
~10 second budget per priority. If the scanner returns zero hits, move on (no prompt). If hits are very high (>20), summarize the top 5 by source diversity before presenting.[[Priority]] — possible blockers I found:
• <description> (source: <source_path> · <source_section>)
• <description> (source: <source_path> · <source_section>)
[Confirm + record] [Edit] [Skip — not blocked]
"Email NACA advisor to set meeting date", "Confirm IRS extension status and schedule tax-return prep block". The user confirms creation; Step 7 (the task-creation step) then creates the task note with ← unblocks <chain> reasoning written into the body. No chain gets confirmed without producing at least one concrete actionable task — vague execution-strategy steps are not acceptable.blocked_by: to the priority's task note frontmatter (only if the task note exists).blocked_by: none to the task note. This is the permanent "user confirmed no blockers" marker — never re-infer.If no task note exists for the priority and the user confirms blockers, the blocked_by write is deferred to Step 7 (the task-creation step, when the task note is created). The chain back-reference renders inline on the bullet in Step 8 (the render step) from the in-memory result, formatted per the 5/18 delta:
← unblocks <plain description>← part of the <cluster name> (e.g. "the reply-debt cluster")← starts the <path name> (e.g. "the NACA approval path (next: advisor meeting → approval → city decision)")For each first-name mentioned in the transcript:
bash ${CLAUDE_PLUGIN_ROOT}/skills/process-journal/scripts/resolve_contact.sh "<name>".found: true: use the canonical wikilink + context summary in any priority bullet that mentions this person.found: false: use the raw name as a red wikilink ([[Raw Name]]) so clicking it creates the contact page later.People mentioned line (Step 6), use the same resolved wikilinks. Do not duplicate the resolution.After 5b/5c/5d/5e produce their candidate sets, extract from the transcript itself:
source: "transcript" and a project_hint extracted from surrounding context (project name mentioned, area implied).tags: [task, research]. They do NOT render in a separate "Research questions" lane — they surface via the existing Tasks Overview Base on the daily hub. Treat as a regular candidate with lane_hint determined by Section 8a rules; the research tag is added in Step 7 (task-note creation).lane_hint: "could-hand-off-to-ai" and ai_capability: "ai-handoff" (set in 5h).**Gratitude**: ⚠️ No gratitude entry today. What are 3 things you're grateful for?Combine the candidate lists from 5b + 5c + 5f into one list. Dedup by (project_slug, normalized_text) — two candidates that point to the same underlying work merge, with the union of their context fields kept on the surviving entry. Provenance is preserved (source: ["transcript", "carry-forward"] etc.) for the Step 8 parenthetical suffix.
When a transcript candidate matches a carry-forward candidate (same task note or same normalized text): the carry-forward annotation is dropped from the parenthetical (the transcript reinforces today; no need to surface "carry-forward" since it's already actively on the mind). The (carry-forward from <date>) marker only renders when the user did NOT re-mention it.
For each merged candidate from 5g, classify into one of three AI-capability levels. This drives the task-note tags: frontmatter (Step 7, the task-creation step) and the bullet capability marker (Step 8, the render step).
| Classification | Tag set | Bullet marker | Rule |
|---|---|---|---|
human-only | [task] | (unmarked) | Replies, person-to-person comms, identity-level decisions, anything requiring tacit context the AI can't fully see |
ai-handoff | [task, ai-handoff] | 🤖 | Codebase work + research + structured queries with clear inputs — AI can run autonomously now |
ai-pending-decision | [task, ai-pending-decision] | ⏳ | Code/work that depends on a specific human decision named in the note body |
Persist the classification on the candidate as ai_capability. Step 7 (task-creation) reads it to set tags: on the task note; Step 8 (render) reads it to render the marker prefix.
Note on GWS-CLI deferral: Reply-drafting via GWS-CLI is deferred until permissions land. Once shipped, draftable replies graduate to ai-pending-decision (AI drafts → user reviews → user sends). Until then, replies stay human-only.
The ### AI Summary heading already exists at the bottom of the journal entry (placed by ensure_journal.sh with placeholder text, nested under ## Morning). Replace its content using a heading-targeted patch.
mcp__obsidian-mcp-tools__patch_vault_file(
filename="5. Resources/Personal/Journal/Morning Entries/YYYY-MM-DD.md",
operation="replace",
targetType="heading",
target="AI Summary",
content="""**Summary**: [extracted summary]
**Mood**: [extracted mood]
**Gratitude**:
1. [item 1]
2. [item 2]
3. [item 3]
**People mentioned**: [[Person 1]], [[Person 2]]
"""
)
What's NOT in the AI Summary:
People mentioned — always use [[wikilinks]] for people, even if no contact page exists yet (red links in Obsidian prompt page creation later). Search vault contacts first for full names:
mcp__qmd__search(query="{Contact}", collection="vault")
If found: [[{Contact} {ContactLastName}]] (full name from contact page)
If not found: [[{Contact}]] (red link — creates page when clicked)
Re-processing (merge behavior): If the user re-processes an already-processed entry (Step 3 confirmed):
Use replace on the existing AI Summary heading instead of append. Do NOT include ### AI Summary in the content when using replace — the heading itself is preserved by the patch tool.
Cross-reference extracted priorities against existing task notes:
For each extracted priority, use the shared helper:
bash ${CLAUDE_PLUGIN_ROOT}/skills/start-day/scripts/match_task_note.sh "distinctive keywords"
This searches all */Tasks/*.md locations (2. Projects/{Area}/Tasks/, 2. Projects/{Area}/{Project}/Tasks/, Personal/Tasks/, Personal/{Project}/Tasks/).
If a matching task note exists: note it for the daily hub display (include task note status and priority)
If no task note exists and the priority warrants one (specific action, due date, multi-session): flag for creation in Step 7 (task-creation step)
/start-day Step 4b renders the Previous Evening link inside the ### Last Night's Reflection blockquote. This step is a safety net for when /start-day was skipped: if the ### Last Night's Reflection section has no Previous Evening link, insert one inside that section's blockquote:
> **Previous Evening**: [[5. Resources/Personal/Journal/Evening Entries/YYYY-MM-DD-1|Last Night's Evening]]
Where YYYY-MM-DD-1 is yesterday's date. If the link is already present (the normal case — /start-day ran), do nothing. Never insert it at the top of the file.
Task notes are the source of truth. Todoist is a notification/reminder layer. This step creates task notes first, then optionally mirrors them to Todoist. This step runs BEFORE Step 8 (render) so that every actionable bullet on the rendered hub wikilinks to a real task note — no (no task note — create) placeholders.
| Classification | Criteria | Action |
|---|---|---|
| Task note warranted | Specific action, has a due date, spans sessions, or p1/p2 | Create task note (7c), optionally mirror to Todoist (7e) |
| Quick action | Sub-15-min, no tracking needed | Todoist-only (7e) or skip entirely |
| Reflection | Vague intention, life decision, habit/routine | Skip — leave in journal only |
For each priority classified as "task note warranted", run:
bash ${CLAUDE_PLUGIN_ROOT}/skills/start-day/scripts/match_task_note.sh "distinctive keywords"
If a matching task note is found:
status: done, note it for the batch presentation ("mentioned again — reopen?")Per spec Section 4 (Area-Level Task Routing):
| Priority's area | Task note location |
|---|---|
| Work/business project ({WorkArea}/{SideArea2}/{SideArea} + project) | 2. Projects/{Area}/{Project}/Tasks/{Task Name}.md |
| Work/business area (no project) | 2. Projects/{Area}/Tasks/{Task Name}.md |
| Personal life project (APAC-Trip, Health, Finances, etc.) | Personal/{Project}/Tasks/{Task Name}.md |
| Personal life area (no project) | Personal/Tasks/{Task Name}.md |
Never route task notes to the knowledge-notes folder — task notes live exclusively under */Tasks/ per the table above.
The tags: block is set from the candidate's ai_capability field (assigned in Step 5h):
ai_capability | tags: |
|---|---|
human-only (default) | [task] |
ai-handoff | [task, ai-handoff] |
ai-pending-decision | [task, ai-pending-decision] |
If the candidate is a research question (per Step 5f), the research tag is added on top of the above. These tags mirror to Todoist/Linear labels via Step 7e (the Todoist mirror sub-step).
# Determine tags based on the candidate's ai_capability (from Step 5h)
if candidate.ai_capability == "ai-handoff":
tags = "tags:\n - task\n - ai-handoff"
elif candidate.ai_capability == "ai-pending-decision":
tags = "tags:\n - task\n - ai-pending-decision"
else: # human-only (default)
tags = "tags:\n - task"
# If candidate is a research question (per Step 5f), add `research` tag
if candidate.is_research_question:
tags += "\n - research"
mcp__obsidian-mcp-tools__create_vault_file(
filename="{routed_path}",
content=f"""---
date: YYYY-MM-DD
type: task
status: todo
area: {area_slug}
project: {project_slug}
priority: {p_level}
due_date: "{YYYY-MM-DD if known else empty}"
scheduled_date: ""
done_date: ""
blocked_by: ""
external_id: ""
{tags}
---
# {Task Name}
> **Project**: [[{Project Hub}]]
{1-2 sentences of context from the journal transcript}
## Dev Log
<triple-backtick>base
filters:
and:
- type == "devlog"
- tasks == "[[{Task Name}]]"
views:
- type: table
name: Related Sessions
order:
- date
- file.name
- session_topic
sort:
- property: date
direction: DESC
<triple-backtick>
"""
)
(Replace <triple-backtick> above with three literal backticks when writing actual task note content. The skill doc can't inline nested triple-backticks cleanly.)
For each new task note (or existing task note re-mentioned today), decide whether to mirror to Todoist:
| Create Todoist mirror? | When |
|---|---|
| Yes | Has a due date, or priority p1/p2, or user needs a reminder notification |
| No | Reference task that lives in the task note alone (e.g., "figure out X") |
If mirroring:
td task add "Task description" \
--project "{AreaProject}" \
--labels "{area_label}" \
--priority p3 \
--due "today"
Record the Todoist task ID in the task note's external_id frontmatter:
obsidian property:set path="{task note path}" property="external_id" value="Todoist: {task_id}"
Before creating anything, present the batch:
Task proposals from YYYY-MM-DD journal:
CREATE TASK NOTES ({N}):
├─ [{Area}/{Project}/Tasks/{Name}] — {summary} [priority, due_date]
└─ ...
MIRROR TO TODOIST ({M}):
├─ Task note {Name} → Todoist "{Name}" [project, p-level, due]
└─ ...
TODOIST-ONLY / QUICK ACTIONS ({Q}):
├─ "{text}" → Todoist [project, p4]
└─ ...
SKIP ({S} — not actionable):
├─ "{text}" — reflection
└─ ...
EXISTING TASK NOTES ({E} — already present):
├─ {Name} (status: todo) — mentioned again, comment added to Todoist
└─ ...
Create these? [Y/n/edit]
Wait for user confirmation. If user says "edit", ask which items to modify. If "n", skip creation and proceed to Step 7g.
After all creation steps complete (even if the user skipped all), append a marker line to the journal entry body.
First run (no existing marker):
obsidian append path="5. Resources/Personal/Journal/Morning Entries/YYYY-MM-DD.md" content="
*Processed ${timestamp} · ${todoist_count} tasks created in Todoist*"
Where timestamp is YYYYMMDDHHMM (e.g., 202604201239) and todoist_count is the number of Todoist tasks actually created in this run.
Re-run (existing marker detected in Step 4): REPLACE the existing marker line in place — do NOT append a second marker line. Use direct file edit (read the file, sed-replace the *Processed ... line, write back). Appending would compound the MCP patch_vault_file bottom-append bug that motivated this refinement.
Do NOT set any frontmatter flag — todoist_tasks_created and journal_processed are both dropped. The marker line is the sole idempotency source.
This step composes the 6-lane priorities block and writes it to the daily hub via a single MCP heading patch on Morning Journal. The lanes are populated from the merged candidate list produced in Step 5g, classified by lane_hint, then rendered with capability markers, inline chain back-references, and contextual suffixes. By the time this step runs, Step 7 has already created task notes for every actionable candidate — so every bullet wikilinks to a real note, no (no task note — create) placeholders.
obsidian read path="1. Daily/$today.md"
Confirm the ## Morning Journal heading exists at H2. On a re-run, extract any existing bullets under each lane for merge (8i).
Walk each candidate from Step 5g; assign to exactly one lane based on the rules below (first-match wins, top to bottom):
| Lane | Triggers (any match → this lane) |
|---|---|
| Must do | priority p1 or p2 (from task note); OR due today/overdue; OR transcript uses urgency language ("I have to", "I need to today", "overdue", "must"); OR lane_hint == "reply-debt" (set when context contains "promised", "owed", "follow-up rule") |
| 🤖 Could hand off to AI | ai_capability == "ai-handoff" (set by 5h) AND not Must-do urgency |
| Focus work | the priority has a project hint matching today's session work, OR carries a parent for sub-project promotion (5c step 2), OR is the transcript's primary topic |
| If time | low-energy language ("maybe", "eventually", "if I get to it", "would be nice"); OR no urgency signal and no project anchor |
| Also on the radar | lane_hint == "also-on-radar" (set by 5c); OR lane_hint == "carry-forward" AND the candidate has no concrete today-action (Decision 9) |
| Execution strategy | synthesis lane — populated in 8e after all bullet lanes are settled |
Carry-forward absorption rule (5/18 delta — Decision 1): candidates with lane_hint: "carry-forward" that DO have a concrete today-action are absorbed into Must do / Focus / Could-hand-off-to-AI per the rules above, with a (carry-forward from <date>) marker appended to their context. Carry-forwards WITHOUT a concrete today-action go to "Also on the radar" with (carry-forward p2 from <date>; no concrete edge today — stay aware).
Research-question candidates (tags: [task, research] from Step 5f / Step 7 task-note creation) classify like any other candidate — they don't get a dedicated lane. They surface separately via the existing Tasks Overview Base on the daily hub.
If a candidate matches none of the lanes above, default to Focus work.
Synthesize a single (meta-theme: …) subtitle from the transcript + carry-forward state. Goal: one phrase that captures what the day is about. Examples from prior days:
*(meta-theme: system-build has been blocking deliverables; today is about closing the loop — ship process-journal v2, batch the comms debt, dispatch the autonomous-handoff layer)*Heuristics:
Render this subtitle on the priorities header (see 8g).
Immediately under the priorities header, render this exact italic legend line:
> **Notation:** 🤖 = AI can run autonomously now · ⏳ = AI can run after the named human decision · *(unmarked)* = human-only · `← unblocks <X>` = back-reference to a chain context inline on bullets
Render each lane only if it has at least one bullet. Lane order is FIXED:
Must do — with an optional subtitle when all bullets share a theme (e.g. *(reply debt — all overdue)*). Bullet format:
- [<marker?>] [[Task Note Wikilink]] *(<context>)* ← <chain back-reference if any>
- [<marker?>] [[Reply to Person]] *(48hr rule, 5+ wk past)* ← part of the reply-debt cluster
Marker 🤖 / ⏳ / (unmarked) per the task note's ai_capability from 5h. ALL named entities in the bullet must be wikilinks (Decision 12 — see Section 8f).
Focus work — with optional subtitle *(today's deep work — <synthesized theme>)*. Bullet format:
- [<marker?>] [[Task Note]] *(<carry-forward state if any>)* ← <chain back-reference>
- [[Re-orient on {WorkArea} work — status and next steps]] *(carry-forward p2 from 5/16; no concrete edge today — stay aware)*
↳ Warm sub-projects under this:
• [[{Project3}]] — 7d since [[Request {Project3} license from {Contact1}]]
• [[{Project2}]] — 14d since [[2026-05-04 - Post-PTO Re-entry, Goals Sent, Trainings Completed]] *(just flipped Warm → Cold)*
(Note: the carry-forward-p2-with-no-edge example actually belongs in "Also on the radar" per Decision 9 — included here only to show the sub-project nesting pattern. Sub-project bullets come from Step 5c's parent-resolution.)
If time — bullet format:
- [<marker?>] [[Task Note]] *(<context>)*
🤖 Could hand off to AI (dispatch in parallel — autonomous TODAY) — note the 🤖 prefix on the lane header itself as a section signpost. Bullet format:
- 🤖 [[Mobile app bug review and fix pass]] *([[Portfolio]] · cold, 71d)* — verbatim: "right now the mobile is kind of buggy..." ← first live test of the autonomous-dev pattern
Include a verbatim: "<transcript quote>" suffix when the transcript explicitly says "AI can handle" / "dispatch" / similar.
Also on the radar (transcript-named or implied, not today-actionable). Bullet format:
- [[Project Hub]] *(warm, 7d)* — <context for why mentioned>
- [[Carry-Forward p2 Item]] *(carry-forward p2 from 5/16; no concrete edge today — stay aware)*
↳ Warm sub-projects under this:
• [[Sub-Project]] — Nd since [[recent file]]
Compose a numbered day plan that orders the Must do + Focus work + Could-hand-off-to-AI bullets into a feasible sequence. Every numbered step → points at a wikilink to a bullet already rendered above (Decision 8). No item lives only in the strategy — if a step describes work that has no corresponding bullet above, the bullet is missing from a lane and must be added.
Step format:
N. **<Phase label>** → <wikilink(s) to bullets above> (<lane reference>)
Examples (5/18 fixture):
1. **Now** → [[Ship /process-journal v2 today]] (Must do)
2. **Quick discovery** → [[Email NACA advisor to set meeting date]] + [[Confirm IRS extension status and schedule tax-return prep block]] (Must do)
3. **Reply batch — single 30-min block** → [[Reply to {Contact}...|{Contact}]] · [[Reply to {Contact1}...|{Contact1}]] · ... (Must do)
4. **🤖 Dispatch AI handoffs in background** → [[Mobile app bug review and fix pass|Portfolio fix]] · ... (Could hand off to AI — all N)
N. **Before EOD** *(housekeeping — not bullets)* → confirm carry-forward outcomes, lock fork decisions
N+1. **EOD** *(housekeeping — not bullets)* → `/vault-commit` · [[5. Resources/Personal/Journal/Evening Entries/$today|evening journal]]
Heuristic phase ordering:
/vault-commit, evening journal.Omit any numbered step whose source lane is empty. Renumber sequentially.
Every named entity in the rendered hub MUST be a wikilink to its canonical vault note:
4. Contacts/People/<Name>.md (resolved via 5e contact re-grounding; voice-fuzz tolerance handled by resolve_contact.sh)*/Tasks/ (created by Step 7 — the task-creation step that ran before this render)2. Projects/<Area>/<Project>/ (used only when a project-level reference is meant, not a specific action)/vault-commit context) → project hubsPipe aliases ([[Long Task Name|short label]]) are encouraged where the canonical filename is verbose.
Assemble in this exact order (omit empty lanes):
> [[5. Resources/Personal/Journal/Morning Entries/$today|Open Morning Entry]]
**Today's priorities** *(meta-theme: <synthesized day theme from 8b>)*
> **Notation:** 🤖 = AI can run autonomously now · ⏳ = AI can run after the named human decision · *(unmarked)* = human-only · `← unblocks <X>` = back-reference to a chain context inline on bullets
**Must do** *(<subtitle if unifying theme>)*:
- [<marker?>] [[Task Note]] *(<context>)* ← <chain back-reference>
- ...
**Focus work** *(today's deep work — <theme>)*:
- ...
**If time** *(<subtitle if fork decision>)*:
- ...
**🤖 Could hand off to AI** *(dispatch in parallel — autonomous TODAY)*:
- 🤖 [[...]] — verbatim: "..." ← <chain ref>
- ...
**Also on the radar** *(transcript-named or implied, not today-actionable)*:
- [[Project Hub]] *(warm, Nd)* — <context>
- ...
**Execution strategy** *(today's order — every actionable bullet above maps to a step here)*:
1. **Now** → [[...]] (<lane>)
2. **<Phase>** → [[...]] (<lane>)
...
N. **Before EOD** *(housekeeping — not bullets)* → ...
N+1. **EOD** *(housekeeping — not bullets)* → ...
Two trailing blank lines after the last lane, then the existing --- separator stays intact.
Patch via:
mcp__obsidian-mcp-tools__patch_vault_file(
filename=f"1. Daily/{today}.md",
operation="replace",
targetType="heading",
target="Morning Journal",
content="<full block above>",
)
After patching, re-read the daily hub. If a duplicate Morning Journal section appears at the bottom (known MCP patch_vault_file issue), remove it via direct file edit.
If Step 4's idempotency check detected an existing bottom marker and the user confirmed re-run:
← unblocks <X> chain annotations from existing bullets unless inference found different chains (then prompt: "Replace existing chain context? [y/N]").Display a summary followed by the execution report (per vault-config/references/source-manifest.md):
Journal processed for YYYY-MM-DD.
**Summary**: [2-3 sentence summary]
**Mood**: [mood]
**Habits**: N/M completed (list checked items, note missed items)
**Priorities**: [count] items extracted, grouped to the daily hub as:
- Must do: N
- Focus work: N
- If time: N
**Todoist**: [created count] tasks created, [initiative count] initiatives, [skip count] skipped, [existing count] already existed
**Gratitude**: [3 items written to journal / already present / ⚠️ not mentioned — prompt shown]
**People**: [list or "none mentioned"]
Journal entry updated: [[5. Resources/Personal/Journal/Morning Entries/YYYY-MM-DD]]
Daily hub updated: [[1. Daily/YYYY-MM-DD]]
---
### Execution Report
#### Sources
- [x] Obsidian CLI — journal read, daily hub read/write
- [x] Obsidian MCP — N sections patched
- [x] QMD Search — people lookup, N contacts resolved
- [x] Todoist — N tasks created, M deduped
#### Warnings
- [only if there are actual warnings]
#### Fix
- [only if there are failed sources with actionable fixes]
Only include the Warnings and Fix sections if there are actual warnings.
The 2026-05-18 daily hub is the byte-level regression target for the v2 render shape. After any change to Step 5 / Step 7 / Step 8, run a dry-run against 2026-05-18 and diff vs the committed hub.
Acceptable deviations (paraphrasing):
← unblocks <X> annotationsNOT acceptable (regressions — investigate and fix):
(no task note — create) placeholders appearing post-Step-7← unblocks <X> / ← part of the <cluster> / ← starts the <path> annotations missing on chain bullets> **Notation:** ... legend line missing under the priorities header*(meta-theme: ...)* subtitle on the priorities header missing↳ Warm sub-projects under this:) missingIf a "not acceptable" item appears, trace back:
(no task note — create) placeholder → Step 7 (task creation) failed to run before Step 8 (render); check workflow ordering← unblocks annotation → Step 5d blocker inference loop didn't propose the chain, or 8d/8e didn't render itThe first real verification is the user's morning invocation: /process-journal on today's transcript. Confirm all 6 lanes render (or are correctly omitted when empty), carry-forward absorbs prior open items, blocker inference asks the right questions on at least one priority, contact re-grounding produces canonical wikilinks, and capability markers appear on bullets matching their ai_capability tags. Capture any hand-edits required as a gap note under {Project} and iterate.
When analyzing the raw transcript:
- [ ] [{WorkArea}] Continue {Project2} work## Morning / ## Evening split — only process content under the relevant section heading| Scenario | Handling |
|---|---|
| No journal entry for date | Report and stop |
| No daily note for date | Report and stop |
| Already processed (bottom marker line present) | Warn and ask. On confirm: refresh AI Summary and re-classify priorities (preserve task notes already created) |
| Journal is empty / very short | Extract what you can, note brevity |
| No priorities mentioned | Write "No explicit priorities mentioned" in both locations |
| No priorities extracted | Daily hub shows "Today's priorities: None for today" |
| No explicit gratitude | Write "⚠️ No gratitude entry today. What are 3 things you're grateful for?" — never fabricate gratitude items |
| No people mentioned | Omit the "People mentioned" line |
| Evening section present | Only process ## Morning section (ignore Evening) |
| Gratitude already in journal | Do not duplicate — keep existing gratitude section |
## Morning / ## Evening content stays untouched)/process-evening)Guides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.
npx claudepluginhub rs42-ai/ai-os-lite --plugin ai-os-lite