SA

safe-git-workflow

Provides an ethotic, policy-aligned workflow for safe Git operations and hook management.

Install

mkdir -p .claude/skills/safe-git-workflow && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/18695" && unzip -o skill.zip -d .claude/skills/safe-git-workflow && rm skill.zip

Installs to .claude/skills/safe-git-workflow

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Use when git commands, commit hooks, admin-approved commits, protected hook paths, raw git bypass attempts, or commit attribution failures appear in agent or developer workflows.
178 chars✓ has a “when” trigger
Intermediate

Key capabilities

  • Recover from blocked git operations
  • Treat hook failures as policy feedback
  • Use `cerun_check` before risky Git work
  • Execute Git operations through `cerun_run` or `cerun` wrapper
  • Report files changed, checks run, and hook output
  • Request admin review for protected file changes

How it works

The workflow interprets git hook failures as policy feedback and guides the user to use `cerun_check` and `cerun_run` for validated operations. It prevents bypassing safety checks and ensures critical changes are reviewed.

Inputs & outputs

You give it
Blocked git operation or commit failure
You get back
Successful git operation or admin-approved commit

When to use safe-git-workflow

  • Resolving git hook failures
  • Executing critical commit operations
  • Managing commit attribution

About this skill

<!-- SPDX-FileCopyrightText: 2026 Blackcat Informatics® Inc. <[email protected]> --> <!-- SPDX-License-Identifier: AGPL-3.0-only -->

Safe Git Workflow

Use this skill to recover from blocked git operations without bypassing hooks, rewriting protected runtime files, or hiding the state that needs review.

ETHOS Grounding

  • one-path-for-critical-operations: Keep one explicit, validated path for critical operations.
  • no-rationalized-shortcuts: Do not discard work or bypass safety checks in the name of pragmatism.
  • forward-motion-only: Fix the current state instead of blaming history or prior authors.
  • evidence-based-engineering-and-decision-quality: Understand, plan, execute, and validate with evidence; measure before optimizing and make trade-offs explicit.

Short Hint

Git is a protected critical operation. Run normal git commands without bypass flags or shell indirection, keep hook failures visible, and ask an admin when policy blocks protected files.

Use When

  • raw git
  • cerun_check
  • cerun_run
  • cerun
  • admin-approved
  • commit attribution
  • hook bypass
  • no-verify
  • protected hook
  • commit failed

Remediation Workflow

  1. Read the hook failure as policy feedback, not as a broken local setup.
  2. Use MCP cerun_check before risky Git or shell work, then execute through MCP cerun_run or the repo-local cerun wrapper when the preflight allows it.
  3. Do not try alternate shells, absolute git paths, subprocesses, aliases, PATH edits, no-verify flags, or direct hook edits.
  4. If protected coding-ethos files must change, prepare the work and ask the admin to review and finalize the commit using the documented admin-approved flow.
  5. Report the files changed, checks run, hook output, and unresolved risks before asking for commit or push approval.

Principle Details

One Path for Critical Operations

When there are multiple ways to accomplish a critical operation, bugs hide in the less-traveled path.

Directive: Keep one explicit, validated path for critical operations.

Quick ref:

  • Keep one explicit, validated path for critical operations.
  • When there are multiple ways to accomplish a critical operation, bugs hide in the less-traveled path.
  • Use the repo's canonical validation entrypoint; do not invent partial substitutes.

Overview

When there are multiple ways to accomplish a critical operation, bugs hide in the less-traveled path. We enforce a single, canonical path for operations that matter.

No Modal Behavior Switches

We strictly ban boolean parameters that fundamentally change what a function does.

A parameter like persist: bool = True creates two different functions masquerading as one. Callers must understand not just what the function does, but which version they're invoking. This is a recipe for confusion and bugs.

The Anti-Pattern (Forbidden):

# ❌ WRONG: Boolean switch creates two code paths
async def onboard_dataframe(
    self,
    entity_id: str,
    dataframe: DataFrame,
    *,
    persist: bool = True,  # This creates a fork in behavior
) -> ProcessingResult:
    result = self._compute_schema_and_stats(dataframe)

    if persist:  # One code path: compute AND store
        await self._store_metadata(entity_id, result)
        await self._store_statistics(entity_id, result)

    return result  # Other code path: compute only

Why This Is Dangerous:

  1. Hidden Complexity: The function signature lies about what it does. Two behaviors, one name.
  2. Testing Burden: Both paths must be tested, but only one is typically exercised in production.
  3. Bug Magnet: Callers pick the wrong path. The bug we hit: persist=True bypassed ULID generation because it wasn't the canonical persistence path.
  4. Violation of SRP: The function has two reasons to change—computation logic OR persistence logic.
  5. Documentation Rot: Docstrings must explain both modes, inevitably becoming stale for one.

The Correct Way: Separate Concerns, Single Path

If an operation can be decomposed, decompose it. If persistence must happen, it happens through ONE designated service.

# ✅ CORRECT: Function does ONE thing
async def onboard_dataframe(
    self,
    entity_id: str,
    dataframe: DataFrame,
) -> ProcessingResult:
    """Compute schema and statistics for a dataframe.

    This function ONLY computes. It does NOT persist.
    Persistence is handled by EntityMetadataService.ingest_dataset().
    """
    return ProcessingResult(
        schema=self._infer_schema(dataframe),
        profile=self._compute_statistics(dataframe),
    )

# ✅ CORRECT: Orchestration layer calls the ONE persistence path
async def ingest(self, request: IngestionRequest) -> IngestionResponse:
    onboarding_result = await onboarding_service.onboard_dataframe(...)

    # THE canonical path for persistence—generates ULID, stores everything
    await dataset_service.ingest_dataset(entity_id, metadata_payload)

Identifying Modal Functions

Watch for these warning signs:

  • Parameters named persist, save, commit, execute, dry_run, skip_*
  • Boolean parameters that guard large if/else blocks
  • Functions where "it depends" on a flag whether side effects occur
  • Docstrings that say "If X is True, then... otherwise..."

Canonical Validation Entry Points

Repos must define one documented way to run quality gates locally.

If a repo documents make check, pre-commit run --all-files, or another validation entrypoint, use that path.

Do not substitute a hand-picked subset and then claim the work is validated.

Alternate commands may exist for debugging, but only the canonical gate proves readiness.

The Exception: Explicit Dry-Run at API Boundaries

A dry_run parameter is acceptable ONLY at the outermost API boundary (CLI commands, REST endpoints) where the user explicitly requests a preview. It must:

  1. Be clearly named and documented as a preview mode
  2. Execute the SAME code path but skip the final commit/write
  3. Never be the mechanism for internal code to "optionally" persist
# ✅ ACCEPTABLE: CLI dry-run for user preview
@cli.command()
def ingest(path: Path, dry_run: bool = False):
    """Ingest a dataset. Use --dry-run to preview without persisting."""
    result = service.ingest(path, dry_run=dry_run)
    # dry_run affects the FINAL write, not internal behavior

Anti-Patterns (Forbidden)

  • def process(data, save: bool = True) — modal persistence
  • def validate(schema, strict: bool = False) — if strictness matters, make two functions
  • def fetch(url, cache: bool = True) — caching is infrastructure, not a per-call decision
  • ❌ Internal functions with persist, commit, or store boolean parameters

The Rule

For any critical operation, ask: "Is there exactly ONE way to do this correctly?" If the answer involves "it depends on a boolean parameter," the design is wrong. Split the function, or designate a single orchestration point.

Repo Addendum

Keep generation routed through coding_ethos.cli.main() and the shared rendering pipeline instead of adding ad hoc writers for individual root files.

If output behavior changes, update the source YAML, renderer logic, and tests together rather than patching only one layer.

No Rationalized Shortcuts

We strictly ban any action that discards, bypasses, or destroys work under the rationalization of "pragmatism," "efficiency," or "complexity."

Directive: Do not discard work or bypass safety checks in the name of pragmatism.

Quick ref:

  • Do not discard work or bypass safety checks in the name of pragmatism.
  • We strictly ban any action that discards, bypasses, or destroys work under the rationalization of "pragmatism," "efficiency," or "complexity."
  • The following thought patterns are explicitly banned.

Overview

We strictly ban any action that discards, bypasses, or destroys work under the rationalization of "pragmatism," "efficiency," or "complexity."

This is the most insidious failure mode in automated systems: the agent that convinces itself that destroying weeks of work is acceptable because "it's taking too long" or "this is too complex." This behavior is not pragmatic—it is catastrophic negligence disguised as reasonable decision-making.

The Forbidden Rationalizations

The following thought patterns are explicitly banned. If you catch yourself thinking any of these, STOP IMMEDIATELY:

  • ❌ "This is taking too long, so I'll take a pragmatic approach..."
  • ❌ "This is too complex, so let me simplify by..."
  • ❌ "I don't have enough time/context, so I'll just..."
  • ❌ "To move forward efficiently, I'll skip..."
  • ❌ "Rather than evaluate each item, I'll batch..."
  • ❌ "The safest approach is to take all changes from one side..."
  • ❌ "I'll mark this as done and document what was skipped..."

These rationalizations ALWAYS precede destructive actions. They are the warning signs of impending catastrophe.

The Merge Catastrophe Pattern

The canonical example: During a complex merge with 50 commits requiring careful evaluation, the agent decides:

"This is becoming too complex. Let me take a pragmatic approach and accept all changes from the feature branch."

This single sentence destroys weeks of work. It:

  1. Discards all careful analysis that was the purpose of the task
  2. Potentially overwrites critical fixes from main
  3. Creates a "completed" task that is actually a time bomb
  4. Requires days of forensic work to even discover the damage

The Anti-Pattern (Forbidden):

# ❌ CATASTROPHIC: "Pragmatic" merge that discards work
git checkout feature-branch
git merge main -X theirs  # "Accept all from feature to resolve conflicts"
git commit -m "Merged main into feature"
# WEEKS OF WORK DESTROYED IN ONE COMMAND

The Correct Way:

# ✅ CORRECT: If merge is complex, acknowledge complexity honestly
# Option 1: Continue methodically, one conflict at a time


---

*Content truncated.*

When not to use it

  • When bypassing hooks is acceptable
  • When rewriting protected runtime files is intended
  • When hiding state that needs review is desired

Limitations

  • Does not allow bypassing hooks
  • Does not permit rewriting protected runtime files
  • Does not allow hiding state that needs review

How it compares

This workflow enforces a single, validated path for critical Git operations, preventing ad-hoc bypasses or shortcuts that can introduce bugs, unlike a manual approach where users might attempt various methods to force a commit.

Compared to similar skills

safe-git-workflow side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
safe-git-workflow (this skill)02moReviewIntermediate
glab62moReviewIntermediate
bash-linux76moReviewIntermediate
azure-devops-cli44moReviewBeginner

Try saying

Example prompts that trigger this skill in your AI assistant.

You might also like

glab

NikiforovAll

Expert guidance for using the GitLab CLI (glab) to manage GitLab issues, merge requests, CI/CD pipelines, repositories, and other GitLab operations from the command line. Use this skill when the user needs to interact with GitLab resources or perform GitLab workflows.

664

bash-linux

davila7

Bash/Linux terminal patterns. Critical commands, piping, error handling, scripting. Use when working on macOS or Linux systems.

753

azure-devops-cli

github

Manage Azure DevOps resources via CLI including projects, repos, pipelines, builds, pull requests, work items, artifacts, and service endpoints. Use when working with Azure DevOps, az commands, devops automation, CI/CD, or when user mentions Azure DevOps CLI.

436

gitlab-ci-patterns

wshobson

Build GitLab CI/CD pipelines with multi-stage workflows, caching, and distributed runners for scalable automation. Use when implementing GitLab CI/CD, optimizing pipeline performance, or setting up automated testing and deployment.

1030

create-worktree-skill

disler

Use when the user explicitly asks for a SKILL to create a worktree. If the user does not mention "skill" or explicitly request skill invocation, do NOT trigger this. Only use when user says things like "use a skill to create a worktree" or "invoke the worktree skill". Creates isolated git worktrees with parallel-running configuration.

213

domain-dns-ops

steipete

Domain/DNS ops across Cloudflare, DNSimple, Namecheap for Peter. Use for onboarding zones to Cloudflare, flipping nameservers, setting redirects (Page Rules/Rulesets/Workers), updating redirect-worker mappings, and verifying DNS/HTTP. Source of truth: ~/Projects/manager.

27

Search skills

Search the agent skills registry