From bcdda71b60ae72405c41003b028594643fd652ba Mon Sep 17 00:00:00 2001 From: Edwin Monk-Fromont Date: Mon, 6 Jul 2026 04:20:12 +0000 Subject: [PATCH] Pre-PR commit --- .agents/docs/card-context.md | 28 +++ .agents/docs/spec-format.md | 112 ++++++++++ .agents/docs/working-doc-format.md | 36 ++++ .agents/skills/acceptance-audit/SKILL.md | 22 ++ .agents/skills/ascii-design/SKILL.md | 17 ++ .agents/skills/automate-test-cases/SKILL.md | 25 +++ .agents/skills/bug-review/SKILL.md | 22 ++ .agents/skills/cherry-pick-changes/SKILL.md | 23 ++ .agents/skills/design-audit/SKILL.md | 33 +++ .agents/skills/draft-spec-changes/SKILL.md | 28 +++ .agents/skills/draft-test-cases/SKILL.md | 26 +++ .agents/skills/git-pull/SKILL.md | 18 ++ .agents/skills/git-update/SKILL.md | 20 ++ .agents/skills/handoff/SKILL.md | 60 ++++++ .agents/skills/implement-this/SKILL.md | 56 +++++ .agents/skills/interview/SKILL.md | 34 +++ .agents/skills/investigate-and-fix/SKILL.md | 25 +++ .agents/skills/mock-this-up/SKILL.md | 28 +++ .agents/skills/plan-cards/SKILL.md | 44 ++++ .agents/skills/plan-implementation/SKILL.md | 25 +++ .../skills/pull-workhorse-updates/SKILL.md | 51 +++++ .agents/skills/security-audit/SKILL.md | 16 ++ .agents/skills/spec-review/SKILL.md | 26 +++ .agents/skills/split-working-doc/SKILL.md | 28 +++ .agents/skills/start-working-doc/SKILL.md | 22 ++ .agents/skills/tech-design/SKILL.md | 28 +++ .agents/skills/workshop/SKILL.md | 26 +++ .claude/.gitignore | 1 + .claude/skills | 1 + .workhorse/design/README.md | 31 +++ .workhorse/design/components.md | 197 ++++++++++++++++++ .workhorse/design/design-system.md | 189 +++++++++++++++++ .workhorse/design/views.md | 67 ++++++ .workhorse/plans/a1/plan.md | 37 ++++ AGENTS.md | 14 ++ 35 files changed, 1416 insertions(+) create mode 100644 .agents/docs/card-context.md create mode 100644 .agents/docs/spec-format.md create mode 100644 .agents/docs/working-doc-format.md create mode 100644 .agents/skills/acceptance-audit/SKILL.md create mode 100644 .agents/skills/ascii-design/SKILL.md create mode 100644 .agents/skills/automate-test-cases/SKILL.md create mode 100644 .agents/skills/bug-review/SKILL.md create mode 100644 .agents/skills/cherry-pick-changes/SKILL.md create mode 100644 .agents/skills/design-audit/SKILL.md create mode 100644 .agents/skills/draft-spec-changes/SKILL.md create mode 100644 .agents/skills/draft-test-cases/SKILL.md create mode 100644 .agents/skills/git-pull/SKILL.md create mode 100644 .agents/skills/git-update/SKILL.md create mode 100644 .agents/skills/handoff/SKILL.md create mode 100644 .agents/skills/implement-this/SKILL.md create mode 100644 .agents/skills/interview/SKILL.md create mode 100644 .agents/skills/investigate-and-fix/SKILL.md create mode 100644 .agents/skills/mock-this-up/SKILL.md create mode 100644 .agents/skills/plan-cards/SKILL.md create mode 100644 .agents/skills/plan-implementation/SKILL.md create mode 100644 .agents/skills/pull-workhorse-updates/SKILL.md create mode 100644 .agents/skills/security-audit/SKILL.md create mode 100644 .agents/skills/spec-review/SKILL.md create mode 100644 .agents/skills/split-working-doc/SKILL.md create mode 100644 .agents/skills/start-working-doc/SKILL.md create mode 100644 .agents/skills/tech-design/SKILL.md create mode 100644 .agents/skills/workshop/SKILL.md create mode 100644 .claude/.gitignore create mode 120000 .claude/skills create mode 100644 .workhorse/design/README.md create mode 100644 .workhorse/design/components.md create mode 100644 .workhorse/design/design-system.md create mode 100644 .workhorse/design/views.md create mode 100644 .workhorse/plans/a1/plan.md diff --git a/.agents/docs/card-context.md b/.agents/docs/card-context.md new file mode 100644 index 0000000..f6925a8 --- /dev/null +++ b/.agents/docs/card-context.md @@ -0,0 +1,28 @@ +--- +workhorse-version: 0.1.0 +--- + +# Establishing card context outside Workhorse + +Skills are discovered natively by Claude Code, so they can be invoked in an external tool with no Workhorse session around them. Inside Workhorse the system prompt injects the card's context — its title, identifier, and description. Outside it, that context is absent, and a skill that needs to know which card it is working on has to establish that context before doing its work. + +Follow this process whenever a skill directs you here. + +## When this applies + +- Apply it only when you do **not** already have the card's context — no title, identifier, or description available to you. This is the case when you are running outside Workhorse +- Inside Workhorse the card's context is always present, so this process never runs there +- If you already established the card's context earlier in this conversation, reuse it — do not ask again + +## Establishing context + +When you have no card context, ask the user to establish it before you start the skill's work. Offer two paths: + +1. **Linear card** — the user gives you a Linear card code and connects the Linear MCP, so you can read the card directly. Read whatever detail helps the task at hand — at minimum the card's title and description. If the Linear MCP is not connected, walk the user through connecting it +2. **Paste** — the user pastes the card's title and description directly into the chat + +Also ask the user for the card's **identifier**. It is used for the file paths of mockups (`.workhorse/design/mockups/{card-id}/`), plans (`.workhorse/plans/{card-id}/`), and test cases (`.workhorse/test-cases/{card-id}/`). Every card has one — a Linear card code supplies it directly. If no Linear or Workhorse ticket backs the work, ask the user to create one so the work is tracked; you can offer to create it for them through the Linear MCP. + +## When context is incomplete + +If the user cannot or will not supply full context, do the best you can with what is available — ask them for whatever detail they can provide to work from, and proceed on that. Don't block on missing context you can reasonably work around. diff --git a/.agents/docs/spec-format.md b/.agents/docs/spec-format.md new file mode 100644 index 0000000..253077c --- /dev/null +++ b/.agents/docs/spec-format.md @@ -0,0 +1,112 @@ +--- +workhorse-version: 0.1.0 +--- + +# Spec format and information architecture + +Specs are the product-level source of truth for a workspace. The format serves three audiences: product owners and testers authoring them (via interview or direct edit), developers and AI agents implementing from them, and anyone browsing them as a knowledge base. + +## Information hierarchy + +Specs live in `.workhorse/specs/` as markdown files organised into directories. The directory structure is the hierarchy: **Product > Area > Subarea > ... > Spec**, with arbitrary nesting depth. + +``` +.workhorse/specs/ +├── patient/ +│ ├── registration.md +│ ├── allergies.md +│ ├── merge/ +│ │ ├── overview.md +│ │ ├── field-resolution.md +│ │ └── conflict-handling.md +│ └── referrals.md +├── scheduling/ +│ ├── appointments.md +│ └── recurring-appointments.md +└── labs/ + ├── requests.md + └── results.md +``` + +Areas appear as they're needed — there's no predefined list. When drafting a new spec, the agent picks an area consistent with the existing structure. The spec explorer reads this structure from the main branch to build the navigable reference view. + +## File format + +Each spec is a markdown file with a single-line YAML frontmatter block and a structured body: + +```markdown +--- +id: ALG +--- + +# Patient allergies + +Summary paragraph describing what this spec covers. + +## Section heading + +- [ ] Acceptance criterion one +- [ ] Acceptance criterion two +``` + +The frontmatter carries exactly one field: + +- `id` — a short, stable identifier for the spec, used for code-to-spec traceability (see [Spec IDs and code references](#spec-ids-and-code-references)) + +Nothing else goes in the frontmatter. The title comes from the H1. The area comes from the directory. The originating card isn't recorded on the spec — it's available via git history and doesn't stay tied to the spec after the card closes. + +Body structure: + +- **Title** — a single `#` H1 at the top, human-readable (e.g. "Patient allergies") +- **Summary** — one or two plain paragraphs below the title, no heading +- **Sections** — `##` headings group related criteria +- **Acceptance criteria** — markdown checkbox items (`- [ ]`) + +## Spec IDs and code references + +The `id` in frontmatter is a short, stable handle. It lets code reference the spec it implements through inline comments, and survives the spec being renamed or moved. + +- IDs are 2–6 character alphanumeric codes, uppercase, chosen when the spec is first created (e.g. `ALG`, `AUTH`, `LAB1`). Use something memorable rather than sequential numbering +- IDs are unique within a workspace. Workhorse checks for collisions on creation +- Once assigned, an ID never changes. The filename or location can change freely — code references keep working +- Code references an implementing spec with an inline comment of the form `// spec: ALG`. For a specific section within the spec, append a kebab-case slug of the heading text: `// spec: ALG#conflict-handling` +- A single piece of code can reference multiple specs with multiple comments — don't try to combine them + +Code references are advisory, not load-bearing. They help a reader jump from an implementation detail to the product rule it answers to. Missing references are not a bug. + +## Writing conventions + +- **Describe the system as it should be, not the changes to make.** Each spec is a coherent snapshot — it reads as "this is how the system works" rather than "change X to Y" or "no longer does Z". No references to "current behaviour", "remains unchanged", "now does", or "rather than the old way". The implementation agent works from the diff to know what's changing. +- **Acceptance criteria are facts about behaviour, not instructions to a developer.** +- **Grade implementation detail by whether it constrains behaviour that must be preserved.** Product-owner-level language is the default: write "the system checks whether all parent cards have been committed" rather than naming the field that tracks commit state, and "Spec complete" rather than an all-caps status constant. But a technical choice belongs in the spec when the choice *is* the requirement — when a reimplementation should be held to it rather than free to pick its own approach. The decision test is: **"Would someone reimplementing this from scratch need to be constrained back to this technical choice?"** If yes, name the detail; the spec is where that constraint is recorded. If no, describe the behaviour and let the implementation choose its tools. + - **Keep the detail** when it is load-bearing. A sync engine that heals divergence by replaying from a known-good checkpoint must preserve that mechanism, so the spec names it — a different healing strategy would be a different product. Backend and platform specs often carry this kind of detail: data-integrity rules, concurrency and ordering guarantees, wire and storage formats, migration and healing strategies. + - **Leave it out** when the detail is one acceptable way among several to build the same behaviour. Choosing React hooks to manage state in a frontend workflow is an implementation choice — the user-visible behaviour is the requirement, so specify that and let the build pick its tools. Product-facing, CRUD, and frontend specs stay behavioural. + - File paths inside `.workhorse/specs/` are always acceptable because they're part of the product's information architecture. +- **Stay within the spec's scope.** Each spec contains only sections that relate directly to its title and area. If content would make more sense in another spec, it belongs there — add a cross-reference (e.g. "see `editor/spec-editor.md`") rather than duplicating or misplacing it. When in doubt, ask: "would someone looking for this information expect to find it in a spec with this title?" +- **Don't specify absences.** Document what the system does, not what it doesn't do. "We don't support X" or "X is not included" is not useful — if it's not in the spec, it's not in the system. If another spec needs updating because this feature changes its behaviour, update that spec declaratively. +- **No point-in-time language.** Don't document transitions ("we used to do X, now we do Y", "this replaces Z"). Each spec is a snapshot of the desired system, not a changelog. +- **No stacking adjectives.** Don't describe behaviour with chains of near-synonyms ("seamless, invisible, frictionless"). Use one precise word or describe the concrete behaviour. +- **No exact measurements in prose.** Pixel widths, animation durations, and precise benchmarks belong in mockups or the design system, not in acceptance criteria. Describe the intent ("compact", "fast enough to feel instant") rather than the number. +- **Open questions must be resolved before a spec is considered done.** A spec with open questions is a draft. Nail them down with the user before committing. +- **Australian/NZ English spelling** (colour, organisation, finalise). + +## When a change warrants a spec update + +Specs describe product behaviour, so spec edits accompany changes that change product behaviour. + +- Product-behaviour changes — new features, removed behaviour, changed flows, revised edge-case handling — require spec edits +- Bug fixes and implementation-detail changes do not require spec edits, unless the bug existed because the spec was unclear, incorrect, or missing. In that case, update the spec first so it reflects the intended behaviour, then fix the code to match +- Refactors and cleanups that leave product behaviour unchanged do not touch specs + +## When to edit, fold, create, or split + +Default to editing the spec that already covers the concept. A new spec file appears only when the content cannot plausibly live as a section or set of criteria inside any existing spec in the same area. + +- **Fold into an existing spec** when the change is a section, criterion, or refinement on a concept the spec already covers. Most spec changes are folds +- **Create a new sibling spec** when the content is a distinct concept within an existing area but does not belong in any current file there +- **Split an existing spec** when it has grown long **and** contains one or more conceptually distinct sub-areas that could each stand alone + +When splitting, the parent topic becomes a folder and the sub-topics become files within it: + +- Add an `overview.md` when the folder has cross-cutting content (shared terminology, relationships between sub-specs, invariants that apply to all children), or when the folder has more than three siblings and a reader needs orientation +- Skip `overview.md` when two or three well-named siblings speak for themselves diff --git a/.agents/docs/working-doc-format.md b/.agents/docs/working-doc-format.md new file mode 100644 index 0000000..c5c583b --- /dev/null +++ b/.agents/docs/working-doc-format.md @@ -0,0 +1,36 @@ +# Working doc format + +A working doc is a per-card drafting space where spec-level and implementation thinking co-exist before the card is split into its long-lived artefacts (specs, plan, test cases). This doc defines its shape and voice. The artefact itself is specified in `.workhorse/specs/working-doc/overview.md`. + +## When to use one + +A working doc suits larger, epic-level cards where the shape of the work is still being found and behaviour and implementation need developing side by side. Most cards don't need one — for those, interview straight into specs and let Tech design write to the plan as usual. + +## Voice + +Unlike a spec, a working doc is written in working voice: + +- Open questions are welcome — track them explicitly as you go +- Point-in-time reasoning is welcome ("we considered X but…") +- Implementation detail, options, and trade-offs sit alongside behaviour +- Nothing here has to be a clean declarative snapshot; that transformation happens at the split + +## Conventional shape + +The file starts minimal — frontmatter (`status: draft`), an H1 title, an overview line. Build the body up under these conventional sections as material accrues. Use only the sections a card needs, and add others when they help. + +- **Behaviour** — what the system should do, at spec level: happy paths, edge cases, interactions. This is the material the split rewrites into specs +- **Implementation options** — approaches under consideration, with their shape and cost +- **Open questions** — unresolved decisions, tracked as a checklist so they're easy to see and close off +- **Trade-offs** — the reasoning behind choices, including rejected options and why +- **Testing notes** — scenarios worth verifying, which the split lifts into test cases + +## Splitting + +When the shape is clear, Split working doc fans the material out: + +- Behaviour → the card's specs, rewritten into declarative spec voice per `.agents/docs/spec-format.md` +- Implementation options and trade-offs → the plan +- Testing notes → the test cases + +Resolve open questions before splitting where you can — specs can't carry them. Split working doc warns before proceeding if any remain, and reminds you which still need follow-up afterwards. diff --git a/.agents/skills/acceptance-audit/SKILL.md b/.agents/skills/acceptance-audit/SKILL.md new file mode 100644 index 0000000..7550ff6 --- /dev/null +++ b/.agents/skills/acceptance-audit/SKILL.md @@ -0,0 +1,22 @@ +--- +name: acceptance-audit +description: "Check whether this card's code meets the acceptance criteria" +label: "Acceptance audit" +pill-order: + implementing: 4 + reviewing: 4 + complete: 3 +workhorse-version: 0.1.0 +--- + +## Your task: Acceptance audit + +Check whether the code on this card's branch meets the acceptance criteria. This is a compliance check against the specs, not a general code-quality review. + +1. Identify what this card was supposed to do: diff the spec changes on this branch against the upstream base (scoped to `.workhorse/specs/`) to see the card's own additions and edits. Also read the surrounding specs in the same area(s) — they describe existing behaviour that must still be met and not regressed +2. Diff this card's branch against its upstream base to see the implementation (a card's base is usually `main`, but may be a parent card's branch) +3. Walk the criteria one by one — both the card's new/changed criteria and the surrounding ones that should still hold. Does the code deliver each one? Has any existing behaviour regressed? +4. Flag criteria that are not yet implemented, partially implemented, or implemented incorrectly — and flag regressions separately +5. Flag any behaviour in the code that isn't covered by a criterion — that's either missing from the spec, or shouldn't be in the code + +Post findings grouped by spec, each finding tied to a specific criterion with file and line references. diff --git a/.agents/skills/ascii-design/SKILL.md b/.agents/skills/ascii-design/SKILL.md new file mode 100644 index 0000000..2a296c0 --- /dev/null +++ b/.agents/skills/ascii-design/SKILL.md @@ -0,0 +1,17 @@ +--- +name: ascii-design +description: "Run a quick UX/UI workshop using ASCII-art sketches" +label: "ASCII design chat" +pill-order: + not-started: 5 + specifying: 11 +workhorse-version: 0.1.0 +--- + +## Your task: ASCII design chat + +If you don't already have this card's context (title, identifier, description) — for instance when running outside Workhorse — establish it first by following `.agents/docs/card-context.md`. + +A lightweight UX/UI workshop. Sketch the screen's skeleton as ASCII art directly in chat, get feedback, and iterate. Keep it fast and rough — the goal is to agree on shape and hierarchy before committing to HTML mockups. + +Once the skeleton is agreed, suggest moving to an HTML mockup as the next step. diff --git a/.agents/skills/automate-test-cases/SKILL.md b/.agents/skills/automate-test-cases/SKILL.md new file mode 100644 index 0000000..03f10e5 --- /dev/null +++ b/.agents/skills/automate-test-cases/SKILL.md @@ -0,0 +1,25 @@ +--- +name: automate-test-cases +description: "Write automated tests for unticked scenarios in this card's test cases" +label: "Automate test cases" +pill-order: + implementing: 6 + reviewing: 5 +jockey-hint: "Surface once the card has a test-cases file with unticked scenarios and implementation is underway. Demote once all scenarios are ticked." +workhorse-version: 0.1.0 +--- + +## Your task: Automate test cases + +If you don't already have this card's context (title, identifier, description) — for instance when running outside Workhorse — establish it first by following `.agents/docs/card-context.md`. + +Write automated tests that match the unticked scenarios in this card's test-cases file, ticking each item as its matching test lands. + +1. Read the test-cases file at `.workhorse/test-cases/{card-id}/`. If no file exists, stop and ask the user whether to run `Draft test cases` first +2. For each unticked scenario, locate the right place to put its automated test — follow the target repo's existing test conventions (framework, file layout, fixtures) +3. Write the test so it exercises the scenario as stated. If the scenario cites a spec id, the test is the automation of that acceptance criterion — match its intent +4. Tick the scenario (`- [ ]` → `- [x]`) once its test is written and passing locally. Update the test-cases file in place +5. If a scenario is genuinely not automatable (manual feel, cross-browser visual), leave it unticked and note in the file why it's manual-only +6. Summarise what you automated, which scenarios remain manual, and any scenarios you couldn't make sense of + +See `.workhorse/specs/test-cases/overview.md` for the file's shape. diff --git a/.agents/skills/bug-review/SKILL.md b/.agents/skills/bug-review/SKILL.md new file mode 100644 index 0000000..f67beef --- /dev/null +++ b/.agents/skills/bug-review/SKILL.md @@ -0,0 +1,22 @@ +--- +name: bug-review +description: "Review code changes on this card for likely bugs, regressions, and missed edges" +label: "Bug review" +pill-order: + implementing: 2 + reviewing: 1 + complete: 1 +workhorse-version: 0.1.0 +--- + +## Your task: Bug review + +Review the code changes on this card's branch for likely bugs, regressions, and missed edges. + +1. Diff this card's branch against its upstream base to see what's changed (a card's base is usually `main`, but may be a parent card's branch) +2. Read the specs to understand the intended behaviour +3. Inspect the diff for anything that looks wrong — use your judgement about what matters for this code +4. Post findings grouped by severity: real bugs first, then smells or likely issues, then nitpicks +5. For each finding, reference the file and a short excerpt so the user can locate it + +Be specific and actionable. Don't flag stylistic preferences as bugs. diff --git a/.agents/skills/cherry-pick-changes/SKILL.md b/.agents/skills/cherry-pick-changes/SKILL.md new file mode 100644 index 0000000..eab7080 --- /dev/null +++ b/.agents/skills/cherry-pick-changes/SKILL.md @@ -0,0 +1,23 @@ +--- +name: cherry-pick-changes +description: "Cherry-pick post-merge commits onto a new follow-up branch" +label: "Cherry-pick changes" +workhorse-version: 0.1.0 +--- + +## Your task: Cherry-pick post-merge changes + +The card just created a follow-up PR on a fresh branch from main. Your job is to cherry-pick the post-merge commits from the previous branch onto this new branch. + +The user message contains the previous branch name and the commit SHAs to cherry-pick. + +1. Cherry-pick each commit in order using `git cherry-pick ` +2. If a cherry-pick applies cleanly, move to the next one +3. If a cherry-pick encounters conflicts: + - Examine the conflict markers to understand what diverged + - Use the card's specs, description, and conversation history to make informed resolution decisions + - Edit the conflicted files to resolve them + - `git add` the resolved files + - `git cherry-pick --continue` to proceed +4. After all commits are applied, push the branch with `git push origin ` +5. Report what you cherry-picked, any conflicts you encountered, and how you resolved them diff --git a/.agents/skills/design-audit/SKILL.md b/.agents/skills/design-audit/SKILL.md new file mode 100644 index 0000000..d468670 --- /dev/null +++ b/.agents/skills/design-audit/SKILL.md @@ -0,0 +1,33 @@ +--- +name: design-audit +description: "Audit this card's mockups or implementation against the design library" +label: "Design audit" +pill-order: + specifying: 6 + implementing: 3 + reviewing: 3 + complete: 2 +workhorse-version: 0.1.0 +--- + +## Your task: Design audit + +Audit this card's design work against `.workhorse/design/` — the source of truth for the project's design direction. + +### What to audit + +Work out what stage the card is at and audit accordingly: + +- **Mockups only** (specifying phase — this card has mockups but no UI code) — audit the HTML mockups in `.workhorse/design/mockups/{card-id}/` +- **Implementation** (implementing or reviewing phase — this card has UI code changes) — audit the shipped code on the card's branch +- **Both** — audit both, and flag any places where the implementation drifted from what the mockups showed + +### How to audit + +1. Read `.workhorse/design/design-system.md` and any other guidance under `.workhorse/design/` (components, philosophy notes) +2. Review against both the high-level principles and the pixel-level detail — use your judgement about what matters for this card +3. Where `.workhorse/design/` disagrees with what's shipped elsewhere in the existing codebase, `.workhorse/design/` wins — it represents the agreed current direction +4. **Flag unchanged aspects that have drifted.** A mockup or implementation should only change the styling and layout of the feature or tweak the card is about — surrounding regions should match the current implementation. Call out any place where unchanged regions have been re-styled or re-imagined, or where stale styling from older mockups (on other cards) has leaked in. See "Preserving unchanged aspects" in your system prompt +5. Do not reference mockups from other cards as inspiration or comparison — each card's mockups are point-in-time artefacts, not canonical components + +Post findings as specific, actionable items. Reference the exact design-system rule each finding relates to. diff --git a/.agents/skills/draft-spec-changes/SKILL.md b/.agents/skills/draft-spec-changes/SKILL.md new file mode 100644 index 0000000..c2c5f2f --- /dev/null +++ b/.agents/skills/draft-spec-changes/SKILL.md @@ -0,0 +1,28 @@ +--- +name: draft-spec-changes +description: "Draft edits to existing specs (or a new spec if no existing one fits) from the card description" +label: "Draft spec changes" +pill-order: + not-started: 3 + specifying: 2 +jockey-hint: "Demote once spec drafts have already been produced in this conversation, unless the user signals they want another pass or the scope has materially shifted." +workhorse-version: 0.1.0 +--- + +## Your task: Draft spec changes + +If you don't already have this card's context (title, identifier, description) — for instance when running outside Workhorse — establish it first by following `.agents/docs/card-context.md`. + +Produce spec edits directly from the card description — no extended interview. + +**Read `.agents/docs/spec-format.md` first.** It defines the writing conventions, the information-architecture rules, and the fold-vs-create-vs-split guidance you must follow. Every edit you make has to conform to it. + +1. Read the card title and description carefully. +2. Read existing specs in `.workhorse/specs/` to understand the area structure. +3. **Default to editing existing specs.** Most spec work is a fold — a new section, criterion, or refinement on a spec that already covers the concept. Only create a new spec file when the content cannot plausibly live in any existing spec in the same area. +4. Edit spec files in place, or write new ones at `.workhorse/specs/{area}/{slug}.md` if genuinely needed. +5. Include a brief summary of what you changed and any open questions you identified. + +Do NOT start by asking questions or exploring the codebase. Go straight to drafting. If the description is too thin for meaningful acceptance criteria, write what you can and list the gaps as open questions. + +**Generate mockups** for any UI-facing specs as part of the draft. Before writing mockup HTML, follow the Design sourcing process from your system prompt: read the section's actual implementation first, then similar components, then cross-check against `.workhorse/design/`. Do not skip this reading pass. diff --git a/.agents/skills/draft-test-cases/SKILL.md b/.agents/skills/draft-test-cases/SKILL.md new file mode 100644 index 0000000..1c1cb0c --- /dev/null +++ b/.agents/skills/draft-test-cases/SKILL.md @@ -0,0 +1,26 @@ +--- +name: draft-test-cases +description: "Draft or refine the test-cases checklist for this card" +label: "Draft test cases" +pill-order: + specifying: 9 + implementing: 5 +jockey-hint: "Surface when the card has specs but no test cases yet, or when the user wants to refresh the scenario list. Demote once a healthy test-cases file exists unless the user signals a fresh area to cover." +workhorse-version: 0.1.0 +--- + +## Your task: Draft test cases + +If you don't already have this card's context (title, identifier, description) — for instance when running outside Workhorse — establish it first by following `.agents/docs/card-context.md`. + +Produce or refine the card's test-cases checklist — the concrete scenarios that verify this card is done. The file is read by both the tester running scenarios by hand and the implementing agent writing automated tests against them. + +1. Read the card's specs in `.workhorse/specs/` and any existing test cases at `.workhorse/test-cases/{card-id}/` +2. Skim the target repo to ground the scenarios in the actual surfaces involved +3. If a test-cases file already exists, edit it in place — add, refine, or reorder scenarios. Don't replace work that still applies +4. If none exists, create one at `.workhorse/test-cases/{card-id}/overview.md` with an H1 title, an optional summary, and one or more checklist sections +5. Write each scenario as one concrete verifiable step in operational voice — a thing to do and the observable outcome. Avoid vague items like "test the feature" +6. Cite the spec id (e.g. "verifies spec: ALG") on scenarios that directly exercise an acceptance criterion. Scenarios without a citation are valid for operational concerns (smoke checks, cross-browser, manual feel) +7. Ask only the clarifying questions you genuinely need — one or two turns at most, not an extended interview + +See `.workhorse/specs/test-cases/overview.md` for the file's shape. diff --git a/.agents/skills/git-pull/SKILL.md b/.agents/skills/git-pull/SKILL.md new file mode 100644 index 0000000..3edc57d --- /dev/null +++ b/.agents/skills/git-pull/SKILL.md @@ -0,0 +1,18 @@ +--- +name: git-pull +description: "Pull remote changes and reconcile with local work, checking for soft conflicts" +label: "Pull" +workhorse-version: 0.1.0 +--- + +## Your task: Pull remote changes + +Pull the latest remote changes into the card's branch and reconcile them with local work. + +1. Run `git pull` to fetch and integrate remote changes +2. If a hard conflict occurs, resolve it using the card's specs, description, and conversation history to make informed decisions +3. **Always check for soft conflicts** — even if git merged cleanly, inspect the incoming changes against local specs and code for assumptions that have been invalidated by the remote changes. Use your judgement about what matters +4. Report what changed. If soft conflicts exist, explain each one: what the local assumption was, what the remote change did, and how you resolved it (or ask the user if ambiguous) +5. Apply straightforward resolutions directly. Ask the user about ambiguous ones. + +When local changes are small, the soft-conflict check can be brief. When local changes are large, examine thoroughly. diff --git a/.agents/skills/git-update/SKILL.md b/.agents/skills/git-update/SKILL.md new file mode 100644 index 0000000..d61a66d --- /dev/null +++ b/.agents/skills/git-update/SKILL.md @@ -0,0 +1,20 @@ +--- +name: git-update +description: "Rebase onto latest upstream, checking for soft conflicts" +label: "Update" +workhorse-version: 0.1.0 +--- + +## Your task: Update branch from upstream + +Rebase this card's branch onto its upstream. The upstream is the parent branch this card was based on — usually `main`, but cards that depend on a parent card rebase onto the parent's branch instead. Determine the actual branch names from `git rev-parse --abbrev-ref HEAD` (the card branch) and `git rev-parse --abbrev-ref @{upstream}` (the base). Use those exact refs, not the workspace default. + +1. Run `git fetch origin` to refresh remote refs, then verify the fetch updated the upstream by comparing `git rev-parse origin/` before and after — if the SHA didn't change but `git ls-remote origin ` reports a different SHA, abort and report the discrepancy rather than rebasing onto stale state +2. Run `git rebase origin/` to rebase onto the upstream +3. If a hard conflict occurs during rebase, resolve it step by step. Use the card's specs, description, and conversation history to decide which side to favour +4. **Always check for soft conflicts** — even if the rebase completed cleanly, inspect the full diff between the old and new base against local specs and code for assumptions invalidated by upstream changes. Use your judgement about what matters +5. After the rebase succeeds, force-push with `git push --force-with-lease origin ` so the remote reflects the rebased history +6. Report what upstream changes came in. If soft conflicts exist, explain each one: what the local assumption was, what upstream changed, and how you resolved it (or ask the user if ambiguous) +7. Apply straightforward resolutions directly. Ask the user about ambiguous ones. + +When local changes are small, the soft-conflict check can be brief. When local changes are large, examine thoroughly. diff --git a/.agents/skills/handoff/SKILL.md b/.agents/skills/handoff/SKILL.md new file mode 100644 index 0000000..3f7a1b8 --- /dev/null +++ b/.agents/skills/handoff/SKILL.md @@ -0,0 +1,60 @@ +--- +name: handoff +description: "Generate a context-rich briefing prompt for an external agent (Claude Code, Cursor, etc.)" +label: "Handoff" +pill-order: + not-started: 7 + specifying: 5 + implementing: 6 + reviewing: 6 +workhorse-version: 0.1.0 +--- + +## Your task: Hand off to an external agent + +The user wants to hand off work on this card to an external agent (Claude Code, Cursor, or another AI tool). Generate the briefing prompt in one pass — do not ask the user to confirm focus first. + +### What to do + +1. **Infer a focus** from the card's current state and conversation history. For example: + - Specs are drafted and no code yet → focus is "begin implementation" + - Implementation is in progress → focus is "continue the implementation" + - There are CI failures or known bugs → focus is "fix the build failures" or "investigate the reported bug" +2. **Compose the full briefing** following the structure below. Write it as instructions addressed to the external agent ("You are picking up work on..."). +3. **Deliver it based on length.** The UI renders ```handoff blocks with an **Open in Claude Code** button that launches a local Claude Code terminal session with the block's contents pre-filled (via a `claude-cli://` deep link), alongside the standard copy button. The deep link URL-encodes the block and is capped near 4500 encoded characters, so a full briefing routinely overflows it and disables the button. To avoid that: + - **If the full briefing is 1000 characters or fewer**, return it inline in a single fenced code block tagged ```handoff. This is the common, short case. + - **If the full briefing exceeds 1000 characters**, do not inline it. Instead: + - Write the full briefing to `.workhorse/handoffs/{card-id}/handoff.md` (create the folder if it doesn't exist). Workhorse commits and pushes this file with the card's branch at the end of your turn — you do not commit it yourself. + - Return a short **pointer prompt** in a single fenced code block tagged ```handoff. The pointer names the card, tells the external agent to fetch `` and **check it out in a git worktree** (e.g. `git fetch origin` then `git worktree add ../-{card-id} `) rather than switching branches in the user's working tree, **pulling the latest so the committed `handoff.md` is present** (an existing local branch or worktree may be stale), and directs it to read `.workhorse/handoffs/{card-id}/handoff.md` for its full briefing and follow it. Keep the pointer well under 1000 characters so the deep link always fits. + - **Critical: whatever you put in the ```handoff block must be a single fenced block with no fenced code blocks (triple backticks) inside it** — nested fences break the outer block and disable both the button and copy. Use inline code with single backticks for paths, commands, and identifiers. The `handoff.md` file itself is exempt: it is a real file, not embedded in a fence, so it may contain fenced code blocks freely. + - Whether inline or in `handoff.md`, teach the agent how to find information (read the specs, diff the branch) rather than inlining large file contents. +4. **Immediately after the code block**, add a short line naming the focus you inferred and inviting the user to redirect — e.g. "This is for starting implementation of the allergies spec. Let me know if you want it for something else." When you moved the briefing into `handoff.md`, say so in that line. + +### Briefing prompt structure + +Whether delivered inline or written to `handoff.md`, the briefing contains these sections, in order: + +**1. Workhorse context** — explain the spec-driven workflow: +- Specs live in `.workhorse/specs/` as structured markdown with YAML frontmatter and checkbox acceptance criteria +- Describe the system as it should be (not changes to make). Acceptance criteria are facts about behaviour. Include implementation detail only where a reimplementation should be constrained back to that technical choice (e.g. a backend sync healing strategy); keep product-facing and frontend criteria behavioural +- Mockups live in `.workhorse/design/mockups/{card-id}/` as standalone HTML with inline CSS +- Design system is at `.workhorse/design/design-system.md` +- The card's implementation plan lives at `.workhorse/plans/{card-id}/` — a free-form markdown working document with tech design notes and/or a checklist of build steps. Read it first if it exists, tick items (`- [ ]` → `- [x]`) as work completes, and expand steps into sub-items if they turn out larger than anticipated +- Australian/NZ English spelling + +**2. Card context** — the card title, identifier, and description (when present) + +**3. Branch instructions** — tell the agent to check the card's branch out in a **git worktree** (e.g. `git fetch origin` then `git worktree add ../-{card-id} `) rather than switching branches in place, so the user's working tree is left undisturbed, and to diff the branch against the upstream base branch to understand what specs and mockups have been added or changed + +**4. Journal summary** — summarise what has happened so far on this card based on the conversation history (what was discussed, what decisions were made, what work was done) + +**5. Conversation context** — compress the key points from the conversation: decisions made, open threads, areas explored, any unresolved questions. This gives the external agent continuity + +**6. Focus instructions** — what the external agent should do, based on the focus you inferred + +### Guidelines + +- The prompt should be self-contained — the external agent should not need to ask the user for context +- Teach the agent how to find information (read the specs, diff the branch) rather than inlining all file contents +- Keep it concise but complete — aim for a prompt that gets the external agent productive immediately +- Write it as instructions addressed to the external agent ("You are picking up work on...") diff --git a/.agents/skills/implement-this/SKILL.md b/.agents/skills/implement-this/SKILL.md new file mode 100644 index 0000000..c386e92 --- /dev/null +++ b/.agents/skills/implement-this/SKILL.md @@ -0,0 +1,56 @@ +--- +name: implement-this +description: "Implement this card" +label: "Implement this" +pill-order: + not-started: 2 + specifying: 4 + implementing: 1 + reviewing: 2 +jockey-hint: "Demote once implementation has begun on this card — the user typically doesn't want to restart from scratch. Leave high when the card is still in specifying phase, or when the user explicitly asks to resume or redo." +workhorse-version: 0.1.0 +--- + +## Your task: Implement this + +If you don't already have this card's context (title, identifier, description) — for instance when running outside Workhorse — establish it first by following `.agents/docs/card-context.md`. + +Implement the work described by this card. The starting point varies — figure out which one applies before writing code. + +### Work out what you're implementing + +1. **Is there a pending spec change on this branch?** Diff this card's branch against its upstream base (a card's base is usually `main`, but may be a parent card's branch — check `git rev-parse --abbrev-ref @{upstream}` or the branch's merge-base), scoped to `.workhorse/specs/` and `.workhorse/design/mockups/`. If there are spec or mockup changes, that diff is the source of truth for what you're building — new/changed criteria describe the work +2. **Otherwise, lead with the card description.** Read the title and description carefully — that's what the user wants. Read relevant existing specs in `.workhorse/specs/` for context: how the surrounding behaviour is supposed to work, what conventions and edge cases already exist. Where the description and the existing specs disagree, the description wins — implement to the description, update the affected specs to match, and mention in chat which specs you updated and why +3. **No spec at all?** Fall back to the card title, description, and any conversation context (e.g. a prior workshop or ASCII design chat). Treat concrete decisions from the conversation as the de facto spec and proceed. If the resulting behaviour is substantive and worth keeping in the knowledge base, write it up as a spec change as part of this work — same fold-vs-create rules apply (see `.agents/docs/spec-format.md`) + +### The plan + +This card may have a plan at `.workhorse/plans/{card-id}/` — a free-form markdown working document with tech design notes and/or a checklist of build steps (see `.workhorse/specs/plan/overview.md`). + +- **If a plan with a checklist exists**, work through the checklist in order and tick items off (`- [ ]` → `- [x]`) as you complete them. Expand a step into sub-items if it turns out larger than anticipated. Self-check against the plan as you go and note if the current work has drifted from what the plan says +- **If a plan exists but has notes only**, use the notes as context and draft the checklist yourself as you begin implementation +- **If no plan exists and the work looks multi-stage**, draft a plan at `.workhorse/plans/{card-id}/plan.md` before starting code work, then follow it +- **If the work is a single focused change**, you can skip the plan — proceed directly + +### Implementation + +- Follow the design system in `.workhorse/design/design-system.md` for any UI work +- Source visual language from the existing implementation first, then `.workhorse/design/` for current direction (`.workhorse/design/` wins on clash). Do not reference mockups from other cards unless the user explicitly asks +- **Preserve unchanged aspects.** Only change the markup and styling for the feature or tweak being implemented. Leave the rest of the screen as it is — same layout, components, copy, spacing, styling — even if you think you can improve it. See "Preserving unchanged aspects" in your system prompt +- Make the code match the acceptance criteria — each criterion should be traceable to code + +### Test cases + +The card may have a test-cases file at `.workhorse/test-cases/{card-id}/` — the checklist of scenarios that verify the card is done. Treat it as both a live specification of what to test and a running record of what's covered. + +- **If a test-cases file exists**, read it alongside the specs so you know what the scenarios are. As you write automated tests that exercise a scenario, tick that scenario off (`- [ ]` → `- [x]`) in the file +- **If no test-cases file exists** and the card has meaningful behaviour worth verifying, create one at `.workhorse/test-cases/{card-id}/overview.md` — an H1 title, optional summary, and checklist sections of concrete scenarios. Cite spec ids on scenarios that verify an acceptance criterion +- **As implementation surfaces new scenarios** (an edge case the specs didn't call out, a regression path worth locking in), append them to the test-cases file + +See `.workhorse/specs/test-cases/overview.md` for the file's shape. + +### Spec ambiguity + +If while implementing you find the spec is unclear, contradictory, or missing something you need, don't guess. Surface it in chat and propose a spec edit before continuing. Prefer editing the existing spec over creating a new one (see `.agents/docs/spec-format.md`). + +If there's no spec and the description/conversation is thin, say so and ask rather than inventing behaviour. diff --git a/.agents/skills/interview/SKILL.md b/.agents/skills/interview/SKILL.md new file mode 100644 index 0000000..57b87fd --- /dev/null +++ b/.agents/skills/interview/SKILL.md @@ -0,0 +1,34 @@ +--- +name: interview +description: "Interview me about this card to develop the acceptance criteria" +label: "Interview me" +pill-order: + not-started: 1 + specifying: 1 +jockey-hint: "Demote sharply once an interview has already happened — if the journal contains an interview entry, or if the recent conversation shows back-and-forth Q&A style exchange. Only re-suggest if the user explicitly asks for another round." +workhorse-version: 0.1.0 +--- + +## Your task: Interview me + +If you don't already have this card's context (title, identifier, description) — for instance when running outside Workhorse — establish it first by following `.agents/docs/card-context.md`. + +Guide the user through developing comprehensive acceptance criteria. Read `.agents/docs/spec-format.md` first so the questions you ask, and the criteria you extract, conform to the spec writing conventions and information-architecture rules. + +Methodology: + +1. **Understand the goal** — start with the high-level intent +2. **Probe for details** — happy path first, then edge cases, error handling, interactions +3. **Surface decisions** — identify ambiguity and ask the user to resolve it +4. **Track open questions** — maintain unresolved questions +5. **Extract acceptance criteria** — as the conversation progresses, extract concrete criteria +6. **Flow into writing** — as soon as enough detail exists in any area, start writing it up. Don't wait for a "ready" signal and don't announce completion; the interview and the write-up are a continuous activity. Keep interviewing on the areas that are still thin while writing up the areas that are solid + +**Where the write-up lands:** if a working doc exists for this card in `draft` status (`.workhorse/working-docs/{card-id}/working-doc.md`), write your findings into it — under the conventional sections in `.agents/docs/working-doc-format.md`, in working voice — rather than drafting specs directly. The working doc is the drafting home while the card is being shaped, and a later Split working doc turns it into specs. With no draft working doc, flow into drafting and editing the relevant spec files as normal. + +Ask focused questions — one or two at a time, not long lists. **Number your questions** (1., 2., etc.) so the user can reply by number. Example: + +1. Where can this action be triggered from — the board, the workspace, or both? +2. Should there be a confirmation step before it happens? + +**Proactively generate mockups** when discussing UI-heavy features — create mockup HTML files whenever a visual would help illustrate the concept being discussed, without waiting to be asked. Before writing any mockup HTML, follow the Design sourcing process from your system prompt: read the section's actual implementation first, then similar components, then cross-check against `.workhorse/design/`. Do not skip this reading pass just because you are mid-interview. diff --git a/.agents/skills/investigate-and-fix/SKILL.md b/.agents/skills/investigate-and-fix/SKILL.md new file mode 100644 index 0000000..d60e3e3 --- /dev/null +++ b/.agents/skills/investigate-and-fix/SKILL.md @@ -0,0 +1,25 @@ +--- +name: investigate-and-fix +description: "Diagnose and fix the bug described on this card" +label: "Investigate and fix" +pill-order: + not-started: 1 + specifying: 1 +jockey-hint: "Surface as a top pill only when the card carries the `Bug` tag, and only in the `not-started` and `specifying` phases. On untagged cards, do not include in pills or suggestions at all." +workhorse-version: 0.1.0 +--- + +## Your task: Investigate and fix + +If you don't already have this card's context (title, identifier, description) — for instance when running outside Workhorse — establish it first by following `.agents/docs/card-context.md`. + +The card describes a bug. Diagnose the cause and apply the fix. + +1. **Read the card** — title, description, reproduction steps, error messages, attachments. Treat these as the report +2. **Locate the code path** — use the existing specs in `.workhorse/specs/` to understand the intended behaviour, then find the code that implements (or should implement) it +3. **Form a diagnosis** — what the code currently does, what it should do, and why the two diverge. State this in chat before touching code so the user can agree or redirect +4. **Apply the fix** — edit the code so it matches the intended behaviour +5. **Decide about the spec** — bug fixes usually don't require spec updates, but if the bug existed because the spec was unclear, wrong, or missing, update the spec first so it reflects the intended behaviour, then fix the code to match (see `.agents/docs/spec-format.md`) +6. **Summarise the diagnosis and the fix** in the conversation — short, specific, with file references + +If the description is too thin to diagnose confidently, ask the user for the missing reproduction details before guessing. diff --git a/.agents/skills/mock-this-up/SKILL.md b/.agents/skills/mock-this-up/SKILL.md new file mode 100644 index 0000000..2b266ee --- /dev/null +++ b/.agents/skills/mock-this-up/SKILL.md @@ -0,0 +1,28 @@ +--- +name: mock-this-up +description: "Produce an HTML mockup for the UI being discussed" +label: "Mock this up" +pill-order: + not-started: 6 + specifying: 12 +jockey-hint: "Demote once one or more mockups have been produced in this conversation, unless the user signals they want another variation or a different screen." +workhorse-version: 0.1.0 +--- + +## Your task: Mock this up + +If you don't already have this card's context (title, identifier, description) — for instance when running outside Workhorse — establish it first by following `.agents/docs/card-context.md`. + +Produce an HTML mockup for the UI being discussed. Skip extended exploration — go straight to the mockup. + +1. Identify the target screen from the card description and conversation context +2. Source the visual language before writing any HTML — do not skip steps: + a. **Read the actual implementation of the section being mocked** in the target repo. The shipped code is the baseline for how the screen really looks today — components, layout, spacing, copy. Start here so your output is grounded in what exists, not imagined from scratch + b. **Read implementations of similar components** elsewhere in the target repo to pick up patterns for any new elements not yet present in the section + c. **Cross-check against `.workhorse/design/`** — the design system, component docs, and philosophy notes. The design library may have been updated more recently than the code, so if it disagrees with the implementation, the design library wins + d. **Do not reference mockups from other cards** under `.workhorse/design/mockups/` unless the user explicitly asks — they are point-in-time artefacts, not canonical components +3. **Preserve unchanged aspects.** Author fresh HTML and CSS only for the feature or tweak being developed. For every other region of the screen, be visually faithful to the current implementation — same layout, components, copy, spacing, styling. Do not re-imagine, re-style, or re-layout regions the card is not changing, and do not let stale styling from mockups on other cards leak in. See "Preserving unchanged aspects" in your system prompt +4. Decide where the file goes based on the kind of card you're on: + - **On a product card**, write to `.workhorse/design/mockups/{card-id}/{slug}.html` with inline CSS and an HTML comment header linking to the relevant spec (if one exists). The `{card-id}` folder scopes the mockup to this card so pre-merge cleanup can strip it on merge + - **On a design card**, write under `.workhorse/design/` directly — pick a meaningful path (e.g. `.workhorse/design/components/{slug}.html`, `.workhorse/design/views/{slug}.html`, or `.workhorse/design/mockups/{slug}.html` if it doesn't fit a more specific folder). Mockups produced on a design card persist to main with the card's PR, so file them where they belong long-term +5. Briefly summarise what you produced diff --git a/.agents/skills/plan-cards/SKILL.md b/.agents/skills/plan-cards/SKILL.md new file mode 100644 index 0000000..dcdf17e --- /dev/null +++ b/.agents/skills/plan-cards/SKILL.md @@ -0,0 +1,44 @@ +--- +name: plan-cards +description: "Workshop how to break this card into smaller spawned cards and capture entries in the card plan" +label: "Plan cards" +pill-order: + not-started: 8 + specifying: 13 + implementing: 7 + reviewing: 7 +jockey-hint: "Always available but low-traffic — surface as an available pill, not a top suggestion. Most cards are implemented as one PR; only suggest prominently when the conversation has already revealed the card is too large to ship in one piece." +workhorse-version: 0.1.0 +--- + +## Your task: Plan cards + +If you don't already have this card's context (title, identifier, description) — for instance when running outside Workhorse — establish it first by following `.agents/docs/card-context.md`. + +Workshop how to slice this card into smaller spawned cards and capture the breakdown in the card plan at `.workhorse/plans/{card-id}/card-plan.md`. + +**The card plan is not the implementation plan.** Do not edit `.workhorse/plans/{card-id}/plan.md` — that is a separate, free-form working document for tech-design notes and build steps. The card plan has a strict shape: + +- An H1 title and an optional intro paragraph +- A flat list of `## ` heading entries, one per spawned card +- Each entry's body is a short description paragraph (and optionally a `` comment) — no checklists, no sub-headings, no nested H3s, no build-step bullets + +Once the user is ready, a bulk Create cards action turns each uncreated entry into a real spawned card based on this one. The parent stays as the umbrella while the children carry the implementation work. + +### How to run the workshop + +1. Read the card's specs in `.workhorse/specs/`, the card description, and any existing **card-plan** file at `.workhorse/plans/{card-id}/card-plan.md`. Ignore `plan.md` in the same folder — it is a different artifact and not what you are editing here +2. Skim the target repo where it helps you reason about boundaries between the children +3. Talk through how to slice the work — natural seams, dependency order, what each child should own. Ask focused questions one or two at a time +4. As entries become clear, write them into `card-plan.md` as `## ` headings with a short description paragraph beneath. Edit in place as the conversation refines them — adding, splitting, merging, reordering entries is normal +5. If `card-plan.md` does not yet exist, create it at the path above with an H1 title and the entries underneath. Do not create or edit any other file +6. **Suggest mockup carry-forward.** Each entry has an inline Mockups picker for choosing which of the parent's mockups travel with the spawned card. As you write entries, populate the picker by inserting a structured comment line directly under the entry's `## ` heading: `` (one comment per entry, comma-separated slugs from `.workhorse/design/mockups/{card-id}/`). Pick only the mockups that fit each entry — the user can adjust later +7. Do not trigger bulk-create yourself. The user runs the Create cards action from the editor when they are ready + +### What each entry should look like + +- The `## ` heading is the spawned card's title — concise, action-oriented, no trailing punctuation, no code suffix (the editor stamps `· CODE` automatically once the card is created) +- The body beneath is the spawned card's description — a short paragraph (or two) covering scope and boundaries. Do not write a checklist, sub-headings, or implementation steps; that detail belongs in each child card's own plan after it is created +- Spawned cards inherit the parent's project and become "based on" the parent via dependencies, so don't restate that + +See `.workhorse/specs/card/card-plan.md` for the canonical shape. diff --git a/.agents/skills/plan-implementation/SKILL.md b/.agents/skills/plan-implementation/SKILL.md new file mode 100644 index 0000000..3c87143 --- /dev/null +++ b/.agents/skills/plan-implementation/SKILL.md @@ -0,0 +1,25 @@ +--- +name: plan-implementation +description: "Draft or refine the implementation checklist from specs and current code" +label: "Plan implementation" +pill-order: + specifying: 8 + implementing: 3 +jockey-hint: "Surface when the user wants a concrete checklist but hasn't yet started coding. Demote once a plan with a healthy checklist exists on the card." +workhorse-version: 0.1.0 +--- + +## Your task: Plan implementation + +If you don't already have this card's context (title, identifier, description) — for instance when running outside Workhorse — establish it first by following `.agents/docs/card-context.md`. + +Draft or refine the implementation checklist in the card's plan file. The plan turns the card's specs and any existing tech notes into a sequenced checklist of steps that `Implement this` can then work through. + +1. Read the card's specs and any existing plan at `.workhorse/plans/{card-id}/` +2. Skim the target repo to ground the steps in the existing code +3. If a plan already exists, edit it in place — add, refine, or reorder checklist sections around the existing prose notes. Don't replace notes +4. If no plan exists, create one at `.workhorse/plans/{card-id}/plan.md` with an H1 title, a short summary, and one or more checklist sections +5. Each checklist item should be a concrete step — a file to change, a feature to wire up, a migration to author. Avoid vague items like "add tests" +6. Ask only the clarifying questions you genuinely need to produce a useful plan — the expectation is one or two turns, not an extended interview + +The plan is a free-form working document, not a spec — checkboxes describe build steps, not product behaviour. See `.workhorse/specs/plan/overview.md`. diff --git a/.agents/skills/pull-workhorse-updates/SKILL.md b/.agents/skills/pull-workhorse-updates/SKILL.md new file mode 100644 index 0000000..15c5244 --- /dev/null +++ b/.agents/skills/pull-workhorse-updates/SKILL.md @@ -0,0 +1,51 @@ +--- +name: pull-workhorse-updates +description: "Pull the current Workhorse release's skills, reference docs, and AGENTS.md framework section onto this card, smart-merging against local edits" +label: "Pull Workhorse updates" +pill-order: + not-started: 9 + specifying: 14 + implementing: 8 + reviewing: 8 + complete: 5 +jockey-hint: "Low-traffic maintenance action — surface as an available pill, not a top suggestion. Only promote when the user explicitly asks to pull or update Workhorse's skills, docs, or framework files." +workhorse-version: 0.1.0 +--- + +## Your task: Pull Workhorse updates + +Bring this workspace's Workhorse framework files up to the current release, smart-merging the new bundle against any local edits. The managed files are the **skills** under `.agents/skills/`, the **reference docs** under `.agents/docs/`, and the **framework section** at the top of `AGENTS.md`. The design library under `.workhorse/design/` is workspace-owned and out of scope — never touch it here. + +Workhorse has materialised the current release's bundle into `.workhorse/.pull-bundle/` in this worktree so you can read it directly. That folder is the source of the new versions ("theirs"); the files already in the workspace are "ours". The folder carries its own `.gitignore` so nothing under it is committed — do not merge it into the repo, and leave the folder for Workhorse to manage. + +### What's in the bundle folder + +- `.workhorse/.pull-bundle/manifest.json` — the authoritative list of managed files. Each entry has the target path (relative to the repo root) and the current bundle version. Read this first +- `.workhorse/.pull-bundle/skills/{folder}/SKILL.md` — the current version of each shipped skill +- `.workhorse/.pull-bundle/docs/{name}.md` — the current version of each shipped reference doc +- `.workhorse/.pull-bundle/AGENTS.section.md` — the current framework section, wrapped in its `` / `` markers + +### Identifying what's managed + +- A skill's `SKILL.md` or a reference doc is Workhorse-shipped only if it carries a `workhorse-version` frontmatter field. A file without that field is a purely local file — never touch it +- The `AGENTS.md` framework section is the region between the `` and `` markers. Everything else in `AGENTS.md` is user-owned — never touch it +- A file's identity is its path (the skill folder name, or the doc filename). If a user has renamed or moved a shipped file, it has detached from the bundle — treat it as local and leave it + +### Procedure + +Work through every entry in the manifest, then check for removals: + +1. **New file** — a manifest entry with no counterpart in the workspace. Copy the bundle version into its target path verbatim, including its `workhorse-version` frontmatter +2. **Unchanged local file** — the workspace copy is identical to the bundle version except for a lower `workhorse-version`. Replace it with the bundle version (this just bumps the version) +3. **Locally edited file** — the workspace copy differs from the bundle version in more than the `workhorse-version`. Smart-merge: take the bundle version as the new baseline and re-apply the user's local intent on top, so the release's improvements land while the user's deliberate edits survive. Set `workhorse-version` to the bundle's version. Read both files fully and reason about intent — do not do a naive line union +4. **Removed file** — a workspace file that carries a `workhorse-version` but has no manifest entry (its path is no longer shipped). Delete it with `rm `. The user reviews the deletion in the PR and can revert it there to keep it as a local fork +5. **AGENTS.md framework section** — merge the marked region the same way: bundle section as baseline, the user's edits within the region re-applied on top, written back between the markers with the marker version bumped. If `AGENTS.md` has no Workhorse markers yet, insert the bundle section at the very top of the file. If `AGENTS.md` doesn't exist, create it containing just the section +6. **`.claude/skills/` symlink** — confirm it exists and points at `../.agents/skills/`. If it's missing or points elsewhere, recreate it. If a real file or directory sits at that path instead of a symlink, leave it alone and note it + +### Conflicts and reporting + +- Apply straightforward merges directly. Where a merge is genuinely ambiguous — the release and the local edit change the same thing in incompatible ways — stop and ask the user how to resolve it rather than guessing +- When every managed file already matches the current bundle version, make no changes and report that the workspace is already up to date +- Summarise what you did: files added, updated (noting which needed a real merge), and removed; whether the AGENTS.md section changed; and any conflicts you surfaced + +Your changes are committed to this card's branch by the normal auto-commit, and the user reviews them through this card's PR. diff --git a/.agents/skills/security-audit/SKILL.md b/.agents/skills/security-audit/SKILL.md new file mode 100644 index 0000000..4640077 --- /dev/null +++ b/.agents/skills/security-audit/SKILL.md @@ -0,0 +1,16 @@ +--- +name: security-audit +description: "Review implementation for common security vulnerabilities" +label: "Security audit" +pill-order: + implementing: 5 + reviewing: 5 + complete: 4 +workhorse-version: 0.1.0 +--- + +## Your task: Security audit + +Review the implementation for security concerns — the OWASP Top 10 and any other issues you find. Use your judgement about what matters for this code. + +Post findings grouped by severity with specific file references. diff --git a/.agents/skills/spec-review/SKILL.md b/.agents/skills/spec-review/SKILL.md new file mode 100644 index 0000000..080a5d4 --- /dev/null +++ b/.agents/skills/spec-review/SKILL.md @@ -0,0 +1,26 @@ +--- +name: spec-review +description: "Review this card's specs with fresh eyes for gaps, contradictions, and cross-spec impact" +label: "Review spec" +pill-order: + specifying: 3 +workhorse-version: 0.1.0 +--- + +## Your task: Review spec with fresh eyes + +If you don't already have this card's context (title, identifier, description) — for instance when running outside Workhorse — establish it first by following `.agents/docs/card-context.md`. + +Read the spec files in `.workhorse/specs/` that relate to this card and review them as if you were seeing them for the first time. Set aside the earlier conversation context and check that the specs stand on their own. + +Look for: + +- Gaps in acceptance criteria +- Contradictions between specs +- Missing edge cases +- Unclear or ambiguous criteria +- Information-architecture issues (content in the wrong spec) +- Cross-spec impact (existing specs that should be updated) +- Violations of the writing and structure conventions in `.agents/docs/spec-format.md` + +Be specific and constructive. Reference exact criteria when noting issues. Post findings as a structured message the user can work through with you — don't silently edit the specs in response to your own review. diff --git a/.agents/skills/split-working-doc/SKILL.md b/.agents/skills/split-working-doc/SKILL.md new file mode 100644 index 0000000..683fba6 --- /dev/null +++ b/.agents/skills/split-working-doc/SKILL.md @@ -0,0 +1,28 @@ +--- +name: split-working-doc +description: "Split a working doc into the card's specs, plan, and test cases once its shape is clear" +label: "Split working doc" +pill-order: + specifying: 8 +jockey-hint: "Surface only when the card has a working doc in draft that is substantially developed and its shape looks settled. On cards with no working doc, do not include in pills or suggestions at all." +workhorse-version: 0.1.0 +--- + +## Your task: Split the working doc + +If you don't already have this card's context (title, identifier, description) — for instance when running outside Workhorse — establish it first by following `.agents/docs/card-context.md`. + +Separate the material in the card's working doc into its long-lived and card-scoped artefacts. Read `.agents/docs/working-doc-format.md` and `.agents/docs/spec-format.md` first. + +1. Read the working doc at `.workhorse/working-docs/{card-id}/working-doc.md`. +2. **Check for unresolved open questions.** If any remain, warn the user and ask them to confirm before proceeding — specs can't carry open questions. +3. Fan the material out: + - Behavioural material → the card's specs, rewritten from working voice into declarative spec voice, following the fold-vs-create rules and writing conventions in `.agents/docs/spec-format.md`. Default to editing existing specs. + - Implementation options and trade-offs → the plan at `.workhorse/plans/{card-id}/plan.md` (see `.workhorse/specs/plan/overview.md`). + - Testing notes → the test cases at `.workhorse/test-cases/{card-id}/` (see `.workhorse/specs/test-cases/overview.md`). +4. **Rewrite, don't move** — no working-voice, point-in-time, or open-question material may land in the specs. +5. If the doc has already been split once, reconcile the material into the existing specs, plan, and test cases rather than creating duplicates. +6. Set the working doc's `status` to `complete`. Leave the doc itself in place — it stays as the record of the reasoning. +7. After splitting, remind the user which open questions still need follow-up. + +Generate or update mockups for any UI-facing behaviour as part of the split, following the Design sourcing process from your system prompt. diff --git a/.agents/skills/start-working-doc/SKILL.md b/.agents/skills/start-working-doc/SKILL.md new file mode 100644 index 0000000..8ebdcb5 --- /dev/null +++ b/.agents/skills/start-working-doc/SKILL.md @@ -0,0 +1,22 @@ +--- +name: start-working-doc +description: "Start a working doc — a drafting space where spec-level and implementation thinking co-exist before splitting into specs, plan, and test cases" +label: "Start working doc" +pill-order: + not-started: 8 + specifying: 13 +jockey-hint: "Good fit for larger, epic-level cards where behaviour and implementation need shaping together before committing to specs. Low-traffic — most cards skip it. Demote once a working doc exists on the card." +workhorse-version: 0.1.0 +--- + +## Your task: Start a working doc + +If you don't already have this card's context (title, identifier, description) — for instance when running outside Workhorse — establish it first by following `.agents/docs/card-context.md`. + +Scaffold a new working doc for this card. A working doc is a per-card drafting space where spec-level and implementation thinking co-exist before the card is split into its long-lived artefacts. It suits larger, epic-level cards; most cards don't need one. + +1. Read `.agents/docs/working-doc-format.md` for the shape and voice of a working doc. +2. Create the file at `.workhorse/working-docs/{card-id}/working-doc.md` with `status: draft` frontmatter, an H1 title derived from the card, and a one-line overview. Keep it minimal — do not pre-draft the body sections. +3. Point the user at **Interview me** and **Tech design** to build the doc up, and mention **Split working doc** as the move for when the shape is clear. + +Do not start interviewing or drafting body content from this skill — creation only. diff --git a/.agents/skills/tech-design/SKILL.md b/.agents/skills/tech-design/SKILL.md new file mode 100644 index 0000000..86e2678 --- /dev/null +++ b/.agents/skills/tech-design/SKILL.md @@ -0,0 +1,28 @@ +--- +name: tech-design +description: "Workshop the technical approach and capture notes in the plan" +label: "Tech design" +pill-order: + specifying: 7 + implementing: 4 +jockey-hint: "Good fit when the user wants to talk through technical tradeoffs before committing to implementation. Demote once substantial tech notes are already in the plan unless the user signals a fresh area to workshop." +workhorse-version: 0.1.0 +--- + +## Your task: Tech design workshop + +If you don't already have this card's context (title, identifier, description) — for instance when running outside Workhorse — establish it first by following `.agents/docs/card-context.md`. + +Workshop the technical approach for this card interactively. The goal is to capture rationale, tradeoffs, and decisions into the card's plan file as prose notes. + +1. Read the card's specs and any existing plan at `.workhorse/plans/{card-id}/` +2. Skim the relevant code in the target repo to anchor the conversation in what exists +3. Surface the design choices that need making — architecture, data flow, component boundaries, migration steps — and ask the user focused questions one or two at a time +4. As decisions land, write them into the target document as prose notes under clear section headings. Don't force a checklist yet — notes are fine on their own +5. If the target is the plan and none exists, create one at `.workhorse/plans/{card-id}/plan.md` — an H1 title, an optional summary, and sections of notes are enough for a first version + +**Where notes land:** if a working doc exists for this card in `draft` status (`.workhorse/working-docs/{card-id}/working-doc.md`), write your notes into it — under the conventional sections in `.agents/docs/working-doc-format.md` — rather than the plan. The working doc is the drafting home while the card is being shaped. With no draft working doc, write to the plan as usual. + +The plan is a free-form working document, not a spec. It can carry a mix of tech design notes, refinement notes, and (later) a checklist of steps — see `.workhorse/specs/plan/overview.md` for the shape. + +Do not start implementation from this skill. This skill is for thinking and note-taking only. diff --git a/.agents/skills/workshop/SKILL.md b/.agents/skills/workshop/SKILL.md new file mode 100644 index 0000000..158acea --- /dev/null +++ b/.agents/skills/workshop/SKILL.md @@ -0,0 +1,26 @@ +--- +name: workshop +description: "Workshop this idea with me" +label: "Workshop this" +pill-order: + not-started: 4 + specifying: 10 +workhorse-version: 0.1.0 +--- + +## Your task: Workshop ideas + +If you don't already have this card's context (title, identifier, description) — for instance when running outside Workhorse — establish it first by following `.agents/docs/card-context.md`. + +The user wants to explore and refine an idea. Help them think through approaches, trade-offs, and possibilities. Generate mockups when a visual would help illustrate a concept. This is exploratory — follow the user's curiosity rather than driving toward a specific output. + +### When generating mockups + +Source the visual language before writing any HTML — do not skip steps: + +a. **Read the actual implementation of the section being mocked** in the target repo. The shipped code is the baseline for how the screen really looks today — components, layout, spacing, copy. Start here so your output is grounded in what exists, not imagined from scratch +b. **Read implementations of similar components** elsewhere in the target repo to pick up patterns for any new elements not yet present in the section +c. **Cross-check against `.workhorse/design/`** — the design system, component docs, and philosophy notes. The design library may have been updated more recently than the code, so if it disagrees with the implementation, the design library wins +d. **Do not reference mockups from other cards** under `.workhorse/design/mockups/` unless the user explicitly asks — they are point-in-time artefacts, not canonical components + +**Preserve unchanged aspects.** Author fresh HTML and CSS only for the feature or tweak you are exploring. For every other region of the screen, be visually faithful to the current implementation — same layout, components, copy, spacing, styling. Do not re-imagine, re-style, or re-layout regions the card is not changing, and do not let stale styling from mockups on other cards leak in. See "Preserving unchanged aspects" in your system prompt. diff --git a/.claude/.gitignore b/.claude/.gitignore new file mode 100644 index 0000000..93c0f73 --- /dev/null +++ b/.claude/.gitignore @@ -0,0 +1 @@ +settings.local.json diff --git a/.claude/skills b/.claude/skills new file mode 120000 index 0000000..2b7a412 --- /dev/null +++ b/.claude/skills @@ -0,0 +1 @@ +../.agents/skills \ No newline at end of file diff --git a/.workhorse/design/README.md b/.workhorse/design/README.md new file mode 100644 index 0000000..3084341 --- /dev/null +++ b/.workhorse/design/README.md @@ -0,0 +1,31 @@ +# Pollen design library + +The design library for pollen — the public-facing Tamanu deployment onboarding wizard. +It is the source of truth for the product's visual language, reverse-engineered from the +shipped SPA (`web/src/`) so that mockups and UI work can be grounded in the real, +BES-branded identity rather than reimagined from scratch. + +Pollen's identity is **BES International**: a navy that carries structure (`#313f6a`) +and a sky blue that carries interaction (`#009cea`), on cool off-white paper, set in +Space Grotesk / Inter / IBM Plex Mono. The generic Workhorse design defaults (warm stone +greys, burnt orange) do not apply here. + +## Contents + +- **[`design-system.md`](design-system.md)** — the single source of truth: colour, + typography, spacing, radius, elevation, motion, print, and design principles +- **[`components.md`](components.md)** — catalogue of the shipped UI components, each + with its CSS classes and visual rules +- **[`views.md`](views.md)** — how those components compose into the wizard, the + artifact sheet, and transient states +- **`mockups/`** — per-card HTML mockups produced during spec/design conversations + (point-in-time artefacts, not canonical components) + +## Using and maintaining it + +- When generating a mockup or building UI, source visual language from the shipped + implementation first, then this library — and where the two disagree, this library + represents the agreed current direction. Keep it in step with `web/src/app.css` and + `web/src/theme.ts` as the design evolves. +- The library documents what the system **does** look like, as a coherent snapshot — not + a changelog of how it got here. diff --git a/.workhorse/design/components.md b/.workhorse/design/components.md new file mode 100644 index 0000000..d3d014a --- /dev/null +++ b/.workhorse/design/components.md @@ -0,0 +1,197 @@ +# Component catalogue + +The shipped UI components of the pollen SPA, as implemented in `web/src/app.css` and +`web/src/components/visuals.tsx`. Each entry names the component, its CSS class(es), and +the visual rules that define it. Tokens referenced here are defined in +`design-system.md`. + +When building new UI, compose from these first and match their register; only author +fresh patterns when nothing here fits. + +## Topbar & brand + +`.topbar`, `.brand`, `.brand-logo`, `.brand-rule`, `.brand-name`, `.topbar-new` + +A sticky white bar with a bottom hairline, `14px 28px` padding. Left: the BES logo +(26px rounded square) · a 1px vertical rule · the product name "New Tamanu" in Space +Grotesk 15px/500. Right: a "Start a new plan" text control — `--sky-deep`, 13px/500, +hairline-bordered, `7px 13px`, that fills with `--sky-tint` on hover. A mono caption +(`--ink-faint`, 11px) may sit in the bar for build/version info. + +## Question card + +`.card`, `.qtitle`, `.qhelp`, `.section-eyebrow`, `.guide` + +The primary content container in the wizard. White surface, `--line` border, +`--radius`, `24px 26px` padding, card shadow, `16px` bottom margin. Enters with the +`rise` animation. + +- **`.qtitle`** — Space Grotesk 17px/600, `-0.01em`. +- **`.qhelp`** — 13px `--ink-soft`, line-height 1.5; renders inline markup. +- **`.section-eyebrow`** — uppercase 11px/600 `--sky-deep` label that groups cards into + sections. +- **`.guide`** — an inline `--sky-tint` note inside a card (contextual guidance): sky + wash, `#bfe4f8` border, `--navy-deep` text, `--radius-sm`-ish 10px. + +## Choice list + +`.choices`, `.choice`, `.choice.on`, `.choice-tick`, `.choice-title`, `.choice-note` + +Vertical list of selectable options (single- or multi-select). Each `.choice` is a +full-width left-aligned button: white, hairline border, 11px radius, `13px 15px` +padding. Hover darkens the border and washes to `#fbfdfe`. Selected (`.on`) takes a +`--sky` border and `--sky-tint` fill. + +- **`.choice-tick`** — 18px rounded-square, hairline border; when selected, fills + `--sky` and shows a white check (the `Check` inline icon). +- **`.choice-title`** — 14px/500; **`.choice-note`** — 12px `--ink-faint`, supports + inline markup. + +Multi-select honours exclusivity (an exclusive "none of these" option clears the rest, +and vice versa) — see `Wizard.tsx`. + +## Band selector + +`.bandrow`, `.band`, `.band.on` + +A compact segmented control for ordinal/scale answers: a 4-column grid (2 columns below +`560px`) of small buttons — 12.5px `--ink-soft`, hairline border, 10px radius. Selected +(`.on`) inverts to a solid `--navy` fill with white text. Bands select in **navy** +(structural quantity); choices select in **sky** (interaction) — this distinction is +intentional. + +## Derived-value note + +`.derive` + +A summary readout shown after inputs (e.g. a derived deployment size): `--sky-tint` +wash, `#bfe4f8` border, 10px radius, `--navy-deep` text; the emphasised value uses the +display font. + +## Verdict banner + +`.verdict`, `.verdict-big`, `.verdict-t`, `.verdict-s` — component `VerdictBanner` + +The headline status of a plan. A pill-radius (11px) block whose foreground/background +come from the verdict's semantic pair (clear / off-default / blocking). `.verdict-t` is +the display-font title; `.verdict-s` the muted subtitle with the count summary. +`.verdict-big` enlarges it for the artifact head. Before any choice is made it shows a +neutral `--line-soft` "Nothing recorded yet" state. + +Verdict → copy: + +- **Blocking** — "Not possible as specified" · _N blocking conflicts — something must + change._ +- **Non-default** — "Possible, with acknowledged off-default choices" · _N choices off + the default path. This will be harder to support._ +- **Default** — "On the default, supported path" · _No off-default choices recorded._ + +## Meters + +`.meters`, `.meter`, `.meter-k`, `.meter-v` + +A row of three equal stat tiles in the rail (Size · Custom · Blocking). Each is a pale +`--paper` tile with a `--line-soft` border and `--radius-sm`: a tiny uppercase key +(`.meter-k`, 9.5px `--ink-faint`) over a display-font value (`.meter-v`, 18px/600). The +Custom and Blocking values turn `--offdef` / `--block` when non-zero. + +## Consequence card + +`.cons`, `.cons-bar`, `.cons-body`, `.cons-head`, `.cons-dot`, `.cons-title`, +`.cons-detail`, `.cons-tags`, `.tag`, `.cost-note` — components `ConsequenceCard`, `Tag` + +The core record of a single triggered consequence, used in both the rail ledger and the +artifact sheet. A white card with a **3px left severity bar** (`.cons-bar`) coloured by +severity. The body carries: + +- **Head** — a 7px severity `.cons-dot` and a display-font `.cons-title` (13px/600). +- **Detail** — `.cons-detail`, 12.5px `--ink-soft`, max 70ch, inline markup. +- **Tags** — one `.tag` (pill, 10.5px/500) per consequence type in its type colour, plus + a neutral status tag; an optional italic `.cost-note` (`--ink-faint`) shows cost + tier · ballpark. + +Card border colour is set to the severity background so neutral consequences recede and +blocking ones read hot. + +## Buttons + +`.btn`, `.btn.primary`, `.btn.ghost`, `.btn.sm` + +- **Primary** — solid `--navy`, white text; hover `--navy-deep`. Used for the single + key action (Finalise, Update, Resume). +- **Ghost** — white, hairline border, `--ink-soft` label; hover darkens the border. + Used for secondary artifact actions (Copy link, Download PDF, Make changes). +- Base: inline-flex, `11px 20px`, 10px radius, 14px/500, ~0.15s transition. **`.sm`** + tightens to `7px 14px` / 13px / 8px radius (used in banners). Disabled drops to 0.5 + opacity. + +## Action bar + +`.actions`, `.actions-hint` + +A right-aligned footer row under the wizard cards holding the primary action, with an +optional left-aligned `--ink-faint` hint ("Answer every question to finalise."). + +## Update / resume bar + +`.updatebar`, `.updatebar-sub`, `.updatebar-actions` — components `UpdateBar`, +`ResumeBar` + +A full-width centred notice below the topbar: `--sky-tint` wash, `#bfe6f9` bottom +border, `--navy-deep` text, 13.5px. Inline `code` chips (ruleset branch names) get a +white background and sky border. Carries one or two `.sm` buttons — a primary action +plus (for resume) a ghost Dismiss. Used for ruleset-preview / update-available prompts +and the "pick up where you left off?" resume offer. + +## Artifact sheet + +`.sheet`, `.sheet-head`, `.sheet-eyebrow`, `.sheet-title`, `.sheet-facts`, +`.sheet-meta`, `.sheet-controls`, `.sheet-section`, `.sheet-section-title` — component +`Artifact` + +The finalised plan as a printable document. A single centred surface (max 920px, 16px +radius, sheet shadow) with: + +- **Head** — a faintly-tinted (`#fbfdfe`) band with the display-font `.sheet-title` + (26px) " deployment", a `.sheet-facts` row (topology, region) in `--ink-soft`, + and right-aligned mono `.sheet-meta` (config hash, date). +- **Controls** — a toggle group (`.tg` — By audience / By topic), a search input + (`.sheet-search`), and ghost action buttons; hidden in print. +- **Sections** — `.sheet-section` blocks separated by `--line-soft`, each led by an + uppercase `--sky-deep` `.sheet-section-title`, holding grouped consequence cards. + +## Toggle group + +`.tg-group`, `.tg`, `.tg.on` + +Segmented toggle for view grouping. Each `.tg` is a hairline-bordered white pill-ish +button (8px radius, 12.5px `--ink-soft`); the active one inverts to solid `--navy` +white — the same navy-selection language as bands. + +## Search input + +`.sheet-search` + +A flexible hairline-bordered text input (8px radius, 13px), `type="search"`, filtering +consequences live by title/detail. + +## Decision record + +`.record`, `.record-row`, `.ledger-empty` + +A bordered table of every question and its recorded answer, closing the artifact. Rows +(`.record-row`) are `space-between` with a `--ink-soft` label and a mono value; odd rows +get a `#fbfdfe` zebra tint. `.ledger-empty` is the muted empty-state line (e.g. "No +consequences match your search."). + +## Splash / status + +`.splash` + +A centred full-height placeholder in `--ink-faint` 14px for transient states — starting +a plan, loading, load errors, and not-found. + +## Related + +- `design-system.md` — tokens these components draw on +- `views.md` — how they compose into screens diff --git a/.workhorse/design/design-system.md b/.workhorse/design/design-system.md new file mode 100644 index 0000000..e1d6c50 --- /dev/null +++ b/.workhorse/design/design-system.md @@ -0,0 +1,189 @@ +# Pollen design system + +The single source of truth for pollen's visual language. Pollen is the public-facing +Tamanu deployment onboarding wizard — a self-contained axum + React/MUI SPA. Its +identity is **BES International**: a navy that carries structure and a sky blue that +carries interaction, set on a cool off-white paper. + +These tokens are reverse-engineered from the shipped SPA and mirror +`web/src/app.css` (`:root`) and `web/src/theme.ts`. When the two disagree, this +document represents the agreed direction; keep `app.css` and this file in step. + +> The generic Workhorse defaults (warm stone greys, burnt orange) do **not** apply to +> pollen. Everything below is the real, shipped BES-blue identity. + +## Principles + +- **Structure in navy, interaction in sky.** Navy (`#313f6a`) is for primary actions, + selected bands, and load-bearing chrome. Sky (`#009cea`) is for selection ticks, + section eyebrows, links, and informational washes. Never swap their roles. +- **Calm, document-like surfaces.** White cards float on cool paper with a hairline + border and a soft, low, downward shadow — not heavy drop shadows. The artifact reads + like a printable record, not a dashboard. +- **Consequence colour is semantic, never decorative.** Green/amber/red map to + Default / Non-default / Blocking and to nothing else. Don't tint UI with them for + emphasis. +- **Quiet motion.** A single 4px rise on entrance and 0.14s hover transitions. All + motion is gated behind `prefers-reduced-motion`. +- **No purple, no gradients, no sparkle.** Flat fills, hairline borders, one accent + family. + +## Colour + +### Brand + +| Token | Value | Role | +| --- | --- | --- | +| `--navy` | `#313f6a` | Primary brand; primary buttons, selected band, `qtitle` accents, MUI `primary` | +| `--navy-deep` | `#27325a` | Navy hover/pressed; `derive`/`updatebar` prose text | +| `--sky` | `#009cea` | Secondary brand; selection tick, selected choice border, MUI `secondary` | +| `--sky-deep` | `#0784c4` | Sky as text: links, section eyebrows, "start new plan" control | +| `--sky-tint` | `#e7f5fd` | Sky informational wash: selected choice, guide/derive/update bars | + +### Ink (text) + +| Token | Value | Role | +| --- | --- | --- | +| `--ink` | `#14222b` | Primary text | +| `--ink-soft` | `#485a63` | Secondary text, help copy, ghost-button label | +| `--ink-faint` | `#7e8c94` | Tertiary/muted: meta, notes, disabled hints, rail labels | + +### Neutrals + +| Token | Value | Role | +| --- | --- | --- | +| `--paper` | `#f4f6f8` | Page background (MUI `background.default`) | +| `--surface` | `#ffffff` | Cards, rail, sheet, controls (MUI `background.paper`) | +| `--line` | `#e3e8eb` | Standard borders | +| `--line-soft` | `#eef1f3` | Subtle dividers, inner separators | + +Hover borders on interactive surfaces darken to `#c4d0d6` (a one-off, not a token). + +### Semantic — verdict & severity + +Each pairs a saturated foreground with a pale background wash of the same hue. Used for +the verdict banner, severity dots/bars, and severity-tinted meters. + +| Meaning | Foreground | Background | +| --- | --- | --- | +| Default / on the supported path | `--clear` `#2e7d52` | `--clear-bg` `#e4f1ea` | +| Non-default / off the default path | `--offdef` `#b5791f` | `--offdef-bg` `#fbf1dc` | +| Blocking / not possible as specified | `--block` `#b23a3a` | `--block-bg` `#f7e4e1` | + +Severity dot/bar uses the foreground colour; the "Default" severity is the exception — +its dot is `--ink-faint` and its wash is `--line-soft`, so an unremarkable consequence +stays visually neutral. + +### Consequence-type tags + +Pill tags on consequence cards, one pale hue per type (`visuals.tsx`, `TYPE_COLOR`): + +| Type | Foreground | Background | +| --- | --- | --- | +| Cost | `#9a6a00` | `#fbf1dc` | +| Operational | `#1f5fa6` | `#e6eff8` | +| Capability loss | `#8a2e2e` | `#f7e4e1` | +| Support | `#6b3a8a` | `#efe6f6` | + +A neutral status tag (`#3a4750` on `#eaedee`) sits alongside them. + +## Typography + +Three self-hosted families, bundled into the binary (`main.tsx`) — no runtime fetch. + +| Token | Stack | Role | +| --- | --- | --- | +| `--font-display` | `"Space Grotesk", system-ui, sans-serif` | Headings (h1–h3), card/section titles, verdict text, meter values, sheet title | +| `--font-body` | `"Inter", system-ui, sans-serif` | Body, controls, labels — the default | +| `--font-mono` | `"IBM Plex Mono", ui-monospace, monospace` | Config hashes, dates, recorded answer values, inline `code` | + +Weights bundled: Space Grotesk 400/500/600/700, Inter 400/500/600, IBM Plex Mono +400/500. + +### Scale + +Type is compact and set in pixels in the shipped CSS. Key sizes, by role: + +- **Sheet title** — 26px / 600, Space Grotesk, `-0.02em` tracking +- **Question title** (`qtitle`) — 17px / 600, Space Grotesk, `-0.01em` +- **Meter value** — 18px / 600, Space Grotesk +- **Brand name** — 15px / 500, Space Grotesk +- **Body / choice title / button** — 13–14px, Inter +- **Help & note copy** — 12–13px, Inter, line-height ~1.5 +- **Eyebrows** — 10.5–11px, uppercase, letter-spacing 0.10–0.12em, weight 600, in + `--sky-deep` (content eyebrows) or `--ink-faint` (rail/meta eyebrows) +- **Tags** — 10.5px / 500 + +Display headings carry slight negative tracking; eyebrows carry wide positive tracking. +Body text never goes below ~12px. + +## Spacing & layout + +- **4px grid.** Padding and gaps are multiples/near-multiples of 4 (e.g. card padding + `24px 26px`, choice padding `13px 15px`, gaps of 6/8/10/12/16px). +- **Two-pane frame.** The wizard is a `288px` sticky rail + fluid main, capped at + `1180px` and centred. Below `880px` the rail is hidden and it collapses to one column. +- **Artifact sheet** is a single centred column capped at `920px`. +- **Sticky chrome.** The topbar sticks to the top (`z-index: 20`); the rail sticks + below it at `top: 57px`. + +## Radius + +| Token / value | Applied to | +| --- | --- | +| `--radius` `12px` | Question cards, informational bars | +| `--radius-sm` `9px` | Meters | +| `16px` | Artifact sheet (the largest surface) | +| `10–11px` | Choices, bands, buttons, consequence cards, records | +| `8px` | Small buttons, toggles, search, topbar control | +| `6px` | Selection tick, inline code chips | +| `99px` (pill) | Tags, severity dots | + +Larger surfaces take larger radii; controls stay tighter. + +## Elevation + +Two soft, downward-only shadows layered as a tight contact shadow plus a wide, faint +ambient one — never a hard drop shadow: + +- **Card** — `0 1px 2px rgba(20,34,43,.03), 0 12px 28px -22px rgba(20,34,43,.16)` +- **Sheet** — `0 1px 2px rgba(20,34,43,.03), 0 16px 36px -24px rgba(20,34,43,.2)` + +Everything else relies on the hairline `--line` border rather than shadow. + +## Motion + +- **Entrance rise.** Cards and consequence cards animate in with `rise`: opacity 0→1 + and `translateY(4px)`→0 over 0.24s ease, gated behind + `@media (prefers-reduced-motion: no-preference)`. +- **Hover transitions.** Interactive surfaces transition `border-color` / `background` + over ~0.14s; buttons over ~0.15s. +- Keep new motion in this register — short, small, opt-out-aware. + +## Print + +The artifact is designed to print as a clean record (`@media print`): topbar, update +bar, and sheet controls are hidden; the sheet drops its max-width, border, radius, and +shadow; sections/cards/records avoid inner page breaks; the entrance animation is +forced to its finished state so nothing prints greyed-out mid-flight; links print as +plain inherited-colour text. + +## Iconography + +Icons are minimal inline SVG (lucide-style paths, `stroke="currentColor"`, +`stroke-width: 2`, round caps/joins) rendered by the `Icon` helper in `visuals.tsx` — +nothing is fetched at runtime. The only shipped glyph is a check; add new icons in the +same 24×24 stroked style. + +## Inline prose markup + +Ruleset-authored copy (help text, notes, consequence detail, guidance) is rendered +through `markup.tsx`, which supports Markdown links (opening in a new tab), `**bold**`, +`*italic*`, and `` `code` ``. Links render in `--sky-deep` underlined with a 2px offset; +code renders in `--font-mono` at 0.9em. It renders to React nodes, never raw HTML, and +only accepts `http(s)` link targets. + +## Related + +- `components.md` — the shipped component catalogue +- `views.md` — how components compose into screens diff --git a/.workhorse/design/views.md b/.workhorse/design/views.md new file mode 100644 index 0000000..fd91631 --- /dev/null +++ b/.workhorse/design/views.md @@ -0,0 +1,67 @@ +# View catalogue + +How pollen's components compose into screens. The SPA has two real screens — the +**wizard** and the **artifact sheet** — plus transient landing/loading states. Routing +lives in `web/src/App.tsx`; the screens in `web/src/components/` and +`web/src/routes/`. Components referenced here are defined in `components.md`. + +## Shell + +Every route renders beneath a persistent sticky **topbar** (brand left, "Start a new +plan" right). Below it, a route may render a full-width **update/resume bar** before its +content. The body sits on `--paper`; content surfaces are white. + +## Wizard (`/a/:id`, draft status) + +The plan-building screen — component `Wizard`, inside a `.frame` two-pane layout. + +- **Rail (288px, sticky).** Top-to-bottom: the **verdict banner**, the three **meters** + (Size · Custom · Blocking), a "Consequences" eyebrow, then the **ledger** — every + triggered consequence as a **consequence card**, sorted most-severe first (Blocking → + Non-default → Default), stable within a severity by ruleset order. +- **Main.** The visible **question cards** in order, each rendering as a choice list, a + band selector, or a multi-select depending on its kind, with optional contextual + `.guide` notes. It closes with the **action bar**: a hint until every visible question + is answered, then the primary **Finalise** button. + +Answering a question patches the plan and re-evaluates on the server; the choice is +reflected optimistically before the response lands. Below 880px the rail drops away and +the questions take the full width. + +## Artifact sheet (`/a/:id`, finalised status) + +The finalised, printable plan — component `Artifact`, inside a single centred +**artifact sheet**. + +- **Head** — " deployment" title, a facts row (topology, region), and mono meta + (config hash, date). +- **Verdict** — the **verdict banner** in its `big` form. +- **Controls** — the audience/topic **toggle group**, a **search input**, and ghost + actions: **Copy link**, **Download PDF**, **Make changes**. +- **Grouped consequences** — **sheet sections**, one per audience (Client IT · BES + technical · Record) or per topic depending on the toggle, each holding its matching + **consequence cards**; empty groups are dropped and a no-match line shows when search + excludes everything. +- **Decision record** — a closing **record** table of every question and its answer. + +"Make changes" forks the plan into a new version (opened in a fresh tab) so the +finalised artifact is never mutated in place. "Download PDF" resets grouping to +by-audience, clears search, and triggers the browser print path (see the print rules in +`design-system.md`). + +## Transient states + +- **Landing (`/`)** — component `NewApplication`: a **splash** ("Starting a new + deployment plan…") that creates a draft then replaces the URL with the draft's id. On + failure it shows the error inline in the splash. +- **Loading / error (`/a/:id`)** — a **splash** while the plan loads or if it fails. +- **Resume offer** — on a fresh, untouched draft with a prior plan on record, a + **resume bar** offers to pick up where the user left off (Resume / Dismiss). It is + suppressed when an update/preview bar is already showing, and disappears once a choice + is made. +- **Not found (`*`)** — a **splash** reading "Not found." + +## Related + +- `design-system.md` — tokens and principles +- `components.md` — the components these views compose diff --git a/.workhorse/plans/a1/plan.md b/.workhorse/plans/a1/plan.md new file mode 100644 index 0000000..72ec9cb --- /dev/null +++ b/.workhorse/plans/a1/plan.md @@ -0,0 +1,37 @@ +# Set up design library for this repo + +Establish `.workhorse/design/` as the design library for pollen, reverse-engineered +from the shipped SPA (`web/src/`). The library is the source of truth future mockup +and UI work sources from, so it must faithfully capture what is *actually* implemented +— the BES-branded blue palette, the Space Grotesk / Inter / IBM Plex Mono type stack, +and the concrete component patterns in `app.css`, `visuals.tsx`, and the routes. + +## Source of truth + +- Tokens: `web/src/app.css` (`:root`), `web/src/theme.ts` +- Component styling: `web/src/app.css`, `web/src/components/visuals.tsx` +- Composition/views: `web/src/App.tsx`, `web/src/components/Wizard.tsx`, + `web/src/components/Artifact.tsx`, `web/src/routes/*` +- Fonts: `web/src/main.tsx` (self-hosted @fontsource) + +Note: the generic Workhorse design-system defaults (warm stone greys, burnt orange) +do **not** apply here — pollen ships a BES blue identity. The library documents the +real thing. + +## Deliverables + +- [x] `.workhorse/design/design-system.md` — the SSoT: palette, semantic colours, + typography, spacing, radii, elevation, motion, print, and voice/principles +- [x] `.workhorse/design/components.md` — catalogue of shipped components (topbar, + question card, choices/bands, verdict banner, meters, consequence card + tags, + buttons, update/resume bars, artifact sheet, decision record, splash) +- [x] `.workhorse/design/views.md` — how the components compose into the wizard, + the artifact sheet, and the transient landing/loading/not-found states +- [x] `.workhorse/design/README.md` — index/orientation for the library + +## Notes + +- No `.workhorse/specs/` changes: this is a design/tooling card, not a product + behaviour change. The library is documentation, not a spec. +- Keep tokens single-sourced in prose (name → value → role) so they don't drift + from `app.css`; cross-reference the file rather than duplicating full CSS. diff --git a/AGENTS.md b/AGENTS.md index 0ba6c78..f3c480e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,3 +1,17 @@ + +# Workhorse framework + +This workspace uses [Workhorse](https://github.com/beyondessential/workhorse), a spec-driven development workbench. Workhorse ships skills (invokable prompts) and reference docs into this repo to shape how AI agents work here. + +- **Skills** live at `.agents/skills/` — each skill is a folder containing a `SKILL.md` with YAML frontmatter and a prompt body. `.claude/skills/` is a symlink to the same folder so Claude Code picks them up natively +- **Reference docs** live at `.agents/docs/` — long-form guidance that skill bodies cite by path (spec format conventions and similar) +- **Specs** live at `.workhorse/specs/` — acceptance criteria for each piece of work, organised into areas by subdirectory + +When picking up a task, read the skill whose folder name matches what you're being asked to do — its `SKILL.md` describes how to approach the work and which reference docs to follow. + +Workhorse manages this section. Run the **Pull Workhorse updates** skill to bring it, the skills, and the reference docs up to the latest release — local edits you make here are preserved through a smart merge. Edit or remove it freely. + + # Agent rules for pollen Pollen is the public-facing Tamanu deployment onboarding wizard: a standalone