(board, filtersInput)
| 511 | } |
| 512 | |
| 513 | async function syncBoardFromRepo(board, filtersInput) { |
| 514 | const workspacePath = activeSession?.workspacePath; |
| 515 | let repo = normalizeText(board.repo); |
| 516 | if (!repo && workspacePath) { |
| 517 | const repoData = await runGhJson(["repo", "view", "--json", "nameWithOwner"], workspacePath); |
| 518 | repo = normalizeText(repoData?.nameWithOwner); |
| 519 | } |
| 520 | if (!repo) { |
| 521 | throw new Error("Repository is not configured. Open the canvas with a repo or call sync_from_repo with { repo: \"owner/name\" }."); |
| 522 | } |
| 523 | const filters = normalizeFilters(filtersInput, board.filters || defaultFilters); |
| 524 | |
| 525 | const issues = await runGhJson( |
| 526 | [ |
| 527 | "issue", |
| 528 | "list", |
| 529 | "--repo", |
| 530 | repo, |
| 531 | "--state", |
| 532 | "open", |
| 533 | "--limit", |
| 534 | String(MAX_SYNC_ISSUES), |
| 535 | "--json", |
| 536 | "number,title,url,labels,assignees,createdAt,updatedAt,author,body", |
| 537 | ], |
| 538 | workspacePath || process.cwd(), |
| 539 | ); |
| 540 | |
| 541 | const filteredIssues = Array.isArray(issues) ? sortIssues(issues.filter((issue) => issueMatchesFilters(issue, filters)), filters.sortBy) : []; |
| 542 | const items = filteredIssues.map((issue) => ({ |
| 543 | id: `issue-${issue.number}`, |
| 544 | title: `#${issue.number} ${normalizeText(issue.title, "Untitled issue")}`, |
| 545 | description: buildIssueDescription(issue), |
| 546 | details: buildIssueDetails(issue), |
| 547 | repo, |
| 548 | number: String(issue.number), |
| 549 | url: normalizeText(issue.url), |
| 550 | labels: Array.isArray(issue.labels) ? issue.labels.map((label) => normalizeText(label?.name)).filter(Boolean) : [], |
| 551 | assignees: Array.isArray(issue.assignees) ? issue.assignees.map((assignee) => normalizeText(assignee?.login)).filter(Boolean) : [], |
| 552 | createdAt: normalizeText(issue.createdAt), |
| 553 | updatedAt: normalizeText(issue.updatedAt), |
| 554 | author: normalizeText(issue.author?.login), |
| 555 | })); |
| 556 | |
| 557 | setBoardItems(board, items, true); |
| 558 | pruneDecisionsForCurrentItems(board); |
| 559 | board.source = "repo"; |
| 560 | board.repo = repo; |
| 561 | board.filters = filters; |
| 562 | board.syncedAt = new Date().toISOString(); |
| 563 | } |
| 564 | |
| 565 | function renderHtml(instanceId, title) { |
| 566 | const safeTitle = escapeHtml(title || "Backlog Swipe Triage"); |
no test coverage detected