| name | agile:initiative:pack |
| description | Pack every markdown artifact in an initiative folder (design.md, refinement-report.md, progress.md) PLUS the full pack for every realized epic in the initiative (invoking agile:epic:pack for each epic in ascending order) into a single NotebookLM-ready source document at NNN-pack.md, then strictly validate that no content was lost in translation. Use this whenever the user wants to combine initiative artifacts for Google NotebookLM ingestion, generate a single source for Gemini-based infographic / slide deck / video presentation creation covering the whole multi-epic program, prepare an initiative for stakeholder briefing material, or asks to "pack", "combine", "bundle", "consolidate", or "flatten" an initiative's documentation. Strict validation blocks the commit on any context loss. |
| user-invocable | true |
| disable-model-invocation | true |
| allowed-tools | Read, Write, Edit, Bash, Glob, Grep, AskUserQuestion, Skill |
Initiative Pack
Combine every markdown artifact in an initiative folder, plus the full per-epic pack for every realized epic in the initiative, into a single NotebookLM-optimized source document. Strictly validate the result so Gemini can generate infographics, slide decks, and video presentations covering the whole program from one source without silent context loss.
Invocation
/agile:initiative:pack — auto-detect a target initiative in agile/initiatives/
/agile:initiative:pack 004 — target initiative 004
/agile:initiative:pack agile/initiatives/004-legacy-financial-accounting-migration — target a specific path
Optional flags (append after the identifier):
--no-include-epics — skip the per-epic pack step and produce a lightweight initiative-only pack (the pre-2026-04-24 behavior)
--force-repack-epics — re-invoke /agile:epic:pack even when an epic's NNN-pack.md is newer than every source artifact in the epic
--max-words N — raise the NotebookLM size limit for very large combined packs (default 500000; initiatives with many rich epics may legitimately need more)
Context
- Current branch: !
git branch --show-current
- Recent initiatives: !
ls agile/initiatives/ 2>/dev/null | sort | tail -10
Why this skill exists
Initiative artifacts live as up to three top-level files: design.md (always present, the strategic spec), refinement-report.md (when the expert panel was run via /agile:initiative:refine), and progress.md (the regenerable cross-epic dashboard). Each realized epic under the initiative also has its own rich artifact tree (epic.md, design.md, plan.md, checklist.md, and every feature's spec.md + tasks.md), which the sibling agile:epic:pack skill flattens into its own NNN-pack.md.
NotebookLM can technically take many sources per notebook, but Gemini produces dramatically better outputs (audio overview, mind map, slide deck, video presentation, infographic) when given a single, well-structured source with explicit cross-section navigation. Multi-source notebooks fragment Gemini's outline extraction and break cross-references.
This skill produces that single source for the entire multi-epic program — strategy first, then each epic's full pack in ascending epic-number order — deterministically, and then validates it strictly so the user can be confident that nothing was dropped, truncated, or silently rewritten.
Scope boundary: the combined pack covers only realized epics (those that exist as directories under agile/epics/NNN-slug/ and backlink to this initiative). Unrealized Epic Candidates from the initiative's design.md are mentioned in prose but not inlined. Use --no-include-epics if you want a short, initiative-only pack (e.g., for an exec-level briefing where the per-epic detail is not needed).
Phases
Phase 1: Resolve & Discover
-
Resolve INIT_DIR:
- If
$ARGUMENTS contains a 3-digit number (e.g. 004): match a directory in agile/initiatives/ whose name starts with that prefix.
- If
$ARGUMENTS contains a path: use it directly (must exist).
- If no positional argument: list candidates in
agile/initiatives/ that contain design.md. If exactly one is in the current branch context, use it. Otherwise use AskUserQuestion to let the user choose from the most-recently-modified candidates.
-
Hard prerequisites (exit with a clear error if any fails):
INIT_DIR/design.md exists. Initiatives without a design are malformed; nothing else makes sense to pack.
-
Soft warnings (do not block, but report):
refinement-report.md missing → the expert-panel refinement was never run (or was rolled back). Pack will still proceed with just the design.
progress.md missing → the realization dashboard hasn't been generated yet. Suggest running /agile:initiative:progress NNN first if the user wants the latest progress in the pack.
-
Discover realized epics (skip entirely if --no-include-epics was passed):
python3 .claude/skills/agile-initiative-pack/scripts/discover-epics.py INIT_DIR_OR_ID
The helper scans every agile/epics/*/design.md, keeps those that backlink to the initiative (either a initiatives/<slug> path-style link or a bare slug following an **Initiative**: label), and emits a JSON list sorted ascending by epic number. Each entry also reports pack_exists and pack_fresh (the latter is true only when NNN-pack.md is newer than every source file in the epic). This lets the next phase skip already-fresh epic packs.
If zero epics are discovered and --no-include-epics was not passed, inform the user and offer three choices via AskUserQuestion:
"Proceed with initiative-only pack" (sets the skip flag for downstream phases)
"Cancel — no epics to include"
"Open the discover-epics output so I can debug"
Phase 2: Pack Each Epic
Skip this phase entirely if --no-include-epics was passed or if discovery returned zero epics.
For each entry from the discovery JSON, in the order they appear (ascending epic number):
-
Decide whether to invoke agile:epic:pack:
- If
pack_fresh is true AND --force-repack-epics was NOT passed: reuse the existing pack_path, report "reused fresh epic NNN pack", and move on.
- Otherwise: invoke the
agile:epic:pack skill via the Skill tool, passing the epic's 3-digit number as the argument. That skill runs its own four-phase workflow and writes NNN-pack.md into the epic directory. When agile:epic:pack prompts about committing the produced file, answer "Done — leave uncommitted" — committing is the initiative pack skill's responsibility at Phase 5 so the reviewer sees a single atomic change.
-
Collect the resulting epic-pack path (always <epic_dir>/<NNN>-pack.md). Keep an ordered list EPIC_PACK_PATHS for Phase 3.
-
If agile:epic:pack fails for any epic (returns a non-zero exit or reports a validation failure): stop immediately, surface the failure verbatim, and offer via AskUserQuestion:
"Fix the failing epic first, then rerun"
"Skip this epic and continue with the remaining ones" (the skipped epic's pack will not be included in the combined pack)
"Abort the initiative pack entirely"
Phase 3: Build the Combined Pack
Run the initiative packer with every epic pack path appended (omit the flag entirely if Phase 2 was skipped):
python3 .claude/skills/agile-initiative-pack/scripts/pack.py \
--init-dir INIT_DIR \
--append-epic-packs EPIC_PACK_PATHS...
The packer writes INIT_DIR/NNN-pack.md. Its stdout reports the source count, appended epic count, and output word + byte counts. Capture this for the final report.
If the packer exits non-zero, surface stderr verbatim and stop. Do not proceed to validation.
Phase 4: Strict Validation
Run the validator in strict mode, passing the same epic pack paths so the preservation checks cover the appended content:
python3 .claude/skills/agile-initiative-pack/scripts/validate.py \
--init-dir INIT_DIR \
--pack INIT_DIR/NNN-pack.md \
--epic-packs EPIC_PACK_PATHS... \
--strict
(If Phase 2 was skipped, omit --epic-packs — the validator then runs with only the initiative-level sources.)
The validator runs eight checks against the freshly written pack:
| # | Check | What it guarantees |
|---|
| 1 | content-coverage | Every non-heading content line from every source (initiative artifacts + every appended epic pack) appears verbatim in the pack |
| 2 | heading-preservation | Pack contains at least as many headings as the sum of source headings across all inputs |
| 3 | table-preservation | Every table row from every source is preserved |
| 4 | code-fence-preservation | Code fence count is preserved (so ASCII DAGs survive intact) |
| 5 | metadata-preservation | Every **FieldName**: metadata line (Status, Refined dates, DevOps IDs, etc.) is preserved |
| 6 | cross-reference-rewriting | No unrewritten design.md / refinement-report.md / progress.md references remain outside code fences |
| 7 | word-count-sanity | Pack word count ≥ 95% of the sum of source word counts |
| 8 | notebooklm-size-limit | Pack word count is below the hard limit (default 500000; override via --max-words) |
On failure (validator exits 1):
- Show the validator's full report to the user.
- Identify whether the failure is in
pack.py (a code bug — the source content exists but the script dropped it), in the source artifacts (an unusual structure the script doesn't yet handle), or in an epic pack that was itself malformed (e.g. came from an older agile-epic-pack version).
- Use
AskUserQuestion to present options:
- "Diagnose and fix the packer", "Diagnose and rebuild the offending epic pack", "Skip validation and write the pack anyway (NOT recommended)", "Abort"
- Do NOT auto-commit on validation failure.
On success (validator exits 0):
- Show the validator's summary report (one PASS line per check) so the user can see exactly what was checked.
- Proceed to Phase 5.
Phase 5: Present & Commit
-
Print a summary block:
Initiative Pack Complete
Source: INIT_DIR
Pack: INIT_DIR/NNN-pack.md
Sources packed: M of 3 possible initiative artifacts + K epic pack(s)
Epic packs:
- Epic NNN: <title> (fresh | repacked)
- Epic NNN: <title> (fresh | repacked)
...
Pack size: X words / Y bytes
Validation:
[PASS] content-coverage (no missing lines)
[PASS] heading-preservation (P pack / Q source headings)
[PASS] table-preservation (R rows preserved)
[PASS] code-fence-preservation (S fences preserved)
[PASS] metadata-preservation (T metadata lines preserved)
[PASS] cross-reference-rewriting (no dangling .md refs)
[PASS] word-count-sanity (ratio Z)
[PASS] notebooklm-size-limit (X / limit words)
Next: upload NNN-pack.md to a new NotebookLM notebook as the only source,
then generate audio overview → mind map → slide deck → video.
-
Use AskUserQuestion to ask:
- Question: "Pack written and validated. What would you like to do next?"
- Options:
"Commit the initiative pack and all newly-produced epic packs" — a single git commit that stages INIT_DIR/NNN-pack.md plus every epic NNN-pack.md that Phase 2 produced or refreshed. Message: docs(agile): add NotebookLM pack for initiative NNN (K epics).
"Commit only the initiative pack" — stage just INIT_DIR/NNN-pack.md; leave epic packs uncommitted for a separate review.
"Open the pack for review first" — print the path and stop.
"Done — leave uncommitted" — print the path and stop.
-
If the user picks a commit option, run the git commands and report the new commit hash.
Key Principles
- Deterministic packer:
pack.py is pure text transformation. The same inputs always produce the same output. There is no LLM in the packing path so the result is reproducible and easy to debug.
- Delegate to
agile:epic:pack for epic content: the initiative pack skill never re-implements epic packing. It invokes the sibling skill via the Skill tool and trusts the file it produces. This keeps the per-epic validation discipline intact and means improvements to the epic packer automatically improve initiative packs too.
- Fresh-pack skipping saves serious time: initiatives with many realized epics would take minutes to repack every time otherwise. The
discover-epics.py helper compares NNN-pack.md mtime to every epic-source mtime; only stale packs are rebuilt. --force-repack-epics overrides this when you explicitly want a clean rebuild.
- Strict validation by default: silent context loss is the worst failure mode for this skill — Gemini will happily generate confident, polished slides about content that was dropped. The validator's job is to make that impossible, and it treats every appended epic pack as an additional source for preservation checks.
- Single H1, demoted hierarchy: the pack has exactly one H1 (the initiative title). Source H1s are demoted to H2; each inlined epic pack's H1 becomes an H2 section ("Epic NNN: ") with all its inner headings demoted one more level. NotebookLM uses heading hierarchy as the primary signal for outline / slide / mind-map generation, so a clean hierarchy directly improves output quality.
- Anchors, not file paths (at the initiative level): initiative-level cross-references ("see refinement-report.md") become anchor links so the pack reads top-to-bottom. Epic-pack internal anchors are left as the epic packer produced them — they resolve within each epic's own section and don't need to cross-link with the initiative content.
- ASCII DAGs stay in code fences: process maps and any whitespace-aligned diagrams are only preserved by NotebookLM inside fenced code blocks. The packer never lifts content out of fences.
- Bridge paragraphs help video output: short narrative bridges between major sections (initiative → epics, and between each epic series) give Gemini natural transition points; video narrations come out noticeably more coherent with them.
- The 500k word limit is real but overridable: NotebookLM truncates oversized sources silently. Initiative-only packs rarely approach this; combined packs for 8+ epic initiatives routinely will. Pass
--max-words with a number you know the current NotebookLM ingest accepts (empirically up to ~900k has worked), or split the pack by producing a subset pack with --no-include-epics and per-epic packs consumed separately.
Scripts
| Script | Purpose | Inputs | Output |
|---|
scripts/discover-epics.py | Find every realized epic backlinked to an initiative and compute pack freshness | positional initiative identifier (number / slug / path) | JSON (default) or text table to stdout |
scripts/pack.py | Combine initiative artifacts + appended epic packs into one markdown file | --init-dir, optional --output, optional --append-epic-packs | Writes NNN-pack.md; prints summary to stdout |
scripts/validate.py | Strict context-preservation validation | --init-dir, --pack, optional --epic-packs, optional --max-words, --strict | Exit 0 = pass, 1 = fail; report on stdout |
References
| File | Purpose |
|---|
references/notebooklm-optimization.md | Background on how NotebookLM/Gemini ingests markdown sources, why the pack is structured the way it is, common failure modes, and tips for the post-pack NotebookLM workflow. Read this when debugging unexpected NotebookLM output, or when adjusting the packer for new artifact types. |
Related skills
| Skill | Relationship |
|---|
agile:epic:pack | Invoked by Phase 2 once per realized epic. Produces agile/epics/NNN-slug/NNN-pack.md, which is then appended into this skill's output. |
agile:initiative:progress | Regenerates progress.md; run it before this skill if you want a fresh realization dashboard inside the pack. |
agile:initiative:refine | Produces refinement-report.md (phase-3.5 expert-panel review). This skill includes that file if present. |
Terminal State
The terminal state is a written, validated NNN-pack.md in the initiative root that contains the initiative's own artifacts plus the full pack for every realized epic (or just the initiative artifacts when --no-include-epics was used). Epic packs produced along the way sit as agile/epics/NNN-slug/NNN-pack.md files and may be committed with the initiative pack or left uncommitted per the user's choice. This skill does NOT upload to NotebookLM, generate any infographic / slide deck / video, or invoke any other skill beyond agile:epic:pack — the NotebookLM workflow is an external step the user takes manually with the produced file.