Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .agents/skills/triage/comment.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ Generate a GitHub issue comment from triage findings.
These variables are referenced throughout this skill. They may be passed as args by an orchestrator, or inferred from the conversation when run standalone.

- **`triageDir`** — Directory containing the reproduction project (e.g. `triage/issue-123`). If not passed as an arg, infer from previous conversation.
- **`report.md`** — File in `triageDir` that MAY exist. Contains the full context from all previous skills (reproduction, diagnosis, fix).
- **`issueDetails`** - The GitHub API issue details payload. This must be provided explicitly by the user or available from prior conversation context / tool calls. If this data isn't available, you may run `gh issue view ${issue_number}` to load the missing issue details directly from GitHub.
- **`report.md`** — File in `triageDir` that MAY exist. Contains the full context from all previous skills (reproduction, diagnosis, fix). Contains everything that you need to know to generate your comment successfully.
- **`branchName`** — The branch name where a fix was pushed. If not passed as an arg, infer from previous conversation.
- **`priorityLabels`** — An array of `{ name, description }` objects representing the available priority labels for the repository. Used to select a priority in the comment.

Expand Down Expand Up @@ -40,7 +41,7 @@ The **Fix** line in the template has three possible forms. Choose the one that m

The **Priority** line communicates the severity of this issue to maintainers. Its goal is to answer the question: **"How bad is it?"**

Select exactly ONE priority label from the `priorityLabels` arg. Use the label descriptions to guide your decision, combined with the triage report's root cause and impact analysis. Render the chosen label name in bold (without the `- ` prefix), then follow it with 1-2 sentences explaining **why** you chose that priority. Answer: "who is likely to be affected and under what conditions?". If you are unsure, use your best judgment based on the label descriptions and the triage findings.
Select exactly ONE priority label from the `priorityLabels` arg. Use the label descriptions to guide your decision, combined with the triage report's root cause and impact analysis. Render the chosen label name in square brackets, in bold, formatted with the `- ` prefix removed (Example: `**[P2: Has Workaround].**). Then, follow it with 1-2 sentences explaining **why** you chose that priority. Answer: "who is likely to be affected and under what conditions?". If you are unsure, use your best judgment based on the label descriptions and the triage findings.

### Template

Expand Down
4 changes: 2 additions & 2 deletions .agents/skills/triage/reproduce.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ Skip if a repository maintainer has commented that this issue should not be repr

Every bug report should include some sort of reproduction. The reproduction project goes in the `triageDir` directory (e.g. `triage/gh-123`). If no `triageDir` is provided, default to `triage/gh-<issue_number>`.

Set up the reproduction project based on what the issue provides you. Once the reproduction project directory has been completed, run `pnpm install` in the workspace top-level root to connect it to the rest of the monorepo.
Set up the reproduction project based on what the issue provides you. Once the reproduction project directory has been completed, run `pnpm install --no-frozen-lockfile` in the workspace top-level root to connect it to the rest of the monorepo.

### StackBlitz Project URL (`https://stackblitz.com/edit/...`)

Expand Down Expand Up @@ -120,7 +120,7 @@ rm -rf examples/<template>/node_modules
# 3. Copy over the selected template into the triage directory
cp -r examples/<template> <triageDir>
# 4. Re-run install (at the workspace root) to add back missing node_modules dependencies
pnpm install
pnpm install --no-frozen-lockfile
```

Verify that the project was created in the correct place (`cat <triageDir>/package.json`).
Expand Down
54 changes: 33 additions & 21 deletions .flue/workflows/issue-triage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,19 +88,22 @@ async function fetchRepoLabels(flue: Flue): Promise<{

async function selectTriageLabels(
flue: Flue,
{ comment, packageLabels }: { comment: string; packageLabels: RepoLabel[] },
{
comment,
priorityLabels,
packageLabels,
}: { comment: string; priorityLabels: RepoLabel[]; packageLabels: RepoLabel[] },
): Promise<string> {
const priorityLabelNames = priorityLabels.map((l) => l.name);
const packageLabelNames = packageLabels.map((l) => l.name);

const labelResult = await flue.prompt(
`Label the following GitHub issue based on the triage report that was already posted.
The report already contains a **Priority** judgment with a specific priority label. Your job is to:
1. Extract the priority label that was already chosen in the report's Priority section.
2. Select 0-3 package labels based on where the issue lives (or most likely lives) in the monorepo.
Select labels for this issue from the lists below based on the triage report. Select exactly one priority label (the report's **Priority** section is a strong hint) and 0-3 package labels based on where the issue lives in the monorepo and how it manifests.
### Rules
- The priority label has already been decided in the report. Extract it exactly as written.
- Select 0-3 package labels based on the triage report's findings. If you cannot confidently determine the affected package(s), return an empty array for packages.
- Return the exact label names as they appear in the lists below — do not modify them.
### Priority Labels (select exactly one)
${priorityLabels.map((l) => `- "${l.name}": ${l.description || '(no description)'}`).join('\n')}
### Package Labels (select zero or more)
${packageLabels.map((l) => `- "${l.name}": ${l.description || '(no description)'}`).join('\n')}
Expand All @@ -113,18 +116,24 @@ ${comment}
`,
{
result: v.object({
labels: v.pipe(
v.array(v.string()),
v.nonEmpty('Labels array must contain at least the priority label.'),
priority: v.pipe(
v.picklist(priorityLabelNames),
v.description(
'The priority label to apply. Must be one of the exact priority label names listed above.',
),
),
packages: v.pipe(
v.array(v.picklist(packageLabelNames)),
v.description(
'The labels to apply to the issue. Must include the priority label from the comment\'s Priority section, plus any selected package labels (e.g. ["- P2: important", "pkg: react"]).',
'Package labels to apply (0-3). Each must be one of the exact package label names listed above.',
),
),
}),
},
);

return labelResult.labels.map((l) => `--add-label ${JSON.stringify(l)}`).join(' ');
const allLabels = [labelResult.priority, ...labelResult.packages];
return allLabels.map((l) => `--add-label ${JSON.stringify(l)}`).join(' ');
}

async function runTriagePipeline(
Expand Down Expand Up @@ -259,14 +268,16 @@ export default async function triage(flue: Flue) {
// - create a PR from that branch entirely in the GH UI
// - ignore it completely
if (triageResult.fixed) {
// Check if the fix skill left uncommitted changes in packages/
const status = await flue.shell('git status --porcelain');
if (status.stdout.trim()) {
const diff = await flue.shell('git diff main --stat');
if (diff.stdout.trim()) {
await flue.shell(`git checkout -B ${flue.branch}`);
await flue.shell('git add -A');
await flue.shell(
`git commit -m ${JSON.stringify(triageResult.commitMessage ?? 'fix(auto-triage): automated fix')}`,
);
const status = await flue.shell('git status --porcelain');
if (status.stdout.trim()) {
await flue.shell('git add -A');
await flue.shell(
`git commit -m ${JSON.stringify(triageResult.commitMessage ?? 'fix(auto-triage): automated fix')}`,
);
}
const pushResult = await flue.shell(`git push -f origin ${flue.branch}`);
console.info('push result:', pushResult);
isPushed = pushResult.exitCode === 0;
Expand All @@ -281,7 +292,7 @@ export default async function triage(flue: Flue) {

const branchName = isPushed ? flue.branch : null;
const comment = await flue.skill('triage/comment.md', {
args: { branchName, priorityLabels },
args: { branchName, priorityLabels, issueDetails },
result: v.pipe(
v.string(),
v.description(
Expand All @@ -302,6 +313,7 @@ export default async function triage(flue: Flue) {

const labelFlags = await selectTriageLabels(flue, {
comment,
priorityLabels,
packageLabels,
});
if (labelFlags) {
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@
"@biomejs/biome": "2.3.6",
"@changesets/changelog-github": "^0.5.2",
"@changesets/cli": "^2.29.8",
"@flue/cli": "^0.0.31",
"@flue/client": "^0.0.17",
"@flue/cli": "^0.0.32",
"@flue/client": "^0.0.18",
"@types/node": "^18.19.115",
"esbuild": "0.25.5",
"eslint": "^9.39.2",
Expand Down
22 changes: 11 additions & 11 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading