Skip to content

Active Recall Session: Agents — Planning vs execution separation #92

Active Recall Session: Agents — Planning vs execution separation

Active Recall Session: Agents — Planning vs execution separation #92

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');