Events & Async Actions
Foundation uses Forge’s event system for two purposes:
- Product event triggers — Jira fires events on issue/sprint/link changes; the backend catches them to keep the issue cache fresh
- Async event consumers — Long-running operations (sync agent execution, cache refresh, resource leveling, WBS generation, import) run in async context with a 15-minute timeout
Table of Contents
Section titled “Table of Contents”- Product Event Triggers
- Scheduled Triggers
- Async Event Consumers
- Rovo Agent Actions
- Manifest Configuration
Product Event Triggers
Section titled “Product Event Triggers”Defined in manifest.yml under modules.trigger. These handlers respond to Jira platform events.
Issue Handler (events/issue-handler.ts)
Section titled “Issue Handler (events/issue-handler.ts)”Handles all issue lifecycle events. This is the primary mechanism for keeping the issue cache fresh.
| Trigger Key | Event | Description |
|---|---|---|
ic | avi:jira:created:issue | New issue created in Jira |
iu | avi:jira:updated:issue | Issue field changed (self-skipped via ignoreSelf: true) |
id | avi:jira:deleted:issue | Issue deleted from Jira |
ilc | avi:jira:created:issuelink | Issue link created |
ild | avi:jira:deleted:issuelink | Issue link deleted |
Processing flow:
- Extract issue ID(s) and project key(s) from the event payload
- Set per-project event timestamps in KVS (
last-issue-event-ts:${projectKey}) for staleness detection - For created/updated events:
- Fetch the full issue from Jira (2 API points)
- Upsert into
issue_cache - Find which lenses contain this issue
- Publish
hierarchy_changedrealtime event to affected lenses - Trigger auto-sync for affected projects
- For deleted events:
- Delete from
issue_cache - Remove hierarchy nodes referencing the deleted issue
- Publish
hierarchy_changedto affected lenses
- Delete from
- For link events:
- Re-fetch both linked issues to update
links_json - Update cache entries
- Re-fetch both linked issues to update
Cost: Product event triggers themselves are free (no API points). The handler’s fetchIssueByKey() call costs 2 points.
Known limitation (ECO-395): avi:jira:updated:issue does NOT fire when workflow transitions use Custom Event Notifications. Cache may go stale for up to 60 minutes in this case.
Sprint Handler (events/sprint-handler.ts)
Section titled “Sprint Handler (events/sprint-handler.ts)”Handles sprint lifecycle events.
| Trigger Key | Event |
|---|---|
spe | avi:jira:started:sprint |
spe | avi:jira:closed:sprint |
spe | avi:jira:updated:sprint |
Processing flow:
- Extract sprint ID from event
- Fetch all issues in the sprint via JQL:
sprint = ${sprintId} - Upsert each issue into the cache (updates sprint state: active/closed/future)
- Find affected lenses and publish
hierarchy_changedevents
Uninstall Handler (events/uninstall-handler.ts)
Section titled “Uninstall Handler (events/uninstall-handler.ts)”| Trigger Key | Event |
|---|---|
oau | avi:forge:uninstalled:app |
Handles app uninstallation. Performs cleanup of app-specific data.
Scheduled Triggers
Section titled “Scheduled Triggers”Cache Integrity Check (events/cache-integrity.ts)
Section titled “Cache Integrity Check (events/cache-integrity.ts)”| Trigger Key | Schedule | Timeout |
|---|---|---|
cic | Every hour | 25 seconds (standard) |
Periodic cache maintenance:
- Stale entry re-fetch: Finds cache entries with
cached_atolder than 2 hours. Re-fetches from Jira (max 50 per run). Respects rate limit budget. - Deleted issue cleanup: If a re-fetch returns null (issue deleted in Jira), deletes the cache entry and removes orphaned hierarchy nodes. This catches missed
avi:jira:deleted:issueevents. - Orphan node cleanup: Finds hierarchy nodes referencing non-existent cache entries.
Daily Health Check (events/daily-health-check.ts)
Section titled “Daily Health Check (events/daily-health-check.ts)”| Trigger Key | Schedule | Timeout |
|---|---|---|
dht | Every day | 900 seconds (15 min) |
Daily analytics and alerting:
- Processes all lenses in batches of 25
- For each lens:
- Loads all issue nodes with cached data
- Computes health metrics: total items, completed, overdue, unassigned, story points
- Calculates a health score (0-100)
- Upserts a
lens_snapshotsrow for the current date
- Evaluates alert rules from
automation_rulestable - Creates alerts in the
alertstable when thresholds are breached
Async Event Consumers
Section titled “Async Event Consumers”Defined in manifest.yml under modules.consumer. These process messages from Forge queues with extended timeouts (up to 15 minutes).
Sync Agent Executor (events/sync-agent-executor.ts)
Section titled “Sync Agent Executor (events/sync-agent-executor.ts)”| Consumer Key | Queue | Function | Timeout |
|---|---|---|---|
sae | generator-queue | sa | Default (25s) |
Executes all sync agents for a lens sequentially.
Processing flow for each sync agent:
- Read the generator’s config (JQL query, generator type, parent node)
- For
jql_insertgenerators:- Execute JQL query via
fetchIssuesByJql() - Upsert fetched issues into cache
- Add new hierarchy nodes for issues not yet in the lens
- Delete hierarchy nodes for issues no longer matching the JQL
- Execute JQL query via
- For
child_extendgenerators:- Fetch children of specified parent issues
- Add child nodes to the hierarchy under their parents
- For
hierarchy_buildergenerators:- Build a full project hierarchy from Jira parent-child relationships
- For
auto_projectgenerators:- Verify project still exists in Jira
- If missing, clean up stale issues and delete the generator
- If available, sync all project issues
- Update generator execution status (
last_executed_at,last_execution_status,last_known_total) - Store incremental diff in KVS for the frontend to display
Concurrency: Uses concurrency: { key: 'gen-${lensId}', limit: 1 } to ensure only one sync runs per lens at a time.
Job tracking: Active jobs are tracked in KVS at active-gen-job:${lensId}. The marker is set before queue push and cleared after completion (or expires after 15 minutes).
Leveling Executor (events/leveling-executor.ts)
Section titled “Leveling Executor (events/leveling-executor.ts)”| Consumer Key | Queue | Function |
|---|---|---|
lve | leveling-queue | le |
Runs the resource leveling algorithm for a lens. Updates leveling_jobs status as it progresses.
Cache Refresh Executor (events/cache-refresh-executor.ts)
Section titled “Cache Refresh Executor (events/cache-refresh-executor.ts)”| Consumer Key | Queue | Function | Timeout |
|---|---|---|---|
cre | cache-refresh-queue | cr | 120 seconds |
Processes per-project cache refresh requests (initiated by admin).
Per-project flow:
- Read the job status from KVS
- Mark project as
refreshing - Check rate limit budget (estimated 501 points per project)
- Fetch all issues via JQL:
project = "${pk}" ORDER BY updated DESC(max 500) - Batch upsert into cache
- Reconcile deleted issues
- Mark project as
completed(orthrottled/failed) - Check if all projects are done; if so, mark the overall job as
completed
Import Executor (events/import-executor.ts)
Section titled “Import Executor (events/import-executor.ts)”| Consumer Key | Queue | Function | Timeout |
|---|---|---|---|
ime | import-queue | ih | 900 seconds |
Processes hierarchy import jobs (third-party imports, project imports).
WBS Executor (events/wbs-executor.ts)
Section titled “WBS Executor (events/wbs-executor.ts)”| Consumer Key | Queue | Function | Timeout |
|---|---|---|---|
wbe | wbs-queue | wb | 900 seconds |
Processes AI-driven Work Breakdown Structure generation jobs.
Rovo Agent Actions
Section titled “Rovo Agent Actions”Defined in manifest.yml under modules.action. These are invoked by the Rovo AI agent (conversational interface in Jira’s Rovo Chat sidebar).
Action Verbs
Section titled “Action Verbs”| Verb | Behavior | Use For |
|---|---|---|
GET | Auto-executes without user confirmation | Read-only queries |
CREATE | Requires user confirmation | Creating new data |
UPDATE | Requires user confirmation | Modifying existing data |
DELETE | Requires user confirmation | Removing data |
TRIGGER | Requires user confirmation | Operations with side effects |
Standalone Actions (29 manifest entries)
Section titled “Standalone Actions (29 manifest entries)”Each action maps to a function handler in foundation/src/actions/:
| Key | Name | Verb | Handler | Description |
|---|---|---|---|---|
addIssues | Add Issues | CREATE | actions/add-issues | Add issues by JQL |
createFlexItem | Flex Item | CREATE | actions/create-flex-item | Create a grouping node |
moveNode | Move | UPDATE | actions/move-node | Move node in hierarchy |
bulkUpdate | Bulk Update | UPDATE | actions/update-field | Bulk update issue fields |
createIssue | New Issue | CREATE | actions/create-and-add-issue | Create Jira issue + add |
runSync | Run Sync | TRIGGER | actions/execute-sync-agents | Execute sync agents |
lensSummary | Summary | GET | actions/get-summary | Lens summary text |
lensContext | Context | GET | actions/get-lens-context | Lens context data |
issueHier | Hierarchy | GET | actions/get-work-issue-hierarchy | Issue type hierarchy |
buildWbs | WBS | CREATE | actions/build-wbs | AI WBS generation |
analyzeGaps | Gaps | GET | actions/analyze-section-gaps | Gap analysis |
removeNodes | Remove | DELETE | actions/remove-nodes | Remove from hierarchy |
orchestrate | Orchestrate | CREATE | actions/orchestrate-lens | Multi-step orchestration |
applySuggestion | Apply | UPDATE | actions/apply-suggestion | Apply AI suggestion |
listLenses | Lenses | GET | actions/lens-crud | List all lenses |
listSync | List Sync | GET | actions/sync-agent-crud | List sync agents |
createSync | Create Sync | CREATE | actions/sync-agent-crud | Create sync agent |
deleteSync | Delete Sync | DELETE | actions/sync-agent-crud | Delete sync agent |
listViews | List Views | GET | actions/view-crud | List views |
cfgView | Config View | UPDATE | actions/view-crud | Configure view |
findNodes | Find | GET | actions/find-nodes | Search nodes |
bulkMove | Bulk Move | UPDATE | actions/bulk-move-nodes | Bulk move nodes |
syncIssues | Sync | TRIGGER | actions/sync-issues | Manual sync |
getTransitions | Transitions | GET | actions/get-transitions-action | Status transitions |
fieldOpts | Field Opts | GET | actions/get-field-options-action | Field options |
validateJql | Check JQL | GET | actions/validate-jql | JQL validation |
createView | New View | CREATE | actions/view-crud | Create view |
setDefView | Default View | UPDATE | actions/view-crud | Set default view |
lensDetails | Lens Details | GET | actions/get-lens-details | Lens detail data |
Dispatcher Actions (6 manifest entries)
Section titled “Dispatcher Actions (6 manifest entries)”These use a _action parameter to multiplex multiple sub-actions through a single manifest entry, conserving the limited action slot budget.
| Key | Name | Verb | Sub-actions |
|---|---|---|---|
lensCrud | Lens CRUD | TRIGGER | createLens, renameLens, deleteLens |
hierMeta | Hier Meta | TRIGGER | getTransitions, getFieldOptions, getLensDetails, getNodeDetails, getSubtreeStats, groupNodesBy, sortNodes, renameFlexItem, flattenSubtree, mergeFlexItems |
viewPerm | View Perm | TRIGGER | createView, deleteView, setDefaultView, grantPermission, revokePermission |
jiraUtil | Jira Util | GET | validateJql, analyzeJiraProject, createFromTemplate |
r2g | R2G | GET | 19 read-only intelligence/analytics actions |
r2r5 | R2R5 | TRIGGER | 14 destructive operations requiring confirmation |
See API Reference - Rovo Agent Dispatchers for the complete sub-action listing.
Manifest Configuration
Section titled “Manifest Configuration”Function Definitions
Section titled “Function Definitions”Functions are defined in manifest.yml under modules.function with 2-character keys to minimize CaaS manifest byte size:
| Key | Handler | Purpose |
|---|---|---|
r | index.handler | Main resolver (all frontend-invoked resolvers) |
ie | events/issue-handler.handler | Issue events |
se | events/sprint-handler.handler | Sprint events |
ci | events/cache-integrity.handler | Hourly cache check |
dh | events/daily-health-check.handler | Daily health snapshots (900s timeout) |
sa | events/sync-agent-executor.handler | Sync agent execution |
le | events/leveling-executor.handler | Resource leveling |
cr | events/cache-refresh-executor.handler | Cache refresh (120s timeout) |
ih | events/import-executor.handler | Import processing (900s timeout) |
wb | events/wbs-executor.handler | WBS generation (900s timeout) |
uh | events/uninstall-handler.handler | App uninstall |
f1-fw, g1-g3 | actions/*.handler | Rovo agent action handlers |
Byte Size Constraint
Section titled “Byte Size Constraint”The Forge CaaS manifest has a ~257KB byte limit (ECO-1310). The current manifest uses slim conventions:
- 2-char function keys
- 2-3 char module/trigger/consumer keys
.for action descriptionsxfor input titles- No optional fields
Current state: 35 actions, ~22,850 bytes with ~650 bytes of headroom. Run node scripts/check-manifest-limits.js before adding actions.
Cross-References
Section titled “Cross-References”- API Reference — resolver endpoint documentation
- Services — business logic used by event handlers
- Database Schema — tables written to by event handlers