Skip to content

Dev PR

Commit work-buddy code changes with test verification, chained doc update, PII scan, cleanup review, and commit metadata recording. Replaces the prose /wb-commit directions.

Workflow name: dev-pr

Workflow ID: wfd_98fccfad2dc34744ad43bdd74f8c7baa

Execution: main

Slash command: /wb-dev-pr

Override not allowed

Steps

# ID Name Type Depends on
1 assess Snapshot git state (branch, changed files, test candidates) code
2 branch_guard Confirm branch (or create one off main) reasoning assess
3 test Run relevant tests; record pass/fail reasoning branch_guard
4 dashboard_evidence Record dashboard verification coverage code test
5 document Update knowledge-store docs via /wb-dev-document (or explicitly skip with rationale) reasoning dashboard_evidence
6 pii_check Scan changed files for PII patterns code document
7 transient_check Scan changed files for transient identifiers code pii_check
8 cleanup Review own changes for debug code, stale refs, PII and transient hits reasoning transient_check
9 commit Stage precisely and commit reasoning cleanup, dashboard_evidence
10 record Record structured commit metadata via commit_record code commit
11 push Ask user about push + PR; act on the answer reasoning record

Step instructions

assess

Auto-run. The conductor calls work_buddy.dev.commit.assess_state() and passes the result forward. Returned fields: - current_branch, is_main: branch info. - changed_files, classified: what you're about to commit, by bucket (module / knowledge / slash / tests / config / other). - test_candidates: Python tests suggested from changed module names. - dashboard: changed status, component coverage, matching App e2e specs, live-harness relevance, and the selection reason. Health registry changes can alter generated Settings UI without a React file changing. - warnings: soft signals (on main, direct JSON edits, empty diff).

branch_guard

Reasoning step. Read assess.is_main. If true, tell the user they're on a protected branch and create a new one:

git checkout -b <branch-name>

Naming: - fix/<short> — bug fixes - feat/<short> — new features or skills - docs/<short> — documentation-only - chore/<short> — config / CI / deps

If on a feature branch already, confirm the name matches the work and proceed.

Advance with {"branch": "<current branch name>", "ready": true}. Set ready: false only if the user explicitly aborted.


Advance via wb_advance(workflow_run_id=..., step_result={...}). The parameter is step_result (not result) — FastMCP silently drops unknown kwargs.

test

Reasoning step. For each module file you changed (assess.classified.module), run its matching test file(s). The conductor suggested candidates in assess.test_candidates — check them first, but also look for test files that import the modules you changed if the heuristic missed them.

Run via:

uv run python -m pytest <test_files> -q --tb=short

Record: which files ran, pass count, fail count. If any failure is on code you changed, advance with blocking: true and fix before retrying the step. If failures are on code you didn't touch, note them and advance with blocking: false.

For dashboard work, use assess.dashboard and load dev/dashboard/verification-directions. Select the surfaces that exercise the changed behavior:

npm --prefix dashboard-react test
npm --prefix dashboard-react run test:e2e -- --workers=1
npm --prefix dashboard-react run test:e2e:live -- --app cowork
npm --prefix dashboard-react run build

Name the environment for every result. Demo fixture routes support presentation checks. Every persisted write uses the isolated live harness. The default e2e proxy can reach the user's dashboard, so a runner name does not establish isolation.

Record surfaces_run using component, e2e, live, visual, and python. If the change affects a dashboard user task, complete dev/dashboard/ux-review or reuse an existing review whose scope and implementation still match. Set ux_review_ref to its workflow run id or artifact path. Use null when a UX review does not apply and explain why. Reassess when the change expands into another surface.

Missing dashboard surface evidence without a rationale produces a recorded warning. It does not block advancement. Resolve the gap when possible and carry remaining warnings into the commit body and metadata.

If no test files apply (e.g. pure doc change), advance with tests_run: [], tests_passed: 0, tests_failed: 0, blocking: false.

Advance shape:

{
  "tests_run": ["tests/unit/test_foo.py"],
  "tests_passed": 12,
  "tests_failed": 0,
  "blocking": false,
  "surfaces_run": ["python"],
  "ux_review_ref": null,
  "rationale": "optional — e.g. 'no tests apply for pure doc change'"
}


Advance via wb_advance(workflow_run_id=..., step_result={...}). The parameter is step_result (not result) — FastMCP silently drops unknown kwargs.

dashboard_evidence

Auto-run. Reassess the current diff and compare the test result's surfaces_run and rationale with dashboard applicability. Return warnings, the dashboard assessment, the evidence reference, and blocking: false. Scope changes after orientation are included. Keep warnings visible in the commit body and structured record.

document

Reasoning step with a sub-workflow reference. The parent workflow expects you to run /wb-dev-document (workflow name dev-document) to propagate your code changes into the knowledge store before committing.

The normal path

`mcp__work-buddy__wb_run("dev-document")`

Run the sub-workflow to completion (scan → propose → confirm → apply → validate → report). Then advance this step with:

{
  "skipped": false,
  "doc_result": { /* the dev-document apply step's result */ },
  "units_updated": ["<unit path>", ...]
}

If dev-document's validate step reports failures, resolve them before advancing this step — don't commit with a broken store.

The escape hatch (use sparingly)

If the commit is genuinely trivial — a typo, formatting, a test-only change that documents nothing observable — you may skip. skip_rationale is required and must be specific; 'trivial' alone is not acceptable:

{
  "skipped": true,
  "skip_rationale": "Typo fix in a docstring; no behavior change."
}

The rationale will be included in the commit body at the record step so the skip is auditable. If you find yourself writing a long rationale, that's a signal the change is not trivial — run dev-document instead.


Advance via wb_advance(workflow_run_id=..., step_result={...}). The parameter is step_result (not result) — FastMCP silently drops unknown kwargs.

pii_check

Auto-run. The conductor calls work_buddy.dev.commit.pii_check() against the current change set. Returns {files_scanned, hits, clean}. - clean: true → proceed. - hits → each entry has file, line, label, match, context. Fix before committing. Common fixes: replace personal paths with config-driven values (cfg["vault_root"]), replace named references to the user with 'the user', move machine-specific paths to gitignored configs.

transient_check

Auto-run. The conductor calls work_buddy.dev.commit.transient_check() against the current change set: the durable-surfaces rule applied programmatically to the diff. Returns {files_scanned, hits, clean}; each hit has file, line, category, match, context. Categories: stage labels (prose and identifier form), dates, task ids, PR/branch/commit references, archaeology identifiers, session tags, migration phrasing. Test-file date and task-id literals are auto-suppressed (fixture data), and journal-shape files (CHANGELOG.md, DECISIONS.md) are skipped.

Unlike PII hits, transient hits are advisory input for the cleanup step, not automatic defects: a quoted example or a versioned interface name is legitimate; a rollout label is not. Judge each hit there.

cleanup

Reasoning step. Walk each file you changed and look for: - Debug prints, TODO/FIXME you left while working. - Stale imports or references to things you renamed. - Dead code from a refactor. - PII hits from the pii_check step — if any, fix them now. - Transient hits from the transient_check step. The scan finds references whose meaning depends on the moment the change was made: branch names, PR numbers, dates, agent-session tags, "after the recent migration", "Slice 3"-style stage labels, "for now", "temporary workaround", or identifiers that read as archaeology (legacy_*, _after_migration_shim, pre_2026_04_26_*). For each hit, either replace with stable domain terms describing current behavior, or judge it legitimate: versioned labels survive only when they name a documented interface, schema, protocol, migration, or compatibility boundary, and quoted examples of the forbidden patterns are fine. Also self-review for anything the regex cannot see (fuzzy phrasing, misleading names). Commit messages are exempt — they're a write-once journal of how the change arrived.

Do not refactor unrelated code. Scope is your own changes only.

Advance with {"ready": true} when clean. If you find and fix issues, mention them in your response so the user sees the pass happened.


Advance via wb_advance(workflow_run_id=..., step_result={...}). The parameter is step_result (not result) — FastMCP silently drops unknown kwargs.

commit

Reasoning step. Stage and commit.

Sign off every commit (DCO)

work-buddy enforces a Developer Certificate of Origin: every commit must be signed off with the -s flag (git commit -s ...), which appends a Signed-off-by trailer. The DCO status check is required on main — a pull request with any unsigned commit cannot merge. Commit with -s from the start; to repair commits already made without it, run git rebase --signoff origin/main and force-push.

Stage precisely

Do NOT use git add -A or git add ..

  • When you own the whole file's diff: git add <file1> <file2>.
  • When a file mixes your hunks with another agent's: git add -p <file> and accept only yours.

Verify with git diff --cached --stat that only your intended changes are staged.

Commit message

Include each dashboard_evidence.warnings item under Dashboard verification warning: and any coverage rationale under Dashboard verification rationale:. These are scoped evidence records, not claims of a passing UX review.

Follow the repo's conventional-commit style (check git log --oneline -5). Keep the subject short and imperative; put the why in the body.

If the document step was skipped, paste the skip_rationale into the commit body under a Doc-update skipped: line so the skip is visible in history.

Use a HEREDOC for multi-line commit messages, and keep the -s:

git commit -s -m "$(cat <<'EOF'
<subject>

<body>
EOF
)"

Advance with:

{
  "commit_hash": "<full or 7+ char hash from git output>",
  "message": "<full commit message, including dashboard verification warnings and rationale>",
  "staged_files": ["..."]
}


Advance via wb_advance(workflow_run_id=..., step_result={...}). The parameter is step_result (not result) — FastMCP silently drops unknown kwargs.

record

Code step. Dispatch commit_record via wb_run with structured metadata. Pull most fields from prior step_results:

Use the full commit.message, including its Dashboard verification warning: and Dashboard verification rationale: entries, so the structured artifact retains the same coverage record as the git commit. Do not reduce it to the subject line.

`mcp__work-buddy__wb_run("commit_record", {
    "commit_hash": <commit.commit_hash>,
    "message": <commit.message>,
    "branch": <branch_guard.branch>,
    "files_changed": ",".join(<commit.staged_files>)`,
    "tests_run": ",".join(<test.tests_run>),
    "tests_passed": <test.tests_passed>,
    "tests_failed": <test.tests_failed>,
    "knowledge_units_updated": ",".join(<document.units_updated or []>),
    "summary": <one-line plain-English summary>,
})

Return the result dict unchanged. If commit_record fails, surface the error and proceed to the push step — a failed metadata record does not block the commit from being pushed.


Advance via wb_advance(workflow_run_id=..., step_result={...}). The parameter is step_result (not result) — FastMCP silently drops unknown kwargs.

push

Reasoning step. Ask the user: "Want me to push and create a PR?"

If yes:

git push -u origin <branch>
gh pr create --title "<concise title>" --body "$(cat <<'EOF'
## Summary
<1-3 bullets>

## Test plan
- [ ] <what to verify>

Task: <task-id if any>
EOF
)"

Report the PR URL back.

If the user declines, confirm the commit is on the local branch and remind them they can push later. Do NOT push without asking — this is a shared-state action that requires explicit consent.


Advance via wb_advance(workflow_run_id=..., step_result={...}). The parameter is step_result (not result) — FastMCP silently drops unknown kwargs.

Context

Commit work-buddy code with test verification, doc hygiene (via chained /wb-dev-document), PII scan, cleanup review, structured commit metadata recording, and optional push + PR.

Philosophy

The previous /wb-commit was a prose checklist loaded by a slash command. Agents skipped the doc-update step under time pressure and silently left stale knowledge units in place. This workflow makes the doc check a DAG step whose skip requires explicit rationale, recorded in the commit body — so skipping is auditable, not invisible.

What this workflow is NOT

  • Not a general code-review step. Use /security-review or a PR reviewer for deeper passes.
  • Not a substitute for the agent's judgment on what 'precise staging' means. You still need to read your own diffs.
  • Not a gate on operational work. Only use from dev mode (after /wb-dev orient) when changing the work-buddy codebase itself.

Doc-update skip policy

document.skipped: true is allowed but expensive: the skip rationale lands in the commit body, visible forever. Use only when the change genuinely documents nothing observable (pure typos, whitespace, test-only internals). When in doubt, run dev-document — empty proposals: [] is cheap and honest.