Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
a2e0a2b
docs: start v1.13.12 engine completion train
Aug 19, 2026
b339855
release: activate v1.13.12 identity and inventory
Aug 19, 2026
87f74b5
engine: add typed error and neutrality foundation
Aug 19, 2026
2d54d58
engine: neutralize stats inspect trace and verify contracts
Aug 19, 2026
0d3b69b
catalog: replace provisional planning contracts
Aug 19, 2026
bdb6d1e
catalog: implement snapshot graph planning
Aug 19, 2026
75837ca
catalog: implement chunk placement loading
Aug 19, 2026
536f5f1
catalog: implement restore plan metadata
Aug 19, 2026
747cba2
Complete v1.13.12 restore plan adoption
Aug 19, 2026
8f8c01b
Complete v1.13.12 GC catalog planning
Aug 19, 2026
c1fef7e
Complete v1.13.12 folder store ownership
Aug 19, 2026
27f3b03
Complete v1.13.12 list and search ownership
Aug 19, 2026
e1d5e53
Complete v1.13.12 configuration ownership
Aug 19, 2026
962a5bb
Complete snapshot read-side engine ownership
Aug 19, 2026
f3eb713
Route inspect stats and verify through engine
Aug 19, 2026
9159591
Activate engine-owned repair orchestration
Aug 19, 2026
ccf9040
Activate engine-owned recovery orchestration
Aug 19, 2026
27f1fec
Activate engine-owned doctor orchestration
Aug 19, 2026
1828e10
Close application composition and thin CLI boundary
Aug 19, 2026
27505fd
Harden engine and catalog contracts
Aug 19, 2026
5fd8984
Complete compatibility and adversarial regression
Aug 19, 2026
39bed34
fix(ci): reconcile v1.13.12 hosted quality
Aug 19, 2026
771b28f
fix(ci): quote candidate linter executable
Aug 19, 2026
bd00617
fix(security): bound integer conversions
Aug 19, 2026
2776f04
fix(security): bound inspect float conversions
Aug 20, 2026
f6cf721
fix(catalog): make GC root reads coherent
Aug 20, 2026
33aa1a5
fix(security): preserve exact unsigned inspect integers
Aug 20, 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
20 changes: 19 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ jobs:

- name: Enforce versioned row writer scope
run: bash scripts/check_versioned_row_writers.sh

- name: Test candidate lint gate contract
run: go test -count=1 ./scripts -run '^TestCandidateLintGate'

- name: Lint
uses: golangci/golangci-lint-action@v9
Expand Down Expand Up @@ -298,10 +301,15 @@ jobs:
"github.com/franchoy/coldkeep/internal/catalog": [
r"^TestCatalogContractFindLogicalFileAcrossBackends/postgres$",
r"^TestCatalogContractFindPhysicalFilesAcrossBackends/postgres$",
r"^TestCatalogContractCurrentFileQueriesAcrossBackends/postgres$",
r"^TestCatalogContractRepositoryConfigurationAcrossBackends/postgres$",
r"^TestCatalogContractFindSnapshotAcrossBackends/postgres$",
r"^TestCatalogContractListSnapshotsAcrossBackends/postgres$",
r"^TestCatalogContractLoadReachabilityRootsAcrossBackends/postgres$",
r"^TestCatalogContractDeferredMethodsAcrossBackends/postgres$",
r"^TestCatalogContractSnapshotGraphAcrossBackends/postgres$",
r"^TestCatalogContractGCPlansAcrossBackends/postgres$",
r"^TestCatalogContractChunkPlacementsAcrossBackends/postgres$",
r"^TestCatalogContractRestorePlansAcrossBackends/postgres$",
],
"github.com/franchoy/coldkeep/internal/db": [
r"^TestEnsurePostgresSchemaAutoMigratesVersionElevenToTwelve$",
Expand All @@ -321,6 +329,10 @@ jobs:
],
"github.com/franchoy/coldkeep/internal/engine": [
r"^TestRemoveByIDPostgresPreservesSharedChunks$",
r"^TestEngineCurrentFilesAndConfigurationAcrossBackends/postgres$",
r"^TestEngineDoctorAcrossBackends/postgres$",
r"^TestEngineGarbageCollectionPlanAcrossBackends/postgres$",
r"^TestEngineStoreFolderAcrossBackends/postgres$",
r"^TestEngineReadStatsAndInspectAcrossBackends/postgres$",
r"^TestEngineReadSnapshotViewsAcrossBackends/postgres$",
r"^TestEngineReadVerifyAcrossBackends/postgres$",
Expand All @@ -332,6 +344,12 @@ jobs:
r"^TestEngineMutationRestoreAcrossBackends/postgres$",
r"^TestEngineMutationErrorsAcrossBackends/postgres$",
r"^TestEngineGCDryRunAcrossBackends/postgres$",
r"^TestEngineRecoverAcrossBackendsAndIsIdempotent/postgres$",
r"^TestEngineRecoverFaultAndCancellationAcrossBackends/postgres$",
r"^TestEngineRepairAcrossBackends/postgres$",
r"^TestEngineRepairValidationOrderingAcrossBackends/postgres$",
r"^TestEngineRepairTypedBoundaryErrors/postgres$",
r"^TestEngineRepairFailFastOnInvariantViolation/postgres$",
],
"github.com/franchoy/coldkeep/internal/maintenance": [
r"^TestGCAdvisoryLockUsesDedicatedSessionAndReleases$",
Expand Down
36 changes: 35 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,41 @@ project, do not start here; start with [README.md](README.md).

------------------------------------------------------------------------

## v1.13.11 - 2026-08-18 — Safety and Backend Compatibility Gate Closure
## v1.13.12 - Unreleased — Engine and Catalog Completion

- Started the mandatory architecture-completion release from exact v1.13.11
merge commit `507859daccf25594142c61e5ab8209a751fb579a`.
- Activated version 1.13.12 and froze the production ownership, compatibility,
catalog-adoption, and thin-CLI acceptance baseline.
- Added the stable backend-neutral engine error taxonomy, deterministic
translation helpers, invariant/cancellation preservation, and exhaustive
active-contract neutrality coverage with only the four explicit Phase 3
observability DTO debts temporarily allowlisted.
- Replaced Stats and Inspect observability-backed contracts with complete
engine-owned DTOs, exact tagged dynamic values, ordered trace events, and a
complete Verify summary while preserving the existing renderer output
through compatibility projection.
- Completed the catalog graph, placement, restore-plan, and GC-plan contracts
on SQLite and PostgreSQL and adopted each in its production path. Completed
engine ownership for folder store, list/search, configuration, snapshots,
inspect/stats/verify, repair, recovery/startup recovery, Doctor, and live GC
planning behind an application composition boundary and enforced thin-CLI
dependency guards.
- Completed the isolated compatibility and adversarial regression phase. Its
full PostgreSQL matrix caught and corrected Doctor session-open exit/message
projection drift; the restarted plain matrix, AES-GCM matrix, G1–G17
adversarial suite, coordination/advisory-session proofs, legacy fixture, and
post-correction full/race suites pass. Phase 21 exact-head candidate evidence
remains unrun.

------------------------------------------------------------------------

## v1.13.11 - 2026-08-19 — Safety and Backend Compatibility Gate Closure

- Published the stable v1.13.11 release from merge commit
`507859daccf25594142c61e5ab8209a751fb579a` after exact-head candidate,
hosted PR, main, tag, and release validation. This completes v1.13.11 but
does not close v1.x; v1.13.12 and v1.13.13 remain mandatory.

- Completed the Phase 20 pre-release state transition and froze the exact-head
candidate contract. The commit containing that contract must pass
Expand Down
4 changes: 2 additions & 2 deletions PRE_RELEASE_CHECKLIST.md
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ python3 scripts/validate_release_state.py --state auto

go build -o coldkeep ./cmd/coldkeep

expected_version="1.13.11"
expected_version="1.13.12"

human_version=$(./coldkeep version)
if [ "$human_version" != "coldkeep version $expected_version" ]; then
Expand Down Expand Up @@ -314,7 +314,7 @@ fi

Expected: local quality checks match CI intent and produce no diff or lint/format failures.

Expected: the built CLI reports exactly 1.13.11 in both human and JSON modes.
Expected: the built CLI reports exactly 1.13.12 in both human and JSON modes.
A version mismatch blocks Profile A and release approval.

Note: `scripts/clean_test_storage.sh` removes `./storage`, `.ci-storage`, and
Expand Down
19 changes: 10 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Coldkeep uses a visual identity based on an ice cube vault:
![CI](https://github.com/franchoy/coldkeep/actions/workflows/ci.yml/badge.svg)
![Go Version](https://img.shields.io/badge/go-1.25+-blue)
![License](https://img.shields.io/badge/license-Apache%202.0-blue)
![Status](https://img.shields.io/badge/status-v1.13.11%20ready%20for%20release-blue)
![Status](https://img.shields.io/badge/status-v1.13.12%20active-blue)
![Release](https://img.shields.io/github/v/release/franchoy/coldkeep?include_prereleases)

> Status: v1.9 formalizes transform-based storage semantics (logical/compressed/physical layers) with block-level compression and explicit staged verification, while preserving deterministic restore, GC safety, snapshot semantics, and mixed-repository compatibility.
Expand All @@ -35,14 +35,15 @@ a valid released baseline, but its earlier final-v1.x conclusion was superseded
after release by a roadmap-to-code audit that identified remaining
must-before-v2 work.

v1.13.11 has completed Phases 0–20 and is ready as a pre-release candidate for safety
and backend compatibility gate closure. One pull request is authorized only
after the immutable commit containing the final gate contract passes
candidate-head CI, Required Gate, CodeQL, and the complete clean local Profile
A gate. Merge, tag, and publication remain later operations. v1.13.12 and
v1.13.13 remain required follow-on releases; SQLite-first remains a future
local-product direction, PostgreSQL compatibility remains required, and v2.0
implementation has not started.
v1.13.11 is complete, merged, tagged, and published. It closed the safety and
backend-compatibility gate at merge commit
`507859daccf25594142c61e5ab8209a751fb579a` without closing v1.x as a whole.

v1.13.12 is the active release for mandatory engine and catalog completion.
v1.13.13 remains the required final independent v1.x and v2 handoff gate.
SQLite-default portable-repository productization remains a future v2.x
objective, PostgreSQL compatibility remains required, and v2.x implementation
is not authorized.

coldkeep is a local-first content-addressed storage engine focused on deterministic restore,
explicit integrity verification, and safe lifecycle behavior under failure scenarios.
Expand Down
25 changes: 25 additions & 0 deletions cmd/coldkeep/application_session.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package main

import (
"context"
"github.com/franchoy/coldkeep/internal/application"
"github.com/franchoy/coldkeep/internal/engine"
)

type commandSession interface {
Engine() engine.Engine
OperationContext(context.Context) (context.Context, context.CancelFunc)
Close() error
}

func openApplicationSession(req application.Request) (commandSession, error) {
return application.Open(req)
}

var openApplicationSessionPhase = openApplicationSession

func openCommandSession(operation string, requireStorage bool, containerDir string) (commandSession, error) {
return openApplicationSessionPhase(application.Request{
Operation: operation, RequireStorage: requireStorage, ContainerDir: containerDir,
})
}
10 changes: 5 additions & 5 deletions cmd/coldkeep/cli_boundary_preservation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ func TestRunRepairCommandDoesNotConstructEngine(t *testing.T) {
}
}

func TestRunDoctorCommandPreservesDirectRecoveryOwnership(t *testing.T) {
func TestRunDoctorCommandPreservesRecoveryFailureShortCircuitCompatibility(t *testing.T) {
originalRecovery := doctorRecoveryPhase
originalSchema := doctorSchemaVersionPhase
originalVerify := doctorVerifyPhase
Expand Down Expand Up @@ -361,7 +361,7 @@ func TestRunDoctorCommandPreservesDirectRecoveryOwnership(t *testing.T) {
t.Fatalf("expected recovery exit code %d, got %d", exitRecovery, got)
}
if !recoveryCalled {
t.Fatal("expected doctor to preserve direct recovery ownership")
t.Fatal("expected the legacy compatibility adapter to invoke recovery")
}
if schemaCalled {
t.Fatal("schema phase should not run after recovery failure")
Expand All @@ -371,7 +371,7 @@ func TestRunDoctorCommandPreservesDirectRecoveryOwnership(t *testing.T) {
}
}

func TestRunDoctorCommandDoesNotConstructEngine(t *testing.T) {
func TestRunDoctorLegacyCompatibilityDoesNotUseGenericCommandEngine(t *testing.T) {
originalRecovery := doctorRecoveryPhase
originalSchema := doctorSchemaVersionPhase
originalVerify := doctorVerifyPhase
Expand All @@ -388,7 +388,7 @@ func TestRunDoctorCommandDoesNotConstructEngine(t *testing.T) {
engineConstructed := false
newCommandEngine = func(_ *sql.DB, _ string) (engine.Engine, error) {
engineConstructed = true
t.Fatal("doctor should not construct an engine repair/recovery API")
t.Fatal("doctor compatibility adapter should not use the generic command-engine seam")
return nil, nil
}
doctorRecoveryPhase = func(string) (recovery.Report, error) {
Expand All @@ -412,6 +412,6 @@ func TestRunDoctorCommandDoesNotConstructEngine(t *testing.T) {
t.Fatalf("runDoctorCommand: %v", err)
}
if engineConstructed {
t.Fatal("doctor unexpectedly constructed an engine")
t.Fatal("doctor unexpectedly used the generic command-engine seam")
}
}
94 changes: 94 additions & 0 deletions cmd/coldkeep/configuration_engine_routing_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package main

import (
"context"
"database/sql"
"strings"
"testing"

"github.com/franchoy/coldkeep/internal/engine"
"github.com/franchoy/coldkeep/internal/storage"
)

func TestRunConfigGetUsesEngineJSONParity(t *testing.T) {
dbconn := openSnapshotRoutingDB(t)
level := int64(5)
installConfigurationCommandStubs(t, dbconn, stubCommandEngine{
getConfigurationFunc: func(_ context.Context, req engine.GetConfigurationRequest) (engine.GetConfigurationResult, error) {
if req.Key != engine.ConfigurationCompressionLevel {
t.Fatalf("unexpected configuration key: %s", req.Key)
}
return engine.GetConfigurationResult{Key: req.Key, Value: "5", IntegerValue: &level}, nil
},
})

output := captureStdout(t, func() {
if err := runConfigCommand(parsedCommandLine{
method: "config", positionals: []string{"get", "compression-level"},
}, outputModeJSON); err != nil {
t.Fatalf("runConfigCommand: %v", err)
}
})
if strings.TrimSpace(output) != `{"command":"config get","data":{"key":"compression-level","value":5},"status":"ok"}` {
t.Fatalf("unexpected config get JSON: %s", output)
}
}

func TestRunConfigSetUsesEngineAndChangedProjection(t *testing.T) {
dbconn := openSnapshotRoutingDB(t)
installConfigurationCommandStubs(t, dbconn, stubCommandEngine{
setConfigurationFunc: func(_ context.Context, req engine.SetConfigurationRequest) (engine.SetConfigurationResult, error) {
if req.Key != engine.ConfigurationCompression || req.Value != " zstd " {
t.Fatalf("unexpected SetConfiguration request: %+v", req)
}
return engine.SetConfigurationResult{Key: req.Key, Value: "zstd", Changed: true}, nil
},
})

output := captureStdout(t, func() {
if err := runConfigCommand(parsedCommandLine{
method: "config", positionals: []string{"set", "compression", " zstd "},
}, outputModeText); err != nil {
t.Fatalf("runConfigCommand: %v", err)
}
})
for _, want := range []string{"compression set to zstd", "This affects only NEW blocks", "Blocks remain readable"} {
if !strings.Contains(output, want) {
t.Fatalf("expected config set output to contain %q, got:\n%s", want, output)
}
}
}

func TestRunConfigSetMapsEngineValidationToUsage(t *testing.T) {
dbconn := openSnapshotRoutingDB(t)
installConfigurationCommandStubs(t, dbconn, stubCommandEngine{
setConfigurationFunc: func(context.Context, engine.SetConfigurationRequest) (engine.SetConfigurationResult, error) {
return engine.SetConfigurationResult{}, engine.NewError(
engine.ErrorInvalidArgument, "set configuration",
"invalid compression codec \"xz\", must be 'none' or 'zstd'", "", nil,
)
},
})
err := runConfigCommand(parsedCommandLine{
method: "config", positionals: []string{"set", "compression", "xz"},
}, outputModeText)
if err == nil || classifyExitCode(err) != exitUsage || !strings.Contains(err.Error(), "invalid compression codec") {
t.Fatalf("expected usage-class engine validation, got %v", err)
}
}

func installConfigurationCommandStubs(t *testing.T, dbconn *sql.DB, stub stubCommandEngine) {
t.Helper()
originalLoad := loadDefaultStorageContextPhase
originalNewEngine := newConfigurationCommandEngine
t.Cleanup(func() {
loadDefaultStorageContextPhase = originalLoad
newConfigurationCommandEngine = originalNewEngine
})
loadDefaultStorageContextPhase = func() (storage.StorageContext, error) {
return storage.StorageContext{DB: dbconn}, nil
}
newConfigurationCommandEngine = func(storage.StorageContext) (engine.Engine, error) {
return stub, nil
}
}
Loading