@skitterbyte/skitterspec 0.1.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +97 -2
- package/assets/claude-md-section.md +11 -0
- package/assets/core/env.config.json.example +24 -0
- package/assets/core/env.config.md +83 -0
- package/assets/core/linear.config.json.example +39 -0
- package/assets/core/linear.config.md +121 -0
- package/assets/rules/spec-planning.md +29 -11
- package/assets/skills/spec/SKILL.md +61 -13
- package/assets/skills/spec-bug/SKILL.md +0 -4
- package/assets/skills/spec-cancel/SKILL.md +8 -3
- package/assets/skills/spec-complete/SKILL.md +10 -10
- package/assets/skills/spec-env/SKILL.md +57 -0
- package/assets/skills/spec-env-down/SKILL.md +56 -0
- package/assets/skills/spec-go/SKILL.md +39 -3
- package/assets/skills/spec-init/SKILL.md +0 -8
- package/assets/skills/spec-pull/SKILL.md +46 -0
- package/assets/skills/spec-push/SKILL.md +53 -0
- package/assets/skills/spec-ready/SKILL.md +0 -2
- package/assets/skills/spec-review/SKILL.md +2 -2
- package/assets/skills/spec-status/SKILL.md +46 -0
- package/bin/skitterspec.js +0 -0
- package/package.json +6 -6
- package/src/cli.js +497 -2
- package/src/env/config.js +152 -0
- package/src/env/provision.js +76 -0
- package/src/env/registry.js +95 -0
- package/src/env/render.js +26 -0
- package/src/env/resolve.js +184 -0
- package/src/env/teardown.js +94 -0
- package/src/init.js +82 -27
- package/src/prompts.js +23 -12
- package/src/sync/apply.js +66 -0
- package/src/sync/base.js +83 -0
- package/src/sync/compare.js +99 -0
- package/src/sync/config.js +198 -0
- package/src/sync/mcp.js +112 -0
- package/src/sync/normalize.js +249 -0
- package/src/sync/pull.js +84 -0
- package/src/sync/push.js +106 -0
- package/src/sync/write.js +86 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spec-env
|
|
3
|
+
description: Provision an isolated environment for a spec — a git worktree on its own branch + a namespaced Docker stack (isolated containers/networks/volumes + a reserved port block), plus an optional editor/terminal opener. Runs `skitterspec spec-env up` and executes the printed git/docker/open commands. Opt-in — needs specs/.core/env.config.json. Use when the user says "/spec-env", "spin up an environment for <spec>", "give this spec its own worktree/stack", or "isolate <spec>".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /spec-env — provision an isolated environment for a spec
|
|
7
|
+
|
|
8
|
+
Give an in-progress spec its own **git worktree** (a sibling directory on its own
|
|
9
|
+
branch, no stashing) + a **namespaced Docker stack** (`COMPOSE_PROJECT_NAME`
|
|
10
|
+
isolates containers/networks/volumes; `PORT_OFFSET` reserves a port block), so N
|
|
11
|
+
specs run side by side and `main` stays clean. An optional `open.command` then
|
|
12
|
+
opens the worktree however you like.
|
|
13
|
+
|
|
14
|
+
This skill is **opt-in**: it only works when `specs/.core/env.config.json` exists
|
|
15
|
+
(copy `env.config.json.example` to adopt it). If it's absent, tell the user how
|
|
16
|
+
to enable it and stop.
|
|
17
|
+
|
|
18
|
+
## 1. Identify the target spec
|
|
19
|
+
|
|
20
|
+
- Use the spec named as an argument, else the spec **currently in context**. If
|
|
21
|
+
neither is clear, ask which spec.
|
|
22
|
+
|
|
23
|
+
## 2. Plan the environment
|
|
24
|
+
|
|
25
|
+
Run the engine — it allocates the slot (idempotent), persists the registry, and
|
|
26
|
+
**prints** the plan (worktree path, branch, project name, port block, the exact
|
|
27
|
+
commands, the `.env` contents, and the opener):
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
skitterspec spec-env up <spec>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
If it reports the feature isn't enabled, relay that and stop — do not hand-roll a
|
|
34
|
+
worktree/stack.
|
|
35
|
+
|
|
36
|
+
## 3. Execute the printed side effects
|
|
37
|
+
|
|
38
|
+
Run the printed commands **in order**, exactly as printed:
|
|
39
|
+
|
|
40
|
+
1. **`git worktree add …`** — creates the sibling worktree on its branch. It is a
|
|
41
|
+
**sibling** of this checkout, **never nested** inside it. If the worktree
|
|
42
|
+
already exists, the engine prints the *attach* form (no `-b`) — do not clobber
|
|
43
|
+
an existing worktree/branch.
|
|
44
|
+
2. **Write the `.env`** — write the printed `.env` contents into the new
|
|
45
|
+
worktree's env file (default `.env`). Do this *after* the worktree exists.
|
|
46
|
+
3. **`docker compose … up -d`** — only printed when Docker is enabled. Brings the
|
|
47
|
+
namespaced stack up in the spec's reserved port block.
|
|
48
|
+
4. **Opener** — if an `open.command` line was printed, run it (e.g. opens the
|
|
49
|
+
worktree in your editor/terminal). Skipped silently when unset.
|
|
50
|
+
|
|
51
|
+
## 4. Report
|
|
52
|
+
|
|
53
|
+
Echo the summary: worktree path, branch, project name, the allocated slot + port
|
|
54
|
+
block, and whether the stack was brought up. **Idempotent** — re-running attaches
|
|
55
|
+
to the existing slot/worktree and never reallocates.
|
|
56
|
+
|
|
57
|
+
Tear down later with `/spec-env-down <spec>`.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spec-env-down
|
|
3
|
+
description: Tear down a spec's isolated environment — stop and remove its namespaced Docker stack (optionally backing up + dropping volumes), remove its git worktree, and free its slot. Guards refuse teardown on a dirty or unpushed worktree unless --force. Runs `skitterspec spec-env down` and executes the printed commands. Opt-in — needs specs/.core/env.config.json. Use when the user says "/spec-env-down", "tear down <spec>'s environment", "clean up the worktree/stack for <spec>", or "reclaim <spec>'s slot".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /spec-env-down — tear down a spec's isolated environment
|
|
7
|
+
|
|
8
|
+
Reverse `/spec-env`: stop + remove the spec's Docker stack, remove its git
|
|
9
|
+
worktree, and free its slot so the ports/slot are reclaimed. **Volumes are the
|
|
10
|
+
only destructive part** — dropped by default (to reclaim disk) unless
|
|
11
|
+
`--keep-volumes`, and always backed up first when `docker.backupCommand` is set.
|
|
12
|
+
|
|
13
|
+
Opt-in: only works when `specs/.core/env.config.json` exists. If absent, say so
|
|
14
|
+
and stop.
|
|
15
|
+
|
|
16
|
+
## 1. Identify the target spec
|
|
17
|
+
|
|
18
|
+
- Use the spec named as an argument, else the spec **currently in context**. If
|
|
19
|
+
neither is clear, ask which spec.
|
|
20
|
+
|
|
21
|
+
## 2. Plan the teardown
|
|
22
|
+
|
|
23
|
+
Run the engine — it checks the guards, frees the slot, and **prints** the plan:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
skitterspec spec-env down <spec> [--keep-volumes] [--force]
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
- **`--keep-volumes`** — keep the stack's data (plain `down`, no backup, no drop).
|
|
30
|
+
- **`--force`** — override the guards below.
|
|
31
|
+
|
|
32
|
+
## 3. Handle a guard block
|
|
33
|
+
|
|
34
|
+
If the CLI reports **blocked** (the worktree has uncommitted changes or unpushed
|
|
35
|
+
commits), **relay the reason and stop** — do not destroy unreviewed work. Offer
|
|
36
|
+
the user `--force` (and suggest committing/pushing first). Only re-run with
|
|
37
|
+
`--force` when the user explicitly asks.
|
|
38
|
+
|
|
39
|
+
## 4. Execute the printed side effects
|
|
40
|
+
|
|
41
|
+
When not blocked, run the printed commands **in order**, exactly as printed:
|
|
42
|
+
|
|
43
|
+
1. **Backup** (only when a `docker.backupCommand` is configured and volumes are
|
|
44
|
+
being dropped) — writes a dump under `.spec-env/backups/` before anything is
|
|
45
|
+
destroyed.
|
|
46
|
+
2. **`docker compose … down`** — with `--volumes` unless `--keep-volumes`.
|
|
47
|
+
3. **`git worktree remove …`** — removes the sibling worktree.
|
|
48
|
+
|
|
49
|
+
The slot is already freed by the CLI.
|
|
50
|
+
|
|
51
|
+
## 5. Report
|
|
52
|
+
|
|
53
|
+
Confirm what happened: worktree removed, containers down, volumes
|
|
54
|
+
**dropped|kept**, slot freed, and the backup path (if any). If the spec wasn't
|
|
55
|
+
provisioned / was already torn down, the CLI reports a clean **no-op** — relay
|
|
56
|
+
that; it's not an error.
|
|
@@ -18,6 +18,23 @@ description: Promote a spec into active development and implement its first phas
|
|
|
18
18
|
|
|
19
19
|
## 2. Move it into development
|
|
20
20
|
|
|
21
|
+
**If per-spec isolation is enabled** (`specs/.core/env.config.json` exists) and
|
|
22
|
+
the spec doesn't already have a worktree, provision it **first**, so all the
|
|
23
|
+
housekeeping below lands on the spec's branch and never on `main`:
|
|
24
|
+
|
|
25
|
+
- Run `skitterspec spec-env up <name>` (the `/spec-env` engine). It adds a git
|
|
26
|
+
worktree on a branch forked from `main`, and — only when the spec's
|
|
27
|
+
`> **Stack:**` header is `worktree + docker` — also brings up its Docker stack.
|
|
28
|
+
Print the worktree path and the opener command it emits.
|
|
29
|
+
- **Do the rest in the worktree**, on the branch: open it (the printed opener, or
|
|
30
|
+
a fresh Claude session rooted there) or, staying in this session, act on the
|
|
31
|
+
worktree path with absolute paths / `git -C <worktreePath>`. The spec move,
|
|
32
|
+
header edits **and** the phase's code all happen on the branch — so the spec's
|
|
33
|
+
evolution travels with the code it describes and lands in one PR. `main` changes
|
|
34
|
+
only when that branch merges (at `/spec-complete`).
|
|
35
|
+
|
|
36
|
+
Then move the spec (in the worktree when isolated, in place otherwise):
|
|
37
|
+
|
|
21
38
|
- If it isn't already under `specs/in-progress/`, move the whole spec folder
|
|
22
39
|
there. **Use `git mv`** to keep history:
|
|
23
40
|
`git mv "specs/backlog/<name>" "specs/in-progress/<name>"`.
|
|
@@ -27,14 +44,16 @@ description: Promote a spec into active development and implement its first phas
|
|
|
27
44
|
- Set the **Developer** header field if it's still `—`: use `git config user.name`.
|
|
28
45
|
- Append a **State log** row:
|
|
29
46
|
`| <YYYY-MM-DD> | In Progress | in-progress | <git user.name> |`.
|
|
30
|
-
- **
|
|
31
|
-
|
|
47
|
+
- **When isolated:** commit the move and **push the branch** now — that records
|
|
48
|
+
the in-progress state for everyone and fires Linear's automation (when linked).
|
|
32
49
|
|
|
33
50
|
A spec ideally reaches here as `Ready` (via `/spec-ready`), but `/spec-go` works
|
|
34
51
|
on a `Draft` too — just sanity-check it's well-formed before building.
|
|
35
52
|
|
|
36
53
|
If the spec is already in `in-progress`, skip the move and implement the **next
|
|
37
|
-
unfinished phase** instead of Phase 1.
|
|
54
|
+
unfinished phase** instead of Phase 1. (When isolated, subsequent `/spec-go` runs
|
|
55
|
+
happen from inside the worktree — where the spec already sits in `in-progress` on
|
|
56
|
+
the branch — and a re-run of `spec-env up` just re-attaches it.)
|
|
38
57
|
|
|
39
58
|
## 3. Pre-flight — commit prior work, then compact
|
|
40
59
|
|
|
@@ -52,6 +71,23 @@ Before writing any code for this phase, get the workspace and context clean:
|
|
|
52
71
|
the spec file on disk is the source of truth, so nothing is lost. Pause for the
|
|
53
72
|
`/compact`, then implement the phase.
|
|
54
73
|
|
|
74
|
+
## 3b. Sync from Linear first (opt-in)
|
|
75
|
+
|
|
76
|
+
**Only when `specs/.core/linear.config.json` exists** and the spec carries a
|
|
77
|
+
`linear_project_id` in its `00-overview.md` frontmatter. Otherwise skip this
|
|
78
|
+
step — no config means zero change to the flow below.
|
|
79
|
+
|
|
80
|
+
- **Run `/spec-pull` first.** Bring down anything Linear changed since the last
|
|
81
|
+
sync (status, priority, discussion-driven fields) so you build against the
|
|
82
|
+
current shared state, not a stale snapshot. On a conflict it refuses — relay
|
|
83
|
+
that and let the user resolve before continuing; do not `--force` for them.
|
|
84
|
+
- **Commit the refreshed snapshot** into the feature branch (a small
|
|
85
|
+
`chore(spec): pull latest from Linear`-style commit) so the frozen spec rides
|
|
86
|
+
in the PR alongside the code it describes.
|
|
87
|
+
- Linear's GitHub branch/PR automation may now drive status transitions off the
|
|
88
|
+
branch and PR you pushed in step 2 — expect state to move on the Linear side;
|
|
89
|
+
keep any manual status edits minimal to avoid fighting it.
|
|
90
|
+
|
|
55
91
|
## 4. Implement the phase
|
|
56
92
|
|
|
57
93
|
Identify the **first unfinished phase** from the `00-overview.md` phase index,
|
|
@@ -27,14 +27,6 @@ empty so git keeps them:
|
|
|
27
27
|
- `specs/.core/` — project rules (always apply; never moved)
|
|
28
28
|
- `specs/backlog/` `specs/in-progress/` `specs/complete/` `specs/cancelled/`
|
|
29
29
|
|
|
30
|
-
Also ensure the two index files exist (create with just their header comment +
|
|
31
|
-
table header if missing — do not regenerate if present):
|
|
32
|
-
|
|
33
|
-
- `specs/backlog/00-index.md` — live view of backlog (`Added | Spec | Type | Status`);
|
|
34
|
-
`/spec` adds rows, `/spec-go` and `/spec-cancel` remove them.
|
|
35
|
-
- `specs/complete/00-index.md` — append-only completion log (`Completed | Spec | Type`),
|
|
36
|
-
newest first; `/spec-complete` prepends a row.
|
|
37
|
-
|
|
38
30
|
## 2. Version control — keep specs tracked
|
|
39
31
|
|
|
40
32
|
The whole lifecycle lives in git — **everything under `specs/` is tracked**, so
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spec-pull
|
|
3
|
+
description: Pull a spec's linked Linear project into the local spec (Linear → repo), three-way aware. Applies remote-only fields; refuses to clobber local edits on a conflict unless --force (which backs up the local side first). Fetches Linear over MCP and runs `skitterspec spec-sync pull`. Opt-in — needs specs/.core/linear.config.json. Use when the user says "/spec-pull", "pull from Linear", "sync Linear changes down", or "update this spec from Linear".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /spec-pull — bring Linear changes into the spec
|
|
7
|
+
|
|
8
|
+
Linear → repo. Applies fields Linear changed since the last sync (status,
|
|
9
|
+
priority, labels, and co-authored fields), rewrites the committed base, and
|
|
10
|
+
stamps `last_synced_at`. It **refuses** to overwrite a local edit that conflicts
|
|
11
|
+
with a Linear edit unless you pass `--force`.
|
|
12
|
+
|
|
13
|
+
**Opt-in**: only runs when `specs/.core/linear.config.json` exists. If absent,
|
|
14
|
+
tell the user how to enable Linear sync and stop.
|
|
15
|
+
|
|
16
|
+
## 1. Identify the target spec
|
|
17
|
+
|
|
18
|
+
Use the argument, else the spec in context; ask if unclear.
|
|
19
|
+
|
|
20
|
+
## 2. Fetch the Linear project
|
|
21
|
+
|
|
22
|
+
- Read `linear_project_id` from `00-overview.md` frontmatter; if missing, the
|
|
23
|
+
spec isn't linked — stop and point at `/spec`.
|
|
24
|
+
- Discover the Linear MCP project-read tool at runtime. If Linear isn't
|
|
25
|
+
connected, relay the fix and stop — **do nothing destructive**.
|
|
26
|
+
- Call it and write the project JSON to a temp file.
|
|
27
|
+
|
|
28
|
+
## 3. Run the engine
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
skitterspec spec-sync pull <spec> --remote <tempfile> [--force]
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
- **No conflict** — the engine applies remote-only fields to the local snapshot,
|
|
35
|
+
rewrites the base, and stamps the sync. Body fields with no local home yet are
|
|
36
|
+
reported as `deferred` (apply them by hand from Linear if needed).
|
|
37
|
+
- **Conflict** (a co-authored field changed on both sides) — the engine
|
|
38
|
+
**refuses** and lists the fields. Relay that; do not force on the user's behalf.
|
|
39
|
+
- **`--force`** — only when the user explicitly asks. Remote wins after the engine
|
|
40
|
+
backs up the local side under `sync.backupDir` (the reflog). Relay the backup
|
|
41
|
+
path.
|
|
42
|
+
|
|
43
|
+
## 4. Report
|
|
44
|
+
|
|
45
|
+
Relay the git-like summary (applied / deferred / conflicts / backup / base). If
|
|
46
|
+
fields were applied, remind the user to review and commit the refreshed snapshot.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spec-push
|
|
3
|
+
description: Push a spec's local content up to its linked Linear project (repo → Linear), three-way aware and ownership-respecting. Never pushes pull-owned fields or local-only sections; aborts if Linear moved since the last sync unless --force (which backs up the remote side first). Runs `skitterspec spec-sync push` then applies the blessed writes over MCP. Opt-in — needs specs/.core/linear.config.json. Use when the user says "/spec-push", "push to Linear", "sync my spec up to Linear", or "update the Linear project from this spec".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /spec-push — send spec content up to Linear
|
|
7
|
+
|
|
8
|
+
Repo → Linear. Sends the fields the repo owns/co-authors (description, phases,
|
|
9
|
+
tasks per config) up to the linked project. It **never** writes `pull`-owned
|
|
10
|
+
fields (status/priority/labels) or `localOnlySections`, and it **aborts** if
|
|
11
|
+
Linear moved since the last sync (pull first) unless you `--force`.
|
|
12
|
+
|
|
13
|
+
**Opt-in**: only runs when `specs/.core/linear.config.json` exists. If absent,
|
|
14
|
+
tell the user how to enable Linear sync and stop.
|
|
15
|
+
|
|
16
|
+
## 1. Identify the target spec
|
|
17
|
+
|
|
18
|
+
Use the argument, else the spec in context; ask if unclear.
|
|
19
|
+
|
|
20
|
+
## 2. Fetch the Linear project
|
|
21
|
+
|
|
22
|
+
- Read `linear_project_id` from `00-overview.md` frontmatter; if missing, stop
|
|
23
|
+
(link via `/spec` first).
|
|
24
|
+
- Discover the Linear MCP tools at runtime (project read **and** update). If
|
|
25
|
+
Linear isn't connected — or the update tool is missing — relay the fix and stop,
|
|
26
|
+
**writing nothing**.
|
|
27
|
+
- Call the read tool and write the project JSON to a temp file.
|
|
28
|
+
|
|
29
|
+
## 3. Run the engine (the guard)
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
skitterspec spec-sync push <spec> --remote <tempfile> --out <mergedfile> [--force]
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
- **Refused** (`remote-moved` / `concurrent-write` / conflict) — relay the message
|
|
36
|
+
and **stop**. Do not write to Linear. Suggest `/spec-pull` first.
|
|
37
|
+
- **OK** — the engine has confirmed it's safe, rewritten the base, and stamped
|
|
38
|
+
`last_synced_at`. Its summary lists the `written` fields (and any `skipped`
|
|
39
|
+
because they're not pushable).
|
|
40
|
+
- **`--force`** — only when the user explicitly asks. Local wins after the engine
|
|
41
|
+
backs up the remote side under `sync.backupDir`. Relay the backup path.
|
|
42
|
+
|
|
43
|
+
## 4. Apply the blessed writes to Linear
|
|
44
|
+
|
|
45
|
+
Only when step 3 returned OK: for each `written` field, call the Linear update
|
|
46
|
+
tool with that field's local value (e.g. `description` → the project description).
|
|
47
|
+
The engine has already vetted the change and moved the base — so if a Linear
|
|
48
|
+
write fails, re-run `/spec-pull` to reconcile rather than retrying blindly.
|
|
49
|
+
|
|
50
|
+
## 5. Report
|
|
51
|
+
|
|
52
|
+
Relay the git-like summary (written / skipped / backup / base) plus which Linear
|
|
53
|
+
fields you updated.
|
|
@@ -42,8 +42,6 @@ Offer to fix small gaps inline if the user wants; otherwise leave it `Draft`.
|
|
|
42
42
|
`> **Status:** Ready (<YYYY-MM-DD>)`.
|
|
43
43
|
- Append a **State log** row: `| <YYYY-MM-DD> | Ready | backlog | <git user.name> |`
|
|
44
44
|
(no folder change — Ready stays in `backlog`).
|
|
45
|
-
- Update the spec's row in `specs/backlog/00-index.md` — set its Status column to
|
|
46
|
-
`Ready` (the row stays; the spec is still in backlog).
|
|
47
45
|
- Optionally add a **Changelog** note if grooming changed anything substantive.
|
|
48
46
|
|
|
49
47
|
## 4. Report
|
|
@@ -59,8 +59,8 @@ reading the code, do that instead of asking.
|
|
|
59
59
|
Reviewed vs codebase: retargeted Phase 2 onto X, dropped Y (removed), ticked Z
|
|
60
60
|
(already done)`).
|
|
61
61
|
- **Status:** if drift is minor, leave status as-is. If a `Ready` spec needs real
|
|
62
|
-
re-grooming, knock it back to `Draft` (set `> **Status:** Draft
|
|
63
|
-
**State log** row
|
|
62
|
+
re-grooming, knock it back to `Draft` (set `> **Status:** Draft` and append a
|
|
63
|
+
**State log** row).
|
|
64
64
|
|
|
65
65
|
## 5. Report
|
|
66
66
|
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spec-status
|
|
3
|
+
description: Show a spec's sync status against its linked Linear project — a read-only, git-status-style per-field divergence (local-only / remote-only / conflict / in-sync). Fetches the Linear project over MCP and runs `skitterspec spec-sync status`. Changes nothing. Opt-in — needs specs/.core/linear.config.json. Use when the user says "/spec-status", "is this spec in sync with Linear", "what's diverged from Linear", or "show spec sync status".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /spec-status — show a spec's divergence from Linear
|
|
7
|
+
|
|
8
|
+
Read-only. Prints, per field, whether the spec and its linked Linear project have
|
|
9
|
+
diverged since the last sync — the `git status` of the hybrid sync. Writes
|
|
10
|
+
nothing to either side.
|
|
11
|
+
|
|
12
|
+
This skill is **opt-in**: it only runs when `specs/.core/linear.config.json`
|
|
13
|
+
exists. If it's absent, tell the user to copy `linear.config.json.example` →
|
|
14
|
+
`linear.config.json` to enable Linear sync, and stop.
|
|
15
|
+
|
|
16
|
+
## 1. Identify the target spec
|
|
17
|
+
|
|
18
|
+
Use the spec named as an argument, else the spec **currently in context**. If
|
|
19
|
+
neither is clear, ask which spec.
|
|
20
|
+
|
|
21
|
+
## 2. Fetch the Linear project (read-only)
|
|
22
|
+
|
|
23
|
+
- Read the spec's `linear_project_id` from `00-overview.md` frontmatter. If it's
|
|
24
|
+
missing, the spec isn't linked yet — say so and stop (link it via `/spec`).
|
|
25
|
+
- Discover the connected Linear MCP tools at runtime (the project-read tool). If
|
|
26
|
+
Linear isn't connected, relay "connect the `linear` MCP server" and stop — do
|
|
27
|
+
nothing else.
|
|
28
|
+
- Call the project-read tool for that id and write the returned JSON to a temp
|
|
29
|
+
file (e.g. under the OS temp dir).
|
|
30
|
+
|
|
31
|
+
## 3. Run the engine
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
skitterspec spec-sync status <spec> --remote <tempfile>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The engine does the three-way compare (local vs Linear vs the committed base) and
|
|
38
|
+
prints each diverged field with its classification and sync direction. Without
|
|
39
|
+
`--remote` it falls back to a local-vs-base comparison (still read-only).
|
|
40
|
+
|
|
41
|
+
## 4. Report
|
|
42
|
+
|
|
43
|
+
Relay the engine's summary verbatim, then offer the natural next step:
|
|
44
|
+
`/spec-pull` for remote-only changes, `/spec-push` for local-only, and — for a
|
|
45
|
+
`conflict` — resolve locally or use `--force` (which backs up the losing side).
|
|
46
|
+
Never write anything from this skill.
|
package/bin/skitterspec.js
CHANGED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skitterbyte/skitterspec",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Spec-driven-development workflow for Claude Code — installs the spec lifecycle skills, rule, and specs/ folders into any project.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude",
|
|
@@ -27,6 +27,10 @@
|
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"prompts": "^2.4.2"
|
|
29
29
|
},
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "git+https://github.com/skitterbyte/skitterspec.git"
|
|
33
|
+
},
|
|
30
34
|
"scripts": {
|
|
31
35
|
"test": "node --test",
|
|
32
36
|
"changelog": "node scripts/generate-changelog.js",
|
|
@@ -34,9 +38,5 @@
|
|
|
34
38
|
"releases": "node scripts/generate-releases.js",
|
|
35
39
|
"releases:retro": "node scripts/generate-releases.js --retro",
|
|
36
40
|
"version": "node scripts/generate-changelog.js && node scripts/generate-releases.js && git add CHANGELOG.md RELEASES.md"
|
|
37
|
-
},
|
|
38
|
-
"repository": {
|
|
39
|
-
"type": "git",
|
|
40
|
-
"url": "git+https://github.com/skitterbyte/skitterspec.git"
|
|
41
41
|
}
|
|
42
|
-
}
|
|
42
|
+
}
|