## slothflowlabs/duckle — v0.7.0…v0.7.1

_220+ commits._

### Features
- **feat(policy): take DuckDB off the network where policy restricts it** (5d0745a)
- **feat(html): follow the pagination a server rendered** (f10c0db)
- **feat(gui): derive a node's schema from what it really produces** (108a4d4)
- **feat(test): compare DECIMAL precision when the expectation spells it out** (cd8ce7e)
- **feat(mcp): run_tests, so an agent can run the suite without a shell** (fc3f2a3)
- **feat(test): row count, uniqueness, not-null, a SQL predicate and tolerance** (add64fe)
- **feat(test): deterministic ordering for a case that never promised one** (c8bd04e)
- **feat(test): assert column types, not only rendered values** (dd42a25)
- **feat(rest,html): archive the raw response to object storage, and from src.html** (86f28a2)
- **feat(python,rest): a deployed target must be prepared, and a row names its artifact** (a9b55e3)
- **feat(xml): record the exact XSD bytes a run derived its schema from** (97d82b0)
- **feat(rest): a fan-out that died at row 900,001 resumes** (828d56d)
- **feat(readme): a live clones-per-month badge in the hero** (5f6c8d6)
- **feat(rest): the incremental cursor reaches the request** (6706414)
- **feat(rest): a fan-out that survives two million parents** (1557451)
- **feat(ai): a ceiling on the bill, and a run that says it did not finish** (46b7b1c)
- **feat(xml): read the schema the feed already published** (9122a4d)
- **feat(ai): ask for a shape, and check the reply is that shape** (8a3a479)
- **feat(python): refuse a run whose .venv is not the environment uv.lock describes** (62a0bed)
- **feat(cache): see, drop and distrust the reuse cache from the CLI** (a462f55)
- **feat(cache): a stage whose inputs did not change does not run again** (06473e9)
- **feat(rest): keep the original response, named by its own content** (63dc6fb)
- **feat(ai): checkpoint classify and embed, not only llm** (105d4ef)
- **feat(html): read the corpus an upstream relation names, not one path** (9816db5)
- **feat(xml): read the corpus an upstream relation names, not one path** (fadfd2e)
- **feat(baseline): let an operator say this is the new normal** (7ede5a1)
- **feat(checkpoint): let the pipeline say which columns are the work** (c018075)
- **feat(checkpoint): never buy the same row twice** (bda903e)
- **feat(policy): make forbidden things impossible rather than discouraged** (d556586)
- **feat(artifact): carry business keys through a parser** (2d5ba76)
- **feat(quality): catch the run that looks fine and is not** (ddd70f7)
- **feat(archive): unpack an archive into artifacts** (a28ecfc)
- **feat(pdf): read the documents an upstream artifact relation names** (506cc05)
- **feat(ducklake): maintain a lake through the same pipelines that fill it** (18c53d8)
- **feat(artifact): copy the bytes, and record where they came from** (74cc847)
- **feat(changed): poll S3 and S3-compatible stores for metadata** (11d315a)
- **feat(work): bound how long a queued item is retried** (e43ddae)
- **feat(ducklake): publish several tables as one snapshot, or refuse** (f12aa54)
- **feat(runner): a resource budget, so one job cannot take the machine down** (1f70a3f)
- **feat(stream): src.changed, poll a remote source without downloading it** (2ba4134)
- **feat(stream): report a source that found nothing as unchanged, not as a plain ok** (bccc9e1)
- **feat(frontend): support dynamic time offsets in template time builtins (#191) (#276)** (de6cc78)
- **feat(backfill): finish the headless surfaces - console API, MCP, web editor** (bc87d4f)
- **feat(backfill): headless backfill, and stop a set from destroying other state** (215bb3f)
- **feat(stream): xf.tumble, event-time tumbling windows that survive between runs** (976f5f8)
- **feat(runner): listen + src.spool, so a push source stops losing what arrives** (fa53681)
- **feat(runner): follow, a continuous mode for pipelines that track their position** (0afb287)
- **feat(python): stream a table through code.python instead of materializing it** (a872f89)
- **feat(connectors): read and write Neo4j, Turso/libSQL and IBM DB2** (b0f8177)
- **feat(kafka): decode Confluent-framed Avro, and stop flagging self-sufficient SQL** (dd6ba82)
- **feat(kafka): resume where the last successful run stopped** (2e319c7)
- **feat(model): register a trained model only when the run succeeded** (53829b8)
- **feat(source): turn a PDF into one row per page** (1c2d683)
- **feat(http): set a proxy, timeouts and a User-Agent once** (165d982)
- **feat(source): read rows out of an HTML page by CSS selector** (73e0050)
- **feat(serve): accept a run, answer for it later, and cancel it** (92b501c)
- **feat(rest): make one request per row of an upstream table** (bf507ca)
- **feat(quality): propose only the record pairs worth comparing** (e2afd6c)
- **feat(ai): survive a rate limit and send requests in parallel** (0b0498e)
- **feat(python): use the workspace's own virtual environment** (18ed0f7)
- **feat(artifacts): describe files as rows a pipeline can reason about** (0b25a8a)
- **feat(python): hand a script the whole table, through Parquet** (e1dddb3)
- **feat(rest): stamp rows with the response they came from** (68a7ab6)
- **feat(engine): reuse an expensive stage's output between runs** (a4aa712)
- **feat(runner): duckle test - assert what a pipeline produces from a fixed input** (7a62839)
- **feat(runner,mcp): run only as far as one node and show what it produced** (44e1e91)
- **feat(geo): write GeoParquet from the Geospatial sink** (0149a85)
- **feat(ducklake): set the catalog schema and its META_* parameters on the node** (7e9feb6)
- **feat(control): carry a run variable into the jobs a pipeline runs** (0b40da2)
- **feat(import): carry a Java body that only sets context values over to nodes** (d262336)
- **feat(control): add a component that sets a run variable** (4fd000a)
- **feat(import): keep the condition that decides which rows reach a mapper output** (57eb185)

### Fixes
- **fix(mcp): resolve vault and env placeholders before a run** (31291bb)
- **fix(html): a page walk that stopped early is incomplete, not ok** (2394e00)
- **fix(gui): describing a node must never write anything** (9d9e8a4)
- **fix(history): an incomplete run is recorded as incomplete** (dc8660b)
- **fix: two silent-data bugs in this session's own work** (dd574fb)
- **fix(gui): route the schema derivation through the bridge it belongs in** (83d1907)
- **fix(gui): Text to Columns tells downstream what it produces** (f7a4f8d)
- **fix(test): a fixture lives beside the test file, and PDF/HTML can take one** (88bb703)
- **perf(rest): stream the parent rows instead of holding them all** (f477a23)
- **fix: three defects in this session's own work** (2f80200)
- **fix(test): the s3 stub must not answer before the body arrives** (da02be8)
- **fix(cache): an engine upgrade invalidates the reuse cache** (0528689)
- **fix(rest): the raw-capture field uses a kind the form knows** (ef532b3)
- **perf(artifacts): bound the corpus list, not just each document** (242968f)
- **fix(archive): a skipped member keeps the identity it was written with** (fff657f)
- **fix(policy): enforce the boundary where the act happens, not only where it is planned** (23c5f61)
- **fix(json): a column that appears late is not a column to lose** (9165999)
- **fix(test): drain the request before answering it in the S3 stub** (74e4212)
- **perf(xml): bound the intermediate, not just the parser** (8ff3d0e)
- **fix(messages): collapse two lost line continuations** (d2e0309)
- **fix(test): compare the whole result, and compare it by type** (4a73d7c)
- **fix(history): persist `unchanged`, and expose it as its own metric** (3f2d8b3)
- **fix(pypi): publish on release, and bump the packaged version to match** (5378adb)
- **fix(workspace): clear the job tabs when a workspace has no pipelines** (1570306)
- **fix(workspace): support inline duckle.json rollups and robust active job recovery (#213) (#275)** (62db060)
- **fix(backfill): a run's flush no longer overwrites an edit made during it** (b10b3d8)
- **fix(sftp): remember host keys, so an unpinned connection notices a change** (ed649a6)
- **fix(site,deps): drop a locality claim that is not true, and unship puppeteer** (b4cb376)
- **fix(site): the connector wall now shows only connectors that exist** (81332c7)
- **fix(engine): a run that cannot record its state no longer reports ok** (29c8248)
- **fix(kafka): apply the security settings the form has always offered** (d7d89a2)
- **fix(quality): make a check told to fail the run actually fail it** (4df34e4)
- **fix(json): make Flatten actually flatten, and let repeated keys keep their parent** (1639cd3)
- **fix(gcs): carry the region and the rest of the bucket's settings into the secret** (e405127)
- **fix(import): stop retyping a column on its way through, and total a blank as nothing** (471a85b)
- **fix(import): take the decimal scale a column declares, where it is safe to** (e24fb29)
- **fix(import): quote the loop's current item where it stands in SQL** (eca5b23)
- **fix(import): three readings that turned a working step into a broken one** (a6d1abf)
- **fix(map): count a join key that is an expression as one key** (124ac16)
- **fix(import): read whether a delimited writer puts the column names out** (ad025d6)
- **fix(import): name the quote setting the one the reader looks for** (eb568c6)
- **fix(csv): say quoting is off instead of leaving the reader on its default** (d00beeb)
- **fix(import): do not mirror a table more than one step writes** (dac8341)
- **fix(import): an output column with nothing to compute is still a column** (d76afcb)
- **fix(import): match on what the job matches on, not on the column inside it** (94213d8)
- **fix(import): only lay declared names over a read that fetches as many columns** (7d8c161)

### Backend
- **release: v0.7.1** (a947a73)

### Tests
- **test(state): wait for the read to have happened, not for 700ms** (fa1bfa9)
- **test(xml): the spill check now watches its own spool, not the whole temp volume** (7892172)
- **test(schema): pin that a declared date format survives a run and a reload** (420c420)

### Docs
- **docs: add comprehensive security, governance, and compliance documentation suite using the Diátaxis framework (#294)** (9906cba)
- **docs(pdf): pin the scanned-page handoff as a contract** (5d316a8)
- **docs(readme): drop the MCP Toplist badge** (3f57a4b)
- **docs(readme): move the MCP Toplist badge to the MCP section** (c46c3ea)
- **docs(readme): put status first** (4e3dcf6)
- **docs(readme): drop the pip installs badge** (24a7daf)
- **docs(readme): bigger badges, and drop the ones about our stack** (d507084)
- **docs(readme): show download counts, from both channels** (07f9b2e)
- **docs: stop describing Duckle as a laptop tool** (88b3bba)
- **docs: show how many people are online in Discord** (8350c16)

### Chore
- **chore: untrack the vendored DuckDB CLI binaries** (58ef585)
- **build(deps): take russh 0.63, which changes what host-key verification is given** (33e04bc)
- **build(deps): take quick-xml 0.42 and toml 1.1, and stop dropping XML entities** (6007ad7)
- **build(deps-dev): take TypeScript 7, Vite 8 and plugin-react 6 (#265)** (0527308)
- **build(deps): take pdf-extract 0.12, lopdf 0.42 and dom_query 0.28** (da8c7f4)
- **build(deps): take odbc-api 29** (608902c)
- **build(deps): take axum 0.8, rusqlite 0.40, apache-avro 0.22 and lapin 4** (68c101e)
- **build(deps): take aes-gcm 0.11 and ed25519-dalek 3, and prove the format held** (4cc8087)
- **build(deps): take zip 8, redis 1.6, jsonwebtoken 11, suppaftp 10** (7271380)
- **build(deps): take getrandom 0.4, prost 0.14 and the rest of the mechanical majors** (0c3ba5e)
- **build(deps): take the majors that need no code change** (032a67a)
- **build(deps): take quick-xml 0.41 and rustls-native-certs 0.8** (e811b50)
- **build(deps): bump the cargo-safe group with 2 updates (#266)** (16ddc86)
- **build(deps): bump the npm-safe group in /frontend with 14 updates (#264)** (9878a26)
- **build(deps): separate safe bumps from major ones** (570af44)
- **build(frontend): let Vite pick its own minifier** (0f3c867)
- **build(deps): bump the actions group across 1 directory with 12 updates (#202)** (63d49b8)
- **chore: ignore the local history-remediation script** (ee835a7)

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