Skip to content

Releases

JAM v1.8.0

Choose a tag to compare

@github-actions github-actions released this 10 Sep 08:44
eecdecc

JAM v1.8.0 — asking a command what it does, and being told which limit was hit

What changed

--help no longer runs the command. Measured on a real machine: a person
typed jam setup --help expecting documentation. The setup wizard ran. It
re-registered JAM with two hosts and moved the recorded registration from one
version to another, while they were reading what they thought was a description
of what the command would do.

The cause was narrow and the reach was not. --help was recognised only as a
command in its own right, so a help flag arriving after a subcommand was just
another argument and fell through to the handler. Every mutating path in the
dispatcher was reachable this way:

jam setup --help              ran the wizard
jam update --help             ran the update
jam refresh --help            re-registered
jam uninstall --help          removed the registration
jam auth login --help         started the credential flow
jam runtime use … --help      rewrote the runtime selection
jam jira write-apply … --help applied the plan

The guard is now in the dispatcher, before the switch, and it looks at every
argument rather than the first. The launcher answers runtime before dispatching,
so it has its own.

There is deliberately no per-command list. A list of commands that must be
protected is a list that will be missing the next command somebody adds; the
dispatcher is the one place all of them pass through.

Completeness says which limit was reached. Three situations were collapsing
into two codes, and two of those readings were wrong:

a preview that stopped at page one       PARTIAL_API_RESPONSE   (wrong)
a complete walk that hit the page cap    OUTPUT_BUDGET          (wrong)
a result larger than the token budget    reported in notes      (right)

PARTIAL_API_RESPONSE says Jira answered with less than it was asked for. A
preview is the caller getting exactly what they asked for — one page, on
purpose. OUTPUT_BUDGET says something was dropped to fit a size; the page cap
is about how far the read walked, and nothing was trimmed.

They now have their own names, and the meta carries what a caller needs to act:

PREVIEW_LIMIT      one page by request  →  ask again with scope="complete"
PAGINATION_LIMIT   the safety cap       →  narrow the JQL
moreAvailable      is there more after what you got
returnedCount      how many you got

The third was already right and is now pinned: a result can be complete and
still be larger than you want, and saying so must not turn complete false.

Pagination stays inside JAM. No continuation token reaches the caller
through any field. Handing one out would move paging to the agent, which is the
boundary this exists to hold.

Gate

npm test          582 pass · 0 fail
npm run release:check   clean
CI                ubuntu + windows, node 20 and 22, all green

New fixtures:

help-no-side-effect.test.ts       31  every mutating dispatcher path × --help and -h,
                                      asserting the mutating modules were not called
completeness-semantics.test.ts     7  each situation separately, both at once, and
                                      "no continuation token reaches the caller"

What an independent review checked and did not find

The review looked for a way past the help gate through argument order, through a
subcommand parsing its own flags first, and through the launcher path. It found
none: the gate runs before the switch, and the launcher's own runtime group has
a matching one. It also confirmed no continuation token can escape through a
nested field, and that PREVIEW_LIMIT and PAGINATION_LIMIT cannot be confused
— a preview caps pages at one, so the pagination flag is structurally
unreachable there.

Install / Upgrade

jam update

Moves this machine's registration to the published release. It does not re-plan
the project binding — that is jam setup's job.

First run on a machine with no JAM:

npx --yes @jam-mcp/bootstrap@1.8.0 setup --agent

Agent setup

Unchanged from 1.7.0.

npx --yes @jam-mcp/bootstrap@1.8.0 setup --agent
jam status --json

Compatibility

Node >= 20. The three packages ship in lockstep at 1.8.0 and depend on each
other at that exact version.

No state change on disk. Nothing in ~/.jam is read or written differently.

One behaviour change a caller can see. A command that carries --help or
-h now prints usage and exits 0 instead of running. Any script that relied on
a help flag being ignored will stop doing the thing it was doing — which is the
point, and is the safe direction to fail in.

Two IncompleteReason values are new — PREVIEW_LIMIT and
PAGINATION_LIMIT — and two CompletenessMeta fields are added,
moreAvailable and returnedCount. A consumer that switches exhaustively on
reason will see values it does not know. The old values are not removed;
searches that used to report PARTIAL_API_RESPONSE or OUTPUT_BUDGET for these
two situations now report the new ones instead.

Verified

npx tsc --noEmit        green
npm test                582 pass / 0 fail
npm run build           green
npm run release:check   consistent across manifests, code and docs
CI                      pr-title + ubuntu/windows × node 20/22, all green

Behaviour, in the suite rather than against a live site — each mutating
dispatcher path is driven with the mutating modules replaced by spies, so the
assertion is that they were not called at all:

every mutating command × --help     usage printed, no mutator called
every mutating command × -h         usage printed, no mutator called
the same commands without a flag    the command runs as before
jam help / --help / -h              unchanged

Not run against real Jira: this release changes no Jira interaction. The
completeness work was verified against a fake Jira that pages, which is where
the page-cap and preview boundaries actually live.

Known limitations

The two new meta fields are optional in the type. moreAvailable and
returnedCount are always populated today, because one place builds a search
meta and it fills both unconditionally. The type does not enforce that. A caller
seeing undefined cannot distinguish "nothing more" from "not reported", and a
second construction site could reintroduce the ambiguity silently.

Usage text goes to stdout from the server and stderr from the launcher. The
launcher holds stdout for the MCP protocol on every path; the server has always
written usage to stdout. This release did not unify them.

The reported incident was not reproduced. Re-running jam setup --help
against the broken build would change this machine's registration again. What
was verified is that the old dispatcher structure routes setup --help to the
wizard, and that the new one does not.

MCP/CLI parity was not audited end to end. The --help path is closed on
the CLI side only.

JAM v1.7.0

Choose a tag to compare

@github-actions github-actions released this 08 Sep 04:10
1b7a576

JAM v1.7.0 — writing Jira when the tools are unreachable

What changed

jam jira write-plan and jam jira write-apply. Reads got a shell address
in 1.4.6 and writes did not. The gap shows up in exactly the situation the reads
were opened for: a session whose MCP registry came up in a failed state cannot be
shown the tools — Claude Code has no reload surface for a running session — while
JAM, its credentials and its Jira access are all fine. That session could read
Jira and could not change it.

jam jira write-plan --operation <op> [--key KEY] --input '<json>'
jam jira write-apply <planId>

Nothing here implements a second write path. Both call the same planWrite /
applyWritePlan the MCP tools call, with the same deps, project binding,
whitelist and normalized error codes. The two-call contract is not relaxed for
the shell: planning changes nothing, and apply takes a planId and has no flag
through which a payload could arrive. There is deliberately no jam jira comment
or jam jira close — a shortcut past planning is what the write plane exists to
prevent, and a terminal does not change that. issue.create goes through the
same write-plan rather than getting a command of its own.

Plans now live in a file, shared by both transports. They lived in the server
process, and the ADR said why. The same section named the condition for
revisiting — "if plans ever need to outlive a process" — and write-plan and
write-apply are two processes.

before   in the server process, in memory
after    ~/.jam/write-plans/<planId>.json, read by MCP and the CLI alike

Sharing the store is the point rather than a side effect: a plan made through
the tools can be applied from the shell after the tools stop answering
, which
is the case this release exists for. Single use moved to the filesystem — take
claims a plan by renaming it, so two concurrent applies cannot both hold one.
For comment.add the alternative is two comments.

Integrity is re-derivation, not a signature. Apply reads the plan's own
recorded input, derives the mutation from it again, and refuses with the new
JAM_WRITE_PLAN_TAMPERED when the stored mutation is not what that input
produces. Editing the file to smuggle a different write means editing the input
to match — which is asking JAM to plan that write. The whitelist runs again too,
so an edited input cannot reach a field planning refuses. The check runs after
the revision check: a moved issue is a conflict, not tampering.

docs/decisions/adr-jira-write-plane.md §"Where plans live" is rewritten rather
than quietly contradicted, and it records what was lost as well as what was
gained.

What did not change

The MCP surface. Five tools, the same names, the same inputs, the same meta
semantics: jira_search, jira_context, jira_full, jira_write_plan,
jira_write_apply. The operation set and both whitelists are untouched, and so
is every existing error code.

JAM still has no Execution Mode. That axis belongs to ASC, and a Jira write still
travels ASC's decision path.

Install / Upgrade

jam update

Moves this machine's registration to the published release. It does not re-plan
the project binding — that is jam setup's job.

First run on a machine with no JAM:

npx --yes @jam-mcp/bootstrap@1.7.0 setup --agent

Agent setup

Unchanged from 1.6.0. The agent entry points are the same:

npx --yes @jam-mcp/bootstrap@1.7.0 setup --agent
jam status --json

An agent that has just registered JAM and cannot yet see the tools now has a
complete shell path — reads since 1.4.6, and writes as of this release.

Compatibility

Node >= 20. The three packages ship in lockstep at 1.7.0 and depend on each
other at that exact version.

One state change on disk. Plans are now files under ~/.jam/write-plans/,
created 0600 in a 0700 directory. Nothing else in ~/.jam is touched, and
plans still expire in ten minutes and are still single-use. A plan made by 1.6.0
cannot exist across an upgrade — it was in a process that has since exited — so
there is nothing to migrate.

Verified

npx tsc --noEmit        green
npm test                538 pass / 0 fail / 4 skipped (542)
npm run build           green
npm run release:check   consistent across manifests, code and docs
CI                      pr-title + ubuntu/windows × node 20/22, all green

Against real Jira, on a dedicated health-check issue in the bound project — no
team ticket was touched:

write-plan                             planned, no mutation
write-apply from a second process      applied · verified: true
same planId again                      JAM_WRITE_PLAN_NOT_FOUND, directory empty
plan, move the issue, then apply       JAM_WRITE_CONFLICT
edit the stored mutation, leave input  JAM_WRITE_PLAN_TAMPERED, nothing reached Jira
read → plan → apply, no MCP at all     applied · verified: true

The last line is what this release exists for.

Known limitations

JAM_WRITE_UNCERTAIN was not exercised. Its trigger is an ambiguous
transport failure — a request that may or may not have landed — and that cannot
be produced against real Jira on demand. Only its code path was read. This is
recorded rather than implied because it is the failure whose handling matters
most: retrying it is what turns one comment into two.

--input JSON does not survive PowerShell quoting.

PowerShell   --input '{\"text\":\"...\"}'   →  "--input must be a JSON object."
Git Bash     --input '{"text":"..."}'        →  fine

Not specific to JAM — the same happens to any CLI taking a JSON argument — but
it is a real obstacle in the environment this feature is most needed in, since
the sessions that lose their MCP tools are often on Windows. Use Git Bash, or
match PowerShell's quoting. A --input-file or reading the object from stdin
would remove the problem and is a candidate for a follow-up; neither was added
here to keep this release to the change it describes.

A mutation is now serialized where the machine's user can read and edit it.
That is a real reduction from "forgery is impossible" to "forgery gains
nothing", and it is the price of a write path that survives its transport. See
the ADR for why a signed token was still not the shape.

JAM v1.6.0

Choose a tag to compare

@github-actions github-actions released this 06 Sep 23:32
dbe98c5

JAM 1.6.0 answers to the same lifecycle words as ASC: status, refresh and
uninstall join setup, update and runtime.

What changed

  • jam status. The first place to ask what is going on. It is doctor's
    user-facing role under the name both products use, and it does not
    reimplement the judgement: the same health gate and the same per-axis
    verdicts — credentials, project binding, runtime, registration, live toolset,
    Jira authentication, Jira project access — answer here. jam doctor keeps
    working and names its replacement.
  • jam refresh. Keeps the version and re-registers what this build owns.
    What goes stale in JAM is a registration line, and update is for when a
    newer release exists; refresh is for when the line drifted from the build
    that is already here. Its scope stops there: the project binding,
    ~/.jam/config.yaml, the credentials and every .jira-agent/project.yaml
    are outside it. jam refresh check and jam refresh plan change nothing.
  • jam uninstall. Removes the MCP registrations JAM wrote and the global
    launcher when one is installed. It keeps ~/.jam in full — the project
    bindings, the runtime choice — and the credentials in the OS secret store.
    There is no purge: nothing yet needs a command that destroys those.
  • Help is organised by what a person is doing — Lifecycle, Jira,
    Authentication, agent entry points — with jam serve named for what it is:
    the host's launch command, not something a person types.
  • Nothing is removed before its replacement is verified, in refresh as in
    update, and a registration JAM could not read back is never reported as done.

What did not change

JAM has no execution mode. It is the Jira access layer: no session model, no
approval path, no guard. A Jira write still travels ASC's decision path and
lands through jira_write_plan / jira_write_apply. The two products share a
vocabulary, not a release train — ASC 0.8.0 and JAM 1.6.0 are independent.

Install / Upgrade

jam update

From nothing:

npx --yes @jam-mcp/bootstrap@1.6.0 init

Agent setup

The canonical entry is unchanged:

npx --yes @jam-mcp/bootstrap@1.6.0 setup --agent

Updating an already-configured machine is jam update; making its registration
match the build already here is jam refresh. Neither is setup --agent, which
re-plans the binding and everything else.

Compatibility

  • Node 20 or newer, unchanged — that is what every manifest's engines declares.
    No config or data format change.
  • jam doctor continues to work, printing a deprecation line; jam status is
    the name to use.

Verified

  • CI: build, tests, release checks, packaging, packed smoke.
  • refresh is checked to leave a bare entry alone, to skip a host with no JAM
    entry, to remove before re-registering, and to fail rather than claim success
    when the read-back still shows the old pin.
  • uninstall is checked to touch no path under ~/.jam and to run no removal
    of the person's files.

Known limitations

  • Published acceptance against the 1.6.0 artefact runs after publishing.
  • refresh measures registrations through each host's own CLI; a host whose
    CLI is not on PATH is reported as unavailable rather than assumed empty.

JAM v1.5.0

Choose a tag to compare

@github-actions github-actions released this 06 Sep 09:48
f4c418c

JAM 1.5.0 adds jam update: it moves this machine's registration to the
published release without re-running setup.

What changed

  • jam update. What goes stale in JAM is a line, not a directory — the host
    launches JAM from a registration carrying an exact pin, and a newer JAM on the
    registry changes nothing until that pin moves. Right after 1.4.6 was published
    this machine measured registration: HOST_REGISTRATION_STALE (registered 1.4.5), and the command that fixed it was jam setup --agent, which also
    re-plans the project binding, credentials and everything else. jam update
    does not call it. It proves the new build answers, re-registers the entry at
    that version, reads the registration back, and runs doctor — which is
    config, credentials and one live read.
  • The order never removes first. The published build is verified before the
    registration is pointed at it, so a failed update leaves the machine running
    what it was running.
  • A host with no jam entry is left alone. Registering JAM somewhere it was
    never registered is adoption, and jam setup is where a person says they want
    that.
  • The registry not answering is UNKNOWN, never "up to date".
  • A registration that lands but is not healthy is rolled back to the pin that
    was there.
  • jam update check --json and jam update plan --json change nothing.

Install / Upgrade

jam update

From nothing:

npx --yes @jam-mcp/bootstrap@1.5.0 init

Optional persistent command:

npm install -g @jam-mcp/launcher@1.5.0

Bindings, runtime selection, credentials and ~/.jam/projects.yaml are untouched
by an update.

Agent setup

The canonical entry is unchanged:

npx --yes @jam-mcp/bootstrap@1.5.0 setup --agent

Updating an already-configured machine is jam update, not setup --agent.
JAM updates JAM only — ASC has asc update, and neither calls the other.

Compatibility

  • Node 20 or newer, unchanged. The five-tool MCP surface is unchanged.
  • Additive CLI only: a new update command. Nothing existing changed shape.
  • hostRegistration accepts a version, so a registration can name a release
    other than the running build's — the rest of the argv is the line setup writes.

Verified

  • Build, launcher + server tests, release:check, pack and tarball smoke.
  • Ten new tests hold the order: check runs nothing, a pin that does not answer is
    never registered, remove precedes add, the read-back is what reports success, a
    failing doctor rolls back, and setup is never invoked.
  • Real machine: 1.4.6 → 1.5.0 through the published artefact, with the project
    binding, credentials and runtime mode compared before and after.

Known limitations

  • Downgrade and pinning a specific version are not implemented.
  • A bare global entry updates the global install and keeps the entry; rolling
    that back is a re-install, and the command says so rather than pretending.
  • Live issue.create remains unexercised, as in 1.4.6.

JAM v1.4.6

Choose a tag to compare

@github-actions github-actions released this 06 Sep 06:06
083cbdd

JAM 1.4.6 lets a session read Jira before it can see the tools. A session that
registers JAM cannot be shown the tools it just registered — Claude Code has no
reload for a running session — so jam jira search | context | full addresses the
same reads to the shell. The five-tool MCP surface is unchanged.

What changed

  • jam jira search <jql> [--scope preview|complete], jam jira context <KEY>…
    and jam jira full <KEY>…. Each calls the same application function its MCP
    tool calls, through the same deps, with the same field and pagination policies
    and the same meta — complete, evidenceScope and limitations included.
    Nothing here re-implements a read, and nothing here is a second source of
    truth.
  • A failure is the same normalized error code the tools return. error.code,
    not a stack trace, so a caller reads one contract rather than two.
  • stdout stays one JSON document. Usage and diagnostics go to stderr, and an
    invalid --scope is refused before any request reaches Jira.
  • Reads only. Writing stays behind plan-then-apply, where a person's gate is.

Why

An agent that had just installed JAM was told to wait for its next session. What
it did instead was the substitution JAM exists to prevent: it answered Jira
questions from the code host, the git log and project documents. The tools being
unreachable for one session is a host constraint; answering from the wrong source
is a correctness failure, and this closes it.

Install / Upgrade

npx --yes @jam-mcp/bootstrap@1.4.6 init

Optional persistent command:

npm install -g @jam-mcp/launcher@1.4.6

Existing users: re-run setup. Bindings, runtime selection, host registration and
credentials are untouched.

Agent setup

The canonical entry is unchanged:

npx --yes @jam-mcp/bootstrap@1.4.6 setup --agent

Compatibility

  • Node 20 or newer, unchanged. The five-tool MCP surface is unchanged — same
    names, same input schemas, same results.
  • Additive CLI only: a new jira command group. Nothing existing changed shape.
  • No GitHub/GitLab runtime dependency.

Verified

  • Build, launcher + server tests (488 passing), release:check, pack and tarball
    smoke — green locally and on CI (Ubuntu/Windows × Node 20/22).
  • Six new tests fix the shape: one JSON document, a multi-word JQL staying one
    query, keys read as given, --scope passed through and a bad one refused
    before any read, a normalized error payload, and usage on stderr.
  • Read a real Jira issue through jam jira search from a shell in a session
    whose MCP tools were registered afterwards. Zero mutations.

Known limitations

  • Writes are not addressed to the shell. Creating or updating an issue stays
    a two-step plan-then-apply through the MCP tools, where the person's gate is.
  • This does not make MCP tools appear in a running session. It is the read,
    reachable another way, for the session that cannot see them yet.
  • Live issue.create remains unexercised, as in 1.4.5, for the same reason:
    an unwanted issue on a real board is not worth a disposable fixture.

JAM v1.4.5

Choose a tag to compare

@github-actions github-actions released this 05 Sep 11:51
75e86e9

JAM 1.4.5 makes a Jira reference survivable. Every issue now carries issueId
— Jira's immutable id — beside key, and statusCategory beside status, so
an agent can hold a reference that does not move and can tell whether something
is finished without matching localized status text. It also states the rule
that was missing: a Jira issue key is minted by Jira and is never predicted.

The five-tool MCP surface is unchanged. Everything here is additive output and
costs no extra Jira request.

What changed

  • issueId travels with key. At all three read levels, and on nested
    references — parent, subtasks, and both sides of an issue link — wherever
    Jira supplies one. A key is the current human- and integration-facing
    locator and Jira can move it to another issue; issueId is the issue.
    Nothing is fabricated: a payload without an id leaves the field absent
    rather than empty.
  • statusCategory travels with status. Jira's own machine-readable
    category key, passed through unchanged. status is a workflow-defined,
    localized name, so matching it against words is wrong in some project or
    some language. JAM does not rename Jira's values, does not derive one from a
    status name, and does not turn it into a verdict of its own.
  • Issue-key prediction is forbidden, and gated. AGENTS.md and
    CLAUDE.md carry a mirrored "Jira issue keys" section: never synthesize,
    increment, predict, reserve, or infer the availability of a key; positively
    resolve an exact key against live Jira before reusing it; a key that did not
    resolve is unusable and is not evidence the number is free.
    release:check fails if any of those three claims leaves either file.
  • Writes are pinned to the issue, not to the string. A plan records the
    target's issueId; apply asks the identity question before the revision
    question, and again on the verification read. A key that has come to name a
    different issue stops with JAM_WRITE_CONFLICT before anything is written.
    A direct read returning an issue with no canonical id is refused
    (PARTIAL_RESULT) rather than carried into a plan; list reads are
    unaffected.
  • Both write receipts report issueId, issue.create included — taken
    from the verification read that was already happening.
  • No extra Jira traffic. id and key are properties of the issue
    resource rather than fields, and statusCategory arrives inside the
    status field that was always requested. No nested reference is ever
    fetched to fill in an id.

The reasoning is recorded in
ADR: Jira reference integrity.

Install / Upgrade

npx --yes @jam-mcp/bootstrap@1.4.5 init

Optional persistent command:

npm install -g @jam-mcp/launcher@1.4.5

Existing users: re-run setup. Bindings, runtime selection, host registration
and credentials are untouched.

Agent setup

The canonical entry is unchanged:

npx --yes @jam-mcp/bootstrap@1.4.5 setup --agent

Compatibility

  • Node 20 or newer, unchanged. The five-tool MCP surface is unchanged — same
    names, same input schemas.
  • Additive JSON only: issueId and statusCategory on read results and on
    nested references, issueId on the plan and apply receipts. A consumer that
    ignores them sees the contract it saw before.
  • No GitHub/GitLab runtime dependency. JAM does not create branches, read
    commits or manage pull requests, and gains none of that here.

Verified

  • Build, 39 launcher + 493 server tests, release:check, pack and tarball
    smoke — green locally on Windows and on CI (Ubuntu/Windows × Node 20/22).
  • Live read acceptance against a real Jira project, read-only: issueId
    equals Jira's raw id and is not the key; statusCategory equals the raw
    statusCategory.key and is not the status name; the same issue read through
    two endpoints reports the same id; 20 issues and 20 nested references all
    carried identity in one Jira request. Zero mutations.
  • A key that does not resolve comes back in meta.missingKeys with
    complete: false, and nothing in the result says or implies the number is
    free.
  • The documentation gate was proven by removing a phrase and watching
    release:check fail.
  • Consumer compatibility: an existing MCP consumer's projection was driven
    with real output from this release and is unchanged in shape — the additive
    fields are ignored, which is the intended outcome.

Known limitations

  • Live issue.create was not exercised. Creating an issue is not
    reversible and a disposable fixture is not worth an unwanted issue on a real
    board, so the create path's identity receipt is covered by unit and
    integration tests rather than by a live mutation.
  • Nested identity is as good as Jira's payload. Where a response shape
    does not carry an id for a nested reference, the field is absent. JAM will
    not fetch the reference to fill it in — that would trade a correctness fix
    for an N+1.
  • No Git or SCM enforcement, deliberately. JAM removes the premise the
    mistake rests on and states the correct procedure where an agent reads it.
    Guarding branches, commits and pull requests belongs to a control plane
    above JAM, which can build it on the identity JAM now returns.
  • Subtask creation is still out of scope. issue.create takes no parent;
    that is a write-capability change with its own schema and verification
    questions.

JAM v1.4.4

Choose a tag to compare

@github-actions github-actions released this 01 Sep 07:30
6125662

JAM 1.4.4 makes project setup deterministic when a machine carries old
settings, and stops "mixed" credentials from reading as a fault. Two field
reports drove it: an operator had to hand-edit ~/.jam/projects.yaml before
--project would take effect, and a working credential split across the OS
store and one exported token was investigated as if it were broken.

What changed

  • --project <KEY> decides the run. It already beat a personal binding,
    JAM_PROJECT_KEY and a legacy preset entry; that is now pinned by tests,
    and a stale binding is repaired through the ordinary replace plan. Nothing
    has to be deleted by hand first.

  • The repository's committed key is never overwritten silently. It used
    to win over --project while being reported as explicit, so the flag
    looked honoured when a different key was in use. A disagreement now stops:

    {
      "status": "user_action_required",
      "code": "JAM_PROJECT_KEY_CONFLICT",
      "requested": { "key": "PROJECT", "source": "explicit" },
      "existing":  { "key": "OTHER",   "source": "repository" }
    }

    No change is applied over a conflict, in any entry point. Which Jira
    project a repository belongs to is the team's decision.

  • Key provenance is reported. Sources are explicit, repository,
    env, binding or preset, and a plan carries project.keySource.

  • Credential sources, per field. describe() and auth status --json
    carry a sources map naming which source supplied JIRA_BASE_URL,
    JIRA_EMAIL and JIRA_API_TOKEN. Names only — no value is ever printed.

  • doctor --json gains a per-axis diagnosis: credentials,
    projectBinding, runtime, registration, liveToolset,
    jiraAuthentication, jiraProjectAccess. A failure is attributed instead
    of guessed at, and mixed is a WARNING on the credentials axis — never a
    failure on its own. Whether Jira accepts the credentials stays on its own
    axis.

Install / Upgrade

npx --yes @jam-mcp/bootstrap@1.4.4 init

Optional persistent command:

npm install -g @jam-mcp/launcher@1.4.4

Existing users: re-run setup. Bindings, runtime selection, host registration
and credentials are untouched — a stale binding is repaired in place.

Agent setup

The canonical entry is unchanged; --project is what became reliable:

npx --yes @jam-mcp/bootstrap@1.4.4 setup --agent --project PROJECT

Compatibility

  • Node 20 or newer, unchanged. The five-tool MCP surface is unchanged.
  • Additive JSON: project.keySource, requested/existing on a conflict,
    sources on credential descriptions, diagnosis on doctor.
  • One new stop: JAM_PROJECT_KEY_CONFLICT. It fires only where a run
    previously used a different key than the flag asked for.

Verified

  • server 475 + launcher 39 tests, typecheck, build, release:check, pack and
    tarball smoke — green locally on Windows and on CI (Ubuntu/Windows ×
    Node 20/22).
  • Live matrix against the published artefact: stale binding replaced
    OLDKEY → the requested key; a disagreeing repository key stopped with
    JAM_PROJECT_KEY_CONFLICT and zero changes; an agreeing repository key
    reported keySource: repository.
  • Real project acceptance: setup --agent --project <KEY> reached ready
    with all seven diagnosis axes OK, including a live Jira read, and no
    credential value in any output.
  • A mixed credential (store plus one exported token) reported WARNING with
    its per-field sources while the overall status stayed ready.

Known limitations

  • A repository conflict is deliberately not auto-resolvable: JAM reports both
    sides and stops, and someone has to decide with the team.

JAM v1.4.3

Choose a tag to compare

@github-actions github-actions released this 31 Aug 03:22
5b8ad9e

JAM 1.4.3 makes the fresh Windows install actually work end to end. Every
defect found in a Windows field verification on a real project (2026-08-31) is fixed:
a fresh machine now always receives an MCP registration that runs, apply's
status stops contradicting itself, and Node 24 deprecation noise is gone from
every JSON surface.

What changed

  • npx PATH contamination (release blocker) — under
    npx --yes @jam-mcp/bootstrap@<version>, npx prepends its cache's
    node_modules/.bin to PATH, which contains a jam shim that vanishes when
    npx exits. The "does this machine have a persistent jam" measurement ran
    through that PATH, answered yes on every fresh machine, and setup then
    registered a bare jam serve that died immediately. The measurement now
    strips package-runner entries (_npx, node_modules/.bin) first: fresh
    machines get the always-runnable npx pin, and bare registration happens only
    over a real persistent install.
  • Apply status honesty — setup apply used to answer
    already_configured alongside changesApplied: true. Executed changes now
    answer applied.
  • DEP0190 removal — every spawnSync(cmd, args, {shell: true}) site
    (host probes, live toolset, npm probe, launcher dispatch, dev scripts) now
    validates bare tokens and joins the argv itself; cmd.exe metacharacters are
    refused instead of concatenated. --json outputs are clean of warnings.

Install / Upgrade

npx --yes @jam-mcp/bootstrap@1.4.3 init

Existing users: re-run setup; a stale or dead registration is replaced in
place. Bindings, runtime selection and credentials are untouched — verified
in-place against a live operating setup.

Agent setup

No change to the canonical entry:

npx --yes @jam-mcp/bootstrap@1.4.3 setup --agent

Compatibility

  • Node 20 or newer, unchanged. The five-tool MCP surface is unchanged.
  • setup apply may now answer applied where it previously (wrongly) said
    already_configured after executing changes.

Verified

  • server 455 + launcher 39 tests, release:check, pack and tarball smoke —
    green locally on Windows and on CI (Ubuntu/Windows × Node 20/22).
  • Live Windows reproduction of the npx-PATH defect: with a contaminated PATH
    and no global jam, setup plan now proposes the npx pin (previously bare
    jam serve).
  • Published-registry fresh setup on Windows with zero manual installs:
    registered npx --yes @jam-mcp/launcher@1.4.3 serve boots, doctor --json
    reports ready on all three axes with 0 bytes on stderr, and the three read
    tools answer live Jira with meta.complete: true.
  • Non-mutating jira_write_plan exercised against live Jira (planId issued,
    nothing applied); structured error path confirmed.
  • In-place re-apply over an existing operating setup: already_configured,
    binding/registration/runtime preserved.

Known limitations

  • The GitHub Release for this version was created by the tag-triggered
    workflow of its day; the successor pipeline separates publish from
    finalization so acceptance always precedes the tag.

JAM v1.4.2

Choose a tag to compare

@github-actions github-actions released this 30 Aug 12:39
0b0a23d

JAM 1.4.2 stops treating a healthy persistent installation as a defect. A bare
jam serve registration is now judged by measuring the executable it actually
runs, and setup's repair respects a persistent install instead of rewriting it
back to an npx pin.

What changed

  • Bare-registration judgement — a jam serve entry carries no version in
    the host's listing, so JAM asks the executable (jam runtime status --json)
    and compares that. Previously a bare entry was permanently misjudged stale.
  • Persistent-respecting repair — when the measured global launcher is
    exactly this release, repair registers bare jam serve; otherwise it keeps
    the npx pin fallback. Repair no longer recreates the npx cache structure on
    a machine that deliberately installed the launcher.

Install / Upgrade

npx --yes @jam-mcp/bootstrap@1.4.2 init

Existing users: re-run setup once; a mis-judged bare registration is repaired
in place. Bindings, runtime selection and credentials are untouched.

Agent setup

No change to the canonical entry:

npx --yes @jam-mcp/bootstrap@1.4.2 setup --agent

Compatibility

  • Node 20 or newer, unchanged. The five-tool MCP surface is unchanged.

Verified

  • release:verify green on Ubuntu and Windows against Node 20 and 22 (CI),
    including new regression tests for the bare-entry judgement.
  • Published via the Trusted Publishing workflow; registry verification and the
    published smoke ran inside it.

Known limitations

  • On a machine where jam resolves only through a package runner's ephemeral
    PATH, the persistent judgement could still be misled — fixed in 1.4.3.
  • This body was restored after the fact (2026-08-31) from the recorded
    procedure and commit history; it claims no verification beyond those records.

JAM v1.4.1

Choose a tag to compare

@colosair colosair released this 30 Aug 09:33
d6e6192

JAM 1.4.1 makes jam doctor answer the question that actually matters on a
half-upgraded machine: not just "is this package current", but "what does the
host registration launch, and what does that process really serve".

What changed

  • Doctor's three axes — package (the runtime this machine would run),
    registration (what the host CLIs have registered for this user, stale pins
    detected by version), and live (the registered command is actually
    launched and its tool list compared). A stale pin serving an older tool set
    no longer reads as ready.
  • Release smoke hardening: EPIPE fix in the published smoke, and the smoke now
    verifies the real consumer path.

Install / Upgrade

npx --yes @jam-mcp/bootstrap@1.4.1 init

Existing users: re-running setup repairs a stale registration; bindings and
credentials are untouched.

Agent setup

No change to the canonical entry:

npx --yes @jam-mcp/bootstrap@1.4.1 setup --agent

Compatibility

  • Node 20 or newer, unchanged. The five-tool MCP surface is unchanged.
  • doctor --json output gains the axes block (additive).

Verified

  • release:verify green on Ubuntu and Windows against Node 20 and 22 (CI).
  • Published via the Trusted Publishing workflow; registry verification and the
    published smoke ran inside it.

Known limitations

  • This body was restored after the fact (2026-08-31) from the recorded
    procedure and commit history; it claims no verification beyond those records.