Skip to content

feat: add quarterly audit CLI, grace period automation, workflows, and agent skill - #7

Open
Piinks wants to merge 3 commits into
flutter:mainfrom
Piinks:launch-4
Open

Piinks wants to merge 3 commits into
flutter:mainfrom
Piinks:launch-4

Conversation

@Piinks

@Piinks Piinks commented Oct 16, 2026

Copy link
Copy Markdown
Collaborator

Based off of #6 - should be reviewed first

Part 3 of 4

Full Picture: #3

Towards flutter/flutter#186415
RFC: flutter/rfc#36

Adds the automated quarterly review audit pipeline, 30-day grace period tracker, and supporting CLI/agent tooling:

  • Adds tool/quarterly_audit.dart and .github/workflows/quarterly_review.yml to run quarterly community and partner team audits, generate reports, open tracking issues, and finalize roster updates (--finalize).
  • Adds tool/check_grace_period.dart and .github/workflows/check_grace_period.yml to post weekly countdown updates during the 30-day review window and notify the assignee when the grace period concludes.
  • Adds tool/check_user.dart for single-user qualification checks, comprehensive unit tests in test/quarterly_audit_test.dart, and the quarterly-ladder-analysis agent skill.

Pre-launch Checklist

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I read the Tree Hygiene wiki page, which explains my responsibilities.
  • I read the Flutter Style Guide recently, and have followed its advice.
  • I signed the CLA.
  • I listed at least one issue that this PR fixes in the description above.
  • I updated/added relevant documentation (doc comments with ///).
  • I added new tests to check the change I am making, or this PR is test-exempt.
  • All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel on Discord.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... I feel like I've seen this before... stacked prs == good

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We chatted about this on Friday - you told me not to go stacked! 🤣

Based off of #6 - should be reviewed first

@@ -0,0 +1,288 @@
import 'dart:io';

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

channeling my inner zach: copyright headers

Comment on lines +152 to +162
buffer.writeln('## Weekly review period status update');
buffer.writeln();
buffer.writeln(
'**$title** is currently in the 30-day review and grace period:');
buffer.writeln('- **Elapsed:** $daysElapsed day(s) (opened $createdDate)');
buffer.writeln(
'- **Remaining:** $daysRemaining day(s) until the 30-day review window concludes on **$targetEndDate**');
buffer.writeln();
buffer.writeln(
'If you were tagged above and have not yet replied, please comment on this thread before **$targetEndDate** to accept your invitation, share your Discord username for team member role provisioning, or share qualitative contributions (issue triage, reproductions, [RFCs](https://github.com/flutter/rfc), design docs, or mentoring).');
return buffer.toString();

@jtmcdole jtmcdole Oct 19, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return '''
## Weekly review period status update

**$title** is currently in the 30-day review and grace period:
- **Elapsed:** $daysElapsed day(s) (opened $createdDate)
- **Remaining:** $daysRemaining day(s) until the 30-day review window concludes on **$targetEndDate**

If you were tagged above and have not yet replied, please comment on this thread before **$targetEndDate** to accept your invitation, share your Discord username for team member role provisioning, or share qualitative contributions (issue triage, reproductions, [RFCs](https://github.com/flutter/rfc), design docs, or mentoring).
''';

Comment on lines +178 to +191
buffer.writeln('## 30-day review period concluded');
buffer.writeln();
buffer.writeln(
'cc $mentions — The 30-day review and grace period for **$title** has concluded ($daysElapsed days since opening).');
buffer.writeln();
buffer.writeln('### Next steps:');
buffer.writeln(
'1. Review qualitative contributions, appeals, and Discord usernames shared by new joiners/promoted members in this thread.');
buffer.writeln(
'2. On the open quarterly review PR branch, run `dart run tool/quarterly_audit.dart --finalize --retain ... --exclude ... --discord user=handle` to update `data/contributors.yaml`, [ROSTER.md](ROSTER.md), and [EMERITUS.md](EMERITUS.md), then merge the PR.');
buffer.writeln(
'3. Update GitHub teams (`@flutter/reviewers`, `@flutter/committers`, and `@flutter/maintainers` as child teams of `@flutter/flutter-hackers`, along with `@flutter/partners` child teams), grant the Discord team member role to newly added ladder members, and remove members transitioning to Dasher Emeritus from the GitHub organization.');
buffer.writeln('4. Close this issue once updates land.');
return buffer.toString();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dito on multiline string

}

/// Posts a comment to a GitHub issue.
Future<void> postIssueComment(int issueNumber, String body) async {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we steal ProcessRunner from somewhere so these could be tested?

Comment thread tool/check_user.dart
}
}

({String? role, String? discord}) findUserInfo(YamlMap doc, String username) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could use JsonSerializable to handle parsing the yaml, or a final class rather than juggling YamlMap / YamlList everywhere.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants