diff --git a/plan-ceo-review/SKILL.md b/plan-ceo-review/SKILL.md
index b05db5e9..033f4e5f 100644
--- a/plan-ceo-review/SKILL.md
+++ b/plan-ceo-review/SKILL.md
@@ -534,6 +534,53 @@ List every ASCII diagram in files this plan touches. Still accurate?
### Unresolved Decisions
If any AskUserQuestion goes unanswered, note it here. Never silently default.
+## Review Log
+
+After producing the Completion Summary above, persist the review result:
+
+```bash
+eval $(~/.claude/skills/gstack/bin/gstack-slug 2>/dev/null)
+mkdir -p ~/.gstack/projects/$SLUG
+echo '{"skill":"plan-ceo-review","timestamp":"TIMESTAMP","status":"STATUS","unresolved":N,"critical_gaps":N,"mode":"MODE"}' >> ~/.gstack/projects/$SLUG/$BRANCH-reviews.jsonl
+```
+
+Before running this command, substitute the placeholder values from the Completion Summary you just produced:
+- **TIMESTAMP**: current ISO 8601 datetime (e.g., 2026-03-16T14:30:00)
+- **STATUS**: "clean" if 0 unresolved decisions AND 0 critical gaps; otherwise "issues_open"
+- **unresolved**: number from "Unresolved decisions" in the summary
+- **critical_gaps**: number from "Failure modes: ___ CRITICAL GAPS" in the summary
+- **MODE**: the mode the user selected (SCOPE_EXPANSION / HOLD_SCOPE / SCOPE_REDUCTION)
+
+## Review Readiness Dashboard
+
+After completing the review, read the review log to display the dashboard.
+
+```bash
+eval $(~/.claude/skills/gstack/bin/gstack-slug 2>/dev/null)
+cat ~/.gstack/projects/$SLUG/$BRANCH-reviews.jsonl 2>/dev/null || echo "NO_REVIEWS"
+```
+
+Parse the output. Find the most recent entry for each skill (plan-ceo-review, plan-eng-review, plan-design-review). Ignore entries with timestamps older than 7 days. Display:
+
+```
++====================================================================+
+| REVIEW READINESS DASHBOARD |
++====================================================================+
+| Review | Runs | Last Run | Status |
+|-----------------|------|---------------------|----------------------|
+| CEO Review | 1 | 2026-03-16 14:30 | CLEAR |
+| Eng Review | 1 | 2026-03-16 15:00 | CLEAR |
+| Design Review | 0 | — | NOT YET RUN |
++--------------------------------------------------------------------+
+| VERDICT: 2/3 CLEAR — Design Review not yet run |
++====================================================================+
+```
+
+**Verdict logic:**
+- **CLEARED TO SHIP (3/3)**: All three have >= 1 entry within 7 days AND most recent status is "clean"
+- **N/3 CLEAR**: Show count and list which are missing, have open issues, or are stale (>7 days)
+- Informational only — does NOT block.
+
## Formatting Rules
* NUMBER issues (1, 2, 3...) and LETTERS for options (A, B, C...).
* Label with NUMBER + LETTER (e.g., "3A", "3B").
diff --git a/plan-ceo-review/SKILL.md.tmpl b/plan-ceo-review/SKILL.md.tmpl
index 9902fafb..8664d095 100644
--- a/plan-ceo-review/SKILL.md.tmpl
+++ b/plan-ceo-review/SKILL.md.tmpl
@@ -452,6 +452,25 @@ List every ASCII diagram in files this plan touches. Still accurate?
### Unresolved Decisions
If any AskUserQuestion goes unanswered, note it here. Never silently default.
+## Review Log
+
+After producing the Completion Summary above, persist the review result:
+
+```bash
+eval $(~/.claude/skills/gstack/bin/gstack-slug 2>/dev/null)
+mkdir -p ~/.gstack/projects/$SLUG
+echo '{"skill":"plan-ceo-review","timestamp":"TIMESTAMP","status":"STATUS","unresolved":N,"critical_gaps":N,"mode":"MODE"}' >> ~/.gstack/projects/$SLUG/$BRANCH-reviews.jsonl
+```
+
+Before running this command, substitute the placeholder values from the Completion Summary you just produced:
+- **TIMESTAMP**: current ISO 8601 datetime (e.g., 2026-03-16T14:30:00)
+- **STATUS**: "clean" if 0 unresolved decisions AND 0 critical gaps; otherwise "issues_open"
+- **unresolved**: number from "Unresolved decisions" in the summary
+- **critical_gaps**: number from "Failure modes: ___ CRITICAL GAPS" in the summary
+- **MODE**: the mode the user selected (SCOPE_EXPANSION / HOLD_SCOPE / SCOPE_REDUCTION)
+
+{{REVIEW_DASHBOARD}}
+
## Formatting Rules
* NUMBER issues (1, 2, 3...) and LETTERS for options (A, B, C...).
* Label with NUMBER + LETTER (e.g., "3A", "3B").
diff --git a/plan-design-review/SKILL.md b/plan-design-review/SKILL.md
index c0ca9512..3a12207b 100644
--- a/plan-design-review/SKILL.md
+++ b/plan-design-review/SKILL.md
@@ -384,7 +384,7 @@ Compare screenshots and observations across pages for:
**Project-scoped:**
```bash
-SLUG=$(git remote get-url origin 2>/dev/null | sed 's|.*[:/]\([^/]*/[^/]*\)\.git$|\1|;s|.*[:/]\([^/]*/[^/]*\)$|\1|' | tr '/' '-')
+eval $(~/.claude/skills/gstack/bin/gstack-slug 2>/dev/null)
mkdir -p ~/.gstack/projects/$SLUG
```
Write to: `~/.gstack/projects/{slug}/{user}-{branch}-design-audit-{datetime}.md`
@@ -556,3 +556,49 @@ Project type: {web app / dashboard / marketing site / etc.}
11. **Never fix anything.** Find and document only. Do not read source code, edit files, or suggest code fixes. Your job is to report what could be better and suggest design improvements. Use `/qa-design-review` for the fix loop.
12. **The exception:** You MAY write a DESIGN.md file if the user accepts the offer. This is the only file you create.
+
+## Review Log
+
+After compiling the report, persist the review result:
+
+```bash
+eval $(~/.claude/skills/gstack/bin/gstack-slug 2>/dev/null)
+mkdir -p ~/.gstack/projects/$SLUG
+echo '{"skill":"plan-design-review","timestamp":"TIMESTAMP","status":"STATUS","design_score":"GRADE","ai_slop_score":"GRADE","mode":"MODE"}' >> ~/.gstack/projects/$SLUG/$BRANCH-reviews.jsonl
+```
+
+Substitute values from the report:
+- **TIMESTAMP**: current ISO 8601 datetime
+- **STATUS**: "clean" if Design Score is A or B; "issues_open" if C, D, or F
+- **GRADE**: the letter grade from the report (Design Score and AI Slop Score respectively)
+- **MODE**: Full / Quick / Deep / Diff-aware / Regression
+
+## Review Readiness Dashboard
+
+After completing the review, read the review log to display the dashboard.
+
+```bash
+eval $(~/.claude/skills/gstack/bin/gstack-slug 2>/dev/null)
+cat ~/.gstack/projects/$SLUG/$BRANCH-reviews.jsonl 2>/dev/null || echo "NO_REVIEWS"
+```
+
+Parse the output. Find the most recent entry for each skill (plan-ceo-review, plan-eng-review, plan-design-review). Ignore entries with timestamps older than 7 days. Display:
+
+```
++====================================================================+
+| REVIEW READINESS DASHBOARD |
++====================================================================+
+| Review | Runs | Last Run | Status |
+|-----------------|------|---------------------|----------------------|
+| CEO Review | 1 | 2026-03-16 14:30 | CLEAR |
+| Eng Review | 1 | 2026-03-16 15:00 | CLEAR |
+| Design Review | 0 | — | NOT YET RUN |
++--------------------------------------------------------------------+
+| VERDICT: 2/3 CLEAR — Design Review not yet run |
++====================================================================+
+```
+
+**Verdict logic:**
+- **CLEARED TO SHIP (3/3)**: All three have >= 1 entry within 7 days AND most recent status is "clean"
+- **N/3 CLEAR**: Show count and list which are missing, have open issues, or are stale (>7 days)
+- Informational only — does NOT block.
diff --git a/plan-design-review/SKILL.md.tmpl b/plan-design-review/SKILL.md.tmpl
index b381c682..97546805 100644
--- a/plan-design-review/SKILL.md.tmpl
+++ b/plan-design-review/SKILL.md.tmpl
@@ -145,3 +145,21 @@ Project type: {web app / dashboard / marketing site / etc.}
11. **Never fix anything.** Find and document only. Do not read source code, edit files, or suggest code fixes. Your job is to report what could be better and suggest design improvements. Use `/qa-design-review` for the fix loop.
12. **The exception:** You MAY write a DESIGN.md file if the user accepts the offer. This is the only file you create.
+
+## Review Log
+
+After compiling the report, persist the review result:
+
+```bash
+eval $(~/.claude/skills/gstack/bin/gstack-slug 2>/dev/null)
+mkdir -p ~/.gstack/projects/$SLUG
+echo '{"skill":"plan-design-review","timestamp":"TIMESTAMP","status":"STATUS","design_score":"GRADE","ai_slop_score":"GRADE","mode":"MODE"}' >> ~/.gstack/projects/$SLUG/$BRANCH-reviews.jsonl
+```
+
+Substitute values from the report:
+- **TIMESTAMP**: current ISO 8601 datetime
+- **STATUS**: "clean" if Design Score is A or B; "issues_open" if C, D, or F
+- **GRADE**: the letter grade from the report (Design Score and AI Slop Score respectively)
+- **MODE**: Full / Quick / Deep / Diff-aware / Regression
+
+{{REVIEW_DASHBOARD}}
diff --git a/ship/SKILL.md b/ship/SKILL.md
index 8aa4a181..e7b8b753 100644
--- a/ship/SKILL.md
+++ b/ship/SKILL.md
@@ -132,6 +132,43 @@ You are running the `/ship` workflow. This is a **non-interactive, fully automat
3. Run `git diff ...HEAD --stat` and `git log ..HEAD --oneline` to understand what's being shipped.
+4. Check review readiness:
+
+## Review Readiness Dashboard
+
+After completing the review, read the review log to display the dashboard.
+
+```bash
+eval $(~/.claude/skills/gstack/bin/gstack-slug 2>/dev/null)
+cat ~/.gstack/projects/$SLUG/$BRANCH-reviews.jsonl 2>/dev/null || echo "NO_REVIEWS"
+```
+
+Parse the output. Find the most recent entry for each skill (plan-ceo-review, plan-eng-review, plan-design-review). Ignore entries with timestamps older than 7 days. Display:
+
+```
++====================================================================+
+| REVIEW READINESS DASHBOARD |
++====================================================================+
+| Review | Runs | Last Run | Status |
+|-----------------|------|---------------------|----------------------|
+| CEO Review | 1 | 2026-03-16 14:30 | CLEAR |
+| Eng Review | 1 | 2026-03-16 15:00 | CLEAR |
+| Design Review | 0 | — | NOT YET RUN |
++--------------------------------------------------------------------+
+| VERDICT: 2/3 CLEAR — Design Review not yet run |
++====================================================================+
+```
+
+**Verdict logic:**
+- **CLEARED TO SHIP (3/3)**: All three have >= 1 entry within 7 days AND most recent status is "clean"
+- **N/3 CLEAR**: Show count and list which are missing, have open issues, or are stale (>7 days)
+- Informational only — does NOT block.
+
+If the verdict is NOT "CLEARED TO SHIP (3/3)", use AskUserQuestion:
+- Show which reviews are missing or have open issues
+- RECOMMENDATION: Choose B (run missing reviews first) unless the change is trivial
+- Options: A) Ship anyway B) Abort — run missing review(s) first C) Reviews not relevant for this change
+
---
## Step 2: Merge the base branch (BEFORE tests)
diff --git a/ship/SKILL.md.tmpl b/ship/SKILL.md.tmpl
index 9339e90c..2a24bea3 100644
--- a/ship/SKILL.md.tmpl
+++ b/ship/SKILL.md.tmpl
@@ -50,6 +50,15 @@ You are running the `/ship` workflow. This is a **non-interactive, fully automat
3. Run `git diff ...HEAD --stat` and `git log ..HEAD --oneline` to understand what's being shipped.
+4. Check review readiness:
+
+{{REVIEW_DASHBOARD}}
+
+If the verdict is NOT "CLEARED TO SHIP (3/3)", use AskUserQuestion:
+- Show which reviews are missing or have open issues
+- RECOMMENDATION: Choose B (run missing reviews first) unless the change is trivial
+- Options: A) Ship anyway B) Abort — run missing review(s) first C) Reviews not relevant for this change
+
---
## Step 2: Merge the base branch (BEFORE tests)
diff --git a/test/gen-skill-docs.test.ts b/test/gen-skill-docs.test.ts
index def042c9..26de63db 100644
--- a/test/gen-skill-docs.test.ts
+++ b/test/gen-skill-docs.test.ts
@@ -322,3 +322,30 @@ describe('description quality evals', () => {
expect(tipsSection).not.toContain('->');
});
});
+
+describe('REVIEW_DASHBOARD resolver', () => {
+ const REVIEW_SKILLS = ['plan-ceo-review', 'plan-eng-review', 'plan-design-review'];
+
+ for (const skill of REVIEW_SKILLS) {
+ test(`review dashboard appears in ${skill} generated file`, () => {
+ const content = fs.readFileSync(path.join(ROOT, skill, 'SKILL.md'), 'utf-8');
+ expect(content).toContain('reviews.jsonl');
+ expect(content).toContain('REVIEW READINESS DASHBOARD');
+ });
+ }
+
+ test('review dashboard appears in ship generated file', () => {
+ const content = fs.readFileSync(path.join(ROOT, 'ship', 'SKILL.md'), 'utf-8');
+ expect(content).toContain('reviews.jsonl');
+ expect(content).toContain('REVIEW READINESS DASHBOARD');
+ });
+
+ test('resolver output contains key dashboard elements', () => {
+ const content = fs.readFileSync(path.join(ROOT, 'plan-ceo-review', 'SKILL.md'), 'utf-8');
+ expect(content).toContain('VERDICT');
+ expect(content).toContain('CLEARED TO SHIP');
+ expect(content).toContain('NOT YET RUN');
+ expect(content).toContain('7 days');
+ expect(content).toContain('Design Review');
+ });
+});