diff --git a/docs/06-working-with-pull-requests.md b/docs/06-working-with-pull-requests.md index 3b9a3ac9..69f5a8a6 100644 --- a/docs/06-working-with-pull-requests.md +++ b/docs/06-working-with-pull-requests.md @@ -137,6 +137,8 @@ This is your first challenge that uses GitHub's web editor, so take a moment wit 3. Verify the **base branch** is `main` and the **compare branch** is your `fix/yourname-issueXX` branch. 4. Activate the **Create pull request** button. +> **Note:** This title only needs to make sense for this one PR. It has no bearing on later chapters - some later challenges (Chapter 7, for example) automatically open their own separate pull request with a title the automation chooses. You never need to reuse or match a title across challenges. + **You are done when:** Your PR appears in the Pull Requests list. The bot will begin running checks within about 30 seconds. Continue to Challenge 6.3. ### Challenge 6.3 Step-by-Step: Pass Required Checks diff --git a/html/docs/06-working-with-pull-requests.html b/html/docs/06-working-with-pull-requests.html index 815f9629..f82617c0 100644 --- a/html/docs/06-working-with-pull-requests.html +++ b/html/docs/06-working-with-pull-requests.html @@ -457,6 +457,9 @@
main and the compare branch is your fix/yourname-issueXX branch.+Note: This title only needs to make sense for this one PR. It has no bearing on later chapters - some later challenges (Chapter 7, for example) automatically open their own separate pull request with a title the automation chooses. You never need to reuse or match a title across challenges.
+
You are done when: Your PR appears in the Pull Requests list. The bot will begin running checks within about 30 seconds. Continue to Challenge 6.3.
Goal: Read bot feedback, fix any issues it finds, and get all required checks to pass.
diff --git a/html/search-index.json b/html/search-index.json index a535c76e..2ce1b9b7 100644 --- a/html/search-index.json +++ b/html/search-index.json @@ -437,12 +437,6 @@ "url": "docs/appendix-j-cloud-editors.html", "body": "Appendix J: GitHub Codespaces Listen to Episode 31: GitHub Codespaces - a conversational audio overview of this chapter. Listen before reading to preview the concepts, or after to reinforce what you learned. Reference companion to: Chapter 01: Choose Your Tools | Also relevant: Chapter 11 Authoritative source: GitHub Docs: Codespaces Cloud Development Environments - Accessibility Guide GitHub Codespaces gives you a full VS Code development environment in your browser or connected to your local VS Code, running on a cloud machine. For screen reader users, this means a consistent, pre-configured environment with no local setup required. Table of Contents What Is GitHub Codespaces? Creating a Codespace Codespace Environments Accessibility in Codespaces Screen Reader Configuration Keyboard Shortcuts in Codespaces Managing Your Codespaces Dotfiles and Persistent Configuration Codespaces vs GitHub.dev Common Issues and Workarounds 1. What Is GitHub Codespaces? A Codespace is a cloud-hosted development environment. When you open one, GitHub provisions a virtual machine, clones your repository into it, and connects it to a VS Code interface - either in your browser or via your local VS Code Desktop. Why this matters for accessibility No local installation of tools, compilers, or language runtimes required Your screen reader and OS settings stay on your machine; only the editor runs in the cloud VS Code's full accessibility features (audio cues, screen reader optimized mode, diff viewer) are available The environment is identical for every workshop participant - facilitators can reproduce issues reliably Free tier: GitHub provides a monthly free allowance of Codespace hours for personal accounts. Workshop usage typically falls well within the free tier. Learning Cards: Cloud Editors Overview Screen reader users Codespaces gives you a full VS Code interface with terminal access -- your screen reader and OS settings stay on your local machine The browser-based editor activates screen reader optimized mode automatically if your OS signals a screen reader is running Connect a Codespace to your local VS Code Desktop (via the Codespaces extension) for the most familiar screen reader experience Low vision users Settings Sync carries your font size, theme, and zoom preferences from local VS Code into Codespaces automatically The browser-based editor supports Ctrl+= / Ctrl+- zoom just like desktop VS Code Use a high-contrast VS Code theme -- it applies identically in the cloud editor Sighted users Press . on any GitHub repository page to open it instantly in github.dev (browser editor, no terminal) Codespaces provisions a full VM with terminal -- use it when you need to run code, not just edit The default 2-core machine is sufficient for workshop exercises; upgrade only for heavy builds 2. Creating a Codespace From a Repository Page Navigate to the repository on GitHub Press the Code button (keyboard shortcut: there is no direct shortcut - Tab to the button) In the panel that opens, choose the Codespaces tab Activate Create codespace on main (or your branch name) The Codespace opens in a new browser tab after provisioning (typically 30-60 seconds) From the Codespaces Dashboard Go to github.com/codespaces Activate New codespace Use the search field to find your repository Choose a branch, machine type, and region Activate Create codespace Machine Types Type CPU RAM Best for 2-core 2 vCPU 8 GB General development, documentation 4-core 4 vCPU 16 GB Builds, tests, moderate workloads 8-core 8 vCPU 32 GB Heavy builds, multiple services For workshop exercises, the default 2-core machine is sufficient. 3. Codespace Environments Browser (VS Code for the Web) The Codespace opens directly in your browser as a fully functional VS Code interface. Works in Chrome, Edge, Firefox, and Safari Screen reader support varies slightly by browser - Chrome and Edge have the most consistent behavior with NVDA and JAWS No installation needed Some VS Code extensions are not available in the browser version Local VS Code Desktop If you prefer your local VS Code setup with your extensions and settings: Install the GitHub Codespaces extension in VS Code Sign in to GitHub in VS Code Open the Command Palette ( Ctrl+Shift+P / Cmd+Shift+P ) Run Codespaces: Connect to Codespace Select an existing Codespace or create a new one When connected via local VS Code, your screen reader interacts with your local VS Code installation - all your familiar settings apply. 4. Accessibility in Codespaces Screen Reader Optimized Mode When VS Code detects a screen reader, it automatically activates Screen Reader Optimized mode. You can verify or toggle it manually: Open the Command Palette ( Ctrl+Shift+P ) Search for Toggle Screen Reader Accessibility Mode Press Enter to activate In this mode: The editor reads content line by line instead of character by character Diff views are rendered as accessible text comparisons Inline suggestions from Copilot are announced on a key" }, - { - "id": "docs/06-working-with-pull-requests.html", - "title": "Working with Pull Requests", - "url": "docs/06-working-with-pull-requests.html", - "body": "Working with Pull Requests Listen to Episode 6: Working with Pull Requests - a conversational audio overview of this chapter. Listen before reading to preview the concepts, or after to reinforce what you learned. Related appendices: Appendix C: Markdown Reference | Appendix B: Screen Reader Cheat Sheet Authoritative sources: GitHub Docs: About pull requests | GitHub Accessibility Guide: Pull Requests | GitHub Accessibility Lab: CLI Guide Creating, Reviewing, and Merging Pull Requests with a Screen Reader See also: Chapter 15: Code Review covers the full review workflow including multi-file diffs and suggested changes. Pull requests are where your work becomes a contribution. This guide takes you through the full pull request workflow - from opening one to participating in review - using only your keyboard and screen reader. Official GitHub Accessibility Guide: GitHub publishes an NVDA-focused guide for working with pull requests using a screen reader at Using GitHub Pull Requests with a Screen Reader . This chapter covers the same material with additional perspectives (VoiceOver, low vision, CLI) and workshop-specific challenges. Use the official guide as a companion reference. Screen reader note - New Files Changed Experience: This guide uses GitHub's improved Files Changed experience, which adds proper ARIA landmark structure to the Files Changed tab, including the file tree and diff navigation. This feature may already be active for your account - it has been broadly rolled out and may no longer appear as a Feature Preview toggle at all. To verify: Activate the User Menu button (top-right of any GitHub page) → activate "Feature preview" → scan the list for "New Files Changed Experience" : If listed and the toggle announces "Pressed" (or "Disable" ) - already enabled, no action needed If listed but not Pressed (or "Enable" ) - activate the toggle to enable it If not listed at all - the feature has graduated to the standard interface; it is active automatically Full step-by-step instructions with per-screen-reader commands are in Pre-Workshop Setup, Step 4 . Browse vs Focus Mode (NVDA): Use Browse Mode (the default) for reading PR conversations, navigating headings, and reviewing diffs. Switch to Focus Mode ( NVDA+Space ) only when you need to type in comment boxes or search fields. Switch back to Browse Mode to resume navigation. Maximize your browser window for consistent landmark layout. Workshop Recommendation (Chapter 6) Chapter 6 is the first PR-validated chapter where students convert issue work into merge-ready contributions. Challenge count: 3 Time per challenge: under 10 minutes each Evidence: PR metadata, bot checks, and merged issue linkage Pattern: small change -> linked PR -> green checks Chapter 6 Challenge Set Create one small branch change - edit a practice file on a new branch. Open a linked PR - use the PR template and include Closes #XX . Pass required checks - respond to bot feedback until all required checks pass. CLI getting-started principles for pull request work For reliable PR workflows in the terminal: Check current branch before pushing ( git branch --show-current ). Keep PR scope small (one focused change per branch). Confirm issue linkage in plain text ( Closes #<number> ). Validate check status after each push ( gh pr checks ). Prefer documented command options only ( gh pr --help ). Branch guidance for Chapter 6: This is the first chapter where you edit files and create branches. Use one of these two paths: Web editor (recommended for beginners): When you edit a file on GitHub.com and click "Propose changes," GitHub creates a branch for you automatically. Name it fix/yourname-issueXX (for example, fix/maria-issue42 ). Local Git (if you cloned in Block 0): Create a feature branch with git checkout -b fix/yourname-issueXX from main . See the "Local Git Alternative" section below for the full command sequence. Do not reuse your learn/<username> branch for this short exercise unless your facilitator tells you to. Chapter 6 works best with a short-lived feature branch such as fix/yourname-issueXX , because it teaches the pull request loop without mixing multiple challenges on one branch. Challenge 6.1 Step-by-Step: Create One Small Branch Change Goal: Edit one of the practice files and save your change on a new branch. Where you are working: your Learning Room repository on GitHub.com, using the web editor. Before you start: This section is preparation for your Challenge 6: Open Your First PR issue - there is no separate issue for making the edit itself. Pick one of the three practice files below, make one focused change, and save it on a new branch. When your branch has a commit, come back and continue with the PR steps later in this chapter. The Learning Room has three practice files with intentional problems. Your assigned issue points you to one of them: The following table summarizes" - }, { "id": "docs/08-open-source-culture.html", "title": "Culture, Etiquette, and Community Standards", @@ -485,6 +479,12 @@ "url": "docs/07-merge-conflicts.html", "body": "Merge Conflicts Listen to Episode 7: Merge Conflicts Are Not Scary - a conversational audio overview of this chapter. Listen before reading to preview the concepts, or after to reinforce what you learned. Related appendices: Appendix E: Advanced Git | Appendix G: VS Code Reference Authoritative sources: GitHub Docs: Resolving merge conflicts | Git SCM: Basic Merge Conflicts Understanding, Preventing, and Resolving Conflicts Merge conflicts sound intimidating but are a normal, manageable part of collaborative development. This guide explains what conflicts are, how to read conflict markers, and how to resolve them - step by step. Workshop Recommendation (Chapter 7) Chapter 7 uses one controlled practice challenge so students can learn conflict resolution without high-pressure scenarios. Challenge count: 1 Time: under 10 minutes Evidence: issue-linked PR and completion comment Pattern: observe, resolve, verify Chapter 7 Challenge Set Resolve conflict markers - identify and clean up conflict markers in an automatically opened practice pull request. Branch guidance for Chapter 7: No manual branch is needed this time. Opening your Challenge 7 issue automatically creates the practice branch and pull request for you. Challenge 7.1 Step-by-Step: Resolve Conflict Markers Goal: Identify the three types of conflict markers in a practice file, decide which content to keep, remove the markers, and submit a clean PR. Agentic strategy: Sometimes an AI agent will confidently generate code that conflicts with human-written code. Resolving merge conflicts is not just a hurdle for human teamwork; it is exactly how you supervise, correct, and collaborate safely with an AI. Where you are working: your Learning Room repository on GitHub.com (web editor) or in VS Code if you cloned locally. Before you start: Open your assigned Challenge 7 issue (the one titled "Challenge 7: Survive a Merge Conflict (@yourname)"). Opening that issue automatically opens a practice pull request in your repository with a real merge conflict already showing in docs/welcome.md - look for a comment on the issue linking that PR. Which tool should I use? Use the inline conflict editor on github.com for this challenge - not github.dev. The "Resolving Conflicts on GitHub (Web Editor)" tool cards further down this chapter cover several tools (github.com, github.dev, VS Code, GitHub Desktop, CLI) because real-world conflicts can happen anywhere. For this specific challenge, stick to the github.com path in the steps below; it's the one this walkthrough (and the evidence you'll post) assumes you used. Open the practice PR linked in the issue comment. Scroll to the bottom of its Conversation tab and click the Resolve conflicts button (see the "Tool Cards: Resolve a Merge Conflict" section further down this chapter for exactly where this button sits and how to reach it with a screen reader). This opens GitHub's inline conflict editor directly on the PR page - a full-page text editor, still on github.com. In that editor, search the file for <<<<<<< . This is the start marker - it shows where the conflict begins. Read the content between <<<<<<< and ======= . This is your version (the current branch). Read the content between ======= and >>>>>>> . This is their version (the incoming branch). Decide which content to keep: Keep only your version, or Keep only their version, or Combine both versions into one clean paragraph. Delete all three marker lines: The <<<<<<< HEAD line (or similar) The ======= separator line The >>>>>>> branch-name line Review the file to confirm no marker lines remain. Search for <<<<<<< again - there should be zero results. Click Mark as resolved (top-right of the file), then Commit merge (appears once every file in the PR is marked resolved) to finish resolving the conflict on the practice PR. The practice PR is disposable - its content is not meant to be merged into your real learning room. Once it shows no conflicts, you're done with it. You do not need to find or click "Close pull request" to complete this challenge; that button is for abandoning a PR entirely (covered later in this chapter for real-world conflicts) and is unrelated to finishing Challenge 7. Leave the practice PR open, or close it without merging if you'd like to tidy up - either is fine. Screen reader tip: Use your screen reader's find command ( Ctrl+F in browser, Ctrl+H in VS Code) to jump directly to <<<<<<< . The markers are plain text, so they are fully readable. You are done when: Your practice PR passes bot validation checks and contains no remaining conflict markers. Completion is judged by the issue evidence comment below, not by merging or closing the practice PR. Completing Chapter 7: Submit Your Evidence When your practice PR is resolved and passing ch" }, + { + "id": "docs/06-working-with-pull-requests.html", + "title": "Working with Pull Requests", + "url": "docs/06-working-with-pull-requests.html", + "body": "Working with Pull Requests Listen to Episode 6: Working with Pull Requests - a conversational audio overview of this chapter. Listen before reading to preview the concepts, or after to reinforce what you learned. Related appendices: Appendix C: Markdown Reference | Appendix B: Screen Reader Cheat Sheet Authoritative sources: GitHub Docs: About pull requests | GitHub Accessibility Guide: Pull Requests | GitHub Accessibility Lab: CLI Guide Creating, Reviewing, and Merging Pull Requests with a Screen Reader See also: Chapter 15: Code Review covers the full review workflow including multi-file diffs and suggested changes. Pull requests are where your work becomes a contribution. This guide takes you through the full pull request workflow - from opening one to participating in review - using only your keyboard and screen reader. Official GitHub Accessibility Guide: GitHub publishes an NVDA-focused guide for working with pull requests using a screen reader at Using GitHub Pull Requests with a Screen Reader . This chapter covers the same material with additional perspectives (VoiceOver, low vision, CLI) and workshop-specific challenges. Use the official guide as a companion reference. Screen reader note - New Files Changed Experience: This guide uses GitHub's improved Files Changed experience, which adds proper ARIA landmark structure to the Files Changed tab, including the file tree and diff navigation. This feature may already be active for your account - it has been broadly rolled out and may no longer appear as a Feature Preview toggle at all. To verify: Activate the User Menu button (top-right of any GitHub page) → activate "Feature preview" → scan the list for "New Files Changed Experience" : If listed and the toggle announces "Pressed" (or "Disable" ) - already enabled, no action needed If listed but not Pressed (or "Enable" ) - activate the toggle to enable it If not listed at all - the feature has graduated to the standard interface; it is active automatically Full step-by-step instructions with per-screen-reader commands are in Pre-Workshop Setup, Step 4 . Browse vs Focus Mode (NVDA): Use Browse Mode (the default) for reading PR conversations, navigating headings, and reviewing diffs. Switch to Focus Mode ( NVDA+Space ) only when you need to type in comment boxes or search fields. Switch back to Browse Mode to resume navigation. Maximize your browser window for consistent landmark layout. Workshop Recommendation (Chapter 6) Chapter 6 is the first PR-validated chapter where students convert issue work into merge-ready contributions. Challenge count: 3 Time per challenge: under 10 minutes each Evidence: PR metadata, bot checks, and merged issue linkage Pattern: small change -> linked PR -> green checks Chapter 6 Challenge Set Create one small branch change - edit a practice file on a new branch. Open a linked PR - use the PR template and include Closes #XX . Pass required checks - respond to bot feedback until all required checks pass. CLI getting-started principles for pull request work For reliable PR workflows in the terminal: Check current branch before pushing ( git branch --show-current ). Keep PR scope small (one focused change per branch). Confirm issue linkage in plain text ( Closes #<number> ). Validate check status after each push ( gh pr checks ). Prefer documented command options only ( gh pr --help ). Branch guidance for Chapter 6: This is the first chapter where you edit files and create branches. Use one of these two paths: Web editor (recommended for beginners): When you edit a file on GitHub.com and click "Propose changes," GitHub creates a branch for you automatically. Name it fix/yourname-issueXX (for example, fix/maria-issue42 ). Local Git (if you cloned in Block 0): Create a feature branch with git checkout -b fix/yourname-issueXX from main . See the "Local Git Alternative" section below for the full command sequence. Do not reuse your learn/<username> branch for this short exercise unless your facilitator tells you to. Chapter 6 works best with a short-lived feature branch such as fix/yourname-issueXX , because it teaches the pull request loop without mixing multiple challenges on one branch. Challenge 6.1 Step-by-Step: Create One Small Branch Change Goal: Edit one of the practice files and save your change on a new branch. Where you are working: your Learning Room repository on GitHub.com, using the web editor. Before you start: This section is preparation for your Challenge 6: Open Your First PR issue - there is no separate issue for making the edit itself. Pick one of the three practice files below, make one focused change, and save it on a new branch. When your branch has a commit, come back and continue with the PR steps later in this chapter. The Learning Room has three practice files with intentional problems. Your assigned issue points you to one of them: The following table summarizes" + }, { "id": "agents/image alt text agent/agents/image-alt-text.agent.html", "title": "image-alt-text.agent", @@ -2219,18 +2219,18 @@ "url": "admin/planning/TOOLING-INVENTORY.html", "body": "Tooling Inventory (Stage 1.4) Purpose: identify every source file in the content repo and the deploy/site repo that hardcodes an episode identifier, an appendix letter, or an audio slug, so Stage 1.3 (Site IA) and Stage 2+ (refactor) can be scoped accurately. The canonical identity source is now docs/EPISODE_MAP.json . Every locked field below should ultimately resolve through that map by narration_id , filename , or topic_prefix + topic_number . Scope of this inventory: Source-controlled tooling and authoring files in c:\\code\\git-going-with-github . Top-level scripts ( generate-*.bat , build-rss-feed.bat , validate-rss-feed.bat , generate-podcast-scripts.py ). podcasts/ tooling and configuration (excluding audio/ , chapters/ , transcripts/ , bundles/ , challenge-bundles/ , logs/ , _backups/ , _snapshot-*/ , llm-podcast-generator-review/generated/ , __pycache__/ ). scripts/ directory. docs/ (excluding EPISODE_MAP.json and EPISODE-MAP-SCHEMA.json ). admin/ markdown. Site repo c:\\code\\ggg . Out of scope (excluded as noise): html/ (generated site output). podcasts/audio/ (binary tagged mp3s, already updated). podcasts/_snapshot-pre-tagging-20260518/ , podcasts/_snapshot-pre-gpt55-20260518-164221/ , podcasts/_backups/ (snapshots). podcasts/logs/ , tmp-* files. podcasts/chapters/ , podcasts/transcripts/ , podcasts/bundles/ , podcasts/challenge-bundles/ (regenerable build outputs). podcasts/llm-podcast-generator-review/generated/ (regression run outputs). node_modules/ , .git/ , epub/ , learning-room/ (out of reorg scope). Counts shown below are raw hits from ripgrep against the patterns \\bep[0-9]{2}\\b , appendix-[a-z]+ , and cc-bonus-[a-e] . Group A: Live tooling that drives audio identity (MUST refactor) These files are part of the active audio/feed pipeline. Each one currently encodes the legacy ep##-slug / cc-NN-slug / cc-bonus-X-slug identity scheme and will need to switch to the canonical map. File Counts Role Refactor required podcasts/config/listening-order.json 58 ep, 5 bonus Defines the listener-facing order of all 79 items by slug, grouped by section headers ("Day 1: Issues...", "Day 2: ..."). Consumed by podcasts/lib/listening-plan.js , podcasts/generate-site.js , and the RSS feed builder via npm run build:podcast-site . Heavy. Replace with derivation from EPISODE_MAP.json track_number ordering. Section headers will need to be added as a new field on map entries (e.g. section_title ) or driven by learning_band groupings. Decision needed: keep section breaks, or flatten to single-stream feed. podcasts/build-bundles.js 77 appendix-, plus a large hardcoded const episodes = [...] array Generates NotebookLM source bundles for each episode. Carries the entire episode catalog inline ( slug , sources , concepts , crossRefs , prerequisites , duration ) and a SOURCE_ALIASES table that maps historical docs/*.md filenames to current ones. Consumed by npm run build:podcast-bundles and indirectly by generate-transcripts.bat . Heavy. The hardcoded episodes array is the parallel catalog of truth. Refactor to read from EPISODE_MAP.json and a separate bundle-config.json (concepts / crossRefs / prerequisites are bundle-only data not in the map; keep them, but key them by narration_id ). SOURCE_ALIASES is an orthogonal docs/* concern. podcasts/build-challenge-bundles.js 3 appendix- Companion to build-bundles.js for the 16 challenges and 5 bonus challenges. Same shape: inline catalog of slugs. Heavy. Same treatment as build-bundles.js . Key challenge bundles by challenge narration_id / topic_prefix=cc / topic_prefix=cc-bonus . podcasts/generate-draft-transcripts.js 1 ep## ref Generates the draft podcasts/scripts/**/*.txt files. Slug-aware: emits to podcasts/scripts/{chapters,challenges,appendices}/<slug>.txt . The three-bucket directory structure ( chapters/ , challenges/ , appendices/ ) is hardcoded. Medium. The three-bucket layout no longer matches the locked nine-band model (chapter, challenge, bonus, ref, git, tools, agents, sec, a11y). Decision needed: rename appendices/ to nine band-named subdirs, or keep flat. podcasts/tts/generate_episode.py 4 ep## TTS dispatcher invoked by generate-audio*.bat via python -m podcasts.tts.generate_audio --slug <slug> . Resolves slug to a script path under podcasts/scripts/{chapters,challenges,appendices}/<slug>.txt . Medium. Update path resolution if podcasts/scripts/ layout changes. Otherwise the script name (still ep##-... ) is the lookup key for the existing 79 mp3s, so this can stay slug-keyed until filenames are rotated in Stage 2. podcasts/tts/generate_all_kokoro.py 2 ep## Higher-level batch driver around generate_episode.py . Low. Same pattern as generate_episode.py . podcasts/listening_plan.py 1 ep## Reads podcasts/config/listening-order.json and emits a structured plan. Medium. Refactor once listening-order.json is replaced with map-derived ordering. podcasts/generate-site.js 1 ep## Builds podcasts/feed.xml and admin/PODCASTS.md . Consu" }, - { - "id": "admin/planning/2026-07-06-onboarding-verification-and-a11y-report-design.html", - "title": "Onboarding verification and accessibility-report design", - "url": "admin/planning/2026-07-06-onboarding-verification-and-a11y-report-design.html", - "body": "Onboarding verification and accessibility-report design Date: 2026-07-06 Status: Approved for implementation Background Two real support incidents (Community-Access/support#61 and #62) exposed two unrelated but structurally similar problems in the workshop's automation: The learning-room accessibility checker floods PRs with near-duplicate findings, making it hard for a screen reader user to find the actual actionable content (and, in Deborah Armstrong's case, to find the merge-conflict controls buried beneath it). Two separate automations (enrollment invitations, Challenge 7 conflict seeding) each silently assume a precondition holds, and say nothing when it doesn't - leaving the learner confused with no signal that anything is wrong until they file a support ticket. This spec covers two independent fixes. They touch different files and different audiences (learner-facing bot output vs. maintainer-owned provisioning code) and can be implemented and landed independently, but are specified together since both were designed in the same review. Part A: Fix the accessibility-checker flood Files: learning-room/.github/scripts/check_accessibility.py , learning-room/.github/workflows/content-validation.yml Root cause check_accessibility.py 's table-description check (around line 88) fires on every line that looks like it's part of a table ( if '|' in line ), rather than once per table. A single N-row table produces N near-identical "Table Description" findings instead of 1. This is what turned Deborah's PR into a 100+ item report. Fix Detect a table by its header line only: a line containing | immediately followed by a separator line matching ^\\s*\\|?\\s*:?-+:?\\s*(\\|\\s*:?-+:?\\s*)*\\|?\\s*$ (standard GFM table separator). Emit at most one "Table Description" finding per table block (keyed by the header line's line number), not one per row. Everything else in the file (alt text, link text) is already correctly scoped to one finding per occurrence - no change needed there. Comment presentation In content-validation.yml 's "Post validation feedback" step: Group feedback.accessibility items by file under a #### <file> sub-heading inside the existing ### Accessibility section, so a screen reader user can skip a whole file's worth of findings via heading navigation. Add a one-line count summary immediately under ### Accessibility , e.g. **3 suggestions across 2 files.** , so scope is clear before reading further. Same treatment is not needed for errors / warnings right now - only accessibility has shown this volume in practice. Do not add speculative grouping to sections with no evidence of the problem (YAGNI). Testing No test harness exists today for learning-room/.github/scripts/*.py (verified: no __tests__ , no pytest config). Add learning-room/.github/scripts/__tests__/test_check_accessibility.py using Python's stdlib unittest (no new dependency), asserting: A 10-row, single-header table produces exactly 1 "Table Description" finding. A file with 2 separate tables produces exactly 2 findings, each attributed to the correct file and header line. A non-table block containing | characters (e.g. inline code with a pipe) does not produce a false positive. Part B: Verify-then-tell-the-truth for two silent-assumption spots B1: Enrollment invitation status Files: .github/scripts/provisioning/github-client.js , .github/scripts/provisioning/provision-core.js , .github/scripts/provisioning/roster.js , roster.schema.json , .github/scripts/provisioning/sync-intake-to-roster.js github-client.js 's ensureCollaborator() already returns { status: 'invited' | 'already-collaborator' } (both the raw- request and fromOctokit variants). Today provision-core.js calls it and discards the result. Changes: Roster schema: add intake_issue_number (integer) and intake_repo (string, owner/name ) as optional fields on a learner record in roster.schema.json . sync-intake-to-roster.js : populate these two fields directly (structured data) instead of only embedding from intake issue #N inside the free-text notes field. Keep writing to notes too, for human readability - just stop being the only source. github-client.js : add a commentOnIssue({ owner, repo, issue_number, body }) method to both the raw- request client and the fromOctokit adapter. provision-core.js : capture the ensureCollaborator() result, include it in provisionLearner() 's return value ( { result, healed, templateSha, collaboratorStatus } ), and - when intake_issue_number / intake_repo are available on the learner record - post one follow-up comment on the intake issue: invited : "Your invitation email is on its way - accept it to open your learning room." already-collaborator : "You already have access - no invitation needed. Your learning room is at <link> ." (This is the exact message that would have resolved support#62 automatically, with no s" - }, { "id": "admin/planning/2026-07-06-a11y-report-dedup-and-grouping-plan.html", "title": "Accessibility Report Dedup and Grouping Implementation Plan", "url": "admin/planning/2026-07-06-a11y-report-dedup-and-grouping-plan.html", "body": "Accessibility Report Dedup and Grouping Implementation Plan For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox ( - [ ] ) syntax for tracking. Goal: Stop the learning-room accessibility checker from flooding student PRs with duplicate "Table Description" findings, and group whatever findings remain by file in the PR comment. Architecture: Two independent fixes in the learning-room/ template (copied into every student repo): (1) check_accessibility.py 's table-description check currently fires once per table row instead of once per table - fix the detection to key off the header+separator row pair; (2) extract the inline comment-building script in content-validation.yml into a plain, testable module ( build-content-validation-comment.js , mirroring the existing .github/scripts/validation-report.js pattern at the repo root) and group accessibility findings by file with a summary count line. Tech Stack: Python 3 stdlib ( re , unittest ) for the checker; Node.js ( node --test , no new dependency) for the comment builder, matching this repo's existing conventions. Global Constraints No new dependencies (Python stdlib only; Node built-in test runner only) - matches this repo's "no test framework dependency" convention (see root CLAUDE.md ). Do not change check_links.py , check_markdown.py , or the errors / warnings sections of the PR comment - no evidence of the same duplication/volume problem there (YAGNI). Preserve the exact existing "does this table have a description before it" heuristic (blank or | -starting previous line) - only change how many times it fires per table, not what it decides. This is the learning-room/ template only. Existing already-provisioned student repos are not touched by this plan (out of scope - see spec). Task 1: Fix per-row duplication in the table-description check Files: Modify: learning-room/.github/scripts/check_accessibility.py Create: learning-room/.github/scripts/__tests__/test_check_accessibility.py Interfaces: Consumes: nothing new. Produces: check_accessibility(filepath) (unchanged signature, already exists) now returns at most one {'title': 'Table Description', ...} finding per table instead of one per row. Step 1: Write the failing tests Create learning-room/.github/scripts/__tests__/test_check_accessibility.py : #!/usr/bin/env python3 """Tests for check_accessibility.py's table-description detection. Run with: python learning-room/.github/scripts/__tests__/test_check_accessibility.py """ import os import sys import tempfile import unittest sys.path.insert( 0 , os.path.join(os.path.dirname(__file__), '..' )) from check_accessibility import check_accessibility # noqa: E402 def write_temp_md ( content ): fd, path = tempfile.mkstemp(suffix= '.md' ) with os.fdopen(fd, 'w' , encoding= 'utf-8' ) as f: f.write(content) return path class TableDescriptionDedupTests (unittest.TestCase): def test_single_table_produces_one_finding_regardless_of_row_count ( self ): rows = '\\n' .join( f'| Row {i} | Value {i} |' for i in range ( 10 )) content = ( 'Some intro text.\\n\\n' '| Name | Value |\\n' '|------|-------|\\n' f' {rows} \\n' ) path = write_temp_md(content) try : issues = check_accessibility(path) finally : os.remove(path) table_findings = [i for i in issues if i.get( 'title' ) == 'Table Description' ] self .assertEqual( len (table_findings), 1 ) def test_two_tables_produce_two_findings ( self ): content = ( 'Intro.\\n\\n' '| A | B |\\n' '|---|---|\\n' '| 1 | 2 |\\n\\n' 'Middle text.\\n\\n' '| C | D |\\n' '|---|---|\\n' '| 3 | 4 |\\n' ) path = write_temp_md(content) try : issues = check_accessibility(path) finally : os.remove(path) table_findings = [i for i in issues if i.get( 'title' ) == 'Table Description' ] self .assertEqual( len (table_findings), 2 ) def test_inline_pipe_outside_table_is_not_flagged ( self ): content = ( 'Use the command `a | b` to pipe output.\\n\\n' 'Just a line with | in it but no real table.\\n' ) path = write_temp_md(content) try : issues = check_accessibility(path) finally : os.remove(path) table_findings = [i for i in issues if i.get( 'title' ) == 'Table Description' ] self .assertEqual( len (table_findings), 0 ) if __name__ == '__main__' : unittest.main() Step 2: Run the tests to verify they fail Run: python learning-room/.github/scripts/__tests__/test_check_accessibility.py -v Expected: test_single_table_produces_one_finding_regardless_of_row_count and test_two_tables_produce_two_findings FAIL ( AssertionError: 10 != 1 and AssertionError: 20 != 2 respectively - one finding per row to" }, + { + "id": "admin/planning/2026-07-06-onboarding-verification-and-a11y-report-design.html", + "title": "Onboarding verification and accessibility-report design", + "url": "admin/planning/2026-07-06-onboarding-verification-and-a11y-report-design.html", + "body": "Onboarding verification and accessibility-report design Date: 2026-07-06 Status: Approved for implementation Background Two real support incidents (Community-Access/support#61 and #62) exposed two unrelated but structurally similar problems in the workshop's automation: The learning-room accessibility checker floods PRs with near-duplicate findings, making it hard for a screen reader user to find the actual actionable content (and, in Deborah Armstrong's case, to find the merge-conflict controls buried beneath it). Two separate automations (enrollment invitations, Challenge 7 conflict seeding) each silently assume a precondition holds, and say nothing when it doesn't - leaving the learner confused with no signal that anything is wrong until they file a support ticket. This spec covers two independent fixes. They touch different files and different audiences (learner-facing bot output vs. maintainer-owned provisioning code) and can be implemented and landed independently, but are specified together since both were designed in the same review. Part A: Fix the accessibility-checker flood Files: learning-room/.github/scripts/check_accessibility.py , learning-room/.github/workflows/content-validation.yml Root cause check_accessibility.py 's table-description check (around line 88) fires on every line that looks like it's part of a table ( if '|' in line ), rather than once per table. A single N-row table produces N near-identical "Table Description" findings instead of 1. This is what turned Deborah's PR into a 100+ item report. Fix Detect a table by its header line only: a line containing | immediately followed by a separator line matching ^\\s*\\|?\\s*:?-+:?\\s*(\\|\\s*:?-+:?\\s*)*\\|?\\s*$ (standard GFM table separator). Emit at most one "Table Description" finding per table block (keyed by the header line's line number), not one per row. Everything else in the file (alt text, link text) is already correctly scoped to one finding per occurrence - no change needed there. Comment presentation In content-validation.yml 's "Post validation feedback" step: Group feedback.accessibility items by file under a #### <file> sub-heading inside the existing ### Accessibility section, so a screen reader user can skip a whole file's worth of findings via heading navigation. Add a one-line count summary immediately under ### Accessibility , e.g. **3 suggestions across 2 files.** , so scope is clear before reading further. Same treatment is not needed for errors / warnings right now - only accessibility has shown this volume in practice. Do not add speculative grouping to sections with no evidence of the problem (YAGNI). Testing No test harness exists today for learning-room/.github/scripts/*.py (verified: no __tests__ , no pytest config). Add learning-room/.github/scripts/__tests__/test_check_accessibility.py using Python's stdlib unittest (no new dependency), asserting: A 10-row, single-header table produces exactly 1 "Table Description" finding. A file with 2 separate tables produces exactly 2 findings, each attributed to the correct file and header line. A non-table block containing | characters (e.g. inline code with a pipe) does not produce a false positive. Part B: Verify-then-tell-the-truth for two silent-assumption spots B1: Enrollment invitation status Files: .github/scripts/provisioning/github-client.js , .github/scripts/provisioning/provision-core.js , .github/scripts/provisioning/roster.js , roster.schema.json , .github/scripts/provisioning/sync-intake-to-roster.js github-client.js 's ensureCollaborator() already returns { status: 'invited' | 'already-collaborator' } (both the raw- request and fromOctokit variants). Today provision-core.js calls it and discards the result. Changes: Roster schema: add intake_issue_number (integer) and intake_repo (string, owner/name ) as optional fields on a learner record in roster.schema.json . sync-intake-to-roster.js : populate these two fields directly (structured data) instead of only embedding from intake issue #N inside the free-text notes field. Keep writing to notes too, for human readability - just stop being the only source. github-client.js : add a commentOnIssue({ owner, repo, issue_number, body }) method to both the raw- request client and the fromOctokit adapter. provision-core.js : capture the ensureCollaborator() result, include it in provisionLearner() 's return value ( { result, healed, templateSha, collaboratorStatus } ), and - when intake_issue_number / intake_repo are available on the learner record - post one follow-up comment on the intake issue: invited : "Your invitation email is on its way - accept it to open your learning room." already-collaborator : "You already have access - no invitation needed. Your learning room is at <link> ." (This is the exact message that would have resolved support#62 automatically, with no s" + }, { "id": "admin/planning/2026-07-06-provisioning-verification-messaging-plan.html", "title": "Provisioning Verification Messaging Implementation Plan",