Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion plugins/backlog-tools/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "backlog-tools",
"description": "Backlog-native Claude Code skills for the Backlog product itself — writing a Backlog import plan from an agreed specification, running one item of such a plan when it is pasted back out of the app, turning another to-do tool's export into an inbox import manifest, and answering the private reading notes the app holds on a repository's Devbook chapters — plus a Claude Code hook that forwards a session's tool and token telemetry to the app.",
"version": "0.11.2",
"version": "0.12.0",
"author": {
"name": "Job Schepers"
},
Expand Down
8 changes: 6 additions & 2 deletions plugins/backlog-tools/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@ while reading.
- **`backlog-import-plan`** — turns an agreed specification into a Backlog import plan
(ADR 0007: `.devbook/arc42/adr/0007-import-reuses-the-entry-text-grammar.md`). Every entry is
a `prompt` an AI session runs, or a `task` or `test` only the user does — never both in one
entry. Before a step stays a `task` or `test`, it asks you whether an AI session could do
it instead, and every step, whatever its kind, names its repository with `repo:`. It always ships a review view next to the raw plan — one HTML page built from
entry. Prompts are the default: while it writes the plan it interviews you — the open
decisions, the values and access the work needs, what a pass looks like — and writes the
answers into the prompts, so no step stops to ask when it runs. A manual check is offered
as an AI-run QA prompt first, and a step stays a `task` or `test` only when you keep it,
with a `Kept manual:` line saying why. Every step, whatever its kind, names its
repository with `repo:`. It always ships a review view next to the raw plan — one HTML page built from
`skills/backlog-import-plan/assets/plan-review.html` that parses the embedded plan
itself and shows its checks, dependency order and entries, published as an artifact where
the host has one and written beside the plan otherwise. User-invoked only
Expand Down
82 changes: 61 additions & 21 deletions plugins/backlog-tools/skills/backlog-import-plan/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,26 @@ mechanics; do not invent syntax beyond it.
- **Output.** A file path, or "paste it here" — ask if neither is stated. The review view
(step 7) is produced either way; it is not an option.
- **Level.** Step-level (the default) or, when asked, [roadmap-level](#roadmap-level-mode).
- **The user's answers.** Gathered by the [interview](#interview) while the plan is written,
never assumed.

## Prompts first

The user prefers work an AI session runs over work they do themselves, and wants every
question a step would raise answered while the plan is written, not when a step runs.
`prompt` is the default kind. A step is a `task` or `test` only when it is the closing
sign-off, or when the interview offered to hand it to an AI session and the user kept it.
A prompt runs to the end without asking anything the plan could have settled; the only
stops left in it are the gates the target repository's own process sets, such as its
approval before a pull request.

## Workflow

1. Read the source material in full, following any `depends-on`/prerequisite references it
names, so ordering is grounded in what is agreed rather than guessed.
names, so ordering is grounded in what is agreed rather than guessed. Note each open
question as you read: an unresolved decision, an alternative left open, a `TBD`, an
`annotation` fence, a value the work needs but the source does not give.
Then run the [interview](#interview)'s first round, before drafting any entry.
2. Derive the plan's `+tag`: one slug from the plan subject, written with the `+` sigil
Backlog stores plan tags under (a `#slug` is a general tag and a different plan from
the `+slug` the app's picker offers). Reuse the exact same slug if
Expand All @@ -43,11 +58,14 @@ mechanics; do not invent syntax beyond it.
states a date; no `effort:`, `!status`, `id:` or body boilerplate.
Then break the work into ordered step entries, one per unit of work. Every step is
exactly one of three kinds, decided by who does it — see the grammar's `## Entry kinds`:
- **`prompt`** — work an AI session runs.
- **`task`** — work only the user can do: a decision, a sign-off, an action in an
account or on a machine the AI cannot reach.
- **`prompt`** — work an AI session runs. Draft every step as one unless it cannot be.
- **`task`** — work only the user can do even with access they could grant: an action
in an account or on a machine no AI session can reach, or the sign-off. A decision is
never a task — the interview asks it now.
- **`test`** — a check the user runs by hand against work already landed, where the
source material asks for manual acceptance or exploratory testing.
source asks for manual acceptance or exploratory testing. Draft it first as a QA
prompt: an AI session starts the application the way the target repository says,
drives the scenarios in a browser or harness, and captures evidence of each pass.

Never combine a prompt with either of the others. A manual step is never a sub-item, checklist line or body
instruction inside a prompt, and a task never carries instructions for an AI. When one
Expand All @@ -67,7 +85,9 @@ mechanics; do not invent syntax beyond it.
a colon, then the entry's numbered title exactly as written (grammar's
`## Step numbers`). Every prompt carries it, worded the same way.
- **Instructions next.** The rest of the body — concise, no padding — is the entry's
primary content.
primary content. Write every interview answer the step depends on into it as a
settled fact — the chosen option, the exact name, value or wording — never as
"confirm with the user", "decide whether", "TBD" or a choice left between options.
- **Setup sub-items.** A `##` sub-item per repository prerequisite the instructions
assume (installing a plugin, updating one, wiring a related change), ordered ahead of
everything else in the entry, titled `Setup: ...`.
Expand All @@ -78,7 +98,9 @@ mechanics; do not invent syntax beyond it.
For each **`task`** entry: a title naming what the user does, then a body addressed to
the user — what to do and what "done" looks like, concise. No marker, no session-name
line, no `Setup:` or knowledge sub-item: those direct an AI session, and a task has
none. `- [ ]` checklist lines are fine for the user's own steps.
none. `- [ ]` checklist lines are fine for the user's own steps. Every task or test but
the sign-off closes its body with one line, `Kept manual: <reason>`, in the user's
words from the interview.

A **`test`** entry is shaped like a task: a title naming what is checked, a body saying
what to exercise and what a pass looks like, `- [ ]` lines for the individual checks,
Expand All @@ -98,16 +120,7 @@ mechanics; do not invent syntax beyond it.
`+tag`; and only the `*priority`, `@area` or `due:` the source material actually
implies.

**Ask before a step stays manual.** Once the steps are drafted, and before sizing them,
ask the user about every step drafted as a `task` or `test` — in one round, a question
per step — whether an AI session could do it instead, and what it would take: access it
could be given (a signed-in CLI, an MCP server, a test account, the running harness), or
a decision the user can make right now. A step the user hands to an AI becomes a
`prompt`, shaped as above, with a `Setup:` sub-item for the access it needs; a decision
answered on the spot is written into the prompts that needed it and its task dropped,
with their `after:` on it removed. A step stays a `task` or `test` only when the user
says it does. The closing sign-off is never asked about; with no task or test drafted,
there is nothing to ask.
Once the steps are drafted, and before sizing them, run the interview's second round.
4. Close every step-level plan with two entries, in this order and last in the document.
Never omit either, however small the plan.
- The **review prompt**, titled `Review the <plan subject> plan for anything missed`. It
Expand Down Expand Up @@ -145,11 +158,37 @@ mechanics; do not invent syntax beyond it.
glance what the plan gets wrong; when the user reports a failed check, fix the plan and
regenerate the view rather than patching the view.
8. Report the output location (if written), the review view's link or path, the entry
count, the repositories targeted, the dependency chain, which drafted tasks or tests the
user's answers turned into prompts, and which sizing answered — the
count, the repositories targeted, the dependency chain, the interview's answers and the
prompts each went into, which drafted tasks or tests became prompts, every step kept
manual with its reason, and which sizing answered — the
`estimate` skill, or this skill's fallback and the step it anchored on. Stop — do
not open the Backlog app, run a prompt, or create a pull request.

## Interview

Ask with the host's question tool where it has one — several questions per round, each
with the options the source supports and a recommended one first — otherwise as one
numbered list in chat, and wait for the answers. Ask only what the source and the target
repository do not already answer; read the repository before asking about it.

- **Round one, before drafting** — everything a prompt would otherwise stop to ask:
- *Decisions:* each open question noted while reading, and each choice the work forces
that the source leaves open — an approach, a name, a scope edge, wording a user sees.
- *Values:* inputs the work needs that are not in the source or the repository — a
version, an endpoint, an identifier, a date. Never ask for a secret's value; ask where
the session will find it (a signed-in CLI, a user-secret, an environment variable).
- *Access:* for work in an account, a service or on a machine, whether an AI session can
be given a way in — a signed-in CLI, an MCP server, a test account, the running
harness. Access the user grants becomes a `Setup:` sub-item of the prompt that uses it.
- *Acceptance:* for each check the source leaves to a person, what a pass looks like, so
a QA prompt can run it.
- **Round two, after drafting** — one question per step still drafted as a `task` or
`test`, the sign-off aside: hand it to an AI session (as a prompt, with the access it
needs), or keep it manual, and why. A handed-over step becomes a `prompt`; a kept one
records the reason as its `Kept manual:` line. Skip the round when nothing is left.
- **Further rounds** whenever writing a prompt turns up a question the answers do not
settle. Never guess an answer and never leave one for the step to ask.

## Sizing the steps

Size every step in one pass once all of them are drafted, never one at a time as each is
Expand Down Expand Up @@ -186,9 +225,10 @@ under the same tag. Steps 5–8 apply unchanged.
`repo:`, and the plan's shared `+tag`; every prompt also opens with the marker line, then the
session-name line naming `<tag>:<its title>`.
- No prompt contains a manual step in any form — no `Manual:` sub-item, no "ask the user
to…" instruction — and no task or test contains instructions for an AI.
to…" instruction — or an open decision: no "confirm with", "decide whether", `TBD`, or
choice left between options. No task or test contains instructions for an AI.
- Every task or test other than the sign-off is one the user was asked about and kept
manual; the rest became prompts.
manual, and says why on its `Kept manual:` line; the rest became prompts.
- `after:` correctly expresses the plan's dependency order, including cross-repository
dependencies and prompts that wait on a task, and never names the other level.
- The last two entries are the plan review, waiting on every leaf of that order, and the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,12 @@ does the work:
every prompt whose work it checks. Automated tests are never a `test` entry: they belong
inside the prompt that writes the code.

`prompt` is the default. A `task` or `test` other than the plan's closing sign-off is one
the user chose to keep manual when the plan was written, and its body ends with a
`Kept manual: <reason>` line saying why — prose, not a token Backlog parses. A decision is
never a `task`: it is asked while the plan is written and its answer is written into the
prompts that need it, so no prompt stops to ask it at run time.

A `prompt` never mixes with the other two. A manual step or check is never a sub-item,
checklist line or instruction inside a `prompt`, and a `task` or `test` never carries
instructions for an AI. Work that needs both is split: the manual step is its own `task`
Expand Down Expand Up @@ -160,23 +166,25 @@ before you start.`` instead; `backlog-run-plan-item` still recognizes that line.

`plan` `*high` `+vscode-desktop-rollout` `repo:backlog-desktop`

# 1 - Confirm the export format with design
# 1 - Reserve the marketplace publisher name

`task` `!ready` `@repos` `+vscode-desktop-rollout` `id:reserve-publisher` `repo:backlog-desktop` `effort:1`

`task` `!ready` `@repos` `+vscode-desktop-rollout` `id:confirm-format` `repo:backlog-desktop` `effort:1`
Reserve the `backlog` publisher name on the VS Code marketplace. Done when the publisher
page shows it as yours.

Agree with design whether the export is plain Markdown or Markdown with front matter, and
note the answer on this entry. Done when the format is written down here.
Kept manual: the publisher account needs my own Microsoft sign-in.

# 2 - Add the export command

`prompt` `*high` `!ready` `@repos` `+vscode-desktop-rollout` `id:add-command` `after:confirm-format` `repo:backlog-desktop` `effort:5`
`prompt` `*high` `!ready` `@repos` `+vscode-desktop-rollout` `id:add-command` `after:reserve-publisher` `repo:backlog-desktop` `effort:5`

Backlog plan item `add-command` of plan `vscode-desktop-rollout` for `backlog-desktop`, after `confirm-format` — run it with the `backlog-run-plan-item` skill.
Backlog plan item `add-command` of plan `vscode-desktop-rollout` for `backlog-desktop`, after `reserve-publisher` — run it with the `backlog-run-plan-item` skill.

Title this session `vscode-desktop-rollout:2 - Add the export command` before you start.

Add an export command to the command palette that serializes the current view to Markdown,
in the format agreed on the `confirm-format` entry.
Add an export command to the command palette that serializes the current view to Markdown
with front matter, publisher `backlog` in the extension manifest.

## Setup: install the command-palette SDK

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -474,12 +474,18 @@ <h2>Entries</h2>
const txt = [...e.instructions, ...e.subs.flatMap(s => [s.title, ...s.lines])].join('\n');
if (/\bask the user\b/i.test(txt)) return { level: 'warn', text: '"ask the user" — a step only the user can do is a task entry' };
});
onPrompts('No prompt leaves a decision open', e => {
const txt = [...e.instructions, ...e.subs.flatMap(s => [s.title, ...s.lines])].join('\n');
const open = /\bTBD\b|\bto be decided\b|\b(confirm|check|agree) with (the )?(user|owner|team|design|product|stakeholders?)\b|\bdecide (whether|which|on|if)\b|\bask (whether|which|if)\b/i.exec(txt);
return open && { level: 'warn', text: `"${open[0]}" — ask it while writing the plan and write the answer in` };
});

// Tasks and tests — the user's own work
const onTasks = (label, fn) => over(manual, label, fn);
onTasks('No task or test carries a marker or session-name line', e => (e.hasMarkerAnywhere || e.hasSessionAnywhere) && { text: `those direct an AI session; a ${e.type} has none` });
onTasks('No task or test carries Setup: or knowledge sub-items', e => e.subs.some(s => s.kind === 'setup' || s.kind === 'knowledge') && { text: `those direct an AI session; a ${e.type} has none` });
onTasks('Every task or test says what to do', e => !e.instructions.some(l => l.trim()) && { text: 'empty body' });
over(manual.filter(e => e.id !== 'sign-off-plan'), 'Every task or test the user kept says why (Kept manual:)', e => !e.instructions.some(l => /^kept manual:\s*\S/i.test(l.trim())) && { text: `no "Kept manual:" line — prompts are the default, so offer this ${e.type} to an AI session or record why the user kept it` });

// Closing pair — a step-level plan only; a roadmap-level document has no steps to review
if (steps.length) {
Expand Down
Loading