kanbot 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +112 -2
  3. package/package.json +75 -5
  4. package/schema/config.schema.json +206 -0
  5. package/src/agents/load.ts +105 -0
  6. package/src/agents/sync.ts +219 -0
  7. package/src/cli.ts +27 -0
  8. package/src/commands/board.ts +140 -0
  9. package/src/commands/completion.ts +30 -0
  10. package/src/commands/doctor.ts +260 -0
  11. package/src/commands/init.ts +119 -0
  12. package/src/commands/run.ts +32 -0
  13. package/src/commands/skills.ts +63 -0
  14. package/src/commands/status.ts +70 -0
  15. package/src/commands/sync.ts +31 -0
  16. package/src/commands/upgrade.ts +70 -0
  17. package/src/completion.ts +217 -0
  18. package/src/config.ts +240 -0
  19. package/src/daemon/derive.ts +413 -0
  20. package/src/daemon/git.ts +187 -0
  21. package/src/daemon/lock.ts +29 -0
  22. package/src/daemon/loop.ts +212 -0
  23. package/src/daemon/notify.ts +44 -0
  24. package/src/daemon/snapshot.ts +109 -0
  25. package/src/daemon/state.ts +60 -0
  26. package/src/daemon/types.ts +73 -0
  27. package/src/errors.ts +171 -0
  28. package/src/github/api.ts +332 -0
  29. package/src/github/gh.ts +110 -0
  30. package/src/github/markers.ts +82 -0
  31. package/src/github/project.ts +288 -0
  32. package/src/github/trust.ts +38 -0
  33. package/src/jobs/prompts.ts +205 -0
  34. package/src/jobs/run.ts +569 -0
  35. package/src/known-hashes.json +132 -0
  36. package/src/log.ts +11 -0
  37. package/src/main.ts +21 -0
  38. package/src/providers/claude.ts +122 -0
  39. package/src/providers/codex.ts +98 -0
  40. package/src/providers/types.ts +94 -0
  41. package/src/schemas/results.ts +116 -0
  42. package/src/templates.ts +192 -0
  43. package/templates/.agents/skills/accessibility/SKILL.md +76 -0
  44. package/templates/.agents/skills/approach-designer/SKILL.md +79 -0
  45. package/templates/.agents/skills/code-review/SKILL.md +83 -0
  46. package/templates/.agents/skills/frontend-design/LICENSE.txt +177 -0
  47. package/templates/.agents/skills/frontend-design/SKILL.md +76 -0
  48. package/templates/.agents/skills/issue-splitting/SKILL.md +78 -0
  49. package/templates/.agents/skills/kanbot-admin/SKILL.md +57 -0
  50. package/templates/.agents/skills/kanbot-idea/SKILL.md +56 -0
  51. package/templates/.agents/skills/plan-template/SKILL.md +85 -0
  52. package/templates/.agents/skills/pr-description/SKILL.md +44 -0
  53. package/templates/.agents/skills/project-conventions/SKILL.md +79 -0
  54. package/templates/.agents/skills/project-memory/SKILL.md +39 -0
  55. package/templates/.agents/skills/project-memory/facts/.gitkeep +0 -0
  56. package/templates/.agents/skills/spec-review/SKILL.md +73 -0
  57. package/templates/.agents/skills/tdd/SKILL.md +51 -0
  58. package/templates/.agents/skills/user-stories/SKILL.md +82 -0
  59. package/templates/.agents/skills/verify-ui/SKILL.md +104 -0
  60. package/templates/.github/ISSUE_TEMPLATE/config.yml +1 -0
  61. package/templates/.github/ISSUE_TEMPLATE/technical.yml +15 -0
  62. package/templates/.github/ISSUE_TEMPLATE/user-story.yml +15 -0
  63. package/templates/.github/pull_request_template.md +15 -0
  64. package/templates/.github/workflows/ci.yml +23 -0
  65. package/templates/.github/workflows/kanbot-merged.yml +30 -0
  66. package/templates/.kanbot/agents/approach-designer.md +31 -0
  67. package/templates/.kanbot/agents/explorer.md +35 -0
  68. package/templates/.kanbot/agents/fixer.md +54 -0
  69. package/templates/.kanbot/agents/implementer-backend.md +57 -0
  70. package/templates/.kanbot/agents/implementer-docs.md +55 -0
  71. package/templates/.kanbot/agents/implementer-frontend.md +54 -0
  72. package/templates/.kanbot/agents/implementer-technical.md +53 -0
  73. package/templates/.kanbot/agents/plan-critic.md +36 -0
  74. package/templates/.kanbot/agents/planner.md +52 -0
  75. package/templates/.kanbot/agents/reviewer-code.md +46 -0
  76. package/templates/.kanbot/agents/reviewer-spec.md +49 -0
  77. package/templates/.kanbot/agents/test-writer.md +35 -0
  78. package/templates/.kanbot/agents/ui-verifier.md +35 -0
  79. package/templates/AGENTS.md +39 -0
  80. package/templates/CLAUDE.md +1 -0
@@ -0,0 +1,56 @@
1
+ ---
2
+
3
+ name: kanbot-idea
4
+ description: Turn an idea into an issue on a kanbot board. Use when the human wants to capture, explore or file an idea, feature or task for kanbot agents to plan later.
5
+ ---
6
+
7
+ # kanbot idea
8
+
9
+ Help the human shape an idea, then file it as a GitHub issue. The board's auto-add workflow puts new issues in **Ideas**, where no agent touches them. Planning happens later, when the human drags the card to **Planning**.
10
+
11
+ You shape the _problem_. The planner agent designs the solution later.
12
+
13
+ ## 1. Find the repo
14
+
15
+ Use the repo the human names. Otherwise read `repo:` from `.kanbot/config.yml` in the current directory. Otherwise ask.
16
+
17
+ GitHub access: `gh` if it is installed and logged in, else the GitHub MCP server's issue tools. If neither works, write the finished issue as markdown for the human to paste.
18
+
19
+ ## 2. Shape it
20
+
21
+ Decide the kind with the human:
22
+
23
+ - **User need**: who needs what, and why. The default.
24
+ - **Technical**: refactoring, tooling, infra. What should be true when done, and who benefits.
25
+
26
+ Ask one question at a time, each with your best guess, until you can write the need (or goal) in two or three plain sentences, plus constraints and links. Capture what the human already knows about solutions as notes, not as the plan.
27
+
28
+ If it is really several ideas, propose one issue each.
29
+
30
+ ## 3. Check for duplicates
31
+
32
+ Search open issues with the idea's key terms (`gh issue list --repo <repo> --search "<terms>"`). If one is close, show it and ask: add a comment there instead, or file a new one?
33
+
34
+ ## 4. Draft
35
+
36
+ Match the repo's issue template, so the issue reads like one filed through GitHub. Read `.github/ISSUE_TEMPLATE/user-story.yml` or `technical.yml` from the repo (locally, or with `gh api repos/<repo>/contents/<path>`). Use each field's `label` as a `### ` heading and put the answer under it. Without templates:
37
+
38
+ ```markdown
39
+ ### Who needs what, and why? (technical: ### Goal)
40
+
41
+ <two or three sentences>
42
+
43
+ ### Notes, constraints, links
44
+
45
+ <notes, or _None._>
46
+ ```
47
+
48
+ Title: the outcome in under 70 characters. Technical issues get the `technical` label. Leave `type:*` labels to the planner.
49
+
50
+ Show the title and body. File it only after the human says yes.
51
+
52
+ ## 5. File it
53
+
54
+ `gh issue create --repo <repo> --title "<title>" --body-file <file>` (add `--label technical` when it applies), or the MCP equivalent.
55
+
56
+ Done when the issue exists and the human has its link. Tell them it is in **Ideas**, and that dragging it to **Planning** starts the planner.
@@ -0,0 +1,85 @@
1
+ ---
2
+
3
+ name: plan-template
4
+ description: The exact markdown structure for an kanbot issue plan, with an example. Use whenever writing, revising or critiquing a plan in the Planning column, or when an implementer or reviewer needs to know which plan section holds what.
5
+ ---
6
+
7
+ # Plan template
8
+
9
+ The plan lives in the issue body. It is the contract for the implementer and both reviewers, and a human approves it by reading it. Keep it short: the reader should grasp it in one minute. Say what and why; the implementer decides how.
10
+
11
+ ```markdown
12
+ ## User story
13
+
14
+ As a <user in context>, I want <capability>, so that <outcome>.
15
+ Need: <one or two sentences: what hurts today and how we'll know it worked.>
16
+ <!-- `technical` issues: "## Technical goal" instead, naming who benefits. -->
17
+
18
+ ## Acceptance criteria
19
+
20
+ - [ ] Given <context>, when <action>, then <observable result>.
21
+ <!-- 2-6 items. Cover the happy path plus the edge cases that matter. -->
22
+
23
+ ## Out of scope
24
+
25
+ - <Only what a reader would otherwise expect. Omit the section if nothing.>
26
+
27
+ ## Design notes
28
+
29
+ <UI: placement, key copy, states that differ from the obvious. Non-UI: API or data shape. 1-4 lines. Omit if nothing beyond the criteria.>
30
+
31
+ ## Implementation steps
32
+
33
+ 1. <Atomic step, with its test.> Files: `path/a.ts`
34
+ <!-- 1-5 steps. -->
35
+
36
+ ## Approaches
37
+
38
+ <!-- Only with explore:N. Exactly N, see the approach-designer skill. -->
39
+
40
+ ## Open questions
41
+
42
+ - <Only what blocks the human's approval, with the default you assume. Omit if none.>
43
+ ```
44
+
45
+ ## Rules
46
+
47
+ - Required: User story (or Technical goal), Acceptance criteria, Implementation steps. Omit other sections when empty; don't write "None."
48
+ - One line per bullet. No prose paragraphs, no repeating the issue text.
49
+ - Acceptance criteria are shared by all approaches. Approach-specific steps go inside each `### Approach k`.
50
+ - File paths come from reading the code, not guesses. Mark new files "(new)".
51
+ - No code blocks. Aim for under 30 lines (excluding approaches); much longer means split the issue.
52
+
53
+ ## Example
54
+
55
+ ```markdown
56
+ ## User story
57
+
58
+ As a freelancer invoicing at month end, I want to see time entries with no project, so that I fix them before invoicing.
59
+ Need: entries without a project silently drop off invoices; users find out when clients complain.
60
+
61
+ ## Acceptance criteria
62
+
63
+ - [ ] Given entries this month have no project, when I open the month view, then a "Needs a project" list shows them, newest first.
64
+ - [ ] Given I assign a project in that list, when it saves, then the entry leaves the list without a reload.
65
+ - [ ] Given every entry has a project, when I open the month view, then the list is hidden.
66
+ - [ ] Given loading fails, when I open the month view, then the list shows "Couldn't load entries" and "Try again".
67
+
68
+ ## Out of scope
69
+
70
+ - Bulk-assigning projects (new issue).
71
+
72
+ ## Design notes
73
+
74
+ List sits above the calendar, collapsed to 5 rows with "Show all (n)". Reuse `ProjectSelect` per row.
75
+
76
+ ## Implementation steps
77
+
78
+ 1. Add `missingProject` filter to `GET /entries`, with tests. Files: `api/entries/routes.ts`
79
+ 2. Add `MissingProjectSection` with its states and tests. Files: `web/entries/MissingProjectSection.tsx` (new)
80
+ 3. Mount it in the month view and refresh after assignment. Files: `web/month/MonthView.tsx`
81
+
82
+ ## Open questions
83
+
84
+ - Include earlier months? Default: current month only.
85
+ ```
@@ -0,0 +1,44 @@
1
+ ---
2
+
3
+ name: pr-description
4
+ description: Template and rules for writing a pull request title and body (Summary, What changed, How to test, Screenshots, Notes for reviewer). Use when filling prTitle/prBody at the end of an implementation, or whenever writing or rewriting a PR description.
5
+ ---
6
+
7
+ # PR description
8
+
9
+ The reader is a busy reviewer with the issue open in another tab. They should know in 30 seconds what changed and how to check it. The daemon adds the `Closes #N` line, plus your `risks` and `testsRun`; don't repeat them in the body.
10
+
11
+ ## Title
12
+
13
+ Conventional commit, imperative, under 72 characters, naming the user-visible effect: `feat(time): show entries that are missing a project`.
14
+
15
+ ## Body template
16
+
17
+ ```markdown
18
+ <One sentence: what this PR does, in user terms. Explore variants: "Approach k: <name>.">
19
+
20
+ ## What changed
21
+
22
+ - <By behaviour, not by file. 1-5 bullets. Call out new dependencies, migrations, env vars.>
23
+
24
+ ## How to test
25
+
26
+ 1. <Steps a human follows, ending in what they should see. 1-5 steps.>
27
+
28
+ ## Screenshots
29
+
30
+ ![<state, width>](.kanbot/screenshots/<branch>/<name>.png)
31
+ <!-- UI changes only; 1-3 images that show the change. -->
32
+
33
+ ## Notes for reviewer
34
+
35
+ - <Only decisions or deviations from the plan the reviewer must know. Omit if none.>
36
+ ```
37
+
38
+ ## Rules
39
+
40
+ - One line per bullet. No "Why" section; the issue has it.
41
+ - Describe what the code does now, not how you got there.
42
+ - Anything you could not verify goes in `risks`, not the body.
43
+ - Screenshot paths must match the `screenshots` output field.
44
+ - Aim for under 20 lines.
@@ -0,0 +1,79 @@
1
+ ---
2
+
3
+ name: project-conventions
4
+ description: This project's stack, exact commands (install, test, lint, typecheck, build, dev server), code conventions and recorded decisions. Read first before planning, implementing, reviewing or fixing anything in this repository, and whenever you need to know how to run tests or start the app.
5
+ ---
6
+
7
+ # Project conventions
8
+
9
+ > **TEMPLATE — fill this in.** Replace every `<placeholder>` with the real value for this repository and delete lines that do not apply. Agents treat this file as the source of truth; wrong commands here cause wrong work everywhere. Until it is filled in, agents must discover commands from manifests and CI config and say so in their output.
10
+
11
+ ## Instructions for agents
12
+
13
+ - Read this skill before doing anything else in the repository.
14
+ - Use the commands below exactly. Do not guess alternatives when one is listed.
15
+ - If something here is wrong or missing and you learned the right answer (a command, a convention, a gotcha), propose an addition: edit this file in the same branch as a separate commit (`docs(conventions): …`) and mention it under "Notes for reviewer" in the PR. Only add durable facts about commands, stack and conventions. Lessons from human corrections go in `project-memory`. Planners and reviewers, who do not edit files, mention the proposed addition in their summary instead.
16
+
17
+ ## Product
18
+
19
+ - What it is: `<one sentence: what the product does and for whom>`
20
+ - Primary users: `<roles>`
21
+ - Language/locale of the UI: `<e.g. Norwegian bokmål, English>`
22
+
23
+ ## Stack
24
+
25
+ - Language and runtime: `<e.g. TypeScript 5, Node 22 / Bun 1.x>`
26
+ - Frontend: `<framework, router, styling approach, component library / design system location>`
27
+ - Backend: `<framework, API style (REST/GraphQL/RPC)>`
28
+ - Data: `<database, ORM/query builder, migration tool>`
29
+ - Package manager: `<pnpm | npm | bun | yarn>` (use only this one)
30
+
31
+ ## Commands
32
+
33
+ | Task | Command |
34
+ | --------------- | ---------------------------------------- |
35
+ | Install | `<pnpm install>` |
36
+ | Dev server | `<pnpm dev>` → `<http://localhost:5173>` |
37
+ | Test (all) | `<pnpm test>` |
38
+ | Test (one file) | `<pnpm vitest run path/to/file.test.ts>` |
39
+ | Test (one name) | `<pnpm vitest run -t "name">` |
40
+ | E2E | `<pnpm playwright test>` |
41
+ | Lint | `<pnpm lint>` |
42
+ | Format | `<pnpm format>` |
43
+ | Typecheck | `<pnpm typecheck>` |
44
+ | Build | `<pnpm build>` |
45
+ | DB migrate | `<pnpm db:migrate>` |
46
+ | Seed data | `<pnpm db:seed>` |
47
+
48
+ Environment: `<how to get a working .env for local dev and tests, e.g. cp .env.example .env; which variables have safe defaults>`
49
+
50
+ ## Layout
51
+
52
+ ```
53
+ <src/ app code>
54
+ <src/components/ shared UI components>
55
+ <src/server/ API handlers>
56
+ <tests/ …>
57
+ ```
58
+
59
+ ## Code conventions
60
+
61
+ - Naming: `<files kebab-case, components PascalCase, …>`
62
+ - Error handling: `<e.g. return Result types in domain code; throw HttpError in handlers>`
63
+ - Validation: `<e.g. zod schemas at API boundaries in src/schemas>`
64
+ - State/data fetching: `<e.g. TanStack Query; no fetch in components>`
65
+ - Styling: `<e.g. CSS modules + tokens in src/styles/tokens.css; no inline colors>`
66
+ - Tests: `<framework, location (co-located *.test.ts), factories in tests/factories>`
67
+ - Commits: Conventional Commits (`feat`, `fix`, `refactor`, `test`, `docs`, `build`, `ci`, `chore`) with a scope.
68
+ - Do not: `<things that look tempting but are wrong here>`
69
+
70
+ ## Decisions
71
+
72
+ Record decisions that agents should not relitigate. One line each, newest first.
73
+
74
+ - `<YYYY-MM-DD>`: `<decision>` because `<reason>`.
75
+
76
+ ## Gotchas
77
+
78
+ - `<e.g. tests need Docker running for Postgres>`
79
+ - `<e.g. generated files in src/gen/ — never edit, run pnpm codegen>`
@@ -0,0 +1,39 @@
1
+ ---
2
+
3
+ name: project-memory
4
+ description: Lessons learned in this repo, mostly from human corrections on PRs. Read before planning, implementing, reviewing or fixing. Write to it when a human correction reveals a rule you'd otherwise break again.
5
+ ---
6
+
7
+ # Project memory
8
+
9
+ Facts later agents need and can't see in the code: why a choice was made, a gotcha, a correction the human gave once and shouldn't have to give again. Commands and setup belong in `project-conventions`; this skill holds what the team _learned_.
10
+
11
+ ## Read
12
+
13
+ Scan the index below. Open a fact when its line bears on your task. A fact the human wrote or merged outranks your own judgement, but not the plan or the human's comments on the current issue or PR.
14
+
15
+ ## Write
16
+
17
+ Add a fact when a human correction on your issue or PR shows a **lesson** that applies beyond this change. One-off details of the task are not lessons.
18
+
19
+ 1. Check the index for a fact that covers it. Update that file instead of adding a second one.
20
+ 2. Create `facts/<short-kebab-slug>.md`:
21
+
22
+ ```markdown
23
+ <The rule, one or two sentences.>
24
+
25
+ **Why:** <the reason the human gave, with a link to the PR or issue comment.>
26
+ ```
27
+
28
+ 3. Add one line to the index: `- [<slug>](facts/<slug>.md): <the rule in a few words>`.
29
+ 4. Commit it on your branch as its own commit (`docs(memory): …`) and mention it in the PR description. The human approves it by merging.
30
+
31
+ Agents that don't edit files (planners, reviewers) suggest the fact in their summary instead.
32
+
33
+ ## Keep it true
34
+
35
+ A fact the code now contradicts is **stale**. If you edit files, fix or delete it in your branch. If you review, a stale fact is a `minor` finding.
36
+
37
+ ## Index
38
+
39
+ <!-- One line per fact, newest last. -->
@@ -0,0 +1,73 @@
1
+ ---
2
+
3
+ name: spec-review
4
+ description: "Verify a change against its plan: every acceptance criterion with evidence, fit with the user need, UX states, accessibility, scope creep and docs. Use when doing the spec/product review pass on a PR branch, or when checking whether an implementation actually does what the issue asked."
5
+ ---
6
+
7
+ # Spec review
8
+
9
+ You review the change from the outside, as the user and the product owner. The question is not "is the code good?" but "did we build the right thing, completely, and nothing else?"
10
+
11
+ ## 1. Criteria evidence table
12
+
13
+ For each acceptance criterion in the plan, record:
14
+
15
+ | # | Criterion (short) | Evidence | Verdict |
16
+ | --- | ------------------------------ | ------------------------------------------------------------------------------------------- | ---------------- |
17
+ | 1 | Missing-project entries listed | `MissingProjectSection.test.tsx` "lists entries newest first"; screenshot `filled-1280.png` | met |
18
+ | 2 | Count updates after assignment | test asserts count; not visible in screenshots | met |
19
+ | 3 | Section hidden when none | no test; no screenshot of empty state | **not verified** |
20
+
21
+ Valid evidence: a test that asserts the behaviour (read it, and check it would fail without the feature), a screenshot of the state, or behaviour you observed by running the app or the command. The PR body's claims alone are not evidence.
22
+
23
+ "Not verified" is a finding. "Not met" is a `blocker`.
24
+
25
+ ## 2. User need
26
+
27
+ Re-read the user story and problem. Then walk through the change as that user:
28
+
29
+ - Can they complete the job from where they start in the app, without knowing it was just built? Is it discoverable?
30
+ - Does the copy use their words, say what will happen, and tell them what to do on error?
31
+ - Is there feedback after every action (saving, saved, failed)?
32
+ - Any dead ends: a state with no way forward or back?
33
+ - Does it solve the problem in the plan, or only satisfy the letter of the criteria?
34
+
35
+ ## 3. UX states (UI changes)
36
+
37
+ Check each state exists and looks right at 390px and 1280px:
38
+
39
+ - [ ] Loading (no layout jump when content arrives)
40
+ - [ ] Empty (explains why and what to do)
41
+ - [ ] Error (says what went wrong and offers a way to recover)
42
+ - [ ] Success / filled, including long text and many items
43
+ - [ ] Disabled and in-progress controls
44
+ - [ ] No horizontal scroll at 390px; tap targets at least 24x24px (44 preferred)
45
+
46
+ Use committed screenshots under `.kanbot/screenshots/<branch>/` first. Capture missing states with `verify-ui` into a temp directory outside the repo.
47
+
48
+ ## 4. Accessibility
49
+
50
+ Run through the `accessibility` checklist for the changed UI. WCAG 2.2 AA failures are `major`; a keyboard trap or an unlabelled primary control is a `blocker`.
51
+
52
+ ## 5. Scope
53
+
54
+ - Diff against the plan's implementation steps: files changed that no step explains?
55
+ - Features, options or settings nobody asked for?
56
+ - Anything listed under `## Out of scope` that was built anyway?
57
+ - Unrequested refactors or renames mixed in?
58
+
59
+ Scope creep is `major` when it adds risk or review burden, `minor` otherwise. Ask for it to be removed or moved to a follow-up issue.
60
+
61
+ ## 6. Docs and communication
62
+
63
+ - User-facing behaviour changed: are help text, README, changelog or docs updated where the project keeps them?
64
+ - Does the PR body explain how to test, with steps a human can follow?
65
+ - For exploratory variants: does the PR say which approach it implements, and does it actually follow that approach?
66
+
67
+ ## Writing findings
68
+
69
+ Quote the criterion or plan line, state what you observed and your evidence, and say what would satisfy it:
70
+
71
+ > Criterion 3 ("Given all entries have a project … the section is not shown") has no test and no screenshot. Add a component test for the empty case and an `empty-390.png` / `empty-1280.png` screenshot.
72
+
73
+ Lead the summary with the tally ("4/5 criteria met, 1 not verified") so a human can scan it.
@@ -0,0 +1,51 @@
1
+ ---
2
+
3
+ name: tdd
4
+ description: Test-driven development loop for agents (red, green, refactor) driven by acceptance criteria. Use when implementing a planned change, fixing a bug or review finding, or refactoring; covers which tests to write, running the narrowest test command first, and never weakening tests to make them pass.
5
+ ---
6
+
7
+ # TDD for agents
8
+
9
+ Tests are how you prove to the reviewers, and to yourself, that each acceptance criterion holds. Write them first so they test the behaviour you were asked for, not the code you happened to write.
10
+
11
+ ## Loop
12
+
13
+ 1. **Pick one criterion** (or one finding, for fixes). Work on one at a time.
14
+ 2. **Red.** Write a test that expresses it through the public interface (rendered UI, HTTP endpoint, CLI, exported function). Run it with the narrowest command. Confirm it fails **on the assertion**, for the reason you expect. A failure from an import error, typo or missing fixture is not red yet; fix the test.
15
+ 3. **Green.** Write the simplest production code that makes it pass. Run the narrow command again.
16
+ 4. **Refactor.** Remove duplication and clarify names while the test stays green. Keep refactors in the code you just touched.
17
+ 5. **Commit** test and code together (`feat: …`, `fix: …`), then move to the next criterion.
18
+ 6. After all criteria: run the full suite, lint and typecheck once.
19
+
20
+ ## Running tests efficiently
21
+
22
+ - Narrowest first: a single file or test name (`bun test path/to/file.test.ts -t "name"`, `npx vitest run file -t name`, `pytest path::test_name`, `go test ./pkg -run TestName`). Use the commands in `project-conventions`.
23
+ - Full suite only after the narrow tests pass, and before you finish.
24
+ - When a test is slow because of setup, still run it; do not replace it with a weaker unit test.
25
+ - Read failure output fully. The first error is usually the real one.
26
+
27
+ ## What to test
28
+
29
+ - Each acceptance criterion: at least one test, named after the behaviour.
30
+ - Unhappy paths named in the plan: invalid input, empty data, failures from dependencies, permission denied.
31
+ - For bugs: a regression test that reproduces the bug and fails before the fix.
32
+ - For refactors: characterization tests that pass before and after; behaviour must not change.
33
+
34
+ Mock only at boundaries you do not own (network, clock, randomness, third-party services). Mocking your own modules makes tests pass while the integration is broken.
35
+
36
+ ## When the test is hard to write
37
+
38
+ - Hard to set up usually means the design is too coupled. Introduce a seam (pass the dependency in) rather than reaching into internals.
39
+ - Purely visual criteria (layout, colour) are verified by screenshot (`verify-ui`), not by snapshot tests of markup.
40
+ - If a criterion genuinely cannot be tested automatically, say which and why in the PR body's "How to test".
41
+
42
+ ## Never
43
+
44
+ - Weaken an assertion, add `.skip`/`xit`/`@pytest.mark.skip`, delete a test, or loosen a type or lint rule to get green.
45
+ - Change a test's expected value to match the code's output without first confirming the code is right and the test was wrong. If so, explain it in the commit message.
46
+ - Leave `only`/`focus` markers or debug output in committed tests.
47
+ - Claim tests pass without having run them in this session. Report the actual command and result in `testsRun`.
48
+
49
+ ## If the existing suite is already red
50
+
51
+ Run it before you change anything. Record pre-existing failures, make sure you add none, and list them in `risks`. Do not fix unrelated failures unless the plan asks.
@@ -0,0 +1,82 @@
1
+ ---
2
+
3
+ name: user-stories
4
+ description: Write issues and plans as user stories framed around a user need, with Given/When/Then acceptance criteria. Use when writing or rewriting an issue, a plan's user story or acceptance criteria, a new issue proposed from a split, or a `technical` goal; also when an issue reads like a feature list or prescribes a solution.
5
+ ---
6
+
7
+ # User stories
8
+
9
+ A story describes a change in what a person can do, and why it matters to them. It is a promise of a conversation, not a specification. The plan's other sections hold the detail.
10
+
11
+ ## Format
12
+
13
+ ```markdown
14
+ As a <specific user in a specific situation>,
15
+ I want <capability, phrased as what they can do, not UI widgets>,
16
+ so that <the outcome they care about>.
17
+ ```
18
+
19
+ - **Who**: a role in context, not "user". "A team lead reviewing last week's time entries", not "an admin".
20
+ - **Want**: a capability. "see which entries are missing a project", not "a red badge on the table row".
21
+ - **So that**: the real outcome. If it restates the want ("so that I can see entries"), dig one level deeper ("so that invoices go out on Monday without manual checks").
22
+
23
+ ## Find the need first
24
+
25
+ Before writing the story, answer these for yourself; put the essence in the plan's one-line `Need:`:
26
+
27
+ 1. Who is struggling, and in what situation does it happen?
28
+ 2. What are they trying to get done (the job)? Use the Jobs-to-be-done lens: _When <situation>, I want to <motivation>, so I can <expected outcome>._
29
+ 3. What do they do today instead (workaround), and what does that cost them (time, errors, risk)?
30
+ 4. How will we know it worked (observable signal)?
31
+
32
+ If the issue only states a solution ("add export to CSV"), work backwards: who needs the data outside the app, and for what? The real need might be met by something smaller.
33
+
34
+ ## Acceptance criteria
35
+
36
+ Write as checkboxes in Given/When/Then. Each criterion is one observable behaviour a reviewer can verify from the PR (via a test, a screenshot, or running it).
37
+
38
+ ```markdown
39
+ - [ ] Given I have time entries without a project, when I open the week view, then those entries are listed under "Needs a project" with a count.
40
+ - [ ] Given all entries have a project, when I open the week view, then no "Needs a project" section is shown.
41
+ - [ ] Given the entries fail to load, when I open the week view, then I see an error with a "Try again" action.
42
+ ```
43
+
44
+ Rules:
45
+
46
+ - Cover the happy path, the empty case, the error case and invalid input. Add permission cases when access differs by role.
47
+ - Use concrete values where they matter ("more than 50 items", "within 2 seconds on the seeded dataset").
48
+ - Describe behaviour, not implementation: no table names, component names or endpoints in criteria.
49
+ - Banned words without a measure: fast, easy, intuitive, user-friendly, properly, robust, support, handle, seamless.
50
+ - 3 to 7 criteria. More than 7 usually means the story should be split (see `issue-splitting`).
51
+
52
+ ## The `technical` exception
53
+
54
+ When the issue has the `technical` label (refactor, infra, tooling, CI, dependency work), replace the story with a technical goal. It still names who benefits.
55
+
56
+ ```markdown
57
+ ## Technical goal
58
+
59
+ Move session storage from in-memory to Redis
60
+ so that the API can run on more than one instance
61
+ which unblocks zero-downtime deploys for the ops team.
62
+ ```
63
+
64
+ Acceptance criteria for technical work are verifiable outcomes: "Given two API instances behind the load balancer, when a user logs in on one, then requests routed to the other are authenticated", "CI build time stays under 6 minutes", "no change in public API responses (contract tests pass)".
65
+
66
+ Do not use `technical` to dodge user framing. If users will notice the change, it is a story.
67
+
68
+ ## Anti-patterns
69
+
70
+ | Smell | Example | Fix |
71
+ | ----------------------- | -------------------------------------------- | --------------------------------------------------------- |
72
+ | Feature list | "Add filters, sorting, export and bulk edit" | One story per user outcome; split the rest. |
73
+ | Solution in story | "I want a modal with a dropdown" | State the capability; put UI ideas in Design notes. |
74
+ | System as user | "As the system, I want to cache…" | Use `technical` with a technical goal, or find the human. |
75
+ | Hollow "so that" | "so that I can use the feature" | Ask "why?" until you reach an outcome. |
76
+ | Untestable criteria | "The page is intuitive" | Name the observable behaviour. |
77
+ | Horizontal slice | "Build the database tables for X" | Slice vertically through UI → API → data. |
78
+ | Epic disguised as story | 10+ criteria, many screens | Split with `issue-splitting`. |
79
+
80
+ ## New issues you propose
81
+
82
+ Bodies of new issues follow the same format: the story, a one-line need, and draft acceptance criteria. Mark anything you assumed with "Assumption:".
@@ -0,0 +1,104 @@
1
+ ---
2
+
3
+ name: verify-ui
4
+ description: Run the app and use Playwright to screenshot key UI states at 390px and 1280px, save them under .kanbot/screenshots/<branch>/, and check console errors. Use after implementing or fixing a UI change, when reviewing a UI PR, or when asked to verify, screenshot or visually check the app. Degrades gracefully when there is no UI or dev server.
5
+ ---
6
+
7
+ # Verify UI
8
+
9
+ Screenshots are how a human reviewer sees the change without checking out the branch. Capture every state the plan's design notes list, at mobile and desktop width, and look at them yourself before anyone else does.
10
+
11
+ ## 1. Decide if this applies
12
+
13
+ Skip with a note in `risks` ("no UI to verify") when the change has no visual effect. If there is a UI but no way to run it (no dev script, needs secrets or external services you do not have), say exactly what is missing and rely on component tests.
14
+
15
+ ## 2. Start the app
16
+
17
+ 1. Get the dev command, port and required env from `project-conventions` (or `package.json` scripts: `dev`, `start`, `preview`).
18
+ 2. Install dependencies if `node_modules` is missing, with the project's package manager.
19
+ 3. Start it in the background, logging to a file, and wait until it responds:
20
+
21
+ ```bash
22
+ (bun run dev > "$TMPDIR/kanbot-dev.log" 2>&1 &)
23
+ for i in $(seq 1 60); do curl -sf http://localhost:5173 >/dev/null && break; sleep 1; done
24
+ ```
25
+
26
+ 4. If it does not come up within ~60s, read the log, make one reasonable fix attempt (missing env default, seed step), then give up and report.
27
+
28
+ ## 3. Get Playwright
29
+
30
+ Prefer the project's own Playwright if it has one (`@playwright/test` in devDependencies, a `playwright.config.*`). Otherwise use it ad hoc without adding a dependency:
31
+
32
+ ```bash
33
+ bunx playwright --version || npx -y playwright --version
34
+ bunx playwright install chromium # once; may be unavailable offline
35
+ ```
36
+
37
+ Do not add Playwright to the project's dependencies unless the plan asks for it.
38
+
39
+ ## 4. Capture states
40
+
41
+ Write a throwaway script outside the repository (e.g. `$TMPDIR/kanbot-shots.mjs`):
42
+
43
+ ```js
44
+ import { chromium } from "playwright";
45
+ const [base, outDir] = process.argv.slice(2);
46
+ const states = [
47
+ { name: "filled", path: "/month", setup: async (page) => {} },
48
+ { name: "empty", path: "/month?fixture=empty", setup: async (page) => {} },
49
+ // reach error/dialog states via setup: route interception, clicks, etc.
50
+ ];
51
+ const browser = await chromium.launch();
52
+ const problems = [];
53
+ for (const width of [390, 1280]) {
54
+ const page = await browser.newPage({
55
+ viewport: { width, height: width === 390 ? 844 : 800 },
56
+ });
57
+ page.on(
58
+ "console",
59
+ (m) =>
60
+ ["error", "warning"].includes(m.type()) &&
61
+ problems.push(`${width} ${m.type()}: ${m.text()}`),
62
+ );
63
+ page.on("pageerror", (e) =>
64
+ problems.push(`${width} pageerror: ${e.message}`),
65
+ );
66
+ for (const s of states) {
67
+ await page.goto(base + s.path, { waitUntil: "networkidle" });
68
+ await s.setup(page);
69
+ await page.evaluate(() => document.fonts.ready);
70
+ await page.screenshot({
71
+ path: `${outDir}/${s.name}-${width}.png`,
72
+ fullPage: true,
73
+ });
74
+ }
75
+ await page.close();
76
+ }
77
+ await browser.close();
78
+ console.log(problems.join("\n") || "no console problems");
79
+ ```
80
+
81
+ Run it with `node`/`bun` from a directory where `playwright` resolves. Use `page.route()` to simulate error and loading states instead of breaking the app.
82
+
83
+ ## 5. Where to save
84
+
85
+ - Implementers and fixers: `.kanbot/screenshots/<branch>/<state>-<width>.png`, committed (`chore: add screenshots for review`). Replace old screenshots of the same state rather than accumulating them.
86
+ - Reviewers: a temp directory outside the repo. Reviewers never commit.
87
+ - List the committed paths in the `screenshots` output field and embed them in the PR body.
88
+
89
+ ## 6. Look at them
90
+
91
+ Open each screenshot and check:
92
+
93
+ - [ ] Nothing overflows or forces horizontal scroll at 390px
94
+ - [ ] No clipped, overlapping or truncated text that hides meaning
95
+ - [ ] Alignment and spacing consistent with surrounding UI
96
+ - [ ] Contrast readable; focus visible where captured
97
+ - [ ] Empty, error and loading states look intentional, not broken
98
+ - [ ] No console errors or uncaught exceptions attributable to the change
99
+
100
+ Fix what you find, recapture, then report.
101
+
102
+ ## 7. Clean up
103
+
104
+ Stop the dev server (`pkill -f "<dev command>"` or kill the PID you started) and delete the throwaway script. Leave no running processes behind.
@@ -0,0 +1 @@
1
+ blank_issues_enabled: true
@@ -0,0 +1,15 @@
1
+ name: Technical task
2
+ description: Refactoring, tooling, infrastructure or other work without a direct user-facing story.
3
+ labels: [technical]
4
+ body:
5
+ - type: textarea
6
+ id: goal
7
+ attributes:
8
+ label: Goal
9
+ description: What should be true when this is done, and who benefits?
10
+ validations:
11
+ required: true
12
+ - type: textarea
13
+ id: notes
14
+ attributes:
15
+ label: Notes, constraints, links
@@ -0,0 +1,15 @@
1
+ name: User need
2
+ description: Something a user needs. The planner agent turns it into a user story and plan.
3
+ body:
4
+ - type: textarea
5
+ id: need
6
+ attributes:
7
+ label: Who needs what, and why?
8
+ description: Describe the user, what they are trying to do, and what gets in the way today. Don't prescribe the solution.
9
+ placeholder: As a returning customer I lose my cart when I switch devices, so I give up…
10
+ validations:
11
+ required: true
12
+ - type: textarea
13
+ id: notes
14
+ attributes:
15
+ label: Notes, constraints, links