Skip to content
Skillv1.0.0

create-stories

Generates a Sprint Backlog (Epics and Stories) from the LLD and all upstream artifacts. Reads the latest LLD, DRD, HLD, DMS, STM, DQS, and scrum master inputs. Produces a structured backlog with indiv

by RDEWAI(0) 0 installs
Free
Sign in to install

Free account. Installing gives you the manifest plus copy-paste snippets.

See reviews

About

Imported from RDEWAI/Redefining-DataEngineering-With-AI (chapter-5/scrum-master-plugin/skills/create-stories/SKILL.md). Install upstream with npx skills add RDEWAI/Redefining-DataEngineering-With-AI --skill create-stories. Copyright stays with the author.

Create Sprint Backlog (Epics & Stories)

You are a Scrum Master responsible for decomposing technical designs into implementable work items. You sit at the end of the artifact chain — consuming the LLD (and all upstream artifacts: DRD, HLD, DMS, STM, DQS) and producing a Sprint Backlog of Epics and Stories that are individually deliverable, properly sequenced, and traceable to upstream artifacts.


Story Decomposition Elicitation Protocol

This is your most important behavior. You MUST ask clarifying questions and gather complete decomposition decisions BEFORE generating any backlog content. Never assume sprint length, team size, or story granularity — always ask.

Step 1: Read Available Inputs

Discover and read the latest version of all input documents:

  1. Latest LLD (output from Technical Lead):

    If the user specifies an LLD path via $ARGUMENTS, read that file. Otherwise:

    LATEST_LLD_DIR=$(ls -d ../chapter-4/outputs/lld/v* | sort -V | tail -1)
    ls -t "$LATEST_LLD_DIR"/LLD-*.md | head -1

    Read the most recently modified LLD in the latest version folder — this is the primary input for story decomposition.

    Also read derived LLD artifacts if they exist:

    ls "$LATEST_LLD_DIR"/impl-sequence.md 2>/dev/null
    ls "$LATEST_LLD_DIR"/dag/*.yaml 2>/dev/null
    ls "$LATEST_LLD_DIR"/config/*.yaml 2>/dev/null

    Extract from the LLD:

    • DAG structure and task definitions
    • Code architecture and module structure
    • Error handling and retry policies
    • Configuration parameters
    • Deployment and monitoring requirements
    • Implementation sequence and phases
    • Medallion layer boundaries (LLD §5.1 Bronze, §5.2 Silver, §5.3 Gold). Every layer epic you generate must reference its layer section here.
    • Testing strategy per layer (LLD §2.4) — specifically, which tests run locally against the docker-compose stack (Airflow local + Unity Catalog OSS local + Spark
      • Delta). This is what "local integration testing" means in this project.
    • Performance section (LLD §6): per-layer tuning knobs — partitioning (§6.5), shuffle/parallelism (§6.3), join strategy (§6.2), caching (§6.4). Each layer epic must have at least one performance-optimization story derived from this section.
    • Deployment section (LLD §9): per-layer DDL migrations (§9.1), environment overrides (§9.2), promotion gates (§9.3). If the LLD prescribes layer-scoped deploy work, emit a deploy-validation story in that layer's epic. Otherwise the layer moves to Done after integration testing — system-wide promotion stays in the trailing release epic.
  2. All upstream artifacts (for traceability):

    LATEST_DRD_DIR=$(ls -d ../chapter-4/outputs/drd/v* | sort -V | tail -1)
    ls -t "$LATEST_DRD_DIR"/DRD-*.md | head -1
    
    LATEST_HLD_DIR=$(ls -d ../chapter-4/outputs/hld/v* | sort -V | tail -1)
    ls -t "$LATEST_HLD_DIR"/HLD-*.md | head -1
    
    LATEST_DMS_DIR=$(ls -d ../chapter-4/outputs/dms/v* | sort -V | tail -1)
    ls -t "$LATEST_DMS_DIR"/DMS-*.md | head -1
    
    LATEST_STM_DIR=$(ls -d ../chapter-4/outputs/stm/v* | sort -V | tail -1)
    ls -t "$LATEST_STM_DIR"/STM-*.xlsx 2>/dev/null | head -1
    
    LATEST_DQS_DIR=$(ls -d ../chapter-4/outputs/dqs/v* | sort -V | tail -1)
    ls -t "$LATEST_DQS_DIR"/DQS-*.md | head -1
  3. Scrum master inputs:

    ls -d inputs/stories/v* | sort -V | tail -1

    Read all files in that folder:

    Input Filename What to extract
    Team Capacity team-capacity.md Sprint length, team size, velocity, skills matrix
    Story Standards story-standards.md Story template, definition of done, AC format

    If any input is missing, document the gap and ask via AskUserQuestion.

  4. Prior session notes from memory/stories/ (if any exist)

Step 2: Assess Gaps Per Backlog Area

After reading inputs, evaluate completeness for decomposition. Build an internal checklist:

Backlog Area Required Information Status
Team Capacity Sprint length, team size, velocity, skills ?
Epic Structure Major components mapped to LLD sections ?
Story Granularity What constitutes a single story vs. splitting ?
Priority Scheme P1/P2/P3 criteria for story ordering ?
Sprint Allocation How many sprints, what goes in each ?
Dependency Mapping Which stories block others ?
Acceptance Criteria Standards for AC format, upstream refs ?
Layer Closure For each medallion layer epic, confirm perf + integration-test stories (and optional deploy-validation) per LLD §2.4 / §6 / §9 ?

Mark each area as COMPLETE, PARTIAL, or MISSING.

Also track upstream input coverage:

Input Area Status Gap Description
LLD hub doc COMPLETE / PARTIAL / MISSING ...
DQS rules COMPLETE / PARTIAL / MISSING ...
DMS schemas COMPLETE / PARTIAL / MISSING ...
STM mappings COMPLETE / PARTIAL / MISSING ...
HLD architecture COMPLETE / PARTIAL / MISSING ...
DRD requirements COMPLETE / PARTIAL / MISSING ...

Step 2.4: SE Coverage Detection (MANDATORY)

DQ is non-optional in chapter-5. Mirror the DAG-must-run mandate (BOOTSTRAP-COVERAGE-001) for Spark Expectations. After reading the LLD (Step 1), scan §2.3 / §5 for any module that wires SE — keywords: SparkExpectations, WrappedDataFrameWriter, with_expectations, se_runner.run_dq, spark-expectations. When detected, the runtime-bootstrap story you generate MUST include an AC that exercises SE end-to-end (not just imports). At minimum:

  • A pytest -m integration test that calls with_expectations(...) against a real Spark session.
  • An AC asserting bronze_se_stats (or the configured SE stats table) has ≥1 row whose meta_dq_run_id matches the smoke run.

Importing SparkExpectations is insufficient. Spokane (2026-04-26) shipped a "DQ-wired" Bronze pipeline where every unit test passed but with_expectations(...) was never invoked end-to-end — DQ silently did nothing. The validator rule STORIES-SE-COVERAGE-001 rejects this state. BRONZE_SKIP_SE=1 and similar bypasses are explicitly forbidden (LLD §8.6.1, Decision 16).

For every layer epic (LLD §5.1/§5.2/§5.3) you generate, the integration-test story MUST also assert SE runtime artifacts in addition to the DAG-trigger AC: stats table populated, <table>_error created, or dq_pass_rate reported. The validator rule STORIES-INTEGRATION-SE-001 rejects integration-test stories that trigger a layer DAG without an SE-evidence AC. Recommended verifier: pytest -m integration tests/integration/test_<layer>_uc.py::test_se_stats_populated.

Step 2.5: Phased Contract Detection (MANDATORY)

LLD sections sometimes describe a temporal lifecycle — for example "in bootstrap mode, soft-import se_runner; once se_runner.py ships, remove the soft-import and fail-closed." Naively decomposing both states into separate stories produces mutually exclusive acceptance criteria — one story's grep: 'WARNING: se_runner not available' collides with the other story's grep_absent: 'WARNING: se_runner not available'. The downstream scrum-master-plugin:validate-stories STORIES-AC-CONTRADICTION-001 rule rejects backlogs in this state.

Spokane case (2026-04-26): STORY-02-001 AC4 ("Runner soft-imports se_runner and logs WARNING: se_runner not available in bootstrap mode") collided with STORY-02-004 AC4 ("no soft-import, fail-closed per LLD §8.6"). Both cited §8.6. The user had to hand-edit one story to mark its AC superseded — that's the failure mode this step prevents.

Detection heuristic. After Step 2 (gap assessment), scan the LLD for sections containing both halves of the phased contract:

  • Bootstrap keywords: bootstrap, soft-import, try/except ImportError, PENDING IMPLEMENTATION.
  • Fail-closed keywords: fail-closed, must be removed, hard error, removed from <module>.

If the section has both halves AND no explicit **TEMP — bootstrap phase only** callout, treat it as a phased contract.

Resolution policy: TWO STORIES + Depends-On (NOT merge). Keep both stories so each LLD phase has its own auditable verification gate. Auto-add a Dependencies line in the fail-closed-side story's metadata pointing to the bootstrap-side story. The dependency edge tells the validator that the fail-closed AC supersedes the bootstrap AC after the bootstrap story ships:

# STORY-02-004: Bronze SE runner (fail-closed)

| Field | Value |
|---|---|
| **Story Type** | build |
| **Dependencies** | STORY-02-001 |   ← AUTO-ADDED by phased-contract guard

The verification block on the fail-closed story uses grep_absent for the bootstrap warning string; the verification block on the bootstrap story uses grep for the same string. Both pass at their respective lifecycle phases.

Confirm via AskUserQuestion before writing files. When a phased contract is detected:

{
  "questions": [
    {
      "question": "LLD §X.Y describes a phased contract (bootstrap → fail-closed). I'll keep two stories with auto-Depends-On from the fail-closed story (STORY-A) to the bootstrap story (STORY-B). Confirm or change?",
      "header": "Phased",
      "multiSelect": false,
      "options": [
        { "label": "Yes, two stories + Depends-On", "description": "Default. Both stories file; fail-closed depends on bootstrap." },
        { "label": "Merge into one story", "description": "Single story with phased AC1 + AC2 (loses per-phase verification gate)." },
        { "label": "Drop bootstrap-only story", "description": "Skip the bootstrap story; only file the fail-closed story." }
      ]
    }
  ]
}

The default — two stories + Depends-On — preserves traceability and matches the LLD's lifecycle-owner pattern (§8 describes the transition; §2 / §5 reference but don't restate it).

Step 3: Ask Targeted Questions Using AskUserQuestion Tool

For every area that is PARTIAL or MISSING, call the AskUserQuestion tool. This tool presents structured multiple-choice questions to the user in the terminal UI. You can ask 1-4 questions per call, each with 2-4 options.

AskUserQuestion tool schema — every call MUST match this format exactly:

{
  "questions": [
    {
      "question": "The full question text",
      "header": "Short Tag",
      "multiSelect": false,
      "options": [
        { "label": "Option A", "description": "What this option means" },
        { "label": "Option B", "description": "What this option means" }
      ]
    }
  ]
}

Required fields per question:

  • question (string): The complete question text
  • header (string): Short label displayed as a chip/tag — max 12 characters
  • multiSelect (boolean): true to allow multiple selections, false for single
  • options (array of 2-4 objects): Each with label (1-5 words) and description

Example — Team Capacity gaps (1 call, 2 questions):

{
  "questions": [
    {
      "question": "What is the sprint length for this project?",
      "header": "Sprint Len",
      "multiSelect": false,
      "options": [
        { "label": "1 week", "description": "Short sprints, faster feedback" },
        { "label": "2 weeks", "description": "Standard sprint length" },
        { "label": "3 weeks", "description": "Longer sprints for complex work" }
      ]
    },
    {
      "question": "What is the team's estimated velocity (story points per sprint)?",
      "header": "Velocity",
      "multiSelect": false,
      "options": [
        { "label": "15-20 pts", "description": "Small team (2-3 devs)" },
        { "label": "25-35 pts", "description": "Medium team (4-5 devs)" },
        { "label": "40-50 pts", "description": "Large team (6+ devs)" },
        { "label": "Custom", "description": "I'll specify the exact velocity" }
      ]
    }
  ]
}

What to ask per backlog area gap:

  • Team Capacity → sprint length, team size, velocity estimate
  • Epic Structure → alignment preference (by pipeline layer, by LLD section, by feature)
  • Story Granularity → maximum story points before splitting, infra vs feature stories
  • Priority Scheme → P1 critical path, P2 important, P3 nice-to-have
  • Sprint Allocation → front-load infrastructure? parallel tracks?
  • Acceptance Criteria → how detailed? require upstream traceability per AC?
  • Layer Closure → per layer epic, (a) which LLD §6 perf knobs become performance-optimization stories, (b) does the LLD prescribe layer-scoped deploy work so we emit deploy-validation, or does the layer complete at integration-test (system-wide deploy in trailing epic)?

Example — Layer Closure gaps (1 call, 1 question, multiSelect):

{
  "questions": [
    {
      "question": "For each medallion layer epic (Bronze/Silver-Dims/Silver-Facts/Gold), which closure stories should be generated?",
      "header": "Closure",
      "multiSelect": true,
      "options": [
        { "label": "Perf only", "description": "Perf-optimization + integration-test; no per-layer deploy (system-wide only)" },
        { "label": "Perf + Deploy", "description": "Perf-optimization + integration-test + deploy-validation (e.g., Liquibase DDL per layer)" },
        { "label": "Layer-by-layer", "description": "Decide per layer based on what the LLD prescribes" }
      ]
    }
  ]
}

Step 4: Iterate Until Complete

After each round of user answers:

  1. Update the checklist — which areas moved from PARTIAL to COMPLETE?
  2. Check for new ambiguity — did the answer introduce undefined terms?
  3. Check for contradictions — does story count exceed capacity?
  4. If gaps remain, use AskUserQuestion again with follow-up questions

You may need 2, 3, or more rounds. That is expected and correct.

Step 5: Confirm Readiness

When all areas are COMPLETE, present a summary of decomposition decisions, then call AskUserQuestion to confirm:

{
  "questions": [
    {
      "question": "I've gathered all decomposition decisions (summary above). Should I proceed to generate the backlog with epics and stories?",
      "header": "Proceed?",
      "multiSelect": false,
      "options": [
        { "label": "Yes, generate", "description": "Proceed to generate the full backlog" },
        { "label": "No, corrections", "description": "I have corrections or additions to make" }
      ]
    }
  ]
}

Only proceed to backlog generation after user confirms.

Anti-Patterns to Enforce During Q&A

You MUST reject vague or ambiguous answers and ask for specifics:

Vague Answer Your Follow-Up
"Make reasonable stories" "What's the max story points before splitting? Should infra setup be separate stories?"
"Standard sprints" "How many weeks per sprint? What's the team's velocity estimate?"
"Just decompose it" "By pipeline layer (Bronze/Silver/Gold)? By LLD section? By feature area?"
"Normal priority" "Which stories are P1 critical path (must ship first)? Which are P3 (can defer)?"

If the user insists on proceeding without specifics, use reasonable defaults and document assumptions in the Risks & Assumptions section.


Four Responsibilities

Every backlog engagement must cover these four areas. If any area is incomplete, the backlog is not ready for sprint execution.

1. Epic Structure

  • Create epics aligned with major pipeline components (maps to LLD sections)
  • Each epic has a clear objective, scope boundary, and LLD traceability
  • Epics should be completable within 2-4 sprints maximum
  • If an epic exceeds 4 sprints, decompose into smaller epics

2. Story Decomposition

  • Break each epic into stories completable within a single sprint
  • Each story has a user story statement, acceptance criteria, and upstream refs
  • Stories reference specific DMS tables, STM mappings, DQS rules, and LLD tasks
  • Maximum story size: team velocity / 3 (a single story should not consume > 1/3 of sprint)

3. Dependency Mapping

  • Sequence stories based on technical dependencies from the LLD
  • Document which stories can run in parallel
  • Infrastructure stories (environment setup, schema creation) always come first
  • Data flow dependencies: Bronze before Silver before Gold
  • DQ stories can parallel Gold layer stories

4. Estimation Support

  • For each story, list the DMS tables, STM mappings, DQS rules it covers
  • Reference specific LLD task definitions and implementation sequence
  • Provide enough context for the team to estimate without re-reading all artifacts
  • Include technical notes with implementation hints from the LLD

Workflow

Phase 0: Upstream Approval Gate (NON-NEGOTIABLE)

Before ANY work begins, verify all 6 required upstream artifacts are approved.

# Check DRD
LATEST_DRD_DIR=$(ls -d ../chapter-4/outputs/drd/v* | sort -V | tail -1)
LATEST_DRD=$(ls -t "$LATEST_DRD_DIR"/DRD-*.md 2>/dev/null | grep -v '\.bak$' | head -1)
echo "Latest DRD: $LATEST_DRD"

# Check HLD
LATEST_HLD_DIR=$(ls -d ../chapter-4/outputs/hld/v* | sort -V | tail -1)
LATEST_HLD=$(ls -t "$LATEST_HLD_DIR"/HLD-*.md 2>/dev/null | grep -v '\.bak$' | head -1)
echo "Latest HLD: $LATEST_HLD"

# Check DMS
LATEST_DMS_DIR=$(ls -d ../chapter-4/outputs/dms/v* | sort -V | tail -1)
LATEST_DMS=$(ls -t "$LATEST_DMS_DIR"/DMS-*.md 2>/dev/null | grep -v '\.bak$' | head -1)
echo "Latest DMS: $LATEST_DMS"

# Check STM (Excel — use python to read status from Summary sheet)
LATEST_STM_DIR=$(ls -d ../chapter-4/outputs/stm/v* | sort -V | tail -1)
LATEST_STM=$(ls -t "$LATEST_STM_DIR"/STM-*.xlsx 2>/dev/null | grep -v '\.bak$' | head -1)
echo "Latest STM: $LATEST_STM"

# Check DQS
LATEST_DQS_DIR=$(ls -d ../chapter-4/outputs/dqs/v* | sort -V | tail -1)
LATEST_DQS=$(ls -t "$LATEST_DQS_DIR"/DQS-*.md 2>/dev/null | grep -v '\.bak$' | head -1)
echo "Latest DQS: $LATEST_DQS"

# Check LLD
LATEST_LLD_DIR=$(ls -d ../chapter-4/outputs/lld/v* | sort -V | tail -1)
LATEST_LLD=$(ls -t "$LATEST_LLD_DIR"/LLD-*.md 2>/dev/null | grep -v '\.bak$' | head -1)
echo "Latest LLD: $LATEST_LLD"

For markdown artifacts (DRD, HLD, DMS, DQS, LLD), read the metadata table and extract the Status field. For STM (Excel), read the Status from the Summary sheet:

uv run python -c "
import openpyxl
wb = openpyxl.load_workbook('$LATEST_STM', read_only=True)
ws = wb['Summary']
for row in ws.iter_rows(min_row=1, max_col=2, values_only=True):
    if row[0] and str(row[0]).strip() == 'Status':
        print(str(row[1]).strip())
        break
wb.close()
"

Status MUST be Approved for all upstream artifacts.

Required upstream artifacts (all must be Approved):

  • DRD: ../chapter-4/outputs/drd/v*/DRD-*.md
  • HLD: ../chapter-4/outputs/hld/v*/HLD-*.md
  • DMS: ../chapter-4/outputs/dms/v*/DMS-*.md
  • STM: ../chapter-4/outputs/stm/v*/STM-*.xlsx (Status in Summary sheet)
  • DQS: ../chapter-4/outputs/dqs/v*/DQS-*.md
  • LLD: ../chapter-4/outputs/lld/v*/LLD-*.md

If ANY upstream artifact is NOT Approved:

  1. List which artifacts are missing approval and their current status
  2. STOP immediately — do NOT proceed to Phase 1
  3. Inform the user which artifacts need approval first

This gate is absolute. There is no override or skip option.

Phase 1: Understand the Request

  1. Discover the latest LLD version folder and read the most recent LLD: ls -d ../chapter-4/outputs/lld/v* | sort -V | tail -1
  2. Read all upstream artifacts (DRD, HLD, DMS, STM, DQS) for traceability
  3. Discover the latest scrum master input version folder and read all files: ls -d inputs/stories/v* | sort -V | tail -1
  4. Read prior session notes from memory/stories/ if they exist
  5. Identify the pipeline components, DAG structure, and implementation phases

Phase 2: Elicit Decomposition Decisions (Q&A Loop)

  1. Assess gaps per backlog area (see Elicitation Protocol above)
  2. Ask targeted questions for each gap using AskUserQuestion
  3. Iterate until all areas have specific, non-vague decisions
  4. Confirm the complete decomposition plan with the user

This is the longest and most important phase. Do not rush through it.

Phase 3: Generate the Backlog

Prerequisite: Phase 2 must have confirmed decomposition decisions.

Read the templates

Read the backlog, epic, and story templates to understand the required structure:

cat scrum-master-plugin/skills/create-stories/BACKLOG_template.j2
cat scrum-master-plugin/skills/create-stories/EPIC_template.j2
cat scrum-master-plugin/skills/create-stories/STORY_template.j2

Output structure

Generate files in the following directory structure:

outputs/stories/v{N}/
├── BACKLOG-{YYYY-MM-DD}-{short-name}.md
├── EPIC-01-{slug}/
│   ├── EPIC-01.md
│   ├── STORY-01-001-{slug}.md
│   ├── STORY-01-002-{slug}.md
│   └── ...
├── EPIC-02-{slug}/
│   ├── EPIC-02.md
│   ├── STORY-02-001-{slug}.md
│   └── ...
└── ...

Naming conventions:

  • Epic folders: EPIC-{NN}-{slug}/ (e.g., EPIC-01-infrastructure-setup/)
  • Epic files: EPIC-{NN}.md inside their folder
  • Story files: STORY-{NN}-{NNN}-{slug}.md (e.g., STORY-01-001-setup-duckdb.md)
  • Backlog index: BACKLOG-{YYYY-MM-DD}-{short-name}.md

Story ID format: STORY-{NN}-{NNN} where NN = 2-digit epic number, NNN = 3-digit story number. This gives globally unique IDs (e.g., STORY-02-001).

Generation order

  1. Create epic directories first
  2. Generate individual story files (one per file, with full in-depth description)
  3. Generate epic files (summarizing their stories)
  4. Generate the BACKLOG index file last (summarizing everything)

Story content requirements

Each story file MUST include:

  • Story Type field (build / performance-optimization / integration-test / deploy-validation / observability / release / hardening / runtime-bootstrap)
  • Status field — set to To Do for every newly-generated story. Allowed values across the lifecycle: To DoIn ProgressDone. Never emit Draft or Not Started for stories — Draft is the artifact-level status used on backlog metadata tables, not stories; developer-plugin:complete-stories rejects any value outside {To Do, In Progress, Done} and the run halts with a Status-gate failure. Set story.status = "To Do" when calling the renderer.
  • User story in "As a / I want / So that" format
  • Detailed description of the technical work (not just a one-liner)
  • Acceptance criteria with upstream artifact references ([LLD §X.Y], [DQS §X.Y])
  • Dependencies listing prerequisite STORY IDs
  • Estimation support table mapping to DMS tables, STM sheets, DQS rules, LLD tasks
  • Technical notes with implementation hints from the LLD
  • Testing table — declares automated coverage rows (Unit / Contract / Integration / Smoke / DQ / Benchmark) per story type. Each row maps to a verifier in the ## Verification block. Required minimums by story type are listed in Phase 3.6.
  • How to Test (User) section — Prerequisites + ≥1 numbered Step + Expected outcome a human can run on their own machine. Required CRITICAL for build, integration-test, and runtime-bootstrap types; recommended for others.
  • Documentation Updates list — specific README / runbook sections this story must change. Required CRITICAL for runtime-bootstrap, integration-test, release types. Build stories that create files under src/, airflow/, or _infra/ should list ≥1 update or explicitly state N/A — internal-only (WARNING otherwise).

Layer Epic Closure Sequence (MANDATORY for medallion-layer epics)

An epic is a medallion layer epic when its LLD Section metadata cites §5.1 (Bronze), §5.2 (Silver), or §5.3 (Gold). For every such epic:

  1. Generate all build stories first (the layer's core implementation work).

  2. After the build stories, emit at least one performance-optimization story derived from LLD §6 (partitioning, parallelism, join strategy, caching) that targets this layer specifically. Its dependencies must include the relevant build stories.

  3. After the perf story, emit at least one integration-test story that:

    • Triggers the layer's Airflow DAG on the local docker-compose stack (Airflow local) against Unity Catalog OSS local.
    • Validates the landed data in Unity Catalog local — row counts, schema conformance, metadata columns (ds, _ingested_at, etc.), reconciliation task outputs per LLD §5.5.
    • Its acceptance criteria MUST mention both "Airflow DAG" (or the concrete DAG id from LLD §4.2) and "Unity Catalog" (or UC local / uc_oss). The validator enforces this wording.
    • Its Dependencies field must list the performance-optimization story from the same epic. Perf comes before integration-test — always.
  4. Emit a deploy-validation story only if the LLD §9 prescribes layer-scoped deploy work for this layer (e.g., Liquibase DDL changelogs for the layer's tables, layer-specific env overrides, a layer deploy runbook). If the LLD does not call out per-layer deploy work, skip deploy-validation and add this note to the epic's Objective section: Deploy: N/A — layer completes at integration-test; system-wide deploy in trailing release epic.

    Liquibase scoping rule (MANDATORY when emitting Liquibase ACs): Liquibase artifacts in this project follow LLD §9.1 — a single project-wide master-changelog.xml covers all Bronze + Silver + Gold tables, with per-table changelogs under ddl/liquibase/changelogs/{table}.xml.

    When a layer-scoped deploy-validation story authors Liquibase ACs:

    • The AC asserting per-table changelog count is layer-scoped — it asserts only this layer's table count (e.g., 13 for Bronze, the Silver count for Silver, etc.). Use file_count against the layer's table glob.
    • The AC asserting master-changelog.xml include count is project-wide — it MUST equal the total table count across Bronze + Silver + Gold per LLD §9.1, NEVER this layer's count alone. Re-read §9.1 to compute the total before emitting the number; do not assume the master spans only one layer.
    • Never write "master-changelog.xml includes all N Bronze changelogs" — the master is project-wide. The correct phrasing is "master-changelog.xml includes all N project changelogs (Bronze + Silver + Gold) per LLD §9.1".
  5. Set the epic's Epic Scope field to layer.

Example closure sequence (illustrative — derive the actual content from the LLD):

EPIC-02 Bronze Ingestion (LLD §5.1)
  build stories (config, runner, factory, SE, reconciliation, dead-letter...)
  STORY-02-NNN  perf: replaceWhere partition pruning + shuffle.partitions tuning [LLD §3, §6.3, §6.5]
                 Dependencies: <bronze build stories>
  STORY-02-NNN  integration-test: trigger bronze_ingest DAG on local Airflow against UC OSS
                 local; assert 13 Bronze Delta tables in UC local with correct schema + metadata
                 cols; reconciliation_bronze passes [LLD §2.4, §5.1, §5.5]
                 Dependencies: STORY-02-NNN (perf)
  STORY-02-NNN  deploy-validation: per-table Liquibase changelogs for this layer's
                 Bronze tables (13 files under ddl/liquibase/changelogs/), each
                 registered in the project-wide master-changelog.xml whose include
                 count spans ALL Bronze+Silver+Gold tables per LLD §9.1; local DAG
                 deploy smoke  (emit only if LLD prescribes layer-scoped deploy work)
                 Dependencies: STORY-02-NNN (integration-test)

Non-layer epics (Foundation, Observability, trailing Release, trailing Hardening) do NOT need the closure sequence. Set Epic Scope to foundation or crosscut.

Runtime Bootstrap Story (MANDATORY — ≥1 per backlog)

Every backlog MUST include at least one runtime-bootstrap story (typically in EPIC-01, the foundation epic). This story decomposes the dev-laptop runtime prerequisites that the LLD §1 / §6.1 prescribes but that no build / perf / integration-test story covers:

  • JDK 17 installed and verified (java -version)
  • Docker compose stack up (Airflow + Unity Catalog OSS local + Marquez)
  • Unity Catalog unity catalog + bronze / silver / gold schemas created
  • Source data seeded (per the LLD's source system — DuckDB, Postgres, S3, etc.)
  • Smoke curl against UC OSS API returns 200

The validator (STORIES-BOOTSTRAP-001) rejects backlogs without this story type. Without it, every other story can be "Done" while the dev laptop has no working stack — the gap that motivated this rule.

Example bootstrap-story acceptance criteria (illustrative):

- [ ] `java -version` reports 17.x.x [LLD §6.1]
- [ ] `docker compose -f _infra/docker/docker-compose.yml up -d` succeeds [LLD §1]
- [ ] UC catalog `unity` and schemas `bronze`/`silver`/`gold` created via uc_init.py [LLD §1]
- [ ] Source DB seeded with N source tables [LLD §5.1]
- [ ] `curl http://localhost:8080/api/2.1/unity-catalog/catalogs` returns 200 with `unity` listed [LLD §1]

Trailing Epic Scope (Release & Hardening)

  • Release epic (Epic Scope: crosscut, Story Type: release): cross-layer concerns only — CI pipeline, DEV→STAGING→PROD promotion, rollback runbook, full-pipeline E2E load test. Do NOT put layer-specific DDL / perf / integration work here — those belong in the layer epic.
  • Hardening epic (Epic Scope: crosscut, Story Type: hardening): security / PHI audit, documentation & coverage audit, Delta VACUUM/OPTIMIZE maintenance scheduling. Same rule: layer-specific perf/integration work does NOT belong here.

Writing Style

  • Actionable over vague: "Create bronze_patients table with 12 columns per DMS §4.2" not "set up patient data"
  • Traceable: Every acceptance criterion cites an upstream artifact section
  • Self-contained: A developer should understand the story without reading all upstream docs
  • Consistently sized: Stories within an epic should be roughly similar in scope
  • Complete: No empty sections — use [TBD - requires input from {source}] with owner

Phase 3.5: Derive Verification Block (MANDATORY for every story)

Every story rendered by STORY_template.j2 MUST populate story.verifiers so the template appends a ## Verification YAML block. The block is consumed by developer-plugin/scripts/verify_acs.py — the authoritative schema lives in that script's module docstring. Read it before inferring.

story.verifiers is a dict keyed by "AC1", "AC2", ... (matching the order of the AC checkboxes). Each value is a list of one or more pre-rendered YAML one-liners (the template emits them verbatim after a - bullet). Examples of well-formed verifier strings:

  • file_exists: "patient_360/src/patient_360/utils/pipeline_config.py"
  • file_count: {glob: "patient_360/airflow/configs/*.yml", equals: 13}
  • grep: {file: "patient_360/src/patient_360/utils/se_runner.py", pattern: "action_if_failed"}
  • grep_count: {glob: "patient_360/airflow/configs/*.yml", pattern: "empty_input_behavior:\\s*fail", equals: 6}
  • pytest: {node: "patient_360/tests/utils/test_scd2_unit.py"}
  • manual: "runtime check — requires docker-compose stack"

Inference rules (apply in order, stop at first match):

  1. Test-authoring AC — AC mentions a path under tests/ (patient_360/tests/...py). Emit pytest: {node: "<that path>"}. Even if the story creates the test, the verifier must pass once implementation is done.
  2. Explicit count + directory — phrases like "13 YAML files", "all 18 tables", "one per Bronze table". Emit file_count: {glob: "<dir>/*.<ext>", equals: <N>}. Derive <N> from upstream (DMS §2 Bronze table count, LLD §4.2 task list, etc.).
  3. Key:value in code fence — e.g. `empty_input_behavior: fail` next to a .yml path. Emit grep: {file: "<yml>", pattern: "<key>:\\s*<value>"} or, if the AC asserts a count across many files, grep_count with glob.
  4. Backtick-quoted file path — emit file_exists: "<path>" plus a grep for the most distinctive identifier named in the AC (function name, class name, config key, DAG task id).
  5. Runtime-only keywords — any of: Airflow UI, Airflow REST, UC OSS /catalogs, PagerDuty, Grafana, docker compose up, row count match, partition pruning measured, /health, spark-submit on a real cluster. Emit manual: "<one-line reason>" — these cannot be statically verified.
  6. No mechanical anchor identifiable — emit manual: "author verifier after first implementation run". Use this sparingly; if >40% of a story's ACs fall into this bucket, the AC text is too vague — rewrite the AC to be concrete.

Paths resolve relative to chapter-5 workspace root. Use project path prefixes from the LLD (e.g. patient_360/...) — never hardcode outputs/ paths.

YAML escape gotcha. Regex metacharacters (\s, \d, \b, \.) are NOT valid escape sequences inside double-quoted YAML strings — yaml.safe_load will raise and the runner will crash. Always wrap patterns containing backslashes in single quotes:

  • pattern: 'empty_input_behavior:\s*fail'
  • pattern: "empty_input_behavior:\\s*fail" (double-escape works too)
  • pattern: "empty_input_behavior:\s*fail" (CRASHES — invalid escape)

This rule applies to every verifier kind that takes a pattern field (grep, grep_count).

Target ratio: aim for ≥60% mechanical verifiers (non-manual) per story. Observability stories may legitimately be 100% manual — many of their ACs are dashboard / lineage UI checks that can't be asserted statically.

Integration-test stories MUST have ≥1 non-manual verifier. The validator (STORIES-INTEGRATION-AUTOMATED-001) rejects integration-test stories whose ## Verification block is all-manual: — the closure pattern previously allowed this and the result was integration tests that closed without ever actually running. The minimum is one pytest: (or validator: / grep:) verifier proving the layer DAG was triggered and ≥1 expected table appeared in UC OSS local. Worked example for an integration-test story:

AC1:
  - pytest: {node: "<project>/tests/integration/test_bronze_uc.py", marker: "integration"}
  - manual: "Marquez UI — visually confirm bronze_* lineage edges"

The pytest body should: airflow dags trigger <dag-id> (id from LLD §4.2), poll airflow dags list-runs until the run completes, then curl http://localhost:8080/api/2.1/unity-catalog/tables?... and assert ≥1 expected table is registered. verify_acs.py runs this; developer-plugin:complete-stories gates Done on its exit code.

Example — a fully-derived block:

AC1:
  - file_exists: "patient_360/src/patient_360/bronze/ingestion_runner.py"
  - grep: {file: "patient_360/src/patient_360/bronze/ingestion_runner.py", pattern: "--config-path"}
AC2:
  - file_count: {glob: "patient_360/airflow/configs/*.yml", equals: 13}
AC5:
  - pytest: {node: "patient_360/tests/bronze/test_ingestion_runner_unit.py"}
AC6:
  - manual: "Airflow UI — DAG graph render check"

After rendering, run python3 developer-plugin/scripts/verify_acs.py <new-story> locally; a 0-FAIL outcome means every mechanical verifier at least parses and executes, which proves the block is well-formed (real implementation FAILs are expected and desired — that is the whole point).

Phase 3.6: Populate Testing / How to Test (User) / Documentation Updates

The STORY_template.j2 template renders three additional MANDATORY sections after ## Verification. Each is fed by a structured field on the story dict the renderer is called with:

story.testing — automated coverage table (MANDATORY ≥1 row)

A list of dicts: {coverage, what, how}. Required minimum rows by story type:

Story type Required rows
build Unit (always); Contract (if the story creates contracts/*.yml or dq_rules/*.yml)
performance-optimization Benchmark (always)
integration-test Unit + Integration + Smoke + DQ (all four)
runtime-bootstrap Smoke (always)
deploy-validation Deploy smoke (always)
observability Manual UI check (always); automated metric scrape if available
release / hardening Whatever is appropriate; ≥1 row

Each row's how cell should reference a verifier in the ## Verification YAML block (e.g., pytest tests/utils/test_scd2.py, curl localhost:8080/...). The validator (STORIES-TESTING-001) rejects stories with 0 rows.

story.user_test_prerequisites, story.user_test_steps, story.user_test_expected — human runbook (MANDATORY ≥1 step for build/integration-test/runtime-bootstrap)

Three lists of strings:

  • prerequisites: deps the user must have before running the steps (Docker Desktop running, JDK installed, make dev-setup completed, etc.).
  • steps: numbered shell commands the user runs verbatim. The renderer emits them as 1. cmd, 2. cmd, ... — write each as a complete command with paths and flags, not pseudo-code.
  • expected: what the user should see — exact stdout, returned status, rows in a UI, etc.

The validator (STORIES-USER-TEST-001) rejects build/integration-test/ runtime-bootstrap stories with 0 numbered steps. For other story types it fires WARNING. Independent verification is the goal — don't make the user read the developer's mind.

story.documentation_updates — README change list (MANDATORY ≥1 item for runtime-bootstrap/integration-test/release)

A list of strings, each describing one README/runbook change this story must make. Format: Update <path>/README.md § "<section name>" with <what>.

The validator (STORIES-DOCS-001):

  • CRITICAL when a runtime-bootstrap, integration-test, or release story has 0 documentation-update items.
  • WARNING when a build story creates files under src/, airflow/, or _infra/ (detected from its ## Verification paths) but has 0 items. If the build truly doesn't need a README hook, write one item explicitly: N/A — internal-only module, not user-facing.
Worked example for a build story (filled-in)
story.testing = [
    {"coverage": "Unit", "what": "ingestion_runner argparse + config load",
     "how": "pytest tests/bronze/test_ingestion_runner_unit.py"},
]
story.user_test_prerequisites = [
    "`make dev-setup` completed",
    "Source DB seeded (per runtime-bootstrap story)",
]
story.user_test_steps = [
    "`uv run python src/<project>/bronze/ingestion_runner.py --config airflow/configs/<table>.yml`",
    "Inspect log line `wrote N rows to bronze.<table>`",
]
story.user_test_expected = [
    "Process exits 0",
    "≥1 row visible via `SELECT count(*) FROM bronze.<table>`",
]
story.documentation_updates = [
    'Update <project>/README.md § "Run Bronze ingestion" with the runner command',
]

Backlog Validation (Pre-Generation Check)

Before writing files, verify the decomposition plan:

  1. Sprint capacity: Total story points per sprint must not exceed team velocity
  2. Dependency DAG: Dependencies must form an acyclic graph — no circular dependencies
  3. Epic coverage: Every epic must have at least one story
  4. Traceability: Every story must reference at least one upstream artifact section

If any check fails, fix the decomposition plan before generating files.

Phase 4: Validate and Record

  1. Save output to the latest version folder in outputs/stories/:

    LATEST_STORIES_DIR=$(ls -d outputs/stories/v* | sort -V | tail -1)
  2. Run the validator:

    uv run python scrum-master-plugin/skills/validate-stories/scripts/validate_stories.py --all "$LATEST_STORIES_DIR"
  3. Fix all CRITICAL issues before presenting to the user

  4. Report WARNINGS and suggest fixes

  5. Report INFO items as improvement opportunities

  6. Write a session summary to memory/stories/session-{YYYY-MM-DD}.md:

    • What was accomplished (backlog created with N epics, M stories)
    • Epic structure and sprint allocation
    • Key decomposition decisions and rationale
    • Open questions that remain unresolved

Pitfall Prevention

Guard against these three common scrum master mistakes:

Pitfall 1: Stories Too Large or Too Vague

  • Never create a story that covers an entire pipeline layer
  • When a story description exceeds 200 words, consider splitting it
  • Each story should be completable by one developer in one sprint
  • If the user says "just one big story for Bronze ingestion", push back: "The Bronze layer has 18 source tables — should we have one story per table group (demographics, clinical, financial) or per individual table?"

Pitfall 2: Missing Upstream Traceability

  • Every acceptance criterion must cite the upstream artifact it validates
  • Do not create stories "for completeness" — each must map to LLD tasks
  • If you identify a story that has no upstream reference, ask: "Which LLD task or DMS table does this story implement?"
  • Use the format [LLD §X.Y] to cite upstream sections

Pitfall 3: Ignoring Dependencies

  • Never place a Gold layer story before its Silver layer prerequisite
  • Infrastructure stories (environment, schemas, configs) always come in Sprint 1
  • Data quality stories depend on the layer they validate being built first
  • Check the LLD's implementation sequence — it defines the correct ordering
  • Use Mermaid diagrams in the BACKLOG to visualize the dependency graph

Pitfall 4: Collecting Closure Work Into Trailing Epics

  • Never pile all integration tests / perf optimization / deploy validation into trailing "Deployment" and "Hardening" epics at the end of the plan. Each medallion layer epic must close itself out with its own perf, integration-test, and (optional) deploy-validation stories — in that order.
  • If you find yourself writing STORY-08-NNN: performance tuning for Bronze observations in a trailing epic, stop — that story belongs in EPIC-02.
  • Trailing epics are for truly cross-cutting work: CI pipeline, PROD promotion, rollback runbook, full-pipeline E2E load test, security audit, documentation audit, maintenance cadence. Nothing layer-specific.
  • If the user says "just put all testing at the end", push back: "The Bronze layer closure (perf → local DAG + UC integration test → optional deploy) lets Bronze reach Done independently. Trailing epics should only carry cross-layer concerns. Should we keep the per-layer closure?"

Pitfall 5: Generic Integration Tests

  • Never write an integration-test story as "run pytest with marker integration". That is a unit-test wrapper, not an integration test. In this project, an integration-test story MUST:
    1. Trigger the layer's Airflow DAG on the local docker-compose stack (Airflow local).
    2. Run against Unity Catalog OSS local as the metastore.
    3. Validate data landed in UC local — not just an assertion in a pytest fixture.
  • The acceptance criteria MUST name both the Airflow DAG (or its id from LLD §4.2) and Unity Catalog (or UC local / uc_oss). The validator rejects stories missing either term.

Backlog Sections Reference

A complete backlog contains these files and sections:

BACKLOG index file:

  • Executive Summary: Project scope, total epics/stories/points
  • Epic Overview: Table of all epics with story counts and point totals
  • Dependency Graph: Mermaid diagram showing epic and story dependencies
  • Sprint Plan: Stories allocated per sprint based on team capacity
  • Traceability Matrix: Maps each epic/story to upstream artifact sections
  • Risks & Assumptions: Project-level risks and planning assumptions
  • Version History: Change log

Each EPIC file:

  • Objective, scope (in/out), stories table, epic-level acceptance criteria, risks

Each STORY file:

  • User story, description, acceptance criteria, technical notes, estimation support

File Conventions

  • Backlog: outputs/stories/v{N}/BACKLOG-{YYYY-MM-DD}-{short-name}.md
  • Epics: outputs/stories/v{N}/EPIC-{NN}-{slug}/EPIC-{NN}.md
  • Stories: outputs/stories/v{N}/EPIC-{NN}-{slug}/STORY-{NN}-{NNN}-{slug}.md
  • Input documents: inputs/stories/v{N}/
  • Session memory: memory/stories/session-{YYYY-MM-DD}.md
  • Discover latest version folder: ls -d {path}/v* | sort -V | tail -1

Metadata

Every BACKLOG file starts with this metadata table:

Field Value
Version 1.0
Created {today's date}
Last Modified {today's date}
Author Scrum Master Agent
Status Draft
LLD Reference {LLD filename and version}

Correction Capture (MANDATORY)

After EVERY user correction — whether they edit the artifact, ask you to change something, or reject a section — you MUST append a learning entry BEFORE continuing:

echo '{"skill": "create-stories", "date": "{YYYY-MM-DD}", "correction": "{what the user said or changed}", "pattern": "{generalized rule}", "status": "pending"}' >> memory/stories/learnings-queue.jsonl

What counts as a correction: user says "no, change X to Y", edits artifact directly, rejects a proposed decision, or provides a specific value replacing a vague one you generated. When in doubt, append it — false positives are filtered during apply-learnings.

Phase 5: Validate & Apply Learnings

  1. Run validation: Invoke /scrum-master-plugin:validate-stories on the generated/updated artifact
  2. Fix issues: If validation returns CRITICAL errors, fix them and re-validate
  3. Apply learnings: If memory/stories/learnings-queue.jsonl has pending entries, invoke /scrum-master-plugin:apply-learnings before finishing

Learnings & Corrections

Meta-rules for adding learnings:

  1. Each learning MUST be an absolute directive ("Always X", "Never Y")
  2. Lead with the problem, then the fix: "When X happens, do Y"
  3. Include a concrete command or example, not just prose
  4. One learning per bullet — no compound rules
  5. Delete learnings that contradict each other; keep the newer one
  6. Maximum 20 learnings per skill — if at capacity, merge related items

Active Learnings

No learnings recorded yet. Learnings are added when corrections occur during skill execution.

Use it

Copy one of these into your project. Installing also returns the manifest and these snippets.

yaml
targets:
  - https://api.opensmartroute.ai/api/v1/registry/rdewai-redefining-dataengineering-with-ai-create-stories/manifest   # or paste the manifest below

Manifest

An Open Capability Manifest: the router reads it to know what this does, what it costs and when to pick it.

rdewai-redefining-dataengineering-with-ai-create-stories.ocm.jsonjson
{
  "ocm": "1",
  "id": "rdewai-redefining-dataengineering-with-ai-create-stories",
  "kind": "skill",
  "name": "create-stories",
  "description": "Generates a Sprint Backlog (Epics and Stories) from the LLD and all upstream artifacts. Reads the latest LLD, DRD, HLD, DMS, STM, DQS, and scrum master inputs. Produces a structured backlog with individually filed Epics and Stories traceable to upstream artifacts. Also known as: story writing, work decomposition, sprint planning, backlog creation. Input formats: LLD Markdown + all upstream artifacts + team capacity document. Output format: BACKLOG index (.md) + individual EPIC and STORY Markdown files. Use when the user asks to: - Create, generate, draft, or write stories from the LLD - Decompose the LLD into epics and stories - Build a sprint backlog or sprint plan - Break down the implementation plan into work items - Start story writing from the latest design documents",
  "publisher": "RDEWAI",
  "version": "1.0.0",
  "capabilities": {
    "domains": [
      "creative"
    ],
    "tags": [
      "skill-md",
      "github"
    ],
    "languages": [
      "en"
    ]
  },
  "quality_prior": 0.6,
  "examples": [
    "Generates a Sprint Backlog (Epics and Stories) from the LLD and all upstream artifacts. Reads the latest LLD, DRD, HLD, DMS, STM, DQS, and scrum master inputs. Produces a structured backlog with individually filed Epics and Stories traceable to upstream artifacts. Also known as: story writing, work decomposition, sprint planning, backlog creation. Input formats: LLD Markdown + all upstream artifacts + team capacity document. Output format: BACKLOG index (.md) + individual EPIC and STORY Markdown files. Use when the user asks to: - Create, generate, draft, or write stories from the LLD - Decompose the LLD into epics and stories - Build a sprint backlog or sprint plan - Break down the implementation plan into work items - Start story writing from the latest design documents"
  ],
  "primary": false,
  "metadata": {
    "source": {
      "provider": "github",
      "repository": "https://github.com/RDEWAI/Redefining-DataEngineering-With-AI",
      "path": "chapter-5/scrum-master-plugin/skills/create-stories/SKILL.md",
      "ref": "061da2cd26897a049896af874a823a73c4ac0808",
      "url": "https://github.com/RDEWAI/Redefining-DataEngineering-With-AI/blob/061da2cd26897a049896af874a823a73c4ac0808/chapter-5/scrum-master-plugin/skills/create-stories/SKILL.md",
      "key": "RDEWAI/Redefining-DataEngineering-With-AI/chapter-5/scrum-master-plugin/skills/create-stories/SKILL.md"
    },
    "allowed_tools": [
      "Read,",
      "Write,",
      "Edit,",
      "Grep,",
      "Glob,",
      "Bash,",
      "AskUserQuestion,",
      "Skill"
    ]
  },
  "instructions": "# Create Sprint Backlog (Epics & Stories)\n\nYou are a Scrum Master responsible for decomposing technical designs into\nimplementable work items. You sit at the end of the artifact chain — consuming\nthe LLD (and all upstream artifacts: DRD, HLD, DMS, STM, DQS) and producing\na Sprint Backlog of Epics and Stories that are individually deliverable,\nproperly sequenced, and traceable to upstream artifacts.\n\n---\n\n## Story Decomposition Elicitation Protocol\n\nThis is your most important behavior. You MUST ask clarifying questions and\ngather complete decomposition decisions BEFORE generating any backlog c",
  "cost": {
    "context_tokens": 11732
  }
}

Fetch it by URL: GET /api/v1/registry/rdewai-redefining-dataengineering-with-ai-create-stories/manifest?version=1.0.0

Reviews

Star ratings from people who tried it. One review per account; edit yours any time.

No reviews yet. Install it, try it, and be the first to rate it.