Skip to content

v1.6.19

Choose a tag to compare

@marmutapp marmutapp released this 19 May 19:23
· 31 commits to main since this release

chore(release): public-repo GitHub Release with per-platform binary archives

Adds direct-download binaries on the public repo's Releases tab so
users who don't want to install via npm can curl the right archive
for their architecture. Builds on the existing cross-compile pipeline
that already produces the 5 platform binaries for npm — same
artifacts, now also surfaced as tarball/zip downloads on
github.com/marmutapp/superbased-observer/releases.

What ships per release:

Asset Platform Contents
observer-vX.Y.Z-linux-x64.tar.gz Linux x86_64 observer + antigravity-bridge.exe
observer-vX.Y.Z-linux-arm64.tar.gz Linux arm64 observer + antigravity-bridge.exe
observer-vX.Y.Z-darwin-x64.tar.gz macOS Intel observer
observer-vX.Y.Z-darwin-arm64.tar.gz macOS Apple Silicon observer
observer-vX.Y.Z-win32-x64.zip Windows x86_64 observer.exe
SHA256SUMS — sha256 of all 5 archives, verifiable via shasum -a 256 -c

Pipeline changes:

  • scripts/release.sh public now accepts an optional <version> arg.
    When set, it force-pushes the same v* tag to the public remote
    pointing at the orphan commit's sha. scripts/release.sh full <version> passes the version through automatically; the legacy
    scripts/release.sh public (no version) form still works for
    tree-only refreshes that don't bump the release version.
  • .github/workflows/npm-release.yml gains a public_release job
    that runs in parallel with publish (only needs build), waits
    for the v* tag to exist on the public repo (polls up to 2 min),
    bundles each platform's bin/ folder into a tarball or zip,
    computes SHA256SUMS, and calls gh release create --repo marmutapp/superbased-observer. Idempotent on retry — uses
    gh release edit + gh release upload --clobber if the release
    already exists.
  • New repo secret on the private repo: PUBLIC_REPO_TOKEN. Fine-
    grained PAT with contents: write on the public repo only. Must
    be set before the v1.6.19 tag lands
    or the new job will fail
    with a gh: HTTP 404 from the release-create step. Setup steps
    in docs/release-runbook.md under "Required CI secret".

Backwards compatibility: existing npm distribution flow is
unchanged. The public_release job is additive; if it fails (e.g.
missing PAT, public-tag push lagged), the npm publish + private
GH Release jobs are unaffected. Re-running the failed job after
fixing the underlying cause picks up where it left off.

Body composition: the public Release notes are the matching
CHANGELOG.md section plus a ### Downloads addendum that lists the
five archives, verification command, and a pointer to the npm
package for users who prefer that install path. Same extraction
logic as the private release job — awk from ## [<version>] to
the next ## [ header.

fix(store): copilot-cli rescan FK 787 — stale LastInsertId on UPSERT-UPDATE

User on a Windows-native daemon reported repeated rescan failures:

watcher.Scan: process failed adapter=copilot-cli
  path=C:\Users\sdrona\.copilot\session-state\<uuid>\events.jsonl
  err="freshness.UpsertFileState: constraint failed: FOREIGN KEY constraint failed (787)"

8 of 79 copilot-cli session files erroring per rescan cycle. Root
cause: the single-row insertSingleAction path (internal/store/store.go:1124)
takes LastInsertId() unconditionally after INSERT ... ON CONFLICT DO UPDATE. Per SQLite docs, UPSERTs that take the UPDATE branch
do not change last_insert_rowid — so on a re-scan that hits the
UPDATE branch, LastInsertId() returns the connection's previous
true-INSERT rowid. If retention has pruned that earlier row,
UpsertFileState then writes the stale last_action_id and trips
the actions(id) foreign-key constraint (SQLITE_CONSTRAINT_FOREIGNKEY,
extended code 787).

The batch InsertActions path (lines 290–428) already documented
and handled this exact issue with an existence pre-check (see its
inline comment at line 314). The single-row path didn't. This ship
brings the single-row path in line:

  • Add the same SELECT id FROM actions WHERE source_file = ? AND source_event_id = ?
    pre-check before the UPSERT.
  • On the UPDATE branch (row already existed): bind a.ID to the
    pre-check's existingID, so downstream UpsertFileState writes
    a valid last_action_id.
  • On the INSERT branch (no pre-existing row): keep using
    LastInsertId(), which is reliable for genuine inserts.

Regression test pins the bug with the user's exact error message:
TestIngestFileAction_RescanAfterRetentionDoesNotFKFail in
internal/store/store_test.go reproduces the failure pre-fix (FK
787 surfaces in err.Error()) and passes post-fix. The test pins
db.SetMaxOpenConns(1) so the connection-level LastInsertId
staleness carries deterministically across operations — same regime
as a long-running daemon doing serial work on a single
high-contention connection.

No DB migration. No daemon restart required for users who upgrade
across this version — but the existing erroring sessions on disk
will keep producing the same warnings until the rescan runs against
the v1.6.19 binary.

chore(antigravity,cost): adapter audit + Gemini 3.x Pro/Flash pricing pins

Bundles the deliverables from the end-to-end Antigravity adapter
audit at docs/antigravity-audit-2026-05-19.md. The audit followed
docs/adapter-audit-playbook.md against the live antigravity corpus
(8,808 rows / 4 source-mounts / 7 distinct model SKUs) and the four
live Gemini sessions served by the running Linux-native
language_server processes.

Headline finding resolved as a non-bug. The kickoff doc's flagged
signal — "reasoning_tokens = 0 across all 8,808 antigravity rows
despite adapter wiring at structured.go:394" — turned out to be a
stale-corpus artifact. Every row in the live DB predates commit
6d37da7 (v1.4.53, 2026-05-15) which replaced case 3: r.output = f.Varint with case 9: r.reasoning + case 10: r.output. Live probes
(TestTokenRowDump + TestStructuredReasoningTokenCapture) confirm
the production parser correctly emits non-zero ReasoningTokens for
fresh Gemini sessions (e.g. 162c4ab9 turn 0: .9 = 598, .10 = 28). Aggregate cost is unchanged because .3 == .9 + .10 and
reasoning bills at the output rate (memory
[[feedback-reasoning-tokens-billed]]) — pre-v1.4.53 .3 × output_rate ≡ post-v1.4.53 (.9 + .10) × output_rate.

Five verified-correct surfaces (G-ok-1 through G-ok-5):

  • Field-map complete for 1.3.1.17.2.* usage; 1.3.1.17.3 =
    error/status strings (correctly skipped); 1.3.1.17.4 = 16-byte
    trace IDs (non-token); 1.3.1.4.* mirrors 1.3.1.17.2.* per turn
    (parallel duplicate emit; capturing only one is correct).
  • Cross-tier emit is mutually exclusive by construction (Path A
    classify() vs Path B applyStructuredEnrichment()). Live data is
    100% structured tier (all 8,808 eventIDs start with
    antigravity-struct-token:); zero classify-tier rows.
  • Re-parse idempotency intact: zero duplicate (source_file, source_event_id) tuples across all 8,808 rows.
  • Store-layer dedup correctly excludes antigravity — all four
    DELETE FROM token_usage sweeps in internal/store/store.go are
    scoped to other tools (copilot-cli ×2, claude-code+codex
    tuple-dedup, claude-code snapshot-drift).

Actionable findings shipped:

  1. Gemini 3.5 Flash added — gemini-3.5-flash exact entry pinned
    at Standard-tier rates per Google's Developer API pricing card
    (2026-05-19): Input $1.50 / Output $9.00 / CacheRead $0.15 per
    1M tokens. The entry also serves as a family prefix via
    familyKeys(), so gemini-3.5-flash-experimental (or any future
    flash-suffix SKU) resolves to Flash rates rather than falling to
    the gemini-3 Pro-family entry. Google has no gemini-3.5-pro
    on its official pricing page as of this date — hypothetical 3.5
    Pro SKUs deliberately fall through gemini-3.5-flash (prefix
    doesn't match) to the gemini-3 family (Pro rates), the
    conservative default. Batch / Flex / Priority tiers and grounding
    per-query fees ($14/1000 = $0.014/call) are NOT modelled —
    per-tier pricing and GroundingPerRequest field structural work
    remains in Workstream B (kickoff doc post-v1.6.18 §2). Per-hour
    cache storage ($1/1M tokens/hr) also deferred — shape doesn't
    fit the current per-call Pricing struct.

  2. B1 — Gemini 3 Flash family-prefix resilience
    gemini-3-flash-<unknown> SKUs (any hypothetical Flash variant
    not pinned in the explicit -preview/-agent/-high/-medium/-low
    set) fall through the family-prefix matcher to the gemini-3
    family and bill at Pro rates ($2/$12 + LC ladder) instead of
    Flash ($0.50/$3) — ~4× over-bill. Gemini 2.5 is robust because
    gemini-2.5-flash and gemini-2.5-flash-lite are both pinned as
    family entries. Adds the missing gemini-3-flash family-prefix
    entry at Flash rates. Zero current live rows affected; pure
    resilience against future Antigravity SKUs.

  3. B2 — Gemini 3 Pro effort SKUs pinned explicitly
    gemini-3-pro-{low,medium,high} were not pinned. 3,831 live
    gemini-3-pro-high rows resolved correctly via the gemini-3
    family-prefix fallback (Pro rates by coincidence), but the
    resolution is load-bearing on the matcher. Three new explicit
    entries paralleling the existing gemini-3.1-pro-* set. Zero
    behavioral change for any current row; pure resilience.

  4. C1 — probe_e371fdb1_test.go removed (164 lines).
    Added in v1.6.11 to investigate session e371fdb1 being "not at
    all being picked up". That session now extracts 17 rows / 17,595
    input tokens in the live DB — the underlying wrong-workspace-stub
    bug was fixed. Probe has served its purpose.

Test coverage added:

  • TestTable_AntigravityInternalSKUs extended with three subtests
    pinning gemini-3-pro-{high,medium,low} to PricingSourceExact.
  • New TestTable_Gemini3FlashFamilyResilience locks in the
    Flash-family fallback (asserts gemini-3-flash-experimental /
    gemini-3-flash-foo-bar resolve to Flash rates, not Pro rates).

Carry-forward (operator decisions, documented in audit doc §X1/X2):

  • 8,808 historical rows could be back-filled with reasoning
    breakdown by invalidating their parse cursors. Aggregate cost is
    already correct; this updates the per-row column only. Most rows
    source from Windows-side .pb files (non-decryptable locally
    per [[project-antigravity-windows-cipher]]).
  • 310 blank-model rows across 3 .pb files (160 file-missing, 150
    in-disk). Self-correctable for the 150 via parse-cursor reset; the
    current parser may resolve a model on re-attempt. Outcome
    unverified pre-action.
  • Explicit gemini-3.1-flash and gemini-3.1-flash-lite family
    pins deferred pending an authoritative pricing card distinguishing
    3.1 Flash full from 3.1 Flash-Lite. Workstream B (pricing audit)
    follow-up.

What didn't change:

  • The antigravity adapter source (internal/adapter/antigravity/*.go)
    is unchanged except for the probe deletion. The wiring is correct
    as of v1.4.53; the audit confirmed it.
  • No schema migration. Schema stays at version 25.
  • No daemon restart required — cost is computed at read time, so
    pricing.go edits take effect on the next dashboard query.

Downloads

Pre-built binaries for each supported platform are attached below. Linux variants bundle antigravity-bridge.exe next to the observer binary for WSL2 users of the Antigravity adapter.

Platform Asset
Linux x86_64 observer-v1.6.19-linux-x64.tar.gz
Linux arm64 observer-v1.6.19-linux-arm64.tar.gz
macOS x86_64 (Intel) observer-v1.6.19-darwin-x64.tar.gz
macOS arm64 (Apple Silicon) observer-v1.6.19-darwin-arm64.tar.gz
Windows x86_64 observer-v1.6.19-win32-x64.zip

Verify with sha256sum -c SHA256SUMS (or shasum -a 256 -c SHA256SUMS on macOS) from the directory containing the downloads.

Also available via npm: npm install -g @superbased/observer@1.6.19