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.
In this repositoryOne other file it gives its agents.
- root-cause-firstSkill
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
- Distinctive: line 8
Use this skill to keep behavior centralized.
- Very specific: line 23
If duplication is discovered while debugging a concrete failure, first use root-cause-first to prove the failure mechanism.
- Distinctive: line 34
If code needs a value, decision, calculation, route, permission, timeout, cost, model choice, parser rule, or state transition that already …
- Distinctive: line 38
Do not use this skill for:
- Distinctive: line 46
Search for the same constant, enum value, route, model ID, timeout, regex, calculation, parser, state transition, or decision phrase.
- Distinctive: line 47
Read both the producer and consumer paths.
- Distinctive: line 51
Prefer existing central modules over new abstractions.
- Distinctive: line 52
Look for registries, config files, shared services, domain utilities, provider interfaces, and type definitions.
- Distinctive: line 53
If no owner exists, create the smallest central owner in the natural module boundary.
- Distinctive: line 57
Do not unify when similar code serves different contracts, different lifecycle boundaries, or intentionally separate contexts.
- Distinctive: line 58
If not unifying, state why the duplication is intentional and how drift is prevented.
- Very specific: line 59
If the duplication caused a concrete bug or regression, keep the original failure from root-cause-first as the verification target.
- Distinctive: line 64
Keep adapters thin: translate inputs/outputs, but do not make policy decisions.
- Distinctive: line 67
Add or update tests at the owner level.
- Distinctive: line 68
Add one call-site regression test when previous duplication caused a bug.
- Distinctive: line 69
Prefer typed unions/const objects over magic strings.
- Distinctive: line 71
Check for drift after the patch.
- Distinctive: line 72
Search again for old constants, duplicated logic, and hardcoded values.
- Distinctive: line 73
Remove dead exports introduced during consolidation.
- Distinctive: line 74
Ensure the final behavior is controlled from the source of truth.
- Distinctive: line 134
When this skill affects the work, include:
≈ “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.
Files
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
| Thought | Reality |
| "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
- 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.
- 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.
- 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-firstas the verification target.
- 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.
- 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.
- 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 charsThey 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.
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
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.

