Active Recall Session: Agents — Planning vs execution separation #92
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Mark Review Complete | |
| concurrency: | |
| group: review-schedule-updates | |
| cancel-in-progress: false | |
| on: | |
| issues: | |
| types: [closed] | |
| permissions: | |
| contents: write | |
| issues: write | |
| jobs: | |
| mark-complete: | |
| runs-on: ubuntu-latest | |
| # Only run for review issues | |
| if: contains(github.event.issue.labels.*.name, 'review-needed') | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| - name: Mark review as complete | |
| id: mark-complete | |
| run: | | |
| node << 'EOF' | |
| const fs = require('fs'); | |
| const issueNumber = ${{ github.event.issue.number }}; | |
| console.log(`📝 Marking review complete for issue #${issueNumber}`); | |
| // Read schedule | |
| const schedulePath = 'docs/reviews/review-schedule.json'; | |
| if (!fs.existsSync(schedulePath)) { | |
| console.log('⚠️ No review schedule found'); | |
| process.exit(0); | |
| } | |
| const schedule = JSON.parse(fs.readFileSync(schedulePath, 'utf8')); | |
| let found = false; | |
| let problemInfo = null; | |
| // Find and update the review | |
| schedule.problems.forEach(problem => { | |
| problem.reviewsDue.forEach(review => { | |
| if (review.issueNumber === issueNumber) { | |
| review.completed = true; | |
| review.completedAt = new Date().toISOString(); | |
| found = true; | |
| // Track in completed reviews | |
| problem.reviewsCompleted.push({ | |
| reviewNumber: review.reviewNumber, | |
| completedAt: review.completedAt, | |
| issueNumber: issueNumber | |
| }); | |
| console.log(`✅ Marked complete: ${problem.problemName} - Review ${review.reviewNumber}`); | |
| // Schedule the next review if this isn't the last one | |
| const intervals = schedule.reviewIntervals; // [1, 3, 7, 14, 30] | |
| const nextReviewNumber = review.reviewNumber + 1; | |
| if (nextReviewNumber <= intervals.length) { | |
| // Calculate next review date based on completion date | |
| const completedDate = new Date(review.completedAt); | |
| const nextInterval = intervals[nextReviewNumber - 1]; | |
| const nextReviewDate = new Date(completedDate); | |
| nextReviewDate.setDate(nextReviewDate.getDate() + nextInterval); | |
| // Add next review to schedule | |
| problem.reviewsDue.push({ | |
| reviewNumber: nextReviewNumber, | |
| scheduledDate: nextReviewDate.toISOString().split('T')[0], | |
| interval: nextInterval, | |
| completed: false, | |
| issueNumber: null | |
| }); | |
| console.log(`📅 Scheduled review ${nextReviewNumber} for ${nextReviewDate.toISOString().split('T')[0]} (${nextInterval} days from completion)`); | |
| } | |
| problemInfo = { | |
| name: problem.problemName, | |
| number: problem.problemNumber, | |
| reviewNumber: review.reviewNumber, | |
| totalReviews: intervals.length, | |
| completedReviews: problem.reviewsCompleted.length, | |
| nextReviewScheduled: nextReviewNumber <= intervals.length, | |
| nextReviewDate: nextReviewNumber <= intervals.length | |
| ? new Date(new Date(review.completedAt).getTime() + intervals[nextReviewNumber - 1] * 24 * 60 * 60 * 1000).toISOString().split('T')[0] | |
| : null | |
| }; | |
| } | |
| }); | |
| }); | |
| if (found) { | |
| schedule.lastUpdated = new Date().toISOString(); | |
| fs.writeFileSync(schedulePath, JSON.stringify(schedule, null, 2)); | |
| console.log('✅ Review schedule updated'); | |
| // Save info for comment | |
| fs.writeFileSync('review-info.json', JSON.stringify(problemInfo, null, 2)); | |
| fs.writeFileSync(process.env.GITHUB_OUTPUT, 'found=true\n', { flag: 'a' }); | |
| } else { | |
| console.log('⚠️ Review not found in schedule'); | |
| fs.writeFileSync(process.env.GITHUB_OUTPUT, 'found=false\n', { flag: 'a' }); | |
| } | |
| EOF | |
| - name: Commit updated schedule | |
| if: steps.mark-complete.outputs.found == 'true' | |
| run: | | |
| git config --local user.email "[email protected]" | |
| git config --local user.name "GitHub Action" | |
| if [ -n "$(git status --porcelain docs/reviews/)" ]; then | |
| git add docs/reviews/review-schedule.json | |
| git commit -m "✅ Mark review complete: Issue #${{ github.event.issue.number }} | |
| Review completed at: $(date -u +"%Y-%m-%d %H:%M:%S UTC") | |
| [skip ci]" | |
| git push origin main | |
| echo "✅ Review completion recorded" | |
| fi | |
| - name: Comment on issue | |
| if: steps.mark-complete.outputs.found == 'true' | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| const reviewInfo = JSON.parse(fs.readFileSync('review-info.json', 'utf8')); | |
| // Calculate progress | |
| const progress = reviewInfo.totalReviews === 0 | |
| ? 0 | |
| : Math.round((reviewInfo.completedReviews / reviewInfo.totalReviews) * 100); | |
| const remaining = reviewInfo.totalReviews - reviewInfo.completedReviews; | |
| // Create progress bar | |
| const filled = Math.floor(progress / 10); | |
| const empty = 10 - filled; | |
| const progressBar = '█'.repeat(filled) + '░'.repeat(empty); | |
| const comment = `## ✅ Review Completed! | |
| Great work! You've completed review **${reviewInfo.reviewNumber}** of **${reviewInfo.totalReviews}** for **#${reviewInfo.number} - ${reviewInfo.name}**. | |
| ### 📊 Progress | |
| ${progressBar} **${progress}%** | |
| - ✅ Completed: ${reviewInfo.completedReviews}/${reviewInfo.totalReviews} reviews | |
| - 📅 Remaining: ${remaining} review(s) | |
| ${reviewInfo.nextReviewScheduled ? `### 🔜 Next Review Scheduled | |
| Your next review (**Review ${reviewInfo.reviewNumber + 1}**) has been automatically scheduled for **${reviewInfo.nextReviewDate}**. | |
| The review is spaced based on when you completed *this* review, ensuring optimal retention intervals even if you're a few days late! 🧠` : `### 🎉 All Reviews Complete! | |
| You've completed all spaced repetition reviews for this problem. The knowledge is now solidly in your long-term memory!`} | |
| ### 🧠 Keep Learning | |
| - Continue solving new problems | |
| - Watch for review notifications | |
| - The more you practice with spaced repetition, the stronger your retention! | |
| --- | |
| _Review completion recorded in \`docs/reviews/review-schedule.json\`_`; | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: ${{ github.event.issue.number }}, | |
| body: comment | |
| }); | |
| console.log('✅ Posted completion comment'); |