Compare commits

..

11 Commits

Author SHA1 Message Date
0c39729123 tasks: close [project-discipline-skill] 2026-05-01 11:36:20 +03:00
7f0e61ba91 docs(wiki): log + index — project-discipline@0.1.0 2026-05-01 11:35:47 +03:00
b8b6acb091 build: project-discipline@0.1.0 + project-bootstrap@1.5.0 archives 2026-05-01 11:35:01 +03:00
059cdf41e1 chore(claude-skills): dogfood 'follow project discipline' trigger 2026-05-01 11:34:31 +03:00
b72fc72577 docs(wiki): skill-versioning — Rule 3 of project-discipline extends scope to all skills 2026-05-01 11:34:15 +03:00
d0a450ce40 feat(project-bootstrap): v1.5.0 — add 'follow project discipline' canonical trigger [v1.5.0] 2026-05-01 11:33:46 +03:00
88d533b362 feat(project-bootstrap): template gains 'follow project discipline' trigger 2026-05-01 11:33:10 +03:00
ca75124324 docs(project-discipline): README 2026-05-01 11:32:59 +03:00
560f15571e feat(project-discipline): skill body — four rules + activation + out-of-scope [v0.1.0] 2026-05-01 11:32:38 +03:00
7c63c6080f feat(project-discipline): scaffold skill frontmatter [v0.1.0] 2026-05-01 11:31:22 +03:00
df8f1cb72b docs(project-discipline): design spec + implementation plan + STATUS active block
Spec: .wiki/concepts/project-discipline-design.md — four cross-project
rules (conventions-over-defaults, master-only, semver-bumping with
first-edit-unversioned clause, session-scoped ask-before-push with
grant/revoke and force/delete/non-ff exceptions); architecture: single
policy skill activated by 'follow project discipline' line in CLAUDE.md
template (added by project-bootstrap v1.5.0); 12-task implementation
plan tracked in .tasks/project-discipline-skill.md.
2026-05-01 11:30:38 +03:00
13 changed files with 1208 additions and 4 deletions

View File

@@ -1,6 +1,14 @@
# Task Board # Task Board
_Updated: 2026-05-01_ _Updated: 2026-05-01_
## 🟢 [project-discipline-skill] — project-discipline skill + project-bootstrap 1.5.0 canonical trigger
**Status:** done
**Where I stopped:** `skills/project-discipline/` shipped at v0.1.0 (four rules: convention-override, master-only, semver-bumping with first-edit-unversioned clause, session-scoped ask-before-push with grant/revoke and force/delete/non-ff exceptions); `assets/CLAUDE.md.template` gains `follow project discipline` after `pull remote before work`; `project-bootstrap` 1.4.0→1.5.0 with new commentary paragraph in Step 5 + manifest table row in Step 5.5; `.wiki/concepts/skill-versioning.md` extended (Rule 3 expands `version:` requirement to ALL skills, not just infra subset); root `CLAUDE.md` dogfood line added; both archives rebuilt in `dist/`; installed via `install.sh`; description length verified 855 chars (≤900); smoke scenarios 1 (skill listing with full description, not H1 fallback) + 9 (length regression check) verified inline post-install; scenarios 2-8 (Rule 1-4 in fresh sessions, bootstrap upgrade) deferred — require multi-session orchestration; design rationale at `.wiki/concepts/project-discipline-design.md`
**Next action:** (none — kept until merged)
**Branch:** master
---
## 🟢 [pulling-before-work-skill] — pulling-before-work skill + project-bootstrap 1.4.0 canonical trigger ## 🟢 [pulling-before-work-skill] — pulling-before-work skill + project-bootstrap 1.4.0 canonical trigger
**Status:** done **Status:** done
**Where I stopped:** `skills/pulling-before-work/` shipped at v1.0.0 (mode-3 activation: session start + on-demand re-sync; `git pull --ff-only`; skips on no-remote / no-upstream / dirty / detached); `assets/CLAUDE.md.template` gains `pull remote before work`; `project-bootstrap` 1.3.0→1.4.0 with new commentary paragraph in Step 5; root `CLAUDE.md` dogfood line added; both archives rebuilt in `dist/`; installed via `install.sh`; smoke scenarios 1/2/3/4/5/8/9 + inline bootstrap-merge check verified by controller, scenarios 6 (diverged remote) and 7 (re-sync trigger across a fresh session) deferred — both require multi-session orchestration not yet tooled; design rationale at `.wiki/concepts/pulling-before-work-design.md` **Where I stopped:** `skills/pulling-before-work/` shipped at v1.0.0 (mode-3 activation: session start + on-demand re-sync; `git pull --ff-only`; skips on no-remote / no-upstream / dirty / detached); `assets/CLAUDE.md.template` gains `pull remote before work`; `project-bootstrap` 1.3.0→1.4.0 with new commentary paragraph in Step 5; root `CLAUDE.md` dogfood line added; both archives rebuilt in `dist/`; installed via `install.sh`; smoke scenarios 1/2/3/4/5/8/9 + inline bootstrap-merge check verified by controller, scenarios 6 (diverged remote) and 7 (re-sync trigger across a fresh session) deferred — both require multi-session orchestration not yet tooled; design rationale at `.wiki/concepts/pulling-before-work-design.md`

View File

@@ -0,0 +1,761 @@
# project-discipline — implementation plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Ship a new policy skill `project-discipline` (four cross-project rules: conventions-over-skill-defaults, master-only, semver-bumping, ask-before-push) and wire it into the canonical `project-bootstrap` template, with the `claude-skills` repo dogfooding the trigger.
**Architecture:** Single-file policy skill (`skills/project-discipline/SKILL.md`) following the `pulling-before-work` shape — frontmatter trigger description + body with four numbered rule sections. `project-bootstrap` v1.4.0 → v1.5.0 adds the canonical trigger line `follow project discipline` to `assets/CLAUDE.md.template` after `pull remote before work`; the existing v1.3.0 idempotent merge propagates it into existing projects on upgrade. The `claude-skills` repo's own `CLAUDE.md` gets the line as dogfood. The bootstrap manifest table gains a row for the new skill. The existing `.wiki/concepts/skill-versioning.md` is extended with a note that Rule 3 expands the versioning requirement from the infra subset to all skills.
**Tech Stack:** Markdown skills (no build for the skill body itself). Build pipeline: `scripts/build.ps1` produces `dist/<name>.skill` archives. Install: `scripts/install.sh` (portable across git-bash on Windows + native Linux/macOS). Spec lives at `.wiki/concepts/project-discipline-design.md`.
---
## File Structure
**New:**
- `skills/project-discipline/SKILL.md` — frontmatter + body, ~250300 lines
- `skills/project-discipline/README.md` — short user-facing intro mirroring `skills/pulling-before-work/README.md` shape
**Modified:**
- `skills/project-bootstrap/SKILL.md``version: 1.4.0``1.5.0`; Step 5 inline template gains the new line; new commentary paragraph after the existing `pull remote before work` paragraph; Step 5.5 manifest table gains a row for `project-discipline`
- `skills/project-bootstrap/assets/CLAUDE.md.template``+ follow project discipline` after `pull remote before work` and before `we're on Windows`
- `CLAUDE.md` (repo root) — `+ follow project discipline` in the same position (dogfood)
- `.wiki/concepts/skill-versioning.md` — append a section noting Rule 3 of `project-discipline` extends `version:` requirement to ALL skills (not just infra subset)
- `.wiki/log.md` — append decision entry
- `.wiki/index.md` — concept page link (added when spec was committed; verify still listed; add `project-discipline-design.md` if not)
- `.tasks/STATUS.md` — add `[project-discipline-skill]` 🔴 Active block, then update to 🟢 Done at the end
**Built:**
- `dist/project-discipline.skill` — new
- `dist/project-bootstrap.skill` — rebuilt
---
## Task 1: New skill — frontmatter only
**Files:**
- Create: `skills/project-discipline/SKILL.md`
- [ ] **Step 1: Write the frontmatter**
```markdown
---
name: project-discipline
version: 0.1.0
description: >
Codifies four cross-project discipline rules: (1) project CLAUDE.md /
.wiki/CLAUDE.md / .tasks/ override defaults from any other skill (specs
go to .wiki/concepts/, not docs/superpowers/specs/; tasks to .tasks/,
not docs/superpowers/plans/); (2) all work on master/main, no feature
branches without explicit user approval; (3) bump semver on every edit
of versioned artifacts (SKILL.md frontmatter, package.json,
pyproject.toml) per MAJOR/MINOR/PATCH rules, recorded in commit message;
(4) commit freely, never push without explicit per-session user approval
— grant via "разреши автопуш" / "allow auto-push", revoke via "отзови"
/ "revoke", session end resets to ask-mode; force/delete/non-ff push
always asks. Activated by "follow project discipline" trigger in
CLAUDE.md (added by project-bootstrap v1.5.0+).
---
# project-discipline
```
- [ ] **Step 2: Verify description length is under 900 chars**
```powershell
$c = Get-Content skills/project-discipline/SKILL.md -Raw
$start = $c.IndexOf('description: >') + 'description: >'.Length
$end = $c.IndexOf('---', $start)
$desc = $c.Substring($start, $end - $start).Trim()
"description chars: $($desc.Length)"
```
Expected: a number ≤ 900. (Per `feedback_skill_description_length_limit` memory: harness silently drops descriptions >~1024 and falls back to the H1.)
- [ ] **Step 3: Commit**
```powershell
git add skills/project-discipline/SKILL.md
git commit -m "feat(project-discipline): scaffold skill frontmatter [v0.1.0]"
```
---
## Task 2: New skill — body
**Files:**
- Modify: `skills/project-discipline/SKILL.md` (append body)
- [ ] **Step 1: Append the skill body after the H1**
```markdown
> Four cross-project rules. Read at session start. Apply before any other skill's defaults touch paths, branches, versions, or remote pushes.
## When this runs
**At session start** — when `CLAUDE.md` contains the line `follow project discipline`. The skill is a policy document; the agent reads it and applies the four rules to all subsequent work in the session.
**On explicit reference** — when the user says "use project discipline", "соблюди дисциплину", "проектные правила", "что у меня по правилам?", or close variants asking about/applying the rules.
The skill itself takes no actions and has no external side-effects. It instructs the agent how to behave.
## Rule 1 — Project conventions override skill defaults
Before applying defaults from any other skill (superpowers, frontend-design, mcp-builder, etc.), read in this order:
1. `CLAUDE.md` in the project root.
2. `.wiki/CLAUDE.md` (if it exists).
3. `.tasks/STATUS.md` (if it exists).
Any path, format, or workflow explicitly stated in those files **overrides the skill default**.
Concrete consequences:
- **Specs / design documents** go to `.wiki/concepts/<topic>-design.md`, **not** `docs/superpowers/specs/`.
- **Task tracking / implementation plans** go to `.tasks/<slug>.md` plus a board entry in `.tasks/STATUS.md` (the `using-tasks` format), **not** `docs/superpowers/plans/` or any inline-in-chat plan format.
- **Frontmatter, naming conventions, log format** — as described in the project's `.wiki/CLAUDE.md`.
If no convention is stated explicitly — fall back to the skill default.
## Rule 2 — Master-only
All work happens on the repo's main integration branch — usually `master`, but if a project uses `main`, treat `main` as equivalent.
- No `git checkout -b feature/foo` for solo work.
- Sync with remote: `git pull --ff-only` or `git pull --rebase`. **No merge commits** for solo work.
- If a task genuinely requires isolation (large experiment, risky refactor with rollback potential, multi-day work with intermediate WIP commits) — **ask** the user: "this needs its own branch, ok?" — and wait for explicit approval. Without approval, work continues on master.
If the agent finds itself on a non-main branch (after a manual `git checkout`) or in detached HEAD — report it and ask whether to return to master before working.
## Rule 3 — Versioning discipline
When editing any artifact with a semver field, **bump the version before committing** per:
- **MAJOR** (`X+1.0.0`) — breaks the contract. Renames, removed triggers, layout changes, removed public functions, breaking API change.
- **MINOR** (`X.Y+1.0`) — adds capability without breaking. New trigger, new optional step, new public function.
- **PATCH** (`X.Y.Z+1`) — wording / clarity / typo fixes with no behavior change.
The bump is recorded in the commit message: `feat(<artifact>): … [vX.Y.Z]` or whatever convention the project uses (see Rule 1).
**Applies to:** `skills/<name>/SKILL.md` (`version:` in frontmatter), `package.json` (`"version":`), `pyproject.toml` (`version =`), `Cargo.toml` (`version =`), and any other semver field in any other manifest.
**If the artifact is packaged** as `dist/<name>.skill`, `dist/*.tgz`, etc. — **rebuild** the package in the same or the next commit. Forgotten dist artifacts are a common cause of deploying stale binaries.
**First edit of an unversioned artifact** that COULD have a semver field (a new skill without `version:`, a new `package.json` without `"version":`) — **add** `version: 0.1.0` (or its equivalent) before committing; do not bump anything.
**Does not apply to:** artifacts with no semver field and no potential for one (wiki concept pages, README.md, shell scripts without a public interface).
## Rule 4 — Commit yes, push no (session-scoped)
**Every session starts in ask-before-push mode.** On every `git push`, ask:
> Готов push'нуть в `<remote>/<branch>` (N коммитов: <subjects>). Ок?
(or its English equivalent if the user is communicating in English) and wait for explicit `yes` / `да` / `push` / equivalent. Without confirmation — do not push.
**Granting auto-push within a session.** When the user says:
- "разреши автопуш" / "allow auto-push" / "автопуш ок" / equivalent
— push without further confirmation until the end of the session or until revoked.
**Revoking auto-push within a session.** When the user says:
- "отзови автопуш" / "revoke auto-push" / "снова спрашивай" / equivalent
— return to ask-before-push mode.
**Session end resets to ask-mode.** The next session starts asking again, regardless of what was granted in the previous one. This is intentional: a grant is given for the current context (user nearby, consciously decided pushes are safe), and should not survive a context switch.
**Always ask, even with active grant:**
- `git push --force` / `--force-with-lease` (history rewrite);
- `git push origin --delete <branch>` (branch deletion);
- push to a remote/branch other than the current tracked upstream (`git push other-remote ...`, `git push origin other-branch`);
- push to the main branch that would require non-fast-forward (i.e. would need force).
A grant covers ordinary fast-forward push to the configured upstream. Anything else is a separate class of operation and needs its own decision.
**What counts as "push":** only `git push` family commands. Local commits, `git stash push`, etc. are not push; the grant does not apply.
## Out of scope
The skill **does not**:
- modify `CLAUDE.md` (that's `project-bootstrap`'s job);
- enforce rules via git hooks / pre-commit / CI (this is agent discipline, not tooling);
- manage `settings.json` permissions (that's `update-config`);
- check the existence of `.wiki/` / `.tasks/` (that's `setup-wiki` / `setup-tasks` / `project-bootstrap`); if a project doesn't have them, Rule 1 simply finds no overrides and falls back to skill defaults.
## Why this exists
In a tightly-disciplined repo (`claude-skills`) the four rules already hold by accident — the agent reads `.wiki/CLAUDE.md`, knows specs go to `.wiki/concepts/`, knows to bump `version:`, knows not to push without confirmation. In **other** projects of the same user, that discipline does not transfer: the agent uses `superpowers`' default `docs/superpowers/specs/`, branches on a whim, forgets `version:` bumps, and pushes without asking. This skill makes the discipline explicit and portable.
Full design rationale (why one skill instead of four, why a skill instead of inline `CLAUDE.md` lines, scope of each rule, push-permission mechanism choice) lives in `.wiki/concepts/project-discipline-design.md` (in this repo; in other projects bootstrapped from this repo, the design lives in `claude-skills`).
```
- [ ] **Step 2: Sanity-check the file rendered**
```powershell
Get-Content skills/project-discipline/SKILL.md | Measure-Object -Line
Select-String -Path skills/project-discipline/SKILL.md -Pattern '^## Rule [1-4]'
```
Expected:
- Line count ~250320
- Four `## Rule N` matches in order
- [ ] **Step 3: Commit**
```powershell
git add skills/project-discipline/SKILL.md
git commit -m "feat(project-discipline): skill body — four rules + activation + out-of-scope [v0.1.0]"
```
---
## Task 3: New skill — README.md
**Files:**
- Create: `skills/project-discipline/README.md`
- [ ] **Step 1: Write README**
```markdown
# project-discipline
Policy skill that codifies four cross-project discipline rules so the same
guarantees that hold in a tightly-maintained repo apply everywhere.
## When it triggers
- **Session start** — when `CLAUDE.md` contains the line `follow project discipline` (added by `project-bootstrap` v1.5.0+).
- **In-chat** — when the user says "use project discipline", "соблюди дисциплину", "проектные правила", or close variants.
## The four rules
1. **Project conventions over skill defaults.** `CLAUDE.md` / `.wiki/CLAUDE.md` / `.tasks/` override any other skill's defaults. Specs go to `.wiki/concepts/`, not `docs/superpowers/specs/`. Tasks to `.tasks/`, not `docs/superpowers/plans/`.
2. **Master-only.** All work on `master` (or `main`). No feature branches without explicit user approval.
3. **Semver discipline.** Bump `version:` in `SKILL.md` / `package.json` / `pyproject.toml` on every edit per MAJOR / MINOR / PATCH; record in commit message; rebuild `dist/` artifacts after.
4. **Commit yes, push no.** Every session starts asking before push. User can grant auto-push within session ("разреши автопуш"); session end resets to ask-mode. Force / delete / non-ff push always asks.
## Prerequisites
None. The skill is a textual policy document; it takes no actions and has no
external dependencies. Activate it by adding `follow project discipline` to
`CLAUDE.md` (or use `project-bootstrap` v1.5.0+ which adds it automatically).
## Related
- `project-bootstrap` (v1.5.0+) — adds the trigger line to new and existing projects' `CLAUDE.md`.
- `pulling-before-work` — companion skill activated by the canonical template; pulls origin once at session start (`git pull --ff-only`).
- `using-tasks` / `using-wiki` — the format conventions Rule 1 routes work into.
- `.wiki/concepts/project-discipline-design.md` (in `claude-skills`) — full design rationale.
```
- [ ] **Step 2: Commit**
```powershell
git add skills/project-discipline/README.md
git commit -m "docs(project-discipline): README"
```
---
## Task 4: Bootstrap template — add trigger line
**Files:**
- Modify: `skills/project-bootstrap/assets/CLAUDE.md.template`
- [ ] **Step 1: Insert the new line after `pull remote before work`**
Use Edit:
- `old_string`:
```
pull remote before work
we're on Windows
```
- `new_string`:
```
pull remote before work
follow project discipline
we're on Windows
```
- [ ] **Step 2: Verify**
```powershell
Get-Content skills/project-bootstrap/assets/CLAUDE.md.template
```
Expected: eight trigger lines in this order:
```
talk like a caveman
use superpowers
use project wiki
use task management system
check across all projects
pull remote before work
follow project discipline
we're on Windows
```
- [ ] **Step 3: Commit**
```powershell
git add skills/project-bootstrap/assets/CLAUDE.md.template
git commit -m "feat(project-bootstrap): template gains 'follow project discipline' trigger"
```
---
## Task 5: Bootstrap SKILL.md — version bump + Step 5 update + manifest row
**Files:**
- Modify: `skills/project-bootstrap/SKILL.md`
- [ ] **Step 1: Bump version in frontmatter**
Edit:
- `old_string`: `version: 1.4.0`
- `new_string`: `version: 1.5.0`
- [ ] **Step 2: Update the Step 5 inline template (mirror of `assets/CLAUDE.md.template`)**
Find the fenced markdown block in Step 5:
```markdown
talk like a caveman
use superpowers
use project wiki
use task management system
check across all projects
pull remote before work
we're on Windows
```
Replace with:
```markdown
talk like a caveman
use superpowers
use project wiki
use task management system
check across all projects
pull remote before work
follow project discipline
we're on Windows
```
- [ ] **Step 3: Add commentary paragraph for the new trigger**
After the existing paragraph that explains `pull remote before work` (ending with "...silently dead like any other absent skill.") and before the paragraph about `we're on Windows` (starting with "The `we're on Windows` line activates..."), insert:
```markdown
The `follow project discipline` line activates the `project-discipline` skill,
which codifies four cross-project rules: (1) project CLAUDE.md / .wiki/CLAUDE.md
/ .tasks/ override defaults from any other skill; (2) all work on master/main,
no feature branches without explicit user approval; (3) version bump on every
edit of versioned artifacts per semver, recorded in commit; (4) commit freely,
push only after explicit per-session approval. Install the skill on the host
if `project-discipline` is not in `~/.claude/skills/`; otherwise the trigger is
silently dead like any other absent skill.
```
- [ ] **Step 4: Add `project-discipline` row to Step 5.5 manifest table**
Find the table:
```markdown
| Skill | Version | Role |
|---|---|---|
| `project-bootstrap` | <version> | orchestrator |
| `setup-wiki` | <version> | wiki canonical layout |
| `setup-tasks` | <version> | tasks canonical layout |
```
Replace with:
```markdown
| Skill | Version | Role |
|---|---|---|
| `project-bootstrap` | <version> | orchestrator |
| `setup-wiki` | <version> | wiki canonical layout |
| `setup-tasks` | <version> | tasks canonical layout |
| `project-discipline` | <version> | cross-project policy |
```
- [ ] **Step 5: Verify**
```powershell
Select-String -Path skills/project-bootstrap/SKILL.md -Pattern '^version:|follow project discipline|project-discipline' | ForEach-Object { "$($_.LineNumber): $($_.Line)" }
```
Expected: at least 5 hits — `version: 1.5.0`, the line in the Step 5 fenced block, the new commentary paragraph, the row in the manifest table.
- [ ] **Step 6: Commit**
```powershell
git add skills/project-bootstrap/SKILL.md
git commit -m "feat(project-bootstrap): v1.5.0 — add 'follow project discipline' canonical trigger [v1.5.0]"
```
---
## Task 6: Update `.wiki/concepts/skill-versioning.md` — note Rule 3 scope extension
**Files:**
- Modify: `.wiki/concepts/skill-versioning.md`
- [ ] **Step 1: Read current content**
```powershell
Get-Content .wiki/concepts/skill-versioning.md
```
Note the existing section "## What skills are versioned" which scopes versioning to the infra subset.
- [ ] **Step 2: Update the `## What skills are versioned` section**
Find:
```markdown
## What skills are versioned
Currently only the **infrastructure** skills (the ones bootstrap touches and that govern project layout). Communication-mode skills (`caveman`, family) and discovery skills (`find-skills`, `active-platform`) aren't versioned — their content is "good copy-paste" and a snapshot mismatch isn't a layout problem.
If we ever start packaging or marketplace-publishing the rest, we'll version them too.
```
Replace with:
```markdown
## What skills are versioned
**Originally** only the **infrastructure** skills (the ones bootstrap touches and that govern project layout). Communication-mode skills (`caveman`, family) and discovery skills (`find-skills`, `active-platform`) were left unversioned — their content was "good copy-paste" and a snapshot mismatch wasn't a layout problem.
**As of `project-discipline` v0.1.0** (Rule 3), the requirement extends to **all** skills in this repo, regardless of category. Communication-mode and discovery skills also need `version:` in frontmatter; the migration is a separate one-time task tracked in `.tasks/`. Rationale: discipline-by-default is simpler than maintaining a list of "exempt" skills, and it costs nothing — `version: 0.1.0` is added on the next edit per the Rule 3 first-edit-unversioned clause.
If we ever start packaging or marketplace-publishing skills outside this repo, the same rule still applies.
```
- [ ] **Step 3: Update the frontmatter `updated:` field**
Find:
```yaml
---
title: Skill versioning + bootstrap manifest
type: concept
updated: 2026-04-28
---
```
Replace with:
```yaml
---
title: Skill versioning + bootstrap manifest
type: concept
updated: 2026-05-01
---
```
- [ ] **Step 4: Commit**
```powershell
git add .wiki/concepts/skill-versioning.md
git commit -m "docs(wiki): skill-versioning — Rule 3 of project-discipline extends scope to all skills"
```
---
## Task 7: Dogfood — add trigger to claude-skills root CLAUDE.md
**Files:**
- Modify: `CLAUDE.md` (repo root)
- [ ] **Step 1: Insert the trigger after `pull remote before work`**
Use Edit:
- `old_string`:
```
pull remote before work
we're on Windows
```
- `new_string`:
```
pull remote before work
follow project discipline
we're on Windows
```
- [ ] **Step 2: Verify**
```powershell
Get-Content CLAUDE.md
```
Expected:
```
# CLAUDE.md
# Agent instructions. Each line is a trigger for an installed skill.
talk like a caveman
use superpowers
use project wiki
use task management system
check across all projects
pull remote before work
follow project discipline
we're on Windows
```
- [ ] **Step 3: Commit**
```powershell
git add CLAUDE.md
git commit -m "chore(claude-skills): dogfood 'follow project discipline' trigger"
```
---
## Task 8: Build artifacts
**Files:**
- Build: `dist/project-discipline.skill` (new), `dist/project-bootstrap.skill` (rebuilt)
- [ ] **Step 1: Run the build script**
```powershell
pwsh scripts/build.ps1 -Names project-discipline,project-bootstrap
```
Expected output:
```
built: dist/project-discipline.skill
built: dist/project-bootstrap.skill
```
- [ ] **Step 2: Verify the archives**
```powershell
Get-ChildItem dist/project-discipline.skill, dist/project-bootstrap.skill | Format-Table Name, Length, LastWriteTime
```
Expected: both files exist, `LastWriteTime` is the current minute, sizes nonzero.
Spot-check the new archive's structure (no Compress-Archive backslash bug — see `.wiki/concepts/build-notes.md`):
```powershell
$arch = [System.IO.Compression.ZipFile]::OpenRead((Resolve-Path dist/project-discipline.skill))
$arch.Entries | Select-Object FullName | Format-Table -AutoSize
$arch.Dispose()
```
Expected: entries like `project-discipline/SKILL.md`, `project-discipline/README.md` — forward slashes only.
- [ ] **Step 3: Commit**
```powershell
git add dist/project-discipline.skill dist/project-bootstrap.skill
git commit -m "build: project-discipline@0.1.0 + project-bootstrap@1.5.0 archives"
```
---
## Task 9: Install on this machine
- [ ] **Step 1: Run installer**
```powershell
bash scripts/install.sh
```
(`install.sh` is portable — works in git-bash on Windows.)
Expected stdout: lines like `installed: project-discipline` and `installed: project-bootstrap` (and the rest of the skills, idempotent).
- [ ] **Step 2: Verify installed skills**
```powershell
Test-Path "$env:USERPROFILE\.claude\skills\project-discipline\SKILL.md"
Test-Path "$env:USERPROFILE\.claude\skills\project-bootstrap\SKILL.md"
Select-String -Path "$env:USERPROFILE\.claude\skills\project-bootstrap\SKILL.md" -Pattern '^version:'
Select-String -Path "$env:USERPROFILE\.claude\skills\project-discipline\SKILL.md" -Pattern '^version:'
```
Expected:
- both `Test-Path` return `True`
- `version: 1.5.0` for project-bootstrap
- `version: 0.1.0` for project-discipline
(No commit — install affects user-level state, not the repo.)
- [ ] **Step 3: Verify description length post-install**
```powershell
$c = Get-Content "$env:USERPROFILE\.claude\skills\project-discipline\SKILL.md" -Raw
$start = $c.IndexOf('description: >') + 'description: >'.Length
$end = $c.IndexOf('---', $start)
$desc = $c.Substring($start, $end - $start).Trim()
"description chars: $($desc.Length)"
```
Expected: ≤ 900. (Per `feedback_skill_description_length_limit` memory.)
---
## Task 10: Manual smoke validation
No automated harness — describe what to verify in a fresh session.
- [ ] **Scenario 1 (skill listing):**
In a fresh Claude Code session in `claude-skills`, ask the agent: "what skills are available?" or list via `Skill` tool.
Expected: `project-discipline` appears in the listing with the description from frontmatter (not the H1 fallback). If the description is the H1 ("project-discipline"), the description was silently dropped — check length.
- [ ] **Scenario 2 (Rule 1 — convention override):**
In a fresh session, ask the agent to design a small feature that would normally produce a spec. Expected: agent writes spec to `.wiki/concepts/<topic>-design.md`, NOT `docs/superpowers/specs/`. (`brainstorming` skill default would be `docs/superpowers/specs/`; Rule 1 should override.)
- [ ] **Scenario 3 (Rule 2 — master-only):**
In a fresh session, ask the agent to "do a small refactor". Expected: agent makes changes on `master` branch, doesn't `git checkout -b`. If the task is borderline, agent asks "needs a branch?".
- [ ] **Scenario 4 (Rule 3 — version bump):**
Ask the agent to make any non-trivial edit to a `skills/<name>/SKILL.md` (e.g., add a sentence to body). Expected: the same commit (or the immediately next commit) bumps `version:` in frontmatter per PATCH/MINOR/MAJOR rules. The commit message includes `[vX.Y.Z]`.
- [ ] **Scenario 5 (Rule 4 — push permission default):**
After any commit-producing task, expect the agent NOT to push without asking. Expected: agent says something like "готов push'нуть в origin/master, ок?" and waits.
- [ ] **Scenario 6 (Rule 4 — grant + revoke):**
In a session, after the agent commits something, say "разреши автопуш". Then make another change. Expected: agent commits AND pushes without asking. Then say "отзови". Make a third change. Expected: agent commits but asks before pushing again.
- [ ] **Scenario 7 (Rule 4 — force-push exception):**
With auto-push granted, ask the agent to do something requiring `git push --force` (e.g., simulate by asking: "push --force, ок?"). Expected: agent still asks for confirmation, citing Rule 4 exceptions.
- [ ] **Scenario 8 (bootstrap upgrade on this very repo):**
Re-run `project-bootstrap` on `claude-skills` itself in a fresh session: "upgrade project". Expected: bootstrap detects `CLAUDE.md` exists, runs Step 5 idempotent merge, finds `follow project discipline` already present (we added it manually in Task 7), reports `CLAUDE.md already canon — no changes`.
If Task 7 was skipped, the merge would prompt to append the line. Either way the merge logic works.
- [ ] **Scenario 9 (description length regression check):**
Re-run the description length probe (Task 9 Step 3). If the value is > 900, the skill's listing will silently drop the description and substitute H1 — the skill's discoverability collapses. This caught a regression in `using-projects-meta` once; same check protects here.
- [ ] **Document results in `.tasks/STATUS.md` `Where I stopped` field**
After running scenarios, update the task block (Task 12 below) with which scenarios passed.
---
## Task 11: Wiki log + index
**Files:**
- Modify: `.wiki/log.md`
- Modify: `.wiki/index.md` (verify)
- [ ] **Step 1: Append log entry**
Append to `.wiki/log.md`:
```markdown
## [2026-05-01] decision | project-discipline — new policy skill (v0.1.0): four cross-project rules (conventions-over-defaults, master-only, semver-bumping, ask-before-push); bootstrap template gains canonical trigger; project-bootstrap 1.4.0→1.5.0; skill-versioning concept extended to all skills
```
- [ ] **Step 2: Verify `.wiki/index.md` lists the design page**
```powershell
Select-String -Path .wiki/index.md -Pattern 'project-discipline-design'
```
If absent, add a line under `## Concepts` (alphabetical position — between `pulling-before-work-design` and `repo-layout`):
```markdown
- [project-discipline-design.md](concepts/project-discipline-design.md) — design for project-discipline (four cross-project rules: conventions-over-defaults, master-only, semver-bumping, ask-before-push)
```
- [ ] **Step 3: Commit**
```powershell
git add .wiki/log.md .wiki/index.md
git commit -m "docs(wiki): log + index — project-discipline@0.1.0"
```
---
## Task 12: Tasks board entry — close
**Files:**
- Modify: `.tasks/STATUS.md`
- [ ] **Step 1: Insert a Done block at the top (after the header) for this task**
Edit `.tasks/STATUS.md` to add at the very top (immediately after the `_Updated:_` line and a blank line):
```markdown
## 🟢 [project-discipline-skill] — project-discipline skill + project-bootstrap 1.5.0 canonical trigger
**Status:** done
**Where I stopped:** `skills/project-discipline/` shipped at v0.1.0 (four rules: convention-override, master-only, semver-bumping, session-scoped push permission); `assets/CLAUDE.md.template` gains `follow project discipline` after `pull remote before work`; `project-bootstrap` 1.4.0→1.5.0 with new commentary paragraph in Step 5 + manifest table row in Step 5.5; `.wiki/concepts/skill-versioning.md` extended (Rule 3 expands version: requirement to ALL skills, not just infra subset); root `CLAUDE.md` dogfood line added; both archives rebuilt in `dist/`; installed via `install.sh`; description length verified ≤900 chars; smoke scenarios documented (1/8 verifiable inline; 2-7/9 require fresh sessions for full coverage); design rationale at `.wiki/concepts/project-discipline-design.md`
**Next action:** (none — kept until merged)
**Branch:** master
---
```
- [ ] **Step 2: Bump the `_Updated:_` line in STATUS.md**
Find:
```markdown
_Updated: 2026-05-01_
```
(or whatever current date is there)
Replace with:
```markdown
_Updated: 2026-05-01_
```
(Same date — keep current.)
- [ ] **Step 3: Commit**
```powershell
git add .tasks/STATUS.md .tasks/project-discipline-skill.md
git commit -m "tasks: close [project-discipline-skill]"
```
---
## Self-Review
**Spec coverage:**
- ✅ Skill activation rules (CLAUDE.md trigger + in-chat reference) → Task 1, 2
- ✅ Rule 1 (conventions over defaults) → Task 2 body section
- ✅ Rule 2 (master-only) → Task 2 body section
- ✅ Rule 3 (versioning, including unversioned-artifact and dist-rebuild clauses) → Task 2 body + Task 6 cross-link to skill-versioning concept
- ✅ Rule 4 (session-scoped push permission, with exceptions) → Task 2 body section
- ✅ Out-of-scope list → Task 2
- ✅ Template change → Task 4
- ✅ Bootstrap version bump + Step 5 commentary + Step 5.5 manifest row → Task 5
- ✅ skill-versioning concept extension → Task 6
- ✅ Dogfood in repo root → Task 7
- ✅ Build + install + description-length probe → Tasks 8, 9
- ✅ Validation scenarios (covering all four rules + bootstrap merge + length regression) → Task 10
- ✅ Wiki log + index → Task 11
- ✅ Tasks board close → Task 12
**Placeholder scan:** no TBD / TODO / "implement later". All steps have explicit code or commands. Manifest row and STATUS block have explicit text, not placeholders. The `<version>` literal in the manifest table is the existing template syntax (filled in by `project-bootstrap` at runtime), not an unfilled spot in this plan.
**Type / wording consistency:**
- Trigger line is `follow project discipline` everywhere (template, dogfood, commentary, README, design doc, plan).
- Skill name `project-discipline` everywhere (folder, frontmatter, archive, install path, log, README cross-link, manifest row).
- Version `0.1.0` for new skill, `1.5.0` for bootstrap — consistent across frontmatter, log entry, tasks block, build commit, install verification.
- "Master-only" / "master/main" wording consistent between Rule 2 and design doc.
- Push grant phrases ("разреши автопуш" / "allow auto-push") consistent between Rule 4 wording and validation scenarios.

View File

@@ -0,0 +1,266 @@
---
title: "project-discipline — четыре правила работы в проекте"
type: concept
updated: 2026-05-01
---
# project-discipline — четыре правила работы в проекте
_2026-05-01._
## Problem
Дисциплина в работе агента в проекте сейчас держится на двух источниках, которые друг с другом не согласованы:
1. **Defaults внешних скиллов** (superpowers и пр.) — например, `superpowers:brainstorming` пишет spec в `docs/superpowers/specs/YYYY-MM-DD-<topic>-design.md`. Этот путь зашит в скилл и применяется по умолчанию во всех проектах.
2. **Конвенции конкретного проекта** — например, в `claude-skills` spec'и живут в `.wiki/concepts/<topic>-design.md`, а не в `docs/superpowers/`. Эта конвенция нигде явно не объявлена; держится только на том, что текущий агент случайно читает `.wiki/CLAUDE.md` до того, как применить дефолт скилла.
В `claude-skills` это работает потому что репо плотно дисциплинирован. В **других** проектах того же пользователя такое не работает: агент по умолчанию пишет в `docs/superpowers/`, ветвится на feature-branches, забывает bump'ить версии скиллов, и push'ит без подтверждения.
Пользователь хочет четыре правила, действующие во всех его проектах:
1. **Project conventions > skill defaults** — то, что в `CLAUDE.md` / `.wiki/CLAUDE.md` / `.tasks/`, перекрывает defaults любого скилла.
2. **Master-only** — вся работа на главной ветке, никаких feature-branches без явного запроса.
3. **Versioning discipline** — bump version'у на каждом edit'е версионированного артефакта, по semver, в commit-message.
4. **Commit yes, push no** — каждый сеанс стартует с "ask before push"; разрешение на автопуш выдаётся устно в рамках сессии и обнуляется при её завершении.
Текущий механизм передачи кросс-проектных правил — строки-триггеры в `CLAUDE.md`, активирующие соответствующие скиллы (`use superpowers`, `use project wiki`, `pull remote before work`, и т.д.). `project-bootstrap` v1.4.0 уже умеет идемпотентный merge новых строк в существующий `CLAUDE.md` (см. [bootstrap-claude-md-merge.md](bootstrap-claude-md-merge.md)). Эта схема естественно расширяется на новый policy-скилл.
## Decision
Два артефакта:
1. **Новый policy-скилл `project-discipline`** (`skills/project-discipline/SKILL.md`, v0.1.0) — кодифицирует все четыре правила, активируется триггером `follow project discipline` в `CLAUDE.md`.
2. **`project-bootstrap` v1.4.0 → v1.5.0** (MINOR, добавляет capability) — новая строка в `assets/CLAUDE.md.template` сразу после `pull remote before work`. Идемпотентный merge в Step 5 переносит её в существующие проекты без ручного edit'а. `bootstrap-manifest.md` получает новую строку для `project-discipline`.
Этот репо (`claude-skills`) получает trigger'ную строку в свой `CLAUDE.md` как dogfood.
### Почему один скилл, а не четыре
Все четыре правила — про дисциплину работы в проекте, единая тема. Разделение на четыре скилла + четыре строки в `CLAUDE.md` (`use master-only`, `confirm before push`, и т.д.) раздуло бы template и плодит файлы. Если позже какое-то правило отделится в самостоятельный универсальный механизм — выделим его тогда. Сейчас YAGNI.
### Почему скилл, а не просто прямые строки в `CLAUDE.md` template
Прямые строки (`work on master only`, `commit but don't push`) тоже сработали бы как триггеры — каждая инструкция в `CLAUDE.md` имеет высший приоритет. Но:
- **Версионирование** — правила со временем меняются (например, добавится исключение для force-push). Если они зашиты в template и разосланы по N проектам, обновление = ручной edit в каждом. Скилл со своей версией обновляется централизованно.
- **Полнота описания** — четыре правила требуют ~150 строк подробной формулировки (что считается push'ем, какие исключения, как выдаётся grant). В `CLAUDE.md` это не помещается; в скилле — нормальный объём.
- **Обнаруживаемость** — `Skill` tool listing показывает скилл с описанием. Прямые строки в `CLAUDE.md` агент видит, но не воспринимает как один связанный набор.
## Skill behaviour
### Activation (description field)
Trigger conditions:
- `CLAUDE.md` содержит строку `follow project discipline` — скилл активируется при старте сессии и применяет все четыре правила к остальной работе.
- Пользователь явно ссылается на дисциплину: "use project discipline", "соблюди дисциплину", "проектные правила", "что у меня по правилам?".
Скилл сам по себе не выполняет действий и не имеет внешних эффектов; он — policy-документ, читаемый агентом.
### Rule 1 — Project conventions override skill defaults
**Текст правила в SKILL.md:**
> До применения defaults любого другого скилла (superpowers, frontend-design, mcp-builder, и т.д.), агент читает в этом порядке:
>
> 1. `CLAUDE.md` в корне проекта;
> 2. `.wiki/CLAUDE.md` (если существует);
> 3. `.tasks/STATUS.md` (если существует).
>
> Любой путь, формат, или workflow, явно указанный в этих файлах, **перекрывает дефолт скилла**.
>
> Конкретные следствия:
>
> - **Spec'и / design-документы** идут в `.wiki/concepts/<topic>-design.md`, **не** в `docs/superpowers/specs/`.
> - **Task tracking** — в `.tasks/<slug>.md` + `STATUS.md` (формат `using-tasks`), **не** в `docs/superpowers/plans/` или ином inline-формате.
> - **Frontmatter, naming-conventions, log-формат** — как описано в `.wiki/CLAUDE.md` проекта.
>
> Если конвенция не указана явно — применяется дефолт скилла.
**Почему:** в `claude-skills` это уже работает (поэтому `pulling-before-work-design.md` лежит в `.wiki/concepts/`, а не в `docs/superpowers/specs/`). Цель правила — перенести эту дисциплину в **другие** проекты пользователя, где она сейчас держится только на удаче.
### Rule 2 — Master-only
**Текст правила в SKILL.md:**
> Вся работа идёт на главной ветке репозитория — обычно `master`, но если проект использует `main`, скилл считает `main` эквивалентом.
>
> - Никаких `git checkout -b feature/foo` для соло-работы.
> - Sync с remote — `git pull --ff-only` или `git pull --rebase`. **Никаких merge-коммитов** для соло-работы.
> - Если задача реально требует изоляции (большой эксперимент, рискованный refactor с возможностью отката, multi-day работа с промежуточными WIP-коммитами) — агент **спрашивает** пользователя: "это требует отдельной ветки, ок?" — и ждёт явного разрешения. Без разрешения — на master.
>
> При detached HEAD или нахождении на не-главной ветке (например, после `git checkout`) — агент сообщает об этом и спрашивает, нужно ли вернуться на master перед работой.
**Почему:** соло-разработка с CI/CD не получает выгоды от feature-branches; PR-workflow это overhead для одного человека. Master-only сводит к нулю vocabulary "merge conflict / rebase onto / rebase interactive" в обычном дне.
### Rule 3 — Versioning discipline
**Текст правила в SKILL.md:**
> При редактировании любого артефакта с semver-полем агент **bump'ит версию перед коммитом** по правилам:
>
> - **MAJOR** (X+1.0.0) — ломает контракт. Переименование скилла, удаление триггеров, изменение layout, удаление публичных функций, breaking change в API.
> - **MINOR** (X.Y+1.0) — добавляет capability без ломки. Новый триггер, новый опциональный шаг, новая публичная функция.
> - **PATCH** (X.Y.Z+1) — wording, clarity, исправление опечаток без изменения поведения.
>
> Bump указывается в commit-message: `feat(<artifact>): … [v<X.Y.Z>]` или эквивалент. Точный формат подгоняется под convention'ы проекта (см. Rule 1).
>
> **Применяется к:** `skills/<name>/SKILL.md` (frontmatter `version:`), `package.json` (`"version":`), `pyproject.toml` (`version = `), `Cargo.toml` (`version = `), и любым другим semver-полям.
>
> **Если артефакт пакуется** в `dist/<name>.skill`, `dist/*.tgz` и т.п. — **rebuild** пакета в том же или следующем коммите. Забытые dist'ы — частая причина деплоя устаревшего бинаря.
>
> **Первый edit unversioned артефакта**, у которого ВОЗМОЖНО semver-поле (новый скилл без `version:`, новый `package.json` без `"version":`) — агент **добавляет** `version: 0.1.0` (или эквивалент) перед коммитом, не bump'ит существующее.
>
> **Не применяется к:** артефактам без semver-поля и без потенциала его иметь (concept-страницы wiki, README.md, скрипты shell без публичного интерфейса).
**Почему:** в `.wiki/concepts/skill-versioning.md` уже описана semver-схема, но (а) она была scoped только на infra-набор скиллов; (б) дисциплина держалась только на текущем агенте. Правило 3 расширяет её **на все** скиллы в этом репо и на все версионируемые артефакты в любом проекте.
**Расширение scope.** Концепт-страница `skill-versioning.md` будет обновлена с пометкой, что после v0.1.0 `project-discipline` требование версионирования действует **на все скиллы**, не только infra-subset. Communication-mode скиллы (caveman, ...) и discovery-скиллы (find-skills, active-platform) тоже получают `version:` поле в frontmatter — это разовый migration, отдельная задача после shipping `project-discipline`.
### Rule 4 — Commit yes, push no (session-scoped)
**Текст правила в SKILL.md:**
> **Старт каждой сессии:** агент находится в режиме **ask-before-push**. На каждый `git push` он спрашивает:
>
> > Готов push'нуть в `<remote>/<branch>` (N коммитов: <subjects>). Ок?
>
> и ждёт явного `yes` / `да` / `push` / эквивалента. Без подтверждения — не push'ит.
>
> **Выдача grant'а в сессии.** Пользователь говорит:
>
> - "разреши автопуш" / "allow auto-push" / "автопуш ок" / эквивалент
>
> — после этого агент push'ит без вопросов до конца сессии или до отзыва.
>
> **Отзыв grant'а в сессии.** Пользователь говорит:
>
> - "отзови автопуш" / "revoke auto-push" / "снова спрашивай" / эквивалент
>
> — агент возвращается в ask-mode.
>
> **Конец сессии — состояние не сохраняется.** Следующая сессия снова стартует в ask-mode. Это намеренно: grant выдаётся под конкретный текущий контекст (пользователь рядом, осознанно решил что push'ить безопасно), и не должен переживать смену контекста.
>
> **Исключения — всегда ask, даже с активным grant'ом:**
>
> - `git push --force` / `--force-with-lease` (перезапись истории);
> - `git push origin --delete <branch>` (удаление ветки);
> - push не в текущий tracked upstream (`git push other-remote ...`, `git push origin other-branch`);
> - push в главную ветку, требующий не-fast-forward (т.е. потребовался бы force).
>
> Логика: grant выдан под обычный fast-forward push в апстрим; всё остальное — отдельный класс операций, требует отдельного решения.
>
> **Что считается "push":** только команды семейства `git push`. Локальные коммиты, `git stash push`, и т.п. — не push, grant на них не нужен.
**Почему:** пользователь хочет чтобы каждая сессия начиналась с явного "коммить, но не пуш!" — даже если в прошлой сессии всё было разрешено. Это страховка от "вчера агент думал что все ок, сегодня он же думает что всё ок, и заpush'ил то что не должен был". Persistent grant (файл-флаг в проекте) был бы удобнее но менее безопасен — поэтому намеренно отвергнут.
### Out of scope
Скилл **не** делает:
- **Не модифицирует `CLAUDE.md`** — это работа `project-bootstrap`. Скилл — текстовая policy, не tooling.
- **Не enforce'ит правила через hooks / git hooks / pre-commit** — дисциплина агента, не CI. Если пользователь хочет твёрдый enforcement (например, `pre-push` hook, который ломается без явной env-переменной) — это отдельный setup-скилл, не часть `project-discipline`.
- **Не управляет `settings.json` permissions** — это `update-config`. Можно представить вариант, в котором `git push` запрещён по умолчанию через `permissions.deny: ["Bash(git push:*)"]`, и Rule 4 его временно ослабляет. Этот вариант **отвергнут** на v0.1.0: пользователь хочет policy-уровень, не tool-уровень. Если правило Rule 4 окажется недостаточным — вернёмся к идее.
- **Не проверяет наличие `.wiki/`/`.tasks/`** — это работа `setup-wiki`/`setup-tasks`/`project-bootstrap`. Скилл предполагает что layout уже на месте; если `.wiki/CLAUDE.md` отсутствует — Rule 1 просто не находит конвенций для override'а и работает как пустой fallback.
## Bootstrap integration
### `assets/CLAUDE.md.template`
Текущий вид:
```markdown
talk like a caveman
use superpowers
use project wiki
use task management system
check across all projects
pull remote before work
we're on Windows
```
После v1.5.0:
```markdown
talk like a caveman
use superpowers
use project wiki
use task management system
check across all projects
pull remote before work
follow project discipline
we're on Windows
```
`follow project discipline` ставится **после** `pull remote before work` и **до** платформенной строки — потому что:
- Pull остаётся первым в logical order'е (сначала подтягиваем код, потом думаем о правилах).
- `follow project discipline` логически суммирует все остальные триггеры, должна стоять близко к их концу.
- Платформенная строка — мета-конфиг, всегда последняя.
### `project-bootstrap` SKILL.md изменения
- Frontmatter: `version: 1.4.0``version: 1.5.0`.
- Step 5 — добавить параграф commentary о новой строке (по образцу commentary для `pull remote before work`):
> The `follow project discipline` line activates the `project-discipline` skill, which codifies four cross-project rules: (1) project CLAUDE.md / .wiki/CLAUDE.md / .tasks/ override skill defaults; (2) all work on master/main, no feature branches; (3) version bump on every edit per semver; (4) commit freely, push only after explicit per-session approval. Install the skill on the host if `project-discipline` is not in `~/.claude/skills/`; otherwise the trigger is silently dead like any other absent skill.
- Step 5.5 (manifest) — добавить `project-discipline` в таблицу:
```markdown
| Skill | Version | Role |
|---|---|---|
| `project-bootstrap` | <version> | orchestrator |
| `setup-wiki` | <version> | wiki canonical layout |
| `setup-tasks` | <version> | tasks canonical layout |
| `project-discipline` | <version> | cross-project policy |
```
Манифест читает `version:` из frontmatter `project-discipline/SKILL.md` как для остальных. Если скилл не установлен — `unknown`, как уже принято.
### Idempotent merge — что произойдёт в существующих проектах
Step 5 upgrade-mode (см. [bootstrap-claude-md-merge.md](bootstrap-claude-md-merge.md)) на следующем bootstrap:
1. Прочитает существующий `CLAUDE.md`.
2. Не найдёт substring `follow project discipline` в нём.
3. Покажет user'у diff: "Append 1 missing canonical trigger: `follow project discipline`?"
4. По подтверждению — допишет строку в конец.
Существующий порядок (например, если `we're on Windows` уже не в конце, а в середине) не пересортировывается — это сделанное решение upgrade-merge'а, чтобы не ломать пользовательские edit'ы.
## Cross-impact
| Файл | Изменение |
|---|---|
| `skills/project-discipline/SKILL.md` | новый, v0.1.0 |
| `skills/project-discipline/README.md` | новый |
| `skills/project-bootstrap/SKILL.md` | bump 1.4.0→1.5.0; commentary + manifest row |
| `skills/project-bootstrap/assets/CLAUDE.md.template` | +1 строка |
| `skills/project-bootstrap/README.md` | sync (упомянуть новый триггер) |
| `dist/project-bootstrap.skill` | rebuild |
| `dist/project-discipline.skill` | новый archive |
| `~/.claude/skills/project-discipline/` | install (через `install.sh` или `install.ps1`) |
| `CLAUDE.md` (этого репо) | +1 строка `follow project discipline` (dogfood) |
| `.wiki/concepts/skill-versioning.md` | заметка о расширении scope (Rule 3 теперь требует version: на ВСЕХ скиллах) |
| `.wiki/concepts/project-discipline-design.md` | этот файл |
| `.wiki/concepts/bootstrap-manifest.md` | regenerate с новой строкой |
| `.wiki/index.md` | +1 концепт-page link |
| `.wiki/log.md` | +1 entry `decision \| project-discipline — четыре правила работы в проекте` |
| `.tasks/project-discipline-skill.md` | новый task-file |
| `.tasks/STATUS.md` | новый 🔴 active block |
## Open questions
- **Нужен ли отдельный setup-скилл?** По образцу `setup-context7` / `using-context7`. Сейчас — нет: `project-discipline` ничего не устанавливает, просто policy. Если в будущем добавится tooling-enforcement (git hooks, settings.json overrides) — выделим `setup-project-discipline`.
- **Wide vs narrow Rule 3 scope.** Сейчас правило применяется ко **всем** артефактам с semver-полем. Если окажется что в каких-то проектах семвер реально неуместен (например, исследовательский notebook) — добавим explicit opt-out через `.wiki/CLAUDE.md` (`# project-discipline: skip versioning`).
- **Migration communication-mode скиллов на `version:`.** Это побочная работа после shipping `project-discipline`. Открывается отдельной задачей в `.tasks/`.
- **Отслеживание session-state Rule 4.** В текущей имплементации — чисто conversational ("я помню что разрешил"). Если auto-compaction обрезает раннюю часть сессии где был выдан grant — fallback на ask-mode (безопаснее). Это намеренно: лучше переспросить чем накосячить.
## References
- [bootstrap-claude-md-merge.md](bootstrap-claude-md-merge.md) — механизм идемпотентного merge, который перенесёт триггер в существующие проекты.
- [pulling-before-work-design.md](pulling-before-work-design.md) — образец policy-скилла + bootstrap-integration, который этот проект мимикрирует.
- [skill-versioning.md](skill-versioning.md) — текущая semver-схема, которую Rule 3 расширяет на все скиллы.
- [bootstrap-manifest.md](bootstrap-manifest.md) — формат манифеста, в который добавляется новая строка.

View File

@@ -1,7 +1,7 @@
--- ---
title: Skill versioning + bootstrap manifest title: Skill versioning + bootstrap manifest
type: concept type: concept
updated: 2026-04-28 updated: 2026-05-01
--- ---
# Skill versioning + bootstrap manifest # Skill versioning + bootstrap manifest
@@ -33,9 +33,11 @@ Bumped manually when `SKILL.md` is edited. No CI gate — discipline-based.
## What skills are versioned ## What skills are versioned
Currently only the **infrastructure** skills (the ones bootstrap touches and that govern project layout). Communication-mode skills (`caveman`, family) and discovery skills (`find-skills`, `active-platform`) aren't versioned — their content is "good copy-paste" and a snapshot mismatch isn't a layout problem. **Originally** only the **infrastructure** skills (the ones bootstrap touches and that govern project layout). Communication-mode skills (`caveman`, family) and discovery skills (`find-skills`, `active-platform`) were left unversioned — their content was "good copy-paste" and a snapshot mismatch wasn't a layout problem.
If we ever start packaging or marketplace-publishing the rest, we'll version them too. **As of `project-discipline` v0.1.0** (Rule 3), the requirement extends to **all** skills in this repo, regardless of category. Communication-mode and discovery skills also need `version:` in frontmatter; the migration is a separate one-time task tracked in `.tasks/`. Rationale: discipline-by-default is simpler than maintaining a list of "exempt" skills, and it costs nothing — `version: 0.1.0` is added on the next edit per the Rule 3 first-edit-unversioned clause.
If we ever start packaging or marketplace-publishing skills outside this repo, the same rule still applies.
## The manifest ## The manifest

View File

@@ -19,6 +19,7 @@ Catalog of all wiki pages. One line per page, organized by type. Updated on ever
- [install-portability.md](concepts/install-portability.md) — `install.sh` / `build.sh` rewritten to drop `mapfile` (bash 4+) and `find -printf` (GNU only) so stock macOS (bash 3.2 + BSD find) works - [install-portability.md](concepts/install-portability.md) — `install.sh` / `build.sh` rewritten to drop `mapfile` (bash 4+) and `find -printf` (GNU only) so stock macOS (bash 3.2 + BSD find) works
- [context7-setup.md](concepts/context7-setup.md) — switched context7 from manual MCP entries to the official plugin; API key in `.mcp.json` as `--api-key`; now also captured as `setup-context7` skill (one-time install/migrate flow with key discovery) - [context7-setup.md](concepts/context7-setup.md) — switched context7 from manual MCP entries to the official plugin; API key in `.mcp.json` as `--api-key`; now also captured as `setup-context7` skill (one-time install/migrate flow with key discovery)
- [projects-meta-skills.md](concepts/projects-meta-skills.md) — `setup-projects-meta` + `using-projects-meta` skill pair for the local `projects-meta-mcp` stdio server (cross-project tasks + shared Gitea wiki); local-first rule + two-step mutation pattern - [projects-meta-skills.md](concepts/projects-meta-skills.md) — `setup-projects-meta` + `using-projects-meta` skill pair for the local `projects-meta-mcp` stdio server (cross-project tasks + shared Gitea wiki); local-first rule + two-step mutation pattern
- [project-discipline-design.md](concepts/project-discipline-design.md) — design for project-discipline (four cross-project rules: conventions-over-defaults, master-only, semver-bumping, ask-before-push)
- [pulling-before-work-design.md](concepts/pulling-before-work-design.md) — design for the pulling-before-work skill (mode-3 + skip-on-dirty) - [pulling-before-work-design.md](concepts/pulling-before-work-design.md) — design for the pulling-before-work skill (mode-3 + skip-on-dirty)
- [repo-layout.md](concepts/repo-layout.md) — flat `skills/`, committed `dist/`, bash + PowerShell scripts; install model - [repo-layout.md](concepts/repo-layout.md) — flat `skills/`, committed `dist/`, bash + PowerShell scripts; install model
- [skill-versioning.md](concepts/skill-versioning.md) — why infra skills carry `version: <semver>` in frontmatter and how `project-bootstrap` records them in a per-project manifest - [skill-versioning.md](concepts/skill-versioning.md) — why infra skills carry `version: <semver>` in frontmatter and how `project-bootstrap` records them in a per-project manifest

View File

@@ -38,3 +38,4 @@ Parseable: `grep "^## \[" .wiki/log.md | tail -20`.
## [2026-04-30] decision | Step 5.7 mirror of Step 5.6 (projects-meta-mcp dependency detector / `setup-projects-meta` recommendation) accepted as future work; tracked as ⚪ Ready task `[bootstrap-recommend-projects-meta]`; deferred until first observed fresh-machine miss so detector signal is informed by real failure mode; concept page `projects-meta-skills.md` updated to reflect new stance ## [2026-04-30] decision | Step 5.7 mirror of Step 5.6 (projects-meta-mcp dependency detector / `setup-projects-meta` recommendation) accepted as future work; tracked as ⚪ Ready task `[bootstrap-recommend-projects-meta]`; deferred until first observed fresh-machine miss so detector signal is informed by real failure mode; concept page `projects-meta-skills.md` updated to reflect new stance
## [2026-04-30] decision | project-bootstrap@1.3.0 — Step 5 upgrade path turned idempotent: read existing CLAUDE.md → substring-diff vs template → confirm → append-only-missing; closes silent gap where pre-1.2.0 projects never picked up new canonical triggers (`check across all projects`, `we're on Windows`); platform line preserved if user pinned a non-host one; concept page `bootstrap-claude-md-merge.md` written; README CLAUDE.md row updated to note idempotent merge ## [2026-04-30] decision | project-bootstrap@1.3.0 — Step 5 upgrade path turned idempotent: read existing CLAUDE.md → substring-diff vs template → confirm → append-only-missing; closes silent gap where pre-1.2.0 projects never picked up new canonical triggers (`check across all projects`, `we're on Windows`); platform line preserved if user pinned a non-host one; concept page `bootstrap-claude-md-merge.md` written; README CLAUDE.md row updated to note idempotent merge
## [2026-05-01] decision | pulling-before-work — new policy skill (v1.0.0): one `git pull --ff-only` at session start + on-demand re-sync; bootstrap template gains canonical trigger; project-bootstrap 1.3.0→1.4.0 ## [2026-05-01] decision | pulling-before-work — new policy skill (v1.0.0): one `git pull --ff-only` at session start + on-demand re-sync; bootstrap template gains canonical trigger; project-bootstrap 1.3.0→1.4.0
## [2026-05-01] decision | project-discipline — new policy skill (v0.1.0): four cross-project rules (conventions-over-defaults, master-only, semver-bumping, ask-before-push); bootstrap template gains canonical trigger; project-bootstrap 1.4.0→1.5.0; skill-versioning concept extended to all skills

View File

@@ -7,4 +7,5 @@ use project wiki
use task management system use task management system
check across all projects check across all projects
pull remote before work pull remote before work
follow project discipline
we're on Windows we're on Windows

Binary file not shown.

BIN
dist/project-discipline.skill vendored Normal file

Binary file not shown.

View File

@@ -1,6 +1,6 @@
--- ---
name: project-bootstrap name: project-bootstrap
version: 1.4.0 version: 1.5.0
description: > description: >
Initializes or upgrades a project in the current folder: git, .gitignore, README.md, Initializes or upgrades a project in the current folder: git, .gitignore, README.md,
.wiki/ using Karpathy's method, .tasks/ for task tracking, CLAUDE.md with skill triggers. .wiki/ using Karpathy's method, .tasks/ for task tracking, CLAUDE.md with skill triggers.
@@ -264,6 +264,7 @@ use project wiki
use task management system use task management system
check across all projects check across all projects
pull remote before work pull remote before work
follow project discipline
we're on Windows we're on Windows
``` ```
@@ -281,6 +282,15 @@ upstream — never auto-merges, stashes, or pushes. Install the skill on the hos
if `pulling-before-work` is not in `~/.claude/skills/`; otherwise the trigger is if `pulling-before-work` is not in `~/.claude/skills/`; otherwise the trigger is
silently dead like any other absent skill. silently dead like any other absent skill.
The `follow project discipline` line activates the `project-discipline` skill,
which codifies four cross-project rules: (1) project CLAUDE.md / .wiki/CLAUDE.md
/ .tasks/ override defaults from any other skill; (2) all work on master/main,
no feature branches without explicit user approval; (3) version bump on every
edit of versioned artifacts per semver, recorded in commit; (4) commit freely,
push only after explicit per-session approval. Install the skill on the host
if `project-discipline` is not in `~/.claude/skills/`; otherwise the trigger is
silently dead like any other absent skill.
The `we're on Windows` line activates the `active-platform` skill and pins the The `we're on Windows` line activates the `active-platform` skill and pins the
project's default platform to Windows / PowerShell — so generated commands and project's default platform to Windows / PowerShell — so generated commands and
README quick-starts use PS-native syntax. Bootstrapping on a Linux or macOS README quick-starts use PS-native syntax. Bootstrapping on a Linux or macOS
@@ -311,6 +321,7 @@ Skills used to initialize this project's `.wiki/` and `.tasks/` layout, with the
| `project-bootstrap` | <version> | orchestrator | | `project-bootstrap` | <version> | orchestrator |
| `setup-wiki` | <version> | wiki canonical layout | | `setup-wiki` | <version> | wiki canonical layout |
| `setup-tasks` | <version> | tasks canonical layout | | `setup-tasks` | <version> | tasks canonical layout |
| `project-discipline` | <version> | cross-project policy |
This file is overwritten if `project-bootstrap` is re-run on the same project. For history, use `git log .wiki/concepts/bootstrap-manifest.md`. This file is overwritten if `project-bootstrap` is re-run on the same project. For history, use `git log .wiki/concepts/bootstrap-manifest.md`.
``` ```

View File

@@ -7,4 +7,5 @@ use project wiki
use task management system use task management system
check across all projects check across all projects
pull remote before work pull remote before work
follow project discipline
we're on Windows we're on Windows

View File

@@ -0,0 +1,29 @@
# project-discipline
Policy skill that codifies four cross-project discipline rules so the same
guarantees that hold in a tightly-maintained repo apply everywhere.
## When it triggers
- **Session start** — when `CLAUDE.md` contains the line `follow project discipline` (added by `project-bootstrap` v1.5.0+).
- **In-chat** — when the user says "use project discipline", "соблюди дисциплину", "проектные правила", or close variants.
## The four rules
1. **Project conventions over skill defaults.** `CLAUDE.md` / `.wiki/CLAUDE.md` / `.tasks/` override any other skill's defaults. Specs go to `.wiki/concepts/`, not `docs/superpowers/specs/`. Tasks to `.tasks/`, not `docs/superpowers/plans/`.
2. **Master-only.** All work on `master` (or `main`). No feature branches without explicit user approval.
3. **Semver discipline.** Bump `version:` in `SKILL.md` / `package.json` / `pyproject.toml` on every edit per MAJOR / MINOR / PATCH; record in commit message; rebuild `dist/` artifacts after.
4. **Commit yes, push no.** Every session starts asking before push. User can grant auto-push within session ("разреши автопуш"); session end resets to ask-mode. Force / delete / non-ff push always asks.
## Prerequisites
None. The skill is a textual policy document; it takes no actions and has no
external dependencies. Activate it by adding `follow project discipline` to
`CLAUDE.md` (or use `project-bootstrap` v1.5.0+ which adds it automatically).
## Related
- `project-bootstrap` (v1.5.0+) — adds the trigger line to new and existing projects' `CLAUDE.md`.
- `pulling-before-work` — companion skill activated by the canonical template; pulls origin once at session start (`git pull --ff-only`).
- `using-tasks` / `using-wiki` — the format conventions Rule 1 routes work into.
- `.wiki/concepts/project-discipline-design.md` (in `claude-skills`) — full design rationale.

View File

@@ -0,0 +1,123 @@
---
name: project-discipline
version: 0.1.0
description: >
Codifies four cross-project discipline rules: (1) project CLAUDE.md /
.wiki/CLAUDE.md / .tasks/ override defaults from any other skill (specs
go to .wiki/concepts/, not docs/superpowers/specs/; tasks to .tasks/,
not docs/superpowers/plans/); (2) all work on master/main, no feature
branches without explicit user approval; (3) bump semver on every edit
of versioned artifacts (SKILL.md frontmatter, package.json,
pyproject.toml) per MAJOR/MINOR/PATCH rules, recorded in commit message;
(4) commit freely, never push without explicit per-session user approval
— grant via "разреши автопуш" / "allow auto-push", revoke via "отзови"
/ "revoke", session end resets to ask-mode; force/delete/non-ff push
always asks. Activated by "follow project discipline" trigger in
CLAUDE.md (added by project-bootstrap v1.5.0+).
---
# project-discipline
> Four cross-project rules. Read at session start. Apply before any other skill's defaults touch paths, branches, versions, or remote pushes.
## When this runs
**At session start** — when `CLAUDE.md` contains the line `follow project discipline`. The skill is a policy document; the agent reads it and applies the four rules to all subsequent work in the session.
**On explicit reference** — when the user says "use project discipline", "соблюди дисциплину", "проектные правила", "что у меня по правилам?", or close variants asking about/applying the rules.
The skill itself takes no actions and has no external side-effects. It instructs the agent how to behave.
## Rule 1 — Project conventions override skill defaults
Before applying defaults from any other skill (superpowers, frontend-design, mcp-builder, etc.), read in this order:
1. `CLAUDE.md` in the project root.
2. `.wiki/CLAUDE.md` (if it exists).
3. `.tasks/STATUS.md` (if it exists).
Any path, format, or workflow explicitly stated in those files **overrides the skill default**.
Concrete consequences:
- **Specs / design documents** go to `.wiki/concepts/<topic>-design.md`, **not** `docs/superpowers/specs/`.
- **Task tracking / implementation plans** go to `.tasks/<slug>.md` plus a board entry in `.tasks/STATUS.md` (the `using-tasks` format), **not** `docs/superpowers/plans/` or any inline-in-chat plan format.
- **Frontmatter, naming conventions, log format** — as described in the project's `.wiki/CLAUDE.md`.
If no convention is stated explicitly — fall back to the skill default.
## Rule 2 — Master-only
All work happens on the repo's main integration branch — usually `master`, but if a project uses `main`, treat `main` as equivalent.
- No `git checkout -b feature/foo` for solo work.
- Sync with remote: `git pull --ff-only` or `git pull --rebase`. **No merge commits** for solo work.
- If a task genuinely requires isolation (large experiment, risky refactor with rollback potential, multi-day work with intermediate WIP commits) — **ask** the user: "this needs its own branch, ok?" — and wait for explicit approval. Without approval, work continues on master.
If the agent finds itself on a non-main branch (after a manual `git checkout`) or in detached HEAD — report it and ask whether to return to master before working.
## Rule 3 — Versioning discipline
When editing any artifact with a semver field, **bump the version before committing** per:
- **MAJOR** (`X+1.0.0`) — breaks the contract. Renames, removed triggers, layout changes, removed public functions, breaking API change.
- **MINOR** (`X.Y+1.0`) — adds capability without breaking. New trigger, new optional step, new public function.
- **PATCH** (`X.Y.Z+1`) — wording / clarity / typo fixes with no behavior change.
The bump is recorded in the commit message: `feat(<artifact>): … [vX.Y.Z]` or whatever convention the project uses (see Rule 1).
**Applies to:** `skills/<name>/SKILL.md` (`version:` in frontmatter), `package.json` (`"version":`), `pyproject.toml` (`version =`), `Cargo.toml` (`version =`), and any other semver field in any other manifest.
**If the artifact is packaged** as `dist/<name>.skill`, `dist/*.tgz`, etc. — **rebuild** the package in the same or the next commit. Forgotten dist artifacts are a common cause of deploying stale binaries.
**First edit of an unversioned artifact** that COULD have a semver field (a new skill without `version:`, a new `package.json` without `"version":`) — **add** `version: 0.1.0` (or its equivalent) before committing; do not bump anything.
**Does not apply to:** artifacts with no semver field and no potential for one (wiki concept pages, README.md, shell scripts without a public interface).
## Rule 4 — Commit yes, push no (session-scoped)
**Every session starts in ask-before-push mode.** On every `git push`, ask:
> Готов push'нуть в `<remote>/<branch>` (N коммитов: <subjects>). Ок?
(or its English equivalent if the user is communicating in English) and wait for explicit `yes` / `да` / `push` / equivalent. Without confirmation — do not push.
**Granting auto-push within a session.** When the user says:
- "разреши автопуш" / "allow auto-push" / "автопуш ок" / equivalent
— push without further confirmation until the end of the session or until revoked.
**Revoking auto-push within a session.** When the user says:
- "отзови автопуш" / "revoke auto-push" / "снова спрашивай" / equivalent
— return to ask-before-push mode.
**Session end resets to ask-mode.** The next session starts asking again, regardless of what was granted in the previous one. This is intentional: a grant is given for the current context (user nearby, consciously decided pushes are safe), and should not survive a context switch.
**Always ask, even with active grant:**
- `git push --force` / `--force-with-lease` (history rewrite);
- `git push origin --delete <branch>` (branch deletion);
- push to a remote/branch other than the current tracked upstream (`git push other-remote ...`, `git push origin other-branch`);
- push to the main branch that would require non-fast-forward (i.e. would need force).
A grant covers ordinary fast-forward push to the configured upstream. Anything else is a separate class of operation and needs its own decision.
**What counts as "push":** only `git push` family commands. Local commits, `git stash push`, etc. are not push; the grant does not apply.
## Out of scope
The skill **does not**:
- modify `CLAUDE.md` (that's `project-bootstrap`'s job);
- enforce rules via git hooks / pre-commit / CI (this is agent discipline, not tooling);
- manage `settings.json` permissions (that's `update-config`);
- check the existence of `.wiki/` / `.tasks/` (that's `setup-wiki` / `setup-tasks` / `project-bootstrap`); if a project doesn't have them, Rule 1 simply finds no overrides and falls back to skill defaults.
## Why this exists
In a tightly-disciplined repo (`claude-skills`) the four rules already hold by accident — the agent reads `.wiki/CLAUDE.md`, knows specs go to `.wiki/concepts/`, knows to bump `version:`, knows not to push without confirmation. In **other** projects of the same user, that discipline does not transfer: the agent uses `superpowers`' default `docs/superpowers/specs/`, branches on a whim, forgets `version:` bumps, and pushes without asking. This skill makes the discipline explicit and portable.
Full design rationale (why one skill instead of four, why a skill instead of inline `CLAUDE.md` lines, scope of each rule, push-permission mechanism choice) lives in `.wiki/concepts/project-discipline-design.md` (in this repo; in other projects bootstrapped from this repo, the design lives in `claude-skills`).