Jira Extension - Design Notes
Offline Support Strategy
Current Challenge
- Jira requires VPN connection to issues.redhat.com
- API calls fail when offline or not on VPN
- Users might want to queue operations while offline
Proposed Approach: Operation Queue in Session
Store pending operations in session state (similar to git commits):
interface QueuedOperation {
id: string;
action: "create" | "update" | "comment" | "transition";
params: any;
timestamp: number;
approved: boolean; // User already approved
}
// Store in session via appendEntry
pi.appendEntry("jira-queue", {
operations: [/* queued ops */]
});
Benefits
- Session-based - Survives restarts, respects branching
- Already Approved - User approved when offline, just need to execute
- Git-like Workflow - Make changes offline, “push” when online
- Transparent - User sees queued operations in session
Implementation Steps
- Detect Offline - Try
jira mewith short timeout - Queue Operation - Store in session with approval flag
- Show Queued - Display pending operations to user
- Sync Command -
/jira-syncto execute queued operations - Auto-sync - Optionally sync on connectivity restore
Example Workflow
[OFFLINE]
User: "Create a bug for X"
Agent: <detects offline>
→ Shows approval dialog (with "QUEUED" indicator)
→ User confirms
→ Stores in session queue
→ Returns: "Queued for sync (1 pending operation)"
[ONLINE]
User: "/jira-sync"
→ Executes queued operations
→ Returns: "Synced 1 operation: Created SRVKP-1234"
Conflict Resolution
What if issue changed while offline?
// Before executing queued operation
const current = await viewIssue(op.params.key);
if (hasConflict(current, op)) {
const confirmed = await ctx.ui.confirm(
"Conflict Detected",
`Issue ${op.params.key} changed since queued.\n\n` +
`Queued: ${op.params.field} = ${op.params.value}\n` +
`Current: ${current[op.params.field]}\n\n` +
`Continue with update?`
);
if (!confirmed) {
// Skip this operation
}
}
Session Entry Structure
// Queued operations
{
type: "custom",
customType: "jira-queue",
timestamp: Date.now(),
data: {
operations: [
{
id: "op-1234",
action: "create",
params: { issueType: "Bug", summary: "..." },
timestamp: Date.now(),
approved: true
}
]
}
}
// Sync results
{
type: "custom",
customType: "jira-sync",
timestamp: Date.now(),
data: {
synced: 3,
failed: 0,
results: [
{ id: "op-1234", success: true, issueKey: "SRVKP-5678" }
]
}
}
When to Implement?
Wait for real need - Implement when:
- You frequently work offline
- You make multiple Jira changes in one session
- VPN connectivity is unreliable
For now, the extension fails gracefully with clear error messages about VPN/network.
Batch Operations Strategy
Use Cases
1. Sprint Planning
User: "Add SRVKP-1234, SRVKP-1235, SRVKP-1236 to current sprint"
→ Batch operation: transition multiple issues
2. Bulk Labeling
User: "Add 'release-notes-pending' label to all issues in current sprint"
→ Batch operation: update labels on multiple issues
3. Team Assignment
User: "Assign all unassigned tasks in SRVKP to the team rotation"
→ Batch operation: update assignee on multiple issues
4. Status Updates
User: "Move all code-reviewed issues to QE Review"
→ Batch operation: transition multiple issues
Proposed Design
Add a batch action that operates on multiple issues:
{
action: "batch",
operation: "transition" | "update" | "comment",
issues: ["SRVKP-1234", "SRVKP-1235", "SRVKP-1236"],
// Operation-specific params
state: "In Progress", // For transition
// OR
field: "labels", // For update
value: "release-notes",
// OR
comment: "Bulk update comment"
}
Approval Pattern
Show all changes in one dialog:
┌─────────────────────────────────────┐
│ Batch Transition (3 issues)? │
│ │
│ Issues: │
│ • SRVKP-1234: Fix bug X │
│ • SRVKP-1235: Add feature Y │
│ • SRVKP-1236: Update docs Z │
│ │
│ Change: To Do → In Progress │
│ │
│ This will transition 3 issues. │
│ │
│ [Yes] [No] │
└─────────────────────────────────────┘
Implementation
async function handleBatch(pi, params, signal, onUpdate, ctx) {
// Validate
if (!params.issues || params.issues.length === 0) {
return error("No issues specified");
}
// Get issue details for approval
const details = await fetchIssueDetails(params.issues);
// Approval
if (ctx.hasUI) {
const confirmed = await ctx.ui.confirm(
`Batch ${params.operation} (${params.issues.length} issues)?`,
buildBatchConfirmation(params, details)
);
if (!confirmed) {
return { cancelled: true };
}
}
// Execute on each issue
const results = [];
for (const issueKey of params.issues) {
onUpdate?.({
content: [{
type: "text",
text: `Processing ${issueKey}...`
}]
});
const result = await executeOperation(
issueKey,
params.operation,
params
);
results.push(result);
}
// Return aggregated results
const succeeded = results.filter(r => r.success).length;
const failed = results.filter(r => !r.success).length;
return {
content: [{
type: "text",
text: `Batch ${params.operation} complete:\n` +
` Succeeded: ${succeeded}\n` +
` Failed: ${failed}`
}],
details: {
action: "batch",
operation: params.operation,
results
}
};
}
When to Implement?
Wait for real need - Implement when:
- You frequently need to update 5+ issues at once
- Sprint planning requires bulk operations
- Team workflows involve batch status changes
For now, you can:
- Make individual API calls (jira CLI is fast)
- Use JQL search + manual batch via web UI if needed
- Script batch operations outside of pi if critical
Recommendations
Phase 1: Current Implementation ✅
- All 8 core actions (me, list, view, search, create, update, comment, transition)
- Approval gates for write operations
- Custom rendering
- State management
- Error handling
Phase 2: Epic and Feature Support 🎯
NEXT PRIORITY - You mentioned epics and features are important:
// Add epic-specific actions
{
action: "epic-view",
key: "SRVKP-1234" // View epic with child issues
}
{
action: "epic-create",
summary: "Epic: Major feature",
description: "..."
}
{
action: "link-to-epic",
issue: "SRVKP-5678",
epic: "SRVKP-1234"
}
Phase 3: Attachments and Links 📎
SECOND PRIORITY - You want these features:
// Attachments
{
action: "attach",
key: "SRVKP-1234",
file: "/path/to/file"
}
{
action: "list-attachments",
key: "SRVKP-1234"
}
// Issue links
{
action: "link",
from: "SRVKP-1234",
to: "SRVKP-5678",
type: "blocks" | "relates to" | "duplicates"
}
Phase 4: Offline Support 📡
Wait for need - Implement if:
- VPN is unreliable
- You work offline frequently
- You want to queue multiple operations
Phase 5: Batch Operations 📦
Wait for need - Implement if:
- You regularly update 5+ issues
- Sprint planning requires bulk ops
- Clear use cases emerge
Next Steps
-
Test the Extension
- Try all 8 actions
- Verify approval dialogs work
- Test error handling (VPN off, wrong issue key, etc.)
-
Add Epic Support (Phase 2)
epic-view- View epic with child issuesepic-create- Create new epiclink-to-epic- Link issue to epicunlink-from-epic- Remove epic link
-
Add Feature Support
- Ensure Feature type works in create
- Add Feature-specific fields if needed
-
Add Attachments (Phase 3)
attach- Attach file to issuelist-attachments- List attachmentsdownload-attachment- Download file
-
Add Links (Phase 3)
link- Create issue linkunlink- Remove issue linklist-links- Show related issues
Implementation Priority
NOW → Test current 8 actions
NEXT → Epic support (epic-view, epic-create, link-to-epic)
THEN → Feature type validation
THEN → Attachments (attach, list-attachments)
THEN → Links (link, unlink, list-links)
LATER → Offline support (if needed)
LATER → Batch operations (if needed)
Questions?
- Offline: Queue operations in session, sync when online (similar to git)
- Batch: Useful but wait for real need; single operations are fast enough for now
- Epic: Should be next priority since you use epics/features
- Attachments: Second priority for documentation and screenshots