agentsclimarketplace

Change control

Skill ats4321/claude-engineering-skills/skills/change-control

26 repository-agnostic engineering skills for Claude Code — debugging, design, review, validation, and AI engineering as operational runbooks.

Install
npx -y skills add ats4321/claude-engineering-skills --skill change-control

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Safe-change discipline for editing ANY repository. Auto-load before editing files, fixing bugs, refactoring, committing, pushing, publishing, deleting, uploading, or running any irreversible command. Covers read-before-edit, smallest-correct-diff at the root cause (not the symptom), checking every caller before changing a shared function, verifying flag/command behavior (e.g. DRY_RUN) before destructive actions, commit hygiene, when to branch, and never presenting unverified work as done. Trigger keywords: edit, fix, refactor, commit, push, publish, release, delete, migrate, rename, deploy, "make a change", "apply the fix".

SKILL.md

15.4 KB, as published. Nobody here has run it

Change Control

Purpose

Every change to a repository is a liability until it is understood, minimal, and verified. This skill is the discipline for making changes that are correct the first time: read before editing, fix the root cause with the smallest correct diff, verify anything irreversible before executing it, and never report work as done that you have not verified.

When to Use / When NOT to Use

Use when:

  • You are about to edit any file in any repository.
  • You are fixing a reported bug (a report names a symptom; you must find the cause).
  • You are changing a function, type, or config value that anything else might depend on.
  • You are about to run anything irreversible: commit, push, publish, delete, upload, migrate, force-anything.
  • You are about to tell a user "done", "fixed", or "working".

Do NOT use (load the complementary skill instead):

  • You don't yet understand the codebase you're changing → codebase-onboarding first.
  • You are diagnosing WHY something is broken (no fix identified yet) → debugging-playbook.
  • You are deciding WHAT tests to write for the change → validation-and-testing.
  • The change is a version bump / pin of a dependency → dependency-management (then return here to apply it).
  • The change is a release/publish workflow → build-and-release.
  • You suspect the change was tried before and reverted → failure-archaeology.

Core Methodology

Two universal rules govern every change: a fix belongs at the shared root cause, not per-caller, and the smallest diff in the wrong place is a second bug, not a small fix. Add nothing the change does not require (see engineering-minimalism for the full sizing doctrine).

Runbook

  1. Read before editing. Read the target file end to end (or the full relevant region for large files). Never edit from memory of a filename or a search-result snippet. If a rule, doc, or CLAUDE.md governs the repo, read it first.
  2. Trace the symptom to the cause. The reported line is where the failure surfaced, not necessarily where it originates. Walk the data backwards: who produced the bad value? Keep walking until you find the first place the invariant broke. That is where the fix goes.
  3. Enumerate every caller before changing shared code. Before touching a function, class, constant, env var, or config key, grep for every usage (see Discovery Commands). A fix that helps the reported call path but breaks or ignores sibling callers is incomplete. One guard in the shared function beats a guard in each caller.
  4. Choose the smallest correct diff. Correct comes first, smallest second. Do not restructure, rename, reformat, or "clean up while you're here". Unrelated changes hide the real change from review and from git bisect.
  5. Verify irreversible commands before running them. For any command that uploads, deletes, publishes, pushes, or migrates:
    • Read --help / docs for the exact flags you will pass. Never assume flag semantics — a flag named DRY_RUN may be a no-op, inverted, or unread by the code path you're on; confirm by reading the code or docs that consume it.
    • Prefer a dry-run/preview mode if one verifiably exists (--dry-run, -n, plan/preview subcommands).
    • Never use an --all style flag when exclusions were requested; enumerate targets explicitly.
    • List exactly what will be affected (files, packages, rows) before executing.
  6. Branch when the change is risky or exploratory. Branch if: the change spans multiple files, you're on the default branch, the change might be abandoned, or you're touching release machinery. Direct edits to a working tree are fine for a single-file, well-understood fix you will commit immediately.
  7. Verify, then commit with hygiene. Run the repo's test command and, when relevant, its build. One logical change per commit. The message states what changed and why, scoped by type (fix:, security:, tests:). Never commit secrets, .env files, or generated artifacts.
  8. Lock the fix in. A non-trivial fix gets one runnable check that fails if the fix regresses (see validation-and-testing). Hardening without a test is temporary.
  9. Report only verified state. "Done" means: you ran it (or its test) and observed the expected result. Anything else is "written but unverified" — say exactly that. Never present unverified work as done.

Decision tree: where does the fix go?

Bug reported at location L
├─ Is the bad value produced at L itself?
│   ├─ YES → fix at L (smallest diff)
│   └─ NO → trace to producer P
│       ├─ Does P have other callers/consumers?
│       │   ├─ YES → do they all need the invariant?
│       │   │   ├─ YES → fix once inside P (root cause)
│       │   │   └─ NO  → fix at the boundary between P and L,
│       │   │            document why siblings are exempt
│       │   └─ NO → fix inside P
│       └─ Is P a third-party dependency?
│           ├─ YES → pin/upgrade/wrap at YOUR boundary
│           │        (see dependency-management); never patch
│           │        symptoms at each call site
│           └─ NO → recurse: is P's input already bad?

Pre-irreversible-action checklist

Run this before ANY commit/push/publish/delete/upload/migrate:

  • I read the actual behavior of every flag I'm passing (docs or source), not what its name suggests.
  • I know the exact set of things affected and listed them.
  • A dry-run or preview was used if one verifiably exists.
  • No --all/wildcard when exclusions were requested.
  • Tests/build pass locally (or I have stated they were not run and why).
  • The diff contains only this change (git diff --stat reviewed).
  • No secrets, .env, or credentials in the diff (git diff scanned).
  • Multi-step operations (e.g. multi-package publish) have EVERY step written down before step one runs — the last step is the one that gets forgotten.
  • Rollback path known (revert commit? unpublish window? backup?). If there is no rollback, double all of the above.

Discovery Commands

All commands are repo-agnostic. Run from the repository root.

# --- Understand what you are about to change ---
git log --oneline -15 -- path/to/file        # recent history of the target file
git log -S "function_name" --oneline          # commits that added/removed this symbol
git blame -L 40,60 path/to/file               # who last touched these lines, and in which commit
git show <hash>                               # read the full commit that introduced the code

# --- Enumerate every caller before changing shared code ---
grep -rn "function_name" --include='*.py' .   # Python; use *.ts/*.tsx/*.js for JS/TS
grep -rn "CONFIG_KEY" .                       # config keys and env vars hide in docs, CI, scripts
grep -rln "from mymodule import" .            # import sites (Python)
grep -rn "require(.*mymodule" .               # CommonJS; grep "from ['\"]" for ESM

# --- Verify flags before irreversible actions ---
some-tool --help                              # read, do not assume
man some-tool                                 # when --help is terse
git push --dry-run                            # git supports dry-run on push
npm publish --dry-run                         # npm supports dry-run on publish
rsync -n ...                                  # rsync: -n / --dry-run
grep -rn "DRY_RUN" .                          # confirm a script actually READS the flag it advertises

# --- Pre-commit hygiene ---
git status && git diff --stat                 # exactly what is staged/changed
git diff                                      # line-level review of your own diff
git diff --name-only -z | xargs -0 -r grep -liE "api[_-]?key|secret|password|token"  # secret scan: -l prints FILENAMES only — never echo matched secret values into logs; inspect flagged files by eye

# --- Verification ---
pytest tests/                                 # Python (or: pytest -x for fail-fast)
npm test                                      # Node (repo may use `node --test`, vitest, jest — check package.json "scripts")
npm run build                                 # verify build before committing build-affecting changes

Ecosystem variants: Python uses pytest/python -m pytest; Node uses npm test/pnpm test; check package.json scripts or pyproject.toml rather than guessing the runner.

Failure Modes & Anti-patterns

SymptomMistakeCorrection
Fix works on the reported path, sibling path still brokenPatched the caller named in the ticket, not the shared producerGrep all callers; put one guard at the root cause
"Fixed" report bounces back immediatelyPresented unverified work as doneRun the test/command and observe the result before saying "done"
Data deleted/uploaded that shouldn't have beenAssumed a flag (e.g. DRY_RUN, --all) behaved as its name impliesRead docs/source for each flag; enumerate targets; never --all with exclusions pending
Two "fix" commits in a row for the same incidentFirst fix shipped without verifying the whole failure surfaceBefore committing, ask: what ELSE breaks the same way? Fix the class, not the instance
Reviewer can't find the real change in the diffReformatting/renaming bundled with the fixSmallest correct diff; separate commits for cosmetic changes
git bisect lands on a 40-file commitMultiple logical changes in one commitOne logical change per commit, scoped message
Regression of a fix months laterFix committed with no test locking it inPair every hardening/fix commit with a test commit (or same commit)
Secret appears in historyCommitted .env or hardcoded credentialsScan diff before commit; secrets live in env, never in tracked files
Release step silently skippedMulti-step irreversible process run from memoryWrite ALL steps down first; check each off; automate the "easy to forget" ones
Broken default branchRisky multi-file change made directly on mainBranch for anything risky, exploratory, or multi-file

Repository Examples

Repo facts below are EXAMPLES illustrating the methodology — never assumptions to bake into other repos.

PRISM — fix committed, then immediately locked in by tests (as of 2026-07-04) In ~/prism, commit 51b92c9 "security: add payload size limit, concurrency cap, repo name validation, Ollama timeout" was immediately followed by b011239 "tests: add security path coverage for signature, repo validation, size limit". This is step 8 executed correctly: the hardening commit and the commit that makes regression impossible ship as a pair. Note also the commit-message hygiene — typed prefix, exact enumeration of what changed.

RAGIT — the fix-after-fix chain (what step 7 prevents) (as of 2026-07-04) In ~/ragit: commit a1ad63ed "Pin chromadb to 0.4.x" was followed by 0a06ae9b "Pin numpy for chromadb 0.4 and add demo GIF" — chromadb 0.4 lacked a numpy<2 constraint, so pinning chromadb alone left numpy 2.0 free to break at runtime. Two successive pinning commits, caught by manual testing because the repo has no tests and no CI. Lesson: after the first fix, ask "what else fails the same way?" before committing — the numpy pin belonged in the same verified change.

RUFLO — the "EASY TO FORGET" last step of an irreversible process (as of 2026-07-04) ~/ruflo publishes three synced npm packages (@claude-flow/cli, claude-flow, ruflo) at the same version, with post-publish dist-tags required on ALL aliases. The docs explicitly mark the ruflo dist-tag "EASY TO FORGET", and commit "fix: @claude-flow/browser peer dep, dist-tags, bump to alpha.3" records a real slip. Publishing is irreversible; the checklist item "every step written down before step one runs" exists because of failures exactly like this.

Owner's saved lesson — verify flags before irreversible actions (as of 2026-07-04) From the owner's persisted memory: never assume flag behavior (e.g. DRY_RUN) before uploads/deletes, and never use --all when exclusions were requested. Encoded above as runbook step 5 and the checklist.

ASVER — declare constraints before they force a fix (as of 2026-07-04) ~/asver (Next.js 16 static deployment) carries commit "Remove server build from package.json for static deployment". The generalized lesson — declare deployment constraints early and strip violating steps up front rather than fixing after the fact — is partly inferred (hypothesis — requires verification).

Validation Criteria

You applied this skill correctly if, for the change you just made:

  1. You can name the file(s) you read in full before editing, and the commit/line where the invariant first broke.
  2. You can list every caller of anything shared you changed, and state why each is (or is not) affected.
  3. The diff contains nothing but the fix (git diff --stat shows only expected files).
  4. Every flag on every irreversible command you ran has documented behavior you actually read.
  5. A test or runnable check exists that fails if the fix regresses — or you explicitly justified why not (trivial one-liner).
  6. Your "done" report names the verification you ran and its observed output; unverified work is labeled unverified.
  7. Someone running git log in six months sees one scoped commit whose message explains itself.

Provenance & Maintenance

Sources: repo-specific knowledge from ~/prism, ~/ragit, ~/ruflo, ~/asver, investigated 2026-07-04, plus the owner's saved lesson on flag verification (2026-07-04). Methodology sections are repo-independent.

Assumptions made:

  • All referenced repos are local-first with zero CI — verification burden is entirely on the local runbook.
  • ASVER's "declare constraints early" lesson is partly inferred (marked hypothesis above).
  • Quoted commit hashes were verified 2026-07-04 and not re-verified in this session (git access unavailable at authoring time).

Re-verification commands:

git -C ~/prism log --oneline | head -5     # expect b011239, 51b92c9 present
git -C ~/ragit log --oneline | head -6     # expect 0a06ae9b, a1ad63ed present
git -C ~/ruflo log --oneline | head -10    # find the dist-tags fix commit
ls ~/prism/tests                            # expect test_security.py

Likely to drift: ruflo's publish process (package list, dist-tag steps); ragit's dependency pins (may be lifted when chromadb/numpy constraints change); presence/absence of CI in any repo (adding CI changes the verification story).

Maintenance checklist:

  • Re-run re-verification commands; update hashes/paths that moved.
  • If any repo gains CI, update the "verification burden is local" assumption.
  • Confirm the owner's flag-verification lesson still stands in their memory file.
  • Re-stamp all Repository Examples with the new verification date.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.