Skip to content

Releases: ashbrener/spec-kit-linear-sync

v0.5.0 — author attribution, ADR mirroring, identity hardening

12 Jun 12:20
9da265f

Choose a tag to compare

[0.5.0] — 2026-06-12 — Author attribution, ADR mirroring, identity hardening

Three additive, spec-driven features (specs 008/010 + the #69 hardening) plus
Dependabot. extension.id stays linear; the command surface is unchanged;
every existing install behaves identically until it opts in. All safety
guarantees (idempotency, drift-awareness, fail-closed writes) hold.

Author-based attribution — spec 010

  • The board shows who authored each spec. Opt-in (linear.attribution.*,
    default OFF). When enabled, each spec Issue gets an account-independent
    author:<handle> label and — for authors who are Linear members — is assigned
    to that author on creation. A non-member or unresolved author is labelled but
    left unassigned
    (never the operator). Disabled/absent ⇒ byte-for-byte today's
    behaviour (operator assignee per FR-034, no author label).
  • Author resolution is filesystem-derived. A **Owner:** / **Author:**
    line in spec.md wins; otherwise the first git author to add the spec
    directory; otherwise unknown (a graceful no-op — no label, no assignee, no
    failure).
  • Members match automatically; the override map is optional. Linear's member
    roster is read at runtime, so a git email that matches a Linear email resolves
    with no configuration. An optional, gitignored linear-authors.local.yml
    (only a .sample is committed) aliases git≠Linear emails and pins handles for
    non-members — no real email or user id ever lands in a tracked file (the
    identity-leak guard covers it).
  • Idempotent + never-clobber. The author label is strip-and-set (zero churn
    on re-run; one swap on author change); the author assignee is written on create
    only, so a manual reassignment in Linear always survives. Sub-issues optionally
    inherit the author label (subissue_label, default off) but never the author
    assignee. Parity-locked with the spec-kit-jira author-attribution feature at the
    user-visible level. No new command; extension.id stays linear.

ADR / decision-record mirroring — spec 008

  • Your decisions now reach the tracker. The Decision / Rationale / Alternatives blocks in each spec's research.md are mirrored as ADR comments
    on that spec's Linear Issue — one comment per decision, in an ADR layout (id,
    title, status, decision, rationale, alternatives, source). It rides the
    existing after_* hooks; no new command, no config. Works for any spec that
    has a research.md; a spec without one is a graceful no-op.
  • Idempotent + update-in-place. Each ADR is keyed by a hidden
    <!-- spec-kit-linear: adr <NNN>-<key> --> marker (heading id D<N>/R<N>,
    else a title slug); an unchanged corpus is zero-churn, a revised decision
    updates its one comment in place, a new decision adds one comment. (Update-in-
    place is Principle I — the filesystem is canonical; it is the sole behavioural
    delta from the clarify-comment path, and the one new mutation, commentUpdate.)
  • Parity with the spec-kit-jira ADR feature: the user-visible comment shape
    matches across both sinks. No config/schema change; extension.id stays
    linear.

Consumer identity-leak hardening (#69)

  • Install refuses to let your identity reach a tracked file. A new install-
    time guard (install::assert_no_identity_leak) scans the consumer's tracked
    tree for operator-identity leaks — operator.* keys, email-shaped strings, and
    a force-tracked operator-local / authors-override file — and surfaces a loud,
    named warning with remediation (Principle VIII). Export
    SPECKIT_LINEAR_STRICT_IDENTITY=1 to make a detected leak fail the install.
    Reinforces the spec-004 config/identity split: identity stays in the gitignored
    operator-local file, never in committed config.

Tooling — Dependabot (#64#67)

  • Dependabot for GitHub Actions (#64) keeps the CI action pins current; the
    first batch bumped actions/checkout, actions/cache, and actions/setup-node
    (#65#67). CI-internal only; no consumer-facing change.

v0.4.0 — Configurable artifact mapping (#17) + lifecycle fix (#61)

11 Jun 07:14
7cd402d

Choose a tag to compare

Highlights

Configurable artifact mapping (spec 007 — resolves #17). The spec→Linear mapping is now operator-configurable via an optional mapping: block in linear-config.yml, while the spec-001 default (repo→Project, spec→Issue, phase→sub-issue, task→checklist) stays the frozen zero-config default — existing installs are byte-for-byte unchanged.

  • #17 spec-as-Project shape: Initiative > Project > Issue > sub-issue — idempotent (zero-churn re-runs), drift-aware on the spec level.
  • Optional L0 narrative super-level → a Linear Initiative above the repo (narrative from the spec **Input**: only), degrading gracefully where Initiatives aren't on the plan.
  • Fail-closed validation at config-load rejects mappings Linear can't build (Project-under-Project, dependency-links-as-nesting, etc.).
  • Constitution v2.1.0 (MINOR) records the bounded configurability.
  • Validated end-to-end against a real Linear workspace (created the full hierarchy, re-ran zero-churn). The three fixes that validation surfaced are included.

Lifecycle fix (#61). Linear issues no longer stick at "in-progress": the reconciler reads the spec's real branch from plan.md for the PR-state lookup instead of guessing from the directory name.

extension.id stays linear; the command surface is unchanged. See the CHANGELOG for full detail.

v0.3.0 — config/identity split, team-scoped seeding, faithful projection

08 Jun 07:53
2585b8f

Choose a tag to compare

Three spec-driven features (specs 004/005/006). extension.id stays linear — commands are unchanged, and existing installs migrate automatically.

Config / identity split (#38, #20)

linear-config.yml now holds only the shareable team/project binding (safe to commit); your operator identity moves to a gitignored operator-local file. Identity + API key resolve via env → local file → prompt (no more per-worktree .env copies). Legacy single-file configs auto-migrate with a one-time notice; the docs/.gitignore contradiction is resolved.

Team-scoped / non-admin seeding (#41)

Seed without workspace-admin: team-scoped label creation, an adopt-existing path (capture UUIDs of states/labels that already exist), graceful permission-error handling, and --scope workspace|team (default team).

Faithful projection (#34, #42)

push now accepts ## Phase N headers with :, , -, or whitespace separators (was colon-only → silent zero sub-issues). The Linear issue description now inlines the spec's own content (Input + Overview + body, capped with clean-boundary truncation + a full-spec link).

All existing safety guarantees (idempotency, drift-awareness, fail-closed) hold. Upgrade is automatic for existing users; catalog users get this once the listing's download_url is bumped.

v0.2.2 — community bug-fix round

07 Jun 20:53
2c4908b

Choose a tag to compare

Fixes from the first wave of external issue reports (thanks @davieshq, @rcollette). No behavior changes beyond the fixes — extension.id stays linear, so commands are unchanged.

  • #33 / #39 / #40 — seed no longer writes a duplicate default_state_uuids key into linear-config.yml; the managed UUID blocks update in place, so the file stays valid single-key YAML and formats cleanly.
  • #36 — the reconcile summary now counts created issues/sub-issues correctly (they were being lost to a subshell → Created: 0).
  • #35pull and status now surface the "malformed config" diagnostic instead of exiting with a silent code 2.
  • #42 — removed the hardcoded README-anchor links from generated issue descriptions (dead links in any consumer repo).
  • #34push now warns on ## Phase N headings not in the ## Phase N: form (previously skipped silently → 0 sub-issues).

Install / upgrade: nothing required for existing users. Catalog users — the listing is being bumped to this version.

v0.2.1 — spec-kit-linear-sync (rename + pull alignment fix)

03 Jun 14:53
e515963

Choose a tag to compare

Branding/metadata release. The repo + extension display name become spec-kit-linear-sync, joining the spec-kit-<tracker>-sync family. No behavior changeextension.id stays linear, so /speckit.linear.* commands are unchanged, and GitHub redirects the old repo URL.

Fixed

  • #31speckit.linear.pull --human misaligned every column when a cell was empty (no phase:* label, null estimate): IFS=$'\t' read collapsed empty fields (tab is IFS-whitespace), shifting later columns left. Now splits on a non-whitespace unit separator so empty fields are preserved.

Changed

  • Repository renamed spec-kit-linearspec-kit-linear-sync; extension.yml name/repository/homepage updated.
  • Functional identifiers intentionally unchanged: command ids, FR-033 hook markers, specs/001-* paths, the GitHub Action filename.

Upgrade: nothing required. Installed users keep /speckit.linear.*. The old GitHub URL redirects; new canonical URL is https://github.com/ashbrener/spec-kit-linear-sync

v0.2.0 — drift-aware write-authority

31 May 05:45
81a905d

Choose a tag to compare

Drift-aware write-authority (spec 003). Write-authority now follows the filesystem, not the branch — any worktree may reconcile a spec to Linear. The bridge detects backward-drift (Linear ahead of the worktree you're reconciling from), surfaces it as a warning, and lets you decide (--on-drift=abort|proceed) — it never silently regresses Linear and never blocks the write. Implements the v2.0.0 constitution's amended Principle IV.

Highlights

  • Write from any worktree — a merged spec (feature branch deleted) reconciles cleanly from main; the old branch-gate is gone.
  • Backward-drift surfaced, never blocked — phase-ordering is the signal; commit-recency only corroborates it. A no-op re-run stays silent (idempotent, SC-017).
  • --on-drift=abort|proceed for non-interactive control; interactive runs prompt via /dev/tty.
  • --retroactive is now a deprecated no-op alias (write-from-any-branch is the default).

Hardening (cross-model review, #26)

  • Recency idempotency (SC-017); fail-closed reads under --on-drift=abort; portable _timeout; skew-value validation; deterministic worktree tie-break; dogfood.sh requires --team; end-to-end drift test coverage (SC-014/015/017/018/019).

Also

  • Catalog tag aligned issue-trackerissue-tracking (#27).

Full notes in CHANGELOG.md.

v0.1.2 — worktree hooks + merge detection

29 May 05:06
fb98224

Choose a tag to compare

Two dogfood-surfaced bug fixes, plus the governance groundwork for the upcoming drift-aware authority work.

Fixed

  • Worktree-safe git hooks path (FR-033, #14)install.sh hardcoded .git/hooks, wrong in a git worktree (where .git is a file and hooks live elsewhere). Now resolves via git rev-parse --git-path hooks (honors core.hooksPath). Worktree-based operators' local hooks now install correctly.
  • Detect merged specs from any branch (FR-013/FR-030, #15) — a merged spec's Linear Issue stayed stuck at its pre-merge lifecycle state when reconciled from a non-feature branch. Root cause: gh pr view --json merged used a non-existent JSON field, so merge detection always failed and fell through to a git probe that can't resolve a deleted/non-local branch. Now uses gh pr list --head <branch> --state all; lifecycle resolves to Merged from any worktree.

Changed — Governance

  • Constitution amended to v2.0.0 (#13) — Principle IV redefined to "Write-Authority Follows The Filesystem (Drift-Aware)": any worktree may write; the bridge surfaces backward-drift but does not block. Governance-only this release — the drift-aware reconcile behavior ships when spec 003 is implemented. The extension version line (0.1.2) and the constitution version line (2.0.0) are independent.

Notes

The worktree-hooks fix unblocks a clean re-vendor for operators who installed via --dev from a worktree. Pin to the release tag: specify extension add linear --from https://github.com/ashbrener/spec-kit-linear/archive/refs/tags/v0.1.2.zip.

Full detail in CHANGELOG.md under [0.1.2].

v0.1.1 — install ergonomics

28 May 21:27
0fe74d2

Choose a tag to compare

Install ergonomics redesign (spec 002) plus three dogfood-surfaced reconcile hotfixes.

Headline

The Linear API key is the only thing an operator brings to install. Team and project are discovered interactively — numbered pickers, "Create new project" inline, zero UUIDs surfaced. /speckit.linear.install resolves the key from .env/env/prompt, verifies via the viewer query, and writes the resolved binding to linear-config.yml.

Added — install ergonomics (spec 002)

  • Viewer-driven discovery flow (FR-037..FR-043) — API-key-first, interactive team + project pickers, projectCreate inline
  • Backwards-compat preserved (FR-044/045) — --team/--project flags + tightened --non-interactive
  • Self-install safety guard (FR-046) — refuses --dev from inside the bridge's own checkout
  • Vendored .git/ detection (FR-049)
  • README install commands corrected (FR-047) — archive-ZIP --from URL, --dev path

Fixed — reconcile hotfixes

  • --retroactive actually bypasses the FR-025 write-authority gate (#3)
  • Lazy-create task-phase:N labels for specs with 10+ phases (#4)
  • Guard null relations/labels in the blocks-lookup path (#6)

Validation

  • Constitution v1.0.0 re-check: 8 Conform / 0 Drift
  • Dogfooded live to a Linear workspace during development

Full detail in CHANGELOG.md under [0.1.1].

v0.1.0 — spec-kit ↔ Linear bridge

28 May 15:42
3f6be46

Choose a tag to compare

Mirror every spec on disk into a Linear Issue — the filesystem stays the single source of truth, Linear is the read-only mirror.

The bridge installs via specify extension add linear and attaches to spec-kit's own after_* hooks plus local git hooks plus a GitHub Actions webhook. Every /speckit.* lifecycle command keeps Linear in sync without re-running anything.

Highlights

  • 🔁 Reconcile-based, never event-push. Every reconcile rebuilds Linear from disk. Re-running on unchanged state produces zero churn (SC-002).
  • 🏷 5 commands: /speckit.linear.install, .seed, .push, .status, .pull. Push fires automatically on every spec-kit hook; the other four are operator escape hatches.
  • 📋 Filesystem ↔ Linear mapping: repo → Project, spec → Issue, task phase → sub-issue, tasks → checklist mirror, clarify sessions → comments, lifecycle phase → workflow state + phase:* label.
  • 🧠 Memory block auto-managed on every spec Issue: current phase / branch / worktree(s) / last-touched / GitHub link, rewritten every reconcile.
  • 🔢 Fibonacci [N] story-point markers on task lines roll up to Linear's estimate field (per-phase + spec rollup).
  • 🤖 Agent identity stampingagent:claude / agent:codex workspace labels let you filter the kanban by which AI agent did the work. Sticky — once applied, never removed.
  • 👤 Operator captured at install as Linear assigneeId on every issueCreate (single-write-on-create — manual reassignment in Linear's UI persists).
  • 🚧 Write-authority gate: only the worktree on a spec's feature branch may mutate that spec's Linear Issue. Other worktrees' syncs are read-only for that spec.
  • 🚀 Layer D + Layer E: local reconciler + GitHub Action webhook are independently idempotent. Either alone keeps Linear converging.

Architectural posture

  • No daemons, no databases, no filesystem watchers, no crons. Bash + curl + jq + gh + git only.
  • Filesystem wins every conflict. Unidirectional sync — bridge never writes back to disk.
  • Constitution v1.0.0 ratified — 8 principles. Pre-release audit: 7 Conform / 1 caveat / 0 Drift.

Performance

Workload Measured Target Headroom
N=10 specs cold reconcile 0.992s ≤30s (SC-007) ~30×
N=10 specs hot reconcile 0.840s ≤5s (SC-008) ~6×

Install

specify extension add linear

Then /speckit.linear.install (interactive ceremony) → /speckit.linear.seed (one-shot workspace setup) → use spec-kit as normal.

See README.md for the full adopt-in-3-steps walkthrough.

CI matrix

Bats unit + integration suites pass across:

  • ubuntu-latest × bash 4.4
  • ubuntu-latest × bash 5.2
  • macos-latest × bash 5.2

(macOS × bash 4.4 excluded — bash 4.4 source doesn't compile against Xcode 16.4 SDK; documented inline in .github/workflows/ci.yml.)

Acknowledgements

Designed and dogfooded against the OSH-INFRA Linear workspace, alongside the sibling spec-kit-red-team extension.