Skip to content

v0.1.4

Choose a tag to compare

@db-tycoon-stephen db-tycoon-stephen released this 02 May 10:17
· 71 commits to main since this release
9809a1b

Tycoon v0.1.4

Released: 2026-04-30

Headline

v0.1.4 closes the four open issues that survived v0.1.3 (#7, #12, #17,
plus the late-add #18 / #19 / #20), adds a comprehensive MkDocs Material
docs site
with tycoon docs serve, and ships a long list of small UX
improvements (-h alias, hygiene fixes, dbt profile flags, non-interactive
register surfaces).

The two themes worth opening with:

  • tycoon data sync — cloud → local DuckDB snapshots (#12).
    Snapshot one or more md: (or local) DuckDBs into a single local
    file you can point dbt-dev / notebooks / agents at instead of prod.
    Three modes (replace / append / skip-existing), optional sync:
    block in tycoon.yml, deliberate v1 non-goals (no reverse, no
    incremental).

  • First-class observability metadata in dbt + Nao (#20). Tycoon
    already accumulated rich run history in .tycoon/metadata.duckdb
    v0.1.4 makes that history visible to the rest of the stack. Every
    scaffolded dbt project ATTACHes the metadata DB as tycoon_meta and
    ships nine stg_tycoon__* staging models (plus a dim_runs mart
    union'ing dlt + dbt timelines). tycoon ask sync then exposes them
    to Nao automatically — no extra plumbing.

What landed

tycoon data sync — cloud → local snapshots ✅ (#12)

tycoon data sync --from md:my_catalog --to ./data/local.duckdb
tycoon data sync --schema mart --tables 'dim_*'
tycoon data sync --mode skip-existing
tycoon data sync                           # uses tycoon.yml's sync block

New module src/tycoon/sync.py (DuckDB ATTACH-based core, sources always
READ_ONLY) + src/tycoon/commands/sync_cmd.py (CLI surface) +
SyncSourceSpec / SyncConfig pydantic models on TycoonProject.

v1 deliberate non-goals: no reverse sync, no incremental, only md: +
local DuckDB sources, full replace per table. 16 new tests in
test_sync.py.

One-command MotherDuck + Nao + LM Studio setup ✅ partial (#7)

Four of six sub-asks landed:

  • §4 tycoon ask init pre-creates all eight directories nao sync
    walks (databases/, queries/, docs/, semantics/, repos/,
    agent/{tools,mcps,skills}). Eliminates the "No such file or
    directory: 'repos'" crash class.
  • §5 New tycoon ask init --llm <provider> flag with shortcuts
    for lm-studio / ollama / openai / anthropic / gemini /
    mistral. The lm-studio shortcut expands to OpenAI-compat config
    pointed at http://localhost:1234/v1 — users don't have to discover
    that "openai + custom base_url" is the LM Studio idiom.
  • §6 tycoon ask doctor health check — validates nao_config.yaml,
    the eight required dirs, MotherDuck auth, and LM Studio reachability.
    Renders an OK/WARN/FAIL status_table; exits non-zero on any FAIL.
  • §7 Auto-generated .tycoon/nao/.gitignore keeps PII row-previews
    • sync artifacts (databases/, repos/, db.sqlite*) out of git.

§3 (smart include_schemas defaults) and §5b (init-wizard LLM prompt)
are deferred to v0.2.0's init redesign (#14) — no point adding LLM
prompting to a wizard that's about to be reworked.

Legacy NYC pipelines fixed ✅ (#17)

nyc_dot_pipeline, mta_pipeline, and mta_bus_speeds_pipeline were
reaching into the global config singleton (config.raw_db) instead of
using the raw_db_path the runner threads through. Fine in real CLI
processes; broke under cli_runner.invoke because monkeypatch.setattr
only rebinds the command's reference.

_run_legacy now passes raw_db_path through; the three pipeline
modules dropped their global-config import. Test runs in 2.57s.

tycoon register dbt profile flags ✅ (#18)

Three new flags mirror dbt's own CLI options:

tycoon register dbt ../my-dbt --profiles-dir ~/.dbt --profile prod_p --target prod

Persisted into tycoon.yml as dbt_profiles_dir / dbt_profile /
dbt_target so subsequent tycoon data transform runs reuse them
without re-passing flags. The warehouse-alignment branch of
register dbt now reads the right adapter config when these are set.

tycoon register warehouse non-interactive flags ✅ (#19)

Companion to #18. Five new flags make the command scriptable in CI:

tycoon register warehouse --type duckdb --path data/wh.duckdb --no-prompt
tycoon register warehouse --type motherduck --catalog my_demo --no-prompt
tycoon register warehouse --type duckdb --path data/new.duckdb --force --no-prompt

--type accepts both canonical (duckdb, motherduck) and
conversational (local, cloud) values for either UX preference.

Observability metadata in dbt + Nao ✅ (#20)

The headline architectural change. Three sub-pieces compose:

1. ATTACH at scaffold time. Every scaffolded dbt profile gains a
tycoon_meta ATTACH entry pointing at .tycoon/metadata.duckdb,
READ_ONLY. dbt models can now SELECT * FROM tycoon_meta.main.<table>
directly, without copying data. The metadata DB is pre-created with the
empty observability schema at scaffold time so the first dbt run
doesn't trip on a missing file.

2. Nine staging models + a dim_runs mart. New tycoon data observability scaffold writes:

dbt_project/models/_tycoon/
├── stg_tycoon__dlt_runs.sql              # views over each metadata table
├── stg_tycoon__dlt_rows_by_table.sql
├── stg_tycoon__dlt_trace_runs.sql
├── stg_tycoon__dlt_trace_steps.sql
├── stg_tycoon__dlt_trace_jobs.sql
├── stg_tycoon__dbt_runs.sql
├── stg_tycoon__dbt_nodes.sql
├── stg_tycoon__dbt_manifest_snapshots.sql
├── stg_tycoon__dbt_schema_changes.sql
├── dim_runs.sql                          # UNION dlt + dbt timelines
└── _tycoon__schema.yml

All materialized: view so they don't double-store data. Pull with
tycoon data transform run --select _tycoon.

3. Nao gets it for free. Once the staging views exist, tycoon ask sync introspects them as part of the warehouse — no extra plumbing.
tycoon ask context --schema _tycoon cats the synced columns.md /
preview.md just like any other schema.

tycoon init wires all three for new projects automatically.
tycoon register dbt wires them for existing projects unless
--no-attach-metadata is passed. tycoon data observability scaffold
is the standalone retrofit command (idempotent).

MkDocs Material docs site ✅

Comprehensive docs site at docs/. ~30 pages, ~25K words, including:

  • Getting started — installation, first project, six core concepts
  • Commands — full reference per command surface (init, register,
    doctor, docs, data sources, data transform, data sync, data query,
    data history, data analyze, data status, data run-all, ask, start,
    stop, run)
  • Referencetycoon.yml schema, templates catalog, observability
    tables, environment variables
  • Recipes — CSV-to-dashboard, MotherDuck cloud sync, LM Studio local
    LLM, adopt tycoon for an existing dbt project
  • Releases — links every release narrative

New tycoon docs serve command (and tycoon docs build --strict) wraps
MkDocs so contributors have one command to read the docs locally:

tycoon docs serve              # http://127.0.0.1:8000 with hot reload
tycoon docs build --strict     # fail on warnings — CI-friendly

New [docs] extra pulls in mkdocs==1.6.1 + mkdocs-material==9.5.49.

-h short-alias for --help

tycoon -h
tycoon data sync -h
tycoon ask doctor -h

Configured once on the root typer app via context_settings; click
propagates it to every sub-command.

Hygiene fixes

  • Drop the noisy "Tables" column from tycoon data sources list.
    Always rendered (all) for the source types most users have
    (rest_api / filesystem) — meaningless. The underlying field still
    appears in tycoon data sources show <name> where there's space.

  • Drop the dbt-fusion check from tycoon doctor. Got its own
    panel and warned when dbtf was on $PATH, but the warning's premise
    didn't survive scrutiny — dbtf is a separate binary, doesn't shadow
    dbt, they coexist fine. Singling out one specific competitor was
    disproportionate. tycoon doctor is more useful when every line on
    it represents a real check.

  • Fix repo .gitignore data/ pattern. The pattern was matching
    any data/ subdirectory anywhere in the tree (intended only for the
    repo-root data/). Caused docs/commands/data/ pages to be silently
    uncommitted across two earlier docs commits. Anchored to root.

  • Add _tycoon_* artifact ignores to the same .gitignore. The
    CLI source repo's own rill/ directory accumulates auto-generated
    observability dashboards when tycoon is invoked against itself during
    testing. Same exclusion bucket as the existing
    "this is the CLI source repo, not a tycoon project" block.

GitHub Actions Node 24 prep

Bumped at branch cut so the deprecation warning is gone from the cycle:

  • actions/checkout v4 → v6
  • actions/upload-artifact v4 → v7
  • actions/download-artifact v4 → v8
  • astral-sh/setup-uv v4 → v7 (the latest moving major-tag alias —
    v8 is published as specific tags only, no moving alias)

GitHub flips the runner default to Node 24 on June 2 2026 and
removes Node 20 entirely on September 16 2026.

CI/CD automation — release pre-flight + nightly e2e

Three additions to the GitHub Actions surface, each removing a step
from the manual-before-each-release checklist:

ci.yml gains three jobs alongside the existing pytest + ruff:

  • builduv build + install the produced wheel into a fresh
    venv + run tycoon --version / -h. Catches packaging regressions
    (manifest typos, broken extras, console-script wiring drift) on
    every PR rather than the next release.
  • docsuv run mkdocs build --strict. Broken internal links
    or missing nav targets block the merge.
  • template-smoke (matrix over the four built-in templates) —
    scaffolds a fresh project from each template, runs tycoon doctor,
    asserts no ERROR lines. Catches template-side regressions
    (missing files, bad placeholder substitution) without spinning up
    the full e2e ingestion suite.

New nightly-e2e.yml runs on a daily cron (08:00 UTC) and
exercises the no-credential live-API tests (nyc-transit +
weather-station). On failure, the workflow opens a GitHub issue
labeled ci,upstream-flake so upstream API drift is visible against
a triage queue rather than surprising us during a release. Skips
issue creation when an open one already exists, so the bug-tracker
doesn't get pinged daily for the same outage.

publish.yml gains a preflight job that gates every other
publish step. Reads the tag, the version pins from pyproject.toml
and src/tycoon/__init__.py, the ## [<version>] - YYYY-MM-DD
entry in CHANGELOG.md, and the _Released: line in
docs/releases/v<version>.md — and fails fast if any disagree.
Eliminates the "tagged the wrong version / forgot to date the
CHANGELOG" failure mode without relying on a manual checklist.

The combined effect: most of what was a Claude-driven manual
pre-release checklist now happens automatically. v0.1.4's own
publish exercises all three new layers as the first end-to-end
verification.

Deferred

Carried forward to a future minor or to v0.2.0:

  • Smart include_schemas defaults for Nao (#7 §3) — defer to v0.2.0
    init redesign
  • Init-wizard LLM provider prompt (#7 §5b) — same
  • tycoon init redesign around required dbt-or-dlt + git remote
    (#14) — explicitly v0.2.0
  • Rill 0.86 DuckLake live-connector migration — revisit when Rill
    ships shared-lock support, or when a Postgres-backed catalog story
    is acceptable

Upgrade notes

pip install -U database-tycoon

No breaking changes for code. Five things worth knowing:

  1. tycoon ask init pre-creates 8 nao directories now — fresh
    projects no longer need a separate nao init step. Existing
    projects re-running ask init will see the dirs appear.
  2. tycoon init and tycoon register dbt now wire tycoon_meta
    into the dbt profile
    by default. The first dbt run on a fresh
    project builds the new models/_tycoon/ views automatically. Pass
    tycoon register dbt --no-attach-metadata if you don't want this on
    an existing project.
  3. The dbt_profiles_dir / dbt_profile / dbt_target keys are new
    in tycoon.yml.
    Optional — only set when tycoon register dbt
    was passed the matching CLI flag. No effect on existing projects
    that don't have them.
  4. The repo's .gitignore data/ pattern is now anchored to root
    (/data/). If you forked tycoon and your fork added subdirectories
    under data/ elsewhere expecting them to be ignored, anchor your
    pattern explicitly.
  5. GH Actions versions bumped. Forks running their own CI should
    re-validate.

Tests / validation

uv run pytest -q385 passed, 1 skipped, 3 deselected. All
previously-existing tests still green; +44 new across the cycle
(observability scaffolding, sync command, register flags, ask
doctor / context / init flags, AGENTS.md, etc.).

uv run mkdocs build --strict clean.