## slothflowlabs/duckle — v0.7.3…v0.7.4

_153+ commits._

### Features
- **feat(sharepoint): read and write SharePoint Server lists and libraries over NTLM** (aa15ce4)
- **feat(access): read and write Microsoft Access databases** (72bdd46)
- **feat(cloud): read S3 and Azure with the identity the run has, no key** (883ea14)
- **feat(editor): build a pipeline from a pasted SELECT, one step per CTE** (313f874)
- **feat(runner): take run parameters on the command line with --param** (9ecaebc)
- **feat(engine): stop a run at its maxRunSeconds and report it as a failure** (c5bcab4)
- **feat(quality): say how many rows a check rejected, and when they were dropped** (93cb285)
- **feat(iceberg): read and write tables through an Iceberg REST catalog** (2053a0f)
- **feat(serve): report a stalled scheduler in /readyz and /metrics** (11c1ab1)
- **feat(alerts): page PagerDuty, and resolve the incident on the all-clear** (ceec4d1)
- **feat(test): record goldens with duckle-runner test --update-golden** (114124d)
- **feat(snk): append to a local Delta Lake table, creating it on first use** (369779d)
- **feat(src): log-based change data capture from PostgreSQL** (b94aa5f)
- **feat(reject): give every error-type reject a machine-readable envelope** (731df52)
- **feat(runjob): pass the caller's input rows to a child job** (274b673)
- **feat(assistant): pick the model from what the endpoint offers, instead of typing it** (01451e2)
- **feat(ai.classify): answer with an evaluation model that cannot pick a label you did not offer** (9cd574b)
- **feat(engine): pin DuckDB 1.5.5, which fixes an intermittent failure on HTTP sources** (7cdc974)
- **feat(engine): a single-file sink publishes its output by rename** (2094cc7)
- **feat(engine): per-node duration and row metrics in run history** (203210e)
- **feat(examples): runnable flow-control workspace, exercised in CI** (b532f6f)
- **feat(runner): review --format json|junit|sarif matches the other gates** (ddb744d)

### Fixes
- **fix(adbc): show ClickHouse columns as what they are (#364)** (5043fb7)
- **fix(sqlserver): upsert through MERGE on the default bulk path** (d68e5ef)
- **fix(connections): SQL Server nodes use their saved connection everywhere (#363)** (2e4ebfc)
- **fix(sqlserver): type date and time columns from what SQL Server says they are (#362)** (036519f)
- **fix(access): load the ODBC installer DLL instead of linking its stub** (fcc79f0)
- **fix(desktop): open the window on Wayland without XWayland (#361)** (b7d463a)
- **fix(build): redact a typed passphrase from the bundled pipeline** (4d99d60)
- **fix(engine): make "Log row count" do what it says** (e9ce04a)
- **fix(engine): resolve saved connections in a child pipeline, not only the parent** (4bc3177)
- **fix(serve): encode inline-handler arguments for JavaScript, not only HTML** (9bdfb3c)
- **fix(review): resolve saved connections on every surface that compiles a pipeline** (0c9d7c5)
- **fix(validate): resolve saved connections before compiling, as every run path does** (efb0dec)
- **fix(validate): refuse --affected --head, which could only mislead or pass vacuously** (e140bc7)
- **fix(serve): the web editor refuses an empty console credential, as serve already did** (95c2593)
- **fix(docker): stop overriding the workspace's own Python interpreter** (1e1de7b)
- **fix(docker): install the DuckDB extensions the image says it has** (868eb91)
- **fix(retry): a receipt naming this pid that this process never started is stale** (ac9fa7d)
- **fix(ai.chunk): the form names the unit the splitter actually uses** (02242f8)
- **fix(webhook): maxRequests counts requests, not the rows they unfold into** (f3be76a)
- **fix(rename): a mapping file written on Windows renames the column it names** (a8e793d)
- **fix(json): a byte order mark on a pipeline document no longer hides it** (580588b)
- **fix(engine): an interrupted run reaches the history, the metrics and the CLI path** (b794bd2)
- **fix(engine): a JSON shape on a cloud source means JSON, not CSV** (e53560d)
- **fix(spool): a cap below one record says so rather than waiting for ever** (360bc62)
- **fix(mongodb): a staged row that cannot be read fails the write** (a2e2fce)
- **fix(engine): refuse an encoding DuckDB accepts and reads wrongly** (c53e9cc)
- **fix(engine): a stopped run leaves no partial file at the output path** (a4dc00b)
- **fix(engine): a run reports the rows it kept, not the rows it skipped** (a5530d8)
- **fix(secrets): a racer adopting the workspace key waits for the bytes** (0109c78)
- **fix(engine): prune deletes only a receipt it has read and found finished** (9b5ed00)
- **fix(oracle): the truncate guard probes the rows it will write** (d1ca96f)
- **fix(engine): a node's memory limit, retries and failure policy apply to that node** (d293c37)
- **fix(engine): a JSON array with a byte order mark still reads as rows** (9e29057)
- **fix(engine): a result the row bridge cannot carry fails the stage** (82ab11b)
- **fix(secrets): concurrent minting of the workspace key agrees on one key** (e8b5cc1)
- **fix(engine): a run receipt is written atomically** (ce72505)
- **fix(engine): an empty JSON file is named as the cause, not the node below it** (623f6eb)
- **fix(mongodb): replace mode stops dropping a collection nothing was written to** (de58783)
- **fix(connectors): a cut-short artifact fetch removes its partial download** (7a1e0d2)
- **fix(runner): a failed build removes its staging tree** (34f2380)
- **fix(engine): a runjob handoff parquet no longer outlives its run** (06874ed)
- **fix(engine): an abandoned NDJSON writer takes its temp files with it** (91b70d1)
- **fix(sinks): truncate mode stops emptying its target when nothing arrived** (4646e7d)
- **fix(engine): concurrent runs stop destroying a pipeline's run history** (7f8ca43)
- **fix(engine): a binder error about a generated guard names the column instead** (14c22d8)
- **fix(sqlserver): the Encrypt toggle reaches the sink's default bulk path** (6dcdaba)
- **fix(ci): guard the example run loop for workspaces without pipelines** (5fa5618)
- **fix(scheduler): a catch-up runs every occurrence it records as fired** (ec1da9c)
- **fix(engine): an Oracle connect gives up instead of waiting for a silent listener** (d4af8a7)
- **fix(engine): SSH, FTP and SQL Server connects give up instead of waiting for a silent peer** (9b45c2a)
- **fix(engine): an AMQP connect gives up instead of waiting for a silent broker** (c7224ff)
- **fix(engine): a sub-pipeline resolves whether it is saved as <id>.json or <id>.pipeline.json** (440a889)
- **fix(ci): build the web image's two binaries one at a time** (1393968)
- **fix(editor): run badges and results show only on the pipeline that ran** (02f7fc2)
- **fix: every run resolves the workspace context before the date builtins** (1faec33)
- **fix(editor): Group By, joins, Add Column and AI nodes show the columns they produce** (84d3f23)
- **fix(web): the Data Catalog panel shows, annotates and inspects the server's workspace** (64f9016)
- **fix(web): Run no longer asks for a key the server's global context file defines** (2c0c370)
- **fix(web): Duckie's Retry reports why the AI engine cannot be installed** (3080780)
- **fix(web): Connect to Claude says why it is unavailable instead of spinning** (e1c3fb1)
- **fix(web): Build pipeline says to build the bundle on the server instead of doing nothing** (eeee799)
- **fix(web): the History tab lists a pipeline's runs, including the editor's own** (8d40c9f)
- **fix(editor): a Rename node's card counts the columns its form renames** (a596e7e)
- **fix(web): the Backfill panel lists, sets and clears saved state through the server** (66fdd70)
- **fix(web): Settings says where machine settings live instead of "Saved"** (583429a)
- **fix(web): a run the server refuses shows the server's reason** (8a65761)
- **fix(editor): autodetect's progress and error stay with the node they were for** (1646aef)
- **fix(editor): the bottom panel opens Output when a run ends, not on every event** (13858d1)
- **fix(desktop): displaced engine and app binaries are swept once their process exits** (183f9e7)
- **fix(runs): runs a killed process left running are reconciled outside the console** (cd8a088)
- **fix(sequence): a baseline is compared in the spelling the keys use** (5d7e6f7)
- **fix(logs): an append after a torn line no longer loses the new record** (30a93cb)
- **fix(connections): a saved Google Cloud Storage connection carries its credentials** (b65a911)
- **fix(catalog): annotations can be cleared, and typing is not wiped by a run** (b139b2c)
- **fix(editor): Save clears the unsaved marker only once the files are written** (05ef055)
- **fix(editor): undo history does not carry across a workspace switch or reload** (1e30e18)
- **fix(history): a run whose record could not be written says so** (9f27422)
- **fix(console): a sign-in whose session could not be saved is not a sign-in** (32f009d)
- **fix(git): nothing is staged when the safety ignore file cannot be written** (c0c200b)
- **fix(webhook): refuse a chunked or truncated request instead of storing it** (2ded276)
- **fix(messages): restore line continuations lost from 36 string literals** (f04c5b8)
- **fix(partition): hourly slices cover the whole last day and bind their windows** (0e1a755)
- **fix(partition): the repeated autumn hour gets its own partition key** (468726e)
- **fix(webhook): a sender is answered from the run's outcome, not the node's** (139c477)
- **fix(listen): refuse a webhook body it cannot take whole instead of answering 200** (82251e7)
- **fix(contexts): headless runs layer contexts by priority, as the desktop does** (075bcb9)
- **fix(subscriptions): a consumer is not run again because its delivery was not recorded** (90e44ae)
- **fix(web): a web editor run is recorded against the file retry can read** (930f956)
- **fix(web): the Schedules dialog reads and saves the workspace's schedules** (80ea326)
- **fix(web): the Stop button stops the run in the web editor** (44479d7)
- **fix(rest): the incremental mark compares timestamps as instants and is encoded in the URL** (c1df565)
- **fix(deploy): a deployed schedule keeps its timezone and exclusion calendar** (d885024)
- **fix(validation): a cycle closed by a trigger link is reported before Run** (0f780b6)
- **fix(settings): opening a workspace no longer inherits the last one's settings** (fce0416)
- **fix(time): a date offset too large for a date is left verbatim instead of panicking** (be0a9a2)
- **fix(contexts): the duplicate-key warning suggests placeholders that resolve** (e5f962b)
- **fix(schedules): the Schedules dialog shows why Run now or Delete failed** (08a3bb4)
- **fix(sql-name): SQL names that differ only in case are the same name** (a59adb0)
- **fix(git): a pull or branch checkout reloads the workspace instead of saving over it** (711363d)
- **fix(backfill): retry reclaims slices a killed executor left running** (0572a28)
- **fix(secrets): a connection that cannot be encrypted is not written in clear text** (944115d)
- **fix(editor): undo reaches a renamed SQL name, a declared schema and an edit inside the debounce** (28b1ea8)
- **fix(rest): picking an HTTP transport no longer replaces the node's saved connection** (bc70fc3)
- **fix(schedules): saving in the desktop dialog keeps the zone, calendar and misfire policy** (da357e0)
- **fix(serve): a zone or exclusion calendar sent for an existing schedule is applied** (86a56ae)
- **fix(filter): "contains", "starts with" and "ends with" match the typed value literally** (6ce0067)
- **fix(editor): Live mode never runs up to a sink while its fields are being edited** (b8903cc)
- **fix(editor): a ctl.setvar name is not pre-empted by a context value on desktop runs** (ab06cb6)
- **fix(serve): startup reconcile no longer interrupts another process's live run** (1bd033d)

### Backend
- **release: v0.7.4** (b62e8ce)
- **Merge pull request #350 from LouisDeconinck/feat/review-report-formats** (7fc41e9)
- **Merge pull request #351 from LouisDeconinck/feat/flow-control-samples** (274fbab)
- **Merge pull request #355 from LouisDeconinck/feat/node-metrics** (89cf83b)

### Tests
- **test(watermark): make the mid-run edit land inside its window, and check it did** (c732200)
- **test(http): the stub answers like a real server, and for as long as the run needs** (8186682)
- **test: restore three tests that lost their #[test] attribute** (27d1836)
- **test(execution): read the whole request before a stub answers it** (b4ddeab)
- **test(runlock): wait out another thread's fork before re-claiming a released lock** (abe7b6f)

### Docs
- **docs: regenerate the capability matrix and Python components for Iceberg REST** (63501b6)

### Chore
- **ci: run the SQL Server tests against a live server** (e1da797)
- **ci: run MinIO from Chainguard's image now the official ones are gone** (e269237)
- **ci(gitlab): make the pipeline parse, and create the bucket integration:minio seeds** (0c46ebc)
- **ci(gitlab): pull MinIO from quay.io** (18cf33e)
- **ci(iceberg): pull MinIO from quay.io, as the minio job already does** (d1a4aff)
- **chore(pypi): regenerate the component list, which was missing three surfaces** (fa20131)
- **ci(signpath): sign the exe itself, with no archive anywhere** (f489de5)
- **ci(signpath): match the real project, and refuse a signing request that returns nothing** (2b58d72)
- **ci: sign the Windows release assets through SignPath, on request for now** (d9ff19e)

_Recap by [Repo Wrapped](https://repowrapped.com/gh/slothflowlabs/duckle?utm_source=github-action)._