Skip to content

Version Packages#213

Open
github-actions[bot] wants to merge 1 commit into
mainfrom
changeset-release/main
Open

Version Packages#213
github-actions[bot] wants to merge 1 commit into
mainfrom
changeset-release/main

Conversation

@github-actions

@github-actions github-actions Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.

Releases

@kurrent/gaffer@0.5.0

Minor Changes

  • 8aec336: Breaking: gaffer.toml gains a [database_config] section for node-level engine settings, and the top-level compilation_timeout / execution_timeout keys move into it. A file that still sets them at the top level now fails to load, with a message pointing at the new section.

    [database_config] declares the engine configuration expected on a deployment target:

    • max_state_size (newly exposed) caps a projection's serialized state in bytes, defaulting to the server's 16 MiB. It is enforced on local runs, so a projection that would exceed the cap faults locally, catching state bloat before deploy.
    • compilation_timeout and execution_timeout are declaration only: gaffer records them for deploy-time configuration checks but does not apply them to local runs, since a wall-clock budget measured on a dev machine isn't comparable to the server's. To bound how long a local projection may run before gaffer treats it as hung, set the GAFFER_TIMEOUT_MS environment variable (default 5000ms). A per-[[projection]] execution_timeout is likewise declaration only and no longer affects local runs.
  • 331f061: Breaking: gaffer.toml now rejects absolute entry and fixtures.<name> paths at load time. Previously an absolute path (e.g. entry = "/etc/passwd", or a Windows drive-letter form like C:\...) slipped past validation while the scaffold write path already rejected it. Both surfaces now enforce the same rule: paths must be relative to the project root and must not escape it.

Patch Changes

  • 9b1f7e8: The Go runtime bindings no longer risk a rare fatal crash (invalid pointer found on stack) under GC pressure. The runtime's integer session handles could appear in pointer-typed stack slots during FFI calls; if the GC moved the stack while a callback was running mid-call, the process aborted. Handles now stay integer-typed end-to-end on the Go side, with all casting done in C shims. The crash could hit anything embedding the bindings, including the CLI.

  • ee1f52e: Projection errors that reach the CLI wrapped in another error now keep their original error code and diagnostics. Previously a wrapped feed error was classified as unexpected-error and its diagnostics were dropped.

  • 733e9d1: gaffer deploy and gaffer status warn when the target node's live engine settings diverge from a declared [database_config]: one line per differing knob, read from the node's options endpoint. Fixtures and local runs assumed the declared values, so a server enforcing a different max_state_size or timeout is visible before it bites. The check is advisory: a server that doesn't expose its options, or refuses the read, skips it silently, and a non-positive max_state_size declares the engine default rather than a value.

    gaffer status --json now emits an object: a projections array (the previous per-projection entries) plus a configDrift array of {"knob", "server", "local"} when the target diverges. Machine consumers see the divergence without a second call. gaffer deploy --json is unchanged; its warning prints on stderr, keeping the stdout payload clean while CI logs still show it.

  • f1c46c3: gaffer dev --debug no longer hangs when a Restart arrives as the session is tearing down; the restart returns cleanly during shutdown instead of leaving the debug adapter's read goroutine waiting forever.

  • f118249: gaffer deploy gains --dry-run and a stable exit-code contract for CI. --dry-run shows the plan and applies nothing. The exit code is now 0 succeeded or nothing to do, 1 an error, and 2 changes are pending (--dry-run only). A new 3 means refused by a guardrail: confirmation was needed but there was no terminal or --yes, or --no-validate was used against production.

    --dry-run reuses the same per-projection plan output as a confirmed deploy, and its --json is the same array shape, so a pipeline can branch on exit 2 or parse the would-be outcomes. The guardrail exit code 3 also applies to recreate and the operate verbs when they can't confirm non-interactively. A production --no-validate refusal now prints its reason instead of exiting silently.

  • ff67802: gaffer deploy now measures its per-projection verdict column by terminal display width, so projection names with multi-byte or full-width characters no longer over-pad the column and misalign the verdicts.

  • 6ef7402: gaffer deploy creates or updates projections on an environment from gaffer.toml: it creates the ones not yet on the server, updates the ones whose definition changed, and skips the ones already in sync (matched by content hash). The emit flag is always sent explicitly, so an update never clears it.

    With no argument it deploys every projection in gaffer.toml; name one to deploy just it. A change to engine version or track-emitted-streams can't be applied in place (it would mean recreating the projection and dropping its state), so gaffer deploy reports it and leaves the projection untouched. On a terminal it shows live per-projection progress; pass --json for machine-readable output.

  • 0614520: gaffer deploy's interactive view no longer drops the last projection's result line when the run finishes. The final row's commit and the program quit now run as one ordered step, so the verdict is always flushed before the view tears down (a single-projection deploy previously showed only the summary).

  • 69aceed: gaffer deploy now flags a projection whose deployed definition was changed outside gaffer since its last deploy, so a deploy doesn't silently revert an out-of-band change.

    • The plan preview and the non-interactive (--yes) apply warnings show a caution ("<name> was changed outside gaffer since its last deploy; deploying overwrites it"), naming the tool when another tool made the change.
    • gaffer deploy --json carries externalChange: true on the affected item, alongside logicChange, so CI can alert.

    Gaffer is the canonical source of truth, so it still deploys - the drift is surfaced, not refused. Degrades silently against a KurrentDB without the deploy-metadata field.

  • 1edbb21: gaffer deploy now plans the whole run before touching the server and confirms before applying. It shows what would change per projection (created / updated / skipped / refused) against the target's reported cluster name, then asks before writing. --yes skips the prompt; without a terminal (or with --json) it won't apply unconfirmed, so pass --yes in scripts. An update whose deployed projection is currently faulted is flagged, since updating won't clear the fault.

    A server that reports itself as production gets a louder confirmation and refuses --no-validate. Production is read from the server's own $server-info, never inferred from the environment name, so a connection that points at production is guarded even if its env is labelled otherwise. Databases that don't report production status are unaffected.

  • 36cd18b: gaffer deploy now records tool metadata on every projection it creates or updates, so a projection carries who deployed it and from where: the tool (Gaffer) and version, the operation, the source revision, and the acting identity. It follows a shared convention that other KurrentDB tools can write and display.

    • revision defaults to the project's git commit (suffixed +changes when the working tree is dirty); set GAFFER_REVISION in CI to record the canonical commit.
    • actor defaults to the identity gaffer connects as (the basic-auth user or OAuth client), omitted for an anonymous connection; set GAFFER_ACTOR in CI to record the pipeline identity.

    The metadata rides on the projection's definition event and is best-effort: against a KurrentDB that predates the feature it is silently ignored and deploy behaves exactly as before.

  • a59afe0: gaffer deploy's plan preview now lists each projection, not just totals. Every projection that would change shows a verdict - create, update, rebuild, refused, or failed - and a dimmed detail column carrying the refusal reason or the failure error in full. In-sync projections stay a count only, so unchanged ones don't drown the signal.

  • cc92ece: gaffer deploy now compiles every projection before sending anything to the server. If any fails to compile, or compiles but carries errors that would fault on the server (such as a quirk that reproduces an upstream engine crash), the whole deploy is refused up front, so a bad projection can't leave the earlier ones already applied. The check runs locally, before connecting, and --no-validate skips it.

  • 1206961: gaffer deploy now treats a changed projection query as a logic change. The new code may read already-processed events differently, so the accumulated state could be wrong. By default deploy keeps the checkpoint, applies the update, and flags the change in the plan. Pass --reset-on-logic-change to rebuild instead: each logic-changed projection is stopped, updated, reset to the beginning, and restarted so it reprocesses from zero with the new logic. An emitting projection re-emits on a rebuild and may duplicate into its target streams, so the plan warns and points at gaffer recreate --delete-emitted for a clean-emit rebuild.

    A continued logic change shows as logicChange: true on its --json item, so CI can alert on it. A change to engine version or track-emitted-streams still can't be applied in place; deploy now points at gaffer recreate rather than just refusing.

  • ad83f81: gaffer diff <projection> compares a projection's local definition against what's deployed on KurrentDB and reports its state: in sync, drifted, not deployed, or untracked.

    When the query differs, the source is shown in an external diff viewer. By default this is git diff --no-index; set GAFFER_EXTERNAL_DIFF to override. Pass --json for machine-readable output.

  • b5cbc4e: gaffer diff renders the query source diff itself instead of shelling out to an external viewer. Every line of both sides is shown with the changes marked in place: dual line-number gutters, +/- colouring, and the span that changed within a line highlighted. The diff is computed on the same canonical form as the drift verdict, so it always matches the +N -M stat that gaffer diff and gaffer status report. It now works without git installed, when piped, and in CI.

    Set GAFFER_EXTERNAL_DIFF to open an external viewer instead (e.g. git diff, delta, difft); it is no longer the default path.

  • ce0de95: Projection info now reports whether a projection writes events. ProjectionInfo gains an emitsEvents flag, true when the projection calls emit, linkTo, linkStreamTo, or copyTo. It is detected on every compile from the source, so consumers no longer need to inspect shape counts.

    gaffer info shows it ("Emits events: yes"); gaffer info --json and the MCP get_projection_info and validate_projection tools include emitsEvents; the testing library exposes it as info.settings.emitsEvents.

  • 36ee512: gaffer rollback <projection> <hash> rolls a deployed projection back to a prior version from its history, stamped operation: rollback in the deploy ledger. The target is named by its content hash from gaffer history; any unique prefix of 4 or more characters works. It confirms first with the current-to-target query diff (--yes skips). The apply is in place: processing continues from the current checkpoint, and local files stay untouched, so gaffer diff shows the rollback as drift until local is reconciled. A version differing in engine version or emitted-stream tracking is refused, pointing at gaffer recreate.

    The gaffer history timeline gains r: it opens the same confirm as a modal for the selected entry, applies on y, and reloads the timeline so the new rollback entry appears on top.

  • eeaff5f: Event-processing errors under engine_version 2 now carry the quirk.handlerError.wedgesOnV2 (error severity) diagnostic. On deployed V2, an exception thrown while processing an event never faults the projection. It wedges silently: status stays Running while processing and persistence have stopped, and nothing is logged. Gaffer keeps faulting the event locally, which is the behaviour V2 should have, and the diagnostic rides the error to explain the divergence. It fires for any event-processing throw (handler, state load, $created, $deleted, state serialization, timeout); a throwing partitionBy is exempt because the server computes partition keys on its read loop, which faults properly.

  • 15a6296: gaffer history <projection> shows a deployed projection's history: every operation on it, newest first, with who made it and how.

    • On a terminal it opens an interactive timeline: a scrolling list on the left, the selected entry's full detail on the right, and a footer naming the projection and target. Navigate with / (or j/k), g/G, PgUp/PgDn; q or Esc quits. Older entries page in as you scroll.
    • Each entry is one write to the projection. One carrying gaffer metadata shows its operation (deploy, rollback, reset), the actor, and the source revision. One without is attributed by what changed: edited-externally when the definition changed outside gaffer, changed-by (with the tool named) for another tool's write, enabled/disabled for a lifecycle change, reconfigured when a checkpoint or performance setting moved, rewritten for an identical redeploy, or created/deleted.
    • A content hash identifies each deployed definition, so a reverted definition is recognisable at a glance: the timeline draws a revert as a branch off the live line, linking the restored definition back to the earlier one it matched (nested reverts included).
    • Piped or with --json it prints the latest entries instead (--limit, default 100, or --all). Each --json entry carries the full content hash, its classification and flags, the tool metadata, and any configuration knobs that moved.

    Against a KurrentDB without the deploy-metadata field it degrades to the history with timestamps and content hashes only.

  • bf1f2ef: gaffer history gains d: a diff of the selected entry against the version before it, shown in an overlay on the timeline. It answers "what changed at this entry" the way git show does. The previous content version is the baseline (state changes are skipped; their definition is identical), the first version diffs from empty, and a state-change entry reports "no definition change".

    The diff uses the same aligned renderer and tints as gaffer diff, with any engine version, emit, or tracking change named above it. The arrow keys keep scrubbing the timeline underneath, so the diff re-renders entry by entry, walking a definition's evolution in place. PgUp/PgDn scroll a long diff; esc, d, or q closes back to the timeline. A baseline on an older page is fetched automatically.

  • 95a5410: gaffer dev --json now exits non-zero if it fails to write its output stream (for example a broken pipe to the editor), instead of silently finishing with a truncated stream.

  • 15602f4: gaffer status and gaffer diff are now ledger-aware, reading the tool metadata gaffer stamps on deploy to say more than untracked or drifted.

    • Ownership of a projection on the server but not in local config: orphan (gaffer deployed it, now gone from gaffer.toml - a deletion candidate) or plain untracked, with the deploying tool named when its metadata is present. --json reports this as owner, including foreign for a projection another tool manages.
    • Drift attribution of an in-config projection that differs from what's deployed: local ahead (you've edited local since your deploy) or changed externally (a tool or a direct write changed the server since). --json splits the latter into changed-by-tool and changed-server.

    Both surface in the status table and detail and in gaffer diff. The status table gains LAST DEPLOY and DEPLOYED VIA columns, and naming a projection (or running gaffer diff) shows the deploy provenance behind it: when, the tool and version, the deployer, and the source revision. The last-deploy date comes from the event itself, so it shows even for a projection with no tool metadata. In --json: owner, attribution, a top-level lastDeployed timestamp, and lastWrite (the tool and actor). Against a KurrentDB without the deploy-metadata field it degrades to the previous behaviour.

  • 189eebd: The MCP server gains deploy_apply, so an assistant can deploy projections from gaffer.toml like gaffer deploy:

    • The same all-or-nothing compile and diagnostics preflight, with no validation bypass.
    • The same per-item results as gaffer deploy --json, and every write stamped operation: deploy in the ledger.
    • A production deploy requires a confirmation answered through the MCP client (elicitation). The prompt names the changed projections, rebuilds, out-of-band overwrites, faulted targets, and any [database_config] divergence.
    • A plan containing resetOnLogicChange rebuilds destroys state, so it always asks; on production that confirmation requires typing the environment name.
  • 33ffb38: The MCP server gains read-only deploy visibility, mirroring the CLI's machine output:

    • deploy_status shows each projection's runtime state and drift verdict on an environment, plus any [database_config] divergence, like gaffer status --json.
    • deploy_plan previews what a deploy would change without applying anything, like gaffer deploy --dry-run --json.
    • deploy_history reads a projection's per-deploy audit log with paging, like gaffer history --json.

    All three accept an env argument and default to the default environment. Applying changes stays in the CLI, behind its confirmation gates.

  • 15cc888: The MCP server gains the operate verbs, so an assistant can manage a deployed projection's lifecycle with a human in the loop:

    • deploy_pause / deploy_resume / deploy_abort mirror gaffer disable / enable / disable --abort.
    • deploy_recreate rebuilds from local config like gaffer recreate, gated on the compile and diagnostics preflight, and stamps operation: recreate in the deploy ledger.
    • deploy_rollback redeploys a prior version by content hash from deploy_history, like gaffer rollback, and stamps operation: rollback.
    • deploy_delete mirrors gaffer delete, including deleteEmitted.

    Writes against a server that reports itself as production require a confirmation answered through the MCP client (elicitation); the assistant cannot answer it. The prompt front-loads PRODUCTION [env.<name>]: and states each verb's consequence. Recreate and delete destroy state with no undo, so they ask every time; on production their confirmation requires typing the projection name. A client without elicitation support cannot perform gated writes; the refusal names the CLI command to run instead. deploy_status and deploy_plan now also echo the resolved target and production flag.

  • 73af704: gaffer enable, gaffer disable, and gaffer delete manage deployed projections on an environment, named directly (they need not be in gaffer.toml).

    • gaffer enable <projection> starts a projection so it resumes from its last checkpoint.
    • gaffer disable <projection> stops it, writing a final checkpoint; --abort skips that checkpoint so a later enable replays from the last one. Disabling is recoverable, so it confirms only against production.
    • gaffer delete <projection> removes the projection with its state and checkpoint streams, keeping emitted streams unless --delete-emitted is passed. It always confirms, and disables the projection first since the server won't delete an enabled one.

    --yes skips the confirmation; without a terminal (or with --json) a guarded verb won't proceed unconfirmed. Production gets a louder confirm and is read from the server's $server-info, never the env label.

  • b2071d0: A per-projection config error (e.g. track_emitted_streams with engine_version 2) no longer blocks every command. Previously one misconfigured projection failed gaffer.toml loading outright, so gaffer info <good-projection> died on an unrelated projection's error. Now config validation splits into structural checks (environments, duplicate names) that stay fatal, and per-projection checks that are deferred; a bad projection only blocks operations on itself. The inspection commands (status, diff, info) show it as invalid through one shared rendering; deploy refuses just that one; recreate and the operate verbs fail only when you name it. Mirrors the per-projection degradation already used for compile errors.

  • 6571975: gaffer recreate now stamps its rebuild in the deploy ledger, so gaffer history attributes it to gaffer instead of showing anonymous lifecycle steps. The create carries operation: recreate with the usual tool, actor, and source revision.

    gaffer history shows a recreate as a single entry: the disable and delete writes it performs are folded into the recreate row, and the detail panel notes the projection was reprocessed from zero. --json keeps every write as its own entry, with the create's kind set to recreate.

  • 42b7612: gaffer recreate <projection> destroys and rebuilds a deployed projection from local config: stop it, delete it (with its state and checkpoint streams), and create it fresh, reprocessing from zero. It applies a create-only change that deploy can't make in place (engine version, track-emitted-streams), or rebuilds a wedged projection an in-place reset can't fix. The projection is compiled before anything is deleted, so a broken local definition can't leave you with nothing to rebuild; --no-validate skips that check (production refuses it). It always confirms, more prominently against production, with --yes for non-interactive use. --delete-emitted also wipes the emitted streams so the rebuild doesn't re-emit duplicates.

  • 6625608: gaffer status shows the runtime state of projections on an environment and how they compare to local config: running, stopped or faulted, progress, and whether each is in sync, drifted, not deployed, or untracked.

    With no argument it lists every local and deployed projection as a table; name a projection for its detail. Pass --json for machine-readable output.

  • 6602c5f: gaffer status and gaffer diff no longer abort when a local projection fails to compile. A compile error is now a per-projection condition, not a whole-command failure. gaffer status shows the broken projection as invalid and still renders the rest of the table with their real runtime state and drift. gaffer diff still shows the source diff, engine version, and track-emitted-streams, marking emit unknown because deriving it needs a successful compile. Both exit 0, and the compile error is shown so you know what to fix.

  • e59a851: track_emitted_streams with engine_version 2 is now reported as a diagnostic rather than a config-load error. The runtime emits quirk.trackEmittedStreams.unsupportedOnV2 (error severity) off the resolved definition, whether the flag comes from gaffer.toml or options({ trackEmittedStreams: true }) in the source. This matches how the other V2 incompatibilities (bi-state, outputState) already surface.

    gaffer info, gaffer dev, and gaffer diff now compile such a projection and show its full analysis plus the flag, instead of failing with a bare config error. gaffer deploy and gaffer recreate still refuse it at preflight (recreate before deleting anything), and the MCP validate tool reports it invalid with the diagnostic. The projection session no longer throws on the combination.

@kurrent/gaffer-runtime@0.3.1

Patch Changes

  • ce0de95: Projection info now reports whether a projection writes events. ProjectionInfo gains an emitsEvents flag, true when the projection calls emit, linkTo, linkStreamTo, or copyTo. It is detected on every compile from the source, so consumers no longer need to inspect shape counts.

    gaffer info shows it ("Emits events: yes"); gaffer info --json and the MCP get_projection_info and validate_projection tools include emitsEvents; the testing library exposes it as info.settings.emitsEvents.

  • eeaff5f: Event-processing errors under engine_version 2 now carry the quirk.handlerError.wedgesOnV2 (error severity) diagnostic. On deployed V2, an exception thrown while processing an event never faults the projection. It wedges silently: status stays Running while processing and persistence have stopped, and nothing is logged. Gaffer keeps faulting the event locally, which is the behaviour V2 should have, and the diagnostic rides the error to explain the divergence. It fires for any event-processing throw (handler, state load, $created, $deleted, state serialization, timeout); a throwing partitionBy is exempt because the server computes partition keys on its read loop, which faults properly.

  • e59a851: track_emitted_streams with engine_version 2 is now reported as a diagnostic rather than a config-load error. The runtime emits quirk.trackEmittedStreams.unsupportedOnV2 (error severity) off the resolved definition, whether the flag comes from gaffer.toml or options({ trackEmittedStreams: true }) in the source. This matches how the other V2 incompatibilities (bi-state, outputState) already surface.

    gaffer info, gaffer dev, and gaffer diff now compile such a projection and show its full analysis plus the flag, instead of failing with a bare config error. gaffer deploy and gaffer recreate still refuse it at preflight (recreate before deleting anything), and the MCP validate tool reports it invalid with the diagnostic. The projection session no longer throws on the combination.

@kurrent/projections-testing@0.2.2

Patch Changes

  • ce0de95: Projection info now reports whether a projection writes events. ProjectionInfo gains an emitsEvents flag, true when the projection calls emit, linkTo, linkStreamTo, or copyTo. It is detected on every compile from the source, so consumers no longer need to inspect shape counts.

    gaffer info shows it ("Emits events: yes"); gaffer info --json and the MCP get_projection_info and validate_projection tools include emitsEvents; the testing library exposes it as info.settings.emitsEvents.

  • Updated dependencies [ce0de95]

  • Updated dependencies [eeaff5f]

  • Updated dependencies [e59a851]

    • @kurrent/gaffer-runtime@0.3.1

@kurrent/gaffer-runtime-darwin-arm64@0.3.1

@kurrent/gaffer-runtime-darwin-x64@0.3.1

@kurrent/gaffer-runtime-linux-arm64@0.3.1

@kurrent/gaffer-runtime-linux-x64@0.3.1

@kurrent/gaffer-runtime-win32-x64@0.3.1

@kurrent/gaffer-darwin-arm64@0.5.0

@kurrent/gaffer-darwin-x64@0.5.0

@kurrent/gaffer-linux-arm64@0.5.0

@kurrent/gaffer-linux-x64@0.5.0

@kurrent/gaffer-win32-x64@0.5.0

@github-actions github-actions Bot requested a review from a team as a code owner June 18, 2026 15:06
@github-actions github-actions Bot force-pushed the changeset-release/main branch 19 times, most recently from 226a130 to 954e742 Compare June 24, 2026 11:15
@github-actions github-actions Bot force-pushed the changeset-release/main branch 10 times, most recently from d7947f1 to 94d25cf Compare June 26, 2026 15:11
@github-actions github-actions Bot force-pushed the changeset-release/main branch 16 times, most recently from 5244c07 to cce8b9a Compare July 3, 2026 11:07
@github-actions github-actions Bot force-pushed the changeset-release/main branch 7 times, most recently from 88c5926 to ae53d0e Compare July 6, 2026 13:54
@github-actions github-actions Bot force-pushed the changeset-release/main branch from ae53d0e to 93c6d4c Compare July 6, 2026 14:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants