diff --git a/.github/agent-instructions/chapter-author-agent.md b/.github/agent-instructions/chapter-author-agent.md new file mode 100644 index 0000000..082ec89 --- /dev/null +++ b/.github/agent-instructions/chapter-author-agent.md @@ -0,0 +1,21 @@ +# Chapter Author Agent Instructions + +## Mission +Create or update the chapter notebook from the chapter PDF, open/update the PR, and iterate until review agents report no blocking concerns. + +## Workflow +1. Read chapter PDF and draft notebook structure that follows chapter flow. +2. Add initial explanations, derivations, examples, and exercises. +3. Submit PR with chapter PDF + notebook pair. +4. Wait for review comments from: + - Content Coverage Agent + - Interactivity Agent +5. Apply requested updates with high educational value. +6. Push revisions and re-run review cycle. +7. Repeat until both agents pass. +8. Mark PR ready for human review. + +## Completion gate +Proceed to human review only when: +- No unresolved missing-concept findings from content review. +- No unresolved high-impact interactivity recommendations. diff --git a/.github/agent-instructions/content-coverage-agent.md b/.github/agent-instructions/content-coverage-agent.md new file mode 100644 index 0000000..d34c101 --- /dev/null +++ b/.github/agent-instructions/content-coverage-agent.md @@ -0,0 +1,27 @@ +# Content Coverage Agent Instructions + +## Mission +Review a chapter PR and verify that notebook content fully covers chapter concepts from the paired PDF. + +## Inputs +- Chapter PDF path from workflow output (`chapter_pdf`) +- Notebook path from workflow output (`chapter_notebook`) +- PR diff + +## Review rules +1. Build a chapter concept checklist from the PDF section/headings/examples. +2. Map each concept to where it appears in the notebook. +3. Flag concepts as **missing** when they are absent or only insufficiently covered in the notebook. +4. Do **not** flag extra material if it is relevant and pedagogically useful. +5. Prioritize mathematically meaningful omissions over formatting/editorial details. +6. A concept is considered covered only when the notebook includes explicit explanation, derivation, or a worked example. +7. Mentions only in variable names, comments, or section titles without explanatory text count as insufficient coverage and should be flagged. +8. Treat insufficient coverage as missing in output comments, and state why the current treatment is not enough for learner understanding. + +## Output format for PR comment +- Missing concept: `` + - Why it matters: `` + - Evidence from chapter: `
` + - Suggested notebook placement: `` + +If no meaningful omissions exist, post: `Coverage review passed: all core chapter concepts are present.` diff --git a/.github/agent-instructions/interactivity-agent.md b/.github/agent-instructions/interactivity-agent.md new file mode 100644 index 0000000..0e6ccab --- /dev/null +++ b/.github/agent-instructions/interactivity-agent.md @@ -0,0 +1,26 @@ +# Interactivity Agent Instructions + +## Mission +Review a chapter PR and propose notebook improvements that use visualization and interactivity to improve understanding. + +## Inputs +- Chapter PDF path from workflow output (`chapter_pdf`) +- Notebook path from workflow output (`chapter_notebook`) +- PR diff + +## Review rules +1. Identify concepts in the chapter where plots, sliders, animations, or parameter sweeps would improve comprehension. +2. Propose additions that are concrete and notebook-friendly. +3. Prefer additions tied directly to chapter learning goals. +4. Skip cosmetic-only suggestions unless they directly improve conceptual clarity. +5. Keep recommendations concise and prioritized by educational impact. +6. Rank educational impact by: (a) concept difficulty in the chapter, (b) likelihood of student misconceptions, and (c) how strongly interactivity clarifies parameter effects or geometric intuition. + +## Output format for PR comment +- Suggested interactive section: `` + - Concept supported: `<concept>` + - Why interactivity helps: `<learning value>` + - Suggested implementation direction: `<plot/widget idea>` + - Suggested location in notebook: `<where to insert>` + +If notebook interactivity is already strong for all major concepts, post: `Interactivity review passed: no high-impact additions identified.` diff --git a/.github/workflows/chapter-pr-agent-cycle.yml b/.github/workflows/chapter-pr-agent-cycle.yml new file mode 100644 index 0000000..4a0c059 --- /dev/null +++ b/.github/workflows/chapter-pr-agent-cycle.yml @@ -0,0 +1,178 @@ +name: Chapter PR Agent Cycle + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + paths: + - "NLPDE/**" + - ".github/agent-instructions/**" + - ".github/workflows/chapter-pr-agent-cycle.yml" + +permissions: + contents: read + pull-requests: write + +jobs: + chapter-context-check: + name: Verify chapter ↔ notebook mapping + runs-on: ubuntu-latest + outputs: + chapter_pdf: ${{ steps.detect.outputs.chapter_pdf }} + chapter_notebook: ${{ steps.detect.outputs.chapter_notebook }} + skip_review: ${{ steps.detect.outputs.skip_review }} + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Detect changed chapter assets + id: detect + shell: bash + run: | + set -euo pipefail + if [[ ! -d NLPDE ]]; then + echo "NLPDE directory not found in this checkout; skipping chapter review jobs." + echo "skip_review=true" >> "$GITHUB_OUTPUT" + echo "chapter_pdf=" >> "$GITHUB_OUTPUT" + echo "chapter_notebook=" >> "$GITHUB_OUTPUT" + exit 0 + fi + + BASE_SHA="${{ github.event.pull_request.base.sha }}" + HEAD_SHA="${{ github.event.pull_request.head.sha }}" + DIFF_OUTPUT="$(git diff --name-only "$BASE_SHA" "$HEAD_SHA" -- NLPDE)" || { + echo "Failed to compute NLPDE file diff for base=$BASE_SHA head=$HEAD_SHA." + exit 1 + } + mapfile -t CHANGED <<< "$DIFF_OUTPUT" + + if [[ ${#CHANGED[@]} -eq 0 ]]; then + echo "No files changed in NLPDE/. Workflow triggered by agent instruction or workflow updates only." + echo "skip_review=true" >> "$GITHUB_OUTPUT" + echo "chapter_pdf=" >> "$GITHUB_OUTPUT" + echo "chapter_notebook=" >> "$GITHUB_OUTPUT" + exit 0 + fi + echo "skip_review=false" >> "$GITHUB_OUTPUT" + + mapfile -t PDF_FILES < <(printf '%s\n' "${CHANGED[@]}" | grep -E '^NLPDE/[^/]*\.pdf$' || true) + mapfile -t IPYNB_FILES < <(printf '%s\n' "${CHANGED[@]}" | grep -E '^NLPDE/[^/]*\.ipynb$' || true) + + if [[ ${#PDF_FILES[@]} -eq 0 && ${#IPYNB_FILES[@]} -eq 0 ]]; then + echo "No chapter PDF or notebook files found in NLPDE/ changes." + echo "Update the chapter PDF and notebook pair in the same PR." + exit 1 + fi + + if [[ ${#PDF_FILES[@]} -ne 1 || ${#IPYNB_FILES[@]} -ne 1 ]]; then + echo "Expected exactly one chapter PDF and one notebook update per PR." + echo "Found ${#PDF_FILES[@]} PDF file(s):" + if [[ ${#PDF_FILES[@]} -eq 0 ]]; then + echo "<none>" + else + printf '%s\n' "${PDF_FILES[@]}" + fi + echo "Found ${#IPYNB_FILES[@]} notebook file(s):" + if [[ ${#IPYNB_FILES[@]} -eq 0 ]]; then + echo "<none>" + else + printf '%s\n' "${IPYNB_FILES[@]}" + fi + exit 1 + fi + + PDF="${PDF_FILES[0]}" + IPYNB="${IPYNB_FILES[0]}" + + PDF_BASE="$(basename "$PDF" .pdf)" + IPYNB_BASE="$(basename "$IPYNB" .ipynb)" + if [[ "$PDF_BASE" != "$IPYNB_BASE" ]]; then + echo "Expected 1:1 chapter naming, but found:" + echo "PDF: $PDF_BASE" + echo "Notebook: $IPYNB_BASE" + echo "Use matching base names, for example: NLPDE_Ch2.pdf and NLPDE_Ch2.ipynb" + exit 1 + fi + + echo "chapter_pdf=$PDF" >> "$GITHUB_OUTPUT" + echo "chapter_notebook=$IPYNB" >> "$GITHUB_OUTPUT" + + content-coverage-agent: + name: Content coverage review + needs: chapter-context-check + if: needs.chapter-context-check.outputs.skip_review != 'true' + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Load content agent instructions + id: content_prompt + shell: bash + run: | + { + echo "prompt<<EOF" + cat .github/agent-instructions/content-coverage-agent.md + echo "EOF" + } >> "$GITHUB_OUTPUT" + + - name: Review chapter coverage (placeholder) + env: + CONTENT_AGENT_PROMPT: ${{ steps.content_prompt.outputs.prompt }} + run: | + echo "Integrate your preferred PR review agent here." + echo "Context PDF: ${{ needs.chapter-context-check.outputs.chapter_pdf }}" + echo "Context notebook: ${{ needs.chapter-context-check.outputs.chapter_notebook }}" + echo "Goal: report missing concepts from chapter in notebook (additional relevant material is allowed)." + echo "Instruction payload size: ${#CONTENT_AGENT_PROMPT} characters" + + interactivity-agent: + name: Interactivity and visualization review + needs: chapter-context-check + if: needs.chapter-context-check.outputs.skip_review != 'true' + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Load interactivity agent instructions + id: interactivity_prompt + shell: bash + run: | + { + echo "prompt<<EOF" + cat .github/agent-instructions/interactivity-agent.md + echo "EOF" + } >> "$GITHUB_OUTPUT" + + - name: Suggest interactive improvements (placeholder) + env: + INTERACTIVITY_AGENT_PROMPT: ${{ steps.interactivity_prompt.outputs.prompt }} + run: | + echo "Integrate your preferred PR review agent here." + echo "Context PDF: ${{ needs.chapter-context-check.outputs.chapter_pdf }}" + echo "Context notebook: ${{ needs.chapter-context-check.outputs.chapter_notebook }}" + echo "Goal: suggest concrete plot/interactivity additions that improve learning outcomes." + echo "Instruction payload size: ${#INTERACTIVITY_AGENT_PROMPT} characters" + + author-revision-loop: + name: Author agent revision loop guidance + needs: [chapter-context-check, content-coverage-agent, interactivity-agent] + if: needs.chapter-context-check.outputs.skip_review != 'true' + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Load author agent instructions + run: cat .github/agent-instructions/chapter-author-agent.md + + config-only-update: + name: Config-only update notice + needs: chapter-context-check + if: needs.chapter-context-check.outputs.skip_review == 'true' + runs-on: ubuntu-latest + steps: + - name: Explain skip + run: echo "Skipping chapter review jobs because no NLPDE chapter files changed." diff --git a/docs/agent-workflow.md b/docs/agent-workflow.md new file mode 100644 index 0000000..90d670a --- /dev/null +++ b/docs/agent-workflow.md @@ -0,0 +1,33 @@ +# Chapter PR Agent Workflow + +This repository uses a PR-centered multi-agent loop for chapter development in `NLPDE/`. + +## Agents +1. **Chapter Author Agent** + - Creates or updates a chapter notebook from the chapter PDF. + - Opens/updates the PR and applies agent feedback. +2. **Content Coverage Agent** + - Uses the chapter PDF as source-of-truth context. + - Verifies notebook concept coverage and reports missing concepts only. +3. **Interactivity Agent** + - Uses the chapter PDF and notebook to propose high-impact visualization/interactivity additions. + +## PR trigger +Workflow file: `.github/workflows/chapter-pr-agent-cycle.yml` + +On PR updates affecting `NLPDE/**`, the workflow: +- Enforces a 1:1 chapter mapping by requiring exactly one changed PDF and one changed notebook in `NLPDE/`, with identical filenames before the extension (case-sensitive), e.g., `NLPDE/NLPDE_Ch2.pdf` ↔ `NLPDE/NLPDE_Ch2.ipynb`. +- Runs content coverage review stage. +- Runs interactivity review stage. +- Runs author revision-loop guidance stage. + +## Preprocessing recommendation (shared chapter context) +Yes—preprocessing is recommended because multiple agents reuse the same chapter context. + +Recommended pattern: +1. Extract chapter PDF text once in a preprocessing step. +2. Chunk by section/subsection with page metadata. +3. Create embeddings and index chunks in a vector store. +4. Expose retrieval output to each agent so all reviews use consistent chapter evidence. + +This reduces repeated parsing costs, improves consistency across agent comments, and helps produce page/section-cited feedback.