From 9a94e1d677919c4275a80f2c31220e666754390a Mon Sep 17 00:00:00 2001 From: Alex Wegener Date: Sat, 2 May 2026 19:00:40 +0200 Subject: [PATCH 1/2] fix(hooks): stop SessionEnd from mutating tracked STATE.md The SessionEnd hook overwrote STATE.md's `last_updated` frontmatter on every session end via `sed -i`. STATE.md is a tracked source-of-truth Markdown, written deliberately by skills (init-project, plan-milestone, plan-task, summarize-task, reassess-roadmap, plan-ceo-review) as part of state transitions. A hook firing on every session-end has no business writing to it -- the result was a phantom diff in `git status` after every session, in every ytstack project. The same hook already appends to `journal/sessions.jsonl` (gitignored, append-only), which carries the recency information without polluting the tracked tree. SessionStart's "Last updated:" line now reflects the last deliberate skill-driven state transition rather than the last process exit -- which is the more useful semantic anyway. Smoke-tested: STATE.md sha unchanged before/after hook invocation; journal entry written correctly with milestone/slice/task/session_id. Surfaced from a downstream user whose engine-vault setup clones a repo containing `.ytstack/` into a subdirectory: every Claude Code session in the vault was rewriting the engine's dev-tracking STATE.md. --- hooks/session-end | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/hooks/session-end b/hooks/session-end index 3fee9a0..6ebc2e4 100644 --- a/hooks/session-end +++ b/hooks/session-end @@ -1,8 +1,11 @@ #!/usr/bin/env bash # ytstack SessionEnd hook # -# Fires when Claude Code ends the session. Updates STATE.md's last_updated -# timestamp and writes a journal entry with end-of-session marker. +# Fires when Claude Code ends the session. Appends a journal entry with +# end-of-session marker. Does NOT mutate STATE.md -- that file is a tracked +# source-of-truth Markdown, written deliberately by skills as part of state +# transitions. A hook firing on every session end has no business writing to +# it (creates phantom diffs on every git status). # # Side-effects only. Does not emit stdout context. @@ -26,17 +29,6 @@ STATE_FILE="$YT_DIR/STATE.md" JOURNAL_DIR="$YT_DIR/journal" TS=$(date -u +"%Y-%m-%dT%H:%M:%SZ") -# Update last_updated field in STATE.md (portable BSD + GNU sed) -if [ -f "$STATE_FILE" ]; then - if sed --version >/dev/null 2>&1; then - # GNU sed - sed -i "s/^last_updated: .*/last_updated: $TS/" "$STATE_FILE" - else - # BSD sed (macOS) - sed -i '' "s/^last_updated: .*/last_updated: $TS/" "$STATE_FILE" - fi -fi - # Append to journal (persistent log of sessions) mkdir -p "$JOURNAL_DIR" JOURNAL_FILE="$JOURNAL_DIR/sessions.jsonl" From cc2b5d8437a73054f561a40394dbf618f94cb43a Mon Sep 17 00:00:00 2001 From: Alex Wegener Date: Sat, 2 May 2026 19:03:40 +0200 Subject: [PATCH 2/2] chore: bump version to 0.1.4 Required for `/plugin update` to pick up the SessionEnd fix. --- .claude-plugin/marketplace.json | 2 +- .claude-plugin/plugin.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 8a696ef..a426627 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -10,7 +10,7 @@ { "name": "ytstack", "description": "Claude Code plugin. Project-OS artifact discipline + curated superpowers and gstack skill wrappers + Agent Teams orchestration.", - "version": "0.1.3", + "version": "0.1.4", "source": "./", "author": { "name": "Yesterday", diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 7553362..99f8a12 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "ytstack", - "version": "0.1.3", + "version": "0.1.4", "description": "Yesterday Technologies Stack -- opinionated software-development OS for AI agents. Curated superpowers + gstack skills plus Project-OS artifact discipline (PROJECT.md, DECISIONS.md, KNOWLEDGE.md, milestone/slice/task hierarchy), orchestrated via SessionStart hooks.", "author": { "name": "Yesterday",