From 906cd3d2642bcff5b18be705162855662383353c Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 27 Feb 2025 17:18:03 +0000 Subject: [PATCH 1/7] synchronize titles on issues --- crates/rust-project-goals-cli/src/rfc.rs | 19 ++++++++++++++- crates/rust-project-goals/src/gh/issues.rs | 27 ++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/crates/rust-project-goals-cli/src/rfc.rs b/crates/rust-project-goals-cli/src/rfc.rs index d2a23549..b562c962 100644 --- a/crates/rust-project-goals-cli/src/rfc.rs +++ b/crates/rust-project-goals-cli/src/rfc.rs @@ -13,7 +13,7 @@ use rust_project_goals::{ gh::{ issue_id::{IssueId, Repository}, issues::{ - change_milestone, create_comment, create_issue, fetch_issue, list_issues_in_milestone, lock_issue, sync_assignees, update_issue_body, FLAGSHIP_LABEL, LOCK_TEXT + change_milestone, change_title, create_comment, create_issue, fetch_issue, list_issues_in_milestone, lock_issue, sync_assignees, update_issue_body, FLAGSHIP_LABEL, LOCK_TEXT }, labels::GhLabel, }, @@ -199,6 +199,11 @@ enum GithubAction<'doc> { issue: GithubIssue<'doc>, }, + ChangeTitle { + number: u64, + title: String, + }, + ChangeMilestone { number: u64, milestone: String, @@ -333,6 +338,10 @@ fn initialize_issues<'doc>( .collect(), }); } + + if existing_issue.title != desired_issue.title { + actions.insert(GithubAction::ChangeTitle { number: existing_issue.number, title: desired_issue.title }); + } if existing_issue.milestone.as_ref().map(|m| m.title.as_str()) != Some(timeframe) { actions.insert(GithubAction::ChangeMilestone { @@ -525,6 +534,9 @@ impl Display for GithubAction<'_> { GithubAction::ChangeMilestone { number, milestone } => { write!(f, "update issue #{} milestone to \"{}\"", number, milestone) } + GithubAction::ChangeTitle { number, title } => { + write!(f, "update issue #{} title to \"{}\"", number, title) + } GithubAction::Comment { number, body } => { write!(f, "post comment on issue #{}: \"{}\"", number, body) } @@ -596,6 +608,11 @@ impl GithubAction<'_> { Ok(()) } + GithubAction::ChangeTitle { number, title } => { + change_title(repository, number, &title)?; + Ok(()) + } + GithubAction::Comment { number, body } => { create_comment(repository, number, &body)?; Ok(()) diff --git a/crates/rust-project-goals/src/gh/issues.rs b/crates/rust-project-goals/src/gh/issues.rs index eaf3bf2f..446b0e22 100644 --- a/crates/rust-project-goals/src/gh/issues.rs +++ b/crates/rust-project-goals/src/gh/issues.rs @@ -197,6 +197,33 @@ pub fn create_issue( } } +pub fn change_title( + repository: &Repository, + number: u64, + title: &str, +) -> anyhow::Result<()> { + let mut command = Command::new("gh"); + command + .arg("-R") + .arg(&repository.to_string()) + .arg("issue") + .arg("edit") + .arg(number.to_string()) + .arg("-t") + .arg(title); + + let output = command.output()?; + if !output.status.success() { + Err(anyhow::anyhow!( + "failed to change milestone `{}`: {}", + number, + String::from_utf8_lossy(&output.stderr) + )) + } else { + Ok(()) + } +} + pub fn change_milestone( repository: &Repository, number: u64, From e6da1f1df537ef362be5216e629cad3a09dbff62 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 27 Feb 2025 17:30:20 +0000 Subject: [PATCH 2/7] don't use LLM, just link to comments --- crates/rust-project-goals-cli-llm/src/main.rs | 6 - .../src/templates.rs | 3 +- .../rust-project-goals-cli-llm/src/updates.rs | 107 +++--------------- crates/rust-project-goals-cli/src/rfc.rs | 6 +- crates/rust-project-goals-llm/src/lib.rs | 12 -- crates/rust-project-goals/src/gh/issues.rs | 5 +- templates/updates.hbs | 12 +- 7 files changed, 26 insertions(+), 125 deletions(-) diff --git a/crates/rust-project-goals-cli-llm/src/main.rs b/crates/rust-project-goals-cli-llm/src/main.rs index 25829c7a..6075f78b 100644 --- a/crates/rust-project-goals-cli-llm/src/main.rs +++ b/crates/rust-project-goals-cli-llm/src/main.rs @@ -24,13 +24,10 @@ async fn main() -> anyhow::Result<()> { } = Opt::parse(); let UpdateArgs { milestone, - quick, vscode, output_file, start_date, end_date, - model_id, - region, } = &serde_json::from_str(&updates_json)?; updates::updates( &repository, @@ -38,10 +35,7 @@ async fn main() -> anyhow::Result<()> { output_file.as_deref(), start_date, end_date, - *quick, *vscode, - model_id.as_deref(), - region.as_deref(), ) .await?; Ok(()) diff --git a/crates/rust-project-goals-cli-llm/src/templates.rs b/crates/rust-project-goals-cli-llm/src/templates.rs index 12d44e3c..e98ad00d 100644 --- a/crates/rust-project-goals-cli-llm/src/templates.rs +++ b/crates/rust-project-goals-cli-llm/src/templates.rs @@ -44,8 +44,7 @@ handlebars::handlebars_helper!(is_complete: |p: Progress| match p { pub struct Updates { pub milestone: String, pub flagship_goals: Vec, - pub other_goals_with_updates: Vec, - pub other_goals_without_updates: Vec, + pub other_goals: Vec, } impl Updates { diff --git a/crates/rust-project-goals-cli-llm/src/updates.rs b/crates/rust-project-goals-cli-llm/src/updates.rs index 60cfcfcd..3836f799 100644 --- a/crates/rust-project-goals-cli-llm/src/updates.rs +++ b/crates/rust-project-goals-cli-llm/src/updates.rs @@ -6,7 +6,6 @@ use std::io::Write; use std::path::Path; use std::process::{Command, Stdio}; -use crate::llm::LargeLanguageModel; use crate::templates::{self, Updates, UpdatesGoal}; use rust_project_goals::gh::issues::ExistingGithubIssue; use rust_project_goals::gh::{ @@ -14,42 +13,18 @@ use rust_project_goals::gh::{ issues::{checkboxes, list_issues_in_milestone, ExistingGithubComment}, }; -const QUICK_UPDATES: &[&str] = &[ - "Jack and Jill went up the hill", - "To fetch a pail of water", - "Jack fell down and broke his crown", - "And Jill came tumbling after.", - "Up Jack got and home did trot,", - "As fast as he could caper;", - "Went to bed to mend his head", - "With vinegar and brown paper.", - "Jill came in and she did grin", - "To see his paper plaster;", - "Mother, vex’d, did whip her next", - "For causing Jack's disaster.", -]; - -fn comments_forever() -> impl Iterator { - QUICK_UPDATES.iter().copied().cycle() -} - pub async fn updates( repository: &Repository, milestone: &str, output_file: Option<&Path>, start_date: &Option, end_date: &Option, - quick: bool, vscode: bool, - model_id: Option<&str>, - region: Option<&str>, ) -> anyhow::Result<()> { if output_file.is_none() && !vscode { anyhow::bail!("either `--output-file` or `--vscode` must be specified"); } - let llm = LargeLanguageModel::new(model_id, region).await?; - let issues = list_issues_in_milestone(repository, milestone)?; let filter = Filter { @@ -70,12 +45,11 @@ pub async fn updates( let mut updates = templates::Updates { milestone: milestone.to_string(), flagship_goals: vec![], - other_goals_with_updates: vec![], - other_goals_without_updates: vec![], + other_goals: vec![], }; - prepare_flagship_goals(repository, &issues, &filter, &llm, quick, &mut updates).await?; - prepare_other_goals(repository, &issues, &filter, &llm, quick, &mut updates).await?; + prepare_flagship_goals(repository, &issues, &filter, &mut updates).await?; + prepare_other_goals(repository, &issues, &filter, &mut updates).await?; progress_bar::finalize_progress_bar(); @@ -112,8 +86,6 @@ async fn prepare_flagship_goals( repository: &Repository, issues: &[ExistingGithubIssue], filter: &Filter<'_>, - llm: &LargeLanguageModel, - quick: bool, updates: &mut Updates, ) -> anyhow::Result<()> { // First process the flagship goals, for which we capture the full text of comments. @@ -135,32 +107,13 @@ async fn prepare_flagship_goals( let mut comments = issue.comments.clone(); comments.sort_by_key(|c| c.created_at.clone()); - comments.retain(|c| filter.matches(c)); + comments.retain(|c| !c.is_automated_comment() && filter.matches(c)); - let summary: String = if comments.len() == 0 { - format!("No updates in this period.") - } else if quick { - QUICK_UPDATES.iter().copied().collect() - } else { - let prompt = format!( - "The following comments are updates to a project goal entitled '{title}'. \ - The goal is assigned to {people} ({assignees}). \ - Summarize the major developments, writing for general Rust users. \ - Write the update in the third person and do not use pronouns when referring to people. \ - Do not respond with anything but the summary paragraphs. \ - ", - people = if issue.assignees.len() == 1 { - "1 person".to_string() - } else { - format!("{} people", issue.assignees.len()) - }, - assignees = comma(&issue.assignees), - ); - let updates: String = comments.iter().map(|c| format!("\n{}\n", c.body)).collect(); - llm.query(&prompt, &updates) - .await - .with_context(|| format!("making request to LLM failed"))? - }; + let mut summary = String::new(); + for c in comments { + summary.push_str(&c.body); + summary.push_str("\n\n"); + } updates.flagship_goals.push(UpdatesGoal { title: title.clone(), @@ -185,12 +138,9 @@ async fn prepare_other_goals( repository: &Repository, issues: &[ExistingGithubIssue], filter: &Filter<'_>, - llm: &LargeLanguageModel, - quick: bool, updates: &mut Updates, ) -> anyhow::Result<()> { // Next process the remaining goals, for which we generate a summary using an LLVM. - let mut quick_comments = comments_forever(); for issue in issues { if issue.has_flagship_label() { continue; @@ -208,36 +158,17 @@ async fn prepare_other_goals( // Find the relevant updates that have occurred. let mut comments = issue.comments.clone(); comments.sort_by_key(|c| c.created_at.clone()); - comments.retain(|c| filter.matches(c)); + comments.retain(|c| !c.is_automated_comment() && filter.matches(c)); // Use an LLM to summarize the updates. let summary = if comments.len() == 0 { - format!("* No updates in this period.") - } else if quick { - let num_comments = std::cmp::min(comments.len(), 3); - quick_comments - .by_ref() - .take(num_comments) - .map(|c| format!("* {c}\n")) - .collect() + format!("No updates in this period.") } else { - let prompt = format!( - "The following comments are updates to a project goal entitled '{title}'. \ - The goal is assigned to {people} ({assignees}). \ - Summarize the updates with a list of one or two bullet points, each one sentence. \ - Write the update in the third person and do not use pronouns when referring to people. \ - Format the bullet points as markdown with each bullet point beginning with `* `. \ - Do not respond with anything but the bullet points. \ - ", - people = if issue.assignees.len() == 1 { - "1 person".to_string() - } else { - format!("{} people", issue.assignees.len()) - }, - assignees = comma(&issue.assignees), - ); - let updates: String = comments.iter().map(|c| format!("\n{}\n", c.body)).collect(); - llm.query(&prompt, &updates).await? + format!( + "[{N} updates available.]({LINK})", + N = comments.len(), + LINK = comments.first().unwrap().url, + ) }; let goal = UpdatesGoal { @@ -254,11 +185,7 @@ async fn prepare_other_goals( progress: checkboxes(&issue), }; - if comments.len() > 0 { - updates.other_goals_with_updates.push(goal); - } else { - updates.other_goals_without_updates.push(goal); - } + updates.other_goals.push(goal); progress_bar::inc_progress_bar(); } diff --git a/crates/rust-project-goals-cli/src/rfc.rs b/crates/rust-project-goals-cli/src/rfc.rs index b562c962..fa303e82 100644 --- a/crates/rust-project-goals-cli/src/rfc.rs +++ b/crates/rust-project-goals-cli/src/rfc.rs @@ -13,7 +13,7 @@ use rust_project_goals::{ gh::{ issue_id::{IssueId, Repository}, issues::{ - change_milestone, change_title, create_comment, create_issue, fetch_issue, list_issues_in_milestone, lock_issue, sync_assignees, update_issue_body, FLAGSHIP_LABEL, LOCK_TEXT + change_milestone, change_title, create_comment, create_issue, fetch_issue, list_issues_in_milestone, lock_issue, sync_assignees, update_issue_body, CONTINUING_GOAL_PREFIX, FLAGSHIP_LABEL, LOCK_TEXT }, labels::GhLabel, }, @@ -351,9 +351,7 @@ fn initialize_issues<'doc>( actions.insert(GithubAction::Comment { number: existing_issue.number, body: format!( - "This is a continuing project goal, and the updates below \ - this comment will be for the new period {}", - timeframe + "{CONTINUING_GOAL_PREFIX} {timeframe}", ), }); } diff --git a/crates/rust-project-goals-llm/src/lib.rs b/crates/rust-project-goals-llm/src/lib.rs index 58666b03..4060dc8d 100644 --- a/crates/rust-project-goals-llm/src/lib.rs +++ b/crates/rust-project-goals-llm/src/lib.rs @@ -11,10 +11,6 @@ pub struct UpdateArgs { /// Milestone for which we generate tracking issue data (e.g., `2024h2`). pub milestone: String, - /// Quick mode does not use an LLM to generate a summary. - #[arg(long)] - pub quick: bool, - /// Quick mode does not use an LLM to generate a summary. #[arg(long)] pub vscode: bool, @@ -30,12 +26,4 @@ pub struct UpdateArgs { /// End date for comments. /// If not given, no end date. pub end_date: Option, - - /// Set a custom model id for the LLM. - #[arg(long)] - pub model_id: Option, - - /// Set a custom region. - #[arg(long)] - pub region: Option, } diff --git a/crates/rust-project-goals/src/gh/issues.rs b/crates/rust-project-goals/src/gh/issues.rs index 446b0e22..d96f5068 100644 --- a/crates/rust-project-goals/src/gh/issues.rs +++ b/crates/rust-project-goals/src/gh/issues.rs @@ -333,6 +333,8 @@ pub const FLAGSHIP_LABEL: &str = "Flagship Goal"; pub const LOCK_TEXT: &str = "This issue is intended for status updates only.\n\nFor general questions or comments, please contact the owner(s) directly."; +pub const CONTINUING_GOAL_PREFIX: &str = "This is a continuing project goal, and the updates below this comment will be for the new period"; + impl ExistingGithubIssue { /// We use the presence of a "lock comment" as a signal that we successfully locked the issue. /// The github CLI doesn't let you query that directly. @@ -376,7 +378,8 @@ pub fn lock_issue(repository: &Repository, number: u64) -> anyhow::Result<()> { impl ExistingGithubComment { /// True if this is one of the special comments that we put on issues. pub fn is_automated_comment(&self) -> bool { - self.body.trim() == LOCK_TEXT + let trimmed_body = self.body.trim(); + trimmed_body == LOCK_TEXT || trimmed_body.starts_with(CONTINUING_GOAL_PREFIX) } pub fn created_at_date(&self) -> NaiveDate { diff --git a/templates/updates.hbs b/templates/updates.hbs index 8e0d036f..4c5075b7 100644 --- a/templates/updates.hbs +++ b/templates/updates.hbs @@ -18,9 +18,9 @@ repository](https://github.com/rust-lang/rust-project-goals/milestone/2). {{/each}} -## Goals with updates +## Other goals -{{#each other_goals_with_updates}} +{{#each other_goals}} {{>introduce_goal}} {{!-- some spacing is required to ensure that markdown is recognized as markdown and not html --}} @@ -30,11 +30,3 @@ repository](https://github.com/rust-lang/rust-project-goals/milestone/2). {{!-- some spacing is required to ensure that markdown is recognized as markdown and not html --}} {{/each}} - -## Goals without updates - -The following goals have not received updates in the last month: - -{{#each other_goals_without_updates}} -{{>introduce_goal}} -{{/each}} \ No newline at end of file From f92b0c757b165e1dbbe959715b162d873031cda0 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 27 Feb 2025 17:43:55 +0000 Subject: [PATCH 3/7] include goal comment text --- .../src/templates.rs | 6 +- .../rust-project-goals-cli-llm/src/updates.rs | 87 +++---------------- templates/goal_comments.hbs | 17 ++++ templates/updates.hbs | 16 +--- 4 files changed, 35 insertions(+), 91 deletions(-) create mode 100644 templates/goal_comments.hbs diff --git a/crates/rust-project-goals-cli-llm/src/templates.rs b/crates/rust-project-goals-cli-llm/src/templates.rs index e98ad00d..72b21f56 100644 --- a/crates/rust-project-goals-cli-llm/src/templates.rs +++ b/crates/rust-project-goals-cli-llm/src/templates.rs @@ -1,6 +1,7 @@ use std::path::{Path, PathBuf}; use handlebars::{DirectorySourceOptions, Handlebars}; +use rust_project_goals::gh::issues::ExistingGithubComment; use serde::Serialize; use rust_project_goals_json::Progress; @@ -73,7 +74,10 @@ pub struct UpdatesGoal { pub is_closed: bool, /// Markdown with update text (bullet list) - pub updates_markdown: String, + pub comments: Vec, + + /// Comments.len but accessible to the template + pub num_comments: usize, /// Progress towards the goal pub progress: Progress, diff --git a/crates/rust-project-goals-cli-llm/src/updates.rs b/crates/rust-project-goals-cli-llm/src/updates.rs index 3836f799..4b347adb 100644 --- a/crates/rust-project-goals-cli-llm/src/updates.rs +++ b/crates/rust-project-goals-cli-llm/src/updates.rs @@ -44,13 +44,10 @@ pub async fn updates( let mut updates = templates::Updates { milestone: milestone.to_string(), - flagship_goals: vec![], - other_goals: vec![], + flagship_goals: prepare_goals(repository, &issues, &filter, true).await?, + other_goals: prepare_goals(repository, &issues, &filter, false).await?, }; - prepare_flagship_goals(repository, &issues, &filter, &mut updates).await?; - prepare_other_goals(repository, &issues, &filter, &mut updates).await?; - progress_bar::finalize_progress_bar(); // Render the output using handlebars and write it to the file. @@ -82,15 +79,16 @@ pub async fn updates( Ok(()) } -async fn prepare_flagship_goals( +async fn prepare_goals( repository: &Repository, issues: &[ExistingGithubIssue], filter: &Filter<'_>, - updates: &mut Updates, -) -> anyhow::Result<()> { + flagship: bool, +) -> anyhow::Result> { + let mut result = vec![]; // First process the flagship goals, for which we capture the full text of comments. for issue in issues { - if !issue.has_flagship_label() { + if flagship != issue.has_flagship_label() { continue; } @@ -109,13 +107,7 @@ async fn prepare_flagship_goals( comments.sort_by_key(|c| c.created_at.clone()); comments.retain(|c| !c.is_automated_comment() && filter.matches(c)); - let mut summary = String::new(); - for c in comments { - summary.push_str(&c.body); - summary.push_str("\n\n"); - } - - updates.flagship_goals.push(UpdatesGoal { + result.push(UpdatesGoal { title: title.clone(), issue_number: issue.number, issue_assignees: comma(&issue.assignees), @@ -126,70 +118,13 @@ async fn prepare_flagship_goals( .url(), progress, is_closed: issue.state == GithubIssueState::Closed, - updates_markdown: summary, + num_comments: comments.len(), + comments, }); progress_bar::inc_progress_bar(); } - Ok(()) -} - -async fn prepare_other_goals( - repository: &Repository, - issues: &[ExistingGithubIssue], - filter: &Filter<'_>, - updates: &mut Updates, -) -> anyhow::Result<()> { - // Next process the remaining goals, for which we generate a summary using an LLVM. - for issue in issues { - if issue.has_flagship_label() { - continue; - } - - let title = &issue.title; - - progress_bar::print_progress_bar_info( - &format!("Issue #{number}", number = issue.number), - title, - progress_bar::Color::Green, - progress_bar::Style::Bold, - ); - - // Find the relevant updates that have occurred. - let mut comments = issue.comments.clone(); - comments.sort_by_key(|c| c.created_at.clone()); - comments.retain(|c| !c.is_automated_comment() && filter.matches(c)); - - // Use an LLM to summarize the updates. - let summary = if comments.len() == 0 { - format!("No updates in this period.") - } else { - format!( - "[{N} updates available.]({LINK})", - N = comments.len(), - LINK = comments.first().unwrap().url, - ) - }; - - let goal = UpdatesGoal { - title: title.clone(), - issue_number: issue.number, - issue_assignees: comma(&issue.assignees), - issue_url: IssueId { - repository: repository.clone(), - number: issue.number, - } - .url(), - is_closed: issue.state == GithubIssueState::Closed, - updates_markdown: summary, - progress: checkboxes(&issue), - }; - - updates.other_goals.push(goal); - - progress_bar::inc_progress_bar(); - } - Ok(()) + Ok(result) } struct Filter<'f> { diff --git a/templates/goal_comments.hbs b/templates/goal_comments.hbs new file mode 100644 index 00000000..6a7f25b1 --- /dev/null +++ b/templates/goal_comments.hbs @@ -0,0 +1,17 @@ +{{#if comments}} + +
+{{num_comments}} updates posted. + +{{#each comments}} +{{body}} +{{/each}} +
+ +{{else}} + + +No updates in this tracking period. + +{{/if}} + diff --git a/templates/updates.hbs b/templates/updates.hbs index 4c5075b7..8915e53d 100644 --- a/templates/updates.hbs +++ b/templates/updates.hbs @@ -9,24 +9,12 @@ repository](https://github.com/rust-lang/rust-project-goals/milestone/2). {{#each flagship_goals}} {{>introduce_goal}} - -{{!-- some spacing is required to ensure that markdown is recognized as markdown and not html --}} - -{{{updates_markdown}}} - -{{!-- some spacing is required to ensure that markdown is recognized as markdown and not html --}} - +{{>goal_comments}} {{/each}} ## Other goals {{#each other_goals}} {{>introduce_goal}} - -{{!-- some spacing is required to ensure that markdown is recognized as markdown and not html --}} - -{{{updates_markdown}}} - -{{!-- some spacing is required to ensure that markdown is recognized as markdown and not html --}} - +{{>goal_comments}} {{/each}} From 3d732e282f206317e108d75b1ce864c142b44dc5 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 27 Feb 2025 18:10:08 +0000 Subject: [PATCH 4/7] updated "why this goal" text from blog post --- src/2025h1/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/2025h1/README.md b/src/2025h1/README.md index 2e0d50b6..1a8dfb3c 100644 --- a/src/2025h1/README.md +++ b/src/2025h1/README.md @@ -72,9 +72,9 @@ The flagship goals proposed for this roadmap are as follows: #### Why these particular flagship goals? -[**Async.**](./async.md) Rust is a great fit for server development thanks to its ability to scale to very high load while retaining low memory usage and tight tail latency. 52% of the respondents in the [2023 Rust survey](https://blog.rust-lang.org/2024/02/19/2023-Rust-Annual-Survey-2023-results.html) indicated that they use Rust to build server-side or backend applications. In [2025H1 our plan](./async.md) is to deliver (a) improved support for async-fn-in-traits, completely subsuming the functionality of the [`async-trait` crate](https://crates.io/crates/async-trait); (b) progress towards sync and async generators, simplifying the creation of iterators and async data streams; (c) and improve the ergonomics of `Pin`, making lower-level async coding more approachable. These items together start to unblock the creation of the next generation of async libraries in the wider ecosystem, as progress there has been blocked on a stable solution for async traits and streams. +[**Async.**](./async.md) This work continues our drive to improve support for async programming in Rust. In 2024H2 we stabilized async closures; explored the generator design space; and began work on the `dynosaur` crate, an experimental proc-macro to provide dynamic dispatch for async functions in traits. In 2025H1 [our plan](./async.md) is to deliver (1) improved support for async-fn-in-traits, completely subsuming the functionality of the [`async-trait` crate](https://crates.io/crates/async-trait); (2) progress towards sync and async generators, simplifying the creation of iterators and async data streams; (3) and improve the ergonomics of `Pin`, making lower-level async coding more approachable. These items together start to unblock the creation of the next generation of async libraries in the wider ecosystem, as progress there has been blocked on a stable solution for async traits and streams. -[**Rust for Linux.**](./rfl.md) The [experimental support for Rust development in the Linux kernel][RFL.com] is a watershed moment for Rust, demonstrating to the world that Rust is indeed a true alternative to C. Currently the Linux kernel support depends on a wide variety of unstable features in Rust; these same features block other embedded and low-level systems applications. We are working to stabilize all of these features so that RFL can be built on a stable toolchain. As we have successfully stabilized the majority of the language features used by RFL, we plan in 2025H1 to turn our focus to compiler flags and tooling options. We will (a) implement [RFC #3716] which lays out a design for ABI-modifying flags; (b) take the first step towards stabilizing [`build-std`](https://doc.rust-lang.org/cargo/reference/unstable.html#build-std) by [creating a stable way to rebuild core with specific compiler options](./build-std.md); (c) extending rustdoc, clippy, and the compiler with features that extract metadata for integration into other build systems (in this case, the kernel's build system). +[**Rust for Linux.**](./rfl.md) This goal continues our work from 2024H2 in supporting the [experimental support for Rust development in the Linux kernel][RFL.com]. Whereas in 2024H2 we were focused on stabilizing required language features, our focus in 2025H1 is stabilizing compiler flags and tooling options. We will (1) implement [RFC #3716] which lays out a design for ABI-modifying flags; (2) take the first step towards stabilizing [`build-std`](https://doc.rust-lang.org/cargo/reference/unstable.html#build-std) by [creating a stable way to rebuild core with specific compiler options](./build-std.md); (3) extending rustdoc, clippy, and the compiler with features that extract metadata for integration into other build systems (in this case, the kernel's build system). [**Rust All Hands 2025.**](./all-hands.md) May 15, 2025 marks the 10-year anniversary of Rust's 1.0 release; it also marks 10 years since the [creation of the Rust subteams](https://internals.rust-lang.org/t/announcing-the-subteams/2042). At the time [there were 6 Rust teams with 24 people in total](http://web.archive.org/web/20150517235608/http://www.rust-lang.org/team.html). There are now 57 teams with 166 people. In-person All Hands meetings are an effective way to help these maintainers get to know one another with high-bandwidth discussions. This year, the Rust project will be coming together for [RustWeek 2025](https://2025.rustweek.org), a joint event organized with [RustNL](https://2025.rustweek.org/about/). Participating project teams will use the time to share knowledge, make plans, or just get to know one another better. One particular goal for the All Hands is reviewing a draft of the [Rust Vision Doc](./rust-vision-doc.md), a document that aims to take stock of where Rust is and lay out high-level goals for the next few years. From 5b9e2c0ef8a44e2e0a925098756fbcbe1899df50 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 27 Feb 2025 19:55:13 +0000 Subject: [PATCH 5/7] improve output of comments --- templates/goal_comments.hbs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/templates/goal_comments.hbs b/templates/goal_comments.hbs index 6a7f25b1..4588fbff 100644 --- a/templates/goal_comments.hbs +++ b/templates/goal_comments.hbs @@ -3,14 +3,31 @@
{{num_comments}} updates posted. + + {{#each comments}} -{{body}} + + + +Comment by {{author}} posted on {{created_at}}:

+ +
+ + + +{{{body}}} + + + +
+ {{/each}}
{{else}} - + + No updates in this tracking period. {{/if}} From 78f8267a0a5d8bde9c4efea866b95d8e776c366d Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 27 Feb 2025 19:56:22 +0000 Subject: [PATCH 6/7] pluralize --- templates/goal_comments.hbs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/templates/goal_comments.hbs b/templates/goal_comments.hbs index 4588fbff..3b91e60c 100644 --- a/templates/goal_comments.hbs +++ b/templates/goal_comments.hbs @@ -1,7 +1,7 @@ {{#if comments}}
-{{num_comments}} updates posted. +{{num_comments}} update(s) posted. @@ -28,7 +28,9 @@ -No updates in this tracking period. +
+No updates posted. +
{{/if}} From a057d77b7a46d0e2dfdd426b02589ddf45e976cc Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 27 Feb 2025 17:20:10 -0500 Subject: [PATCH 7/7] Update crates/rust-project-goals-cli-llm/src/updates.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Rémy Rakic --- crates/rust-project-goals-cli-llm/src/updates.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/rust-project-goals-cli-llm/src/updates.rs b/crates/rust-project-goals-cli-llm/src/updates.rs index 4b347adb..df883ef8 100644 --- a/crates/rust-project-goals-cli-llm/src/updates.rs +++ b/crates/rust-project-goals-cli-llm/src/updates.rs @@ -86,7 +86,7 @@ async fn prepare_goals( flagship: bool, ) -> anyhow::Result> { let mut result = vec![]; - // First process the flagship goals, for which we capture the full text of comments. + // We process flagship and regular goals in two passes, and capture comments differently for flagship goals. for issue in issues { if flagship != issue.has_flagship_label() { continue;