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
1 change: 1 addition & 0 deletions .github/workflows/nexu-pal-issue-opened.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,5 @@ jobs:
ISSUE_NUMBER: ${{ github.event.issue.number }}
ISSUE_TITLE: ${{ github.event.issue.title }}
ISSUE_BODY: ${{ github.event.issue.body }}
ISSUE_AUTHOR_ASSOCIATION: ${{ github.event.issue.author_association }}
run: node scripts/nexu-pal/process-issue-opened.mjs
44 changes: 30 additions & 14 deletions scripts/nexu-pal/lib/triage-opened-engine.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ function sanitizeJsonResponse(raw) {
return raw.replace(/^```(?:json)?\s*\n?/m, "").replace(/\n?```\s*$/m, "");
}

function isInternalIssueAuthor(authorAssociation) {
return authorAssociation === "MEMBER" || authorAssociation === "OWNER";
}

async function detectAndTranslate({ chat, issueTitle, issueBody }) {
const content = `Title: ${issueTitle}\n\nBody:\n${issueBody}`;

Expand Down Expand Up @@ -249,6 +253,7 @@ function buildNeedsInformationComment({ missingItems, reason }) {
export async function buildOpenedIssueTriagePlan({
issueTitle,
issueBody,
issueAuthorAssociation,
chat,
}) {
Comment thread
nettee marked this conversation as resolved.
const plan = createTriagePlan();
Expand Down Expand Up @@ -298,6 +303,31 @@ export async function buildOpenedIssueTriagePlan({
plan.diagnostics.push(...translation.diagnostics);
}

const classification = await classifyBugOnly({
chat,
englishTitle,
englishBody,
});

if (classification.is_bug === true) {
plan.labelsToAdd.push("bug");
}

plan.diagnostics.push(
`bug classification: ${classification.reason ?? "no reason provided"}`,
);

plan.diagnostics.push(
`author association: ${issueAuthorAssociation ?? "unknown"}`,
);

if (isInternalIssueAuthor(issueAuthorAssociation)) {
plan.diagnostics.push(
"internal author detected; skipped roadmap/duplicate/completeness/needs-triage checks",
);
return plan;
}

const roadmap = await matchRoadmap({
title: englishTitle,
body: englishBody,
Expand All @@ -315,20 +345,6 @@ export async function buildOpenedIssueTriagePlan({
plan.diagnostics.push(...duplicate.diagnostics);
}

const classification = await classifyBugOnly({
chat,
englishTitle,
englishBody,
});

if (classification.is_bug === true) {
plan.labelsToAdd.push("bug");
}

plan.diagnostics.push(
`bug classification: ${classification.reason ?? "no reason provided"}`,
);

const completeness = await assessInformationCompleteness({
chat,
englishTitle,
Expand Down
2 changes: 2 additions & 0 deletions scripts/nexu-pal/process-issue-opened.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const repo = process.env.GITHUB_REPOSITORY;
const issueNumber = process.env.ISSUE_NUMBER;
const issueTitle = process.env.ISSUE_TITLE ?? "";
const issueBody = process.env.ISSUE_BODY ?? "";
const issueAuthorAssociation = process.env.ISSUE_AUTHOR_ASSOCIATION ?? "NONE";

if (!endpoint || !apiKey || !ghToken || !repo || !issueNumber) {
console.error(
Expand Down Expand Up @@ -55,6 +56,7 @@ async function main() {
const plan = await buildOpenedIssueTriagePlan({
issueTitle,
issueBody,
issueAuthorAssociation,
chat,
});

Expand Down
6 changes: 4 additions & 2 deletions specs/current/nexu-pal.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ Runs in order:

3. **Intent classification** — Sends the normalized English title and body to the LLM and assigns only the `bug` label when the issue clearly describes broken behavior.

4. **Completeness check** — Uses the LLM to decide whether the issue is too incomplete to continue triage. If so, adds `needs-information`, posts a follow-up comment, and pauses there.
4. **Internal-member short-circuit** — If `issue.author_association` is `MEMBER` or `OWNER`, the opened-issue flow stops after translation + bug classification. Internal issues skip known-issue matching, completeness checks, and `needs-triage` labeling.

5. **Triage label** — If the issue is not roadmap-matched and does not need more information, adds the `needs-triage` label.
5. **Completeness check** — For non-internal authors, uses the LLM to decide whether the issue is too incomplete to continue triage. If so, adds `needs-information`, posts a follow-up comment, and pauses there.

6. **Triage label** — For non-internal authors, if the issue is not roadmap-matched and does not need more information, adds the `needs-triage` label.

The opened-issue flow is split into a small pipeline:

Expand Down
Loading