Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
31d633f
feat(cli): pass chDB config file to local server
Jun 25, 2026
8be7e3e
feat(cli): add local chDB checkpoint command
Jun 25, 2026
19c0530
feat(cli): restore dirty local store from checkpoint
Jun 25, 2026
3fa344f
fix(cli): harden chDB checkpoint recovery
Jun 26, 2026
bbe6be3
Merge branch 'main' into codex/chdb-checkpoints
Makisuo Jun 30, 2026
44c51e8
fix(cli): make checkpoints immutable and durable
Jun 27, 2026
1bd2815
fix(cli): reconcile interrupted checkpoint restores
Jun 27, 2026
e78435d
fix(cli): preserve checkpoints across recovery
Jun 28, 2026
ecfae14
fix(cli): make retirement cleanup restart-safe
Jun 28, 2026
3278b59
fix(cli): journal destructive store resets
Jun 28, 2026
8b577fe
feat(cli): checkpoint pins, maintenance lock, and archive foundation
Jun 28, 2026
57ebfde
feat(cli): centralized archive tuning configuration
Jun 28, 2026
399a076
feat(cli): archive generation write path with durable promotion
Jun 28, 2026
96e9976
feat(cli): archive listing, active parquet paths, and catalog rebuild
Jun 28, 2026
53ab525
feat(cli): maple archive command group
Jun 28, 2026
0cd11d6
docs: local telemetry archives architecture and operator guide
Jun 28, 2026
a931fc5
feat(cli): native archive smoke and DuckDB acceptance
Jun 28, 2026
e8d917a
feat(cli): archive calibration with candidate matrix and generated co…
Jun 28, 2026
7bf55eb
fix(archives): close archive-root symlink escapes and bind state to l…
Jun 28, 2026
22c328c
fix(archives): close read-side symlink escapes (HIGH-1/HIGH-2 from R1…
Jun 28, 2026
6dc8e19
fix(archives): fail-closed listing, rebuild preflight, mandatory root…
Jun 28, 2026
c7b38a7
fix(archives): bounded sharding and pre-promotion Parquet reopen vali…
Jun 28, 2026
8526b59
fix(archives): deterministic sharding, schema/hour/byte validation, p…
Jun 28, 2026
2a9dc31
test(archives): pin export path-safety invariants (single-quote/backs…
Jun 28, 2026
f45f13d
fix(archives): repair runtime incompatibilities and strictness gaps (…
Jun 29, 2026
cd34b7a
fix(archives): timezone, schema normalization, and smoke determinism
Jun 29, 2026
9de7394
fix(archives): merge-safe static-snapshot part-interval sharding (CRI…
Jun 29, 2026
ea3850d
fix(archives): verify shard SHA-256 and byte size against manifest (t…
Jun 29, 2026
48cc7f3
fix(archives): merge freeze, source-interval validation, exact schema…
Jun 29, 2026
8b64729
test(archives): adversarial merge-injection probe (Gate 2 cross-check…
Jun 29, 2026
ddf969c
feat(archives): repair Gate 2 round-4 (non-contiguous offsets, schema…
Jun 29, 2026
528112d
fix(archives): non-commutative digest, authoritative byte refinement,…
Jun 29, 2026
82d1294
test(archives): permanent adversarial validation matrix (Gate 2 round 5)
Jun 29, 2026
445a3d2
fix(archives): NULL-safe multiset digest + fail-closed digest algorit…
Jun 29, 2026
c668376
fix(archives): explicit NULL flag in digest (invariant alignment, Gat…
Jun 29, 2026
46b64f8
feat(checkpoints): additive seams for crash-safe archive generation (…
Jun 29, 2026
5aca8ca
feat(archives): crash-safe generation journal + automatic reconciliat…
Jun 29, 2026
0ff7d0b
test(archives): authoritative SIGKILL crash-recovery harness (Gate 3a)
Jun 29, 2026
eaa5b27
fix(archives): bind crash recovery to durable owned state
Jun 30, 2026
87e3dda
test(archives): make SIGKILL recovery oracle exact
Jun 30, 2026
b5883cc
fix(archives): tighten aborted journal and crash oracles
Jun 30, 2026
c181b3e
fix(archives): preserve legitimate restored-store symlinks
Jun 30, 2026
27dbc65
fix(archives): verify observed crash-recovery invariants
Jun 30, 2026
35de158
style(archives): format crash-recovery matrix
Jun 30, 2026
6ec3ccd
feat(archives): v3 operation journal with kind discriminator + v2 mig…
Jun 30, 2026
ea836b0
feat(archives): conservative journaled GC with tombstone-based collec…
Jun 30, 2026
edea4a8
feat(cli): archive reconcile + archive gc subcommands (Gate 3b)
Jun 30, 2026
37a3793
test(archives): interrupted-GC SIGKILL oracle + hostile GC tests + ma…
Jun 30, 2026
13f64b7
fix(archives): GC state machine, locked reconcile, nonmutation, missi…
Jun 30, 2026
f544ec2
fix(archives): strict locked reconcile wrapper — v2 action, fail-clos…
Jun 30, 2026
55fde0b
fix(archives): reconciliation as one locked protocol with concrete ac…
Jun 30, 2026
ebe93b0
feat(archives): pure reconciliation decision engine — the single tran…
Jun 30, 2026
b541cd4
fix(archives): single reconciliation engine — one inspector, one pure…
Jun 30, 2026
8d37f3b
fix(archives): make the pure decision operative — executor switches o…
Jun 30, 2026
4b56d71
fix(archives): complete preflight, split GC helpers, parity test (Gat…
Jul 1, 2026
2b8797d
fix(archives): exhaustive GC preflight + symlink-aware collision chec…
Jul 1, 2026
6e1b41a
fix(archives): lstat-aware topology classifier + strict suffix/prefix…
Jul 1, 2026
4a29908
fix(archives): enforce root-aware reconciliation topology
Jul 1, 2026
f1772a2
feat(archive): harden calibration and config loading
Jul 1, 2026
5178ce8
docs(archive): operator/architecture guide and draft PR narrative (R9)
Jul 1, 2026
83b395b
fix(archive): strict manifests, session calibration, semantic config,…
Jul 2, 2026
14f13ef
fix(archive): canonical tolerances, strict pin identity, larger disjo…
Jul 2, 2026
d7fc301
fix(archive): larger persisted held-out scope + hybrid size-scaled co…
Jul 2, 2026
04ed309
fix(archive): enforce held-out cardinality and release fault seam
Jul 2, 2026
a1328a0
fix(archive): per-signal like-for-like held-out hybrid comparison
Jul 3, 2026
ef471ba
fix(archive): align incomplete calibration evidence
Jul 3, 2026
94d93d3
docs(archive): remove draft PR body from branch
Jul 9, 2026
3e75e01
fix(archive): make calibration measurement directional
Jul 10, 2026
e99d885
fix(archive): validate directional held-out costs
Jul 10, 2026
269053b
fix(archive): version directional calibration configs
Jul 10, 2026
1378ecc
fix(cli): report calibration failures through Effect
Jul 10, 2026
8330749
fix(cli): render archive errors without stacks
Jul 10, 2026
c1a8ce0
Merge branch 'main' into codex/local-telemetry-archives-impl
Makisuo Jul 11, 2026
4fdcbb7
fix(cli): require repeatable checkpoint reopen
Jul 12, 2026
6c25f76
fix(cli): validate archive calibration budgets
Jul 12, 2026
a7700b2
fix(cli): validate archive calibration child output
Jul 12, 2026
ec2fccd
fix(cli): preflight archive restore volumes
Jul 12, 2026
4948e80
fix(cli): stream archive integrity verification
Jul 12, 2026
e814df6
Merge PR #129 checkpoint reopen fix into archive branch
Jul 12, 2026
d02fbbe
fix(cli): serialize checkpoint restore workers
Jul 12, 2026
12a427b
Merge PR #129 restore serialization fix into archive branch
Jul 12, 2026
2a21451
Merge current main into PR #129
Jul 12, 2026
9bc3b0b
Merge updated PR #129 into archive branch
Jul 12, 2026
6bbfdb7
test(cli): require native archive recovery CI
Jul 12, 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
86 changes: 85 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,98 @@ jobs:

# shellcheck is preinstalled on the ubuntu-latest runner image.
- name: shellcheck
run: shellcheck scripts/install.sh scripts/uninstall.sh scripts/build-local-binary.sh
run: >-
shellcheck scripts/install.sh scripts/uninstall.sh scripts/build-local-binary.sh
apps/cli/test/native-checkpoint-smoke.sh
apps/cli/test/native-archive-smoke.sh
apps/cli/test/native-archive-crash-recovery-probe.sh

# Syntax-check the POSIX installers against the actual /bin/sh they claim.
- name: sh -n
run: |
sh -n scripts/install.sh
sh -n scripts/uninstall.sh

local-checkpoint-native:
name: Local checkpoint native
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6

- uses: jdx/mise-action@c37c93293d6b742fc901e1406b8f764f6fb19dac # v2.4.4

- run: bun install --frozen-lockfile

- name: Build native local bundle
run: scripts/build-local-binary.sh

- name: Run repeated checkpoint restore and fresh-process reopen smoke
env:
KEEP_ROOT: "1"
TMPDIR: ${{ runner.temp }}/maple-native-checkpoint
run: |
mkdir -p "$TMPDIR"
apps/cli/test/native-checkpoint-smoke.sh "$GITHUB_WORKSPACE/dist"

- name: Upload checkpoint failure evidence
if: ${{ failure() }}
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4
with:
name: native-checkpoint-failure-${{ github.run_id }}
path: ${{ runner.temp }}/maple-native-checkpoint
if-no-files-found: ignore

local-archive-native:
name: Local archive native
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6

- uses: jdx/mise-action@c37c93293d6b742fc901e1406b8f764f6fb19dac # v2.4.4

- run: bun install --frozen-lockfile

- name: Install pinned DuckDB CLI
run: |
curl -fsSL https://github.com/duckdb/duckdb/releases/download/v1.5.3/duckdb_cli-linux-amd64.gz \
-o "$RUNNER_TEMP/duckdb.gz"
echo "f05f3b448a9a1bc6e7ac27ff14dfe67bf5761b153c2002723365a456618ef35b $RUNNER_TEMP/duckdb.gz" \
| sha256sum --check --strict
gunzip "$RUNNER_TEMP/duckdb.gz"
chmod +x "$RUNNER_TEMP/duckdb"
echo "$RUNNER_TEMP" >> "$GITHUB_PATH"

- name: Build native local bundle
run: scripts/build-local-binary.sh

- name: Run archive lifecycle smoke
env:
KEEP_ROOT: "1"
TMPDIR: ${{ runner.temp }}/maple-native-archive
run: |
mkdir -p "$TMPDIR"
apps/cli/test/native-archive-smoke.sh "$GITHUB_WORKSPACE/dist"

- name: Run archive crash-recovery boundaries
env:
KEEP_ROOT: "1"
TMPDIR: ${{ runner.temp }}/maple-native-archive-recovery
run: |
mkdir -p "$TMPDIR"
apps/cli/test/native-archive-crash-recovery-probe.sh "$GITHUB_WORKSPACE/dist"

- name: Upload archive failure evidence
if: ${{ failure() }}
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4
with:
name: native-archive-failure-${{ github.run_id }}
path: |
${{ runner.temp }}/maple-native-archive
${{ runner.temp }}/maple-native-archive-recovery
if-no-files-found: ignore

service-map-perf:
name: Service Map Perf
runs-on: ubuntu-latest
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,5 @@ playwright/.cache/

# local-only Drizzle Studio config pointing at miniflare D1
drizzle.config.local.ts
.18bd7*.bun-build
.[0-9a-f]*.bun-build
2 changes: 1 addition & 1 deletion apps/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"type": "module",
"scripts": {
"start": "bun run src/bin.ts",
"test": "vitest run",
"test": "bun test test/*.test.ts",
"typecheck": "tsc --noEmit"
},
"dependencies": {
Expand Down
39 changes: 32 additions & 7 deletions apps/cli/src/bin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { Mode } from "./core/mode"
import { TelemetryLayer } from "./core/telemetry"
import { maybeNotifyUpdate } from "./core/update"
import { WarehouseExecutorFromMode } from "./core/warehouse"
import { archiveErrorMessage } from "./server/archives/errors"
import { CHECKPOINT_REOPEN_PROBE_ENV, validateCheckpointDataDir } from "./server/checkpoints"
import { MAPLE_VERSION } from "./version"

// WarehouseExecutorFromMode needs Mode (which needs MapleConfig). provideMerge
Expand All @@ -31,10 +33,33 @@ const MainLayer = WarehouseExecutorFromMode.pipe(
// exporter flushes when its layer scope closes, and only the outermost provide's
// scope is the runtime's main scope that `BunRuntime.runMain` closes on exit.
// Merging it into MainLayer leaves spans unflushed for short-lived commands.
maybeNotifyUpdate.pipe(
Effect.flatMap(() => Command.run(cli, { version: MAPLE_VERSION })),
Effect.withSpan("maple", { attributes: { "cli.argv": process.argv.slice(2).join(" ") } }),
Effect.provide(MainLayer),
Effect.provide(TelemetryLayer),
BunRuntime.runMain,
)
const checkpointProbeDataDir = process.env[CHECKPOINT_REOPEN_PROBE_ENV]

if (checkpointProbeDataDir !== undefined) {
// Private re-exec path used by checkpoint restore. It intentionally bypasses
// CLI dispatch, update checks, telemetry, and schema bootstrap: success means
// this new process loaded the persisted restored representation and queried
// its core tables before closing chDB cleanly.
try {
process.stdout.write(`${JSON.stringify(validateCheckpointDataDir(checkpointProbeDataDir))}\n`)
} catch (error) {
process.stderr.write(
`checkpoint reopen probe failed: ${error instanceof Error ? error.message : String(error)}\n`,
)
process.exitCode = 1
}
} else {
maybeNotifyUpdate.pipe(
Effect.flatMap(() => Command.run(cli, { version: MAPLE_VERSION })),
Effect.withSpan("maple", { attributes: { "cli.argv": process.argv.slice(2).join(" ") } }),
Effect.catchTag("@maple/cli/ArchiveError", (error) =>
Effect.sync(() => {
process.stderr.write(archiveErrorMessage(error))
process.exitCode = 1
}),
),
Effect.provide(MainLayer),
Effect.provide(TelemetryLayer),
BunRuntime.runMain,
)
}
7 changes: 6 additions & 1 deletion apps/cli/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import { metrics, query } from "./commands/data"
import { timeseries, breakdown, compare } from "./commands/analytics"
import { login, logout, whoami } from "./commands/auth"
import { use } from "./commands/config"
import { start, stop, reset } from "./commands/server"
import { start, stop, reset, checkpoint, restore } from "./commands/server"
import { archive } from "./commands/archive"
import { update } from "./commands/update"

// One CLI, two backends. Every query command bottoms out at the shared
Expand Down Expand Up @@ -46,6 +47,10 @@ export const cli = Command.make("maple").pipe(
start,
stop,
reset,
checkpoint,
restore,
// Parquet archives (local mode)
archive,
// Self-update
update,
// Services
Expand Down
Loading