From 8c7e17edcbaab11398f066fd5c2225aff6b755ae Mon Sep 17 00:00:00 2001 From: vitya Date: Fri, 1 May 2026 10:20:08 +0300 Subject: [PATCH] tasks: open [pulling-before-work-skill] with implementation plan --- .tasks/pulling-before-work-skill.md | 648 ++++++++++++++++++++++++++++ 1 file changed, 648 insertions(+) create mode 100644 .tasks/pulling-before-work-skill.md diff --git a/.tasks/pulling-before-work-skill.md b/.tasks/pulling-before-work-skill.md new file mode 100644 index 0000000..65aaad4 --- /dev/null +++ b/.tasks/pulling-before-work-skill.md @@ -0,0 +1,648 @@ +# pulling-before-work — 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 `pulling-before-work` (one pull at session start + on-demand re-sync) and wire it into the canonical `project-bootstrap` template, with the `claude-skills` repo dogfooding the trigger. + +**Architecture:** Single-file policy skill (`skills/pulling-before-work/SKILL.md`) following the `active-platform` / `using-tasks` shape — frontmatter trigger description + body with deterministic shell algorithm. `project-bootstrap` v1.4.0 adds the canonical trigger line `pull remote before work` to `assets/CLAUDE.md.template`; 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. + +**Tech Stack:** Markdown skills (no build for the skill body itself). Build pipeline: `scripts/build.ps1` produces `dist/.skill` archives. Install: `scripts/install.sh` (or `.ps1`). Spec lives at `.wiki/concepts/pulling-before-work-design.md`. + +--- + +## File Structure + +**New:** +- `skills/pulling-before-work/SKILL.md` — frontmatter + body, ~80–120 lines +- `skills/pulling-before-work/README.md` — short user-facing intro mirroring `skills/using-tasks/README.md` shape + +**Modified:** +- `skills/project-bootstrap/SKILL.md` — `version: 1.3.0` → `1.4.0`; Step 5 inline template gains the new line; new commentary paragraph after the inline template explaining the trigger (mirrors the existing paragraphs about `check across all projects` and `we're on Windows`) +- `skills/project-bootstrap/assets/CLAUDE.md.template` — `+ pull remote before work` before `we're on Windows` +- `CLAUDE.md` (repo root) — `+ pull remote before work` before `we're on Windows` (dogfood) +- `.wiki/log.md` — append decision entry +- `.wiki/index.md` — concept page link (added in spec commit; verify still listed) +- `.tasks/STATUS.md` — add `[pulling-before-work-skill]` block + +**Built:** +- `dist/pulling-before-work.skill` — new +- `dist/project-bootstrap.skill` — rebuilt + +--- + +## Task 1: New skill — frontmatter only + +**Files:** +- Create: `skills/pulling-before-work/SKILL.md` + +- [ ] **Step 1: Write the frontmatter** + +```markdown +--- +name: pulling-before-work +version: 1.0.0 +description: > + Pulls the current branch from origin once at session start and on explicit + re-sync requests. Use when CLAUDE.md contains the trigger line "pull remote + before work", or when the user says "sync", "resync", "pull", "обнови репо", + "git pull please", or close variants asking to refresh from the remote. + Runs `git pull --ff-only` — never auto-merges or rebases. Stays silent in + non-git folders. Prints one informational line and exits when there is no + origin remote, no upstream tracking, the working tree is dirty, or HEAD is + detached. Does not stash, commit, or push. Activated by `project-bootstrap` + v1.4.0+ via the canonical CLAUDE.md template. +--- + +# pulling-before-work +``` + +- [ ] **Step 2: Verify description length is under 900 chars** + +Run: +```powershell +$c = Get-Content skills/pulling-before-work/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/pulling-before-work/SKILL.md +git commit -m "feat(pulling-before-work): scaffold skill frontmatter" +``` + +--- + +## Task 2: New skill — body + +**Files:** +- Modify: `skills/pulling-before-work/SKILL.md` (append body) + +- [ ] **Step 1: Append the skill body after the H1** + +```markdown +> Pull from `origin` once when work starts. Don't auto-merge. Don't trample dirty work-trees. Don't ask twice in the same session unless asked. + +## When this runs + +**At session start** — once, when the skill is activated by the `pull remote before work` line in `CLAUDE.md`. The cycle below runs immediately. + +**On explicit re-sync** — when the user says any of: `sync`, `resync`, `pull`, `обнови репо`, `pull please`, `git pull`, `подтяни`, `pull from origin`. Re-runs the full cycle. There is no per-session counter; the user is always allowed to ask. + +**Never** before each commit, before each tool call, on every message, or in any other implicit cadence. Mode-3 ("start + on-demand") was the explicit design choice — see `.wiki/concepts/pulling-before-work-design.md`. + +## The pull cycle + +Run these checks in order. Print at most one line of chat output per run. + +### 1. Inside a git work-tree? + +```bash +git rev-parse --is-inside-work-tree 2>/dev/null +``` + +If the command fails or prints anything other than `true` → **exit silently, no chat output.** This is the not-a-git-repo case; the skill must not be noisy in random folders. + +### 2. Has an `origin` remote? + +```bash +git remote get-url origin 2>/dev/null +``` + +If the command fails (no such remote) → print one line and exit: + +``` +no origin remote — skip pull +``` + +### 3. Is the working tree clean? + +```bash +git status --porcelain +``` + +If the output is non-empty → print one line and exit: + +``` +working tree dirty — skipping pull. commit/stash, потом скажи "sync" +``` + +Never stash automatically. Stash-pop conflicts are exactly the friction this skill exists to remove. + +### 4. Is HEAD attached? + +```bash +git symbolic-ref -q HEAD +``` + +If the command fails (empty output, exit 1) → detached HEAD. Print: + +``` +detached HEAD — skip pull +``` + +### 5. Does the current branch have an upstream? + +```bash +git rev-parse --abbrev-ref --symbolic-full-name '@{u}' 2>/dev/null +``` + +Capture the upstream name (e.g. `origin/master`). If the command fails → no upstream tracking. Print: + +``` +no upstream tracking for — skip pull +``` + +(Where `` is `git rev-parse --abbrev-ref HEAD`.) + +### 6. Pull, fast-forward only + +```bash +git pull --ff-only +``` + +(No args — uses the configured upstream captured above.) + +Classify by exit code and stdout: + +| Result | Print | +|---|---| +| Already up to date | `✅ already up to date with ` | +| Fast-forward, N commits | `✅ pulled N commits from ` | +| Non-fast-forward / diverged (exit non-zero with "diverged" or "non-fast-forward" in output) | `⚠️ diverged from — resolve manually (git pull --rebase or merge); skill never auto-merges/rebases` | + +### Out of scope + +The skill never: + +- commits, stashes, or pushes +- recurses into submodules +- pulls from non-`origin` remotes +- pulls on detached HEAD +- runs auto-merge or auto-rebase +- runs more than once per session unless the user asks + +## Recovery hints + +If the skill skipped because of a dirty tree: + +```powershell +# Windows / PowerShell +git status # see what's dirty +git add . ; git commit -m "wip" +# then ask the agent: "sync" +``` + +```bash +# Linux / macOS +git status +git add . && git commit -m "wip" +# then say "sync" +``` + +If the skill reported `diverged`: + +```bash +# Option A: rebase your local commits on top of origin +git pull --rebase + +# Option B: explicit merge (creates a merge commit) +git pull --no-ff +``` + +The skill stays out of these decisions on purpose — both options have valid use cases and the user owns the choice. + +## Why this exists + +Stale local branches are a silent footgun: edits land on top of yesterday's `origin`, the divergence shows up at push time, and by then there's a chunk of work to rebase or merge on the wrong base. One pull at start covers the common case; an explicit re-sync trigger handles long sessions where someone pushed mid-flight. + +Full design rationale (mode choice, dirty-tree skip vs stash, `--ff-only` vs auto-merge, the upstream-check) lives in `.wiki/concepts/pulling-before-work-design.md`. +``` + +- [ ] **Step 2: Sanity-check the file rendered** + +Read the file back and confirm: +- Frontmatter still parses (no `---` accidentally inside the body) +- All six numbered steps are present +- Recovery hints block has both PowerShell and bash variants + +- [ ] **Step 3: Commit** + +```powershell +git add skills/pulling-before-work/SKILL.md +git commit -m "feat(pulling-before-work): skill body — pull cycle, recovery hints, rationale" +``` + +--- + +## Task 3: New skill — README.md + +**Files:** +- Create: `skills/pulling-before-work/README.md` + +- [ ] **Step 1: Write README** + +```markdown +# pulling-before-work + +Policy skill that pulls the current branch from `origin` once at session start +and on explicit re-sync requests. Designed to remove the "edited on stale base" +footgun without trampling dirty work-trees or auto-merging. + +## When it triggers + +- **Session start** — when `CLAUDE.md` contains the line `pull remote before work` (added by `project-bootstrap` v1.4.0+). +- **In-chat** — when the user says `sync`, `resync`, `pull`, `обнови репо`, `git pull please`, or close variants. + +Stays silent in non-git folders. Prints one informational line and exits in: +no `origin` remote, no upstream tracking, dirty work-tree, detached HEAD. + +## What it does + +`git pull --ff-only` against the configured upstream — never auto-merges, never +auto-rebases, never stashes, never commits, never pushes. On divergence it prints +a warning with manual-resolution hints and exits. + +## Prerequisites + +None. The skill is a no-op outside git repos and folders without an `origin` +remote, so it's safe to leave activated everywhere. + +## Related + +- `project-bootstrap` (v1.4.0+) — adds the trigger line to new and existing projects' `CLAUDE.md`. +- `.wiki/concepts/pulling-before-work-design.md` (in projects bootstrapped from this repo: this design lives in `claude-skills`) — full design rationale. +``` + +- [ ] **Step 2: Commit** + +```powershell +git add skills/pulling-before-work/README.md +git commit -m "docs(pulling-before-work): README" +``` + +--- + +## Task 4: Bootstrap template — add trigger line + +**Files:** +- Modify: `skills/project-bootstrap/assets/CLAUDE.md.template` + +- [ ] **Step 1: Insert the new line before the platform line** + +Current: +```markdown +# 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 +we're on Windows +``` + +Target: +```markdown +# 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 +we're on Windows +``` + +Use `Edit` with `old_string="check across all projects\nwe're on Windows"` → `new_string="check across all projects\npull remote before work\nwe're on Windows"`. + +- [ ] **Step 2: Verify** + +```powershell +Get-Content skills/project-bootstrap/assets/CLAUDE.md.template +``` + +Expected: the seven trigger lines above, in that order. + +- [ ] **Step 3: Commit** + +```powershell +git add skills/project-bootstrap/assets/CLAUDE.md.template +git commit -m "feat(project-bootstrap): template gains 'pull remote before work' trigger" +``` + +--- + +## Task 5: Bootstrap SKILL.md — version bump + Step 5 update + +**Files:** +- Modify: `skills/project-bootstrap/SKILL.md` + +- [ ] **Step 1: Bump version in frontmatter** + +Edit: +- `old`: `version: 1.3.0` +- `new`: `version: 1.4.0` + +- [ ] **Step 2: Update the Step 5 inline template (mirror of `assets/CLAUDE.md.template`)** + +In Step 5, find the fenced markdown block: + +```markdown +talk like a caveman +use superpowers +use project wiki +use task management system +check across all projects +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 +we're on Windows +``` + +- [ ] **Step 3: Add commentary paragraph for the new trigger** + +After the existing paragraph that explains `check across all projects` and before the paragraph about `we're on Windows`, insert: + +```markdown +The `pull remote before work` line activates the `pulling-before-work` skill, +which runs one `git pull --ff-only` at session start (and on explicit re-sync +requests like "sync"). It's a no-op outside git repos and skips with a one-line +warning if the working tree is dirty, HEAD is detached, or the branch has no +upstream — never auto-merges, stashes, or pushes. Install the skill on the host +if `pulling-before-work` is not in `~/.claude/skills/`; otherwise the trigger is +silently dead like any other absent skill. +``` + +- [ ] **Step 4: Verify** + +```powershell +Select-String -Path skills/project-bootstrap/SKILL.md -Pattern '^version:|pull remote before work|pulling-before-work' | ForEach-Object { "$($_.LineNumber): $($_.Line)" } +``` + +Expected: at least 4 hits — `version: 1.4.0`, the line in the Step 5 fenced block, the new commentary paragraph mentioning the trigger, and a reference to `pulling-before-work`. + +- [ ] **Step 5: Commit** + +```powershell +git add skills/project-bootstrap/SKILL.md +git commit -m "feat(project-bootstrap): v1.4.0 — add 'pull remote before work' canonical trigger" +``` + +--- + +## Task 6: Dogfood — add trigger to claude-skills root CLAUDE.md + +**Files:** +- Modify: `CLAUDE.md` (repo root) + +- [ ] **Step 1: Insert the trigger before the platform line** + +Use Edit: +- `old`: `check across all projects\nwe're on Windows` +- `new`: `check across all projects\npull remote before work\nwe'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 +we're on Windows +``` + +- [ ] **Step 3: Commit** + +```powershell +git add CLAUDE.md +git commit -m "chore(claude-skills): dogfood 'pull remote before work' trigger" +``` + +--- + +## Task 7: Build artifacts + +**Files:** +- Build: `dist/pulling-before-work.skill` (new), `dist/project-bootstrap.skill` (rebuilt) + +- [ ] **Step 1: Run the build script** + +```powershell +pwsh scripts/build.ps1 -Names pulling-before-work,project-bootstrap +``` + +Expected output: +``` +built: dist/pulling-before-work.skill +built: dist/project-bootstrap.skill +``` + +- [ ] **Step 2: Verify the archives** + +```powershell +Get-ChildItem dist/pulling-before-work.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): +```powershell +$arch = [System.IO.Compression.ZipFile]::OpenRead((Resolve-Path dist/pulling-before-work.skill)) +$arch.Entries | Select-Object FullName | Format-Table -AutoSize +$arch.Dispose() +``` + +Expected: entries like `pulling-before-work/SKILL.md`, `pulling-before-work/README.md` — forward slashes, no backslashes. + +- [ ] **Step 3: Commit** + +```powershell +git add dist/pulling-before-work.skill dist/project-bootstrap.skill +git commit -m "build: pulling-before-work@1.0.0 + project-bootstrap@1.4.0 archives" +``` + +--- + +## Task 8: Install on this machine + +- [ ] **Step 1: Run installer** + +```powershell +bash scripts/install.sh +``` + +(`install.sh` is portable — works in git-bash on Windows. No `.ps1` exists yet; that's a separate ⚪ Ready task `[install-ps1]`.) + +Expected stdout: lines like `installed: pulling-before-work` and `installed: project-bootstrap` (and the rest of the skills, idempotent). + +- [ ] **Step 2: Verify installed skills** + +```powershell +Test-Path "$env:USERPROFILE\.claude\skills\pulling-before-work\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:' +``` + +Expected: +- both `Test-Path` return `True` +- `version: 1.4.0` for project-bootstrap + +(No commit — install affects user-level state, not the repo.) + +--- + +## Task 9: Manual smoke validation + +Validation per spec scenarios. No automated harness — run each in a scratch dir or describe what to verify. + +- [ ] **Scenario 1 (clean repo with remote, up to date):** + +```powershell +$tmp = Join-Path $env:TEMP "pull-smoke-1" +git clone https://github.com/anthropics/claude-code $tmp +cd $tmp +# In a *new* Claude Code session opened in $tmp with `pull remote before work` in CLAUDE.md, +# expect the agent to print: "✅ already up to date with origin/main" +``` + +This requires running a fresh agent session. Document the expected line in chat as proof. + +- [ ] **Scenario 2 (no remote):** + +```powershell +$tmp = Join-Path $env:TEMP "pull-smoke-2" +New-Item -Type Directory $tmp | Out-Null +cd $tmp +git init +"pull remote before work" | Out-File CLAUDE.md +# Open agent session here. Expect: "no origin remote — skip pull" +``` + +- [ ] **Scenario 4 (dirty tree):** + +In a clean repo with origin, `Set-Content -Path test.txt -Value "wip"`. Open agent session. Expect: `working tree dirty — skipping pull. commit/stash, потом скажи "sync"`. + +- [ ] **Scenario 8 (bootstrap upgrade on this very repo):** + +Re-run `project-bootstrap` on `claude-skills` itself: + +```powershell +# In a fresh Claude Code session in claude-skills root, say: "upgrade project" +# Bootstrap detects CLAUDE.md exists, runs Step 5 idempotent merge. +# Expected: it reports CLAUDE.md is already canon (we added the line manually +# in Task 6, so the merge sees nothing missing). No prompt to append. +``` + +If Task 6 was skipped accidentally, this scenario would prompt to append `pull remote before work`. Either way demonstrates the merge logic works. + +- [ ] **Document results in `.tasks/STATUS.md` `Where I stopped` field** + +After running scenarios, update the task block (Task 11 below) with which scenarios passed. + +--- + +## Task 10: 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 | 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 +``` + +- [ ] **Step 2: Verify `.wiki/index.md` lists the design page** + +```powershell +Select-String -Path .wiki/index.md -Pattern 'pulling-before-work-design' +``` + +If absent, add a line under `## Concepts`: + +```markdown +- [pulling-before-work-design.md](concepts/pulling-before-work-design.md) — design for the pulling-before-work skill (mode-3 + skip-on-dirty) +``` + +- [ ] **Step 3: Commit** + +```powershell +git add .wiki/log.md .wiki/index.md +git commit -m "docs(wiki): log + index — pulling-before-work@1.0.0" +``` + +--- + +## Task 11: Tasks board entry + +**Files:** +- Modify: `.tasks/STATUS.md` + +- [ ] **Step 1: Insert a Done block at the top (after the header) for this task** + +```markdown +## 🟢 [pulling-before-work-skill] — pulling-before-work skill + project-bootstrap 1.4.0 canonical trigger +**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/4/8 verified manually; design rationale at `.wiki/concepts/pulling-before-work-design.md` +**Next action:** (none — kept until merged) +**Branch:** master + +--- +``` + +- [ ] **Step 2: Commit** + +```powershell +git add .tasks/STATUS.md .tasks/pulling-before-work-skill.md +git commit -m "tasks: close [pulling-before-work-skill]" +``` + +--- + +## Self-Review + +**Spec coverage:** +- ✅ Skill description / activation rules → Task 1, 2 +- ✅ Pull cycle (6 steps incl. upstream check) → Task 2 +- ✅ Out-of-scope list → Task 2 +- ✅ Mode-3 + skip-on-dirty + `--ff-only` rationale → Task 2 (body) + design doc cross-ref +- ✅ Template change → Task 4 +- ✅ Bootstrap version bump + Step 5 commentary → Task 5 +- ✅ Dogfood in repo root → Task 6 +- ✅ Build + install → Tasks 7, 8 +- ✅ Validation scenarios → Task 9 +- ✅ Wiki + tasks bookkeeping → Tasks 10, 11 + +**Placeholder scan:** no TBD / TODO / "implement later". All steps have explicit code or commands. + +**Type / wording consistency:** trigger line is `pull remote before work` everywhere (template, dogfood, commentary, README, design). Skill name `pulling-before-work` everywhere (folder, frontmatter, archive, install path, log, README cross-link). Version `1.0.0` for new skill, `1.4.0` for bootstrap — consistent across frontmatter, log, tasks block.