CtrlK
BlogDocsLog inGet started
Tessl Logo
SkillPublic

new-feat

Use when starting a piece of feature or fix work in this repository — taking or opening its GitHub issue, cutting the branch (a worktree on the local bare repo, an in-place branch on the remote environment) and producing the implementation plan, including the wiki pages the work will make stale and its observability plan. Also the step for turning a tracker finding into a branch without publishing it.

75

Quality

94%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide
SecuritybySnyk

Low

Low-risk findings worth noting

SKILL.md
Quality
Evals
Security

Start new work for $ARGUMENTS. If it is empty, ask for a feature name, an issue number, or a finding before doing anything.

What this run must produce

Four things, in this order — each depends on the one before:

  1. The issue. Taken by number when one exists, opened otherwise. The branch name is derived from its title, so nothing else can happen first.
  2. The branch. A worktree on the local bare repo, or an in-place branch on the remote environment — Step 1 decides which.
  3. The plan. Files, steps, the wiki pages the work makes stale, the changeset, and the observability plan.
  4. The plan, attacked. stress-plan run against it and every finding closed, before a line of code is written.

Report all four in the final message: issue number and its project status, branch name (and worktree path), the plan, and what the stress-test found.

Write the plan to NEW-FEAT.md at the root of the checkout, always — not only in a non-interactive run. It is this branch's blackboard as well as its plan: a long session gets compacted, and what survives a compaction is what was written down, not what was being held in context. Read it first after any compaction, before touching a file. Keep it current at every boundary — a step finished, a gate run, a commit made — and record a gate you have not run as NOT RUN rather than leaving it blank; that is a real value and usually the honest one. It is scratch, never committed.

Open it with the branch name and the issue, on lines of their own:

# NEW-FEAT — fix/example-branch

Issue: #412

The session-metrics collector reads those two lines to name the card's issue when the pull request closes several: the branch line proves the file is this branch's, and the Issue: line names its issue. For a tracker finding write the repository-qualified form, Issue: englishstreetventures/osn-tracker#601 — a bare #601 names a public issue. For several issues, list the branch's own first: Issues: #412, #415.

When a gate cannot run

Find out once, before Step 0, rather than failing each step in turn:

command -v gh >/dev/null && gh auth status >/dev/null 2>&1 && echo "gh: yes" || echo "gh: no"
[ -d /Users/ac/.work/osn.git ] && [ "$(uname)" = "Darwin" ] && echo PERSONAL || echo REMOTE

No gh or no network: the issue step's static form is the issue you would file, written into the report as write-issue §No network describes, and the branch still gets a name derived from that title. Never describe an issue as opened, moved or labelled when the command could not run. No user to answer a question: take the conservative default the step names, record it, continue. Nothing here is a stop.

Step 0 — The issue comes first

Every branch traces to an issue, so the work is visible before it starts.

Take an existing issue when $ARGUMENTS is a number or URL (#412, englishstreetventures/osn#412):

gh issue view 412 --repo englishstreetventures/osn --json number,title,body,labels

A review finding is the exception that already has an issue. An S-, P- or C- ID, or an osn-tracker# reference, names an issue in the private englishstreetventures/osn-tracker. Take it by number there. Do not open a duplicate in the public repo, and keep the finding's text out of the branch name — englishstreetventures/osn is public and its branch list is visible, so fix/timing-oracle-in-claim-compare publishes the defect before the fix lands. Name the branch after the area or the tracker number: fix/cire-api-claim-hardening, fix/tracker-601. The same rule covers the plan file and every commit message on the branch.

Otherwise open one with the write-issue skill. It picks the title, type and labels, writes a body that stands on its own, files it in the public repository, rates it through rate-complexity and adds it to the Project. The type sets the branch prefix below, so get it right there: Feature for new capability, Bug for something built that behaves wrongly, Task for the rest.

Then three things follow from the issue:

  • Status, which is the claim — first, because an issue another session holds ends the run here. If your brief carries CLAIMED: <repo>#<n> for this issue, the orchestrator that dispatched you holds it; go on. Otherwise run next-batch §Claim: held by another session → stop and report which; free → it moves the issue to In Progress in the OSN Platform project. The board calls need the project scope; if it is missing, say so and move it in the UI rather than skipping it.
  • The branch name — kebab-case the title, prefix it: feat/ for a Feature, fix/ for a Bug, chore/, refactor/ or docs/ for a Task. Step 1 checks the name is unused and cuts it; it does not derive its own.
  • Complexity — an issue write-issue just opened is already rated; do not rate it again. An existing issue taken by number with no complexity: label gets one now: invoke the rate-complexity skill, which proposes a rating from the issue body alone and asks the owner to confirm or amend it. Do this before the branch exists: the rating is the denominator every session-metrics query divides spend by, and one made later — with a token total already on screen — is contaminated and worthless. An unattended run rates it anyway and adds complexity:unconfirmed. Never rate from the diff, and never let the agent that does the work rate the work.

Step 1 — The branch

The probe above said PERSONAL or REMOTE. They differ in one thing: whether there is a bare repo to add a worktree to.

First fetch main and check the name is free, before cutting anything. On REMOTE, drop -C /Users/ac/.work/osn.git.

git -C /Users/ac/.work/osn.git fetch origin "+refs/heads/main:refs/remotes/origin/main"
git -C /Users/ac/.work/osn.git cat-file -e "origin/main:.claude/metrics/$(printf '%s' '<branch>' | tr -c 'A-Za-z0-9._-' '-' | sed 's/^-*//;s/-*$//').json" 2>/dev/null && echo "taken: card on main"
gh api "repos/englishstreetventures/osn/pulls?state=all&head=englishstreetventures:<branch>" --jq '.[] | "taken: #\(.number)"'

The refspec is explicit because a bare clone maps no remote-tracking refs: there a plain fetch origin main updates only FETCH_HEAD, and the worktree starts from a stale origin/main.

Any taken line means an earlier pull request used the name. Session-metrics cards join transcripts by branch name alone, so on a reused name tools/pr-metrics can separate the two pull requests' sessions only at the earlier merge, and any follow-up session on the earlier work lands on this card. Add -2 to the name and check again. Cut once: a session that cuts two branches leaves its spend on neither card.

PERSONAL — the bare repo at /Users/ac/.work/osn.git. Every piece of work gets its own worktree; never check the branch out inside an existing one (main/ included) — that mutates its state.

git -C /Users/ac/.work/osn.git worktree add /Users/ac/.work/osn.git/<dir> -b <branch> origin/main
(cd /Users/ac/.work/osn.git/<dir> && bun install --frozen-lockfile)      # a fresh worktree has no node_modules

<dir> is the branch name without its prefix. If the work stacks on another open PR's branch, cut from that branch instead of origin/main and record the base, or prep-pr opens the PR against main:

git -C /Users/ac/.work/osn.git worktree add /Users/ac/.work/osn.git/<dir> -b <branch> <parent-branch>
git -C /Users/ac/.work/osn.git/<dir> config branch.<branch>.gh-merge-base <parent-branch>

Report the branch, its base and the worktree path. All work happens in that worktree, so cd into it before anything else.

REMOTE — the repository is already checked out in the working directory. No worktree.

git checkout -B <branch> origin/main
[ -d node_modules ] || bun install --frozen-lockfile

If the session was given a designated claude/* branch, use that exact name instead of the one from Step 0 and never push to any other; if the check says it is taken, keep it and report the clash. -B makes a re-run idempotent; with uncommitted work in progress, switch without resetting.

Step 2 — The plan

Explore and plan; do not implement yet. Dispatch a Plan subagent when one is available, otherwise do it inline. If dispatched, open its prompt with TASK-BRANCH: <branch> on its own line — the collector reads it back out (tools/pr-metrics/index.ts, resolveDispatchBranch) to attribute the planning spend to this branch's card; without it the spend banks against whatever branch this session happened to be on.

Start in the wiki, not the source. The systems the work touches have pages holding their contract, finding history and observability — cheaper to read than to reconstruct from code. Follow the three-tier ladder in AGENTS.md §The wiki (detail in wiki/conventions/wiki-search.md) (Obsidian MCP when present, else the obsidian CLI, else grep), then open the source to confirm what the pages claim.

The plan names:

  • the existing files and patterns in play — Effect services, Elysia routes, Drizzle schema, SolidJS components — and the reference implementation elsewhere in the repo to copy from
  • the files to create or modify, and the steps in order
  • the wiki pages this work makes stale, by repo path — prep-pr has to update every one, and finding them now is cheaper than at PR time
  • for every config value the plan says to set, the file and line that reads it. No citation means the instruction is a guess, and a good implementer will implement the guess cleanly: a wrong config value produces a tidy diff, a green build and no behaviour change, which no gate can fail on. A value read in more than one place is two facts, not one
  • for a change to any build config, the directories that build writes and which of them are served publicly. "The build passes" and "the output is what I expected" are different claims
  • the issue's premise, and each wiki claim the design rests on, verified against the code. An issue states what was true when it was written, and a recently reviewed page can still be wrong about the one thing the plan needs. Cite the file and line that confirms each claim. Only the claims the design depends on, not every page read
  • for a change that moves, merges or deletes tested code, a table of each test case it deletes and the test that covers the same behaviour afterwards. A case with no new home is lost coverage, found now by stress-plan rather than after the commit by review-tests
  • the test plan: the E2E test that proves the feature, and the artifact it ends by producing. For any part that must also be tested in isolation, every way that part can fail, listed now, before its code. The isolated tests are one per entry, written before the code; no unit tests beyond that list, and none written after the code. For code that only an E2E flow covers, list each branch the code takes and the flow step that reaches it, in NEW-FEAT.md, before the code exists. Rules: wiki/conventions/testing-patterns.md §What to test, and when
  • Effect, WebSocket or E2E-encryption considerations, if any
  • for a change under .claude/skills/, the eval scenarios that score text it moves or rewrites. Find them with grep -l "<moved phrase>" .claude/evals/*/criteria.json, one search per phrase. For each scenario, say how its criteria's wording stays true after the change
  • the changeset — always needed unless every changed file is on the allowlist in scripts/changeset-required.sh; @cire/* packages are version-less and never share a changeset with a versioned one
  • the observability plan for every new service, route or service function — which error paths use Effect.logError and any new secret field for the redaction list; which functions get Effect.withSpan("<domain>.<operation>") and that outbound HTTP goes through instrumentedFetch; which counters or histograms join the owning metrics.ts, named {namespace}.{domain}.{subject}.{measurement} with a bounded string-literal attribute type — never a user, request or event id. wiki/shared/observability/overview.md holds the rules.

Step 3 — Attack the plan before building on it

Invoke the stress-plan skill with the path to NEW-FEAT.md. It hands the plan to a second model in a fresh context. Every finding is fixed in the plan, rejected in writing only when you can name the fact it got wrong, or escalated to the owner when its facts stand and the choice is theirs. Implementation starts when none is open and every escalation has an answer.

It decides for itself whether the plan is worth attacking — a rename or a flag on a value already traced to its reader is skipped, anything touching auth, schema, a Worker binding, a build config, more than one package, or a whole class of defect is not. Do not pre-empt that call; invoke it and let it skip.

This is the one gate with no downstream equivalent. prep-pr's reviews check the code against the plan; nothing else checks the plan against the repo.

Step 4 — Implement

While implementing, invoke the skill that already encodes the sub-task — UI, Cloudflare, TDD, debugging, brainstorming when scope is open, Obsidian syntax for any wiki edit. The routing table is references/skills-routing.md; when unsure whether one fits, invoke it — a wrong fit costs little.

Finish

Summarise the issue and its status, the branch (and worktree path), the plan, and what stress-plan found — how many findings, how many fixed, how many rejected and the fact each got wrong, and how many escalated to the owner and their answers. On PERSONAL, cd into the worktree before any implementation starts. When the user is happy with the implementation, prompt: "Ready to prepare this branch for a PR? Run /prep-pr to validate changesets, run tests, get performance and security reviews, and push the branch."

Repository

englishstreetventures/osn

Path

.claude/skills/new-feat/SKILL.md

Last updated
First committed

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.