Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
cbe6f83
fix(query+ingest): value-anchored NL→SQL grounding, hierarchy resolut…
Jun 2, 2026
277f96a
fix(ci): satisfy PR gate (lockstep, lint, unit/integration tests)
Jun 2, 2026
7847a81
feat(ingestion): reconstruct multi-row period headers in XLSX sections
Jun 2, 2026
3b30b74
Merge commit '7b02792' into recon/nl2sql-superset
Jun 30, 2026
c135bcc
feat(query+ingest): unify value-anchoring superset onto the NL→SQL br…
Jun 30, 2026
60c7f14
Merge reviewed source and SDK boundaries into grounding proposal
Oct 14, 2026
f56ebfa
Preserve executed SQL receipts and honor redacted value access
Oct 14, 2026
69e0636
Pin executed snapshots across conversation turns
Oct 14, 2026
03c70f1
Describe the value catalog in retrieval types
Oct 14, 2026
5d4059b
Reject inadmissible requests before retrieval and model invocation
Oct 14, 2026
b3cbf5d
Confine value anchoring to eligible registered snapshots
Oct 14, 2026
1090110
Require read capability before query retrieval
Oct 14, 2026
c4d0862
Preserve sampling privacy decisions before filtering evidence
Oct 14, 2026
fa2e09f
Classify profiled values beyond the sampling prefix
Oct 14, 2026
e00cbf9
Merge branch 'main' of https://github.com/fireflyframework/flyquery i…
Oct 14, 2026
4f2d824
Apply the configured provider prompt cache to agent runs
Oct 14, 2026
0565a28
Lock public Agentic dependencies and review service source variants
Oct 14, 2026
2f1ee71
Qualify combined query safety and Agentic adoption as 26.10.2
Oct 14, 2026
b2daad6
Derive application metadata from the release version
Oct 14, 2026
a465f06
Return typed pages from agent table SDK operations
Oct 14, 2026
7d8d97c
Make agent table Java examples compile with WebClient
Oct 14, 2026
89ad2f6
Make agent table Python examples executable with scoped clients
Oct 14, 2026
3428ac4
Return typed dataset and conversation discovery pages
Oct 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
19 changes: 19 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Copyright 2026 Firefly Software Foundation
# SPDX-License-Identifier: Apache-2.0
.git
.venv
venv
__pycache__
.pytest_cache
.ruff_cache
.mypy_cache
.env
.env.*
.local_blobs
.local
vendor
sdks
build
dist
*.log
*.whl
27 changes: 3 additions & 24 deletions .github/workflows/docker-publish.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright 2026 Firefly Software Foundation
# SPDX-License-Identifier: Apache-2.0
#
# Multi-arch image build + GHCR push.
#
Expand All @@ -12,16 +13,8 @@
# (the owner is normalised to lower-case below, since
# GHCR requires lower-case repository namespaces).
#
# The Dockerfile uses BuildKit named contexts for the pyfly +
# fireflyframework-agentic sibling repos. We clone them into ./vendor/
# and pass them via ``build-contexts:`` so the same Dockerfile works
# both locally (siblings on disk) and in CI.
#
# The Docling OCR engine is an opt-in runtime extra (``pip install
# 'flyquery[docling]'``) selected via ``FLYCANON_PDF_OCR_ENGINE=docling``.
# The image does not bake docling because the PyTorch + HF wheels add
# ~2.5 GB per architecture; operators that want layout-aware OCR
# extend the runtime stage (see docs/deployment.md).
# The Dockerfile validates the tracked server lock and installs its frozen
# public dependency graph. No adjacent framework checkout is required.

name: Docker publish (multi-arch)

Expand Down Expand Up @@ -56,8 +49,6 @@ concurrency:

env:
REGISTRY: ghcr.io
PYFLY_REF: v26.05.05
AGENTIC_REF: v26.05.21

jobs:
publish:
Expand All @@ -73,15 +64,6 @@ jobs:
name="${GITHUB_REPOSITORY##*/}"
echo "image=${{ env.REGISTRY }}/${owner}/${name}" >> "$GITHUB_OUTPUT"

- name: Check out sibling firefly framework repos
run: |
git clone --depth=1 --branch "$PYFLY_REF" \
https://github.com/fireflyframework/fireflyframework-pyfly.git \
./vendor/pyfly
git clone --depth=1 --branch "$AGENTIC_REF" \
https://github.com/fireflyframework/fireflyframework-agentic.git \
./vendor/fireflyframework-agentic

- uses: docker/setup-qemu-action@v3
with:
platforms: linux/amd64,linux/arm64
Expand Down Expand Up @@ -131,9 +113,6 @@ jobs:
sbom: false
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-contexts: |
pyfly=./vendor/pyfly
fireflyframework-agentic=./vendor/fireflyframework-agentic
cache-from: type=gha,scope=flyquery
cache-to: type=gha,mode=max,scope=flyquery

Expand Down
101 changes: 23 additions & 78 deletions .github/workflows/pr-gate.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright 2026 Firefly Software Foundation
# SPDX-License-Identifier: Apache-2.0
#
# PR gate -- runs on every pull request, on push to main, and on
# workflow_dispatch.
Expand All @@ -8,19 +9,14 @@
# 2. typecheck : pyright (best-effort, advisory)
# 3. unit : pytest tests/unit
# 4. integration : pytest tests/integration (Postgres+Redis+MinIO via testcontainers)
# 5. lockstep-check : 21 byte-equivalent files vs canon-pinned SHAs
# 5. lockstep-check : 19 historical baselines + 2 reviewed service variants
# 6. sdk-python : import-smoke + ruff under sdks/python
# 7. sdk-java : ``mvn verify`` under sdks/java
#
# Notes
# -----
# * pyfly + fireflyframework-agentic live in the public
# ``fireflyframework`` organization. The
# per-job ``Check out sibling firefly framework repos`` step
# clones the tagged refs into ``./vendor/`` and ``sed``-rewrites
# ``[tool.uv.sources]`` to point there for the duration of CI.
# * Pin the framework refs in ``env.{PYFLY_REF,AGENTIC_REF}`` so
# the gate is reproducible.
# * Public first-party sources are recorded in pyproject.toml and uv.lock.
# * Validate the lock before frozen sync; CI must not resolve new dependencies.

name: PR gate

Expand Down Expand Up @@ -50,8 +46,6 @@ concurrency:

env:
PYTHON_VERSION: "3.13"
PYFLY_REF: v26.05.05
AGENTIC_REF: v26.05.21

jobs:
lint:
Expand All @@ -65,26 +59,14 @@ jobs:
- uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Check out sibling firefly framework repos
run: |
git clone --depth=1 --branch "$PYFLY_REF" \
https://github.com/fireflyframework/fireflyframework-pyfly.git \
./vendor/pyfly
git clone --depth=1 --branch "$AGENTIC_REF" \
https://github.com/fireflyframework/fireflyframework-agentic.git \
./vendor/fireflyframework-agentic
- name: Repoint uv path sources at ./vendor
run: |
sed -i \
-e 's|path = "\.\./\.\./fireflyframework/fireflyframework-pyfly"|path = "./vendor/pyfly"|' \
-e 's|path = "\.\./\.\./fireflyframework/fireflyframework-agentic"|path = "./vendor/fireflyframework-agentic"|' \
pyproject.toml
- name: uv sync (dev + s3)
run: uv sync --extra dev --extra s3 --extra file-readers
run: |
uv lock --check
uv sync --frozen --extra dev --extra s3 --extra file-readers
- name: ruff check
run: uv run ruff check src tests
run: uv run --frozen ruff check src tests
- name: ruff format --check
run: uv run ruff format --check src tests
run: uv run --frozen ruff format --check src tests

typecheck:
name: Typecheck (advisory)
Expand All @@ -98,24 +80,12 @@ jobs:
- uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Check out sibling firefly framework repos
run: |
git clone --depth=1 --branch "$PYFLY_REF" \
https://github.com/fireflyframework/fireflyframework-pyfly.git \
./vendor/pyfly
git clone --depth=1 --branch "$AGENTIC_REF" \
https://github.com/fireflyframework/fireflyframework-agentic.git \
./vendor/fireflyframework-agentic
- name: Repoint uv path sources at ./vendor
run: |
sed -i \
-e 's|path = "\.\./\.\./fireflyframework/fireflyframework-pyfly"|path = "./vendor/pyfly"|' \
-e 's|path = "\.\./\.\./fireflyframework/fireflyframework-agentic"|path = "./vendor/fireflyframework-agentic"|' \
pyproject.toml
- name: uv sync (dev)
run: uv sync --extra dev --extra file-readers
run: |
uv lock --check
uv sync --frozen --extra dev --extra file-readers
- name: pyright
run: uv run pyright src/flyquery
run: uv run --frozen pyright src/flyquery

unit:
name: Unit tests
Expand All @@ -128,22 +98,10 @@ jobs:
- uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Check out sibling firefly framework repos
run: |
git clone --depth=1 --branch "$PYFLY_REF" \
https://github.com/fireflyframework/fireflyframework-pyfly.git \
./vendor/pyfly
git clone --depth=1 --branch "$AGENTIC_REF" \
https://github.com/fireflyframework/fireflyframework-agentic.git \
./vendor/fireflyframework-agentic
- name: Repoint uv path sources at ./vendor
run: |
sed -i \
-e 's|path = "\.\./\.\./fireflyframework/fireflyframework-pyfly"|path = "./vendor/pyfly"|' \
-e 's|path = "\.\./\.\./fireflyframework/fireflyframework-agentic"|path = "./vendor/fireflyframework-agentic"|' \
pyproject.toml
- name: uv sync (dev)
run: uv sync --extra dev --extra file-readers
run: |
uv lock --check
uv sync --frozen --extra dev --extra file-readers
- name: pytest tests/unit
env:
# Dummy LLM keys so pydantic-ai providers can instantiate
Expand All @@ -152,7 +110,7 @@ jobs:
OPENAI_API_KEY: sk-dummy-key
ANTHROPIC_API_KEY: sk-dummy-key
AWS_DEFAULT_REGION: eu-west-1
run: uv run pytest -q tests/unit -m 'not integration'
run: uv run --frozen pytest -q tests/unit -m 'not integration'

integration:
name: Integration tests
Expand All @@ -166,22 +124,10 @@ jobs:
- uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Check out sibling firefly framework repos
run: |
git clone --depth=1 --branch "$PYFLY_REF" \
https://github.com/fireflyframework/fireflyframework-pyfly.git \
./vendor/pyfly
git clone --depth=1 --branch "$AGENTIC_REF" \
https://github.com/fireflyframework/fireflyframework-agentic.git \
./vendor/fireflyframework-agentic
- name: Repoint uv path sources at ./vendor
run: |
sed -i \
-e 's|path = "\.\./\.\./fireflyframework/fireflyframework-pyfly"|path = "./vendor/pyfly"|' \
-e 's|path = "\.\./\.\./fireflyframework/fireflyframework-agentic"|path = "./vendor/fireflyframework-agentic"|' \
pyproject.toml
- name: uv sync (dev + s3 for MinIO conformance)
run: uv sync --extra dev --extra s3 --extra file-readers
run: |
uv lock --check
uv sync --frozen --extra dev --extra s3 --extra file-readers
- name: Build the pinned upstream MinIO test server
run: docker build --tag flyquery-integration-minio:${{ github.sha }} tests/integration/minio
- name: pytest tests/integration
Expand All @@ -195,7 +141,7 @@ jobs:
OPENAI_API_KEY: sk-dummy-key
ANTHROPIC_API_KEY: sk-dummy-key
AWS_DEFAULT_REGION: eu-west-1
run: uv run pytest tests/integration -q --timeout=300 -m 'not llm'
run: uv run --frozen pytest tests/integration -q --timeout=300 -m 'not llm'

lockstep-check:
name: Lockstep check (canon-pinned SHAs)
Expand All @@ -206,9 +152,8 @@ jobs:
with:
python-version: ${{ env.PYTHON_VERSION }}
# The lockstep script imports nothing from pyfly/agentic; it
# walks the 21 lock-step files, computes SHA-256 after a
# canon-normalising substitution, and compares to the pinned
# JSON. No uv sync + no sibling clones needed.
# checks nineteen historical baseline hashes and two reviewed
# full-file service variants. No dependency installation needed.
- name: Run lockstep check
run: python scripts/check_lockstep.py

Expand Down
6 changes: 3 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ wheels/
.uv/
.pip/

# uv.lock is generated locally; CI runs ``uv sync`` (not ``uv sync
# --frozen``) so the lockfile doesn't need to ride in git.
uv.lock
# The server lock is reviewed release source; SDK development locks remain local.
**/uv.lock
!/uv.lock

# --- Java SDK build artefacts ------------------------------------------------
sdks/java/target/
Expand Down
35 changes: 35 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,41 @@ follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and
the project uses [CalVer](https://calver.org/) (YY.MM.PP) per the
Firefly Framework convention (memory: `firefly_uses_calver`).

## [26.10.2] - 2026-10-14

### Changed

- Use the public fireflyframework-agentic 26.10.1 wheel with the qualified
pyfly 26.06.113 runtime. Track the server dependency lock and validate it
before frozen CI and image installs.
- Apply `FLYQUERY_PROMPT_CACHE` when constructing agents. Enabled mode adds
Anthropic instruction-cache hints; disabled mode omits this middleware.
User messages, tool results and generated answers are not memoized.
- Ground queries with bounded value catalogs, scoped relation candidates and
persisted conversation snapshot pins. Candidate execution probes pass the
registered-table fence and a bounded result limit before candidate selection.
- Keep nineteen historical shared-source baselines and two explicitly reviewed
service variants under source-drift checks.

### Fixed

- Reject missing or unauthorized dataset scope before retrieval or model calls,
recording a caller-scoped rejected audit row without reading dataset metadata.
- Classify original samples before filtering them, and inspect retained profile
values before embedding. Redact/reject stores an explicit empty-list denial
so profiles cannot reintroduce protected values into schema knowledge.
- Exclude inactive columns from catalog and retrieval projections. Preserve
original Parquet files and conversation snapshot selections.
- Refresh the OpenAPI Decimal schemas for the resolved Pydantic runtime and
align server, actuator, Python and Java SDK release metadata.

A nonempty executed candidate is a selection heuristic, not proof that the SQL
matches the requested entities or filters. The engine does not enforce its
statement-timeout setting or provide an operating system sandbox. Deployment
resource limits do not implement that missing query deadline. Remote object-store
DuckDB reads are not qualified by the local registered-file tests. PII detection
covers sampled and retained profile values; it is not a scan of every source row.

## [26.6.0] - 2026-06-01

### Fixed — Semantic layer brought up to its documented contract
Expand Down
41 changes: 9 additions & 32 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright 2024-2026 Firefly Software Foundation
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand All @@ -16,18 +17,8 @@
#
# Multi-stage Docker build for flyquery.
#
# Sibling-path deps (pyfly, fireflyframework-agentic) are passed in as
# named BuildKit contexts so the build context stays scoped to this
# directory.
#
# Usage:
# docker buildx build \
# --build-context pyfly=../../fireflyframework/fireflyframework-pyfly \
# --build-context fireflyframework-agentic=../../fireflyframework/fireflyframework-agentic \
# --tag flyquery:latest \
# .
#
# See docker-compose.yml for the canonical invocation.
# Dependencies come from public first-party sources pinned by uv.lock.
# Build: docker build --tag flyquery:local .

ARG PYTHON_VERSION=3.13

Expand All @@ -43,31 +34,17 @@ RUN apt-get update \
ENV UV_PROJECT_ENVIRONMENT=/app/.venv \
UV_LINK_MODE=copy

# Stage sibling sources (only what uv needs to install the editable wheel).
COPY --from=pyfly /pyproject.toml /build/pyfly/pyproject.toml
COPY --from=pyfly /README.md /build/pyfly/README.md
COPY --from=pyfly /src /build/pyfly/src

COPY --from=fireflyframework-agentic /pyproject.toml /build/fireflyframework-agentic/pyproject.toml
COPY --from=fireflyframework-agentic /README.md /build/fireflyframework-agentic/README.md
COPY --from=fireflyframework-agentic /LICENSE /build/fireflyframework-agentic/LICENSE
COPY --from=fireflyframework-agentic /fireflyframework_agentic /build/fireflyframework-agentic/fireflyframework_agentic

# Stage the project manifests for layer caching. README.md is required
# by hatchling because pyproject.toml declares ``readme = "README.md"``.
WORKDIR /app
COPY pyproject.toml /app/pyproject.toml
COPY README.md /app/README.md
COPY uv.lock* /app/

# Rewrite path-source entries so uv resolves siblings inside the container.
RUN sed -i \
-e 's|path = "\.\./\.\./fireflyframework/fireflyframework-pyfly"|path = "/build/pyfly"|' \
-e 's|path = "\.\./\.\./fireflyframework/fireflyframework-agentic"|path = "/build/fireflyframework-agentic"|' \
/app/pyproject.toml
COPY LICENSE /app/LICENSE
COPY uv.lock /app/uv.lock

RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --no-install-project --no-dev --no-editable
uv lock --check \
&& uv sync --frozen --no-install-project --no-dev --no-editable

# Copy the application source + migrations and finalise the install.
COPY src/ /app/src/
Expand All @@ -78,7 +55,7 @@ COPY docker-entrypoint.sh /app/docker-entrypoint.sh
RUN chmod +x /app/docker-entrypoint.sh

RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --no-dev --no-editable
uv sync --frozen --no-dev --no-editable


# ---- Stage 2: runtime -----------------------------------------------------
Expand Down Expand Up @@ -112,7 +89,7 @@ RUN apt-get update \
&& useradd --uid 10001 --shell /usr/sbin/nologin --no-create-home flyquery

WORKDIR /app
# Copy artefacts as the unprivileged ``canon`` user so the runtime always
# Copy artefacts as the unprivileged ``flyquery`` user so the runtime always
# has read access to bundled resources (e.g. resources/prompts/*.yaml)
# regardless of whatever host umask produced the source tree.
COPY --from=builder --chown=flyquery:flyquery /app/.venv /app/.venv
Expand Down
Loading
Loading