agentleFS
cohen-lielcohen-liel/agent-skills/ssot-enforcer/SKILL.md

ssot-enforcer

Skill15 starsChanged 5 months agoMITView on GitHub

Single-source-of-truth refactoring and review workflow. Use when encountering duplicated logic, scattered constants/configuration, parallel implementations, repeated calculations, local policy decisions, model/tool routing outside central registries, or user requests mentioning SSOT, centralize, deduplicate, unify, "two places doing the same thing", "why is this implemented manually", or behavior that should go through shared service/config/registry files. Do not use for merely similar code with different contracts or lifecycles.

The file

Show its rules and text

We split this skill into the rules it gives an agent

21 rules. About 0 are common, 19 are distinctive, and 2 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈19

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 2

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Use this skill to keep behavior centralized.

    line 8
  2. Very specific:

    If duplication is discovered while debugging a concrete failure, first use root-cause-first to prove the failure mechanism.

    line 23
  3. Distinctive:

    If code needs a value, decision, calculation, route, permission, timeout, cost, model choice, parser rule, or state transition that already …

    line 34
  4. Distinctive:

    Do not use this skill for:

    line 38
  5. Distinctive:

    Search for the same constant, enum value, route, model ID, timeout, regex, calculation, parser, state transition, or decision phrase.

    line 46
  6. Distinctive:

    Read both the producer and consumer paths.

    line 47
  7. Distinctive:

    Prefer existing central modules over new abstractions.

    line 51
  8. Distinctive:

    Look for registries, config files, shared services, domain utilities, provider interfaces, and type definitions.

    line 52
  9. Distinctive:

    If no owner exists, create the smallest central owner in the natural module boundary.

    line 53
  10. Distinctive:

    Do not unify when similar code serves different contracts, different lifecycle boundaries, or intentionally separate contexts.

    line 57
  11. Distinctive:

    If not unifying, state why the duplication is intentional and how drift is prevented.

    line 58
  12. Very specific:

    If the duplication caused a concrete bug or regression, keep the original failure from root-cause-first as the verification target.

    line 59
  13. Distinctive:

    Keep adapters thin: translate inputs/outputs, but do not make policy decisions.

    line 64
  14. Distinctive:

    Add or update tests at the owner level.

    line 67
  15. Distinctive:

    Add one call-site regression test when previous duplication caused a bug.

    line 68
  16. Distinctive:

    Prefer typed unions/const objects over magic strings.

    line 69
  17. Distinctive:

    Check for drift after the patch.

    line 71
  18. Distinctive:

    Search again for old constants, duplicated logic, and hardcoded values.

    line 72
  19. Distinctive:

    Remove dead exports introduced during consolidation.

    line 73
  20. Distinctive:

    Ensure the final behavior is controlled from the source of truth.

    line 74
  21. Distinctive:

    When this skill affects the work, include:

    line 134

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

SSOT Enforcer

Use this skill to keep behavior centralized. The goal is to remove parallel sources of truth without creating unnecessary abstraction.

Red Flags — Stop If You Catch Yourself Thinking

ThoughtReality
"I'll just hardcode the timeout / URL / model ID here too"If it has an owner (config/registry), import it. A second copy will drift.
"I'll copy this regex/parser into the new component"Export the parser from one place; two copies diverge silently.
"These two blocks look the same, I'll merge them"Same shape is not the same responsibility. Merge only if they must change together.
"I'll add one local branch just for this case"Local policy branches are how a registry rots. Put the decision in the owner.
"It's quicker to recompute it in the UI"The UI may format a value; it must not re-derive the business rule.
"I'll wrap the call site with a fallback default"A fallback at the call site is a second source of truth for that default. Centralize it.

Relationship To Root Cause First

If duplication is discovered while debugging a concrete failure, first use root-cause-first to prove the failure mechanism. When the proven cause is scattered or duplicated truth, use this skill to consolidate ownership, then return to root-cause-first for regression verification against the original symptom.

Core Rule

One responsibility should have one owner:

  • Policy belongs in policy modules.
  • Configuration belongs in config/registry modules.
  • Calculations belong in calculation/domain modules.
  • Tool/model/service routing belongs in routing/provider registries.
  • UI formatting can adapt data, but should not reimplement business logic.

If code needs a value, decision, calculation, route, permission, timeout, cost, model choice, parser rule, or state transition that already has an owner, call the owner. Do not duplicate the rule locally.

When Not To Use

Do not use this skill for:

  • Code that only looks similar but serves different contracts, data shapes, lifecycle boundaries, or product contexts.
  • Pure presentation copy, one-off test fixtures, generated snapshots, or examples where drift cannot affect production behavior.
  • Greenfield feature work before there is a clear repeated responsibility or natural owner.

Required Workflow

  1. Scan for duplicate responsibility before editing.
    • Search for the same constant, enum value, route, model ID, timeout, regex, calculation, parser, state transition, or decision phrase.
    • Read both the producer and consumer paths.
    • Identify whether the duplication is exact, semantic, or only superficial.
  2. Identify the current or missing source of truth.
    • Prefer existing central modules over new abstractions.
    • Look for registries, config files, shared services, domain utilities, provider interfaces, and type definitions.
    • If no owner exists, create the smallest central owner in the natural module boundary.
  3. Decide whether to unify.
    • Unify when two places answer the same question or must change together.
    • Do not unify when similar code serves different contracts, different lifecycle boundaries, or intentionally separate contexts.
    • If not unifying, state why the duplication is intentional and how drift is prevented.
    • If the duplication caused a concrete bug or regression, keep the original failure from root-cause-first as the verification target.
  4. Move behavior to the owner.
    • Export a named function, typed constant, registry entry, or domain helper from the owner.
    • Replace local calculations/decisions with calls to that owner.
    • Keep adapters thin: translate inputs/outputs, but do not make policy decisions.
  5. Protect the contract.
    • Add or update tests at the owner level.
    • Add one call-site regression test when previous duplication caused a bug.
    • Prefer typed unions/const objects over magic strings.
  6. Check for drift after the patch.
    • Search again for old constants, duplicated logic, and hardcoded values.
    • Remove dead exports introduced during consolidation.
    • Ensure the final behavior is controlled from the source of truth.

Worked Example

Duplication (what to avoid). The free-shipping threshold lives in two places:

// checkout.js (server)
if (cart.total >= 50) order.shipping = 0;

// CartBanner.jsx (UI)
const remaining = 50 - cartTotal; // "Add $X for free shipping"

Marketing changes the threshold to 75. Someone updates the server and forgets the banner — now the banner promises free shipping that checkout does not give. One policy, two sources of truth, one production bug.

Consolidated. Give the policy one owner; let the UI adapt the value for display but not re-decide it.

// pricing.js — the owner
export const FREE_SHIPPING_THRESHOLD = 75;
export const qualifiesForFreeShipping = (total) => total >= FREE_SHIPPING_THRESHOLD;

// checkout.js
if (qualifiesForFreeShipping(cart.total)) order.shipping = 0;

// CartBanner.jsx
const remaining = Math.max(0, FREE_SHIPPING_THRESHOLD - cartTotal);

Counter-example — do NOT unify. These look identical today but answer different questions:

validateProductName(s)  // catalog rule: 1-100 chars
validateChatMessage(s)  // chat rule:    1-100 chars

They share a shape, not a responsibility. Product names may later allow 200 chars; chat may add emoji rules. Merging them couples two unrelated contracts, and the next requirement forces an awkward split. Keep them separate — the match is a coincidence, not a shared owner.

Verification. Grep for the old literal (50 and the duplicated >= check) and confirm only pricing.js owns the threshold.

Anti-Patterns To Block

  • Hardcoding a model ID, API URL, timeout, route, status, cost, or policy in a tool when a registry/config exists.
  • Reimplementing the same calculation in UI and server.
  • Adding "just this one" local branch for behavior that belongs in a provider, router, or domain module.
  • Copying a parser/regex into a second component instead of exposing a shared parser.
  • Creating a new helper that duplicates an existing helper with a different name.
  • Adding fallback behavior in a call site when the real fix is central contract enforcement.

Acceptable Local Logic

Local code may:

  • Validate local inputs before calling the owner.
  • Adapt transport/view shapes to domain shapes.
  • Handle presentation-only formatting.
  • Contain test fixtures that intentionally duplicate values for readability, when drift cannot affect production behavior.

Final Answer Shape

When this skill affects the work, include:

  • SSOT: what became or remained the source of truth.
  • Consolidated: which duplicate paths were removed or routed through it.
  • Verification: searches/tests proving no obvious duplicate source remains.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.