style(no-slop): remove every em-dash + banned words across all modules + capstone

Apply the no-ai-slop standard (now binding in AGENTS.md): the em-dash character is
banned outright (restructured, not blind-replaced), plus the banned word/phrase
list (delve, leverage, robust, seamless, truly, unlock, etc.). 0 em-dashes remain
in modules + capstone; the only "robust" left is the planted M10 ai-change.patch
trap. Module H1 titles use a colon separator.

All deliberate teaching devices preserved; labs compile/parse (py/sh/yaml/json);
no junk. AGENTS.md updated with the hard no-slop rules.

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 23:21:09 -04:00
parent 513d7e7ac8
commit 389ac2e460
99 changed files with 1324 additions and 1315 deletions
@@ -6,13 +6,13 @@
"file": "cli.py",
"line": 49,
"severity": "blocker",
"comment": "The `clear` branch never calls save(tlist). The list is emptied in memory and the process exits, so tasks.json is untouched. It prints 'cleared all tasks' but the next `list` shows everything still there a silent no-op. Add save(tlist) before printing."
"comment": "The `clear` branch never calls save(tlist). The list is emptied in memory and the process exits, so tasks.json is untouched. It prints 'cleared all tasks' but the next `list` shows everything still there, a silent no-op. Add save(tlist) before printing."
},
{
"file": "tasks.py",
"line": 28,
"severity": "suggestion",
"comment": "No test covers clear(). Add one that adds two tasks, calls clear(), and asserts the list is empty matching the Module 13 suite style."
"comment": "No test covers clear(). Add one that adds two tasks, calls clear(), and asserts the list is empty, matching the Module 13 suite style."
},
{
"file": "tasks.py",
@@ -1,11 +1,11 @@
# Label taxonomy the triage agent's instructions
# Label taxonomy: the triage agent's instructions
The triage agent reads this file, then reads one incoming issue, and proposes labels, a priority,
and where the issue should be routed. Like the review rubric, this is committed and versioned: your
triage taxonomy is a project decision, not a setting buried in some bot's web UI.
**The labels below are the only labels that exist.** The agent must choose from this list. If it
invents a label that isn't here, the lab's `triage.py` rejects the whole suggestion that rejection
invents a label that isn't here, the lab's `triage.py` rejects the whole suggestion; that rejection
is a guardrail, not a bug. An agent that can mint arbitrary labels is an agent that can quietly
reshape your taxonomy; keeping the allowed set in version control and validating against it is how
you keep the agent inside its lane (the least-privilege idea from Module 22).
@@ -13,27 +13,27 @@ you keep the agent inside its lane (the least-privilege idea from Module 22).
## Allowed labels
Type (exactly one):
- `type:bug` something is broken or behaves wrong
- `type:feature` a request for new behavior
- `type:docs` documentation only
- `type:question` a usage question, not a code change
- `type:bug`: something is broken or behaves wrong
- `type:feature`: a request for new behavior
- `type:docs`: documentation only
- `type:question`: a usage question, not a code change
Priority (exactly one):
- `priority:p0` data loss, security, or the app is unusable for everyone
- `priority:p1` a serious bug with no good workaround
- `priority:p2` a real bug with a workaround, or a wanted feature
- `priority:p3` minor, cosmetic, or nice-to-have
- `priority:p0`: data loss, security, or the app is unusable for everyone
- `priority:p1`: a serious bug with no good workaround
- `priority:p2`: a real bug with a workaround, or a wanted feature
- `priority:p3`: minor, cosmetic, or nice-to-have
Area (zero or more):
- `area:cli` the command-line front end (`cli.py`)
- `area:core` task logic (`tasks.py`)
- `area:docs` README and lesson text
- `area:cli`: the command-line front end (`cli.py`)
- `area:core`: task logic (`tasks.py`)
- `area:docs`: README and lesson text
Readiness (exactly one) — this is the one that decides routing, and it's the Module 9 idea made
Readiness (exactly one). This is the one that decides routing, and it's the Module 9 idea made
concrete: an issue can go to a person *or* be handed to an agent.
- `ready:ai-ready` small, well-scoped, reproducible; safe to hand to an issue-to-PR agent (the
- `ready:ai-ready`: small, well-scoped, reproducible; safe to hand to an issue-to-PR agent (the
kind of agent Module 25 builds). Route `assignee_type: agent`.
- `ready:needs-human` ambiguous, risky, or needs a product decision. Route `assignee_type: human`.
- `ready:needs-human`: ambiguous, risky, or needs a product decision. Route `assignee_type: human`.
## Output format
@@ -1,11 +1,11 @@
# Review rubric the AI reviewer's instructions
# Review rubric: the AI reviewer's instructions
This is the committed instruction set the AI reviewer reads before it looks at a diff. It lives in
the repo on purpose: like the committed AI config from Module 5 and the skills from Module 21, a
review rubric is a durable, versioned artifact. Change how the reviewer behaves and that change
arrives as a diff in a PR, reviewable like any other.
Keep it short and opinionated. A vague rubric produces vague, noisy comments the fastest way to
Keep it short and opinionated. A vague rubric produces vague, noisy comments, the fastest way to
get a team to ignore the AI reviewer entirely.
## What to check, in priority order
@@ -17,7 +17,7 @@ get a team to ignore the AI reviewer entirely.
3. **Security smells (Module 15).** Hardcoded secrets, shelling out on unsanitized input, a new
dependency that doesn't obviously exist.
4. **Correctness on edge cases.** Empty input, bad index, missing file.
5. **Style nits last, and clearly labeled.** Only if they matter. Nits drown signal.
5. **Style nits, last, and clearly labeled.** Only if they matter. Nits drown signal.
## How to comment
+4 -4
View File
@@ -1,15 +1,15 @@
"""Assistive AI reviewer local simulation of a PR-reviewer bot.
"""Assistive AI reviewer: local simulation of a PR-reviewer bot.
This stands in for a forge-native reviewer (an app/bot triggered when a PR opens, running on a
runner from Module 19) without needing any hosted account. It does the two deterministic halves of
the job and leaves the one judgment call what actually happens to the PR to you.
the job and leaves the one judgment call (what actually happens to the PR) to you.
python reviewer.py prompt # assemble the prompt: rubric + diff, for the agent to review
python reviewer.py apply ai-review.sample.json # ingest the agent's JSON, render it, gate it
The point of this module: the agent produces comments and a recommendation. It never approves,
never requests-changes-as-a-gate, never merges. The `apply` step ends at a HUMAN DECISION, every
time. Stdlib only no pip install.
time. Stdlib only, no pip install.
"""
import argparse
@@ -68,7 +68,7 @@ def cmd_apply(args: argparse.Namespace) -> int:
comments = review.get("comments", [])
print("=" * 70)
print("AI REVIEWER first pass (advisory only)")
print("AI REVIEWER: first pass (advisory only)")
print("=" * 70)
print(f"\nSummary: {summary}\n")
@@ -1,6 +1,6 @@
Title: `done` command crashes on an empty list
When I run `python cli.py done 0` right after a fresh checkout before adding any tasks it throws
When I run `python cli.py done 0` right after a fresh checkout, before adding any tasks, it throws
an IndexError and dumps a stack trace instead of a friendly message. Every other command handles the
empty-list case fine, so this one feels like an oversight.
+7 -7
View File
@@ -1,14 +1,14 @@
"""Assistive issue-triage agent local simulation of a triage bot.
"""Assistive issue-triage agent: local simulation of a triage bot.
Stands in for a forge-native triage agent (triggered when an issue opens) without a hosted account.
It assembles the prompt, then validates and renders the AI's suggestion and stops at a human
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 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
hallucinated label is rejected. Stdlib only no pip install.
hallucinated label is rejected. Stdlib only, no pip install.
"""
import argparse
@@ -31,7 +31,7 @@ and a rationale for the issue that follows. Return ONLY the JSON object the taxo
"""
# Allowed labels are the backticked `prefix:value` tokens in the taxonomy file. Keeping the source
# of truth in the committed markdown not hardcoded here is the point.
# of truth in the committed markdown (not hardcoded here) is the point.
LABEL_RE = re.compile(r"`([a-z]+:[a-z0-9-]+)`")
@@ -75,7 +75,7 @@ def cmd_apply(args: argparse.Namespace) -> int:
bogus = [l for l in labels if l not in allowed]
if bogus:
print("=" * 70)
print("REJECTED the agent suggested labels that aren't in the taxonomy:")
print("REJECTED: the agent suggested labels that aren't in the taxonomy:")
for l in bogus:
print(f" - {l}")
print(
@@ -85,7 +85,7 @@ def cmd_apply(args: argparse.Namespace) -> int:
return 1
print("=" * 70)
print("TRIAGE AGENT suggestion (advisory only)")
print("TRIAGE AGENT: suggestion (advisory only)")
print("=" * 70)
print(f"\n Labels: {', '.join(labels) or '(none)'}")
print(f" Route to: {sug.get('assignee_type', '?')}")
@@ -99,7 +99,7 @@ def cmd_apply(args: argparse.Namespace) -> int:
" - confirm apply the labels and route as proposed\n"
" - edit change a label or the route, then apply\n"
" - reject the triage is wrong; do it yourself\n"
"\nA wrong label here costs one glance and one click to fix which is exactly why\n"
"\nA wrong label here costs one glance and one click to fix, which is exactly why\n"
"triage is the safe place to let an agent in first.\n"
)
return 0