Files
Rohit Ghumare 3ecf630b0f feat(projects): add 48 builds and a 52-project roadmap (#497)
* feat(projects): workflow-hooks stage 1

* feat(projects): workflow-hooks stage 2

* feat(projects): workflow-hooks stage 3

* feat(projects): workflow-hooks stage 4

* fix(projects): preserve sponsor navigation in project footer

* feat(projects): agent-budget-planner stage 1

* feat(projects): agent-budget-planner stage 2

* feat(projects): agent-budget-planner stage 3

* feat(projects): agent-budget-planner stage 4

* feat(projects): agent-trace-debugger stage 1

* feat(projects): agent-trace-debugger stage 2

* feat(projects): agent-trace-debugger stage 3

* feat(projects): agent-trace-debugger stage 4

* feat(projects): browser-agent stage 1

* feat(projects): browser-agent stage 2

* feat(projects): browser-agent stage 3

* feat(projects): browser-agent stage 4

* feat(projects): calendar-focus-planner stage 1

* feat(projects): calendar-focus-planner stage 2

* feat(projects): calendar-focus-planner stage 3

* feat(projects): calendar-focus-planner stage 4

* feat(projects): changelog-writer-from-git stage 1

* feat(projects): changelog-writer-from-git stage 2

* feat(projects): changelog-writer-from-git stage 3

* feat(projects): changelog-writer-from-git stage 4

* feat(projects): cloud-agent-with-aws-strands stage 1

* feat(projects): cloud-agent-with-aws-strands stage 2

* feat(projects): cloud-agent-with-aws-strands stage 3

* feat(projects): cloud-agent-with-aws-strands stage 4

* feat(projects): csv-sql-question-workbench stage 1

* feat(projects): csv-sql-question-workbench stage 2

* feat(projects): csv-sql-question-workbench stage 3

* feat(projects): csv-sql-question-workbench stage 4

* feat(projects): dataset-split-auditor stage 1

* feat(projects): dataset-split-auditor stage 2

* feat(projects): dataset-split-auditor stage 3

* feat(projects): dataset-split-auditor stage 4

* feat(projects): desktop-control stage 1

* feat(projects): desktop-control stage 2

* feat(projects): desktop-control stage 3

* feat(projects): desktop-control stage 4

* feat(projects): distributed-eval-farm stage 1

* feat(projects): distributed-eval-farm stage 2

* feat(projects): distributed-eval-farm stage 3

* feat(projects): distributed-eval-farm stage 4

* feat(projects): doc-qa-with-citations stage 1

* feat(projects): doc-qa-with-citations stage 2

* feat(projects): doc-qa-with-citations stage 3

* feat(projects): doc-qa-with-citations stage 4

* feat(projects): document-extraction-desk stage 1

* feat(projects): document-extraction-desk stage 2

* feat(projects): document-extraction-desk stage 3

* feat(projects): document-extraction-desk stage 4

* feat(projects): durable-agent-jobs stage 1

* feat(projects): durable-agent-jobs stage 2

* feat(projects): durable-agent-jobs stage 3

* feat(projects): durable-agent-jobs stage 4

* feat(projects): feedback-theme-board stage 1

* feat(projects): feedback-theme-board stage 2

* feat(projects): feedback-theme-board stage 3

* feat(projects): feedback-theme-board stage 4

* feat(projects): harness-bench stage 1

* feat(projects): harness-bench stage 2

* feat(projects): harness-bench stage 3

* feat(projects): harness-bench stage 4

* feat(projects): inbox-triage-desk stage 1

* feat(projects): inbox-triage-desk stage 2

* feat(projects): inbox-triage-desk stage 3

* feat(projects): inbox-triage-desk stage 4

* feat(projects): json-schema-output-guard stage 1

* feat(projects): json-schema-output-guard stage 2

* feat(projects): json-schema-output-guard stage 3

* feat(projects): json-schema-output-guard stage 4

* feat(projects): llm-gateway-with-fallbacks stage 1

* feat(projects): llm-gateway-with-fallbacks stage 2

* feat(projects): llm-gateway-with-fallbacks stage 3

* feat(projects): llm-gateway-with-fallbacks stage 4

* feat(projects): local-model-eval-harness stage 1

* feat(projects): local-model-eval-harness stage 2

* feat(projects): local-model-eval-harness stage 3

* feat(projects): local-model-eval-harness stage 4

* feat(projects): mcp-at-scale stage 1

* feat(projects): mcp-at-scale stage 2

* feat(projects): mcp-at-scale stage 3

* feat(projects): mcp-at-scale stage 4

* feat(projects): mcp-at-scale stage 5

* feat(projects): meeting-notes-to-actions stage 1

* feat(projects): meeting-notes-to-actions stage 2

* feat(projects): meeting-notes-to-actions stage 3

* feat(projects): meeting-notes-to-actions stage 4

* feat(projects): memory-server stage 1

* feat(projects): memory-server stage 2

* feat(projects): memory-server stage 3

* feat(projects): memory-server stage 4

* feat(projects): multi-agent-code-review-panel stage 1

* feat(projects): multi-agent-code-review-panel stage 2

* feat(projects): multi-agent-code-review-panel stage 3

* feat(projects): multi-agent-code-review-panel stage 4

* feat(projects): postmortem-writer stage 1

* feat(projects): postmortem-writer stage 2

* feat(projects): postmortem-writer stage 3

* feat(projects): postmortem-writer stage 4

* feat(projects): pr-review-reporter stage 1

* feat(projects): pr-review-reporter stage 2

* feat(projects): pr-review-reporter stage 3

* feat(projects): pr-review-reporter stage 4

* feat(projects): prompt-regression-tester stage 1

* feat(projects): prompt-regression-tester stage 2

* feat(projects): prompt-regression-tester stage 3

* feat(projects): prompt-regression-tester stage 4

* feat(projects): rag-freshness-pipeline stage 1

* feat(projects): rag-freshness-pipeline stage 2

* feat(projects): rag-freshness-pipeline stage 3

* feat(projects): rag-freshness-pipeline stage 4

* feat(projects): report-judge stage 1

* feat(projects): report-judge stage 2

* feat(projects): report-judge stage 3

* feat(projects): report-judge stage 4

* feat(projects): research-report-agent stage 1

* feat(projects): research-report-agent stage 2

* feat(projects): research-report-agent stage 3

* feat(projects): research-report-agent stage 4

* feat(projects): research-report-agent stage 5

* feat(projects): research-report-agent stage 6

* feat(projects): research-report-agent stage 7

* feat(projects): retrieval-evaluation-lab stage 1

* feat(projects): retrieval-evaluation-lab stage 2

* feat(projects): retrieval-evaluation-lab stage 3

* feat(projects): retrieval-evaluation-lab stage 4

* feat(projects): rust-agent-shell stage 1

* feat(projects): rust-agent-shell stage 2

* feat(projects): rust-agent-shell stage 3

* feat(projects): rust-agent-shell stage 4

* feat(projects): sandbox-ladder stage 1

* feat(projects): sandbox-ladder stage 2

* feat(projects): sandbox-ladder stage 3

* feat(projects): sandbox-ladder stage 4

* feat(projects): self-improving-skill-loop stage 1

* feat(projects): self-improving-skill-loop stage 2

* feat(projects): self-improving-skill-loop stage 3

* feat(projects): self-improving-skill-loop stage 4

* feat(projects): semantic-notes-search stage 1

* feat(projects): semantic-notes-search stage 2

* feat(projects): semantic-notes-search stage 3

* feat(projects): semantic-notes-search stage 4

* feat(projects): skill-installer stage 1

* feat(projects): skill-installer stage 2

* feat(projects): skill-installer stage 3

* feat(projects): skill-installer stage 4

* feat(projects): skill-router stage 1

* feat(projects): skill-router stage 2

* feat(projects): skill-router stage 3

* feat(projects): skill-router stage 4

* feat(projects): skill-scanner stage 1

* feat(projects): skill-scanner stage 2

* feat(projects): skill-scanner stage 3

* feat(projects): skill-scanner stage 4

* feat(projects): skill-validator stage 1

* feat(projects): skill-validator stage 2

* feat(projects): skill-validator stage 3

* feat(projects): skill-validator stage 4

* feat(projects): source-grounded-study-coach stage 1

* feat(projects): source-grounded-study-coach stage 2

* feat(projects): source-grounded-study-coach stage 3

* feat(projects): source-grounded-study-coach stage 4

* feat(projects): support-agent-with-google-adk stage 1

* feat(projects): support-agent-with-google-adk stage 2

* feat(projects): support-agent-with-google-adk stage 3

* feat(projects): support-agent-with-google-adk stage 4

* feat(projects): tiny-coding-agent stage 1

* feat(projects): tiny-coding-agent stage 2

* feat(projects): tiny-coding-agent stage 3

* feat(projects): tiny-coding-agent stage 4

* feat(projects): token-counter-and-cost-meter stage 1

* feat(projects): token-counter-and-cost-meter stage 2

* feat(projects): token-counter-and-cost-meter stage 3

* feat(projects): token-counter-and-cost-meter stage 4

* feat(projects): tool-call-firewall stage 1

* feat(projects): tool-call-firewall stage 2

* feat(projects): tool-call-firewall stage 3

* feat(projects): tool-call-firewall stage 4

* feat(projects): typed-workflow-agent-with-mastra stage 1

* feat(projects): typed-workflow-agent-with-mastra stage 2

* feat(projects): typed-workflow-agent-with-mastra stage 3

* feat(projects): typed-workflow-agent-with-mastra stage 4

* feat(projects): visual-evidence-library stage 1

* feat(projects): visual-evidence-library stage 2

* feat(projects): visual-evidence-library stage 3

* feat(projects): visual-evidence-library stage 4

* feat(projects): voice-note-transcriber-pipeline stage 1

* feat(projects): voice-note-transcriber-pipeline stage 2

* feat(projects): voice-note-transcriber-pipeline stage 3

* feat(projects): voice-note-transcriber-pipeline stage 4

* feat(projects): web-change-brief stage 1

* feat(projects): web-change-brief stage 2

* feat(projects): web-change-brief stage 3

* feat(projects): web-change-brief stage 4

* feat(projects): workflow-hooks stage 1

* feat(projects): workflow-hooks stage 2

* feat(projects): workflow-hooks stage 3

* feat(projects): workflow-hooks stage 4

* feat(projects): publish the practical application catalog

* feat(projects): add 52 planned builds to the roadmap

* fix(projects): make lesson animations explain computed changes

Stage mechanisms should expose the decisions learners are implementing. Preserve record identity as state changes and keep project context below the selected lesson.

* fix(projects): agent-budget-planner stage 01 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): agent-budget-planner stage 02 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): agent-budget-planner stage 03 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): agent-budget-planner stage 04 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): agent-trace-debugger stage 03 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): browser-agent stage 02 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): browser-agent stage 03 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): browser-agent stage 04 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): calendar-focus-planner stage 01 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): cloud-agent-with-aws-strands stage 01 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): cloud-agent-with-aws-strands stage 02 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): cloud-agent-with-aws-strands stage 04 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): desktop-control stage 04 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): distributed-eval-farm stage 01 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): distributed-eval-farm stage 02 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): distributed-eval-farm stage 04 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): document-extraction-desk stage 03 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): durable-agent-jobs stage 01 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): durable-agent-jobs stage 02 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): durable-agent-jobs stage 03 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): durable-agent-jobs stage 04 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): feedback-theme-board stage 01 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): inbox-triage-desk stage 03 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): llm-gateway-with-fallbacks stage 01 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): llm-gateway-with-fallbacks stage 04 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): mcp-at-scale review corrections

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): meeting-notes-to-actions stage 01 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): meeting-notes-to-actions stage 04 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): memory-server stage 04 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): pr-review-reporter stage 01 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): pr-review-reporter stage 03 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): pr-review-reporter stage 04 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): research-report-agent stage 01 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): retrieval-evaluation-lab review corrections

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): rust-agent-shell stage 01 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): rust-agent-shell stage 04 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): semantic-notes-search stage 03 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): skill-installer review corrections

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): skill-router stage 02 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): skill-router stage 04 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): tiny-coding-agent stage 02 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): voice-note-transcriber-pipeline stage 03 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): web-change-brief stage 03 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): workflow-hooks stage 01 contracts

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* fix(projects): site review corrections

Keep the stage contract, learner scaffold and verification evidence
consistent at the reviewed failure boundary.

* docs(projects): record verified review corrections
2026-09-29 21:38:54 +05:30

192 lines
6.0 KiB
Python

"""Render actual command transcripts or browser captures into GIF recordings.
Authoring dependency: Pillow and ffmpeg. Neither is needed by learners.
"""
import argparse
import html
import json
import os
from pathlib import Path
import shutil
import subprocess
import tempfile
import textwrap
import time
def execute(command, cwd, expected=0):
start = time.monotonic()
result = subprocess.run(
command, cwd=cwd, capture_output=True, text=True, timeout=180
)
output = result.stdout + result.stderr
if result.returncode != expected:
raise RuntimeError(
f"Expected exit {expected}, got {result.returncode}: {command}\n{output}"
)
return {
"command": command,
"cwd": str(cwd),
"exitCode": result.returncode,
"output": output,
"durationMs": round((time.monotonic() - start) * 1000),
}
def frame(lines, title):
from PIL import Image, ImageDraw, ImageFont
image = Image.new("RGB", (1120, 630), "#111a29")
draw = ImageDraw.Draw(image)
candidates = [
"/System/Library/Fonts/Menlo.ttc",
"/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf",
]
font = next(
(ImageFont.truetype(p, 18) for p in candidates if Path(p).exists()),
ImageFont.load_default(),
)
draw.text((28, 20), title[:85], font=font, fill="#9fb2d7")
draw.line((28, 55, 1092, 55), fill="#31415c")
for n, line in enumerate(lines[-22:]):
draw.text(
(28, 78 + n * 23),
line,
font=font,
fill="#89d9af" if line.startswith("$ ") else "#e4eaf5",
)
return image
def encode(frames, output, duration=450):
output = Path(output)
output.parent.mkdir(parents=True, exist_ok=True)
frames[-1].save(output.with_suffix(".png"))
if shutil.which("ffmpeg"):
with tempfile.TemporaryDirectory(prefix="aifs-gif-") as folder:
for i, image in enumerate(frames):
image.save(Path(folder) / f"{i:04d}.png")
subprocess.run(
[
"ffmpeg",
"-hide_banner",
"-loglevel",
"error",
"-y",
"-framerate",
str(1000 / duration),
"-i",
str(Path(folder) / "%04d.png"),
"-filter_complex",
"[0:v]split[a][b];[a]palettegen[p];[b][p]paletteuse",
"-loop",
"0",
str(output),
],
check=True,
)
else:
frames[0].save(
output, save_all=True, append_images=frames[1:], duration=duration, loop=0
)
def terminal(records, output, title):
frames, lines = [], []
for record in records:
lines.extend(
textwrap.wrap("$ " + " ".join(record["command"]), width=96) or [""]
)
frames.append(frame(lines, title))
chunks = []
for line in record["output"].splitlines():
chunks.extend(
textwrap.wrap(line.expandtabs(2), width=96, replace_whitespace=False)
or [""]
)
for offset in range(0, len(chunks), 4):
lines.extend(chunks[offset : offset + 4])
frames.append(frame(lines, title))
lines.append(f"exit {record['exitCode']}")
frames.extend([frame(lines, title)] * 3)
if not frames:
raise ValueError("Recording needs at least one command")
encode(frames, output)
Path(output).with_suffix(".json").write_text(
json.dumps(
{
"title": title,
"recordedAt": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
"records": records,
},
indent=2,
)
+ "\n"
)
def browser(url, output, title, browse, actions):
from PIL import Image
def call(*args):
return subprocess.run(
[browse, *args], check=True, capture_output=True, text=True, timeout=45
)
call("viewport", "1120x630")
call("goto", url)
frames = []
with tempfile.TemporaryDirectory(prefix="aifs-browser-gif-", dir="/tmp") as folder:
for i, action in enumerate([[]] + actions):
if action:
call(*action)
path = str(Path(folder) / f"{i}.png")
call("screenshot", "--viewport", path)
frames.extend([Image.open(path).convert("RGB").copy()] * 3)
encode(frames, output, 650)
Path(output).with_suffix(".json").write_text(
json.dumps(
{"title": title, "url": url, "actions": actions, "kind": "browser capture"},
indent=2,
)
+ "\n"
)
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
"--recipe", type=Path, help="JSON {cwd,title,commands:[{argv,expectExit?}]}"
)
parser.add_argument("--browser", help="URL to capture")
parser.add_argument(
"--actions", type=Path, help="JSON array of browse command arrays"
)
parser.add_argument("--browse", default=os.environ.get("BROWSE_BIN", "browse"))
parser.add_argument("--output", required=True, type=Path)
parser.add_argument("--title", default="Recorded project run")
args = parser.parse_args()
if args.browser:
browser(
args.browser,
args.output,
args.title,
args.browse,
json.loads(args.actions.read_text()) if args.actions else [],
)
elif args.recipe:
recipe = json.loads(args.recipe.read_text())
cwd = Path(recipe.get("cwd", ".")).resolve()
records = [
execute(command["argv"], cwd, command.get("expectExit", 0))
for command in recipe["commands"]
]
terminal(records, args.output, recipe.get("title", args.title))
else:
parser.error("choose --recipe or --browser")
if __name__ == "__main__":
main()