~cytrogen/gstack

9eb74debd50b9fdc83b7b9f2061339cb54ed2210 — Garry Tan a month ago fdd4518
feat: inline /office-hours — no more "another window" (v0.11.3.1) (#352)

* feat: inline /office-hours invocation — no more "another window"

BENEFITS_FROM now uses read-and-follow pattern (same as /autoplan) to run
/office-hours inline. Removes handoff note save infrastructure from
plan-ceo-review template. Keeps handoff note check for backward compat.

* chore: bump version and changelog (v0.11.3.1)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
M CHANGELOG.md => CHANGELOG.md +7 -0
@@ 1,5 1,12 @@
# Changelog

## [0.11.5.1] - 2026-03-23 — Inline Office Hours

### Changed

- **No more "open another window" for /office-hours.** When `/plan-ceo-review` or `/plan-eng-review` offer to run `/office-hours` first, it now runs inline in the same conversation. The review picks up right where it left off after the design doc is ready. Same for mid-session detection when you're still figuring out what to build.
- **Handoff note infrastructure removed.** The handoff notes that bridged the old "go to another window" flow are no longer written. Existing notes from prior sessions are still read for backward compatibility.

## [0.11.5.0] - 2026-03-23 — Bash Compatibility Fix

### Fixed

M VERSION => VERSION +1 -1
@@ 1,1 1,1 @@
0.11.5.0
0.11.5.1

M autoplan/SKILL.md => autoplan/SKILL.md +33 -1
@@ 331,12 331,44 @@ Say to the user via AskUserQuestion:
> not per-product — it captures the thinking behind this specific change."

Options:
- A) Run /office-hours first (in another window, then come back)
- A) Run /office-hours now (we'll pick up the review right after)
- B) Skip — proceed with standard review

If they skip: "No worries — standard review. If you ever want sharper input, try
/office-hours first next time." Then proceed normally. Do not re-offer later in the session.

If they choose A:

Say: "Running /office-hours inline. Once the design doc is ready, I'll pick up
the review right where we left off."

Read the office-hours skill file from disk using the Read tool:
`~/.claude/skills/gstack/office-hours/SKILL.md`

Follow it inline, **skipping these sections** (already handled by the parent skill):
- Preamble (run first)
- AskUserQuestion Format
- Completeness Principle — Boil the Lake
- Search Before Building
- Contributor Mode
- Completion Status Protocol
- Telemetry (run last)

If the Read fails (file not found), say:
"Could not load /office-hours — proceeding with standard review."

After /office-hours completes, re-run the design doc check:
```bash
SLUG=$(~/.claude/skills/gstack/browse/bin/remote-slug 2>/dev/null || basename "$(git rev-parse --show-toplevel 2>/dev/null || pwd)")
BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null | tr '/' '-' || echo 'no-branch')
DESIGN=$(ls -t ~/.gstack/projects/$SLUG/*-$BRANCH-design-*.md 2>/dev/null | head -1)
[ -z "$DESIGN" ] && DESIGN=$(ls -t ~/.gstack/projects/$SLUG/*-design-*.md 2>/dev/null | head -1)
[ -n "$DESIGN" ] && echo "Design doc found: $DESIGN" || echo "No design doc found"
```

If a design doc is now found, read it and continue the review.
If none was produced (user may have cancelled), proceed with standard review.

# /autoplan — Auto-Review Pipeline

One command. Rough plan in, fully reviewed plan out.

M plan-ceo-review/SKILL.md => plan-ceo-review/SKILL.md +37 -38
@@ 432,65 432,64 @@ Say to the user via AskUserQuestion:
> not per-product — it captures the thinking behind this specific change."

Options:
- A) Run /office-hours first (in another window, then come back)
- A) Run /office-hours now (we'll pick up the review right after)
- B) Skip — proceed with standard review

If they skip: "No worries — standard review. If you ever want sharper input, try
/office-hours first next time." Then proceed normally. Do not re-offer later in the session.

**Handoff note save (BENEFITS_FROM):** If the user chose A (run /office-hours first),
save a handoff context note before they leave. Reuse $SLUG and $BRANCH from the
design doc check block above (they use the same `remote-slug || basename` fallback
that handles repos without an origin remote). Then run:
```bash
mkdir -p ~/.gstack/projects/$SLUG
USER=$(whoami)
DATETIME=$(date +%Y%m%d-%H%M%S)
```
Write to `~/.gstack/projects/$SLUG/$USER-$BRANCH-ceo-handoff-$DATETIME.md`:
```markdown
# CEO Review Handoff Note
If they choose A:

Generated by /plan-ceo-review on {date}
Branch: {branch}
Repo: {owner/repo}
Say: "Running /office-hours inline. Once the design doc is ready, I'll pick up
the review right where we left off."

Read the office-hours skill file from disk using the Read tool:
`~/.claude/skills/gstack/office-hours/SKILL.md`

## Why I paused
User chose to run /office-hours first (no design doc found).
Follow it inline, **skipping these sections** (already handled by the parent skill):
- Preamble (run first)
- AskUserQuestion Format
- Completeness Principle — Boil the Lake
- Search Before Building
- Contributor Mode
- Completion Status Protocol
- Telemetry (run last)

## System Audit Summary
{Summarize what the system audit found — recent git history, diff scope,
CLAUDE.md key points, TODOS.md relevant items, known pain points}
If the Read fails (file not found), say:
"Could not load /office-hours — proceeding with standard review."

## Discussion So Far
{Empty — handoff happened before Step 0. Frontend/UI scope detection has not
run yet — it will be assessed when the review resumes.}
After /office-hours completes, re-run the design doc check:
```bash
SLUG=$(~/.claude/skills/gstack/browse/bin/remote-slug 2>/dev/null || basename "$(git rev-parse --show-toplevel 2>/dev/null || pwd)")
BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null | tr '/' '-' || echo 'no-branch')
DESIGN=$(ls -t ~/.gstack/projects/$SLUG/*-$BRANCH-design-*.md 2>/dev/null | head -1)
[ -z "$DESIGN" ] && DESIGN=$(ls -t ~/.gstack/projects/$SLUG/*-design-*.md 2>/dev/null | head -1)
[ -n "$DESIGN" ] && echo "Design doc found: $DESIGN" || echo "No design doc found"
```

Tell the user: "Context saved. Run /office-hours in another window. When you come back
and invoke /plan-ceo-review, I'll pick up the context automatically — including the
design doc /office-hours produces."
If a design doc is now found, read it and continue the review.
If none was produced (user may have cancelled), proceed with standard review.

**Mid-session detection:** During Step 0A (Premise Challenge), if the user can't
articulate the problem, keeps changing the problem statement, answers with "I'm not
sure," or is clearly exploring rather than reviewing — offer `/office-hours`:

> "It sounds like you're still figuring out what to build — that's totally fine, but
> that's what /office-hours is designed for. Want to pause this review and run
> /office-hours first? It'll help you nail down the problem and approach, then come
> back here for the strategic review."
> that's what /office-hours is designed for. Want to run /office-hours right now?
> We'll pick up right where we left off."

Options: A) Yes, run /office-hours first. B) No, keep going.
Options: A) Yes, run /office-hours now. B) No, keep going.
If they keep going, proceed normally — no guilt, no re-asking.

**Handoff note save (mid-session):** If the user chose A (run /office-hours first from
mid-session detection), save a handoff context note with the same format above, but
include any Step 0A progress in the "Discussion So Far" section — premises discussed,
problem framing attempts, user answers so far. Use the same bash block to generate the
file path.
If they choose A: Read the office-hours skill file from disk:
`~/.claude/skills/gstack/office-hours/SKILL.md`

Follow it inline, skipping these sections (already handled by parent skill):
Preamble, AskUserQuestion Format, Completeness Principle, Search Before Building,
Contributor Mode, Completion Status Protocol, Telemetry.

Tell the user: "Context saved with your discussion so far. Run /office-hours, then
come back to /plan-ceo-review."
Note current Step 0A progress so you don't re-ask questions already answered.
After completion, re-run the design doc check and resume the review.

When reading TODOS.md, specifically:
* Note any TODOs this plan touches, blocks, or unlocks

M plan-ceo-review/SKILL.md.tmpl => plan-ceo-review/SKILL.md.tmpl +11 -44
@@ 129,59 129,26 @@ context to pick up where we left off."

{{BENEFITS_FROM}}

**Handoff note save (BENEFITS_FROM):** If the user chose A (run /office-hours first),
save a handoff context note before they leave. Reuse $SLUG and $BRANCH from the
design doc check block above (they use the same `remote-slug || basename` fallback
that handles repos without an origin remote). Then run:
```bash
mkdir -p ~/.gstack/projects/$SLUG
USER=$(whoami)
DATETIME=$(date +%Y%m%d-%H%M%S)
```
Write to `~/.gstack/projects/$SLUG/$USER-$BRANCH-ceo-handoff-$DATETIME.md`:
```markdown
# CEO Review Handoff Note

Generated by /plan-ceo-review on {date}
Branch: {branch}
Repo: {owner/repo}

## Why I paused
User chose to run /office-hours first (no design doc found).

## System Audit Summary
{Summarize what the system audit found — recent git history, diff scope,
CLAUDE.md key points, TODOS.md relevant items, known pain points}

## Discussion So Far
{Empty — handoff happened before Step 0. Frontend/UI scope detection has not
run yet — it will be assessed when the review resumes.}
```

Tell the user: "Context saved. Run /office-hours in another window. When you come back
and invoke /plan-ceo-review, I'll pick up the context automatically — including the
design doc /office-hours produces."

**Mid-session detection:** During Step 0A (Premise Challenge), if the user can't
articulate the problem, keeps changing the problem statement, answers with "I'm not
sure," or is clearly exploring rather than reviewing — offer `/office-hours`:

> "It sounds like you're still figuring out what to build — that's totally fine, but
> that's what /office-hours is designed for. Want to pause this review and run
> /office-hours first? It'll help you nail down the problem and approach, then come
> back here for the strategic review."
> that's what /office-hours is designed for. Want to run /office-hours right now?
> We'll pick up right where we left off."

Options: A) Yes, run /office-hours first. B) No, keep going.
Options: A) Yes, run /office-hours now. B) No, keep going.
If they keep going, proceed normally — no guilt, no re-asking.

**Handoff note save (mid-session):** If the user chose A (run /office-hours first from
mid-session detection), save a handoff context note with the same format above, but
include any Step 0A progress in the "Discussion So Far" section — premises discussed,
problem framing attempts, user answers so far. Use the same bash block to generate the
file path.
If they choose A: Read the office-hours skill file from disk:
`~/.claude/skills/gstack/office-hours/SKILL.md`

Follow it inline, skipping these sections (already handled by parent skill):
Preamble, AskUserQuestion Format, Completeness Principle, Search Before Building,
Contributor Mode, Completion Status Protocol, Telemetry.

Tell the user: "Context saved with your discussion so far. Run /office-hours, then
come back to /plan-ceo-review."
Note current Step 0A progress so you don't re-ask questions already answered.
After completion, re-run the design doc check and resume the review.

When reading TODOS.md, specifically:
* Note any TODOs this plan touches, blocks, or unlocks

M plan-eng-review/SKILL.md => plan-eng-review/SKILL.md +33 -1
@@ 363,12 363,44 @@ Say to the user via AskUserQuestion:
> not per-product — it captures the thinking behind this specific change."

Options:
- A) Run /office-hours first (in another window, then come back)
- A) Run /office-hours now (we'll pick up the review right after)
- B) Skip — proceed with standard review

If they skip: "No worries — standard review. If you ever want sharper input, try
/office-hours first next time." Then proceed normally. Do not re-offer later in the session.

If they choose A:

Say: "Running /office-hours inline. Once the design doc is ready, I'll pick up
the review right where we left off."

Read the office-hours skill file from disk using the Read tool:
`~/.claude/skills/gstack/office-hours/SKILL.md`

Follow it inline, **skipping these sections** (already handled by the parent skill):
- Preamble (run first)
- AskUserQuestion Format
- Completeness Principle — Boil the Lake
- Search Before Building
- Contributor Mode
- Completion Status Protocol
- Telemetry (run last)

If the Read fails (file not found), say:
"Could not load /office-hours — proceeding with standard review."

After /office-hours completes, re-run the design doc check:
```bash
SLUG=$(~/.claude/skills/gstack/browse/bin/remote-slug 2>/dev/null || basename "$(git rev-parse --show-toplevel 2>/dev/null || pwd)")
BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null | tr '/' '-' || echo 'no-branch')
DESIGN=$(ls -t ~/.gstack/projects/$SLUG/*-$BRANCH-design-*.md 2>/dev/null | head -1)
[ -z "$DESIGN" ] && DESIGN=$(ls -t ~/.gstack/projects/$SLUG/*-design-*.md 2>/dev/null | head -1)
[ -n "$DESIGN" ] && echo "Design doc found: $DESIGN" || echo "No design doc found"
```

If a design doc is now found, read it and continue the review.
If none was produced (user may have cancelled), proceed with standard review.

### Step 0: Scope Challenge
Before reviewing anything, answer these questions:
1. **What existing code already partially or fully solves each sub-problem?** Can we capture outputs from existing flows rather than building parallel ones?

M scripts/gen-skill-docs.ts => scripts/gen-skill-docs.ts +34 -2
@@ 2021,11 2021,43 @@ Say to the user via AskUserQuestion:
> not per-product — it captures the thinking behind this specific change."

Options:
- A) Run /${first} first (in another window, then come back)
- A) Run /${first} now (we'll pick up the review right after)
- B) Skip — proceed with standard review

If they skip: "No worries — standard review. If you ever want sharper input, try
/${first} first next time." Then proceed normally. Do not re-offer later in the session.`;
/${first} first next time." Then proceed normally. Do not re-offer later in the session.

If they choose A:

Say: "Running /${first} inline. Once the design doc is ready, I'll pick up
the review right where we left off."

Read the ${first} skill file from disk using the Read tool:
\`~/.claude/skills/gstack/${first}/SKILL.md\`

Follow it inline, **skipping these sections** (already handled by the parent skill):
- Preamble (run first)
- AskUserQuestion Format
- Completeness Principle — Boil the Lake
- Search Before Building
- Contributor Mode
- Completion Status Protocol
- Telemetry (run last)

If the Read fails (file not found), say:
"Could not load /${first} — proceeding with standard review."

After /${first} completes, re-run the design doc check:
\`\`\`bash
SLUG=$(~/.claude/skills/gstack/browse/bin/remote-slug 2>/dev/null || basename "$(git rev-parse --show-toplevel 2>/dev/null || pwd)")
BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null | tr '/' '-' || echo 'no-branch')
DESIGN=$(ls -t ~/.gstack/projects/$SLUG/*-$BRANCH-design-*.md 2>/dev/null | head -1)
[ -z "$DESIGN" ] && DESIGN=$(ls -t ~/.gstack/projects/$SLUG/*-design-*.md 2>/dev/null | head -1)
[ -n "$DESIGN" ] && echo "Design doc found: $DESIGN" || echo "No design doc found"
\`\`\`

If a design doc is now found, read it and continue the review.
If none was produced (user may have cancelled), proceed with standard review.`;
}

function generateDesignSketch(_ctx: TemplateContext): string {

M test/gen-skill-docs.test.ts => test/gen-skill-docs.test.ts +10 -0
@@ 773,6 773,16 @@ describe('BENEFITS_FROM resolver', () => {
    const qaContent = fs.readFileSync(path.join(ROOT, 'qa', 'SKILL.md'), 'utf-8');
    expect(qaContent).not.toContain('Prerequisite Skill Offer');
  });

  test('inline invocation — no "another window" language', () => {
    expect(ceoContent).not.toContain('another window');
    expect(engContent).not.toContain('another window');
  });

  test('inline invocation — read-and-follow path present', () => {
    expect(ceoContent).toContain('office-hours/SKILL.md');
    expect(engContent).toContain('office-hours/SKILL.md');
  });
});

// --- {{DESIGN_OUTSIDE_VOICES}} resolver tests ---