Skip to content

Releases: ashbrener/spec-kit-jira-sync

v0.3.0 — ADR mirroring + author attribution

12 Jun 12:24
e4af8f1

Choose a tag to compare

MINOR feature release. Two new user-facing features since v0.2.1.

ADR / decision-record mirroring (feature 005)

Each spec's research.md decision records — the Decision / Rationale / Alternatives blocks (both the bold-lead and stock-bullet grammars) — are mirrored as one idempotent comment per decision on the spec's Jira issue. Re-runs are zero-churn; a changed decision updates its single comment in place (never a duplicate). The ADR comment stream is disjoint from clarify-session comments (speckit-adr: vs speckit-note: markers) and parity-locked to the Linear sibling's ADR layout (Linear-008 parity). Carried through the neutral workstate.decisions[] floor field; the reconcile engine stays vendor-neutral. Additive and on by default — no config, no new command.

Author-based attribution (feature 007)

Opt-in two-track attribution that makes the board reflect who authored each spec:

  • an account-independent author:<handle> label stamped on the spec issue always (works for authors with no Jira account), plus
  • a Jira assignee set on create only when the author maps to a real accountId (never re-sent on update, so a manual reassignment survives — Linear bridge FR-034 semantics).

Author resolution is vendor-neutral (Owner:/Author: line wins, else first git author to add the spec dir, else a graceful unknown no-op). The email→accountId/handle mapping is the sink's job via a gitignored operator map (jira-authors.local.yml; only a .sample placeholder ships, as the map holds PII). Off by default — absent/enabled: false is byte-identical to prior behavior.

Install

The GitHub source ZIP at the v0.3.0 tag is the install artifact:
https://github.com/ashbrener/spec-kit-jira-sync/archive/refs/tags/v0.3.0.zip

Note: the v0.3.0 tag currently sits on the release/v0.3.0 branch. After release PR #14 merges, the tag will be re-pointed to the merge commit on main (matching the v0.2.0 / v0.2.1 process).

v0.2.1 — multi-spec & dry-run fixes

11 Jun 11:16

Choose a tag to compare

PATCH bug-fix release over v0.2.0. No new features — both fixes landed on main after the v0.2.0 tag, so the cataloged v0.2.0 still carried the multi-spec collision bug. The GitHub source ZIP at this tag is the install artifact.

Fixed

  • #10 — spec-scoped phase Subtask identity (fixes cross-spec collision on multi-spec repos). The feature-003 unified level loop matched a phase Subtask by its task-phase:N identity label alone; task-phase:N is a phase number (unique only within a spec), so across a multi-spec repo every spec's "Phase N" matched the same Subtask — specs 2..N updated spec 1's Subtask instead of creating their own. The phase find is now parent-scoped (parent = <story> AND labels = task-phase:N), restoring 001 behaviour. No label-scheme change; single-spec boards are unaffected; a plain reconcile.sh --all self-heals a mis-scoped board.
    • Empty taskList → HTTP 400 INVALID_INPUT guard: a ## Phase with zero task lines no longer renders a childless ADF taskList (which Jira rejects) — a paragraph placeholder is emitted, and every taskItem carries non-empty content.
    • Field-level error detail: a non-2xx write now surfaces the Jira response body (errorMessages / errors) in the failure line.
  • #9 — dry-run of an unmirrored spec no longer spuriously exits 3: a --dry-run create synthesizes the DRY-0 placeholder key; the post-create reconciles read against it, which 404s on a live Jira → fail-closed rc 3 → the whole dry-run exited 3 even though the board was fully readable. The existence-check read is now skipped for the DRY-0 placeholder (scoped to DRY-0 only — a real key still fails closed).

Install: specify extension add jira-sync --from https://github.com/ashbrener/spec-kit-jira-sync/archive/refs/tags/v0.2.1.zip

v0.2.0 — re-mode + engine unification

08 Jun 21:45
e284ba7

Choose a tag to compare

Minor release on top of v0.1.0. Install via the GitHub-generated source tarball at this tag.

Feature 004 — guarded re-mode / orphan pruning (new, user-facing)

An opt-in, controlled-destruction reconcile.sh --remode that converges a board to the shape the current mapping projects:

  • Orphan pruning — prunes the bridge-owned artifacts a prior mapping shape left behind, identified by a vendor-neutral diff O = E \ D over the speckit-* identity labels, then regenerates the new shape in one pass.
  • Fail-safe scoping — an issue carrying no speckit-* identity label (e.g. operator-created) is structurally excluded and never touched.
  • Dry-run preview--remode --dry-run previews the exact prune + regenerate set with zero writes, byte-faithful to the real run.
  • Fail-closed — reads are fail-closed (an unreadable read aborts before any delete); a partial prune failure is surfaced and completable by a re-run; backward-drift on a to-be-pruned issue is warned first.
  • Selectable destruction modelremode.destruction: hard-delete (default) or archive.
  • Ordinary reconcile stays strictly non-destructive — it only warns when it detects prior-shape orphans.
  • Governance — gated on a constitution v1.1.0 amendment: a scoped controlled-destruction carve-out to Principle I (flag-only, bridge-owned-only, dry-run-previewable, fail-closed). No principle removed.

Feature 003 — engine orchestration unification (internal, behavior-preserving)

Re-platforms the engine onto one neutral, mapping-driven projection (sync_level_artifact + link_to_parent) driven by a vendor-neutral level loop; the 001-era orchestrators (~450 lines) are removed. An enforced committed gate keeps the engine path free of Jira issue-type / artifact-name / relationship knowledge, so the eventual engine extraction is a near-mechanical lift. No operator-observable change — behavior is byte-for-byte identical and the full suite passes unchanged.

Full changelog: https://github.com/ashbrener/spec-kit-jira-sync/blob/v0.2.0/CHANGELOG.md

spec-kit-jira-sync v0.1.0

08 Jun 13:01
1a1cf88

Choose a tag to compare

spec-kit-jira-sync v0.1.0

A real reconcile engine — idempotent, drift-aware, fail-closed — that mirrors
your spec-kit specs into Jira and never corrupts your board.

This is not a prompt that asks an LLM to "make some Jira tickets." It is a
deterministic reconcile engine (the same hardened core the shipped
spec-kit-linear-sync runs) wired to Jira's REST API. The filesystem is the
single source of truth; Jira is a one-way, read-only mirror. Every run converges
the board to disk:

  • Idempotent — a re-run over an unchanged spec corpus performs zero
    writes. It reuses the existing issues instead of duplicating them. Run it as
    often as you like.
  • Drift-aware — before each write the engine computes a backward-drift
    signal (lifecycle ordering + commit recency). If Jira is ahead of disk it
    surfaces a named WARNING rather than silently clobbering, and you choose the
    disposition (--on-drift=proceed warns and writes; --on-drift=abort skips
    the drifted spec).
  • Fail-closed — invalid config exits 2; an unreadable Jira exits 3.
    When the engine cannot read the board reliably it refuses to write rather than
    risk a duplicate. No partial corruption.
  • Schema-gated — every record is validated against the neutral workstate
    schema (under uv, PEP 668-safe) before any write touches Jira.

What it mirrors

By default, the zero-config projection is:

  • Epic per repo — one per-repository Epic.
  • Story per spec — one Story per specs/NNN-feature/ directory, linked under
    the repo Epic, transitioned through your workflow as the spec's lifecycle phase
    advances.
  • Subtask per phase — one Subtask per task phase, with that phase's tasks
    rendered as a done/not-done ADF checklist in the Subtask body.

Feature 001 — the core bridge (Layer D reconcile)

A single src/reconcile.sh command mirrors a spec-kit project's specs into Jira
through parser → schema-valid workstate → Jira sink. The parser reads the
on-disk spec corpus (spec.md / plan.md / tasks.md), infers the lifecycle
phase, and emits neutral workstate JSON; the Jira sink consumes only
workstate. The reconcile engine (drift detection, commit-recency gating,
layered idempotency) is vendor-neutral — Jira lives only in the sink and config.

Feature 002 — configurable artifact mapping

An optional mapping: block in jira-config.yml makes the spec-kit→Jira
projection operator-configurable, while keeping today's behavior as the frozen,
zero-config default (a no-config upgrade is byte-for-byte identical — the
regression anchor):

  • Per-level mapping + available-type detection — each workstate level
    (repo/spec/phase/task) maps to a configurable Jira issue type and a
    parent-link relationship, validated at config-load against the project's
    live available issue types, with a per-level on_absent fallback. All
    fail-closed before any write.
  • 2-level checklist mode — phases/tasks collapse into a keyed in-body
    checklist on the spec issue (no Subtask children), diffed as an isolated
    byte-stable sub-tree so re-runs stay zero-churn and human prose edits survive.
  • Status rollup (off by default) — rolls phase/spec completion up to issue
    status (phase done when all tasks checked, repo Epic done when all specs
    merged), transitioning only on a real completion change.
  • Initiative super-level (off by default) — a narrative level above the Epic,
    mapping to a Jira Initiative where available and degrading gracefully onto the
    Epic (behind a stable marker + repo label) where it is not — never
    hard-failing. Narrative is sourced only from the explicit spec.md Input:
    line.
  • --workstate <file|-> direct input — feeds a schema-validated workstate
    document straight to the sink, skipping the parser, so any producer can drive
    the mirror.

Install

specify extension add jira

Then copy config-template.yml to .specify/extensions/jira/jira-config.yml,
fill in your project key, issue-type ids, and phase→status ids, and set
JIRA_BASE_URL / JIRA_EMAIL / JIRA_API_TOKEN in a gitignored .env.

Two commands ship: /speckit.jira.push (reconcile/write) and
/speckit.jira.status (read-only dry-run drift preview).

Privacy

No real Jira coordinates or PII ship in this release. The Basic-auth token and
all site/project binding values live only in your gitignored .env and
jira-config.yml. A privacy guard gates CI.

License: MIT