What is this? A Claude Code skill that guides non-developer team members through picking a bug from a backlog, setting up a dev environment, fixing it with AI assistance, and shipping a PR. Built by team Ceres at Automattic for the Woo Extensions Bug Blitz.
Can I use this? This is a snapshot of our team's internal skill, shared as an example. It references our tools (Linear, specific extensions) and won't work out of the box for you — but the workflow and phases are portable. Fork it and adapt it to your stack.
How to install: Save this file as
.claude/skills/bug-blitz/skill.mdin your project. Then invoke it with/bug-blitzin Claude Code. See Claude Code skills documentation for details.
name: bug-blitz description: Guided bug-fixing session. Picks a bug from your issue tracker, sets up the environment, walks through the fix, and ships a PR. Progress tracked as sub-issues under a parent issue. Use when someone mentions bug blitz, fix a bug, or bug squashing.
Guide a team member through picking a WooCommerce extension bug, setting up an environment, fixing it with AI assistance, and shipping a PR. All work happens in this repo — extension code is cloned into tmp/.
The parent issue for this Bug Blitz session. Sub-issues are created under it. Update this before each new session.
- Parent issue ID: YOUR-PARENT-ISSUE
All references to "the parent issue" throughout this skill refer to this ID. It is defined here once — do not hardcode it elsewhere.
All repos are on github.com — no Automattic proxy needed. The Bug Blitz targets extensions only (not WooCommerce Core). See the [full target list]([your bug blitz kickoff post]).
| Extension | Linear Team | Linear Label (if needed) | Repo |
|---|---|---|---|
| WooPayments | [team] | Automattic/woocommerce-payments | |
| Stripe for WooCommerce | [team] | woocommerce/woocommerce-gateway-stripe | |
| WooCommerce Subscriptions | [team] | private | |
| Product Bundles | [team] | woocommerce-product-bundles |
private |
| Composite Products | [team] | woocommerce-composite-products |
private |
| Gift Cards | [team] | woocommerce-gift-cards |
private |
| Product Add-Ons | [team] | woocommerce-product-addons |
private |
| Product Recommendations | [team] | woocommerce-product-recommendations |
private |
| Back in Stock Notifications | [team] | woocommerce-back-in-stock-notifications |
private |
| Min/Max Quantities | [team] | woocommerce-min-max-quantities |
private |
| Conditional Shipping and Payments | [team] | woocommerce-conditional-shipping-and-payments |
private |
| Additional Variation Images | [team] | woocommerce-additional-variation-images |
private |
| Points and Rewards | [team] | woocommerce-points-and-rewards |
private |
| AutomateWoo | [team] | private | |
| AutomateWoo – Refer a Friend | [team] | private | |
| AutomateWoo – Birthdays | [team] | private | |
| Google Analytics for WooCommerce | [team] | woocommerce/woocommerce-google-analytics-integration | |
| Google for WooCommerce | [team] | woocommerce/google-listings-and-ads | |
| MailPoet | [team] | mailpoet/mailpoet | |
| Pinterest for WooCommerce | [team] | woocommerce/pinterest-for-woocommerce | |
| WooCommerce Analytics | [team] | woocommerce/woocommerce | |
| WooCommerce Tax | [team] | private | |
| Product CSV Import Suite | [team] | private |
Important: Some extensions share a Linear team. For those, use the Linear Label column to filter issues to the specific extension. For teams with a single extension, filtering by team is sufficient.
If the user picks "Other", ask them for the extension name, Linear team identifier, and repo path (Org/repo) on github.com. Refer them to the [full target list]([your bug blitz kickoff post]).
All repos use standard github.com commands:
- Clone:
git clone git@github.com:<Org>/<repo>.git - gh auth check:
gh auth status - gh auth login:
gh auth login - gh commands:
gh <command> - Push: standard
git push
Read your team roster from your project's configuration to match user names to Linear usernames. Do not hardcode — always read the file.
When presenting bugs, estimate difficulty from these signals:
- Easy — short description, single behavior affected, keywords like trim/validation/string/copy/label/display. No related issues.
- Medium — moderate description length, keywords like logic/conditional/calculation/state. 1-2 related issues.
- Hairy — long description, mentions multiple files/components/systems. Many related issues or cross-extension references.
Present the estimate as a guess and let the user override.
We are guests in these extension repositories. Follow these norms:
- Plain language in PRs and comments. Don't call out individual developers by name when discussing code decisions.
- Link to prior discussions when referencing historical decisions (PR reviews, GitHub issue threads). Let the history speak for itself.
- Follow the repo's conventions. Check for CLAUDE.md, AGENTS.md, PR templates, changelog formats, and branching models (e.g.
developvstrunk). Adopt them. - Don't close issues unilaterally. When recommending closure, comment with evidence (what fixed it, when, how you verified) and let the owning team make the final call.
- State facts, not judgments. When describing root causes, say what the code does and what the reported behavior is. Don't speculate about what was "overlooked" or "not accounted for."
Before starting, verify the required tools are available:
-
Linear MCP — try fetching the parent issue (see Configuration). If it fails:
Linear MCP isn't connected. You'll need it for bug selection and progress tracking. Run this in your terminal (outside Claude Code), then restart Claude Code:
claude mcp add --transport sse --scope user linear-server https://mcp.linear.app/sseIt will open your browser for OAuth authentication.
If Linear MCP is not available after guidance, the skill cannot proceed — let the user know and stop.
-
Slack integration (optional) — if you have an MCP server that provides Slack access, verify it's connected. The skill can use it to fetch linked Slack threads for additional bug context. Not required — the skill works fine without it.
-
gh CLI — run
which gh. If not installed:You'll need the GitHub CLI to create PRs later. Install it with:
brew install ghI'll check auth in the setup phase.
If gh is missing, note it but continue — we can revisit during setup.
- Fetch the parent issue (see Configuration for the parent issue ID) via Linear MCP to get session context — title, description, date, facilitator.
- Also fetch its comments to see if there are any session-specific instructions.
- Greet the user:
Welcome to the Bug Blitz!
I'll walk you through the whole process — picking a bug, getting set up, fixing it, and shipping a PR. Everything happens right here. I'll track your progress on Linear as we go.
Let's start by finding you a bug to work on.
Then proceed immediately to Phase 2.
Ask two questions, one at a time. Wait for the user's answer before asking the next.
Which extension do you want to work on? Here are the eligible ones:
- WooPayments
- Stripe for WooCommerce
- WooCommerce Subscriptions
- Product Bundles
- Composite Products
- Gift Cards
- Product Add-Ons
- Product Recommendations
- Back in Stock Notifications
- Min/Max Quantities
- Conditional Shipping and Payments
- Additional Variation Images
- Points and Rewards
- AutomateWoo
- AutomateWoo – Refer a Friend
- AutomateWoo – Birthdays
- Google Analytics for WooCommerce
- Google for WooCommerce
- MailPoet
- Pinterest for WooCommerce
- WooCommerce Analytics
- WooCommerce Tax
- Product CSV Import Suite
Look up the selected extension in the Extension Mapping table.
What difficulty level are you going for?
- Easy — small, contained fixes. A
.trim()call, a copy change, a missing validation. Great for a first contribution.- Medium — logic bugs, conditional handling, missing edge cases. More codebase reading, but I'll handle the heavy lifting.
- Hairy — multi-file changes, cross-system issues. You might not finish in 90 minutes, but you'll learn a lot.
Using the Linear MCP, search for bugs matching:
- Team: the Linear team for the selected extension
- Status: Todo or Backlog
- Assignee: unassigned
- Label: Bug (or similar — check what labels the team uses)
- Extension label (for shared-team extensions only): also filter by the extension-specific label from the Extension Mapping table (e.g.
woocommerce-product-bundles). This is critical — some teams cover many extensions, so without the label filter you'll get bugs for unrelated extensions.
Use query_data or list_issues with appropriate filters. Fetch up to 15 issues to have enough to filter.
Prioritize bugs that drive customer tickets — look for keywords like "customer", "ticket", "support", "reported", "complaint" in issue descriptions. These are the highest-impact fixes.
For each issue returned, apply the difficulty heuristic from the Configuration section. Filter to the user's chosen difficulty level, but if fewer than 3 match, include adjacent difficulties and note them.
Show 3-5 bugs. For each, include a brief reason for the difficulty estimate so the user can sanity-check it:
Here are some options (difficulty is my best guess — you know better):
[ISSUE-ID]: [Title] (Easy — [one-line reason, e.g. "single function, clear reproduction steps, no related issues"]) [One-line summary of what's broken and why it matters for support]
[ISSUE-ID]: [Title] (Medium — [one-line reason]) [One-line summary]
...
Pick a number, or tell me if you want to see more options or try a different product/difficulty.
Once the user picks a bug:
- Identify the user. If you already know who they are from context, confirm: "I'll assign this to [Name] — is that right?" If you don't know, ask their name. Match against your team roster in your project's configuration first. If the name is ambiguous or not on the roster, use
get_user(Linear MCP, accepts full name or email) to look up their Linear username, then confirm. If that doesn't find them, ask for their Linear username or email directly. - Assign the issue to the user in Linear via MCP (
save_issuewith assignee). - Add the
your-tracking-labellabel to the issue in Linear. Append this label to the existing labels — do not replace or remove any labels already on the issue. Fetch the current labels first, then save with the full list plus the new one. This label is used for tracking all Bug Blitz contributions across teams. (Linear view: [your tracking view URL]) - Confirm: "Got it — [ISSUE-ID] is now assigned to you and tagged for the Bug Blitz. Let's get set up."
Store the selected issue details (ID, title, description, repo info, GitHub host) for use in later phases.
Before setting up the environment, do a deeper read of the specific bug the user picked. This catches issues that look easy in a title but have hidden depth in the comments or description.
-
Fetch the full issue via Linear MCP, including all comments.
-
Rate the complexity on this scale:
- 1–3 (Easy) — short description, clear reproduction steps, single behavior, no related issues
- 4–6 (Medium) — moderate scope, some conditional logic or state involved, 1–2 related issues
- 7–10 (Hairy) — long or vague description, multiple files/systems, many related issues, security-sensitive, or no clear acceptance criteria
-
Present the assessment briefly:
Quick complexity check on [ISSUE-ID]:
I'd rate this a [score]/10 ([Easy/Medium/Hairy]). [One or two sentences of reasoning — what signals drove the rating.]
-
If the rating matches the user's stated difficulty preference (or is easier), proceed:
Looks like a good match for what you're after. Let's get set up.
-
If the rating is significantly higher than what the user chose (e.g. they picked Easy but this reads as Hairy), flag it clearly and offer an out:
This one reads harder than it looks — I'd call it [rating] because [reason]. Want to continue anyway, or pick a different bug?
Wait for their response. If they want to continue, proceed. If they want a different bug, loop back to Phase 2 Bug Selection without re-asking Q1 and Q2 (keep the extension and difficulty preference).
Proceed to Phase 3.
Announce the plan before doing anything:
I'm going to set up everything you need. Here's what I'll do and why:
- Clone the repo — downloading [extension] into
tmp/[repo-name]/so we can work on the code- Check GitHub auth — making sure you can push to [github host] and create a PR
For testing, we'll rely on the automated test suite and code review — QIT runs regression tests on every PR automatically. If you want to test manually in a browser too, I can help with that, but it's optional.
If you already have a different setup you'd prefer, let me know and I'll adapt.
Wait for the user to confirm or suggest alternatives before proceeding.
Check if tmp/[repo-name]/ already exists:
- If yes: "I see this repo already cloned. Want me to sync it to the latest trunk, or start fresh?"
- Sync:
cd tmp/[repo-name] && git checkout trunk && git pull - Fresh: First run
git statusin the existing clone to check for uncommitted changes. If there are uncommitted changes, warn the user: "There are uncommitted changes from a previous session. Want me to discard them and start fresh, or keep them?" Only delete after explicit confirmation:rm -rf tmp/[repo-name]then clone.
- Sync:
- If no: Clone using the correct host URL from the extension mapping:
Then:git clone [clone-url] tmp/[repo-name]cd tmp/[repo-name] && git checkout trunk && git pull
Tell the user what's happening and why at each step. These are non-developers — don't assume they know what git checkout trunk means.
Run the appropriate auth check command from the GitHub Host Commands config:
-
If authenticated: "GitHub auth looks good — you're logged in as [username]."
-
If not authenticated: Walk the user through it:
You'll need to authenticate with [GitHub host] so we can push code and create a PR later.
I'll run the login command — it will open your browser for authentication. Follow the prompts there.
Run the auth login command. Wait for confirmation.
By default, testing relies on the automated test suite (QIT) and code review. Do not prompt for a test environment unless the user asks for one.
If the user asks to test manually in a browser, offer these options:
If you'd like to verify your fix visually, here are some options:
- Jurassic Ninja — go to jurassic.ninja/create?woocommerce, create a site, and paste the SFTP URL here. Quick to set up, no local dependencies.
- Local Docker — some extensions provide
npm run upor similar. Checkpackage.jsonscripts — not all repos have this.- wp-env — I can set up a local WordPress site at
tmp/bug-blitz-test-site/with a.wp-env.jsonthat pulls in WooCommerce and the extension. Requires Docker Desktop. Supports automated verification with Playwright MCP if available. Usenpx @wordpress/env(notwp-env— the bare package name doesn't resolve).- Existing test site — if you have a WordPress site you use for testing, give me the details
Or we can skip this and let QIT + the reviewers handle verification.
If the user provides a JN SFTP URL (format: sftp://[site]:[password]@[host]:[port]//[path]):
Parse the connection details:
- SSH user: the site name (e.g.
extended-lamprey.jurassic.ninja) - SSH password: the string between
:and@ - SSH host: the hostname after
@(e.g.ssh.atomicsites.net) - SSH port: the port number (typically
22) - Document root: the path after the port (e.g.
/srv/htdocs/) - Site URL:
https://[site name] - Plugins directory:
[document root]/wp-content/plugins/
Test the connection and confirm.
If Docker: Run npm run up or npm run up:recreate in tmp/[repo-name]/ and confirm the local site is accessible.
If existing site: Ask for URL and access details.
Create a sub-issue under the parent issue (from Configuration) in Linear:
- Title:
[User's name] — [Issue ID]: [Short bug title] - Assignee: the user (by Linear username from the team roster)
- Parent: the parent issue ID from Configuration
Use save_issue via Linear MCP. Set the parent to the parent issue's internal ID (fetch it in Pre-flight/Phase 1 if not already available). Create it in In Progress status.
Sub-issue status transitions throughout the skill:
- In Progress — on creation (Phase 3)
- Done — when PR is submitted (Phase 5), or when the session ends with a final update
The sub-issue tracks the session's work, not the PR lifecycle. Submitting a PR means the session goal is achieved.
Update the sub-issue status at each transition using save_issue.
Then post the first comment on the sub-issue:
Setup complete
- Extension: [name]
- Repo: cloned to
tmp/[repo-name]- Test environment: [JN URL] / skipped
- Bug: [Linear issue URL]
- Starting fix work now.
Confirm to the user: "I've created a sub-issue under the parent issue to track your progress. Moving on to the fix."
Proceed to Phase 4.
All code operations in this phase happen inside tmp/[repo-name]/. Use absolute paths when running commands.
Before touching any code, perform a planning process with the user. For medium and hairy bugs, use superpowers:brainstorming (requires the superpowers plugin) to explore the root cause and design the fix collaboratively, then save the spec to issues/{parent-id}/ so context survives session interruptions. Offer to open it for the user to review.
Based on the bug description, comments, and an initial exploration of the extension codebase, lay out the steps needed to fix this bug:
Here's my plan for fixing this bug:
- Create a working branch
- [Investigate: specific area to look at]
- [Fix: what needs to change]
- [Test: write regression test if test suite exists]
- Self-review the changes
- Commit, push, and create PR
- Update Linear
Does this look right, or would you adjust anything?
Wait for the user's approval. Use superpowers:writing-plans (requires the superpowers plugin) when available for the implementation plan; fall back to EnterPlanMode/ExitPlanMode otherwise. Then create a task for each step using TaskCreate. Mark each task as in_progress when starting and completed when done. This gives the user visibility into progress and ensures nothing gets skipped.
If the plan needs to change mid-execution (e.g. the root cause is different than expected), update the tasks accordingly and let the user know.
Create a working branch from trunk:
cd tmp/[repo-name]
git checkout -b fix/[ISSUE-ID]-[short-slug]Tell the user:
I've created a branch called
fix/[ISSUE-ID]-[short-slug]. This is your isolated workspace — everything you change here stays separate from the main codebase until we submit a PR.
- Read the Linear issue description and fetch its comments via Linear MCP. Comments often contain reproduction steps, customer context, workarounds, or developer notes that aren't in the description. Also check if there's a synced Slack thread linked from the issue — if you have an MCP server with Slack access, fetch it for additional context (discussions, screenshots, customer quotes).
- Read the linked GitHub issue (if one exists — check the Linear issue's attachments). GH issues often contain reproduction steps, proposed fixes, related bugs, and developer discussion that isn't on Linear. Use
gh issue view <number> --repo <org/repo> --json title,body,commentsto fetch the full issue with comments. - Confirm reproducibility. Before investigating code, try to reproduce the bug in the test environment. If it can't be reproduced, research whether it was resolved — either directly via a fix in this repo, or as a side effect of an upstream change (e.g., a WooCommerce core or parent plugin update). An unreproducible bug may follow the already-fixed protocol below.
- Explore the extension codebase. Use Grep and Glob to find the relevant code. Look for:
- Keywords from the bug description
- File paths mentioned in the issue
- Related function names or class names
- Root cause analysis: Check
git logandgit blamefor the relevant code to understand how it got to this state. Check GitHub PR history for related discussions — prior reviews often explain design decisions. Present findings as history: "This was introduced in [commit/PR] as part of [feature]." State what the code does and what the reported behavior is — let the facts speak. - Present your findings in plain language:
Here's what I found:
The bug: [plain-language description of what goes wrong]
Where it happens:
[file path]around line [N] — [brief explanation of what this code does]The expected behavior: [what should happen instead]
Does this match what you've seen in support tickets? Anything I'm missing?
Wait for the user's response. If they have additional context, incorporate it.
Milestone nudge:
Want me to post a progress update to your sub-issue? Here's what I'd say:
"Root cause identified: [brief description]. Relevant code in
[file path]."Post it?
If yes, post the comment to the sub-issue via Linear MCP.
If investigation reveals the bug is already resolved in the current codebase:
- Verify the fix works — in the test environment or by reading the code and identifying the fix commit/PR
- Update the Linear issue — add the
your-tracking-labellabel, set status to "In Review", and comment with your findings (what fix resolved it, when it shipped, how you verified). Let the owning team close it. If the Linear issue is archived and can't accept comments, fall back to the linked GitHub issue. - Create the sub-issue as Done to track the investigation work
- Move on to the next bug
This is a valid outcome — confirming a fix and cleaning up stale issues is useful work.
- Propose the code change. Show what you plan to change and explain in plain language why:
Proposed fix:
In
[file path], I'll [plain-language description of the change]. Here's what the code looks like now vs. what it would look like after:Before: [relevant code snippet]
After: [modified code snippet]
Why this works: [explanation a non-developer can follow]
Want me to apply this?
- Wait for user confirmation.
- Apply the fix using the Edit tool.
- Check if the extension has a test suite (look for
tests/ortest/directories,phpunit.xml,jest.config, etc.):- If yes: Write a regression test that covers the bug. Explain what the test does:
I'm also adding a test that verifies this exact bug doesn't come back. It [description of what the test checks].
- If no test suite or unclear: Skip and note it.
- If yes: Write a regression test that covers the bug. Explain what the test does:
Milestone nudge:
Fix applied. Want me to update your sub-issue? Here's what I'd say:
"Fix applied: [what changed]. [Regression test added / No test suite found]."
Post it?
Review your own changes. Run git diff in tmp/[repo-name]/ and examine the output for:
- Edge cases not covered
- Unintended side effects
- Style inconsistencies with surrounding code
- Missing error handling that the original code has elsewhere
- Any files changed that shouldn't have been
Present the review:
Self-review:
[Summary of what changed — files modified, lines added/removed]
Looks good:
- [Things that are correct]
Flagged for attention:
- [Any concerns, or "None — this looks clean"]
If issues are found, propose corrections and apply after confirmation.
If a test environment was set up in Phase 3:
Deploy the modified code to the test environment and tell the user:
Your fix is live at [test URL]. Try reproducing the original bug — it should be resolved now.
[Specific testing steps based on the bug]
Let me know what you see.
Wait for feedback. If they report issues, loop back to Step 3.
If no test environment (the default):
The self-review looks clean and QIT will run automated regression tests on the PR. Ready to ship when you are.
Milestone nudge:
Want me to post a testing update? Here's what I'd say:
"Review complete. [Verified on test site / Relying on automated tests + code review]. [Any observations]."
Post it?
Proceed to Phase 5.
- Stage and commit changes in
tmp/[repo-name]/:
First, run git status in tmp/[repo-name]/ and show the user which files changed. Stage only the files that were intentionally modified — do NOT use git add -A or git add ., which can accidentally include IDE config, .env files, or debug artifacts. Stage files by name.
Draft a commit message and show it to the user before committing. Let them adjust if needed:
cd tmp/[repo-name]
git add [specific files]
git commit -m "Fix [ISSUE-ID]: [short description]
[One-paragraph explanation of what was wrong and what this change does.]
Fixes: [Linear issue URL]"- Push the branch:
cd tmp/[repo-name]
git push -u origin fix/[ISSUE-ID]-[short-slug]If the push fails, check the error message and help the user troubleshoot (auth issues, permission denied, etc.).
Create a draft PR using the appropriate gh command from the GitHub Host Commands config. Draft PRs are visible to the owning team but clearly marked as not ready for review — this gives the HE a chance to review the PR themselves before it enters the review queue.
PR title: Fix [ISSUE-ID]: [short description]
PR body (use a heredoc):
## Summary
[Plain-language description of the bug and the fix, written for the engineering team that owns this extension.]
## Bug
[ISSUE-ID]: [Title]
[Linear issue URL]
## Changes
- [Bullet list of what changed and why]
## Testing
- [How the fix was verified — JN site testing notes or "Automated tests added, manual testing skipped"]
- [Regression test description if one was added]
## Notes
This PR was created during the [Woo Bug Blitz](https://developer.woocommerce.com/2026/04/08/bug-blitz-how-woos-happiness-team-crushed-150-backlogged-bugs/) using the [`/bug-blitz` Claude Code skill](https://gist.github.com/woogists/4ff8af7ff81b6a84dce2bfdc22db36d6). The fix was authored with Claude Code assistance by a Happiness Engineer who encounters this bug in support tickets.
Use gh pr create --draft to create it in draft state.
Present the PR URL to the user:
Draft PR created! [PR URL]
Take a look and make sure everything looks right. When you're happy with it, click "Ready for review" on GitHub to move it into the review queue. QIT will run automated tests automatically.
-
Update the original bug issue status to "In Review" via Linear MCP (use
save_issueto update status). If the user didn't finish the fix, set it to "In Progress" instead. -
Update the sub-issue status to "Done" (PR submitted = session goal achieved). If the user didn't finish, leave it "In Progress".
-
Post a final comment on the sub-issue (created in Phase 3):
Status: PR submitted PR: [PR URL] What was done: [plain-language summary of the fix] Findings: [anything surprising discovered during the fix — unexpected code patterns, related bugs spotted, etc. If nothing notable: "Straightforward fix, no surprises."] Open questions: [if any, otherwise omit this line]
If the user ran out of time or hit a blocker and couldn't finish:
Status: In progress / Blocked What was done: [what was accomplished so far] Where it stopped: [current state — e.g. "Fix applied but tests failing", "Root cause identified but fix is complex"] Next steps: [what someone would need to do to finish] Findings: [anything learned along the way]
Proceed to Phase 6.
Nice work! Your draft PR is up and your progress is logged on Linear.
What happens next (from the Bug Blitz review flow):
- Review your PR — take a look at the diff on GitHub. When you're happy with it, click "Ready for review" to move it out of draft state.
- QIT automated checks — regression tests run automatically on your PR. Check the PR page for results.
- Specialized HE review (optional) — a Product Ambassador, support pod member, or domain expert can test and confirm the fix solves the original issue. If you know someone who owns that area, ping them.
- Engineering review (optional) — the owning team does a code quality check. If there are UX changes, loop in PMs/designers.
- Merge — once reviewed, the fix ships.
Share your PR in the Bug Blitz Slack channel.
Need help? Reach out to your QA team for help with quality checks and filling testing gaps.
Want to pick another bug? I can start over. The setup is already done, so it'll be faster this time.
Or if you're done, that's great too.
If the user wants another bug:
- Loop back to Phase 2 (Bug Selection)
- Skip Phase 3 setup steps that are already done (gh auth, JN site)
- Clone a new extension repo into
tmp/if the user picks a different product, or reuse the existing one
If the user is done:
- End the session with a brief summary of what was accomplished.