diff --git a/.hooks/issue-linter.js b/.hooks/issue-linter.js new file mode 100644 index 0000000..eb76225 --- /dev/null +++ b/.hooks/issue-linter.js @@ -0,0 +1,264 @@ +#!/usr/bin/env node + +/** + * Issue Linter - Pre-commit hook validator + * + * Runs before every commit to ensure issue files are valid. + * + * Usage: + * node .hooks/issue-linter.js + * + * Exit codes: + * 0 - All checks passed + * 1 - Validation errors found + */ + +const fs = require('fs'); +const path = require('path'); +const { execSync } = require('child_process'); + +// Configuration +const ISSUES_DIR = '.issues'; +const REQUIRED_FRONTMATTER = ['id', 'title', 'status', 'priority', 'created']; +const VALID_STATUSES = ['open', 'in-progress', 'done', 'blocked']; +const VALID_PRIORITIES = ['low', 'medium', 'high', 'critical']; +const REQUIRED_SECTIONS = ['What', 'Why', 'Acceptance Criteria', 'Verification']; + +// Colors for output +const RED = '\x1b[31m'; +const GREEN = '\x1b[32m'; +const YELLOW = '\x1b[33m'; +const RESET = '\x1b[0m'; + +let errors = []; +let warnings = []; + +function logError(msg) { + errors.push(msg); + console.error(`${RED}[issue-linter] ERROR: ${msg}${RESET}`); +} + +function logWarning(msg) { + warnings.push(msg); + console.warn(`${YELLOW}[issue-linter] WARNING: ${msg}${RESET}`); +} + +function logInfo(msg) { + console.log(`${GREEN}[issue-linter] ${msg}${RESET}`); +} + +/** + * Parse YAML frontmatter from markdown content + */ +function parseFrontmatter(content) { + const match = content.match(/^---\n([\s\S]*?)\n---/); + if (!match) return {}; + + const frontmatter = {}; + const lines = match[1].split('\n'); + + for (const line of lines) { + const colonIndex = line.indexOf(':'); + if (colonIndex === -1) continue; + + const key = line.slice(0, colonIndex).trim(); + let value = line.slice(colonIndex + 1).trim(); + + // Handle arrays (depends-on) + if (value.startsWith('[') && value.endsWith(']')) { + value = value.slice(1, -1).split(',').map(v => v.trim()); + } + + frontmatter[key] = value; + } + + return frontmatter; +} + +/** + * Check if a section exists in the content + */ +function sectionExists(content, sectionName) { + // Look for ## Section Name or ### Section Name + const regex = new RegExp(`^#{2,3}\\s+${sectionName}\\s*$`, 'm'); + return regex.test(content); +} + +/** + * Get all files that were changed in this commit + */ +function getChangedFiles() { + try { + const output = execSync('git diff --cached --name-only', { encoding: 'utf8' }); + return output.trim().split('\n').filter(f => f.length > 0); + } catch (e) { + // Fallback for when git commands fail + return []; + } +} + +/** + * Get the staging area (added files) + */ +function getStagedFiles() { + try { + const output = execSync('git diff --cached --name-only --diff-filter=ACM', { encoding: 'utf8' }); + return output.trim().split('\n').filter(f => f.length > 0); + } catch (e) { + return []; + } +} + +/** + * Get all issue files in .issues/ + */ +function getIssueFiles() { + const issuesPath = path.join(process.cwd(), ISSUES_DIR); + + if (!fs.existsSync(issuesPath)) { + return []; + } + + const files = fs.readdirSync(issuesPath, { recursive: true }); + return files + .filter(f => f.endsWith('.md')) + .map(f => path.join(ISSUES_DIR, f)); +} + +/** + * Validate a single issue file + */ +function validateIssueFile(filePath) { + const fullPath = path.join(process.cwd(), filePath); + + if (!fs.existsSync(fullPath)) { + logError(`${filePath} does not exist`); + return false; + } + + const content = fs.readFileSync(fullPath, 'utf8'); + const frontmatter = parseFrontmatter(content); + let hasErrors = false; + + // Check required frontmatter + for (const field of REQUIRED_FRONTMATTER) { + if (!(field in frontmatter)) { + logError(`${filePath}: Missing frontmatter field "${field}"`); + hasErrors = true; + } + } + + // Check status is valid + if (frontmatter.status && !VALID_STATUSES.includes(frontmatter.status)) { + logError(`${filePath}: Invalid status "${frontmatter.status}". Must be one of: ${VALID_STATUSES.join(', ')}`); + hasErrors = true; + } + + // Check priority is valid + if (frontmatter.priority && !VALID_PRIORITIES.includes(frontmatter.priority)) { + logError(`${filePath}: Invalid priority "${frontmatter.priority}". Must be one of: ${VALID_PRIORITIES.join(', ')}`); + hasErrors = true; + } + + // Check completed date if status is done + if (frontmatter.status === 'done' && !frontmatter.completed) { + logError(`${filePath}: Has status "done" but no "completed" date in frontmatter`); + hasErrors = true; + } + + // Check required sections + for (const section of REQUIRED_SECTIONS) { + if (!sectionExists(content, section)) { + logError(`${filePath}: Missing section "## ${section}"`); + hasErrors = true; + } + } + + // Check Plan exists if status is in-progress + if (frontmatter.status === 'in-progress' && !sectionExists(content, 'Plan')) { + logError(`${filePath}: Has status "in-progress" but no Plan section`); + hasErrors = true; + } + + // Check Agent Working Notes is deleted if status is done + if (frontmatter.status === 'done' && sectionExists(content, 'Agent Working Notes')) { + logError(`${filePath}: Has status "done" but Agent Working Notes section not deleted`); + hasErrors = true; + } + + return !hasErrors; +} + +/** + * Check if code was changed without a corresponding issue file + */ +function checkCodeWithoutIssue(stagedFiles) { + const codeExtensions = ['.js', '.ts', '.jsx', '.tsx', '.py', '.go', '.rs', '.java', '.c', '.cpp', '.h', '.hpp', '.rb', '.php', '.cs', '.swift', '.kt', '.scala', '.vue', '.svelte']; + + const codeFiles = stagedFiles.filter(f => { + const ext = path.extname(f); + return codeExtensions.includes(ext) || f.startsWith('src/') || f.startsWith('lib/') || f.startsWith('app/'); + }); + + const issueFiles = getIssueFiles(); + + for (const codeFile of codeFiles) { + // Check if there's a related issue file + // Extract potential issue number from recent commits or check .issues/INDEX.md + // For simplicity, we just warn if there are code changes + if (issueFiles.length === 0) { + logWarning(`${codeFile}: Code changed but no issue files found`); + } + } +} + +/** + * Main validation + */ +function main() { + console.log('[issue-linter] Running pre-commit validation...\n'); + + const stagedFiles = getStagedFiles(); + const issueFiles = getIssueFiles(); + + // If no issues exist yet (first time setup), skip issue validation + if (issueFiles.length === 0) { + logInfo('No issue files found. Skipping issue validation.'); + logInfo('Add issue files to .issues/ directory before committing code.'); + process.exit(0); + } + + // Validate all issue files (not just staged ones) + let allValid = true; + for (const file of issueFiles) { + if (!validateIssueFile(file)) { + allValid = false; + } + } + + // Check for code changes without issues + checkCodeWithoutIssue(stagedFiles); + + // Summary + console.log(''); + if (errors.length > 0) { + console.error(`${RED}[issue-linter] FAIL: ${errors.length} error(s) found${RESET}`); + if (warnings.length > 0) { + console.warn(`${YELLOW}[issue-linter] ${warnings.length} warning(s)${RESET}`); + } + process.exit(1); + } else if (warnings.length > 0) { + console.warn(`${YELLOW}[issue-linter] PASS with warnings: ${warnings.length} warning(s)${RESET}`); + process.exit(0); + } else { + logInfo('PASS: All issue files are valid'); + process.exit(0); + } +} + +// Run if called directly +if (require.main === module) { + main(); +} + +module.exports = { validateIssueFile, parseFrontmatter }; diff --git a/.issues/INDEX.md b/.issues/INDEX.md new file mode 100644 index 0000000..c239340 --- /dev/null +++ b/.issues/INDEX.md @@ -0,0 +1,35 @@ +# Issue Index + +All open and closed issues for this project. + +## Open Issues + +| # | Title | Priority | Depends On | Status | +|---|---|---|---|---| +| — | No open issues | — | — | — | + +## Closed Issues + +| # | Title | Completed | +|---|---|---| +| — | No closed issues | — | + +## Legend + +- **Priority**: low < medium < high < critical +- **Status**: open → in-progress → done (or blocked) +- **Depends On**: Blocked until these issues are done + +## Creating a New Issue + +1. Pick the next number (highest + 1) +2. Create `/.issues/-.md` +3. Use format from `/docs/workflow/ISSUE-FORMAT.md` +4. Add entry to this table +5. See `/docs/workflow/AGENT-PROMPTS.md` for creation prompt + +## Workflow Overview + +See `/docs/workflow/INDEX.md` for quick start. + +See `/docs/workflow/WORKFLOW.md` for detailed stages. diff --git a/.issues/example/001-example-issue.md b/.issues/example/001-example-issue.md new file mode 100644 index 0000000..863d99b --- /dev/null +++ b/.issues/example/001-example-issue.md @@ -0,0 +1,56 @@ +--- +id: 001 +title: Example issue with full format +status: open +priority: medium +created: 2024-04-18 +--- + +## What +This is an example issue demonstrating the complete format. Replace this with your actual issue. + +## Why +Use this as a template when creating new issues. Delete this issue after reviewing the format. + +## Acceptance Criteria +- [ ] This example can be deleted +- [ ] Format is clear and usable +- [ ] All required sections are present + +## Verification +1. Read this file +2. Verify all sections are present +3. Delete this file when done + +--- + +## Agent Working Notes + +### Plan + +- [ ] + +### Status Log + + +### Blockers + + +### Self-Verification + +- [ ] Smoke test ran: +- [ ] Acceptance criteria checked: +- [ ] Screenshot taken (if UI change): +- [ ] Dependent issues still work: + +### Human Review Notes + + +Review date: + +Reasoning check: +- [ ] Plan makes sense +- [ ] Status log shows good decisions +- [ ] Self-verification is complete and honest + +Feedback: diff --git a/README.md b/README.md index 9c97215..9103d4d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,78 @@ -# workflow +# Workflow Template -Standard issue-based workflow template for teams. Clone this repo to start a new project with enforced issue tracking. \ No newline at end of file +A portable, file-based issue tracking and development workflow for teams. + +## Quick Start + +1. **Clone this repo** into your new project +2. **Install dependencies**: `pnpm install` (or npm, yarn) +3. **Run setup**: `pnpm run setup` (installs pre-commit hook) +4. **Read the docs**: See `docs/workflow/INDEX.md` +5. **Start working**: See `docs/workflow/WORKFLOW.md` + +## What This Is + +- **Issues are files** in `/.issues/`, not in external trackers +- **Issues are tracked by git**, alongside the code they affect +- **Agents think out loud** in issue files, making reasoning visible +- **Humans approve reasoning**, not code line-by-line +- **Pre-commit hooks enforce** issue format before any commit + +## File Structure + +``` +/ +├── docs/workflow/ # Workflow documentation +│ ├── INDEX.md ← Start here +│ ├── ISSUE-FORMAT.md ← Issue file format +│ ├── WORKFLOW.md ← Step-by-step process +│ └── AGENT-PROMPTS.md ← Copy-paste agent prompts +├── .issues/ # Issue files +│ ├── INDEX.md # List of all issues +│ └── example/ # Example issues +├── .hooks/ # Pre-commit validators +│ └── issue-linter.js # Issue format validator +└── package.json # Setup scripts +``` + +## Setup + +```bash +# Clone this repo into your new project +git clone https://git.fbrns.co/shoko/workflow.git my-new-project +cd my-new-project + +# Remove git history (optional, for a fresh start) +rm -rf .git + +# Initialize git +git init + +# Install dependencies +pnpm install + +# Setup pre-commit hook +pnpm run setup + +# Remove this README (it's the template's README) +rm README.md +``` + +## For Teams + +This template is maintained at: https://git.fbrns.co/shoko/workflow + +To update the template for all projects: +1. Pull latest changes from this repo +2. Merge into your project + +## Documentation + +- [Workflow Overview](docs/workflow/INDEX.md) +- [Issue Format](docs/workflow/ISSUE-FORMAT.md) +- [Step-by-Step Workflow](docs/workflow/WORKFLOW.md) +- [Agent Prompts](docs/workflow/AGENT-PROMPTS.md) + +## License + +Internal use. See https://git.fbrns.co/shoko/workflow diff --git a/docs/workflow/AGENT-PROMPTS.md b/docs/workflow/AGENT-PROMPTS.md new file mode 100644 index 0000000..d226129 --- /dev/null +++ b/docs/workflow/AGENT-PROMPTS.md @@ -0,0 +1,255 @@ +# Agent Prompts + +Copy-paste ready prompts for each stage of the workflow. + +--- + +## Stage 2: Pick Up — Agent Prompt + +Copy and paste this when starting work on an issue: + +``` +You're picking up issue #: + +Steps: +1. Read /.issues/<number>-<title>.md completely +2. Read all depends-on issues: + <list issue numbers here> +3. Read related code: + <list files here> +4. Write your Plan in ## Agent Working Notes > Plan: + - Approach: how will you solve this? + - Files to touch: which files will you change? + - Risks: what could go wrong? +5. Change status to `in-progress` +6. Wait for human acknowledgment before proceeding + +Remember: You must understand the dependencies before starting. Don't assume they work a certain way. +``` + +--- + +## Stage 3: Implementation — Status Log Prompt + +After each significant step, log it: + +``` +Add to ## Status Log: + +YYYY-MM-DD HH:MM - <What you did> +<Why you did it this way> +<Any decisions made> +``` + +Example: +``` +2024-04-18 14:30 - Implemented delete button component +Decided to put it in SettingsPage.tsx rather than separate component +since it's only used in one place. Button uses danger variant for emphasis. +``` + +--- + +## Stage 3: Implementation — Scope Change Prompt + +If scope needs to change: + +``` +Stop implementation immediately. + +Add to ## Status Log: +--- +Scope change detected: <description> + +Original scope: <what was scoped> +New requirement: <what was found> + +Proposed solution: +<your proposed approach> + +Status: Waiting for human approval before proceeding. +--- +``` + +--- + +## Stage 3: Implementation — Blocker Prompt + +If blocked: + +``` +Add to ## Blockers: + +Blocker: <description> +Proposed solution: <your proposed approach> +Status: Waiting for resolution. + +Do not proceed until this is resolved. +``` + +--- + +## Stage 4: Self-Verification Prompt + +Copy and paste this template, then fill in each item: + +``` +## Self-Verification + +Complete before claiming done: + +- [ ] Smoke test ran: + Command: <command> + Result: <pass/fail> + If fail: <what failed, what you did about it> + +- [ ] Acceptance criteria checked: + <List each criterion and result> + - [ ] Criterion 1: <pass/fail> — <notes> + - [ ] Criterion 2: <pass/fail> — <notes> + +- [ ] Screenshot taken (if UI change): + <path to screenshot> or N/A + +- [ ] Dependent issues still work: + - Issue #<number>: <what you tested> — <pass/fail> + - Issue #<number>: <what you tested> — <pass/fail> +``` + +--- + +## Stage 5: Request Review Prompt + +After completing self-verification: + +``` +## Agent Working Notes + +[after Self-Verification is complete] + +Add to ### Human Review Notes: + +Agent requests review. + +All self-verification checks passed. Ready for approval to close. + +Files changed: <list> +Tests added: <list if any> +Screenshots: <path if applicable> +``` + +--- + +## Full Issue Implementation Prompt + +For the agent to use from start to finish: + +``` +## Your Task + +Implement issue #<number>: <title> + +## Instructions + +1. **Read the issue file**: `/.issues/<number>-<title>.md` +2. **Read dependencies**: Issues listed in `depends-on` +3. **Read related code**: Files that will be affected +4. **Write your Plan** in the issue file's `## Agent Working Notes > Plan` +5. **Wait for acknowledgment** ("ok" from human) +6. **Implement** the feature or fix +7. **Log decisions** in `## Status Log` as you go +8. **If scope changes or blocked**: Stop, document, wait +9. **Self-verify** using the template in Stage 4 +10. **Request review** when done + +## Key Rules + +- Think out loud in the issue file +- Verify before claiming done +- Ask if unsure — don't assume +- Dependencies must be verified, not assumed +- Pre-commit hook will check your issue file — keep it complete + +## Do NOT + +- Skip the issue file format +- Skip self-verification +- Proceed without human acknowledgment on plans +- Ignore scope changes +- Assume dependencies work without checking +``` + +--- + +## Dependency Verification Prompt + +When checking if a dependency works: + +``` +## Dependency Check: Issue #<number> + +Issue: <title> +Status: <status> +Output: <what this issue produces> + +Verification performed: +- Ran tests: <command> — <pass/fail> +- Checked integration: <what you tested> +- Screenshots (if UI): <path or N/A> + +Result: <dependency works / dependency has issues> + +If dependency has issues: +- Document what doesn't work +- Write proposed fix in ## Blockers +- Do not proceed until resolved +``` + +--- + +## Issue Creation Prompt + +For creating a new issue: + +``` +## Create New Issue + +Create a new issue file in /.issues/ + +1. Check /.issues/INDEX.md for the next available number +2. Create /.issues/<number>-<slug>.md using the format in /docs/workflow/ISSUE-FORMAT.md +3. Fill in: + - All frontmatter + - ## What — what needs to be built or fixed + - ## Why — why it matters + - ## Acceptance Criteria — testable checklist + - ## Verification — how to test it + - Leave ## Agent Working Notes empty +4. Add to /.issues/INDEX.md +5. Set status to `open` + +Issue number: <next number> +Issue slug: <descriptive-kebab-case> +``` + +--- + +## Pre-commit Hook Failure Response + +If the pre-commit hook fails: + +``` +The pre-commit hook rejected your commit due to issue file errors. + +Error: <error message from hook> + +Fix the issue file(s) before committing: +- Missing frontmatter fields +- Missing required sections +- Invalid status values +- Missing Plan when status is in-progress +- Missing completed date when status is done +- Agent Working Notes not deleted when status is done + +After fixing, try committing again. +``` diff --git a/docs/workflow/INDEX.md b/docs/workflow/INDEX.md new file mode 100644 index 0000000..8822d96 --- /dev/null +++ b/docs/workflow/INDEX.md @@ -0,0 +1,96 @@ +# Workflow Template + +A portable, file-based issue tracking and development workflow for teams. + +## Quick Start + +1. **Clone or fork this repo** into your new project +2. **Run setup** (if applicable to your project) +3. **Read this entire doc** before starting work +4. **Read `/docs/workflow/ISSUE-FORMAT.md`** before creating your first issue +5. **Follow `/docs/workflow/WORKFLOW.md`** for the step-by-step process + +## What This Is + +A workflow where: +- **Issues are files** in `/.issues/`, not in external trackers +- **Issues are tracked by git**, alongside the code they affect +- **Agents think out loud** in issue files, making reasoning visible +- **Humans approve reasoning**, not code line-by-line +- **Pre-commit hooks enforce** issue format before any commit + +## File Structure + +``` +/ +├── docs/workflow/ +│ ├── INDEX.md ← You are here +│ ├── ISSUE-FORMAT.md ← Required fields for issue files +│ ├── WORKFLOW.md ← Step-by-step stages and gates +│ └── AGENT-PROMPTS.md ← Copy-paste prompts for agents +├── .issues/ +│ ├── INDEX.md ← List of all open issues +│ └── example/ +│ └── 001-example.md +├── .hooks/ +│ └── issue-linter.js ← Pre-commit validator +└── package.json ← (optional) setup scripts +``` + +## Key Principles + +1. **If it's not written down, it doesn't exist.** + All context, decisions, and feedback live in the issue file. + +2. **The agent thinks out loud.** + Every significant step—plan, decisions, blockers, verification—is written in the issue. + +3. **Verification before handoff.** + The agent must prove the work works before declaring it done. + +4. **Humans approve reasoning, not tasks.** + Your job is to agree or disagree with the agent's logic, not to catch missing code. + +5. **Integration is a first-class concern.** + Issues have dependencies. Dependencies must be checked before claiming done. + +## Before Starting a New Project + +Tell your agent to set up the workflow: + +> "feynman, set up the workflow using the template from https://git.fbrns.co/shoko/workflow" + +The agent will copy the structure and install the pre-commit hook automatically. + +## For New Team Members + +```bash +# Clone the project +git clone <repo-url> +pnpm install # or npm install, yarn, etc. + +# Read the docs +cat docs/workflow/INDEX.md +cat docs/workflow/ISSUE-FORMAT.md +cat docs/workflow/WORKFLOW.md + +# Check what's being worked on +cat .issues/INDEX.md + +# Pick an issue, read it, start working +``` + +## Pre-commit Hook + +The hook at `.hooks/issue-linter.js` runs automatically before every commit. It will reject commits that: +- Change code without a corresponding issue file +- Have incomplete issue files (missing required fields) +- Have invalid status values +- Have `done` status without completion date + +## Getting Help + +- **Workflow questions** → Read `/docs/workflow/WORKFLOW.md` +- **Issue format questions** → Read `/docs/workflow/ISSUE-FORMAT.md` +- **Agent instructions** → Copy prompts from `/docs/workflow/AGENT-PROMPTS.md` +- **What's open** → Check `/.issues/INDEX.md` diff --git a/docs/workflow/ISSUE-FORMAT.md b/docs/workflow/ISSUE-FORMAT.md new file mode 100644 index 0000000..4c29cb2 --- /dev/null +++ b/docs/workflow/ISSUE-FORMAT.md @@ -0,0 +1,215 @@ +# Issue Format + +Every issue is a single Markdown file in `/.issues/`. No exceptions. + +## File Naming + +``` +<number>-<slug>.md +``` + +- `<number>`: Sequential, zero-padded to 3 digits (001, 002, 010, 100) +- `<slug>`: Short, kebab-case, descriptive (e.g., `user-authentication`, `fix-nav-crash`) + +Examples: +- `001-user-authentication.md` +- `042-fix-login-modal.md` +- `100-setup-ci-cd.md` + +## Required Frontmatter + +```yaml +--- +id: 001 +title: Add user authentication +status: open # open | in-progress | done | blocked +priority: high # low | medium | high | critical +depends-on: # optional, list issue IDs + - 000 +created: 2024-04-18 +completed: # fill when status becomes done +--- +``` + +## Required Sections + +### 1. What +One paragraph explaining *what* needs to be built or fixed. Be specific. + +### 2. Why +One paragraph explaining *why* this matters. Link to customer feedback, bug reports, or business context if available. + +### 3. Acceptance Criteria +A checklist. Each item should be: +- Testable (can say "pass" or "fail") +- Specific (not vague like "works well") +- Independent (not dependent on other criteria) + +Example: +```markdown +## Acceptance Criteria +- [ ] Button visible only to authenticated users +- [ ] Clicking opens a confirmation modal +- [ ] Confirming deletes account and redirects to homepage +- [ ] No console errors on the settings page +``` + +### 4. Verification +How to test this issue. Include: +- What commands to run +- What to look for +- What routes to check +- Any manual steps required + +Example: +```markdown +## Verification +1. Run `pnpm test -- --grep "settings"` +2. Start dev server: `pnpm dev` +3. Navigate to `/settings` +4. Log in and verify button appears +5. Click button, verify modal opens +6. Confirm deletion, verify redirect to homepage +``` + +## Agent Working Notes (Required for All Issues) + +This section is **for the agent to fill in**. It is deleted before closing. + +```markdown +--- + +## Agent Working Notes + +### Plan +<!-- What approach will you take? List steps before coding. --> +- [ ] + +### Status Log +<!-- Timestamped entries: what was done, what was decided, what was found --> +<!-- Format: YYYY-MM-DD HH:MM - Entry --> + +### Blockers +<!-- List any blockers with proposed solutions. If none, write "None." --> + +### Self-Verification +<!-- Must be filled before claiming done --> +- [ ] Smoke test ran: <!-- command and result --> +- [ ] Acceptance criteria checked: <!-- which ones, results --> +- [ ] Screenshot taken (if UI change): <!-- path or "N/A" --> +- [ ] Dependent issues still work: <!-- which ones, results --> +``` + +### Self-Verification Fields + +| Field | When to Fill | What to Write | +|---|---|---| +| Smoke test | Always | Command run and whether it passed | +| Acceptance criteria | Always | Which criteria were checked, results | +| Screenshot | UI changes only | Path to screenshot or "N/A" | +| Dependent issues | Has depends-on | Which issues were tested, results | + +## Human Review Notes + +Filled by the human reviewer. + +```markdown +### Human Review Notes +<!-- Human fills after agent marks done --> + +Review date: YYYY-MM-DD + +Reasoning check: +- [ ] Plan makes sense +- [ ] Status log shows good decisions +- [ ] Self-verification is complete and honest + +Feedback: <!-- any changes requested, or "Approved" --> +``` + +## Example Issue + +```markdown +--- +id: 023 +title: Add delete account button to settings +status: open +priority: high +depends-on: + - 018 +created: 2024-04-18 +--- + +## What +Add a "Delete Account" button to the user settings page. The button should only be visible to authenticated users and require confirmation before deletion. + +## Why +Users need a way to permanently delete their account. Currently there's no path to account deletion, leading to support requests. + +## Acceptance Criteria +- [ ] Button visible only to authenticated users +- [ ] Clicking opens a confirmation modal +- [ ] Confirming deletes account and redirects to homepage +- [ ] No console errors on the settings page + +## Verification +1. Run `pnpm test -- --grep "settings"` +2. Start dev server: `pnpm dev` +3. Navigate to `/settings` +4. Verify button appears after login +5. Click button, verify modal opens +6. Confirm deletion, verify redirect to homepage + +--- + +## Agent Working Notes + +### Plan +- [ ] + +### Status Log + +### Blockers +None. + +### Self-Verification +- [ ] Smoke test ran: +- [ ] Acceptance criteria checked: +- [ ] Screenshot taken (if UI change): +- [ ] Dependent issues still work: + +### Human Review Notes + +Review date: + +Reasoning check: +- [ ] Plan makes sense +- [ ] Status log shows good decisions +- [ ] Self-verification is complete and honest + +Feedback: +``` + +## Validation Rules + +The pre-commit hook checks: + +| Rule | Error Message | +|---|---| +| Code changed without issue file | `Code changed but no issue file found for: <files>` | +| Missing frontmatter | `Missing frontmatter in: <file>` | +| Missing required sections | `Missing section in <file>: <section>` | +| Invalid status | `Invalid status in <file>: <value>` | +| Status "done" without completed date | `<file> has status "done" but no completed date` | +| Status "in-progress" without Plan | `<file> has status "in-progress" but no Plan` | +| Agent Working Notes not deleted on close | `<file> has status "done" but Agent Working Notes not deleted` | + +## Creating a New Issue + +1. Pick the next number: check `/.issues/INDEX.md` for the highest +2. Create the file with this exact template +3. Add to `/.issues/INDEX.md` +4. Move status to `in-progress` when starting work +5. Delete Agent Working Notes when closing + +Do not create issues outside of `/.issues/`. Do not use external issue trackers. diff --git a/docs/workflow/WORKFLOW.md b/docs/workflow/WORKFLOW.md new file mode 100644 index 0000000..13ea810 --- /dev/null +++ b/docs/workflow/WORKFLOW.md @@ -0,0 +1,345 @@ +# Workflow + +The complete step-by-step process for working through an issue, from creation to close. + +## Overview + +``` +┌────────────────────────────────────────────────────────────────────┐ +│ 1. ISSUE CREATION Human or agent creates issue file │ +│ All required fields filled │ +│ Dependencies identified │ +└────────────────────────────────┬───────────────────────────────────┘ + ↓ +┌────────────────────────────────────────────────────────────────────┐ +│ 2. PICK UP Agent reads issue + dependencies │ +│ Agent writes Plan │ +│ Human acknowledges or revises │ +└────────────────────────────────┬───────────────────────────────────┘ + ↓ +┌────────────────────────────────────────────────────────────────────┐ +│ 3. IMPLEMENTATION Agent works and logs decisions │ +│ New information → pause + ask │ +│ Blocker → write + wait │ +└────────────────────────────────┬───────────────────────────────────┘ + ↓ +┌────────────────────────────────────────────────────────────────────┐ +│ 4. SELF-VERIFICATION Agent runs smoke test │ +│ Agent checks acceptance criteria │ +│ Agent takes screenshot if UI │ +│ Agent verifies dependencies │ +└────────────────────────────────┬───────────────────────────────────┘ + ↓ +┌────────────────────────────────────────────────────────────────────┐ +│ 5. READY FOR REVIEW Agent marks done in Status Log │ +│ Agent requests review in file │ +│ Human reviews reasoning │ +│ Human approves or requests changes │ +└────────────────────────────────┬───────────────────────────────────┘ + ↓ +┌────────────────────────────────────────────────────────────────────┐ +│ 6. CLOSE Human approves → status: done │ +│ Agent Working Notes deleted │ +│ PR created with issue number │ +└────────────────────────────────────────────────────────────────────┘ +``` + +## Stage 1: Issue Creation + +### Who: Human (or agent with human approval) + +### Steps + +1. Check `/.issues/INDEX.md` for the current highest issue number +2. Create `/.issues/<number>-<slug>.md` using the format in `ISSUE-FORMAT.md` +3. Fill in: + - All frontmatter (id, title, status, priority, depends-on, created) + - `## What` — what needs to be built or fixed + - `## Why` — why it matters + - `## Acceptance Criteria` — testable checklist + - `## Verification` — how to test it + - Leave `## Agent Working Notes` empty (for the agent to fill) +4. Add the issue to `/.issues/INDEX.md` +5. Mark status as `open` + +### Exit Gate + +Issue file exists with all required fields. Human has reviewed and approved the issue. + +--- + +## Stage 2: Pick Up + +### Who: Agent + +### Steps + +1. Read this issue file completely +2. Read all issues listed in `depends-on` +3. Read any related code that will be affected +4. Write your Plan in `## Agent Working Notes > Plan` + - Approach: how will you solve this? + - Files to touch: which files will you change? + - Risks: what could go wrong? +5. Change status to `in-progress` +6. Commit this initial work (optional, but recommended) +7. Wait for human acknowledgment + +### Human's Role + +Read the Plan. Ask yourself: +- Does the approach make sense? +- Are the files to touch correct? +- Did the agent read the dependencies? + +React with: +- **"ok"** — proceed with implementation +- **"revise" + feedback** — explain what needs to change and why + +### Exit Gate + +Agent has written a Plan. Human has said "ok" (or equivalent). + +--- + +## Stage 3: Implementation + +### Who: Agent + +### Steps + +1. Work through the Plan +2. After each significant step, add an entry to `## Status Log`: + ```markdown + YYYY-MM-DD HH:MM - Did X, decided Y because Z + ``` +3. If new information changes scope: + - Stop + - Write the new information in Status Log + - Add a note: "Scope change detected, waiting for approval" + - Wait for human approval before continuing +4. If you encounter a blocker: + - Write it in `## Blockers` with a proposed solution + - Wait for resolution before continuing +5. Do NOT skip steps or make assumptions about dependencies + +### What Belongs in Status Log + +- Decisions made and why +- Code approaches tried and discarded +- Findings from reading code +- Anything that affects the plan +- Any interaction with dependencies + +### What Does NOT Belong in Status Log + +- Trivial actions ("changed variable x to y") +- Unnecessary detail +- Personal commentary + +### Exit Gate + +Implementation complete. Self-Verification filled (see Stage 4). + +--- + +## Stage 4: Self-Verification + +### Who: Agent + +### Steps + +1. Run smoke tests: + ```bash + # Run tests related to this feature + pnpm test -- --grep "<relevant-pattern>" + + # Check for console errors + # (manually or via test) + ``` +2. Check each Acceptance Criterion: + - Can you verify it passes? Mark `[x]` + - Does it fail? Mark `[ ]` and fix it +3. If UI change: take a screenshot + - Save to `.issues/screenshots/<issue-id>-<description>.png` + - Reference it in Self-Verification +4. If depends-on: verify dependent features still work + - Run their tests + - Do a quick manual check +5. Fill `## Agent Working Notes > Self-Verification` + +### Self-Verification Must Be Honest + +If a smoke test fails, fix it before claiming done. If an acceptance criterion can't be met, document why and wait for human guidance. + +Do not claim "verified" if it isn't. The human will find out during review. + +### Exit Gate + +All Self-Verification items checked. Smoke test passes. Dependencies verified. + +--- + +## Stage 5: Ready for Review + +### Who: Human + +### Agent's Steps + +1. Ensure Status Log is complete +2. Ensure Self-Verification is complete +3. Add a review request in the file: + ```markdown + ### Human Review Notes + + Review date: YYYY-MM-DD + + Agent requests review. + ``` +4. The human will fill in the rest + +### Human's Steps + +1. Read the issue file completely +2. Read the Status Log +3. Read the Self-Verification +4. Ask yourself: + - Does the reasoning make sense? + - Were good decisions made? + - Did the agent check the dependencies? + - Is the Self-Verification honest? + - Are there any edge cases not covered? + +5. Either: + - **Approve**: Write "Approved" in Human Review Notes, proceed to Stage 6 + - **Request changes**: Write specific feedback in Human Review Notes, agent fixes (go back to Stage 3) + +### What You're Approving + +**Reasoning, not tasks.** You're not checking code line-by-line. You're checking: +- The agent understood the problem +- The agent made sensible decisions +- The agent verified the work +- Integration with dependencies was checked + +If the reasoning is sound and verification was thorough, approve. + +### Exit Gate + +Human has written "Approved" in Human Review Notes. + +--- + +## Stage 6: Close + +### Who: Agent (with human oversight) + +### Steps + +1. Human changes status to `done` +2. Human adds `completed: <date>` to frontmatter +3. Agent deletes the `## Agent Working Notes` section +4. Agent creates PR with issue number in title: `feat(#023): Add delete account button` +5. Agent commits any remaining changes +6. Agent notifies human PR is ready +7. Human reviews PR and merges (or agent merges if approved) + +### PR Requirements + +- Title includes issue number: `feat(#023): ...`, `fix(#042): ...` +- PR description links to the issue file +- All checks pass (including pre-commit hook) + +### Exit Gate + +Issue closed. PR merged. Issue file has: +- status: done +- completed: <date> +- Agent Working Notes section deleted + +--- + +## Dependency Handling + +### Creating Dependent Issues + +When creating an issue that depends on another: +1. List the dependency in `depends-on` frontmatter +2. Read the dependency's issue file +3. Understand what the dependency produces +4. In your Plan, reference the dependency's output + +### Working on Dependent Issues + +Before starting: +1. Read the dependency's issue file +2. Read the dependency's code output (PR, files changed) +3. Verify the dependency works in context + +During: +4. If dependency breaks, document it in Blockers +5. Do not assume dependency is correct + +Before claiming done: +6. Verify your work with the dependency's output +7. If integration breaks, fix or document + +### Blocking Issues + +If an issue is blocked by a dependency: +- Set status to `blocked` +- Add a note explaining why +- Move to the next unblocked issue +- Check back when the dependency is closed + +--- + +## Parallel Work + +Multiple agents can work on multiple issues simultaneously if: +1. Issues are not dependent on each other +2. Each agent reads the other's issues (to understand integration points) +3. Each agent documents integration points checked + +If issues ARE dependent: +- Complete the dependency first (or mark it as priority) +- Or coordinate with the human on timing + +--- + +## Handling Scope Creep + +If during implementation you discover the issue needs more than originally scoped: + +1. **Stop coding** +2. Document what was found in Status Log +3. Write a proposed scope change in Status Log +4. Mark it: "Scope change: waiting for approval" +5. **Wait for human decision** +6. Either: + - Human approves scope expansion + - Human creates a new issue for the expanded scope + - Human decides scope stays the same + +Do NOT unilaterally expand scope. Do NOT ignore the scope change. + +--- + +## Error Handling + +| Situation | Action | +|---|---| +| Blocker encountered | Write in Blockers with proposed solution. Wait. | +| Dependency broken | Document in Blockers. Wait for fix or guidance. | +| Scope needs to expand | Stop. Document. Wait for approval. | +| Can't verify something | Document what couldn't be verified and why. Ask for guidance. | +| Human doesn't respond | Send a reminder. Do not proceed without acknowledgment. | +| Pre-commit hook fails | Fix the issue file. Do not bypass the hook. | + +--- + +## When in Doubt + +Ask. Write in the issue file. Wait for response. Proceed only when you have acknowledgment. + +It is better to pause and ask than to assume and break things. diff --git a/package.json b/package.json new file mode 100644 index 0000000..5f2b9d9 --- /dev/null +++ b/package.json @@ -0,0 +1,14 @@ +{ + "name": "workflow-template", + "version": "1.0.0", + "description": "Standard issue-based workflow template for teams", + "private": true, + "scripts": { + "setup": "node .hooks/issue-linter.js --setup", + "validate:issues": "node .hooks/issue-linter.js", + "test": "echo \"Add your test commands here\"" + }, + "devDependencies": { + "pre-commit-hook": "^3.0.0" + } +}