project-kit-cli 0.1.0__py3-none-any.whl
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.
- project_kit/__init__.py +8 -0
- project_kit/__main__.py +5 -0
- project_kit/agents.py +81 -0
- project_kit/ai_attribution.py +69 -0
- project_kit/approval.py +36 -0
- project_kit/assets/hooks/commit-msg +14 -0
- project_kit/assets/project/workflow.yml +63 -0
- project_kit/assets/skills/pk-decide/SKILL.md +63 -0
- project_kit/assets/skills/pk-discover/SKILL.md +57 -0
- project_kit/assets/skills/pk-handoff/SKILL.md +43 -0
- project_kit/assets/skills/pk-plan/SKILL.md +55 -0
- project_kit/assets/skills/pk-provision/SKILL.md +45 -0
- project_kit/assets/skills/pk-start/SKILL.md +47 -0
- project_kit/assets/skills/pk-workflow/SKILL.md +51 -0
- project_kit/assets/templates/adr.md +32 -0
- project_kit/assets/templates/backlog.example.json +59 -0
- project_kit/assets/templates/brief.md +77 -0
- project_kit/assets/templates/constitution-input.md +78 -0
- project_kit/assets/templates/development-workflow.md +51 -0
- project_kit/assets/templates/github/ISSUE_TEMPLATE/adr.yml +21 -0
- project_kit/assets/templates/github/ISSUE_TEMPLATE/bug.yml +25 -0
- project_kit/assets/templates/github/ISSUE_TEMPLATE/config.yml +1 -0
- project_kit/assets/templates/github/ISSUE_TEMPLATE/epic.yml +15 -0
- project_kit/assets/templates/github/ISSUE_TEMPLATE/feature.yml +22 -0
- project_kit/assets/templates/github/pull_request_template.md +21 -0
- project_kit/assets/templates/interview.md +68 -0
- project_kit/backlog.py +312 -0
- project_kit/cli.py +286 -0
- project_kit/config.py +139 -0
- project_kit/doctor.py +187 -0
- project_kit/fsutil.py +27 -0
- project_kit/gh.py +152 -0
- project_kit/handoff.py +360 -0
- project_kit/help.py +152 -0
- project_kit/installer.py +100 -0
- project_kit/labels.py +17 -0
- project_kit/project_choice.py +127 -0
- project_kit/providers/__init__.py +1 -0
- project_kit/providers/github.py +329 -0
- project_kit/provision.py +260 -0
- project_kit/provision_issues.py +360 -0
- project_kit/state.py +115 -0
- project_kit/templating.py +23 -0
- project_kit/workflow.py +168 -0
- project_kit_cli-0.1.0.dist-info/METADATA +97 -0
- project_kit_cli-0.1.0.dist-info/RECORD +49 -0
- project_kit_cli-0.1.0.dist-info/WHEEL +4 -0
- project_kit_cli-0.1.0.dist-info/entry_points.txt +3 -0
- project_kit_cli-0.1.0.dist-info/licenses/LICENSE +21 -0
project_kit/__init__.py
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"""project-kit: define, plan and set up a project before handing off to Spec Kit."""
|
|
2
|
+
|
|
3
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
__version__ = version("project-kit-cli")
|
|
7
|
+
except PackageNotFoundError: # running from a source tree that was never installed
|
|
8
|
+
__version__ = "0.0.0"
|
project_kit/__main__.py
ADDED
project_kit/agents.py
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""AI coding agents project-kit can hand the terminal over to after ``init``.
|
|
2
|
+
|
|
3
|
+
An agent is whatever reads the installed skills and runs ``/pk-start``. Today that is Claude
|
|
4
|
+
Code only; supporting another one is a new entry in ``AGENTS``.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
import shutil
|
|
9
|
+
import subprocess
|
|
10
|
+
from collections.abc import Callable, Mapping
|
|
11
|
+
from dataclasses import dataclass
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass(frozen=True)
|
|
16
|
+
class Agent:
|
|
17
|
+
id: str
|
|
18
|
+
name: str
|
|
19
|
+
executable: str
|
|
20
|
+
prompt: str # what the agent is started with: the entry-point skill
|
|
21
|
+
install_hint: str
|
|
22
|
+
inside_env: str # environment variable the agent sets in the shells it opens
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
AGENTS = (
|
|
26
|
+
Agent(
|
|
27
|
+
id="claude",
|
|
28
|
+
name="Claude Code",
|
|
29
|
+
executable="claude",
|
|
30
|
+
prompt="/pk-start",
|
|
31
|
+
install_hint="https://claude.com/claude-code",
|
|
32
|
+
inside_env="CLAUDECODE",
|
|
33
|
+
),
|
|
34
|
+
)
|
|
35
|
+
AGENT_IDS = tuple(a.id for a in AGENTS)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def get_agent(agent_id: str) -> Agent:
|
|
39
|
+
return next(a for a in AGENTS if a.id == agent_id)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def is_inside(agent: Agent, env: Mapping[str, str] | None = None) -> bool:
|
|
43
|
+
"""True when we run from a shell opened by this agent: launching it again would nest."""
|
|
44
|
+
return bool((os.environ if env is None else env).get(agent.inside_env))
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def find_executable(agent: Agent) -> str | None:
|
|
48
|
+
return shutil.which(agent.executable)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def choose(
|
|
52
|
+
ask: Callable[[str], str] | None = None,
|
|
53
|
+
out: Callable[[str], None] = print,
|
|
54
|
+
) -> Agent | None:
|
|
55
|
+
"""Ask which agent to open now. Enter takes the first one. ``None``: the user declines."""
|
|
56
|
+
out("\nOpen an AI agent now to continue with /pk-start?")
|
|
57
|
+
for n, agent in enumerate(AGENTS, 1):
|
|
58
|
+
out(f" {n}) {agent.name}")
|
|
59
|
+
none = len(AGENTS) + 1
|
|
60
|
+
out(f" {none}) No, I will do it myself")
|
|
61
|
+
try:
|
|
62
|
+
answer = (ask or input)("Choice [1]: ").strip()
|
|
63
|
+
except EOFError: # no terminal attached: never launch anything
|
|
64
|
+
return None
|
|
65
|
+
if answer == "":
|
|
66
|
+
return AGENTS[0]
|
|
67
|
+
if answer.isdigit() and 1 <= int(answer) <= len(AGENTS):
|
|
68
|
+
return AGENTS[int(answer) - 1]
|
|
69
|
+
return None
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def launch(agent: Agent, root: Path, run: Callable[..., object] = subprocess.run) -> int:
|
|
73
|
+
"""Run the agent in the current terminal, in ``root``, started with its entry skill.
|
|
74
|
+
|
|
75
|
+
Returns the agent's exit code; the terminal is inherited, so it is interactive.
|
|
76
|
+
"""
|
|
77
|
+
exe = find_executable(agent)
|
|
78
|
+
if exe is None:
|
|
79
|
+
raise FileNotFoundError(agent.executable)
|
|
80
|
+
result = run([exe, agent.prompt], cwd=root, check=False)
|
|
81
|
+
return getattr(result, "returncode", 0)
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""Keep AI assistants out of the commit history when the project asks for it.
|
|
2
|
+
|
|
3
|
+
Two layers, because each assistant removes itself in its own way:
|
|
4
|
+
|
|
5
|
+
* Claude Code has its own setting (``attribution`` in ``.claude/settings.json``), which stops
|
|
6
|
+
it from adding the co-author trailer and the "Generated with" line.
|
|
7
|
+
* For any other assistant, and as a safety net, a ``commit-msg`` git hook strips co-author
|
|
8
|
+
trailers that name a known AI tool. It lives in ``.githooks/`` so it is versioned and the
|
|
9
|
+
whole team gets it; it is switched on with ``git config core.hooksPath .githooks``.
|
|
10
|
+
|
|
11
|
+
Both only ever add what is missing; nothing the user wrote is overwritten.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import contextlib
|
|
15
|
+
import json
|
|
16
|
+
import os
|
|
17
|
+
from importlib.resources import files
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
|
|
20
|
+
from project_kit.fsutil import atomic_write_text
|
|
21
|
+
|
|
22
|
+
CLAUDE_SETTINGS = Path(".claude") / "settings.json"
|
|
23
|
+
HOOK = Path(".githooks") / "commit-msg"
|
|
24
|
+
HOOKS_PATH_COMMAND = "git config core.hooksPath .githooks"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def configure_claude(root: Path) -> tuple[Path | None, str]:
|
|
28
|
+
"""Make Claude Code stop signing commits and PRs. Returns (changed file or None, note)."""
|
|
29
|
+
path = root / CLAUDE_SETTINGS
|
|
30
|
+
data: dict = {}
|
|
31
|
+
if path.exists():
|
|
32
|
+
try:
|
|
33
|
+
loaded = json.loads(path.read_text(encoding="utf-8"))
|
|
34
|
+
except json.JSONDecodeError:
|
|
35
|
+
return None, f"{CLAUDE_SETTINGS.as_posix()} is not valid JSON; left alone."
|
|
36
|
+
if not isinstance(loaded, dict):
|
|
37
|
+
return None, f"{CLAUDE_SETTINGS.as_posix()} is not a JSON object; left alone."
|
|
38
|
+
data = loaded
|
|
39
|
+
|
|
40
|
+
attribution = data.get("attribution")
|
|
41
|
+
attribution = dict(attribution) if isinstance(attribution, dict) else {}
|
|
42
|
+
if attribution.get("commit") == "" and attribution.get("pr") == "":
|
|
43
|
+
return None, ""
|
|
44
|
+
attribution["commit"] = ""
|
|
45
|
+
attribution["pr"] = ""
|
|
46
|
+
data["attribution"] = attribution
|
|
47
|
+
atomic_write_text(path, json.dumps(data, indent=2, ensure_ascii=False) + "\n")
|
|
48
|
+
return CLAUDE_SETTINGS, ""
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def install_hook(root: Path) -> tuple[Path | None, str]:
|
|
52
|
+
"""Copy the commit-msg hook unless the project already has one. Returns (new file, note)."""
|
|
53
|
+
dest = root / HOOK
|
|
54
|
+
if dest.exists():
|
|
55
|
+
return None, ""
|
|
56
|
+
script = (files("project_kit") / "assets" / "hooks" / "commit-msg").read_text("utf-8")
|
|
57
|
+
atomic_write_text(dest, script)
|
|
58
|
+
with contextlib.suppress(OSError): # no executable bit on some filesystems (Windows)
|
|
59
|
+
os.chmod(dest, 0o755)
|
|
60
|
+
return HOOK, ""
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def hook_is_active(root: Path) -> bool:
|
|
64
|
+
"""True if git is already pointed at ``.githooks`` in this repository."""
|
|
65
|
+
config = root / ".git" / "config"
|
|
66
|
+
if not config.is_file():
|
|
67
|
+
return False
|
|
68
|
+
text = config.read_text(encoding="utf-8", errors="replace")
|
|
69
|
+
return any("".join(line.split()).lower() == "hookspath=.githooks" for line in text.splitlines())
|
project_kit/approval.py
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""Approval gates: record that the user signed off on a phase."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from project_kit.backlog import load_backlog
|
|
6
|
+
from project_kit.config import load_config
|
|
7
|
+
from project_kit.state import PHASES, State, StateError, load_state, save_state
|
|
8
|
+
from project_kit.workflow import load_workflow
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def approve_phase(root: Path, phase: str) -> State:
|
|
12
|
+
"""Record the approval of ``phase`` in the project state.
|
|
13
|
+
|
|
14
|
+
A gate refuses to open while an earlier enabled gate of ``workflow.yml`` is still open,
|
|
15
|
+
so the plan cannot be approved before the brief. The ``plan`` gate also refuses to open
|
|
16
|
+
unless the backlog on disk is valid, so an approval always refers to a backlog that
|
|
17
|
+
provisioning can use.
|
|
18
|
+
"""
|
|
19
|
+
if phase not in PHASES:
|
|
20
|
+
raise StateError(f"Unknown phase {phase!r}. Phases: {', '.join(PHASES)}")
|
|
21
|
+
load_config(root) # the project must have been initialised
|
|
22
|
+
state = load_state(root)
|
|
23
|
+
open_gates = load_workflow(root).open_gates_before(phase, state)
|
|
24
|
+
if open_gates:
|
|
25
|
+
names = ", ".join(f"{s.id} (/{s.skill})" for s in open_gates)
|
|
26
|
+
raise StateError(
|
|
27
|
+
f"Cannot approve {phase!r} yet: approve first {names}. "
|
|
28
|
+
"To skip a phase, set `enabled: false` on it in .project-kit/workflow.yml."
|
|
29
|
+
)
|
|
30
|
+
if phase == "plan":
|
|
31
|
+
load_backlog(root)
|
|
32
|
+
state.approve(phase)
|
|
33
|
+
if PHASES.index(phase) > PHASES.index(state.phase):
|
|
34
|
+
state.phase = phase
|
|
35
|
+
save_state(root, state)
|
|
36
|
+
return state
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# project-kit: keep AI assistants out of the commit history.
|
|
3
|
+
# Removes "Co-authored-by:" trailers added by AI tools, and their "Generated with" lines.
|
|
4
|
+
# Enable with: git config core.hooksPath .githooks
|
|
5
|
+
file="$1"
|
|
6
|
+
tmp="$file.pk-tmp"
|
|
7
|
+
grep -v -i -E \
|
|
8
|
+
-e '^co-authored-by:.*(claude|anthropic|copilot|openai|chatgpt|codex|gemini|cursor|aider|devin)' \
|
|
9
|
+
-e '^.*generated with.*(claude|copilot|codex|gemini|cursor)' \
|
|
10
|
+
"$file" > "$tmp"
|
|
11
|
+
# grep exits 1 when nothing is left (an empty message): keep that case valid and silent.
|
|
12
|
+
cat "$tmp" > "$file"
|
|
13
|
+
rm -f "$tmp"
|
|
14
|
+
exit 0
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# project-kit workflow: the phases a project goes through before it is handed to Spec Kit.
|
|
2
|
+
# Safe to edit by hand. Same idea as Spec Kit's workflow.yml: an ordered list of steps with
|
|
3
|
+
# review gates, read by the skills to know what comes next.
|
|
4
|
+
#
|
|
5
|
+
# gate: true the phase ends with an explicit approval (`project-kit approve <id>`)
|
|
6
|
+
# enabled: false skip the phase (small projects); later gates stop waiting for it
|
|
7
|
+
#
|
|
8
|
+
# The order is fixed and the ids are the ones project-kit knows; only `enabled`, `gate`,
|
|
9
|
+
# `title` and `produces` are meant to be changed.
|
|
10
|
+
schema_version: "1.0"
|
|
11
|
+
workflow:
|
|
12
|
+
id: "project-kit"
|
|
13
|
+
name: "Project definition flow"
|
|
14
|
+
description: "From an idea to a provisioned repository and a Spec Kit handoff"
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- id: init
|
|
18
|
+
title: "Set up project-kit in the repository"
|
|
19
|
+
skill: pk-start
|
|
20
|
+
gate: false
|
|
21
|
+
produces:
|
|
22
|
+
- .project-kit/config.yml
|
|
23
|
+
|
|
24
|
+
- id: discover
|
|
25
|
+
title: "Define what the project is: problem, users, scope, constraints"
|
|
26
|
+
skill: pk-discover
|
|
27
|
+
gate: true
|
|
28
|
+
produces:
|
|
29
|
+
- docs/project/brief.md
|
|
30
|
+
|
|
31
|
+
- id: decide
|
|
32
|
+
title: "Decide the stack and the architecture"
|
|
33
|
+
skill: pk-decide
|
|
34
|
+
gate: true
|
|
35
|
+
produces:
|
|
36
|
+
- docs/adr/
|
|
37
|
+
|
|
38
|
+
- id: workflow
|
|
39
|
+
title: "Agree how the team will work: branches, reviews, quality gates"
|
|
40
|
+
skill: pk-workflow
|
|
41
|
+
gate: true
|
|
42
|
+
produces:
|
|
43
|
+
- docs/development-workflow.md
|
|
44
|
+
|
|
45
|
+
- id: plan
|
|
46
|
+
title: "Turn it all into phases, epics and a backlog"
|
|
47
|
+
skill: pk-plan
|
|
48
|
+
gate: true
|
|
49
|
+
produces:
|
|
50
|
+
- docs/project/roadmap.md
|
|
51
|
+
- .project-kit/backlog.json
|
|
52
|
+
|
|
53
|
+
- id: provision
|
|
54
|
+
title: "Create milestones, labels, branches, the Project and the issues"
|
|
55
|
+
skill: pk-provision
|
|
56
|
+
gate: false
|
|
57
|
+
|
|
58
|
+
- id: handoff
|
|
59
|
+
title: "Hand over to Spec Kit: constitution, then one spec per issue"
|
|
60
|
+
skill: pk-handoff
|
|
61
|
+
gate: true
|
|
62
|
+
produces:
|
|
63
|
+
- .project-kit/handoff/constitution-input.md
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pk-decide
|
|
3
|
+
description: Guide the user through the technical and architectural decisions of the project (repository structure, language, framework, package manager, data, auth, hosting, CI) and record each one as an ADR in docs/adr/. Use when the user wants to choose the stack or architecture, or to revisit a decision.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# pk-decide — phase 2
|
|
7
|
+
|
|
8
|
+
Turn the brief into **decisions**: one ADR per decision, with the options considered and the
|
|
9
|
+
reason for the choice. project-kit does not choose for the user; it makes the choice
|
|
10
|
+
explicit, argued and written down. The ADRs feed the plan and, later, the Spec Kit
|
|
11
|
+
constitution.
|
|
12
|
+
|
|
13
|
+
Read `.project-kit/templates/interview.md` first and follow it. ADRs use
|
|
14
|
+
`.project-kit/templates/adr.md`, are named `docs/adr/NNNN-short-title.md` (next free number)
|
|
15
|
+
and can also be written by hand.
|
|
16
|
+
|
|
17
|
+
## Inputs
|
|
18
|
+
|
|
19
|
+
- `docs/project/brief.md`, especially "Constraints" and "Technical preferences already
|
|
20
|
+
stated". Preferences are proposals to confirm, not decisions.
|
|
21
|
+
- Existing `docs/adr/*.md`: never decide twice. To change a decision, write a new ADR and mark
|
|
22
|
+
the old one `Superseded by ADR-NNNN`.
|
|
23
|
+
|
|
24
|
+
## Steps
|
|
25
|
+
|
|
26
|
+
1. **List the decisions this project needs**, from this checklist and from the brief; leave
|
|
27
|
+
out whatever does not apply (a command-line tool has no auth or hosting question):
|
|
28
|
+
- Repository: single repository, monorepo or several repositories; monolith or separate
|
|
29
|
+
services.
|
|
30
|
+
- Language and runtime; framework(s).
|
|
31
|
+
- Package manager and, for monorepos, workspace and build tooling (for example pnpm, npm,
|
|
32
|
+
yarn, uv, cargo workspaces, turborepo, nx).
|
|
33
|
+
- Data: storage, migrations, backups.
|
|
34
|
+
- Authentication and authorisation.
|
|
35
|
+
- API style and integrations with external services.
|
|
36
|
+
- Hosting, environments and deployment; CI.
|
|
37
|
+
- Testing approach and tools; observability.
|
|
38
|
+
- Anything the brief marks as legal or compliance-driven.
|
|
39
|
+
2. **Show the list** and ask which ones are *critical* now (they block planning) and which
|
|
40
|
+
can wait. In "light" mode, only decide the critical ones. Deferred decisions are written
|
|
41
|
+
as `Status: Proposed` or left for a later `pk-decide`.
|
|
42
|
+
3. **For each decision, one at a time:**
|
|
43
|
+
1. Ask the question in the interview format: options with pros and cons for *this*
|
|
44
|
+
project, a recommendation with the reason, and what depends on the answer. Use the
|
|
45
|
+
brief's constraints (team skills, budget, scale, compliance) as the drivers.
|
|
46
|
+
2. If a decision follows from an earlier one (a framework implies a language), do not ask:
|
|
47
|
+
state it and record it in the ADR as a consequence.
|
|
48
|
+
3. After the answer, write the ADR immediately (`Status: Accepted`, today's date) and tell
|
|
49
|
+
the user its path.
|
|
50
|
+
4. **Check consistency** across ADRs: no contradictory choices (for example a package manager
|
|
51
|
+
that the chosen framework does not support). Raise any conflict as a question.
|
|
52
|
+
5. **Present** the list of ADRs with their status and anything still undecided.
|
|
53
|
+
6. **Approval gate.** When the critical ADRs are accepted and the user explicitly approves,
|
|
54
|
+
run `project-kit approve decide`.
|
|
55
|
+
7. Run `project-kit status` and offer `pk-workflow` next: continue now, or stop here.
|
|
56
|
+
|
|
57
|
+
## Rules
|
|
58
|
+
|
|
59
|
+
- Do not decide on the user's behalf and do not present your recommendation as settled.
|
|
60
|
+
- Never invent versions, prices or benchmarks; if a fact matters and you are not sure, say so
|
|
61
|
+
and mark it `[NEEDS CLARIFICATION]`.
|
|
62
|
+
- Keep each ADR to one decision. Write them in the language of `config.yml`.
|
|
63
|
+
- The `Status:` line matters: the handoff reads it to build the constitution.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pk-discover
|
|
3
|
+
description: Interview the user about what the project is (problem, users, scope, constraints, success criteria) and write docs/project/brief.md; also clarifies an existing brief. Use when the user wants to define or describe the project, refine the brief, or after pk-start.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# pk-discover — phase 1
|
|
7
|
+
|
|
8
|
+
Produce the **project brief**: what the project is and why, not how it is built. Technology is
|
|
9
|
+
decided in the next phase (`pk-decide`). The brief can be written by this interview, filled
|
|
10
|
+
in by hand from `.project-kit/templates/brief.md`, or both.
|
|
11
|
+
|
|
12
|
+
Read `.project-kit/templates/interview.md` first and follow it: one question at a time with a
|
|
13
|
+
recommended answer, save after every answer, mark gaps, approval only on an explicit "yes".
|
|
14
|
+
|
|
15
|
+
## Inputs
|
|
16
|
+
|
|
17
|
+
- `.project-kit/config.yml` (name, language) and `project-kit status`.
|
|
18
|
+
- The description the user gave in `pk-start`, if any.
|
|
19
|
+
- `docs/project/brief.md`, if it exists (hand-written or from an earlier session): ask only
|
|
20
|
+
about what is missing or partial.
|
|
21
|
+
|
|
22
|
+
## Steps
|
|
23
|
+
|
|
24
|
+
1. If `docs/project/brief.md` does not exist, create it from `.project-kit/templates/brief.md`
|
|
25
|
+
(replace `{{project_name}}`), and fill in whatever the user's description already answers.
|
|
26
|
+
2. **Scan the brief** against these topics, marking each Clear / Partial / Missing:
|
|
27
|
+
- Problem and value: who hurts, how, what happens today without it.
|
|
28
|
+
- Users and stakeholders: roles, how they differ, who decides.
|
|
29
|
+
- Scope: the capabilities that must exist, grouped by theme, and what is explicitly out.
|
|
30
|
+
- Success criteria: how the user will know it worked, measurable where possible.
|
|
31
|
+
- Constraints: legal and compliance, budget, deadline, team size and skills, existing
|
|
32
|
+
systems, data residency.
|
|
33
|
+
- Data and integrations: what information is handled, which external services are needed.
|
|
34
|
+
- Risks and assumptions: what could make the project fail, what is being taken for granted.
|
|
35
|
+
- Terminology: words with an ambiguous meaning in this domain.
|
|
36
|
+
3. **Interview** on the Partial and Missing topics, highest impact first, with a maximum of
|
|
37
|
+
**8 questions** in the first pass. Keep them at product level: if the user volunteers a
|
|
38
|
+
technology ("it will be in Next.js", "we use pnpm"), do not debate it; write it under
|
|
39
|
+
"Technical preferences already stated" for `pk-decide` and move on.
|
|
40
|
+
4. If the user gave nothing to start from, begin with: "In a few sentences, what do you want
|
|
41
|
+
to build and who is it for?" and derive the next questions from the answer.
|
|
42
|
+
5. **Check quality** before presenting: every goal and success criterion is verifiable, the
|
|
43
|
+
scope has an "out of scope" list, no statement names a technology as a requirement.
|
|
44
|
+
6. **Present** a short summary of the brief and the markers still open.
|
|
45
|
+
7. **Offer a clarification pass** (at most 5 more questions) before approval.
|
|
46
|
+
8. **Approval gate.** When the user explicitly approves, set `**Status**: Approved` in the
|
|
47
|
+
brief and run `project-kit approve discover`.
|
|
48
|
+
9. Run `project-kit status` and offer `pk-decide` next: continue now, or stop here.
|
|
49
|
+
|
|
50
|
+
## Rules
|
|
51
|
+
|
|
52
|
+
- Never invent users, numbers, deadlines or constraints. Unknown means a
|
|
53
|
+
`[NEEDS CLARIFICATION: ...]` marker or a labelled assumption.
|
|
54
|
+
- Write the brief in the language of `config.yml`.
|
|
55
|
+
- Do not run `project-kit approve discover` without an explicit "yes".
|
|
56
|
+
- The brief is the user's document: if they edit it by hand between questions, re-read it
|
|
57
|
+
before the next change.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pk-handoff
|
|
3
|
+
description: Hand the project over to Spec Kit: generate the constitution input from the project's decisions and set up Spec Kit (phase 6). Use when planning and provisioning are done and the user wants to start specifying features.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# pk-handoff — phase 6
|
|
7
|
+
|
|
8
|
+
Prepare the text for `/speckit-constitution`, make sure Spec Kit is available, and point the
|
|
9
|
+
user at the first specs. Spec Kit owns `.specify/`; project-kit never writes inside it.
|
|
10
|
+
|
|
11
|
+
## Steps
|
|
12
|
+
|
|
13
|
+
1. Ask the user whether the project has rules of its own that should be part of the
|
|
14
|
+
constitution (security, compliance, performance, team conventions). If so, write them as
|
|
15
|
+
a Markdown list to `.project-kit/handoff/constitution-extra.md`. That file is yours and
|
|
16
|
+
project-kit never overwrites it; it is added under "Project-specific rules".
|
|
17
|
+
Governance content only: no feature requests, no implementation tasks.
|
|
18
|
+
2. Run `project-kit handoff --dry-run` and show the user what will be generated.
|
|
19
|
+
3. Run `project-kit handoff`. It writes `.project-kit/handoff/constitution-input.md` and
|
|
20
|
+
reports the state of Spec Kit.
|
|
21
|
+
4. If Spec Kit is not ready, explain what `project-kit handoff --install-speckit` would run
|
|
22
|
+
(it installs the `specify-cli` package with `uv` and runs `specify init --here`, which
|
|
23
|
+
merges Spec Kit's files into the repository). Only after an explicit "yes", run
|
|
24
|
+
`project-kit handoff --install-speckit --yes`.
|
|
25
|
+
5. Tell the user to run, in this session:
|
|
26
|
+
`/speckit-constitution @.project-kit/handoff/constitution-input.md`
|
|
27
|
+
You cannot run that command for them.
|
|
28
|
+
6. After the constitution exists, suggest mentioning `docs/project/`, `docs/adr/` and
|
|
29
|
+
`docs/development-workflow.md` in `CLAUDE.md` or `AGENTS.md`. Explain that from here Spec
|
|
30
|
+
Kit does the work: each backlog issue is one spec, and its text (description and acceptance
|
|
31
|
+
criteria) is the input of `/speckit-specify`; then `/speckit-clarify`, `/speckit-plan`,
|
|
32
|
+
`/speckit-tasks` and `/speckit-implement`. project-kit does not write specs.
|
|
33
|
+
Suggest the order: the issues of the first phase, by priority.
|
|
34
|
+
7. When the user confirms the constitution is in place, run `project-kit approve handoff`.
|
|
35
|
+
|
|
36
|
+
## Rules
|
|
37
|
+
|
|
38
|
+
- `constitution-input.md` is regenerated every time. Do not edit it; put project-specific rules
|
|
39
|
+
in `constitution-extra.md`. If the user removes its `project-kit:managed` header the file is
|
|
40
|
+
theirs and is no longer regenerated.
|
|
41
|
+
- Never modify anything inside `.specify/` by hand.
|
|
42
|
+
- If project-kit warns about an untested Spec Kit version, tell the user, but continue: the
|
|
43
|
+
only thing project-kit depends on is the input file.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pk-plan
|
|
3
|
+
description: Turn the project's brief and decisions into a phased roadmap and a validated backlog (.project-kit/backlog.json). Use when the user wants to plan the project, break it into phases and epics, or revise the backlog before provisioning.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# pk-plan — phase 4
|
|
7
|
+
|
|
8
|
+
Produce the project backlog and get it approved. Nothing is created in the provider here;
|
|
9
|
+
that happens later, in the provision phase.
|
|
10
|
+
|
|
11
|
+
## Inputs
|
|
12
|
+
|
|
13
|
+
- `docs/project/brief.md` (scope, goals, constraints), `docs/adr/*.md` (decisions) and
|
|
14
|
+
`docs/development-workflow.md` (process). The plan is **derived** from them: scope becomes
|
|
15
|
+
epics, constraints and decisions become issues (repository setup, CI, the chosen
|
|
16
|
+
infrastructure) in the first phase.
|
|
17
|
+
- **Run `project-kit status` first.** If an enabled earlier phase is not done, stop and tell
|
|
18
|
+
the user which skill to run (`/pk-discover`, `/pk-decide`, `/pk-workflow`). Do not
|
|
19
|
+
improvise a brief. If they want to skip a phase, they set `enabled: false` on it in
|
|
20
|
+
`.project-kit/workflow.yml`; only then plan without it, and say what is missing.
|
|
21
|
+
- `.project-kit/config.yml` (project name, language, provider).
|
|
22
|
+
- `.project-kit/templates/backlog.example.json`: follow its shape exactly.
|
|
23
|
+
|
|
24
|
+
Write the backlog content in the language set in `config.yml`.
|
|
25
|
+
|
|
26
|
+
## Steps
|
|
27
|
+
|
|
28
|
+
1. **Draft the phases.** Each phase becomes a milestone and a value of the Phase field.
|
|
29
|
+
Keep them few and ordered by delivery (for example `v0.1 MVP`, `v0.2`, `v1.0`).
|
|
30
|
+
2. **Draft the epics**, one per coherent delivery inside a phase.
|
|
31
|
+
3. **Break each epic into issues** (`feature`, `bug`, `chore`, `adr`, `docs`) with `parent`
|
|
32
|
+
pointing at the epic. Give every `feature`, `bug` and `chore` concrete acceptance
|
|
33
|
+
criteria: observable statements a reviewer can tick, not tasks.
|
|
34
|
+
4. **Set priority (P0–P3) and size (XS–XL)** on every issue. Prefer small issues; split
|
|
35
|
+
anything you would size XL unless it is an epic.
|
|
36
|
+
5. **Write the file** to `.project-kit/backlog.json`.
|
|
37
|
+
6. **Validate:** run `project-kit backlog validate`. Fix every problem it reports and run it
|
|
38
|
+
again until it passes. Never hand-edit your way around a validation error.
|
|
39
|
+
7. **Present the plan** to the user: the summary printed by the validator plus, per phase, the
|
|
40
|
+
epics and their issues in a short list.
|
|
41
|
+
8. **Approval gate.** Ask the user explicitly whether the plan is approved. If they ask for
|
|
42
|
+
changes, edit the backlog, validate again and present it again. Only when they say yes,
|
|
43
|
+
run `project-kit approve plan`.
|
|
44
|
+
9. Optionally write `docs/project/roadmap.md` summarising the phases and epics for humans.
|
|
45
|
+
10. Run `project-kit status` and offer `pk-provision` next: continue now, or stop here.
|
|
46
|
+
|
|
47
|
+
## Rules
|
|
48
|
+
|
|
49
|
+
- Do not run `project-kit approve plan` without an explicit "yes" from the user in this
|
|
50
|
+
conversation, and never approve on their behalf.
|
|
51
|
+
- Ids are lowercase words joined by hyphens and stay stable once provisioned; do not rename
|
|
52
|
+
them when revising a backlog that was already provisioned.
|
|
53
|
+
- Do not edit `.project-kit/state.json` by hand.
|
|
54
|
+
- Each issue is meant to become a Spec Kit spec later: keep it about one deliverable, with
|
|
55
|
+
acceptance criteria a reviewer can verify.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pk-provision
|
|
3
|
+
description: Create the milestones, labels, branches, GitHub Project and issues of the approved backlog in the repository's provider (phase 5). Use when the user wants to publish the plan to GitHub or to sync new backlog entries.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# pk-provision — phase 5
|
|
7
|
+
|
|
8
|
+
Turn `.project-kit/backlog.json` into real milestones, labels, branches, a Project and issues.
|
|
9
|
+
This writes to the provider, so nothing happens without the user's explicit consent.
|
|
10
|
+
|
|
11
|
+
## Before starting
|
|
12
|
+
|
|
13
|
+
- The plan must be approved: `project-kit approve plan` (the pk-plan skill does it).
|
|
14
|
+
- Run `project-kit doctor`. `gh` must be logged in with the `repo` and `project` scopes.
|
|
15
|
+
- The repository must already have a commit on its main branch.
|
|
16
|
+
|
|
17
|
+
## Steps
|
|
18
|
+
|
|
19
|
+
1. Run `project-kit provision --dry-run` and show the user the plan it prints: what will be
|
|
20
|
+
created, what already exists, and the note about branch protection.
|
|
21
|
+
- A `BLOCKING` line means nothing can be applied; explain it and help fix it.
|
|
22
|
+
- The `Project:` line says which GitHub Project will be used: one already linked to the
|
|
23
|
+
repository (`already exists`) or a new one. Tell the user and ask whether that is the one
|
|
24
|
+
they want. If not, rerun with `--project "<number or exact title>"` to use another
|
|
25
|
+
existing Project, or with a new title to create it.
|
|
26
|
+
- If it stops with "Several Projects match this repository", show the list, ask the user
|
|
27
|
+
which one (or a name for a new one) and rerun with `--project`. The choice is remembered.
|
|
28
|
+
2. Ask the user whether to go ahead. Only after an explicit "yes" run
|
|
29
|
+
`project-kit provision --yes`. Never pass `--yes` without that consent.
|
|
30
|
+
3. Report the result. Running the command again is always safe: it only creates what is
|
|
31
|
+
missing, never rewrites existing issues and never moves cards the user has moved.
|
|
32
|
+
|
|
33
|
+
## Things to tell the user
|
|
34
|
+
|
|
35
|
+
- Project **views** (Board, Roadmap, table) cannot be created through the API; they are made by
|
|
36
|
+
hand once in the Project's page.
|
|
37
|
+
- Branch protection is only reported, never configured. On a private repository with a free
|
|
38
|
+
plan GitHub does not offer it; the branch rules are then followed by discipline.
|
|
39
|
+
- If GitHub says the rate limit was reached, wait a minute and run the command again: the
|
|
40
|
+
progress is saved and the command resumes where it stopped.
|
|
41
|
+
|
|
42
|
+
## Rules
|
|
43
|
+
|
|
44
|
+
- Do not edit `.project-kit/state.json`; project-kit owns it.
|
|
45
|
+
- To add work later, edit the backlog (pk-plan), validate it and run this again.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pk-start
|
|
3
|
+
description: Start here. Check that project-kit is ready in this repository, settle the basics (language, AI co-author policy) and ask whether to only initialise or to start defining the project right away. Use when the user has just run `project-kit init`, wants to begin a new project, or asks where to start.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# pk-start — phase 0
|
|
7
|
+
|
|
8
|
+
Entry point of project-kit. The files are already in the repository (`project-kit init` put
|
|
9
|
+
them there); this skill checks them, settles the basics and lets the user choose how far to go
|
|
10
|
+
now. Nothing is created in GitHub or GitLab here.
|
|
11
|
+
|
|
12
|
+
## Steps
|
|
13
|
+
|
|
14
|
+
1. **Check the tools.** Run `project-kit doctor`.
|
|
15
|
+
- `FAIL` lines block: explain each hint and wait until it is fixed.
|
|
16
|
+
- `warn` lines are optional (`uv` and Spec Kit are only needed at the handoff phase).
|
|
17
|
+
2. **Read the setup.** If `.project-kit/config.yml` is missing, tell the user to run
|
|
18
|
+
`project-kit init` in the terminal and stop. Otherwise read it back (project name,
|
|
19
|
+
provider, language, branches) and ask whether it is right. These are plain values that can
|
|
20
|
+
also be edited by hand. If the language is wrong, edit `language:` in the file.
|
|
21
|
+
3. **AI co-author.** If `config.yml` says `ai_coauthor: true` and the user has not been
|
|
22
|
+
asked yet, ask whether AI assistants (Claude, Copilot...) should appear as co-authors of
|
|
23
|
+
commits and pull requests. If they do not want it:
|
|
24
|
+
- set `ai_coauthor: false` in `config.yml` and run `project-kit init`: it makes Claude
|
|
25
|
+
Code stop signing (`attribution` in `.claude/settings.json`) and installs a
|
|
26
|
+
`commit-msg` hook that strips the co-author trailer of any other assistant;
|
|
27
|
+
- ask before running `git config core.hooksPath .githooks`, which switches the hook on for
|
|
28
|
+
this clone. Each teammate runs that command once.
|
|
29
|
+
4. **Ask how far to go now.** Offer exactly these two options:
|
|
30
|
+
|
|
31
|
+
| Option | What happens |
|
|
32
|
+
|--------|--------------|
|
|
33
|
+
| **A. Only initialise** | Stop here. The user comes back later with `/pk-discover` |
|
|
34
|
+
| **B. Start defining the project** | Continue now with the discovery interview |
|
|
35
|
+
|
|
36
|
+
Recommend B unless the user said they are in a hurry.
|
|
37
|
+
5. **If A:** run `project-kit status`, show it, and explain that `/pk-discover` is next. Done.
|
|
38
|
+
6. **If B:** ask for a short description of the project in the user's own words, a few
|
|
39
|
+
sentences, a pasted note or "nothing yet, ask me". Then follow the `pk-discover` skill
|
|
40
|
+
(`.claude/skills/pk-discover/SKILL.md`) using that description as the starting point.
|
|
41
|
+
|
|
42
|
+
## Rules
|
|
43
|
+
|
|
44
|
+
- `project-kit init` never overwrites existing files, so it is safe to run again.
|
|
45
|
+
- Do not edit `.project-kit/state.json` by hand; project-kit owns it.
|
|
46
|
+
- The phases are listed in `.project-kit/workflow.yml`; the user may disable some of them
|
|
47
|
+
(`enabled: false`) for a small project. `project-kit status` shows what is left.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pk-workflow
|
|
3
|
+
description: Agree how the team will work (branches, pull requests, reviews, commits, versioning, quality gates, definition of done) and write docs/development-workflow.md. Use when the user wants to define the development process or change it.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# pk-workflow — phase 3
|
|
7
|
+
|
|
8
|
+
Record **how the project is developed**: the process that the plan, the provisioned
|
|
9
|
+
repository and the Spec Kit constitution will all follow. It is written in
|
|
10
|
+
`docs/development-workflow.md` (template: `.project-kit/templates/development-workflow.md`),
|
|
11
|
+
by this interview or by hand.
|
|
12
|
+
|
|
13
|
+
Read `.project-kit/templates/interview.md` first and follow it.
|
|
14
|
+
|
|
15
|
+
## Inputs
|
|
16
|
+
|
|
17
|
+
- `docs/project/brief.md` and `docs/adr/*.md`: team size, repository structure, package
|
|
18
|
+
manager and CI already decided there are not asked again; link them.
|
|
19
|
+
- `.project-kit/config.yml`: branch names (`main`, `release`, `develop`) and provider.
|
|
20
|
+
- The PR and issue templates that `project-kit init` put in `.project-kit/templates/github/`.
|
|
21
|
+
|
|
22
|
+
## Topics (maximum 8 questions; propose a default for each and ask only what matters)
|
|
23
|
+
|
|
24
|
+
- **Team and review:** how many people, who approves, how many approvals.
|
|
25
|
+
- **Branches:** keep `main` / `release` / `develop` with one branch per spec, or a lighter
|
|
26
|
+
model (only `main`) for a small project. Name the types of working branch.
|
|
27
|
+
- **Merging:** merge strategy per branch, who may merge, tags and releases.
|
|
28
|
+
- **Commits and versions:** commit convention, versioning scheme.
|
|
29
|
+
- **Repository tooling:** formatters, linters, git hooks, which follow from the ADRs.
|
|
30
|
+
- **Quality gates:** what must be green before merging (tests, lint, types, security scan).
|
|
31
|
+
- **Definition of Done.**
|
|
32
|
+
- **Git hosting rules:** branch protection availability on the hosting plan.
|
|
33
|
+
|
|
34
|
+
## Steps
|
|
35
|
+
|
|
36
|
+
1. Create `docs/development-workflow.md` from the template if it does not exist; fill in what
|
|
37
|
+
the ADRs and config already settle.
|
|
38
|
+
2. Interview on the rest, then write the answers into the document after each one.
|
|
39
|
+
3. If the user changes branch names or drops `release`/`develop`, edit `branches:` in
|
|
40
|
+
`.project-kit/config.yml` too (it must keep three different names), and tell the user.
|
|
41
|
+
4. **Present** the document and the open markers; offer a clarification pass.
|
|
42
|
+
5. **Approval gate.** On an explicit "yes", set `**Status**: Approved` and run
|
|
43
|
+
`project-kit approve workflow`.
|
|
44
|
+
6. Run `project-kit status` and offer `pk-plan` next: continue now, or stop here.
|
|
45
|
+
|
|
46
|
+
## Rules
|
|
47
|
+
|
|
48
|
+
- Do not configure anything in the provider here: branches and protection are created by
|
|
49
|
+
`pk-provision`, after the plan.
|
|
50
|
+
- Do not repeat technical decisions; link the ADR.
|
|
51
|
+
- Write in the language of `config.yml`.
|