@linchpinagency/skills 0.1.9 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/package.json +1 -1
- package/skills/browser-automation/SKILL.md +7 -1
- package/skills/commit-and-release/SKILL.md +8 -7
- package/skills/design-previews/SKILL.md +7 -6
- package/skills/task-tracking/SKILL.md +157 -174
- package/skills/task-tracking/references/clickup-json.md +14 -0
- package/skills/task-tracking/references/clickup-mcp-tools.md +37 -0
- package/skills/task-tracking/references/handoff.md +40 -0
- package/skills/wp-audit/SKILL.md +2 -2
- package/skills/wp-local-setup/SKILL.md +8 -85
- package/skills/wp-local-setup/references/scaffold-baselines.md +83 -0
- package/skills/wp-studio-cli/SKILL.md +5 -0
- package/skills/write-a-linchpin-skill/SKILL.md +7 -0
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ GitHub Copilot, and other compatible coding agents.
|
|
|
12
12
|

|
|
13
13
|
|
|
14
14
|
<!-- x-release-please-start-version -->
|
|
15
|
-
### Latest release: 0.1.
|
|
15
|
+
### Latest release: 0.1.10
|
|
16
16
|
<!-- x-release-please-end -->
|
|
17
17
|
|
|
18
18
|
| Release | Skill standard | Install |
|
|
@@ -259,8 +259,8 @@ A project that wants skills in more than one agent's directory should run
|
|
|
259
259
|
| `engagement-types` | Project mgmt | Tell support, site maintenance, projects, product/plugin work, and pre-sales apart — each lives somewhere different in ClickUp and is planned and closed differently. |
|
|
260
260
|
| `support-triage` | Project mgmt | Run a client support request end to end — clarify the real need, reproduce, judge urgency and scope, fix in the right layer, verify, and close the loop with the requester. |
|
|
261
261
|
| `dependency-updates` | Workflow | Handle the dependency work Renovate can't automerge — majors, breaking changes, failing or conflicted bot PRs, security advisories, `@wordpress/*` package sets. |
|
|
262
|
-
| `commit-and-release` | Workflow | Write
|
|
263
|
-
| `task-tracking` | Workflow | Tie every unit of work to a ClickUp task (or explicit `NO-TASK`) with minimal friction via the ClickUp MCP — resolve/search a task, create one on request ("create an issue" means ClickUp, not GitHub), update
|
|
262
|
+
| `commit-and-release` | Workflow | Write commit messages and PR titles that satisfy the repo's own commitlint rules, and stay out of release-please's way (it owns versions and `CHANGELOG.md`). Branch naming lives in `task-tracking`. |
|
|
263
|
+
| `task-tracking` | Workflow | Tie every unit of work to a ClickUp task (or explicit `NO-TASK`) with minimal friction via the ClickUp MCP — resolve/search a task, create one on request ("create an issue" means ClickUp, not GitHub), split work that spans sessions or PRs into parent + subtasks, name the branch, update the task when the work lands, and carry the task key in the commit scope. |
|
|
264
264
|
| `write-a-linchpin-skill` | Meta | The house standard for authoring skills in this library — placement test, tier model, required frontmatter, the section skeleton, and the four house rules. Enforced by `scripts/validate-skills.mjs`. |
|
|
265
265
|
|
|
266
266
|
_(More WordPress, React, Cloudflare Workers, marketing, and design skills to come.)_
|
package/package.json
CHANGED
|
@@ -13,7 +13,10 @@ parallel runs.
|
|
|
13
13
|
|
|
14
14
|
Skills that need a browser ([`web-qa`](../web-qa/SKILL.md),
|
|
15
15
|
[`wp-audit`](../wp-audit/SKILL.md), [`design-previews`](../design-previews/SKILL.md))
|
|
16
|
-
reference this rather than each choosing their own way in.
|
|
16
|
+
reference this rather than each choosing their own way in. **The one exception is a local
|
|
17
|
+
Studio site**, whose MCP has its own `take_screenshot` and `inspect_design` against PHP-WASM
|
|
18
|
+
— that isn't a browser and doesn't come through this ladder; see
|
|
19
|
+
[`wp-studio-cli`](../wp-studio-cli/SKILL.md).
|
|
17
20
|
|
|
18
21
|
## When to use
|
|
19
22
|
|
|
@@ -81,6 +84,9 @@ session and are not part of this ladder.
|
|
|
81
84
|
- **Never store credentials, cookies, or auth state in the repo.** Use the browser's existing
|
|
82
85
|
session or a gitignored auth file.
|
|
83
86
|
- **Never navigate anywhere the task didn't call for.** Stay on the target application.
|
|
87
|
+
- **Never reach for `claude-in-chrome` tools.** They fight the Chrome DevTools MCP for the
|
|
88
|
+
same browser session; the ladder above is the whole set. This is stated here as well as in
|
|
89
|
+
the ladder because it's the one rule another skill is most likely to trip over.
|
|
84
90
|
- If the browser tooling fails twice in a row, stop and report it rather than cycling through
|
|
85
91
|
variations of the same call.
|
|
86
92
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: commit-and-release
|
|
3
|
-
description: Write
|
|
4
|
-
version: 1.
|
|
3
|
+
description: Write commit messages and PR titles that satisfy a Linchpin repo's own commitlint rules, and stay out of the way of release-please, which owns versions and CHANGELOG.md. Use when composing a commit message, when commitlint or a husky hook rejects one, when opening a PR, when asked how a change gets released or deployed, or before touching a version number anywhere. Not for running lint or tests — use `quality-gates`. Not for naming the branch or resolving the task key in the scope — use `task-tracking`.
|
|
4
|
+
version: 1.1.0
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Commit and release
|
|
@@ -17,20 +17,21 @@ Two pieces of automation own this pipeline, and both bite when you guess:
|
|
|
17
17
|
|
|
18
18
|
## When to use
|
|
19
19
|
|
|
20
|
-
- Composing a commit message
|
|
20
|
+
- Composing a commit message or PR title.
|
|
21
21
|
- A commit was rejected by commitlint or a husky hook.
|
|
22
22
|
- The user asks how a change reaches staging or production.
|
|
23
23
|
- Anything is about to touch a version number or `CHANGELOG.md`.
|
|
24
24
|
- Reviewing or merging a release PR.
|
|
25
25
|
|
|
26
26
|
**Not this skill:** running lint/tests before the commit — [`quality-gates`](../quality-gates/SKILL.md).
|
|
27
|
-
|
|
27
|
+
Naming the branch, and finding or creating the task whose key goes in the scope —
|
|
28
|
+
[`task-tracking`](../task-tracking/SKILL.md).
|
|
28
29
|
|
|
29
30
|
## Owns
|
|
30
31
|
|
|
31
|
-
Canonical for: commit message grammar,
|
|
32
|
-
|
|
33
|
-
[`task-tracking`](../task-tracking/SKILL.md)
|
|
32
|
+
Canonical for: commit message grammar, PR-title rules, and the boundary between what you
|
|
33
|
+
write and what release-please generates. Defers task resolution **and branch naming** to
|
|
34
|
+
[`task-tracking`](../task-tracking/SKILL.md), verification to [`quality-gates`](../quality-gates/SKILL.md).
|
|
34
35
|
|
|
35
36
|
## Preflight — the rules are per-repo
|
|
36
37
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: design-previews
|
|
3
|
-
description: Generate three genuinely different visual directions as self-contained HTML previews, screenshot them at desktop and mobile
|
|
3
|
+
description: Generate three genuinely different visual directions as self-contained HTML previews, screenshot them at desktop and mobile, and get the client's pick before any theme or block work starts. Use when kicking off a design, when someone asks for design options or mockups, when a brief is vague and needs something to react to, or before building a homepage or landing page. Not for auditing an existing design — use `wp-audit`. Not for choosing a browser tool — use `browser-automation`.
|
|
4
4
|
version: 1.1.0
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -27,7 +27,8 @@ and [`wp-block-conventions`](../wp-block-conventions/SKILL.md).
|
|
|
27
27
|
## Owns
|
|
28
28
|
|
|
29
29
|
Canonical for: the brief template, how directions are differentiated, preview output rules,
|
|
30
|
-
the review loop, and the handoff. Implementation belongs to the skills above
|
|
30
|
+
the review loop, and the handoff. Implementation belongs to the skills above; getting a
|
|
31
|
+
browser to screenshot with belongs to [`browser-automation`](../browser-automation/SKILL.md).
|
|
31
32
|
|
|
32
33
|
## Preflight — confirm the brief first
|
|
33
34
|
|
|
@@ -68,10 +69,10 @@ three palettes of one layout still isn't.
|
|
|
68
69
|
gitignored; the repo is `wp-content` and previews must never ship). One file per
|
|
69
70
|
direction, generated in parallel when the harness supports it.
|
|
70
71
|
→ `design-1.html`, `design-2.html`, `design-3.html` exist and open standalone.
|
|
71
|
-
3. **Screenshot each at desktop and mobile.**
|
|
72
|
-
`
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
3. **Screenshot each at desktop and mobile.** Get a browser via
|
|
73
|
+
[`browser-automation`](../browser-automation/SKILL.md), which owns the tool choice and its
|
|
74
|
+
order — navigate to the `file://` path, set each viewport, capture. Don't pick a browser
|
|
75
|
+
tool here. → Six images: three directions × two widths.
|
|
75
76
|
4. **Present for a decision** — each direction as name, file path, screenshot, and one line
|
|
76
77
|
on what makes it different. Offer exactly three responses: pick one, pick one with
|
|
77
78
|
modifications, or regenerate all three.
|
|
@@ -1,59 +1,77 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: task-tracking
|
|
3
|
-
description: Associate every unit of work with a task in Linchpin's task platform (currently ClickUp, via the ClickUp MCP) with the least friction, update it when the work lands, and leave a handoff when stopping mid-flight. Use whenever starting work, creating a TODO, preparing to commit, finishing a change, or pausing work someone else may pick up — and whenever anyone says "create an issue", "create a task", "file a ticket", or "log a bug", all of which mean a ClickUp task unless they name GitHub.
|
|
4
|
-
version: 1.
|
|
3
|
+
description: Associate every unit of work with a task in Linchpin's task platform (currently ClickUp, via the ClickUp MCP) with the least friction, update it when the work lands, and leave a handoff when stopping mid-flight. Use whenever starting work, creating a TODO, scoping something that will span multiple sessions or PRs, preparing to commit, finishing a change, or pausing work someone else may pick up — and whenever anyone says "create an issue", "create a task", "file a ticket", or "log a bug", all of which mean a ClickUp task unless they name GitHub. If no task exists, confirm NO-TASK and keep working; the commit scope carries the task key (e.g. LINCHPIN-5113) or NO-TASK.
|
|
4
|
+
version: 1.4.0
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Task tracking (ClickUp)
|
|
8
8
|
|
|
9
|
-
**Goal: get work into the task system with the least friction, while never blocking the
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
**Goal: get work into the task system with the least friction, while never blocking the user
|
|
10
|
+
from working.** Every unit of work is either tied to a ClickUp task (its commits carry the
|
|
11
|
+
task key) or explicitly marked **NO-TASK**. The user always chooses; you make the right thing
|
|
12
|
+
the easy thing.
|
|
13
13
|
|
|
14
|
-
The platform is currently **ClickUp**, driven through the **ClickUp MCP
|
|
15
|
-
specifics in the tool calls
|
|
16
|
-
platform change.
|
|
14
|
+
The platform is currently **ClickUp**, driven through the **ClickUp MCP** — keep the ClickUp
|
|
15
|
+
specifics in the tool calls, so the workflow below survives a platform change.
|
|
17
16
|
|
|
18
17
|
## When to use
|
|
19
18
|
|
|
20
19
|
- Starting any unit of work, before cutting a branch.
|
|
21
20
|
- **Anyone asking for an issue, task, ticket, bug, or backlog item to be created** — in any
|
|
22
21
|
wording. See *"Create an issue" means ClickUp* below.
|
|
22
|
+
- **Scoping work that won't fit one sitting** — multiple PRs, multiple sessions, or a long
|
|
23
|
+
list of distinct action items. See step 2.
|
|
23
24
|
- Opening a local TODO that should exist in the task system too.
|
|
24
25
|
- Preparing to commit and needing the scope key.
|
|
25
26
|
- Finishing work — the task needs its status and a pointer to the PR.
|
|
26
27
|
|
|
27
|
-
**Not this skill:** the commit message grammar and release
|
|
28
|
+
**Not this skill:** the commit message grammar and release behavior —
|
|
28
29
|
[`commit-and-release`](../commit-and-release/SKILL.md). Running checks before you commit —
|
|
29
|
-
[`quality-gates`](../quality-gates/SKILL.md).
|
|
30
|
+
[`quality-gates`](../quality-gates/SKILL.md). Which space and folder a task belongs in —
|
|
31
|
+
[`engagement-types`](../engagement-types/SKILL.md).
|
|
30
32
|
|
|
31
33
|
## Owns
|
|
32
34
|
|
|
33
|
-
Canonical for: resolving, creating, and updating the task;
|
|
34
|
-
commits; branch naming; and the PR ↔ task link.
|
|
35
|
-
than the scope* belongs to
|
|
35
|
+
Canonical for: resolving, creating, and updating the task; how work is split across tasks
|
|
36
|
+
and subtasks; the **scope key** that goes in commits; branch naming; and the PR ↔ task link.
|
|
37
|
+
Everything about the commit message *other than the scope* belongs to
|
|
38
|
+
[`commit-and-release`](../commit-and-release/SKILL.md).
|
|
39
|
+
|
|
40
|
+
## Preflight
|
|
41
|
+
|
|
42
|
+
Establish three things before the first ClickUp call. None of them blocks the work:
|
|
43
|
+
|
|
44
|
+
| Check | How | When it fails |
|
|
45
|
+
| --- | --- | --- |
|
|
46
|
+
| **Is the ClickUp MCP connected?** | Are `clickup_*` tools present in this session? | **Say so once, out loud** — "no ClickUp MCP in this session, so this is NO-TASK" — then work as NO-TASK |
|
|
47
|
+
| **Is the routing pinned?** | `.clickup.json` at the repo root, else a ClickUp section in `CLAUDE.md`/`AGENTS.md` | Fall back to the hierarchy lookup in step 4, then offer to write the file |
|
|
48
|
+
| **Which Space?** | Infer from the git remote or repo name (repo `linchpin.com` → Space **Linchpin**) | Widen to a scoped Space picker — never dump the whole hierarchy |
|
|
49
|
+
|
|
50
|
+
**A missing MCP is a reportable condition, not a silent skip.** A user can act on "I couldn't
|
|
51
|
+
reach ClickUp"; they can't act on commits that quietly say `NO-TASK`. Same for a pinned list
|
|
52
|
+
id that no longer resolves — say it and re-look-up rather than falling through to the default
|
|
53
|
+
list. Orientation beyond ClickUp is [`project-context`](../project-context/SKILL.md), which
|
|
54
|
+
defers back here for the Space.
|
|
36
55
|
|
|
37
56
|
## "Create an issue" means ClickUp
|
|
38
57
|
|
|
39
58
|
**"Issue", "task", "ticket", "bug", "backlog item" — all of them mean a ClickUp task here.**
|
|
40
|
-
Asked to create one, run the creation flow in step
|
|
41
|
-
|
|
59
|
+
Asked to create one, run the creation flow in step 4. Being in a GitHub repo, reviewing a PR,
|
|
60
|
+
or reading `gh` output does not make "create an issue" mean a GitHub issue. Which space,
|
|
42
61
|
folder, and (for multi-site clients) which site it lands in is
|
|
43
62
|
[`engagement-types`](../engagement-types/SKILL.md)'s call.
|
|
44
63
|
|
|
45
|
-
**A GitHub issue only when GitHub is named** — "open a *GitHub* issue", "
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
once with `AskUserQuestion`, recommending ClickUp.
|
|
64
|
+
**A GitHub issue only when GitHub is named** — "open a *GitHub* issue", "`gh issue create`".
|
|
65
|
+
Use `gh issue create`; if it's work Linchpin will do, create the ClickUp task too and
|
|
66
|
+
cross-link them (issue body → `app.clickup.com/t/<KEY>`; `clickup_create_comment` → issue
|
|
67
|
+
URL). ClickUp stays the system of record. For the genuinely ambiguous — a public repo where
|
|
68
|
+
issues *are* the tracker — ask once with `AskUserQuestion`, recommending ClickUp.
|
|
51
69
|
|
|
52
70
|
## Vocabulary
|
|
53
71
|
|
|
54
72
|
- **Task key / issue key** — ClickUp's *custom ID*, e.g. `LINCHPIN-5113`. Space-scoped, so
|
|
55
|
-
prefixes differ per space
|
|
56
|
-
|
|
73
|
+
prefixes differ per space. This is what goes in commits — **not** the internal id
|
|
74
|
+
(`86badg2te`), though `clickup_get_task` accepts either.
|
|
57
75
|
- **NO-TASK** — the sentinel used in the commit scope when work has no associated task.
|
|
58
76
|
|
|
59
77
|
## Workflow
|
|
@@ -66,192 +84,153 @@ Try these in order; stop at the first that succeeds:
|
|
|
66
84
|
`app.clickup.com/t/...` URL) → `clickup_get_task` to confirm it exists. Capture its
|
|
67
85
|
`custom_id`, `name`, and `status`. Done.
|
|
68
86
|
2. **No reference given → search before asking.** Derive keywords from the work and
|
|
69
|
-
`clickup_search` (or `clickup_filter_tasks`), narrowed to the
|
|
70
|
-
don't trawl
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
`NO-TASK`.
|
|
76
|
-
- **Create a task now** — run the creation flow below, then use the new key.
|
|
77
|
-
- The user can also paste a key they had in mind.
|
|
87
|
+
`clickup_search` (or `clickup_filter_tasks`), narrowed to the Space you established in
|
|
88
|
+
Preflight so you don't trawl the whole workspace. Prefer open/active statuses. If there
|
|
89
|
+
are plausible matches, present the top few and let the user pick or reject.
|
|
90
|
+
3. **Still nothing → ask, don't assume.** `AskUserQuestion` with three ways out: **work as
|
|
91
|
+
NO-TASK** (recommended for quick/throwaway work), **create a task now** (the flow in step
|
|
92
|
+
4), or paste a key they had in mind.
|
|
78
93
|
|
|
79
94
|
**Never block work.** NO-TASK is a first-class, always-available choice.
|
|
80
95
|
|
|
81
|
-
Record the resolved key (or `NO-TASK`)
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
this change — see **Branch & PR**.
|
|
96
|
+
Record the resolved key (or `NO-TASK`) and reuse it for every commit in this unit of work.
|
|
97
|
+
When you open a local TODO with `TaskCreate`, put the key in the task text so the local list
|
|
98
|
+
and ClickUp stay aligned.
|
|
85
99
|
|
|
86
|
-
### 2.
|
|
100
|
+
### 2. Right-size the tracking (before cutting the branch)
|
|
87
101
|
|
|
88
|
-
|
|
89
|
-
`AskUserQuestion`): **"Create a ClickUp task for this before committing?"**
|
|
102
|
+
One task is the default and usually right. But when scoping reveals work that will
|
|
90
103
|
|
|
91
|
-
- **
|
|
92
|
-
- **
|
|
104
|
+
- **span more than one session**, or plausibly **exhaust this context window**, or
|
|
105
|
+
- need **more than one PR**, or
|
|
106
|
+
- carry **a large number of distinct action items**,
|
|
93
107
|
|
|
94
|
-
|
|
108
|
+
then one task can't hold the state, and a plan that lives only in the chat dies with the
|
|
109
|
+
session. Confirm the shape with the user — once, with `AskUserQuestion`:
|
|
95
110
|
|
|
96
|
-
|
|
111
|
+
| Shape | Use when | How |
|
|
112
|
+
| --- | --- | --- |
|
|
113
|
+
| **One task** | Multi-step, but one sitting and one PR | The default; nothing extra to do |
|
|
114
|
+
| **Parent + a subtask per step** | Steps land in separate commits or PRs, or someone else may pick one up | Create the parent, then each subtask via `clickup_create_task`'s `parent` |
|
|
115
|
+
| **Keep the plan local** | Exploratory work whose shape will change | `TaskCreate` only — revisit if it grows |
|
|
116
|
+
|
|
117
|
+
- **Every item carries its own "done when"** in its description. A subtask named "Fix the
|
|
118
|
+
thing" with no acceptance line is a reminder, not a handoff.
|
|
119
|
+
- **The scope key is the parent's**, unless a subtask genuinely owns its own PR — then that
|
|
120
|
+
subtask's key scopes those commits and the parent tracks the whole.
|
|
121
|
+
- **Splitting late is fine.** If one task turns out bigger than it looked, come back here.
|
|
122
|
+
|
|
123
|
+
### 3. Before committing, if NO-TASK — offer to create one
|
|
124
|
+
|
|
125
|
+
When the work is complete and you're about to commit a NO-TASK change, ask once (via
|
|
126
|
+
`AskUserQuestion`): **"Create a ClickUp task for this before committing?"** No → commit with
|
|
127
|
+
`NO-TASK`. Yes → run the creation flow, then commit with the new key. One prompt at commit
|
|
128
|
+
time; don't nag.
|
|
97
129
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
130
|
+
### 4. Creation flow (least friction)
|
|
131
|
+
|
|
132
|
+
Reached three ways: from step 2 (splitting a larger endeavor), from step 3 (a NO-TASK change
|
|
133
|
+
about to be committed), or directly, when someone just says *"create an issue/task for X"* —
|
|
134
|
+
a standalone request needing no commit or branch behind it.
|
|
101
135
|
|
|
102
136
|
`clickup_create_task` requires a `list_id` and `name`. Resolve the list with the cheapest
|
|
103
137
|
path that works:
|
|
104
138
|
|
|
105
|
-
1. **
|
|
106
|
-
list, and often a
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
4. `clickup_create_task` → read back the new task's **`custom_id`** and use it as the commit
|
|
120
|
-
scope.
|
|
121
|
-
|
|
122
|
-
### 4. Update the task when the work lands
|
|
139
|
+
1. **Use the routing you found in Preflight.** `.clickup.json` pins the Space, a default
|
|
140
|
+
list, and often a source-directory → list map — confirm the destination in one line
|
|
141
|
+
("Create in *Mantle › Modules › Security*?") rather than making the user navigate.
|
|
142
|
+
2. **Otherwise build a scoped picker** from `clickup_get_workspace_hierarchy` — see
|
|
143
|
+
[`references/clickup-json.md`](references/clickup-json.md) for both paths.
|
|
144
|
+
3. **Name + details:** default `name` to the commit subject / work summary and confirm.
|
|
145
|
+
Optionally `assignees: ["me"]` (via `clickup_resolve_assignees`), a `priority`, and a
|
|
146
|
+
`markdown_description` — which is where the "done when" line goes.
|
|
147
|
+
4. `clickup_create_task`, then **read the key back with `clickup_get_task`.** The create
|
|
148
|
+
response carries `custom_id` inconsistently — often `null`, because the key is assigned
|
|
149
|
+
after the task exists. `null` means "not yet", never "this space has no keys", so don't
|
|
150
|
+
fall back to the internal id as your commit scope.
|
|
151
|
+
|
|
152
|
+
### 5. Update the task when the work lands
|
|
123
153
|
|
|
124
154
|
A task that never moves is worse than no task — it makes the board lie. Once the change is
|
|
125
155
|
committed and the PR is open, close the loop in ClickUp:
|
|
126
156
|
|
|
127
|
-
1. **Comment with the pointer.** `clickup_create_comment`
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
2. **Move the status
|
|
131
|
-
They're per-Space/List
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
when the user asked for it.
|
|
157
|
+
1. **Comment with the pointer.** `clickup_create_comment` with the PR URL and a one-line
|
|
158
|
+
summary. This is what makes the task useful to whoever picks it up next — do it even if
|
|
159
|
+
you can't move the status.
|
|
160
|
+
2. **Move the status, but read the valid ones first** (`expand_statuses: true`, or
|
|
161
|
+
`clickup_get_list`). They're per-Space/List and there can be dozens. If none obviously
|
|
162
|
+
matches the state ("PR open, awaiting review"), ask rather than guess.
|
|
163
|
+
3. **Don't close what you can't verify.** An open PR is *in review*, not done — terminal
|
|
164
|
+
statuses need the user's word or a deploy you observed.
|
|
165
|
+
4. **Subtasks close as they land; the parent closes last.** Moving a parent while its
|
|
166
|
+
subtasks are open is the same lie as never moving anything.
|
|
167
|
+
5. **Time tracking is opt-in** — `clickup_add_time_entry` only when asked.
|
|
139
168
|
|
|
140
169
|
For `NO-TASK` work there's nothing to update — skip this step silently.
|
|
141
170
|
|
|
142
|
-
###
|
|
143
|
-
|
|
144
|
-
When work pauses unfinished — end of day, a context switch, or handing off — the task is
|
|
145
|
-
where the state belongs. Not a local file, not the chat: the task is what a teammate opens.
|
|
146
|
-
|
|
147
|
-
Post one `clickup_create_comment` with these five things, and nothing else:
|
|
148
|
-
|
|
149
|
-
```markdown
|
|
150
|
-
**Handoff — <date>**
|
|
151
|
-
- **Done:** <what actually works now, and where it's committed or pushed>
|
|
152
|
-
- **In progress:** <what's half-built, and which files>
|
|
153
|
-
- **Open decisions:** <what needs an answer before continuing, and the options>
|
|
154
|
-
- **Where:** branch `<branch>`, PR <link or "none yet">, environment <local|staging|prod>
|
|
155
|
-
- **Next step:** <the single next action, concrete enough to start from cold>
|
|
156
|
-
```
|
|
171
|
+
### 6. Session handoff (when you stop mid-flight)
|
|
157
172
|
|
|
158
|
-
|
|
173
|
+
When work pauses unfinished, the state belongs on the task — not in a local file and not in
|
|
174
|
+
the chat. Post one `clickup_create_comment` covering **done / in progress / open decisions /
|
|
175
|
+
where (branch, PR, environment) / next step**, written for someone who wasn't here, and
|
|
176
|
+
commit or stash first so it points at something real.
|
|
159
177
|
|
|
160
|
-
|
|
161
|
-
history.
|
|
162
|
-
- **Be honest about what's unfinished.** A handoff that overstates progress costs more than
|
|
163
|
-
no handoff.
|
|
164
|
-
- **One handoff comment per pause**, not a running log — supersede the previous one by
|
|
165
|
-
posting a fresh comment rather than editing history.
|
|
166
|
-
- Uncommitted work is not a handoff. Commit or stash it first and say which
|
|
167
|
-
([`commit-and-release`](../commit-and-release/SKILL.md)).
|
|
178
|
+
Template and the rules that make it actionable: [`references/handoff.md`](references/handoff.md).
|
|
168
179
|
|
|
169
|
-
##
|
|
180
|
+
## Scope, branch & PR
|
|
170
181
|
|
|
171
|
-
**Scope = the task key or `NO-TASK`.** That is this skill's half of the message:
|
|
182
|
+
**Scope = the task key or `NO-TASK`.** That is this skill's half of the commit message:
|
|
172
183
|
|
|
173
184
|
```
|
|
174
185
|
feat(LINCHPIN-5113): Add cloudflare email sending on launch
|
|
175
|
-
chore(NO-TASK): Tidy editorconfig and ignore rules
|
|
176
186
|
```
|
|
177
187
|
|
|
178
|
-
Everything else
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
-
|
|
194
|
-
- With a task: **`issue/<ISSUE-KEY>`** — the ClickUp custom ID, e.g. `issue/LINCHPIN-5113`.
|
|
195
|
-
- NO-TASK: **`no-task/<short-kebab-slug>`** describing the change (a bare `issue/no-task`
|
|
196
|
-
would collide across changes).
|
|
197
|
-
- Started NO-TASK, then created a task before pushing? Rename the branch to match:
|
|
198
|
-
`git branch -m issue/<ISSUE-KEY>`.
|
|
199
|
-
- **Pull request** (head = your branch, base = `main`):
|
|
200
|
-
- Title follows the commit convention: `type(<ISSUE-KEY | NO-TASK>): subject`.
|
|
201
|
-
- Body **links the ClickUp task** — paste `https://app.clickup.com/t/<ISSUE-KEY>` and the
|
|
202
|
-
key so GitHub ↔ ClickUp stay connected. For NO-TASK, note there's no task.
|
|
203
|
-
- Keep every commit on the branch using the same scope.
|
|
188
|
+
Everything else — allowed types, sentence case, punctuation limits, breaking changes, release
|
|
189
|
+
commits — is [`commit-and-release`](../commit-and-release/SKILL.md). One note about the *key*
|
|
190
|
+
rather than the grammar: a trailing PR number (`… (#758)`) is appended by the PR/release flow,
|
|
191
|
+
not by hand.
|
|
192
|
+
|
|
193
|
+
Work happens on a dedicated branch opened as a PR against the base branch (usually `main`) —
|
|
194
|
+
never commit straight to `main`.
|
|
195
|
+
|
|
196
|
+
- **Branch naming**, cut from an up-to-date `main`: **`issue/<custom_id>`** — the ClickUp
|
|
197
|
+
custom ID verbatim (`issue/LINCHPIN-5113`), never the internal id and never a slug. Without
|
|
198
|
+
a task, **`no-task/<short-kebab-slug>`**, since a bare `issue/no-task` would collide. Created
|
|
199
|
+
a task after starting NO-TASK? `git branch -m issue/<custom_id>`.
|
|
200
|
+
- **The PR body links the ClickUp task** — paste `https://app.clickup.com/t/<custom_id>` and
|
|
201
|
+
the key so GitHub ↔ ClickUp stay connected; for NO-TASK, note there's no task. The title
|
|
202
|
+
follows the commit convention, whose grammar is `commit-and-release`'s.
|
|
203
|
+
- Keep every commit on the branch using the same scope.
|
|
204
204
|
|
|
205
205
|
## Reducing friction
|
|
206
206
|
|
|
207
|
-
- **Pin the routing per project in `.clickup.json
|
|
208
|
-
the
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
207
|
+
- **Pin the routing per project in `.clickup.json`** — the Space, a default list, and (where
|
|
208
|
+
the board mirrors the code) a directory → list map, so creation is a one-line confirm
|
|
209
|
+
instead of navigation. Schema, worked example, and packaging notes:
|
|
210
|
+
[`references/clickup-json.md`](references/clickup-json.md). The ids live in that project's
|
|
211
|
+
repo, never in this shared library.
|
|
212
212
|
- **Write the file when you had to look it up.** Resolving a list the slow way is the moment
|
|
213
213
|
to offer to pin it — otherwise the next agent pays the same cost.
|
|
214
214
|
- **Remember the last-used list** within a session and reuse it.
|
|
215
|
-
- **
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
## Gotchas
|
|
220
|
-
|
|
221
|
-
- **"Issue" is not a GitHub word here.** Route it to ClickUp unless GitHub was named.
|
|
222
|
-
- **Search before creating** — avoid duplicate tasks; an open task often already exists.
|
|
223
|
-
- **Don't dump the hierarchy.** 36 spaces is overwhelming; always scope `space_ids` and go
|
|
224
|
-
only as deep as you need (`max_depth`).
|
|
225
|
-
- **Use `custom_id` in commits**, never the internal id (`86badg2te`).
|
|
226
|
-
- **Custom-ID prefixes are space-specific** — read the prefix off the task; don't assume
|
|
227
|
-
`LINCHPIN-` for non-Linchpin work.
|
|
228
|
-
- **NO-TASK is not failure.** Offer task creation, accept "no", and move on.
|
|
229
|
-
|
|
230
|
-
## Quick reference
|
|
231
|
-
|
|
232
|
-
| Step | Tool |
|
|
233
|
-
| --- | --- |
|
|
234
|
-
| Confirm a given key/URL | `clickup_get_task` (accepts `LINCHPIN-5113` or `86badg2te`) |
|
|
235
|
-
| Find an existing task | `clickup_search` / `clickup_filter_tasks` (scope to the Space) |
|
|
236
|
-
| Build a Space/List picker | `clickup_get_workspace_hierarchy` (`space_ids`, `max_depth: 2`) |
|
|
237
|
-
| Resolve "me"/assignees | `clickup_resolve_assignees` |
|
|
238
|
-
| Create the task | `clickup_create_task` (`list_id` + `name` required) |
|
|
239
|
-
| Branch the work | `git switch -c issue/LINCHPIN-#### main` (or `no-task/<slug>`) |
|
|
240
|
-
| Commit | `type(LINCHPIN-#### | NO-TASK): subject` |
|
|
241
|
-
| Open the PR | `gh pr create` — title `type(KEY): …`, body links `app.clickup.com/t/<KEY>` |
|
|
242
|
-
| Comment on the task | `clickup_create_comment` (PR URL + one-line summary) |
|
|
243
|
-
| Move the status | `clickup_update_task` (valid statuses come from the List) |
|
|
244
|
-
| Hand off mid-flight | `clickup_create_comment` with the five-line handoff block |
|
|
215
|
+
- **Batch the questions** — task-vs-NO-TASK, the split shape, and the list in as few
|
|
216
|
+
`AskUserQuestion` prompts as possible.
|
|
217
|
+
|
|
218
|
+
Call signatures for every step: [`references/clickup-mcp-tools.md`](references/clickup-mcp-tools.md).
|
|
245
219
|
|
|
246
220
|
## Guardrails
|
|
247
221
|
|
|
248
222
|
- **Never open a GitHub issue in place of a ClickUp task.** "Create an issue" means ClickUp;
|
|
249
223
|
`gh issue create` needs the user to have said *GitHub*.
|
|
250
|
-
- **Never invent a task key
|
|
251
|
-
|
|
252
|
-
- **Never
|
|
253
|
-
|
|
254
|
-
- **Never
|
|
224
|
+
- **Never invent a task key**, and never fall back to the internal id (`86badg2te`) because
|
|
225
|
+
the create call returned `custom_id: null` — read it back. Unresolvable means `NO-TASK`.
|
|
226
|
+
- **Never assume the custom-ID prefix** — it's Space-specific; read it off the task rather
|
|
227
|
+
than reaching for `LINCHPIN-` on non-Linchpin work.
|
|
228
|
+
- **Never claim a task exists that you didn't create.** A missing MCP or a failed call gets
|
|
229
|
+
said out loud, not treated as though the board was updated.
|
|
230
|
+
- **Never block the user** waiting for a task decision. NO-TASK is always available and is
|
|
231
|
+
not a failure state; offer creation, accept "no", move on.
|
|
232
|
+
- **Never mark a task complete** on your own judgment, and **never guess a status name** —
|
|
233
|
+
they're Space-specific. An open PR is at most "in review".
|
|
255
234
|
- **Never create a duplicate task** — search first; an open one usually exists.
|
|
256
235
|
- **Never dump the full workspace hierarchy** into a prompt; scope `space_ids` and
|
|
257
236
|
`max_depth`.
|
|
@@ -259,12 +238,16 @@ Work happens on a dedicated branch opened as a PR against the base branch (usual
|
|
|
259
238
|
|
|
260
239
|
## Done
|
|
261
240
|
|
|
241
|
+
- [ ] Preflight ran: MCP availability, routing, and Space established — and any failure was
|
|
242
|
+
**said out loud** rather than silently downgraded.
|
|
262
243
|
- [ ] Any "create an issue/task/ticket" request produced a **ClickUp** task — or a GitHub
|
|
263
244
|
issue only because the user named GitHub, in which case the two are cross-linked.
|
|
264
|
-
- [ ] The unit of work has a resolved task key or an explicit, user-accepted `NO-TASK
|
|
265
|
-
|
|
266
|
-
- [ ]
|
|
267
|
-
|
|
245
|
+
- [ ] The unit of work has a resolved task key or an explicit, user-accepted `NO-TASK`, read
|
|
246
|
+
back from `custom_id` rather than taken from an internal id.
|
|
247
|
+
- [ ] Work spanning sessions, contexts, or PRs was split deliberately with the user, and
|
|
248
|
+
every task or subtask carries a "done when".
|
|
249
|
+
- [ ] The branch matches the key (`issue/<custom_id>` or `no-task/<slug>`), every commit on it
|
|
250
|
+
carries the same scope, and the PR body links `app.clickup.com/t/<custom_id>`.
|
|
268
251
|
- [ ] For task-backed work: a comment with the PR link exists, and the status reflects
|
|
269
252
|
reality without over-claiming completion.
|
|
270
253
|
- [ ] If work is pausing unfinished, a handoff comment exists that a teammate could act on
|
|
@@ -25,6 +25,20 @@ Check in this order, and stop at the first hit:
|
|
|
25
25
|
3. Nothing pinned → fall back to the hierarchy lookup in the main skill, and **offer to write
|
|
26
26
|
`.clickup.json`** once the list has been resolved, so the next agent doesn't repeat the work
|
|
27
27
|
|
|
28
|
+
## When nothing is pinned — the picker
|
|
29
|
+
|
|
30
|
+
Falling back to a lookup is fine; doing it unscoped is not. `clickup_get_workspace_hierarchy`
|
|
31
|
+
will happily return dozens of spaces and bury the prompt.
|
|
32
|
+
|
|
33
|
+
1. Call it with `max_depth: 2` and **`space_ids` set to the likely Space**, so you get Folders
|
|
34
|
+
+ Lists for one space rather than the whole workspace.
|
|
35
|
+
2. Offer the candidate Lists via `AskUserQuestion` — e.g. `linchpin.com › Development`,
|
|
36
|
+
`linchpin.com › Deploy`, `Internal Projects › …`.
|
|
37
|
+
3. Only widen to a Space picker first when the Space genuinely can't be inferred from the git
|
|
38
|
+
remote or repo name.
|
|
39
|
+
|
|
40
|
+
Then write the file, so the next agent skips all of this.
|
|
41
|
+
|
|
28
42
|
## Schema
|
|
29
43
|
|
|
30
44
|
Every field is optional except `space` and `defaultList` — a two-key file is already useful.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# ClickUp MCP — call signatures
|
|
2
|
+
|
|
3
|
+
The tool for each step of the workflow in [`../SKILL.md`](../SKILL.md). Names are the ClickUp
|
|
4
|
+
MCP's; if these tools aren't in the session, the workflow's Preflight says what to do instead.
|
|
5
|
+
|
|
6
|
+
| Step | Tool |
|
|
7
|
+
| --- | --- |
|
|
8
|
+
| Confirm a given key/URL | `clickup_get_task` (accepts `LINCHPIN-5113` or `86badg2te`) |
|
|
9
|
+
| Find an existing task | `clickup_search` / `clickup_filter_tasks` (scope to the Space) |
|
|
10
|
+
| Build a Space/List picker | `clickup_get_workspace_hierarchy` (`space_ids`, `max_depth: 2`) |
|
|
11
|
+
| Resolve "me"/assignees | `clickup_resolve_assignees` |
|
|
12
|
+
| Create the task | `clickup_create_task` (`list_id` + `name` required) |
|
|
13
|
+
| Create a subtask | `clickup_create_task` with `parent: <parent task id>` |
|
|
14
|
+
| Read the key back | `clickup_get_task` → `custom_id` |
|
|
15
|
+
| List valid statuses | `clickup_get_task` with `expand_statuses: true`, or `clickup_get_list` |
|
|
16
|
+
| Branch the work | `git switch -c issue/LINCHPIN-#### main` (or `no-task/<slug>`) |
|
|
17
|
+
| Commit | `type(LINCHPIN-#### \| NO-TASK): subject` |
|
|
18
|
+
| Open the PR | `gh pr create` — title `type(KEY): …`, body links `app.clickup.com/t/<KEY>` |
|
|
19
|
+
| Comment on the task | `clickup_create_comment` (PR URL + one-line summary) |
|
|
20
|
+
| Move the status | `clickup_update_task` (valid statuses come from the List) |
|
|
21
|
+
| Hand off mid-flight | `clickup_create_comment` with the five-line handoff block |
|
|
22
|
+
|
|
23
|
+
## Two that bite
|
|
24
|
+
|
|
25
|
+
**`custom_id` is assigned after creation.** `clickup_create_task` returns `custom_id: null`
|
|
26
|
+
much of the time — the key exists moments later. Always `clickup_get_task` before using a key
|
|
27
|
+
as a commit scope, and never read `null` as "this space doesn't use custom IDs".
|
|
28
|
+
|
|
29
|
+
**Statuses are per-Space/List and there are often dozens** — a single Linchpin list carries
|
|
30
|
+
open, unstarted, custom, done, and closed variants (`needs estimate`, `needs peer/code
|
|
31
|
+
review`, `in qa/testing`, `blocked by client`, `resolved`, `complete`, …). Read them; never
|
|
32
|
+
guess a name, and never assume `complete` is the only terminal one.
|
|
33
|
+
|
|
34
|
+
## Escaping note for editors of this file
|
|
35
|
+
|
|
36
|
+
The pipe in the commit row is escaped (`\|`). GFM splits table cells on pipes **even inside
|
|
37
|
+
code spans**, so an unescaped one silently truncates the cell.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Session handoff
|
|
2
|
+
|
|
3
|
+
What to post on a task when work pauses unfinished — end of day, a context switch, running
|
|
4
|
+
low on context, or handing to someone else. Step 6 of [`../SKILL.md`](../SKILL.md).
|
|
5
|
+
|
|
6
|
+
The task is where the state belongs. Not a local file, not the chat: the task is what a
|
|
7
|
+
teammate opens.
|
|
8
|
+
|
|
9
|
+
## The comment
|
|
10
|
+
|
|
11
|
+
One `clickup_create_comment`, these five things, nothing else:
|
|
12
|
+
|
|
13
|
+
```markdown
|
|
14
|
+
**Handoff — <date>**
|
|
15
|
+
- **Done:** <what actually works now, and where it's committed or pushed>
|
|
16
|
+
- **In progress:** <what's half-built, and which files>
|
|
17
|
+
- **Open decisions:** <what needs an answer before continuing, and the options>
|
|
18
|
+
- **Where:** branch `<branch>`, PR <link or "none yet">, environment <local|staging|prod>
|
|
19
|
+
- **Next step:** <the single next action, concrete enough to start from cold>
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Rules that keep it useful
|
|
23
|
+
|
|
24
|
+
- **Write it for someone who wasn't here.** No "as discussed", no pronouns pointing at chat
|
|
25
|
+
history, no "the file we changed".
|
|
26
|
+
- **Be honest about what's unfinished.** A handoff that overstates progress costs more than
|
|
27
|
+
no handoff — the next person trusts it and builds on sand.
|
|
28
|
+
- **One handoff per pause, not a running log.** Supersede the previous one by posting a fresh
|
|
29
|
+
comment rather than editing history, so the newest comment is always current.
|
|
30
|
+
- **Uncommitted work is not a handoff.** Commit or stash first and say which, per
|
|
31
|
+
[`commit-and-release`](../../commit-and-release/SKILL.md). A handoff pointing at a dirty
|
|
32
|
+
working tree on someone else's machine is not actionable.
|
|
33
|
+
- **On a parent + subtasks split, the handoff goes on the parent** and names the subtask in
|
|
34
|
+
flight — so one comment still answers "where is this?" without opening every child.
|
|
35
|
+
|
|
36
|
+
## Why the "Next step" line carries the most weight
|
|
37
|
+
|
|
38
|
+
Everything above it is context; that line is the only part that gets someone moving. "Finish
|
|
39
|
+
the migration" fails the test. "Run `npm run validate` — it fails on `wp-audit`'s missing
|
|
40
|
+
README row; add the row and re-run" passes: the next person starts without rereading anything.
|
package/skills/wp-audit/SKILL.md
CHANGED
|
@@ -35,8 +35,8 @@ the code being changed.
|
|
|
35
35
|
| Target | How | Caveat |
|
|
36
36
|
| --- | --- | --- |
|
|
37
37
|
| Local Studio site | [`wp-studio-cli`](../wp-studio-cli/SKILL.md) → `need_for_speed`, `take_screenshot`, `inspect_design` | **Synthetic.** PHP-WASM + SQLite, no CDN, no production cache — good for diagnosis and before/after, not a production claim |
|
|
38
|
-
| Production / staging |
|
|
39
|
-
| Legacy local (wp-env / LocalWP) |
|
|
38
|
+
| Production / staging | A real browser via [`browser-automation`](../browser-automation/SKILL.md) against the live URL; server state via [`wp-pressable`](../wp-pressable/SKILL.md) read-only commands | The only numbers you can quote to a client as real |
|
|
39
|
+
| Legacy local (wp-env / LocalWP) | [`browser-automation`](../browser-automation/SKILL.md) against the local URL | Studio MCP tools won't apply |
|
|
40
40
|
|
|
41
41
|
Resolve two things before measuring: **which environment**, and **which URL path** (default
|
|
42
42
|
`/` if unspecified). State both in the report — an audit without them isn't reproducible.
|
|
@@ -51,68 +51,14 @@ Target shape (the repo root doubles as `wp-content`):
|
|
|
51
51
|
.gitignore # allowlist pattern — see below
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
-
### composer.json
|
|
55
|
-
|
|
56
|
-
```json
|
|
57
|
-
{
|
|
58
|
-
"name": "linchpin/<project>",
|
|
59
|
-
"repositories": [
|
|
60
|
-
{ "type": "composer", "url": "https://wpackagist.org" },
|
|
61
|
-
{ "type": "composer", "url": "https://packagist.linchpin.com" }
|
|
62
|
-
],
|
|
63
|
-
"require": {
|
|
64
|
-
"php": ">=8.2"
|
|
65
|
-
},
|
|
66
|
-
"require-dev": {
|
|
67
|
-
"composer/installers": "^2"
|
|
68
|
-
},
|
|
69
|
-
"extra": {
|
|
70
|
-
"installer-paths": {
|
|
71
|
-
"plugins/{$name}/": ["type:wordpress-plugin"],
|
|
72
|
-
"themes/{$name}/": ["type:wordpress-theme"]
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
```
|
|
54
|
+
### composer.json and .gitignore baselines
|
|
77
55
|
|
|
78
|
-
-
|
|
79
|
-
|
|
80
|
-
- A plugin built **only for this client** is committed to `plugins/` instead (and
|
|
81
|
-
allowlisted in `.gitignore`).
|
|
82
|
-
- Which plugins a project needs is project-specific — don't copy another site's list.
|
|
83
|
-
- Mature projects add the PHP QA stack to `require-dev` (`wp-coding-standards/wpcs`,
|
|
84
|
-
`phpstan/phpstan` + `szepeviktor/phpstan-wordpress`, `php-parallel-lint/php-parallel-lint`,
|
|
85
|
-
`friendsofphp/php-cs-fixer`) — mirror `linchpin/linchpin.com` when setting that up.
|
|
86
|
-
|
|
87
|
-
### .gitignore baseline (allowlist pattern)
|
|
88
|
-
|
|
89
|
-
Ignore everything Composer or the runtime writes; explicitly re-include what's ours:
|
|
90
|
-
|
|
91
|
-
```gitignore
|
|
92
|
-
# Plugins/themes are Composer-installed — commit only project code
|
|
93
|
-
/plugins/*
|
|
94
|
-
!plugins/<project>-functionality/
|
|
95
|
-
!plugins/<project>-functionality/**
|
|
96
|
-
/themes/*
|
|
97
|
-
!themes/<project>/
|
|
98
|
-
!themes/<project>/**
|
|
99
|
-
/vendor
|
|
100
|
-
node_modules
|
|
101
|
-
|
|
102
|
-
# WordPress runtime
|
|
103
|
-
debug.log
|
|
104
|
-
/uploads/
|
|
105
|
-
/upgrade/
|
|
106
|
-
|
|
107
|
-
# WordPress Studio runtime (SQLite) — never commit these
|
|
108
|
-
db.php
|
|
109
|
-
/database
|
|
110
|
-
/mu-plugins/sqlite-database-integration
|
|
111
|
-
mu-plugins/99-studio-loader.php
|
|
112
|
-
```
|
|
56
|
+
Both templates, the package-name conventions for each dependency source, and the allowlist
|
|
57
|
+
trap: [`references/scaffold-baselines.md`](references/scaffold-baselines.md).
|
|
113
58
|
|
|
114
|
-
|
|
115
|
-
|
|
59
|
+
Two things worth knowing before you open it: **which plugins a project needs is
|
|
60
|
+
project-specific** — don't copy another site's list — and the `.gitignore` is an *allowlist*,
|
|
61
|
+
so every committed plugin needs its own re-include pair or git silently ignores it.
|
|
116
62
|
|
|
117
63
|
### The project theme
|
|
118
64
|
|
|
@@ -203,19 +149,6 @@ correct. From here, day-to-day operation is `wp-studio-cli`.
|
|
|
203
149
|
- **Media isn't in git** (`/uploads/` is ignored). Getting real content/uploads locally
|
|
204
150
|
is per-project — check that project's docs.
|
|
205
151
|
|
|
206
|
-
## Quick reference
|
|
207
|
-
|
|
208
|
-
| Task | Command |
|
|
209
|
-
| --- | --- |
|
|
210
|
-
| Start the project theme | see [`wp-theme-baseline`](../wp-theme-baseline/SKILL.md) — child / fresh / fork |
|
|
211
|
-
| Install plugins | `composer install` (repo root) |
|
|
212
|
-
| Add a wordpress.org plugin | `composer require wpackagist-plugin/<slug>` |
|
|
213
|
-
| Add a premium/shared plugin | `composer require linchpin/<slug>` (packagist.linchpin.com) |
|
|
214
|
-
| Build the theme (if it has a build) | `npm run build` in `themes/<project>` (`npm start` to watch) |
|
|
215
|
-
| Symlink repo into Studio | `mv <site>/wp-content <site>/wp-content-studio-default && ln -s <repo> <site>/wp-content` |
|
|
216
|
-
| Start the site | `studio start --skip-browser --path ~/Studio/<project>` |
|
|
217
|
-
| Activate the theme | `studio wp theme activate <project> --path ~/Studio/<project>` |
|
|
218
|
-
| Site URL + credentials | `studio site status --path ~/Studio/<project> --format json` |
|
|
219
152
|
|
|
220
153
|
## Guardrails
|
|
221
154
|
|
|
@@ -231,7 +164,8 @@ correct. From here, day-to-day operation is `wp-studio-cli`.
|
|
|
231
164
|
- **Never commit Composer-installed plugins/themes** — `installer-paths` writes into
|
|
232
165
|
gitignored directories by design.
|
|
233
166
|
- Don't hand-edit versions or `CHANGELOG.md` in a scaffolded repo — release-please owns
|
|
234
|
-
them ([`commit-and-release`](../commit-and-release/SKILL.md))
|
|
167
|
+
them ([`commit-and-release`](../commit-and-release/SKILL.md)), and tie the setup work to a
|
|
168
|
+
task before committing ([`task-tracking`](../task-tracking/SKILL.md)).
|
|
235
169
|
|
|
236
170
|
## Done
|
|
237
171
|
|
|
@@ -241,14 +175,3 @@ correct. From here, day-to-day operation is `wp-studio-cli`.
|
|
|
241
175
|
and the SQLite runtime pieces intact.
|
|
242
176
|
- [ ] The site loads, the project theme is active, and the admin URL/credentials are known.
|
|
243
177
|
- [ ] `.gitignore` allowlists only project code; `git status` is clean of vendored plugins.
|
|
244
|
-
|
|
245
|
-
## Related skills
|
|
246
|
-
|
|
247
|
-
- [`wp-theme-baseline`](../wp-theme-baseline/SKILL.md) — choosing and standing up the project
|
|
248
|
-
theme that lands in `themes/<project>/`.
|
|
249
|
-
- [`wp-studio-cli`](../wp-studio-cli/SKILL.md) — operating the running Studio site (WP-CLI
|
|
250
|
-
passthrough, `eval`, the PHP-WASM `ABSPATH` rule).
|
|
251
|
-
- [`wp-pressable`](../wp-pressable/SKILL.md) — the hosted environments this baseline deploys
|
|
252
|
-
to, and the release-please → `linchpin/actions` pipeline.
|
|
253
|
-
- [`task-tracking`](../task-tracking/SKILL.md) — tie the setup work to a ClickUp task before
|
|
254
|
-
committing.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Scaffold baselines — `composer.json` and `.gitignore`
|
|
2
|
+
|
|
3
|
+
The two file templates a new Linchpin WordPress project repo starts from. Copy, substitute
|
|
4
|
+
`<project>`, then follow Part 1 of [`../SKILL.md`](../SKILL.md).
|
|
5
|
+
|
|
6
|
+
Both encode the same premise: **the repo is `wp-content`**, plugins and themes arrive via
|
|
7
|
+
Composer, and only project-specific code is committed.
|
|
8
|
+
|
|
9
|
+
## `composer.json`
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
{
|
|
13
|
+
"name": "linchpin/<project>",
|
|
14
|
+
"repositories": [
|
|
15
|
+
{ "type": "composer", "url": "https://wpackagist.org" },
|
|
16
|
+
{ "type": "composer", "url": "https://packagist.linchpin.com" }
|
|
17
|
+
],
|
|
18
|
+
"require": {
|
|
19
|
+
"php": ">=8.2"
|
|
20
|
+
},
|
|
21
|
+
"require-dev": {
|
|
22
|
+
"composer/installers": "^2"
|
|
23
|
+
},
|
|
24
|
+
"extra": {
|
|
25
|
+
"installer-paths": {
|
|
26
|
+
"plugins/{$name}/": ["type:wordpress-plugin"],
|
|
27
|
+
"themes/{$name}/": ["type:wordpress-theme"]
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Where dependencies come from:
|
|
34
|
+
|
|
35
|
+
| Source | Package name | Command |
|
|
36
|
+
| --- | --- | --- |
|
|
37
|
+
| wordpress.org plugin | `wpackagist-plugin/<slug>` | `composer require wpackagist-plugin/<slug>` |
|
|
38
|
+
| wordpress.org theme | `wpackagist-theme/<slug>` | `composer require wpackagist-theme/<slug>` |
|
|
39
|
+
| Premium / shared-private | `linchpin/<slug>` | `composer require linchpin/<slug>` |
|
|
40
|
+
| Built only for this client | *not a dependency* | Commit it to `plugins/` and allowlist it below |
|
|
41
|
+
|
|
42
|
+
- **Which plugins a project needs is project-specific** — don't copy another site's list.
|
|
43
|
+
- `installer-paths` writes into `plugins/` and `themes/`, which are gitignored. That's by
|
|
44
|
+
design; CI runs `composer install` at deploy time.
|
|
45
|
+
- Mature projects add the PHP QA stack to `require-dev`: `wp-coding-standards/wpcs`,
|
|
46
|
+
`phpstan/phpstan` + `szepeviktor/phpstan-wordpress`, `php-parallel-lint/php-parallel-lint`,
|
|
47
|
+
`friendsofphp/php-cs-fixer`. Mirror an existing repo that already has it configured rather
|
|
48
|
+
than assembling the versions from scratch.
|
|
49
|
+
|
|
50
|
+
## `.gitignore` (allowlist pattern)
|
|
51
|
+
|
|
52
|
+
Ignore everything Composer or the runtime writes; explicitly re-include what's ours:
|
|
53
|
+
|
|
54
|
+
```gitignore
|
|
55
|
+
# Plugins/themes are Composer-installed — commit only project code
|
|
56
|
+
/plugins/*
|
|
57
|
+
!plugins/<project>-functionality/
|
|
58
|
+
!plugins/<project>-functionality/**
|
|
59
|
+
/themes/*
|
|
60
|
+
!themes/<project>/
|
|
61
|
+
!themes/<project>/**
|
|
62
|
+
/vendor
|
|
63
|
+
node_modules
|
|
64
|
+
|
|
65
|
+
# WordPress runtime
|
|
66
|
+
debug.log
|
|
67
|
+
/uploads/
|
|
68
|
+
/upgrade/
|
|
69
|
+
|
|
70
|
+
# WordPress Studio runtime (SQLite) — never commit these
|
|
71
|
+
db.php
|
|
72
|
+
/database
|
|
73
|
+
/mu-plugins/sqlite-database-integration
|
|
74
|
+
mu-plugins/99-studio-loader.php
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**The allowlist is the part that bites.** Adding a new *committed* plugin later requires its
|
|
78
|
+
own `!plugins/<name>/` **and** `!plugins/<name>/**` pair — without both, the `/plugins/*` rule
|
|
79
|
+
silently keeps it out of git and the omission usually surfaces at deploy.
|
|
80
|
+
|
|
81
|
+
The Studio block matters just as much in the other direction: those four paths are the local
|
|
82
|
+
SQLite database layer. Committing them ships a `db.php` drop-in that shadows a real host's
|
|
83
|
+
MySQL configuration.
|
|
@@ -27,6 +27,11 @@ the fallback and the scripting route.
|
|
|
27
27
|
[`wp-audit`](../wp-audit/SKILL.md). A legacy project on wp-env or LocalWP — use that
|
|
28
28
|
project's tooling ([`quality-gates`](../quality-gates/SKILL.md) detects which).
|
|
29
29
|
|
|
30
|
+
`take_screenshot` and `inspect_design` below are **Studio's own**, rendering PHP-WASM rather
|
|
31
|
+
than driving a browser — enough for markup and layout checks. When you need a *real* browser
|
|
32
|
+
against the Studio URL (actual session state, extensions, console and network behaviour), get
|
|
33
|
+
one via [`browser-automation`](../browser-automation/SKILL.md).
|
|
34
|
+
|
|
30
35
|
## Preflight — pick the interface
|
|
31
36
|
|
|
32
37
|
1. **Try MCP first.** A cheap call like `site_list` confirms it's connected.
|
|
@@ -61,6 +61,13 @@ hand-roll this parse and drift"). If you can't name one, drop to B.
|
|
|
61
61
|
Most skills here are **A or B**. `wordpress-blocks` is the reference B (recipes and grammar
|
|
62
62
|
live in `references/`); this library's own `scripts/validate-skills.mjs` is the C pattern.
|
|
63
63
|
|
|
64
|
+
**What the validator checks:** a body over **200 lines with no `references/` at all** warns —
|
|
65
|
+
that combination is Tier B content held in Tier A. Length alone is never the fault;
|
|
66
|
+
`wordpress-blocks` runs 877 lines across its package and passes, because the
|
|
67
|
+
reference-shaped parts were promoted. **Don't compress prose to clear this warning** —
|
|
68
|
+
promote the templates, command matrices, and schemas. That's the only fix that improves the
|
|
69
|
+
skill rather than just the number.
|
|
70
|
+
|
|
64
71
|
## Step 3 — Write `SKILL.md`
|
|
65
72
|
|
|
66
73
|
### Frontmatter (all required)
|