| name | eod-ship |
| description | End-of-day shipping pipeline — claude-sync, domain-split commits, push, ISSUE creation linked to ThakiCloud Project #5, daily skill digest, and Slack summary across all managed repos. Use when the user types "EOD ship", "퇴근 정리", "EOD 정리", "오늘 작업 마무리", or runs `/eod`. Do NOT use for morning-only sync (use sod-ship), single-repo ship (use release-ship), or WIP commits without push (use domain-commit). |
| disable-model-invocation | true |
EOD-Ship — End-of-Day pipeline
Complete end-of-day shipping pipeline across all 5 managed repositories.
Reference
Pipeline (Sequential, per repo)
For each repo listed in references/managed-repos.md:
| Phase | Step | Skill | MANDATORY |
|---|
| 1.5 | Claude Sync | claude-sync | yes (cursor-sync는 SOD/EOD에서 제외 — 사용자 지시 2026-06-26; 필요 시 /cursor-sync 수동) |
| 1.6 | gbrain structure Sync | gbrain-sync | yes (agency-org + client pod structure; brain/memory excluded) |
| 1.7 | Runtime-state batch commit | scripts/commit_runtime_state.sh | best-effort (this repo only; folds volatile monitor state into ONE chore(state) commit so it doesn't pollute domain-commits — US intraday dumps stay gitignored) |
| 1.8 | Env-parity manifest refresh | scripts/env_bootstrap.sh --export | yes (this repo only; re-records external symlinks + Python version so the OTHER machine can --heal to match tomorrow morning) |
| 1.9 | Paxis submodule pull | submodule update --remote praxis | yes (this repo only; bump praxis gitlink to latest main BEFORE ship so Phase 2–4 commits/pushes the bump) |
| 2–4 | Ship: commit → push → issue → Project #5 link | release-ship --no-pr (pipeline mode) | YES — Phase 4 HARD FAIL ON SKIP |
| 5 | Daily skill digest | daily-skill-digest | best-effort |
| 6 | Slack summary | post to #효정-할일 | best-effort |
| 7 | Daily cost analysis | ccusage daily | yes (final step, report-only) |
Phase 1.9 — Paxis submodule pull (this repo only)
praxis (git@github.com:ThakiCloud/praxis.git) tracks main and is the ONLY submodule pulled to latest at EOD. Run this BEFORE Phase 2–4 so the gitlink bump is part of the ship commit/push:
git -C ~/thaki/ai-platform-strategy submodule update --init --remote praxis 2>&1 | tail -3
if ! git -C ~/thaki/ai-platform-strategy diff --quiet -- praxis; then
git -C ~/thaki/ai-platform-strategy add praxis
echo "praxis bumped → release-ship will commit/push the gitlink"
else
echo "praxis already at latest main — no bump"
fi
Other submodules (ai-suite, thaki-ui, ai-platform-webui, thaki-cloud-assistant) stay pinned to their recorded SHA — do NOT --remote them at EOD.
Phase 2–4 delegation (why eod historically failed to link)
Phases 2–4 are a single release-ship --no-pr call per repo, in pipeline mode — NOT a hand-rolled domain-commit + git push + commit-to-issue sequence. This was the gap vs /release-ship:
- Orphan detection is mandatory at EOD. By end of day most work is already committed/pushed (during-day
release-ship runs, chore(state) runtime commits, etc.), so a fresh domain-commit produces 0 new commits → nothing feeds issue creation → 0 issues created → Project #5 stays empty. release-ship's Step 4-fallback (orphan detection) handles exactly this: when the tree is clean (STEP2_SKIPPED=true) it scans git log --since="24 hours ago" | grep -v '#[0-9]' for unlinked commits and creates issues for them. Hand-rolled Phase 4 had no such fallback.
- Inline, proven linking. release-ship Step 4a–4d inlines
gh project item-add 5 --owner ThakiCloud + set_all_fields() + the 4d verify loop. eod must NOT paraphrase this — invoke release-ship so the same code path that works for /release-ship runs for /eod.
Per-repo invocation (loop over references/managed-repos.md):
⛔ Project #5 scope (user directive 2026-06-26): only ai-platform-strategy gets issues + Project #5 links. Every other repo is commit+push ONLY. release-ship's own Step 4-gate enforces this, but eod passes the right flag so intent is explicit:
if [ "$REPO" = "ai-platform-strategy" ]; then
release-ship --no-pr
else
release-ship --no-pr --no-issue
fi
--no-pr everywhere (no auto-merge at end of day). --no-issue on the 5 non-ai-platform repos. If a repo's branch policy needs a PR, drop --no-pr for that repo.
Hard-Fail Rules
The reason this pipeline failed historically (observed 2026-05-22): Phase 4 was silently skipped despite being marked MANDATORY. Without enforcement, 27 commits went unlinked. The rules below prevent recurrence.
Phase 4 (release-ship Step 4) is HARD-FAIL — ai-platform-strategy ONLY
The hard-fail rules below apply only to ai-platform-strategy. For the other 5 repos Phase 4 is intentionally skipped (--no-issue), so "0 issues" there is the CORRECT outcome, not a failure. Never mark a non-ai-platform repo FAILED for having 0 issues.
- (ai-platform-strategy) If there were commits today (new from Phase 2 or orphan commits from release-ship Step 4-fallback) AND Phase 4 created 0 issues → mark pipeline as ❌ FAILED
- A clean tree is NOT a pass by itself: release-ship Step 4-fallback MUST have run orphan detection and logged
{orphan_fallback: "clean", orphan_count: 0} before Phase 4 is considered satisfied. Skipping Phase 4 because "no new commits" is the historical bug — it is a FAIL, not a pass.
- If any issue is missing from Project #5 → ❌ FAILED
- If any issue has fewer than 5 of 7 fields populated (Status/Priority/Size/Sprint/Estimate are mandatory; Start/End dates can be optional for live work but recommended) → ❌ FAILED
- Failure does NOT block other repos — log per-repo and continue
- Failure DOES block the "✅ EOD complete" Slack message — instead post "⚠️ EOD partial — N/M repos linked to Project #5"
Verification (must run before Slack)
After Phase 4 for ai-platform-strategy (the only repo that creates issues), run the verification query from commit-to-issue/references/project-config.md § Verification Query. Assert:
for issue in created_issues_today:
assert issue.project5_linked == True
assert all(field is not None for field in [
issue.status, issue.priority, issue.size,
issue.estimate, issue.sprint,
])
if not issue.start_date or not issue.end_date:
log_warning(f"{issue.number}: missing date fields")
If verification fails for any issue, retry Phase 4c (field setup) once. If still failing, log to Slack with the issue URL and continue.
Output
Final Slack post format (#효정-할일):
🌙 EOD <YYYY-MM-DD>
Repos shipped: <N>/6
✓ ai-platform-strategy: 3 commits → 2 issues (#138, #139) ✓ Project #5
✓ realtime-translator: 1 commit → push only (no Project #5, by design)
✓ macro-factor-dashboards: 2 commits → push only (by design)
…
Project #5: N new items (ai-platform-strategy only), fields complete: F/N
Daily skill digest: <link>
💸 Today's cost: $XX.XX (in/out/cache: …) — models: sonnet, opus (⚠️ if Opus-heavy)
Status: ✅ COMPLETE | ⚠️ PARTIAL — N issues missing from Project #5
Phase 7 — Daily Cost Analysis (final step)
Run after the Slack summary, as the closing step. Reports today's Claude usage cost via ccusage so the cost-guard rules (loop-monitor-cost-guard, cost_audit.py) have ground-truth numbers.
ccusage daily --since $(date +%Y%m%d) 2>/dev/null | tail -30
Fallback: if ccusage is not on PATH, use npx ccusage daily --since $(date +%Y%m%d). If both fail, log a warning and skip — report-only, never blocks EOD completion.
Report: today's total USD + token breakdown, models used (flag if Opus dominates — pipeline/orchestration should be Sonnet per cost-guard), and a one-line within-budget verdict. Append the 💸 Today's cost: line to the Slack summary above.
Why this pipeline exists
The user works across 5 repos daily and previously lost track of which work was committed where. EOD-ship enforces:
- Visibility: every commit lands in Project #5, visible to the team scrum
- Traceability: issues link back to commits via body references
- No orphans: Phase 4 (via release-ship Step 4-fallback) catches commits that bypassed the normal
issue/123-feature branch workflow — including work already committed/pushed earlier in the day
Without Phase 4 hard-fail enforcement, the pipeline becomes ineffective — exactly what happened the week of 2026-05-18 ~ 2026-05-22 (resulting in 7 retro issues #138-144 being created manually after the fact).
Common failure modes
| Symptom | Root cause | Fix |
|---|
0 issues at EOD, Project #5 empty (the reported /eod vs /release-ship gap) | eod ran a fresh domain-commit, found tree already committed during the day → 0 new commits → no issues. No orphan detection. | Delegate Phase 2–4 to release-ship --no-pr (pipeline mode) — its Step 4-fallback scans 24h orphan commits and links them |
| 0 issues created despite commits | Phase 4 silently skipped | Hard-fail rule above |
| Issue created but missing from Project #5 | item-add failed silently | Verification step catches it |
| Fields partially set | --text used on date field | Use --date YYYY-MM-DD (see project-config.md gotchas) |
Could not resolve to a Repository | Wrong owner | Always git remote -v first (see managed-repos.md) |
| Cache: same issue created twice | No dedup check | Check git log --grep="#NNN" before creating |
| Slack post says ✅ but Project #5 empty | Verification step skipped | Run verification BEFORE posting Slack |
Options
eod-ship skip-sync — skip Phases 1, 1.5 (sync), useful when you only want to commit/push
eod-ship current-only — only operate on the current repo, not all 5
eod-ship --no-slack — skip Phase 6 (Slack post)
eod-ship --dry-run — print plan but don't execute (debug mode)
Rules
- Phase 4 MANDATORY — never skip silently
- Per-repo isolation — one repo's failure does not abort others
- Run verification BEFORE Slack — never post success with broken state
- Use
git push --no-verify only if pre-push hook hangs >4min (E2E tests)
- Project #5 issues:
sylvanus4/ai-strategy ONLY (user directive 2026-06-26). Other repos commit+push only (--no-issue) — never create issues or link them to Project #5. 0 issues on a non-ai-platform repo is correct, not a failure.
- Every created issue MUST be assigned to
sylvanus4 — never leave unassigned (release-ship Step 4b / commit-to-issue both use --assignee sylvanus4). Unassigned past-sprint cards are auto-deleted by the weekend cleanup.
- Board cleanup is automated:
com.thaki.sprint-archive (Sat/Sun 14:00) runs scripts/skills/project5_sprint_cleanup.py. End state = only ai-platform-strategy on my Project #5 slice: my OTHER personal-repo cards (realtime-translator, macro-factor-dashboards, github-to-notion-sync, cursor-template, ai-model-event-stock-analytics) are deleted from the board (any sprint); for ai-platform-strategy — current archived→Done (un-archive), current unassigned→assign me, past assigned→26-Archive, past unassigned→delete. Team items never touched. eod-ship does NOT archive; that's the weekend job's job.