Issue forms and needs-info: ask short bug reports for steps to reproduce (#2416)

* Triage bot: needs-info for short bug reports without steps

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01TPWBBSRPfPYWgrrhbznewR

* Issue forms for bugs and feature requests; document needs-info

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01TPWBBSRPfPYWgrrhbznewR

---------

Co-authored-by: jyviko <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
This commit is contained in:
authored and GitHub committed 2026-10-18 05:44:48 -04:00
1 parent 136a3e9a2f
commit 003abc2149
9 files changed
+433 -45

No files matched your search

+41
View File
@@ -0,0 +1,41 @@
name: Bug report
description: Something in SolidCraft does the wrong thing
labels: [bug]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to report this! Inside the app, **Report an Issue** fills most of this in for you, with the command, its settings and your environment.
- type: textarea
id: what
attributes:
label: What happened
description: What did you expect, and what happened instead?
validations:
required: true
- type: textarea
id: steps
attributes:
label: Steps to reproduce
description: |
What you clicked or typed, in order. For a problem on a particular design, `solidcraft-cli script design.solidcraft --out repro.json` turns its history into a script that `solidcraft-cli eval repro.json` replays; attach it, trimmed to the failing step if you can.
placeholder: |
1. Sketch a circle on the XY plane
2. Extrude it 10 mm
3. Fillet the top edge with 6 mm
validations:
required: true
- type: input
id: version
attributes:
label: SolidCraft version and OS
description: Help → About shows the version.
placeholder: 0.15.0, Windows 11
validations:
required: true
- type: textarea
id: media
attributes:
label: Screenshots or recording
description: |
For anything you can see in the app, a screenshot or short recording of a small example helps the most. Please leave out private designs and personal details.
-23
View File
@@ -1,23 +0,0 @@
---
name: Bug report
about: Help reproduce and fix a SolidCraft problem
title: ''
labels: ''
assignees: ''
---
## Behavior
What did you expect, and what happened instead?
## Reproduction
Include steps, SolidCraft version/commit and relevant environment details. Prefer a small example without private design data.
When the problem shows on a particular design, `solidcraft-cli script design.solidcraft --out repro.json` turns its history into a script that `solidcraft-cli eval repro.json` replays; attach it, trimmed to the failing step if you can.
## Screenshots of the behavior (when observable)
For observable CAD, UI or model behavior, include actual descriptive screenshots or a short recording from a small reproduction. This includes kernel, geometry, assembly and backend effects that can be shown in the app. Coding agents should run the app and capture the evidence themselves, rather than asking a human for evidence they can produce. Show the actual failure/result, preferably before and after, with brief steps, expected/actual behavior and annotations where helpful.
Flowcharts and Mermaid diagrams cannot substitute for evidence of visible behavior. Use diagrams for architectural reasoning when actual screenshots cannot illustrate the point. Changes with no useful observable behavior may omit screenshot/video evidence. Exclude private designs and sensitive details; attach media or link to an accessible recording rather than committing generated review artifacts.
+2
View File
@@ -1,3 +1,5 @@
# Blank issues stay on: the app's Report an Issue opens issues/new?title=…&body=… with the report
# filled in (crates/ui-egui/src/issue_report.rs), which GitHub drops when blank issues are off.
blank_issues_enabled: true
contact_links:
- name: Questions and chat
+16
View File
@@ -0,0 +1,16 @@
name: Feature request
description: Something SolidCraft should do
labels: [enhancement]
body:
- type: textarea
id: goal
attributes:
label: What are you trying to do
description: The part or workflow you have in mind, and where SolidCraft gets in the way today.
validations:
required: true
- type: textarea
id: idea
attributes:
label: How you imagine it working
description: Optional. Describe the behaviour in your own words; please don't paste another product's documentation.
+27 -10
View File
@@ -1,17 +1,19 @@
# Labels new issues and PRs from fixed rules, `/triage` for maintainers, and a manual backfill
# over everything still unlabelled (CONTRIBUTING.md, "Labels and triage"). The logic is in
# scripts/triage/triage.js (tested in ci.yml).
# Labels new issues and PRs from fixed rules, `/triage` for maintainers, asks short bug reports
# for reproduction steps (`needs-info`, closed after 14 days unanswered), and a manual backfill
# (CONTRIBUTING.md, "Labels and triage"). The logic is in scripts/triage/ (tested in ci.yml).
name: Triage
on:
issues:
types: [opened, labeled]
types: [opened, labeled, edited]
issue_comment:
types: [created]
# pull_request_target so PRs from forks can be labelled. It runs the base branch's
# scripts/triage and only lists the PR's changed paths; the PR's code is never checked out.
pull_request_target:
types: [opened]
schedule:
- cron: '41 5 * * *'
workflow_dispatch:
inputs:
dry_run:
@@ -25,7 +27,7 @@ permissions:
pull-requests: write
concurrency:
group: triage-${{ github.event.issue.number || github.event.pull_request.number || 'backfill' }}
group: triage-${{ github.event.issue.number || github.event.pull_request.number || 'repo' }}
cancel-in-progress: false
jobs:
@@ -37,9 +39,12 @@ jobs:
if: >-
(github.event_name == 'issue_comment' &&
github.event.comment.user.type != 'Bot' && startsWith(github.event.comment.body, '/triage')) ||
((github.event_name == 'issue_comment' || github.event.action == 'edited') &&
contains(github.event.issue.labels.*.name, 'needs-info') &&
github.event.sender.login == github.event.issue.user.login) ||
(github.event.action == 'labeled' && startsWith(github.event.label.name, 'priority:') &&
contains(github.event.issue.labels.*.name, 'needs-triage')) ||
(github.event_name != 'issue_comment' && github.event.action != 'labeled')
(github.event_name != 'issue_comment' && github.event.action != 'labeled' && github.event.action != 'edited')
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
@@ -50,20 +55,32 @@ jobs:
with:
script: |
const triage = require('./scripts/triage/triage.js');
const info = require('./scripts/triage/needs-info.js');
const event = context.eventName;
const action = context.payload.action;
const esc = (t) => String(t).replace(/[&<>"]/g, (c) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' })[c]);
const th = (...names) => names.map((data) => ({ data, header: true }));
if (event === 'issue_comment') {
core.info(await triage.handleComment({ github, context }));
} else if (event === 'issues' && context.payload.action === 'labeled') {
await info.handleReply({ github, context });
} else if (event === 'issues' && action === 'labeled') {
await triage.handleLabeled({ github, context });
} else if (event === 'issues' && action === 'edited') {
await info.handleReply({ github, context });
} else if (event === 'schedule') {
const closed = await info.sweep({ github, context });
core.info(`Closed for missing information: ${closed.join(', ') || 'none'}`);
} else if (event === 'workflow_dispatch') {
const dryRun = process.env.DRY_RUN !== 'false';
const plan = await triage.backfill({ github, context, dryRun });
const esc = (t) => String(t).replace(/[&<>"]/g, (c) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' })[c]);
const rows = plan.map((p) => [`#${p.number}`, p.pull ? 'PR' : 'issue', esc(p.labels.join(', ') || '—'), esc(p.title)]);
const asks = await info.backfill({ github, context, dryRun });
await core.summary
.addHeading(dryRun ? `Backfill dry run: ${plan.length} unlabelled` : `Backfill: ${plan.length} labelled`)
.addTable([[{ data: 'Item', header: true }, { data: 'Kind', header: true }, { data: 'Labels', header: true }, { data: 'Title', header: true }], ...rows])
.addTable([th('Item', 'Kind', 'Labels', 'Title'), ...plan.map((p) => [`#${p.number}`, p.pull ? 'PR' : 'issue', esc(p.labels.join(', ') || '—'), esc(p.title)])])
.addHeading(dryRun ? `needs-info dry run: ${asks.length} would be asked` : `needs-info: ${asks.length} asked`)
.addTable([th('Issue', 'Asks', 'Title'), ...asks.map((p) => [`#${p.number}`, esc(p.asks.join(', ')), esc(p.title)])])
.write();
} else {
core.info(`Labelled: ${(await triage.handleOpened({ github, context })).join(', ') || 'nothing'}`);
if (event === 'issues') await info.handleOpened({ github, context });
}