# Start Day

> Morning startup: git pull, QMD update, session notes review, alerts check, ideas triage, and daily briefing

- Skill: `aemerson-commits/start-day` (Agent Skill)
- Install (CLI): `npx skillmds@latest add aemerson-commits/start-day`
- Raw SKILL.md: https://api.skillmd.com/api/skills/aemerson-commits/start-day/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: aemerson-commits (https://skillmd.com/u/aemerson-commits)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/aemerson-commits/start-day

---


# Start Day — Morning Session Startup

Run this at the start of every session when the user says "good morning", "let's start", or similar.

## Obsidian CLI

**Auto-detect**: Set `OBS` var based on which Obsidian binary exists:
```bash
OBS="/c/Program Files/Obsidian/Obsidian.exe"
[ ! -f "$OBS" ] && OBS="/c/Users/${USERNAME:-$USER}/AppData/Local/Programs/obsidian/Obsidian.exe"
```

⚠️ **`$USER` is EMPTY in the Bash tool on Windows** — `$USERNAME` carries it. A bare `$USER`
silently builds `/c/Users//AppData/...`, which fails the `[ -f ]` test and reads as "the binary
isn't installed" rather than as a broken path. Always `${USERNAME:-$USER}`.

All CLI commands: append `2>&1 | grep -v "Loading\|out of date"`

## Execution

Run as many steps in parallel as possible. Steps 1-4 and Step 8 (Event Log check) are fully independent — launch them all at once. Step 5 depends on reading results. Step 9 (briefing) is the final synthesis.

**Batch independent shell commands into ONE call.** Each tool invocation carries fixed overhead (hook fires, subprocess spawns). Combine unrelated, path-agnostic probes into a single block (e.g. `git pull --rebase --autostash; date +%u`) and push slow background work (indexing, cache warms) into a backgrounded subshell (`( long-running-command ) &`) so it never blocks the briefing. Fewer calls = fewer hook fires = faster startup.

### Step 1 — Git Pull (parallel)

```bash
git pull --rebase --autostash
```

Note the files changed and summarize what came in (new features, fixes, docs, etc.).

**Recurring conflict — files regenerated by hooks/scripts.** A plain `git pull` can abort with "local changes would be overwritten" when a tracked file is rewritten every session by automation (a derived queue, a usage tracker, a generated registry). Use `--rebase --autostash` (above) so the pull itself doesn't choke on your own working copy. If the autostash pop then conflicts and the ONLY conflicted paths are known regen-output files, they're disposable — resolve by taking the pulled version and dropping the stash, then let the session re-regenerate them:

```bash
git checkout HEAD -- <regenerated-file-1> <regenerated-file-2>
git stash drop
```

If any OTHER path is conflicted, stop and resolve it normally — do NOT blanket-discard.

### Step 1b — Workspace Integrity (repo-local, instant)

In a monorepo, workspace source directories and/or the root `node_modules` can vanish
from the working tree while the git index still lists them — so `git status` stays
clean and the damage surfaces minutes later as a confusing "the dependency isn't
installed" from whatever runs a build next. Concurrent sessions and worktree churn are
the usual suspects. Catch it before anything builds:

```bash
# A check that (a) asserts each workspace dir exists on disk, and (b) probes a few
# sentinel packages for a usable entry point — not just a directory count.
node scripts/check-workspace-integrity.mjs
```

Two details make this worth scripting rather than eyeballing:

- **A file count cannot see a partial prune.** A dependency tree can sit at hundreds of
  entries — far above any count threshold — while specific packages are gutted and every
  lint/test/build is broken. Probe for a resolvable entry point instead.
- **A gutted package is not repaired by a plain install** — the installer sees the
  directory and skips it. Remove that one package directory, then reinstall.

Exit 0 = all present; exit 1 = something's gone, and it should print the one-line
recovery (restore tracked source dirs from HEAD; reinstall for a wiped dependency tree).
Fail soft — never let this block the briefing. Surface only if it flags something;
otherwise a single "Workspace: intact" line.

### Step 1c — In-Flight Overlap Check (repo-local, instant)

**If dead session worktrees pile up faster than they're cleaned,** sweep them before reading
the overlap list below, or the graveyard drowns the real signal. A worktree that should have
been removed when its session ended typically survives for one of three reasons: the session
was killed (window closed, process ended) without its cleanup hook ever firing; the worktree
was left in a locked "still checking out" state by an add that got interrupted, and removal
tooling refuses to touch a locked tree; or the branch itself outlived the worktree and got
rebuilt from it on the next resume. A sweep step that only removes a worktree once its tree is
clean and every commit is already on the integration branch (by patch, not just by ancestry) is
safe to run unattended.

Surface what every OTHER session is already working on, so the day's plan routes new work
to DISTINCT topics. When sessions run in parallel, the one collision that isolation cannot
prevent is two of them building the same feature — you get duplicate branches and duplicate
PRs solving the same problem. Step 1's pull already fetched the remote, so skip a second one:

```bash
node scripts/in-flight.mjs --no-fetch
```

Read-only. Lists open PRs plus every session worktree with its topic (parsed from the
conventional-commit scope), whether it carries uncommitted work, how far ahead of the
integration branch it is, and an `OVERLAP` flag for any topic with more than one active
branch. Fail soft — a git/CLI error just skips it.

Surface in the briefing:

- If it reports overlaps, lead with the flagged topic list ("4 sessions on `<topic>` —
  check before starting another there").
- If none, a single "In flight: N sessions, all distinct topics" line.
- **When the user states today's goals, cross-check each against the active-branch topics**
  and flag any that already have a live branch ("`<topic>` already has 4 active branches —
  route there rather than start fresh?"). This is the visibility half of the concurrency
  fix; isolation and commit guards are the enforcement half.

### Step 2 — Re-index (background, parallel)

Run any project-specific re-indexing in background — don't wait for it. For example:
```bash
npx qmd update && npx qmd embed  # if using qmd for semantic search
```

### Step 3 — Review Recent Session Notes (parallel, use Agent)

Read the last 2-3 session notes from `{{project}}/Sessions/` (glob for `*.md`, pick most recent by date). Summarize:
- What was worked on
- Any open items, blockers, or follow-ups
- "Left Off" state from last session

```bash
"$OBS" read path="{{project}}/Sessions/{YYYY-MM-DD}.md" 2>&1 | grep -v "Loading\|out of date"
```

Also check if yesterday's session note exists — if not, flag it (session notes may have been missed).

**Check whether it was actually closed out, not just checkpointed.** If your session-notes
process distinguishes a cheap mid-day checkpoint from a full end-of-day close-out, look for
whatever marker the full close-out leaves on the note (a frontmatter stamp, a dated header —
whatever your process uses). A day can end on checkpoints alone if the user never said an
end-of-day phrase, which leaves the Roadmap, project status, memory, and help content behind
for work that already shipped; a check that only looks for a missing note can't tell a
checkpoint-only day from a properly closed one. If yesterday's note exists but carries no
close-out marker, surface it — *"yesterday ended on checkpoints — Roadmap/status/memory may be
behind"* — and offer to run the full close-out for that date before starting new work.

### Step 4 — Check Memory State (parallel, use Agent)

Read and summarize:
1. `memory/promises.md` — any unblocked deferred items?
2. `memory/working-state.md` — any crash buffer / interrupted work?
3. `memory/MEMORY.md` Active Alerts section — list all active warnings

If `promises.md` or `working-state.md` don't exist, that's fine — report clean state.

**If your memory index gets truncated or summarized past some size at session load**, that
cost already landed by the time anyone notices — morning is when you can still act on it, not
after another day of accumulation on top. If you have a tool that reports index size and
archive candidates, run it here (read-only) and surface a line only when it actually flags
something ("N entries archivable, index over budget"); otherwise stay silent. Prefer a
mechanism that only *archives* — moves old entries verbatim into a dated file — over anything
that rewrites or condenses content; a lossy condense of a memory index is a far easier mistake
to make (and to regret) than letting the file grow a bit longer.

**Landed-state guard.** Memory is a point-in-time snapshot — a note that says "dev-only" or "pending" can be stale if a later session (or a concurrent one) already shipped it. Before presenting a memory item as still-pending, spot-check anything that cites a PR number or commit SHA against live git/CI (`git log`, `gh pr view`, or your deploy tool) rather than repeating the note's claim verbatim. Flag mismatches ("marked dev-only, actually already on prod") rather than silently trusting or silently correcting — the user decides how to reconcile it.

**Automate the provable half.** A scanner can mechanize this over your notes and flag only claims it can PROVE are stale — the note says pre-production while the cited SHA is already on the release branch. Because it never guesses, it's safe to run unconditionally:

```bash
node scripts/lint-memory-landed-claims.mjs        # --json for machine output
```

Two lessons from building one: it needs a **citable token** (a SHA or PR number) on the line to check anything, so items written as vague prose stay invisible to it and still need the manual pass above — and writing a **detector alone doesn't fix the problem**, because nothing runs it. Wiring it into this checklist is what closes the adoption gap; an unrun detector is indistinguishable from no detector.

### Step 5 — Check Ideas Inbox

```bash
"$OBS" read path="Ideas.md" 2>&1 | grep -v "Loading\|out of date"
```

If there are ideas (anything beyond frontmatter + `# Ideas` header), report count and brief titles. Ask if user wants to run `/triage-ideas` to route them, or offer to do it inline.

If inbox is empty, report "Ideas inbox is clear."

### Step 6 — Scan Recent Learnings

Check for entries added in the last few days:
```bash
"$OBS" read path="{{project}}/Learnings/Gotchas.md" 2>&1 | grep -v "Loading\|out of date"
"$OBS" read path="{{project}}/Learnings/Architecture.md" 2>&1 | grep -v "Loading\|out of date"
```

Only mention if there are recent additions worth calling out (new gotchas relevant to likely work today).

### Step 7 — Verify Pending Items

Check any pending infrastructure items from MEMORY.md alerts. For example:
- Secrets that should be set
- Services that should be running
- Anything marked "Pending" in MEMORY.md Active Work sections

Report verified items and clear resolved alerts from MEMORY.md.

**If the project tracks status in structured docs** (a roadmap, project cards, an admin dashboard), spot-check that the structured status agrees with reality — the recurring failure mode is a feature that shipped while its tracker still reads "in progress" or "not started," because nothing advanced it after an attended deploy that had no code commit (infra/secret/config changes count as ship events too). Don't auto-fix — surface mismatches and let the user confirm before reconciling.

### Step 8 — Daily Event Log Review (if applicable)

If your project has a cross-dashboard event log for errors and duplicates, surface unresolved items now. For example, if using a D1 `event_log` table:

```bash
# Query the event log for recent unresolved errors
# (adapt to your project's error tracking setup)
npx wrangler d1 execute your-db --remote --command \
  "SELECT dashboard, category, contentSummary, createdAt FROM event_log WHERE eventType='error' AND status='new' ORDER BY createdAt DESC LIMIT 50" \
  --json
```

**Surface in briefing:**
- If no unresolved errors: report "Event Log: clear"
- If errors exist: report count + top 3-5 as one-liners: `relativeTime · source · category · summary[:80]`
  - Group clusters (e.g. "5 of 8 are api-error from the same view" → suggest `/troubleshooting`)
  - Flag items >7 days old as stale or backlogged
- **Window guard**: with a large limit the response can pull a long backlog. Detail-list only the recent window (last ~14 days) in the briefing; roll everything older into "+N older unresolved (>14d)" so a backlog of stale rows can't crowd out today's real issues.
- Don't auto-resolve — user reviews and marks Resolve / Acknowledge / Dismiss themselves

**Prefer ONE aggregate endpoint over N per-queue queries.** Once the briefing pulls from
several queues — event log, open bugs, feature requests, an approval queue — each as its own
authenticated round-trip, collapse them into a single summary endpoint returning
`{ events: {...}, bugs: {...}, features: {...}, approvals: {...} }`. It is *summary-grade*
by design (top ~10 per queue); deep triage still happens in the canonical views. Keep the
per-queue query documented as the fallback for when you need older rows than the aggregate
returns, or when the aggregate is unreachable.

**Route infra alerts into the same log.** If health-check and cron-watchdog alerts email but
never land in the event log, they are invisible to this step and get triaged only by whoever
reads mail. Mirroring them into the log at send time makes an infra incident a real,
resolvable row you triage like any application error.

### Step 8c — Open Bug Reports (the list itself, not just its drift)

Status-reconciliation checks tell you which tickets have drifted from git; this step surfaces
the open bugs THEMSELVES. Run a read-only query for tickets of kind `bug`, pre-sorted
new → in-progress → triaged, severity desc, newest first. Surface:

- If none: "Bugs: none open"
- Else: "Bugs: N open (X new · Y in progress · Z triaged)" + the top ~5 as one-liners:
  `<id> · <severity> · <status> · <title> (<reporter>, <age>d)` — append `fix on <release branch>`
  when a linked commit says so.
- **Lead with** any `new` bug past the triage SLA and anything critical/high — those demand a
  same-day decision.
- **Close-out prompt**: a bug whose fix is already on the release branch is a candidate to
  close — offer it rather than closing silently. **A commit *reference* is evidence, not
  proof**: skip the offer when the referencing commit was clearly partial or parked.
- **Check whether your close actually notifies the reporter — don't assume it does.**
  Notification is frequently *opt-in*, and a tracker that once emailed on close may have been
  changed to silent after a bad auto-notice went out. Read the close path before you promise
  anyone was told. Worse, the notify flag usually has to ride the **same** request that closes
  the ticket: many APIs reject a notify against an already-terminal record, so a silent close
  can only be undone by reopening. Decide notify-vs-silent *before* running the close.
- A `triaged` bug idle 14+ days is backlog rot — roll those into one "+N aging triaged" line.
- Don't triage here; the user does that in the canonical queue view.

### Step 8.5 — Pipeline & Plan of Attack (if project tracking is set up)

If the project uses a gated project pipeline (e.g. Obsidian project notes with gate state), read the open notes and build three buckets:

1. **Blocked on you** — projects at a gate requiring a human decision (e.g. threat assessment, signoff) OR any unanswered open question. These are the "Questions for Me" — the things only you can unblock. List each with its one-line question/decision. Lead the plan with this bucket.
   - **A PR's checks stuck at `action_required` belongs here too, not in the agent-ready queue.** Some CI platforms hold workflow runs for human approval whenever the PR was opened by a bot/automation account — the checks read as pending or red, but nothing is actually failing and no amount of agent effort clears it; only a person clicking "approve" does. Folding that state into an ordinary "failing" classification routes it to an agent with an unfixable instruction.
2. **Agent-ready (today's unattended queue)** — projects flagged as unattended-runnable with no unanswered questions, at an active gate (research, scope, build, verify, visual). These are what an overnight agent skill or `/advance-gate` can drive forward without you. Order by priority then value.
3. **Needs scoping** — open projects not yet ready for unattended work, stuck early (no plan written). Candidates for a self-refill research pass if the agent-ready queue is thin.

If an overnight agent run finished, surface what it produced — draft PRs to review, queued questions, the morning checklist — and fold its queued questions into bucket 1.

**RECONCILE that morning checklist, don't recite it.** Nothing auto-clears those boxes. A
dashboard that renders a status note verbatim — no cross-check against git, the PR list, or the
database — will show a completed task as outstanding forever, and reciting the note into the
briefing launders a stale claim into a fresh-looking one. Verify each box against ground truth
in the same pass and tick what has landed.

Two failure modes to design against:

- **Nobody owns the note.** An unattended worker writes it, then terminates; the reviewer treats
  "the worker owns this file" as permanent and writes nothing back. Make ownership
  **state-scoped**: the worker owns the note *while running*; once the run is terminal, whoever
  reviews it owns the checkboxes. Without that split, every skill that touches the file reads
  itself as the wrong owner and the boxes stay open.
- **Prose is not a checkbox.** If a downstream generator filters on `[ ]` versus `[x]`, writing
  "DONE" in the body clears nothing. Tick the **source** box, in the file the generator reads.

**Then actually retire what you ticked, don't just leave it checked.** A ticked box is still a
rendered row — if the pipeline view itself is DERIVED (regenerated from the source notes and
todos, not hand-maintained), ticking a source alone doesn't remove the row until the generator
re-runs. Tick every source first, *then* regenerate, or the next regen re-emits what you meant
to clear. Otherwise a fully closed cycle still reads as a wall of open work, and the signal the
checklist exists to carry gets buried under its own history.

Keep it to the top few per bucket; the full board lives in whatever project-tracking view you use.

**A verifier's exit code can encode more than pass/fail.** Some status-check scripts exit
non-zero to mean "items remain that need a person," not "the check itself failed" — that's a
healthy, expected signal on a day the queue isn't empty, not an error. Before reporting a
non-zero exit as a problem, read what the script actually printed (its counts, its category
labels) rather than trusting the raw code — a run that did exactly its job, including on a day
it also fixed something, can look identical to a broken one if you only look at the number.

### Step 9 — Friday Wisdom Check

Check if today is Friday:
```bash
date +%u
```

If the result is `5` (Friday) and the `/wisdom` skill is installed, **first check whether it already ran this week** — re-prompting after it already ran is noise. If `/wisdom` stamps a run-log or last-run marker on completion (e.g. `.claude/skills/wisdom/last-run.log`), check that (falling back to scanning this week's session notes for a mention if no marker exists). If it ran within the last 7 days, skip the prompt and add a one-line briefing note instead: "Wisdom: already run {date} this week — skipping the Friday prompt."

Otherwise, after presenting the briefing, ask:

> **It's Friday — run weekly `/wisdom`?** This will audit skill health, review evolve instincts, fold in the latest `/insights` usage signal, and propose knowledge improvements.
>
> Wisdom folds in your Claude Code **usage report** (friction patterns + suggested improvements), but it can only *read* a report you've already generated — it can't run `/insights` itself. For the freshest signal, **run `/insights` first**, then `/wisdom`. If you skip it, wisdom still runs and just notes "no usage signal folded in."

If the user says yes, invoke the `/wisdom` skill. Do NOT auto-run it — always ask first. If they haven't run `/insights` in the last ~7 days, gently remind them it'll sharpen the wisdom pass.

If `/wisdom` is not installed, skip this step silently.

## Output Format

Present a concise morning briefing:

```
Good morning! Here's your daily briefing:

**Git pull**: X files, summary of changes
**Workspace**: intact / N missing (surface only if flagged — with the one-line recovery)
**In flight**: N sessions, all distinct topics / OVERLAP on `<topic>` (N branches)
**Last session (date)**: What was done, where we left off
**Crash buffer**: Clean / has active state (details)
**Active alerts**:
- alert 1
- alert 2
**Event Log**: clear / N new errors+duplicates needing review (top 3-5 listed if >0)
**Bugs**: none open / N open (X new · Y in progress · Z triaged) — top ~5, leading with SLA-overdue new + critical/high
**Pipeline — blocked on you**: N — the questions/decisions only you can clear (top 3-5; "all clear" if none)
**Pipeline — agent-ready today**: N — the pre-scoped unattended queue (top 3-5 by priority), ready for overnight agent or /advance-gate
**Night shift (if ran)**: state, draft PRs to review, queued questions
**Ideas inbox**: X items / clear
**Skill health**: Last audit {date} — {pass/due for audit}. Top 3 used skills last 7 days: X, Y, Z
**Recent gotchas**: Any new entries worth noting
**Pending items**: Verified / needs attention

What are you working on today?
```

## Key Principles

- **Maximize parallelism**: Steps 1-4 should all launch simultaneously (use Agent tool for 3 and 4)
- **Background indexing**: Don't block on re-indexing — it can finish while briefing
- **Don't overwhelm**: Keep the briefing scannable. Details on request
- **Surface blockers first**: If there's interrupted work or critical alerts, lead with those
- **Ideas triage is optional**: Ask before running — user may want to defer
- **Silence-by-design needs its own staleness escalation**: several steps above deliberately
  print nothing on the common case, so a routine "all clear" morning doesn't train the reader
  to skip the briefing — but that intentional quiet looks identical whether nothing changed or
  the underlying data source stopped updating. Any step that depends on an external event that
  can simply stop arriving (an export, a sync, a feed) should carry its own "this has been
  quiet too long" threshold, independent of whatever it normally reports, so a dead source
  doesn't hide behind the design that keeps a healthy one quiet.

