Skill snapshot
Skill anarefin/ai-agent-skills/merge-ears-workspace/skill-snapshot
Merge, combine, or consolidate two or more EARS (Easy Approach to Requirements Syntax) specification .md files into a single coherent EARS spec. Use this whenever the user wants to unify several requirement/EARS spec files — e.g. "merge these EARS specs", "combine the Member and Group specifications into one", "consolidate docs/ears/*.md into a single document", or any request to fold multiple per-domain/per-controller spec files into one. The skill deduplicates overlapping cross-cutting rules, entities, concepts, error-message rows and business rules (preserving every source reference), flags genuine conflicts for review instead of silently dropping them, and is project-neutral — it works on any set of EARS files that follow the standard section layout, not just one codebase.From its SKILL.md
npx -y skills add anarefin/ai-agent-skills --skill skill-snapshotAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 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.
SKILL.md
10.9 KB, ~2.4k tokens by cl100k_base, as published. Nobody here has run it
Merge EARS Specifications
You merge two or more EARS specification .md files into one standalone EARS spec.
The output must read as if it were authored as a single document — not a stapled-together pile of
files — while losing nothing: every business rule, entity, concept, error message, and source
reference from every input survives the merge.
You are structure-aware but project-neutral. You assume the input files follow the standard
EARS section layout (described in references/section-taxonomy.md), but you hardcode nothing about
any particular codebase, framework, or domain. Whatever domains the inputs describe, you merge them
faithfully.
The four governing decisions
- Consolidate & dedupe, but keep every reference. Overlapping content (shared cross-cutting
rules, shared entities, repeated concepts, identical error rows, identical business rules) is
merged into a single copy — but the surviving copy's
> **Source files:**annotation is the union of the source-file lists from every copy it absorbed. Origin information is never lost. - Ask for the merged system name. Each input scopes its statements to its own subject (e.g. "the Group Management system", "the Member Management system"). Ask the user what the merged system should be called, then rewrite every statement's subject to that one name.
- Flag conflicts, never drop them. When two inputs genuinely disagree (same entity described
with different property types/constraints, contradictory rules, same error condition mapped to
different messages), keep both versions and annotate them with a
[NEEDS REVIEW]marker that names the conflicting sources. Guessing a winner is forbidden. - Bias toward lossless. When you cannot confidently tell whether two statements express the same rule, keep both. Over-keeping is a minor cosmetic cost; silently dropping a real requirement corrupts the source of truth.
Workflow
Step 0 — Gather inputs (do not assume)
- Which files. Take the EARS files to merge from the user's request or arguments (paths or
globs). If none were given, list the candidate
.mdfiles (e.g. indocs/ears/) and ask which to combine. You need at least two. - Merged system name. Ask the user for the system name every merged statement should use (e.g. "the Member & Group Management system"). This is decision #2 — do not invent it silently.
- Output path. Default to
docs/ears/<MergedName>-EARS-Specification.md, derived from the system name, in the same directory as the inputs. Confirm or let the user override. Overwrite an existing file of that name.
Read every input file in full before writing anything. You cannot merge what you have not read.
Step 1 — Parse each input into canonical sections
Split each file by its markdown headings into the canonical section taxonomy. Read
references/section-taxonomy.md for the full section list and the exact merge rule for each one.
The taxonomy, in order:
- Title + front-matter blockquote
- Document Conventions
- System Overview
- Cross-Cutting Requirements (sub-blocks: Audit and Record Lifecycle; Authentication and Authorisation; Request Handling; Operational Cross-Cuts; Error Response Format + its error-condition→message table)
Module:sections (one or many; each may contain subsections,> **Source files:**annotations, and**Field-level validation — …:**blocks)- Domain Entities and Properties
- Domain Concepts and States
- Business Rules Summary (numbered)
- Open Questions
- Extraction Summary (metrics table + per-file ledger)
- Review by Developer (code)
- Review by Developer (business requirements)
Any heading you encounter that does not map to the taxonomy is carried through, never dropped —
collect such content and emit it under an ## Additional Sections heading near the end (before the
Review-by-Developer sections), noting which input it came from.
Step 2 — Merge section by section
Apply references/section-taxonomy.md's per-section rules. Summary:
- Title / front-matter. New title:
<MergedName> Business Requirements Specification (EARS). In the blockquote, set> **System name used in statements:** the <MergedName> system; set> **Source Entry Point(s):**to the union of all inputs' entry points; add> **Merged from:**listing the input filenames and the merge date. Keep the standard Format/Purpose/Note boilerplate. - Document Conventions. Identical across well-formed inputs — emit once. If an input adds a marker the others lack, include it.
- System Overview. Write one cohesive overview spanning all merged domains. Do not paste the inputs' overviews back to back; synthesize a unified narrative that still names each domain's distinct responsibilities.
- Cross-Cutting Requirements. Within each sub-block, gather every statement, normalize the subject to the merged name, then dedupe rules that are semantically the same. Surviving statements use the merged name. When two cross-cutting rules cover the same topic but differ in substance, keep both and flag (decision #3, #4).
- Error-condition → message table. Union all rows. Dedupe identical
(condition, message)pairs. If the same condition maps to different messages across inputs, emit a row for each and append[NEEDS REVIEW: <SourceA> vs <SourceB>]so the divergence is visible. - Module sections. Concatenate all
## Module:sections from all inputs in a sensible order (group related domains together). Keep each module's> **Source files:**annotations and**Field-level validation — …:**blocks intact and verbatim (these are not statement prose, so they keep their original file paths). Rewrite only the statement-subject to the merged name. If two inputs define a module with the same name, merge their subsections under one heading and flag any contradictory statements. - Domain Entities and Properties. Dedupe shared entities. Match entities by the domain file
in their
> **Source files:**line, not by heading text — the same entity often appears under different headings across inputs (e.g. "Member" vs "MemberInfo", "Project" vs "ProjectInfo", "Domain Status" vs "DomainStatus") while pointing to the same source file.- Same entity, identical property table → keep one copy; set its
> **Source files:**to the union of every copy's source files (decision #1). - Same entity, differing tables → emit the superset of properties (union of rows). For any
property whose Type/Meaning/Constraints conflict between inputs, keep both descriptions and
append
[NEEDS REVIEW: <SourceA> vs <SourceB>]to that row. Still union the source files. - Prefer the richer heading/description when names differ; you may note the alternate name.
- Same entity, identical property table → keep one copy; set its
- Domain Concepts and States. Same dedupe-by-meaning approach (e.g. Applicable Gender, Member Status, Data/Domain Status, Project Association Type recur across inputs). Identical → keep one + union refs; differing → keep both + flag.
- Business Rules Summary. Concatenate all rules, dedupe identical ones, then renumber contiguously from 1. Keep conflicting rules and flag them.
- Open Questions. Union and dedupe. Preserve any
[NEEDS REVIEW]breadcrumb footers verbatim. - Extraction Summary. Combine into one summary: sum the numeric metrics (controllers,
action services, statement-type tallies, etc.), union plugins/areas traced, and concatenate
the per-file coverage ledgers. Add a line:
Merged on <date> from <N> source specifications: <list>. - Review by Developer (code) and Review by Developer (business requirements). Keep both placeholder sections. Concatenate any non-empty findings from the inputs under the matching heading; if all inputs are empty, keep the single empty placeholder.
How to decide two statements are "the same rule"
Normalize away the system-name subject and trivial wording differences (articles, "shall"/"must" phrasing, British/American spelling). If what remains is the same condition acting on the same subject producing the same outcome, they are duplicates → keep one. If the condition, the subject entity, the threshold, or the outcome differs in any substantive way, they are not duplicates → keep both (and flag if they appear to contradict). When genuinely unsure, keep both (decision #4).
Step 3 — Self-check before finishing
Run the bundled checker against your output and fix anything it reports:
python3 ~/.claude/skills/merge-ears/scripts/check_merged_spec.py <output-file> \
--inputs <input1> <input2> [...] --system-name "<MergedName>"
It verifies the structural invariants: no duplicate entity headings, contiguous Business-Rules
numbering, no duplicate (condition, message) error rows, every [NEEDS REVIEW] marker names its
sources, and the merged system name is the subject used throughout (reporting any leftover original
subjects). Treat its findings as a checklist — resolve each before declaring the merge done.
Then report to the user: the output path, how many statements/entities/rules came in vs. went out
(showing what was deduped), and a list of every [NEEDS REVIEW] conflict you flagged so they know
what needs a human decision.
Anti-patterns (do not do these)
- Stapling files together. Four overviews, four Cross-Cutting blocks, the Country entity four times — that is concatenation, not a merge. Consolidate.
- Dropping a source reference during dedupe. The whole point of decision #1: the surviving copy must carry the union of source files. A reader must still be able to trace any rule back.
- Picking a winner in a conflict. When inputs disagree, you flag — you never quietly choose.
- Keeping mixed system-name subjects. After the merge, every statement says the one merged system name. Leftover "the Group Management system" sentences are a bug.
- Rewriting
> **Source files:**paths into prose or "merged-name" form. Those annotations are not statements; they keep their literal file paths (just unioned where entities were deduped).
What ships with it: 3 files
20.3 KB alongside SKILL.md, 1 of them executable
evals/
- evals.json3.5 KB
references/
- section-taxonomy.md8.3 KB
scripts/
- check_merged_spec.pyruns8.5 KB