Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
4d92a0a
docs: add v3.0.0 unified TS core + Bun server design spec
hessius Jul 2, 2026
34e4343
docs: add v3.0.0 unified TS core + Bun server implementation plan
hessius Jul 2, 2026
61ada1c
feat(core): scaffold @metic/core handler + Platform interface
hessius Jul 5, 2026
1106d95
refactor(core): extract compass rules into @metic/core
hessius Jul 5, 2026
be91880
refactor(core): extract pure logic modules into @metic/core
hessius Jul 5, 2026
6603222
fix(docker): preserve monorepo layout so frontend build resolves @met…
hessius Jul 5, 2026
dca2de2
refactor(core): extract portable AI knowledge, errors and prompts int…
hessius Jul 5, 2026
eac1609
feat(server): Bun proxy-mode server + Node platform (Phase 4)
hessius Jul 6, 2026
778b5e4
test(server): fix type-only errors in bun-server tests
hessius Jul 6, 2026
b52bd4d
feat(core): port shot annotations route family
hessius Jul 6, 2026
a68fe57
feat(core): port dial-in session route family
hessius Jul 6, 2026
58ffadf
feat(core): port pour-over preferences route family
hessius Jul 6, 2026
6afdc7b
feat(core): add AI provider seam + dial-in AI recommendations
hessius Jul 6, 2026
77f0aac
feat(core): add machine.fetch seam to the Platform
hessius Jul 6, 2026
b5cce58
feat(core): port shot-analysis pure logic into the core package
hessius Jul 6, 2026
e0ed18e
feat(core): port shot-analysis route family into the core package
hessius Jul 6, 2026
0de1e41
feat(core): port profile recommendation routes into the core package
hessius Jul 6, 2026
d5b248e
feat(core): port apply-recommendations route into the core package
hessius Jul 6, 2026
47e6930
feat(core): port regenerate-description route into the core package
hessius Jul 6, 2026
d8e8c04
feat(core): port analyze_and_profile (full profile generation) into t…
hessius Jul 6, 2026
02e19f0
feat(web): add browser Platform impl for the unified core (Phase 3 ke…
hessius Jul 6, 2026
1c20dfa
feat(core): port system settings/version/network-ip routes into the c…
hessius Jul 6, 2026
39ffd68
chore: gitignore *.tsbuildinfo build artifacts
hessius Jul 6, 2026
baa10f4
feat(core): port machine shot-history routes with tombstone/notes ove…
hessius Jul 6, 2026
3e5749f
feat(core): port machine shot-history read routes into the core package
hessius Jul 6, 2026
ed58fc0
feat(core): port machine command + status routes into the core package
hessius Jul 6, 2026
c2938a1
feat(core): port profiles-crud route family to @metic/core
hessius Jul 6, 2026
7c5717e
feat(core): port system meta routes + model discovery to @metic/core
hessius Jul 6, 2026
26e9ed8
feat(core): port recipe library to @metic/core as single source
hessius Jul 6, 2026
7a10e4e
fix(server): serve config.json with an empty serverUrl
hessius Jul 6, 2026
0656aaf
feat(core): port profile image-proxy route into @metic/core
hessius Jul 6, 2026
5a001eb
feat(core): cover remaining proxy-mode routes (update status, schedul…
hessius Jul 6, 2026
275c8eb
test(e2e): visit Settings in the full-app sweep
hessius Jul 6, 2026
4f82261
fix(e2e): drop useless body initializer in full-app sweep
hessius Jul 6, 2026
b875421
fix(e2e): exclude local-only full-app sweep from CI
hessius Jul 6, 2026
697dcfc
feat(core): wire @metic/core into the browser fetch path behind a flag
hessius Jul 11, 2026
44a479e
feat(core): port pour-over active flows, progress seam, and read stubs
hessius Jul 11, 2026
a16719d
feat(web): cut the browser over to @metic/core and delete the legacy …
hessius Jul 11, 2026
9d42b04
feat(server): SQLite storage backend + interceptor module map (#531, …
hessius Jul 12, 2026
cf98e08
feat(server): Tailscale routes over the LocalAPI unix socket (Phase 5…
hessius Jul 12, 2026
c10dfa1
feat(docker): distroless single-binary image + CI size gate (Phase 6,…
hessius Jul 12, 2026
8732672
chore: ignore bun --compile temp artifacts
hessius Jul 12, 2026
4a4edef
feat(core): benign /api/profiles/sync/accept/{id} stub (Phase 7 parit…
hessius Jul 12, 2026
6a0cdca
feat!: delete Python backend, cut over to the unified Bun image (Phas…
hessius Jul 12, 2026
5d2eea1
fix: remove orphaned MQTT bridge and MCP server UI in proxy mode
hessius Jul 12, 2026
85af799
feat(android): support the hardware back button (#536)
hessius Jul 11, 2026
526c2be
fix(ai): compact on-device prompts to fit small context windows
hessius Jul 12, 2026
05887aa
fix(web): handle rejected profile-image load in HistoryView effect
hessius Jul 13, 2026
55587df
fix(core): credit stage exit trigger reached at the stage transition
hessius Jul 13, 2026
3ad3eb4
fix(ai): make the AI gate provider-aware and promote AI_MODE when a h…
hessius Jul 14, 2026
2667dcd
Merge pull request #558 from hessius/feat/wire-core-interceptor-flag
hessius Jul 15, 2026
5fcc7e6
Merge remote-tracking branch 'origin/main' into version/3.0.0
hessius Jul 15, 2026
cdd6ecb
chore(deps): drop unused react-day-picker and dead ui/calendar component
hessius Jul 16, 2026
d015a26
ci: use metic healthcheck instead of curl in build-publish smoke test
hessius Jul 16, 2026
2a23a96
feat(profiles): import from metprofiles links, direct URLs, and raw JSON
hessius Jul 16, 2026
734e039
feat(share): native share-target import for profiles (Android + iOS s…
hessius Jul 16, 2026
7a534da
feat(share): complete iOS Share Extension implementation
hessius Jul 17, 2026
76e5c08
feat(share-import): central result popover for automatic profile imports
hessius Jul 17, 2026
c2d71ae
fix(share): foreground app on iOS share import and stop UI text selec…
hessius Jul 19, 2026
c2aa584
docs(readme): document server features removed in 3.0.0
hessius Jul 20, 2026
6b1413c
docs(updating): warn 2.x upgraders about the distroless healthcheck b…
hessius Jul 21, 2026
37cbbd4
fix(web): never block app init on slow machine-backed /api/history
hessius Jul 22, 2026
6293482
fix(web): avoid lookbehind regex in markdown cleaning (Safari <16.4)
hessius Jul 22, 2026
cc9035b
chore: bump version to 3.0.0-beta.2
hessius Jul 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,12 @@ data/
logs/
*.log

# Node modules (web builder stage installs fresh)
# Node modules (builder stages install fresh)
apps/web/node_modules/
apps/web/dist/
apps/bun-server/node_modules/
apps/bun-server/dist/
packages/core/node_modules/

# Python cache
__pycache__/
Expand Down
38 changes: 18 additions & 20 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,51 +3,49 @@

version: 2
updates:
# PythonFastAPI server
- package-ecosystem: "pip"
directory: "/apps/server"
# npmWeb frontend (Bun uses package.json)
- package-ecosystem: "npm"
directory: "/apps/web"
schedule:
interval: "weekly"
day: "monday"
open-pull-requests-limit: 5
open-pull-requests-limit: 10
labels:
- "dependencies"
- "python"
- "javascript"
commit-message:
prefix: "chore(deps)"
groups:
dev-dependencies:
dependency-type: "development"
update-types: ["minor", "patch"]
production-dependencies:
dependency-type: "production"
update-types: ["patch"]

# PythonMCP server
- package-ecosystem: "pip"
directory: "/apps/mcp-server"
# npmBun server host (@metic/server)
- package-ecosystem: "npm"
directory: "/apps/bun-server"
schedule:
interval: "weekly"
day: "monday"
open-pull-requests-limit: 3
labels:
- "dependencies"
- "python"
- "javascript"
commit-message:
prefix: "chore(deps)"

# npm — Web frontend (Bun uses package.json)
# npm — shared @metic/core handler
- package-ecosystem: "npm"
directory: "/apps/web"
directory: "/packages/core"
schedule:
interval: "weekly"
day: "monday"
open-pull-requests-limit: 10
labels:
- "dependencies"
- "javascript"
commit-message:
prefix: "chore(deps)"
groups:
dev-dependencies:
dependency-type: "development"
update-types: ["minor", "patch"]
production-dependencies:
dependency-type: "production"
update-types: ["patch"]

# Docker — unified Dockerfile
- package-ecosystem: "docker"
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/build-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,8 @@ jobs:
# Check container is running
docker ps | grep test-container

# Check health endpoint
docker exec test-container curl -f http://localhost:3550/health || exit 1
# Check health endpoint (distroless image has no curl; use the binary's own healthcheck)
docker exec test-container /app/metic healthcheck || exit 1

- name: Cleanup
if: always()
Expand Down
112 changes: 63 additions & 49 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ on:

jobs:
# ============================================================================
# Relay Server Tests (Python/FastAPI)
# Core + Server Tests (TypeScript/Bun)
# ============================================================================
# @metic/core is the shared request handler; apps/bun-server is the compiled
# single-binary host. Both run under Bun and share the frozen /api/* contract
# tests that are the cross-runtime parity oracle.
server-tests:
name: Server Tests (Python)
name: Core + Server Tests (Bun)
runs-on: ubuntu-latest
defaults:
run:
working-directory: apps/server
permissions:
contents: read

Expand All @@ -31,37 +31,52 @@ jobs:
with:
submodules: recursive

- name: Set up Python 3.13
uses: actions/setup-python@v6
- name: Setup Bun (attempt 1)
id: setup_bun_1
continue-on-error: true
uses: oven-sh/setup-bun@v2
with:
python-version: "3.13"
cache: "pip"
cache-dependency-path: apps/server/requirements-test.txt

- name: Install dependencies
run: |
pip install --upgrade pip
pip install -r requirements-test.txt
# Pin Bun for CI reproducibility and transient download stability.
# Keep this in sync with docker/Dockerfile.unified bun base image.
bun-version: 1.3.14

- name: Run Python tests with coverage
env:
GEMINI_API_KEY: test_key_for_ci
run: |
pytest test_main.py test_logging.py test_taste_compass.py test_recommendations.py -v \
--cov=main --cov=logging_config --cov=config \
--cov=prompt_builder --cov=api --cov=services \
--cov=utils --cov=models \
--cov-report=xml --cov-report=term-missing
- name: Setup Bun (attempt 2)
id: setup_bun_2
if: steps.setup_bun_1.outcome == 'failure'
continue-on-error: true
uses: oven-sh/setup-bun@v2
with:
bun-version: 1.3.14

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v7
- name: Setup Bun (attempt 3)
if: steps.setup_bun_2.outcome == 'failure'
uses: oven-sh/setup-bun@v2
with:
files: ./apps/server/coverage.xml
flags: relay
name: server-coverage
bun-version: 1.3.14

- name: Install @metic/core dependencies
working-directory: packages/core
run: bun install --frozen-lockfile

- name: Typecheck @metic/core
working-directory: packages/core
run: bunx tsc --noEmit

- name: Run @metic/core contract + unit tests
working-directory: packages/core
run: bunx vitest run

- name: Install apps/bun-server dependencies
working-directory: apps/bun-server
run: bun install --frozen-lockfile

- name: Check coverage threshold
run: coverage report --fail-under=68
- name: Typecheck apps/bun-server
working-directory: apps/bun-server
run: bunx tsc --noEmit

- name: Run apps/bun-server tests
working-directory: apps/bun-server
run: bun test

# ============================================================================
# Web Frontend Tests (TypeScript/React)
Expand Down Expand Up @@ -212,6 +227,20 @@ jobs:
cache-from: type=gha
cache-to: type=gha,mode=max

- name: Enforce image size gate
run: |
# The 3.0.0 distroless single-binary image is a single Bun process
# (no Python/nginx/mosquitto/s6). Guard against accidental bloat.
# Threshold is the uncompressed size reported by `docker images`.
MAX_MB=260
SIZE_BYTES=$(docker image inspect meticai:test --format '{{.Size}}')
SIZE_MB=$(( SIZE_BYTES / 1024 / 1024 ))
echo "Unified image size: ${SIZE_MB} MB (limit ${MAX_MB} MB)"
if [ "${SIZE_MB}" -gt "${MAX_MB}" ]; then
echo "::error::Image size ${SIZE_MB} MB exceeds the ${MAX_MB} MB gate"
exit 1
fi

- name: Test container starts
run: |
docker run -d --name test-container \
Expand All @@ -226,8 +255,9 @@ jobs:
# Check container is running
docker ps | grep test-container

# Check health endpoint
docker exec test-container curl -f http://localhost:3550/health || exit 1
# Check health endpoint. The distroless image has no shell/curl, so
# probe via the binary's own healthcheck subcommand.
docker exec test-container /app/metic healthcheck || exit 1

- name: Setup Bun (attempt 1)
id: setup_bun_1
Expand Down Expand Up @@ -295,22 +325,6 @@ jobs:
with:
submodules: recursive

- name: Set up Python 3.13
uses: actions/setup-python@v6
with:
python-version: "3.13"

- name: Install Python linting tools
run: pip install ruff black

- name: Run ruff on relay
run: ruff check apps/server/
continue-on-error: true

- name: Check Python formatting
run: black --check apps/server/
continue-on-error: true

- name: Setup Bun (attempt 1)
id: setup_bun_1
continue-on-error: true
Expand Down
12 changes: 12 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# .gitignore

# Node
node_modules/
packages/*/dist/

# Secrets
.env
tasks.md
Expand Down Expand Up @@ -39,6 +43,8 @@ htmlcov/
data/
!data/PourOverBase.json
!data/recipes/
!packages/core/src/data/
!packages/core/src/data/**

# Update tracking
.versions.json
Expand Down Expand Up @@ -84,3 +90,9 @@ testflight.md

# Brainstorming visual companion
.superpowers/

# TypeScript incremental build info
*.tsbuildinfo

# Bun compile temp artifacts
*.bun-build
3 changes: 0 additions & 3 deletions .gitmodules

This file was deleted.

6 changes: 6 additions & 0 deletions HOME_ASSISTANT.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# 🏠 Home Assistant Integration

> **⚠️ Removed in 3.0.0.** The MQTT bridge (Mosquitto broker + meticulous-addon)
> was removed when the Python backend was replaced by the unified Bun server.
> Home Assistant auto-discovery is no longer available. Live telemetry and
> machine control remain fully functional inside Metic via the built-in
> `/api/ws/live` WebSocket. This document is retained for users still on 2.x.

Connect Metic to Home Assistant to get real-time espresso machine telemetry, create automations, and control your Meticulous from HA dashboards.

## How It Works
Expand Down
Loading
Loading