Files
claude-skills/.tasks/pulling-before-work-skill.md

20 KiB
Raw Blame History

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/<name>.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, ~80120 lines
  • skills/pulling-before-work/README.md — short user-facing intro mirroring skills/using-tasks/README.md shape

Modified:

  • skills/project-bootstrap/SKILL.mdversion: 1.3.01.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

---
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:

$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
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

> 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 trueexit 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?

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?

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?

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?

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 <branch> — skip pull

(Where <branch> is git rev-parse --abbrev-ref HEAD.)

6. Pull, fast-forward only

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 <upstream>
Fast-forward, N commits ✅ pulled N commits from <upstream>
Non-fast-forward / diverged (exit non-zero with "diverged" or "non-fast-forward" in output) ⚠️ diverged from <upstream> — 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:

# Windows / PowerShell
git status            # see what's dirty
git add . ; git commit -m "wip"
# then ask the agent: "sync"
# Linux / macOS
git status
git add . && git commit -m "wip"
# then say "sync"

If the skill reported diverged:

# 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

# 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
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:

# 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:

# 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
Get-Content skills/project-bootstrap/assets/CLAUDE.md.template

Expected: the seven trigger lines above, in that order.

  • Step 3: Commit
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:

talk like a caveman
use superpowers
use project wiki
use task management system
check across all projects
we're on Windows

Replace with:

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:

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
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
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

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
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

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
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):

$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
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
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
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):
$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):
$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:

# 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:

## [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
Select-String -Path .wiki/index.md -Pattern 'pulling-before-work-design'

If absent, add a line under ## Concepts:

- [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
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

## 🟢 [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
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.