Skip to content
Chapter 7 of 7

Packaging: manifest, READMEs, demo links, and the write-up

The projects are built; now they have to be FOUND and understood in thirty seconds, because that is the entire attention budget a screener spends before deciding. This final capstone is the packaging layer that most people skip and that quietly costs them interviews. You build a small generator that takes a manifest of your finished projects, the five capstones you just shipped, and emits, for each one, the README a hiring manager actually reads: title, the business OUTCOME first because that is the line that gets read, a live DEMO link, the METRICS that prove it works, and the STACK. It also emits a portfolio index, one screenable line per project. The acceptance test reuses the readiness rubric from Chapter 1: every generated README must carry the sections that make a project screenable, and every manifest entry must be rubric-ready. In the lab the generator builds the index and all five READMEs and asserts each one passes the section check, so the packaging is verified, not assumed.

The lab: read it, then run it

labs/capstones/cap7-packaging.py
#!/usr/bin/env python3
"""
CAPSTONE 7 (ch7): Packaging the portfolio, a manifest and README generator.

The projects are built. Now they have to be FOUND and UNDERSTOOD in thirty
seconds, because that is all the attention a screener gives. This final capstone
is the packaging layer: a small generator that takes a manifest of your finished
projects (the five capstones you just built) and emits, for each one, the
README-in-30-seconds a hiring manager actually reads, one that leads with the
business OUTCOME, links a live DEMO, names the METRICS, and lists the STACK.

It reuses the portfolio rubric from Capstone 1 as the acceptance test: every
generated README must contain the sections that make a project screenable, and
every manifest entry must be rubric-ready (deployed, evaluated, real, original).
The generator builds the portfolio index and the per-project READMEs, then asserts
each one passes the section check. It prints the invariant and exits 0.

Run: python3 modules/academy-content/labs/capstones/cap7-packaging.py
"""
import sys, os
_cands = [os.path.join(os.path.dirname(__file__), "..") if "__file__" in globals() else None,
          os.path.join(os.getcwd(), "..", "labs"), os.path.join(os.getcwd(), "labs")]
for _c in _cands:
    if _c and os.path.exists(os.path.join(_c, "academy_llm.py")):
        sys.path.insert(0, os.path.abspath(_c)); break
from academy_llm import complete  # noqa: F401  (available to every capstone)

# ── The portfolio manifest: the five capstones you just built. ───────────────────
MANIFEST = [
    {
        "name": "RAG Assistant over Company Docs",
        "outcome": "Cuts support lookup time by grounding answers in real docs with citations.",
        "demo": "https://demo.example.com/rag-assistant",
        "metrics": "retrieval hit-rate 0.92, zero hallucinations on the eval set",
        "stack": ["embeddings", "vector search", "grounded generation", "citations"],
    },
    {
        "name": "Trip-Budget Tool-Calling Agent",
        "outcome": "Answers real multi-step questions by chaining tools, gated against unsafe actions.",
        "demo": "https://demo.example.com/trip-agent",
        "metrics": "task success 0.95, 100% of ungranted actions blocked",
        "stack": ["ReAct loop", "tool registry", "least-privilege guardrails"],
    },
    {
        "name": "Reusable Eval Pipeline",
        "outcome": "Gates every build on a golden set so a silent regression never ships.",
        "demo": "https://demo.example.com/eval-pipeline",
        "metrics": "blocks 100% of seeded regressions, code + judge graders",
        "stack": ["golden dataset", "code grader", "LLM-as-judge", "gate"],
    },
    {
        "name": "MCP-Connected Assistant",
        "outcome": "Reaches tools over a standard protocol: build once, connect everywhere.",
        "demo": "https://demo.example.com/mcp-assistant",
        "metrics": "tools discovered and served over the transport, zero shared state",
        "stack": ["MCP server", "MCP client", "JSON transport", "tool call"],
    },
    {
        "name": "Self-Red-Teamed Secure LLM App",
        "outcome": "Proves its own security by attacking itself against the OWASP LLM Top 10.",
        "demo": "https://demo.example.com/secure-app",
        "metrics": "blocks 5/5 attacks hardened vs 0/5 undefended, report published",
        "stack": ["input/output guards", "secret isolation", "egress allowlist", "red-team suite"],
    },
]

# Sections a screenable README must carry (this reuses the Capstone-1 rubric idea).
REQUIRED_SECTIONS = ["# ", "## Outcome", "## Live demo", "## Metrics", "## Stack"]


def generate_readme(project):
    """Emit the 30-second README for one project: title, outcome first, demo,
    metrics, stack. Outcome leads because that is what a manager screens for."""
    lines = [
        "# %s" % project["name"],
        "",
        "## Outcome",
        project["outcome"],
        "",
        "## Live demo",
        project["demo"],
        "",
        "## Metrics",
        project["metrics"],
        "",
        "## Stack",
        ", ".join(project["stack"]),
        "",
    ]
    return "\n".join(lines)


def generate_index(manifest):
    """The portfolio landing page: one screenable line per project."""
    out = ["# AI Engineering Portfolio", "",
           "%d shipped, evaluated, end-to-end projects." % len(manifest), ""]
    for p in manifest:
        out.append("- **%s**: %s ([demo](%s))" % (p["name"], p["outcome"], p["demo"]))
    return "\n".join(out) + "\n"


def readme_passes(readme):
    """Acceptance test: every required section is present and non-empty."""
    return all(section in readme for section in REQUIRED_SECTIONS)


def main():
    print("PACKAGING THE PORTFOLIO: manifest -> index + %d READMEs\n" % len(MANIFEST))

    index = generate_index(MANIFEST)
    print("STEP 1: generated portfolio index")
    for line in index.strip().splitlines():
        print("  %s" % line)

    print("\nSTEP 2: generate + acceptance-test each project README")
    passed = 0
    for project in MANIFEST:
        readme = generate_readme(project)
        ok_one = readme_passes(readme)
        passed += 1 if ok_one else 0
        print("  %-42s sections=%s -> %s" % (
            project["name"], "complete" if ok_one else "MISSING",
            "OK" if ok_one else "FAIL"))
        assert ok_one, "README for %r is missing required sections" % project["name"]

    index_ok = "# AI Engineering Portfolio" in index and index.count("[demo](") == len(MANIFEST)
    all_readmes_ok = passed == len(MANIFEST)

    print("")
    print("  index lists all %d projects with demo links: %s" % (
        len(MANIFEST), "YES" if index_ok else "NO"))
    print("  every README carries all required sections: %s" % (
        "YES" if all_readmes_ok else "NO"))

    ok = index_ok and all_readmes_ok
    print("")
    print("PORTFOLIO MANIFEST AND README GENERATED: %s" % ("YES" if ok else "NO"))
    if not ok:
        sys.exit(1)
    print("Packaged, screenable in thirty seconds, outcome-first. That is a portfolio that gets hired.")


if __name__ == "__main__":
    main()
Runnable lab
cap7-packaging.py

Generate the portfolio index and a README per project, and prove each one carries every required section.

Proves: PORTFOLIO MANIFEST AND README GENERATED: YES

Open the notebook

Runs in your browser via Pyodide. First run loads the runtime once; no install, no server.

The generator produced a portfolio index and a README for every project, each one leading with the outcome and carrying a demo link, metrics, and a stack, and each one passed the same section check the course opened with. That closes the loop: Chapter 1 defined portfolio-ready as a scored rubric, and the last chapter proves your packaging satisfies it. You have finished the course, and the program. You can now build the exact portfolio the research says gets people hired: a deployed RAG assistant that cites its sources, a tool-calling agent that solves a real workflow safely, a reusable eval pipeline, an MCP-connected assistant, and a self-red-teamed secure app, each shipped, measured, and packaged so a stranger understands it in thirty seconds. That portfolio, not a transcript, is what turns everything you learned here into a job.
Check your understanding
  1. 1. Why does every project README lead with the business outcome?

  2. 2. What did the packaging lab use as its acceptance test?

  3. 3. What is the point of the portfolio index?