fix(M7-27+capstone): apply AI-drives-git reframe, lesson=theory, de-slop course-wide

Phase 2 sweep — all modules are post-pivot, so the learner directs the AI agent
(Claude Code as the worked example) to do the git/setup work and verifies, instead
of typing commands by hand; no re-teaching basics. Lesson sections are theory with
example output; all execution lives in the labs. De-slopped ("prose" etc. gone
course-wide, em-dash density thinned). /path/to placeholders -> ~/ai-workflow-course.

Every deliberate teaching device verified intact: M10 ai-change.patch trap,
M12 bad-clear-snippet, M13/M27 planted pending_count bug, M15 secret+typosquat+MD5,
M18 BREAK=1, M21 absent-.gitignore, M22 poisoned skill, M24 no-op patch, M25 --simulate.
Labs compile/parse (py/sh/yaml/json); no junk.

Closes #83
Closes #86
Closes #89

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TfzV5QvtPDz8LJS3Pu5VLT
This commit is contained in:
2026-06-22 21:58:17 -04:00
parent a29823f4b3
commit f925fd9645
38 changed files with 1735 additions and 1424 deletions
+5 -5
View File
@@ -4,7 +4,7 @@ Stands in for a forge-native triage agent (triggered when an issue opens) withou
It assembles the prompt, then validates and renders the AI's suggestion — and stops at a human
confirm. The agent proposes labels and a route; it does not apply them.
python triage.py prompt # taxonomy + issue -> prompt. Paste to your AI.
python triage.py prompt # taxonomy + issue -> prompt for the agent
python triage.py apply ai-triage.sample.json # validate + render + confirm gate
The validation step matters: the agent may only use labels that exist in label-taxonomy.md. A
@@ -42,9 +42,9 @@ def allowed_labels(taxonomy_text: str) -> set[str]:
def load_json_response(path: Path):
"""Parse the JSON the AI returned.
Chat assistants very often wrap their output in a ```json ... ``` code fence (or add a line of
prose) even when told to "return only the JSON" so a strict json.loads on the raw paste fails
on the most likely real output. Try a strict parse first; if that fails, fall back to the
Chat assistants very often wrap their output in a ```json ... ``` code fence (or add a stray
line of text) even when told to "return only the JSON", so a strict json.loads on the raw paste
fails on the most likely real output. Try a strict parse first; if that fails, fall back to the
outermost { ... } block, which survives a code fence or surrounding text. Stdlib only."""
raw = path.read_text()
try:
@@ -109,7 +109,7 @@ def main(argv: list[str]) -> int:
parser = argparse.ArgumentParser(description=__doc__)
sub = parser.add_subparsers(dest="cmd", required=True)
p = sub.add_parser("prompt", help="assemble the triage prompt to paste to your AI")
p = sub.add_parser("prompt", help="assemble the triage prompt for the agent to act on")
p.add_argument("--taxonomy", default=str(HERE / "label-taxonomy.md"))
p.add_argument("--issue", default=str(HERE / "sample-issue.md"))
p.set_defaults(func=cmd_prompt)