_We write about the tools in Anyshift's ecosystem: the CLIs and platforms that Annie integrates with. This one is about acli, Atlassian's command-line interface for Jira. It's the third in a series with Annie meets pup and Annie meets gcx._

The Problem

In this demo, a developer opens pull request #1923. It modifies validate_session() in shared/auth/session.py, a shared authentication module. Three services in production import it: checkout-service, notification-worker, and inventory-sync. Their teams (payments, notifications, catalog) should know now, not a sprint later when something breaks in staging.

  PR #1923  (shared/auth/session.py)
       │
       ├─→ checkout-service       →  payments
       ├─→ notification-worker    →  notifications
       └─→ inventory-sync         →  catalog

The information existed while the pull request was still open: which services consume the change, which teams own them, who reviewed the last similar change. Jira is the right place for that work to land. The hard part is deciding where to file it before the work exists.

That decision comes from production, not from the Jira issue alone.

Why this belongs in Jira

Jira is where teams coordinate the follow-up work: who owns it, which team board it belongs on, what evidence is attached, and whether it is linked to a parent issue or an existing ticket.

Annie can decide what follow-up work is needed before the ticket exists because it reads Anyshift's production context: running services, dependency paths, deploy history, PR provenance, and ownership.

For Atlassian readers, this fits the direction of Teamwork Graph: Jira and Rovo keep work context connected; Annie brings in the production impact that tells that work where to land.

From PR Impact To Jira

annie do takes one pull request and prepares the Jira work: one parent issue (the grouping ticket) plus one advisory ticket (the heads-up) for each affected team. If the graph resolves a reviewer, the advisory is assigned before acli writes to Jira.

For "PR #1923" the routing is:

  • checkout-service imports the changed function, so Payments (PAY) gets an advisory.
  • notification-worker imports it too, so Notifications (NOTIF) gets one.
  • inventory-sync depends on it through lib-common@2.4.1, so Catalog (CAT) gets one.
  • deprecated or sandbox-only services are skipped.
  • an existing advisory from a nearby PR is linked, not duplicated.

That context comes from code paths, deploys, ownership history, and the PR itself.

That is the handoff: Annie prepares and saves the plan; acli executes it in Jira after approval.

Diagram of the handoff between annie do and acli. Left card on a beige background with an ANYSHIFT cyan pill: annie do reads the Anyshift graph, writes the runbook, never touches Jira. Middle: a runbook.yaml document with terracotta arrows pointing in from the left and out to the right. Right card with an ATLASSIAN navy pill: acli owns Jira auth, project keys, assignees, and work-item commands; never touches the graph. Footer caption: the runbook on disk is the contract between them.

annie do writes a runbook (the YAML plan reviewed before execution). It includes the impact evidence and the exact acli commands.

acli then uses Jira's own authentication to create, bulk-create, and link the work items.

The generated files

annie do output: YAML with the PR impact.

Color-highlighted YAML impact excerpt for annie do. It keeps the original PR, changed file, consumers, routing evidence, skipped services, and existing advisory chain, with YAML keys in yellow, service names in cyan, values in green, and comments in muted blue.

acli step: Annie converts the plan into the JSON that create-bulk expects.

Color-highlighted JSON payload for acli create-bulk. It shows one child advisory issue for PAY, with a readable summary, Jira Task type, ADF description body, labels including pr-1923, parentIssueId pointing back to the ENG-1 parent issue id, and the routed assignee account id.

After approval, acli creates the parent issue, creates the child advisories, then links each child back to the parent. The last step reads the parent issue key, loops over each child ticket key, and asks acli to create one Jira relationship link, Relates, per child:

Simplified flow showing Anyshift mapping PR 1923 to impacted services and teams, Annie writing Jira keys into a runbook, and acli creating linked Jira work: ENG-1 as the parent issue with PAY-1, NOTIF-1, and CAT-1 as child advisory tickets.

Before approval, the affected teams' Jira boards have no tickets for the PR #1923 yet. Annie has found the impact; Jira has not received the work yet.

Jira filtered to the four demo projects (Engineering, Payments, Notifications, Catalog). Main pane reads "There's nothing matching your search". The Space filter dropdown is open, showing all four projects checked.

_Before: Annie has found the impacted services. Jira has no advisory work yet._

After annie do finishes, a parent issue appears in ENG with three tickets linked under it. Each ticket lands on the right team's board. PAY has the routed reviewer; the other teams use the project default.

Jira filtered to the same four projects. Four rows now visible: ENG-1 (Cross-team change advisories for anyshift-backend#1923, assigned to roxane fischer), PAY-1 (advisory affecting checkout-service, assigned to roxane fischer), NOTIF-1 (advisory affecting notification-worker, Unassigned), CAT-1 (advisory affecting inventory-sync, Unassigned). All four labeled pr-1923, all in Backlog.

_After: one parent issue, three tickets, on the right boards. PAY has its routed assignee; the others fall back to project default._

Where it is going

acli is the third vendor CLI Annie hands off to. The pattern stays the same: read the production context, render a runbook, hand it to the tool that owns the writes.

For Atlassian, the bigger path is a Teamwork Graph connector that makes Anyshift's infrastructure memory available wherever Jira agents need production impact. The acli demo is the first concrete step: a native Jira write, with review before execution, backed by production evidence.

The verbs we'd run next on the same shape:

  • Continuous ticket sync as production context changes. A service moves to a new team and the open ticket gets reassigned. A code path gets renamed and the affected tickets get an updated link. A blast radius grows and the priority moves with it.
  • Dedup against open work. Before filing a new ticket, annie do searches Jira for any already referencing the same module. If one exists, evidence is appended as a comment instead of a fresh duplicate landing on the team's board.
  • Stale-ticket cleanup. The graph knows when a code path is deprecated or a service is decommissioned. annie do scans its open tickets and closes the ones whose underlying issue has resolved, with a comment explaining why.