LogoCocode Skills

If this is the first story starting in this epic, move epic to In Progress too

Developer로서 **스토리 개발** 워크플로우를 실행합니다.

Developer로서 스토리 개발 워크플로우를 실행합니다.

Workflow Overview#

Goal: Implement a user story from start to completion

Phase: 4 - Implementation (Execution)

Agent: Developer

Inputs: Story ID, story document (if exists), sprint plan

Output: Working, tested code; updated story status; implementation notes

Duration: 1 hour to 3 days (varies by story size)

Required for: All stories in all project levels


Pre-Flight#

  1. Load context per helpers.md#Combined-Config-Load
  2. Load sprint status per helpers.md#Load-Sprint-Status
  3. Load story:
    • If story document exists: Read docs/stories/STORY-{ID}.md
    • Else: Find story in sprint plan docs/sprint-plan-*.md
  4. Load architecture (if Level 2+): Read docs/architecture-*.md
  5. Check story status:
    • If "not_started": Begin implementation
    • If "in_progress": Resume implementation
    • If "completed": Ask user if they want to re-implement or extend
  6. Load ZenHub context per helpers.md#Load-ZenHub-Context
  7. Check ZenHub story ID: If story has zh_issue_id in sprint status, store for pipeline management
  8. Resolve branch hierarchy: per helpers.md#Resolve-Branch-Names
    • Compute epic_branch, story_branch, task_prefix from sprint-status story entry
    • If story already has branch field in sprint-status, use that instead
  9. Check if branches exist: git branch -a to see which branches already exist
  10. Load sub-tasks (if zh_sub_tasks_enabled):
    • Check story entry in sprint-status.yaml for sub_tasks[] array
    • If sub-tasks exist, these will serve as implementation checklist (Part 2)
    • Track sub-task zh_issue_ids for pipeline management during implementation

Story Implementation Process#

Use TodoWrite to track implementation tasks (typically 5-15 tasks per story)

Approach: Practical, quality-focused, thorough.


Part 1: Understand Requirements#

Read and analyze story:

  1. User story: Who, what, why
  2. Acceptance criteria: All criteria that must pass
  3. Technical notes: Implementation guidance
  4. Dependencies: What must exist first
  5. Story points: Complexity estimate

Display to user:

Implementing STORY-{ID}: {Title}

User Story:
As a {type}, I want to {capability}, so that {benefit}

Acceptance Criteria: {count}
Story Points: {points}
Dependencies: {list}
Sub-tasks: {count} (from ZenHub)  ← if sub-tasks loaded

I'll now plan the implementation...

Move to In Progress on ZenHub:

If zh_available and zh_story_id exists:
  Call helpers.md#Move-Pipeline-with-Context(zh_story_id, "In Progress")
  Log: "✓ ZenHub: #{issue_number} → In Progress"

  # If this is the first story starting in this epic, move epic to In Progress too
  Check epic's stories in sprint-status:
    If ALL other stories are "not_started":
      # This is the first story — move epic to In Progress
      If zh_epic_id exists:
        Call helpers.md#Move-Pipeline-with-Context(zh_epic_id, "In Progress")
        Log: "✓ ZenHub: Epic #{epic_number} → In Progress (first story started)"

Check dependencies:

  • Are dependent stories complete?
  • Are external dependencies met?
  • If not, warn user and ask to proceed anyway or wait

Part 2: Plan Implementation Tasks#

Break story into technical tasks:

Based on story size and type, typical task breakdown:

Backend-heavy story (API, data, business logic):

  1. Define data models/schemas
  2. Create database migrations (if needed)
  3. Implement repository/data layer
  4. Implement business logic
  5. Create API endpoints/controllers
  6. Add input validation
  7. Add error handling
  8. Write unit tests
  9. Write integration tests
  10. Update API documentation

Frontend-heavy story (UI, components):

  1. Create component structure
  2. Implement UI layout
  3. Add state management
  4. Implement user interactions
  5. Add form validation (if forms)
  6. Integrate with backend APIs
  7. Add error handling and loading states
  8. Write component tests
  9. Test accessibility
  10. Test responsive design

Full-stack story:

  • Combine backend + frontend tasks
  • Add integration between layers

Infrastructure story:

  1. Design infrastructure
  2. Create IaC scripts
  3. Set up resources
  4. Configure networking/security
  5. Test infrastructure
  6. Document setup

If sub-tasks exist (from Pre-Flight step 10): Use sub-tasks as the primary implementation checklist:

Implementation Checklist (from ZenHub Sub-tasks):
- [ ] #{sub_num_1} {sub_task_title_1}
- [ ] #{sub_num_2} {sub_task_title_2}
- [ ] #{sub_num_3} {sub_task_title_3}
...

As each sub-task is completed, move its ZenHub pipeline:

If zh_available and sub_task has zh_issue_id:
  Call helpers.md#Move-Pipeline-with-Context(zh_sub_task_id, "In Progress")
  ... (after completing the sub-task)
  Call helpers.md#Move-Pipeline-with-Context(zh_sub_task_id, "Done")
  Update sprint-status sub_task status → "done"

If no sub-tasks, use TodoWrite to create task list for story

Example:

TodoWrite:
- [ ] Create password reset token model
- [ ] Add token fields to users table (migration)
- [ ] Implement token generation logic
- [ ] Create request-reset endpoint
- [ ] Create validate-token endpoint
- [ ] Create reset-password endpoint
- [ ] Add email sending for reset link
- [ ] Create frontend reset request page
- [ ] Create frontend reset form page
- [ ] Write backend unit tests
- [ ] Write API integration tests
- [ ] Write frontend component tests
- [ ] Manual testing
- [ ] Validate all acceptance criteria

Part 3: Set Up Branch Hierarchy#

Create hierarchical branch structure:

  1. Create epic and story branches per helpers.md#Create-Branch-Hierarchy:

    Call Create-Branch-Hierarchy(epic_branch, story_branch)
    - Creates epic branch from main (if not exists)
    - Creates story branch from epic (if not exists)
    - Switches to story branch
    
  2. Update sprint-status.yaml with branch info:

    # Story entry
    branch: "story/STORY-{ID}-{slug}"
    epic_branch: "epic/EPIC-{number}-{slug}"
    
    # Epic branches section (if new epic branch created)
    epic_branches:
      - epic_id: "{zh_epic_id}"
        epic_name: "{epic_name}"
        branch: "epic/EPIC-{number}-{slug}"
        created: true
    
  3. Display branch hierarchy:

    Branch Hierarchy:
    main
    └── {epic_branch}
        └── {story_branch}  ← current
    
  4. Check codebase structure

    • Use Glob/Grep to understand existing patterns
    • Identify where new code should live
    • Note existing naming conventions
  5. Verify development environment

    • Dependencies installed
    • Tests can run
  6. Note starting point:

    git status
    git log -1
    

Part 4: Implement - Backend (if applicable)#

Step 1: Data Layer

If story requires data changes:

  1. Define models/schemas

    • Create or update data models
    • Follow project's ORM/schema pattern
  2. Create migrations

    -- Example for password reset
    ALTER TABLE users ADD COLUMN reset_token VARCHAR(255);
    ALTER TABLE users ADD COLUMN reset_token_expiry TIMESTAMP;
    CREATE INDEX idx_reset_token ON users(reset_token);
    
  3. Test migration (run, verify, rollback, run again)

Step 2: Business Logic

  1. Create service/logic files

    • Follow project structure
    • Single responsibility functions
    • Clear function names
  2. Implement core logic

    • Start with happy path
    • Add error handling
    • Handle edge cases
  3. Add validation

    • Input validation
    • Business rule validation
    • Error messages

Example (Node.js/Express):

// services/password-reset.service.js
const crypto = require('crypto');
const bcrypt = require('bcrypt');

class PasswordResetService {
  generateResetToken() {
    return crypto.randomBytes(32).toString('hex');
  }

  async requestReset(email) {
    const user = await User.findByEmail(email);
    if (!user) {
      // Don't reveal if email exists
      return { success: true };
    }

    const token = this.generateResetToken();
    const expiry = new Date(Date.now() + 3600000); // 1 hour

    await user.update({
      reset_token: await bcrypt.hash(token, 10),
      reset_token_expiry: expiry
    });

    await EmailService.sendPasswordResetEmail(user.email, token);

    return { success: true };
  }

  async validateToken(token) {
    const user = await User.findByResetToken(token);
    if (!user) {
      return { valid: false, error: 'Invalid token' };
    }

    if (user.reset_token_expiry < new Date()) {
      return { valid: false, error: 'Token expired' };
    }

    return { valid: true, userId: user.id };
  }

  async resetPassword(token, newPassword) {
    const validation = await this.validateToken(token);
    if (!validation.valid) {
      throw new Error(validation.error);
    }

    const user = await User.findById(validation.userId);
    const hashedPassword = await bcrypt.hash(newPassword, 10);

    await user.update({
      password: hashedPassword,
      reset_token: null,
      reset_token_expiry: null
    });

    return { success: true };
  }
}

module.exports = new PasswordResetService();

Step 3: API Endpoints

  1. Create routes/controllers
    • RESTful patterns
    • Proper HTTP methods and status codes
    • Error handling middleware

Example:

// routes/auth.routes.js
router.post('/request-password-reset',
  validate(requestResetSchema),
  async (req, res, next) => {
    try {
      const { email } = req.body;
      await PasswordResetService.requestReset(email);
      res.json({ success: true, message: 'If email exists, reset link sent' });
    } catch (error) {
      next(error);
    }
  }
);

router.post('/reset-password',
  validate(resetPasswordSchema),
  async (req, res, next) => {
    try {
      const { token, newPassword } = req.body;
      await PasswordResetService.resetPassword(token, newPassword);
      res.json({ success: true, message: 'Password reset successful' });
    } catch (error) {
      next(error);
    }
  }
);

Mark backend tasks complete in TodoWrite


Part 5: Implement - Frontend (if applicable)#

Step 1: Component Structure

  1. Create components following project structure
  2. Set up routing (if new pages)
  3. Add state management (if needed)

Step 2: UI Implementation

  1. Build layouts

    • HTML structure
    • CSS/styling
    • Responsive design
  2. Add interactivity

    • Form handling
    • API integration
    • Loading states
    • Error handling

Example (React):

// components/PasswordResetRequest.jsx
import { useState } from 'react';
import { requestPasswordReset } from '../api/auth';

export default function PasswordResetRequest() {
  const [email, setEmail] = useState('');
  const [loading, setLoading] = useState(false);
  const [message, setMessage] = useState('');
  const [error, setError] = useState('');

  const handleSubmit = async (e) => {
    e.preventDefault();
    setLoading(true);
    setError('');
    setMessage('');

    try {
      await requestPasswordReset(email);
      setMessage('Password reset link sent to your email');
      setEmail('');
    } catch (err) {
      setError('Failed to request password reset. Please try again.');
    } finally {
      setLoading(false);
    }
  };

  return (
    <div className="password-reset-request">
      <h2>Reset Your Password</h2>
      <form onSubmit={handleSubmit}>
        <div className="form-group">
          <label htmlFor="email">Email Address</label>
          <input
            type="email"
            id="email"
            value={email}
            onChange={(e) => setEmail(e.target.value)}
            required
            disabled={loading}
          />
        </div>

        {error && <div className="alert alert-error">{error}</div>}
        {message && <div className="alert alert-success">{message}</div>}

        <button type="submit" disabled={loading}>
          {loading ? 'Sending...' : 'Send Reset Link'}
        </button>
      </form>
    </div>
  );
}

Mark frontend tasks complete in TodoWrite


Part 6: Testing#

Step 1: Unit Tests

Write tests for individual functions/components:

Backend unit tests:

// services/password-reset.service.test.js
describe('PasswordResetService', () => {
  describe('generateResetToken', () => {
    it('should generate a random token', () => {
      const token1 = service.generateResetToken();
      const token2 = service.generateResetToken();

      expect(token1).toHaveLength(64);
      expect(token1).not.toEqual(token2);
    });
  });

  describe('requestReset', () => {
    it('should send reset email for existing user', async () => {
      const email = 'test@example.com';
      await service.requestReset(email);

      const user = await User.findByEmail(email);
      expect(user.reset_token).not.toBeNull();
      expect(user.reset_token_expiry).toBeGreaterThan(new Date());
    });

    it('should not reveal non-existent email', async () => {
      const result = await service.requestReset('fake@example.com');
      expect(result.success).toBe(true); // Generic response
    });
  });

  describe('validateToken', () => {
    it('should validate correct token', async () => {
      // Setup user with token
      const result = await service.validateToken(validToken);
      expect(result.valid).toBe(true);
    });

    it('should reject expired token', async () => {
      // Setup user with expired token
      const result = await service.validateToken(expiredToken);
      expect(result.valid).toBe(false);
      expect(result.error).toBe('Token expired');
    });
  });
});

Frontend component tests:

// components/PasswordResetRequest.test.jsx
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import PasswordResetRequest from './PasswordResetRequest';

describe('PasswordResetRequest', () => {
  it('renders reset form', () => {
    render(<PasswordResetRequest />);
    expect(screen.getByLabelText(/email/i)).toBeInTheDocument();
    expect(screen.getByText(/send reset link/i)).toBeInTheDocument();
  });

  it('submits email and shows success message', async () => {
    render(<PasswordResetRequest />);

    const emailInput = screen.getByLabelText(/email/i);
    const submitButton = screen.getByText(/send reset link/i);

    fireEvent.change(emailInput, { target: { value: 'test@example.com' } });
    fireEvent.click(submitButton);

    await waitFor(() => {
      expect(screen.getByText(/reset link sent/i)).toBeInTheDocument();
    });
  });

  it('shows error message on failure', async () => {
    // Mock API to fail
    render(<PasswordResetRequest />);

    fireEvent.change(screen.getByLabelText(/email/i), {
      target: { value: 'test@example.com' }
    });
    fireEvent.click(screen.getByText(/send reset link/i));

    await waitFor(() => {
      expect(screen.getByText(/failed to request/i)).toBeInTheDocument();
    });
  });
});

Run tests:

# Backend
npm test services/password-reset.service.test.js

# Frontend
npm test components/PasswordResetRequest.test.jsx

# All tests
npm test

Step 2: Integration Tests

Test complete flows:

// tests/integration/password-reset.test.js
describe('Password Reset Flow', () => {
  it('should complete full password reset', async () => {
    // 1. Request reset
    const res1 = await request(app)
      .post('/api/auth/request-password-reset')
      .send({ email: 'test@example.com' });
    expect(res1.status).toBe(200);

    // 2. Get token from database (in real scenario, from email)
    const user = await User.findByEmail('test@example.com');
    const token = user.reset_token;

    // 3. Validate token
    const res2 = await request(app)
      .get(`/api/auth/validate-reset-token/${token}`);
    expect(res2.body.valid).toBe(true);

    // 4. Reset password
    const newPassword = 'NewSecure123!';
    const res3 = await request(app)
      .post('/api/auth/reset-password')
      .send({ token, newPassword });
    expect(res3.status).toBe(200);

    // 5. Verify can login with new password
    const res4 = await request(app)
      .post('/api/auth/login')
      .send({ email: 'test@example.com', password: newPassword });
    expect(res4.status).toBe(200);
  });
});

Step 3: Check Test Coverage

npm run test:coverage

# Target: ≥80% coverage
# Focus on critical paths and business logic

Mark testing tasks complete in TodoWrite


Part 7: Validate Acceptance Criteria#

Go through each acceptance criterion:

Acceptance Criteria Checklist:
- [ ] User can request password reset from login page
      → Test manually: Click "Forgot Password", enter email, submit

- [ ] System sends email with reset link within 1 minute
      → Check email inbox, verify link received

- [ ] Reset link contains secure, expiring token (1-hour validity)
      → Verify token in database, check expiry timestamp

- [ ] User can set new password meeting strength requirements
      → Test with weak password (should fail)
      → Test with strong password (should succeed)

- [ ] System validates password confirmation matches
      → Test with mismatched passwords (should fail)

- [ ] Expired tokens show clear error message
      → Manually expire token in DB, try to use it

- [ ] Successful reset shows confirmation and redirects to login
      → Complete flow, verify redirect

- [ ] User can login with new password immediately
      → Login with new password

- [ ] Old password no longer works after reset
      → Try to login with old password (should fail)

Update status:

  • Mark each criterion as ✓ when validated
  • Note any issues or failures
  • Fix issues before proceeding

Part 8: Manual Testing & QA#

Functional testing:

  • Test happy path end-to-end
  • Test error cases (invalid email, expired token, weak password, etc.)
  • Test edge cases (special characters in email, very long passwords, etc.)
  • Test on different browsers (if frontend)
  • Test on mobile (if applicable)

UX testing:

  • Is the flow intuitive?
  • Are error messages clear?
  • Are loading states visible?
  • Is it accessible (keyboard navigation, screen readers)?

Security testing:

  • Are tokens secure (random, hashed)?
  • Is rate limiting in place?
  • Are inputs sanitized?
  • Is HTTPS enforced?

Mark manual testing complete in TodoWrite


Part 9: Code Quality Review#

Self-review checklist:

Code Style:

  • Follows project conventions
  • Consistent naming
  • No commented-out code
  • No console.logs or debug statements
  • Proper error handling

Functionality:

  • All acceptance criteria met
  • Edge cases handled
  • Error messages are user-friendly
  • No hardcoded values (use config)

Testing:

  • Test coverage ≥80%
  • All tests passing
  • Integration tests cover main flows
  • Edge cases are tested

Documentation:

  • Code comments for complex logic
  • API documentation updated (if API changes)
  • README updated (if setup changes)
  • CHANGELOG updated (if applicable)

Security:

  • No secrets in code
  • Input validation in place
  • SQL injection prevented (parameterized queries)
  • XSS prevented (sanitized outputs)
  • Authentication/authorization correct

Part 9.5: Task Branch Management (Optional)#

Decision heuristic — when to use task branches:

ConditionAction
Task touches 3+ filesCreate task branch
Task estimated 2+ hoursCreate task branch
Task is experimental/riskyCreate task branch
Task touches 1-2 files, <2 hoursCommit directly on story branch

If using task branch:

  1. Create task branch per helpers.md#Create-Task-Branch:

    Call Create-Task-Branch(story_branch, "{task_slug}")
    Example: task/STORY-008-fix-lint-rules
    
  2. Implement task on the task branch:

    • Write code, tests
    • Commit frequently on task branch
  3. Create PR and merge per helpers.md#Create-PR-and-Merge:

    Call Create-PR-and-Merge(
      source: task_branch,
      target: story_branch,
      title: "fix: {task description} (STORY-{ID})",
      merge_strategy: "squash"
    )
    
    • Squash merge keeps story branch history clean
    • Task branch is deleted after merge
  4. Repeat for each task that warrants a branch

If committing directly on story branch:

  • Make focused commits with clear messages
  • No PR needed — changes go directly to story branch

Display task branch activity:

Task Branches:
  task/STORY-008-fix-lint-rules → story (squash merged) ✓
  task/STORY-008-update-deps → story (squash merged) ✓
  [direct commit] Add missing test cases ✓

Part 10: Complete Story — PR Flow and Status Update#

Step 1: Final commit and push on story branch

  1. Ensure on story branch:
    git checkout {story_branch}
    
  2. Stage, commit, and push:
    git add .
    git commit -m "feat({component}): implement {story title} (STORY-{ID})
    
    - {summary of changes}
    
    Closes STORY-{ID}"
    git push origin {story_branch}
    

Step 2: Create story → epic PR per helpers.md#Create-PR-and-Merge:

Call Create-PR-and-Merge(
  source: story_branch,
  target: epic_branch,
  title: "feat: STORY-{ID} {title}",
  body: "## Summary\n- {changes}\n\n## Acceptance Criteria\n- [x] All criteria met\n\nCloses STORY-{ID}",
  merge_strategy: "merge"   # preserve story commit history
)
  • Do NOT auto-merge — PR stays open for review
  • Store pr_url for status tracking

Step 3: Move to Review/QA on ZenHub:

If zh_available and zh_story_id exists:
  Call helpers.md#Move-Pipeline-with-Context(zh_story_id, "Review/QA")
  Log: "✓ ZenHub: #{issue_number} → Review/QA"

Step 4: Update sprint status:

Per helpers.md#Update-Sprint-Status:

  1. Find STORY-{ID} in sprint status YAML
  2. Update status to "dev-complete"
  3. Update branch, epic_branch fields (if not already set)
  4. Update pr_url, pr_status: "open"
  5. Add completion_date
  6. Add actual_points (if different from estimate)
  7. Increment sprint completed_points
  8. Save status file

Step 5: Post-review guidance (displayed to user):

PR Review and Merge Instructions:

1. Review PR: {pr_url}
2. After PR is approved and merged (story → epic):
   - ZenHub: Move #{issue_number} → Done
   - sprint-status.yaml: Update pr_status to "merged", status to "done"

3. When ALL stories in this epic are Done:
   - Create epic → main PR:
     gh pr create --base main --head {epic_branch} \
       --title "feat: {epic_name}" --body "..."
   - Merge with merge commit (preserve epic history)
   - ZenHub: Move Epic #{epic_number} → Done

Update story document (if exists):

## Progress Tracking

**Status History:**
- {date}: Created
- {date}: Started (branch: {story_branch})
- {date}: Code complete, PR created
- {date}: PR merged → Done

**Branch:** {story_branch}
**PR:** {pr_url}
**Actual Effort:** {points} points

Display Summary to User#

Show completion summary:

✓ Story Development Complete!

STORY-{ID}: {Title}
Status: Dev Complete → PR Open
Story Points: {points}
Actual Effort: {points} points

Implementation:
- Files created/modified: {count}
- Tests: {count} tests, {coverage}% coverage
- All acceptance criteria validated ✓

Branch Hierarchy:
main
└── {epic_branch}
    └── {story_branch}  ← PR open
        ├── task/{slug-1} (squash merged) ✓   # if task branches used
        └── task/{slug-2} (squash merged) ✓

PR: {pr_url} (story → epic, merge commit)

Sub-tasks: {completed}/{total} done     (if sub-tasks exist)

ZenHub Pipeline History:        (if zh_available)
  Sprint Backlog → In Progress → Review/QA
  Epic: #{epic_number} In Progress

Next Steps:
1. Review and merge PR: {pr_url}
2. After merge: Move #{issue_number} → Done
3. Continue with next story or create epic → main PR

Recommend Next Steps#

If more stories in sprint:

Story STORY-{ID} PR open for review!

Sprint Progress: {completed}/{total} points

Pending PR: {pr_url} (story → epic)

Next stories in Sprint:
- STORY-{next}: {title} ({points} points)

Run /dev-story STORY-{next} to continue
Or run /sprint-status to see full sprint progress

If last story in epic:

✓ All stories in Epic complete!

All story PRs merged to {epic_branch}:
- STORY-{A}: ✓ merged
- STORY-{B}: ✓ merged

Next: Create epic → main PR
  gh pr create --base main --head {epic_branch} --title "feat: {epic_name}"
  After merge: ZenHub Epic #{epic_number} → Done

If last story in sprint:

✓ Sprint Complete!

Velocity: {points} points

Next: Start Sprint 2 or run sprint retrospective

If Level 0 (single story):

✓ Story Complete!

Project complete! Single story implemented and tested.

Next: Deploy to production or continue with enhancements

Helper References#

  • Load config: helpers.md#Combined-Config-Load
  • Load sprint status: helpers.md#Load-Sprint-Status
  • Update sprint status: helpers.md#Update-Sprint-Status
  • Save document: helpers.md#Save-Output-Document
  • ZenHub context: helpers.md#Load-ZenHub-Context
  • Resolve branches: helpers.md#Resolve-Branch-Names
  • Create branch hierarchy: helpers.md#Create-Branch-Hierarchy
  • Create task branch: helpers.md#Create-Task-Branch
  • Create PR: helpers.md#Create-PR-and-Merge
  • Move pipeline: helpers.md#Move-Pipeline-with-Context

Tips for Effective Implementation#

Start Small:

  • Break story into smallest possible tasks
  • Complete one task fully before moving to next
  • Commit frequently

Test as You Go:

  • Don't wait until end to test
  • Write tests alongside code
  • Fix issues immediately

Ask Questions:

  • If acceptance criteria unclear, ask user
  • If technical approach uncertain, propose options
  • Don't make assumptions

Quality Over Speed:

  • Working correctly > finishing quickly
  • Good tests > high coverage number
  • Clean code > clever code

Notes for LLMs#

  • Maintain approach (practical, quality-focused, thorough)

  • Use TodoWrite to track implementation tasks (very important!)

  • Always start by reading acceptance criteria

  • Load architecture to understand system design

  • Write tests throughout implementation (not at end)

  • Validate each acceptance criterion explicitly

  • Use Read/Write/Edit tools for code changes

  • Use Bash tool for running tests, git commands

  • Update sprint status when story complete

  • Ask user for clarification when requirements ambiguous

  • Show progress throughout implementation (don't go silent)

  • On story start (Part 1), move ZenHub issue to "In Progress" pipeline if zh_available and zh_story_id exists

  • If first story in epic, also move epic to "In Progress"

  • On story completion (Part 10), move ZenHub issue to "Review/QA" pipeline

  • Pipeline moves are best-effort: if ZenHub MCP fails, warn and continue

  • Read zh_story_id from sprint-status.yaml (populated by sprint-planning or create-story)

  • If sub-tasks exist (Pre-Flight step 10), use them as implementation checklist in Part 2

  • Move sub-task pipelines during implementation: "In Progress" when starting, "Done" when completed

  • Update sprint-status sub_task entries as they complete (status, zh_pipeline)

Hierarchical Branch Strategy:

  • Always create epic → story branch hierarchy (Part 3)
  • Use helpers.md#Resolve-Branch-Names to compute names, helpers.md#Create-Branch-Hierarchy to create
  • Epic branches are lazy-created (on first story start, not during sprint planning)
  • If branch creation fails, fall back to feature/STORY-{ID} flat branch
  • Store branch names in sprint-status.yaml for cross-session consistency

Task Branch Heuristic (Part 9.5):

  • 3+ files OR 2+ hours → use task branch (squash merge to story)
  • Otherwise → commit directly on story branch
  • Task branches are optional — no penalty for skipping

PR Flow (Part 10):

  • story → epic: merge commit (preserves story history) — PR stays open for review
  • After PR is reviewed and merged → move to Done
  • When all stories in epic are Done → create epic → main PR (merge commit)
  • If gh CLI unavailable, output manual PR instructions (do not block)

Fallback Strategy:

  • If hierarchical branches fail → use flat feature/STORY-{ID} branch
  • If ZenHub MCP unavailable → skip pipeline moves, continue with git workflow
  • If gh CLI unavailable → provide manual PR instructions
  • Never block the developer workflow due to tooling issues

Remember: You are implementing working software. Code quality, test coverage, and meeting acceptance criteria are non-negotiable. Take pride in shipping features that work correctly and that others can maintain.