fix(issues): GAP-06 wire CreateSpecButton in IssueDetail
- Add onCreateSpec prop to IssueDetailProps - Import and conditionally render CreateSpecButton after actions section - Derive hasActiveAgent and hasEnrichment from enrichment data - 3 new integration tests (visible, hidden, disabled when agent active) - All 23 IssueDetail integration tests pass, lint clean Co-Authored-By: Claude Opus 4.6 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
c2798a9991
commit
bfd24f0d57
@@ -20,6 +20,7 @@ import { CommentForm } from './CommentForm';
|
||||
import { InlineEditor } from './InlineEditor';
|
||||
import { LabelManager } from './LabelManager';
|
||||
import { AssigneeManager } from './AssigneeManager';
|
||||
import { CreateSpecButton } from './CreateSpecButton';
|
||||
import type { IssueDetailProps } from '../types';
|
||||
|
||||
export function IssueDetail({
|
||||
@@ -45,6 +46,7 @@ export function IssueDetail({
|
||||
onAddAssignees,
|
||||
onRemoveAssignees,
|
||||
collaborators,
|
||||
onCreateSpec,
|
||||
onClose,
|
||||
onReopen,
|
||||
onComment,
|
||||
@@ -214,6 +216,17 @@ export function IssueDetail({
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Create Spec */}
|
||||
{onCreateSpec && (
|
||||
<CreateSpecButton
|
||||
issueNumber={issue.number}
|
||||
issueClosed={issue.state === 'closed'}
|
||||
hasActiveAgent={!!enrichment?.agentLinks?.some(l => l.status === 'active')}
|
||||
hasEnrichment={!!enrichment?.enrichment}
|
||||
onCreateSpec={onCreateSpec}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Task Linked Info */}
|
||||
{hasLinkedTask && (
|
||||
<Card className="bg-success/5 border-success/30">
|
||||
|
||||
+38
@@ -260,4 +260,42 @@ describe('IssueDetail integration', () => {
|
||||
fireEvent.click(screen.getByLabelText('Remove assignee dev1'));
|
||||
expect(onRemoveAssignees).toHaveBeenCalledWith(['dev1']);
|
||||
});
|
||||
|
||||
// GAP-06: CreateSpecButton integration
|
||||
it('renders CreateSpecButton when onCreateSpec is provided', () => {
|
||||
render(
|
||||
<IssueDetail
|
||||
{...baseProps}
|
||||
onCreateSpec={vi.fn()}
|
||||
/>,
|
||||
);
|
||||
// CreateSpecButton renders a section with aria-label "Create spec from issue"
|
||||
expect(screen.getByLabelText('Create spec from issue')).toBeDefined();
|
||||
expect(screen.getByText('Create Spec')).toBeDefined();
|
||||
});
|
||||
|
||||
it('does not render CreateSpecButton when onCreateSpec is not provided', () => {
|
||||
render(<IssueDetail {...baseProps} />);
|
||||
expect(screen.queryByLabelText('Create spec from issue')).toBeNull();
|
||||
});
|
||||
|
||||
it('CreateSpecButton is disabled when agent is active', () => {
|
||||
const enrichment = {
|
||||
issueNumber: 42,
|
||||
triageState: 'triage' as const,
|
||||
completenessScore: 50,
|
||||
enrichment: { problem: 'p', goal: 'g', scopeIn: [], scopeOut: [], acceptanceCriteria: [], technicalContext: '' },
|
||||
agentLinks: [{ agentId: 'a1', status: 'active' as const, specNumber: '001' }],
|
||||
};
|
||||
render(
|
||||
<IssueDetail
|
||||
{...baseProps}
|
||||
enrichment={enrichment as never}
|
||||
onTransition={vi.fn()}
|
||||
onCreateSpec={vi.fn()}
|
||||
/>,
|
||||
);
|
||||
const createBtn = screen.getByText('Create Spec');
|
||||
expect(createBtn.hasAttribute('disabled')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -52,6 +52,7 @@ export interface IssueDetailProps {
|
||||
onAddAssignees?: (logins: string[]) => Promise<void>;
|
||||
onRemoveAssignees?: (logins: string[]) => Promise<void>;
|
||||
collaborators?: string[];
|
||||
onCreateSpec?: () => Promise<{ specNumber: string } | null>;
|
||||
onClose?: (comment?: string) => Promise<void>;
|
||||
onReopen?: () => Promise<void>;
|
||||
onComment?: (body: string) => Promise<void>;
|
||||
|
||||
+8
-7
@@ -3,7 +3,7 @@
|
||||
**Branch:** `terminal/enhancement-issues-tab`
|
||||
**Created:** 2026-02-12
|
||||
**Total Gaps:** 41 confirmed (from triple-verified audit)
|
||||
**Status:** 10 / 41 complete
|
||||
**Status:** 11 / 41 complete
|
||||
|
||||
---
|
||||
|
||||
@@ -95,17 +95,17 @@ Each gap has: ID, description, status, files to modify, doc reference, test stat
|
||||
- **Commit:** (combined with GAP-04)
|
||||
|
||||
### GAP-06: CreateSpecButton not used in IssueDetail.tsx
|
||||
- **Status:** `PENDING`
|
||||
- **Status:** `DONE`
|
||||
- **Priority:** MUST-FIX
|
||||
- **Scope:** Medium
|
||||
- **Doc ref:** Phase 2 PRD > US-8 > AC8.1; Phase 2 PRD Section 4.2
|
||||
- **Files to modify:** `renderer/components/github-issues/components/IssueDetail.tsx`
|
||||
- **Files to modify:** `renderer/components/github-issues/components/IssueDetail.tsx`, `types/index.ts`
|
||||
- **Source component:** `CreateSpecButton.tsx` — accepts issueNumber, issueClosed, hasActiveAgent, activeSpecNumber, hasEnrichment, onCreateSpec
|
||||
- **Fix:** Import CreateSpecButton. Add inside actions div (after Investigate button, ~line 163). Wire props from enrichment data.
|
||||
- **Tests:** Render with onCreateSpec → button visible; check disabled when hasActiveAgent
|
||||
- **Test status:** `PENDING`
|
||||
- **Fix:** Added onCreateSpec to IssueDetailProps, imported CreateSpecButton, conditionally renders after actions when onCreateSpec provided, derives hasActiveAgent and hasEnrichment from enrichment data
|
||||
- **Tests:** 3 new tests: button visible with onCreateSpec, hidden without, disabled when agent active
|
||||
- **Test status:** `PASS` (23/23)
|
||||
- **Depends on:** None (standalone component)
|
||||
- **Commit:** —
|
||||
- **Commit:** GAP-06
|
||||
|
||||
### GAP-07: CompletenessBreakdown not used in EnrichmentPanel.tsx
|
||||
- **Status:** `PENDING`
|
||||
@@ -554,6 +554,7 @@ Each gap has: ID, description, status, files to modify, doc reference, test stat
|
||||
| 2026-02-12 | GAP-21 | DONE — optimistic store updates in useMutations, 21 tests pass | GAP-21 |
|
||||
| 2026-02-12 | GAP-02+03 | DONE — InlineEditor wired for title (required) and body (multiline) in IssueDetail, 7 new tests, 14 pass | GAP-02+03 |
|
||||
| 2026-02-12 | GAP-04+05 | DONE — LabelManager+AssigneeManager wired in IssueDetail, repoLabels/collaborators fetched via IPC, 6 new tests, 20 pass | GAP-04+05 |
|
||||
| 2026-02-12 | GAP-06 | DONE — CreateSpecButton wired in IssueDetail with onCreateSpec prop, 3 new tests, 23 pass | GAP-06 |
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user