Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
d58afe5
revert(release): re-embed runtime assets into the single shipped binary
DeusData Aug 9, 2026
a4336dc
feat(release): ship one archive set and tolerate a single Microsoft !…
DeusData Aug 9, 2026
93696ae
docs(security): publish the AV false-positive evidence; harden arm64 W^X
DeusData Aug 9, 2026
caf84c5
test(contracts): align the release contracts with the single-composit…
DeusData Aug 9, 2026
edef66c
chore: ignore the generated UI source and drop the stale variant help…
DeusData Aug 9, 2026
8473e5e
test(httpd): a missing embedded frontend is a permanent 404, not a re…
DeusData Aug 9, 2026
04d53a0
test(vt): the gate contract no longer claims zero tolerance
DeusData Aug 9, 2026
17f4f6d
docs(third-party): keep the ObjectScript scanner deviation documented
DeusData Aug 9, 2026
fe7f371
test(vt): drop the cmp dependency from the release-notes contract
DeusData Aug 9, 2026
83d6a78
test(venue): re-home the isolated-release-download guard
DeusData Aug 9, 2026
6415f94
fix(packages): put every wrapper and its tests on the same base
DeusData Aug 9, 2026
d602eb6
test(composition): gate that read-only data stays out of the executab…
DeusData Aug 9, 2026
39e0254
fix(smoke): UI presence is the caller's claim, not every lane's assum…
DeusData Aug 9, 2026
045e1aa
test(windows): keep the extended-path machinery in the non-ASCII guard
DeusData Aug 9, 2026
1ba668c
fix(cli): keep the install/uninstall existence probes extended-path safe
DeusData Aug 9, 2026
a3ae045
fix(cli): restore `uninstall --dir` so a custom install stays removable
DeusData Aug 9, 2026
c9b5b39
test(release): restore the archive-extractor contract, and fix what i…
DeusData Aug 9, 2026
57f30e2
style(cli): clang-format the uninstall --dir target resolution
DeusData Aug 9, 2026
0f3eda8
test(release): launch the extractor via $BASH, not a bare bash
DeusData Aug 9, 2026
dce5518
test(pypi): restore the publication concurrency tests for the single-…
DeusData Aug 9, 2026
3f54d7c
test(go): restore the publication concurrency tests for the single-fi…
DeusData Aug 9, 2026
79a0ba9
test(windows): print the captured index error when a non-ASCII case f…
DeusData Aug 9, 2026
09c91df
test(windows): carry the index response and cache listing into the fa…
DeusData Aug 9, 2026
926b7bc
test(windows): read the worker logs when the pipeline fails a non-ASC…
DeusData Aug 9, 2026
b1526d2
test(windows): retry a failed non-ASCII case with a fresh cache
DeusData Aug 9, 2026
591155d
test(windows): probe the failing case through the CLI, which prints d…
DeusData Aug 9, 2026
aac3616
test(windows): keep and dump the worker log for the failing CLI probe
DeusData Aug 10, 2026
601dcbf
fix(pipeline): name every silent failure edge in generation finalize
DeusData Aug 10, 2026
f36ab45
fix(store): normalize the Windows file-API path on every SQLite open
DeusData Aug 10, 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
16 changes: 8 additions & 8 deletions .github/workflows/_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,13 @@ jobs:
# Archive layout/name live in the ONE canonical script the local
# artifact-flow smoke lane also runs (venue-parity contract).
- name: Archive release binary (canonical package-release.sh)
run: scripts/package-release.sh ${{ matrix.goos }} ${{ matrix.goarch }} --variant ui
run: scripts/package-release.sh ${{ matrix.goos }} ${{ matrix.goarch }}

- name: Attest release binary provenance
if: ${{ inputs.attest }}
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
with:
subject-path: codebase-memory-mcp-ui-${{ matrix.goos }}-${{ matrix.goarch }}.tar.gz
subject-path: codebase-memory-mcp-${{ matrix.goos }}-${{ matrix.goarch }}.tar.gz

- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
Expand Down Expand Up @@ -133,13 +133,13 @@ jobs:
# artifact-flow smoke lane also runs (venue-parity contract).
- name: Archive release binary (canonical package-release.sh)
shell: msys2 {0}
run: scripts/package-release.sh windows amd64 --variant ui CC=clang CXX=clang++
run: scripts/package-release.sh windows amd64 CC=clang CXX=clang++

- name: Attest release binary provenance
if: ${{ inputs.attest }}
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
with:
subject-path: codebase-memory-mcp-ui-windows-amd64.zip
subject-path: codebase-memory-mcp-windows-amd64.zip

- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
Expand Down Expand Up @@ -183,13 +183,13 @@ jobs:

- name: Archive release binary (canonical package-release.sh)
shell: msys2 {0}
run: scripts/package-release.sh windows arm64 --variant ui CC=clang CXX=clang++
run: scripts/package-release.sh windows arm64 CC=clang CXX=clang++

- name: Attest release binary provenance
if: ${{ inputs.attest }}
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
with:
subject-path: codebase-memory-mcp-ui-windows-arm64.zip
subject-path: codebase-memory-mcp-windows-arm64.zip

- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
Expand Down Expand Up @@ -235,13 +235,13 @@ jobs:
ldd build/c/codebase-memory-mcp 2>&1 | grep -q "not a dynamic executable" || ldd build/c/codebase-memory-mcp 2>&1 | grep -q "statically linked"

- name: Archive release binary (canonical package-release.sh)
run: scripts/package-release.sh linux ${{ matrix.arch }}-portable --variant ui
run: scripts/package-release.sh linux ${{ matrix.arch }}-portable

- name: Attest release binary provenance
if: ${{ inputs.attest }}
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
with:
subject-path: codebase-memory-mcp-ui-linux-${{ matrix.arch }}-portable.tar.gz
subject-path: codebase-memory-mcp-linux-${{ matrix.arch }}-portable.tar.gz

- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
Expand Down
4 changes: 1 addition & 3 deletions .github/workflows/dry-run.yml
Original file line number Diff line number Diff line change
Expand Up @@ -151,11 +151,9 @@ jobs:
- name: Extract archive artifacts
run: |
scripts/ci/extract-release-archives.sh "$RUNNER_TEMP/release-archives" binaries \
--archive-scope=ui \
--expect-archives=8 \
--expect-binaries=8 \
--expect-packs=8 \
--expect-runtime-files=32
--expect-runtime-files=24

- name: VirusTotal scan
uses: crazy-max/ghaction-virustotal@936d8c5c00afe97d3d9a1af26d017cfdf26800a2 # v5.0.0
Expand Down
4 changes: 1 addition & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -216,11 +216,9 @@ jobs:
mkdir -p "$ARCHIVE_DIR" binaries
gh release download "$VERSION" --dir "$ARCHIVE_DIR" --repo "$GITHUB_REPOSITORY" --pattern '*.tar.gz' --pattern '*.zip'
scripts/ci/extract-release-archives.sh "$ARCHIVE_DIR" binaries \
--archive-scope=ui \
--expect-archives=8 \
--expect-binaries=8 \
--expect-packs=8 \
--expect-runtime-files=32
--expect-runtime-files=24

- name: Security audits on all unique extracted release objects
run: |
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ private/
build/
node_modules/
graph-ui/dist/
# Generated by scripts/embed-frontend.sh into the source tree (the linker needs
# it beside the other UI sources). Removed by scripts/clean.sh; never committed.
src/ui/embedded_assets.c

# Generated reports
BENCHMARK_REPORT.md
Expand Down
86 changes: 32 additions & 54 deletions Makefile.cbm
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,18 @@ endif
# link), this flag fixes the OUTCOME, and the composition gate proves it on the
# shipped artifact. ELF-only: Apple's ld rejects -z noexecstack outright and it
# is meaningless for PE, so it is gated rather than made "common".
#
# -z separate-code additionally keeps read-only DATA out of the executable
# segment. GNU ld enables it by default on x86-64 but NOT on aarch64, so the
# arm64 binaries emitted ONE R E PT_LOAD spanning the whole image: .rodata is
# correctly marked A (not AX), but the kernel applies SEGMENT permissions, so
# ~259 MB of tree-sitter parse tables was mapped executable at runtime while the
# amd64 build of the same source mapped them R only. That is a large ROP gadget
# surface for data that is never executed, and it is invisible to section flags.
ELF_HARDENING_FLAGS :=
ifeq ($(IS_LINUX),yes)
ifneq ($(IS_MINGW),yes)
ELF_HARDENING_FLAGS := -Wl,-z,noexecstack
ELF_HARDENING_FLAGS := -Wl,-z,noexecstack -Wl,-z,separate-code
endif
endif

Expand Down Expand Up @@ -358,19 +366,17 @@ GIT_SRCS = src/git/git_context.c

# CLI module (new)
CLI_SRCS = src/cli/cli.c src/cli/progress_sink.c src/cli/hook_augment.c src/cli/client_adapter.c \
src/cli/agent_clients.c src/cli/agent_profiles.c src/cli/integration_assets.c \
src/cli/agent_clients.c src/cli/agent_profiles.c \
src/cli/config_json_like.c src/cli/config_toml_edit.c src/cli/config_yaml_edit.c \
src/cli/config_text_edit.c src/cli/activation_transaction.c

# UI module (graph visualization). Production-standard builds deliberately link
# only the no-I/O pack stub. Test binaries substitute the real parser plus the
# empty manifest so parser/install behavior remains covered without a UI pack.
# UI module (graph visualization)
UI_SRCS = \
src/ui/config.c \
src/ui/http_server.c \
src/ui/layout3d.c \
src/ui/httpd.c \
src/ui/asset_pack_stub.c
src/ui/embedded_stub.c

# mimalloc (vendored, global allocator override)
#
Expand Down Expand Up @@ -458,7 +464,6 @@ YYJSON_SRC = vendored/yyjson/yyjson.c

# All production sources
PROD_SRCS = $(FOUNDATION_SRCS) $(STORE_SRCS) $(CYPHER_SRCS) $(MCP_SRCS) $(DAEMON_SRCS) $(DISCOVER_SRCS) $(GRAPH_BUFFER_SRCS) $(PIPELINE_SRCS) $(SIMHASH_SRCS) $(SEMANTIC_SRCS) $(TRACES_SRCS) $(WATCHER_SRCS) $(GIT_SRCS) $(CLI_SRCS) $(UI_SRCS) $(YYJSON_SRC)
TEST_PROD_SRCS = $(subst src/ui/asset_pack_stub.c,src/ui/asset_pack.c src/ui/asset_manifest_stub.c,$(PROD_SRCS))
EXISTING_C_SRCS = $(EXTRACTION_SRCS) $(LSP_SRCS) $(TS_RUNTIME_SRC) \
$(GRAMMAR_SRCS) $(AC_LZ4_SRCS) $(ZSTD_SRCS) $(SQLITE_WRITER_SRC)

Expand All @@ -476,17 +481,6 @@ EXISTING_C_SRCS = $(EXTRACTION_SRCS) $(LSP_SRCS) $(TS_RUNTIME_SRC) \
PROJECT_HDRS = $(wildcard src/*.h src/*/*.h $(CBM_DIR)/*.h $(CBM_DIR)/lsp/*.h tests/*.h \
tests/repro/*.h)

# ── Integration-asset integrity constant (generated, never hand-edited) ──
# The binary embeds exactly ONE fact about the shipped integration templates:
# the SHA-256 of assets/cbm-integrations.json, generated at build time (rule
# below the BUILD_DIR definition; target lines expand immediately). Appended
# to PROJECT_HDRS so every single-invocation target (test-runner,
# test-repro-runner, test-runner-tsan, codebase-memory-mcp) rebuilds when the
# asset changes — a stale constant would make every install fail verification.
INTEGRATIONS_ASSET = assets/cbm-integrations.json
INTEGRATIONS_HASH_HDR = $(BUILD_DIR)/generated/cbm_integrations_hash.h
PROJECT_HDRS += $(INTEGRATIONS_HASH_HDR)

# ── Test sources ─────────────────────────────────────────────────

TEST_FOUNDATION_SRCS = \
Expand Down Expand Up @@ -702,11 +696,6 @@ ALL_TEST_SRCS =$(TEST_FOUNDATION_SRCS) $(TEST_EXTRACTION_SRCS) $(TEST_STORE_SRCS

BUILD_DIR = build/c

# Integration-asset hash header (variables defined next to PROJECT_HDRS; the
# rule lives here because target lines expand $(BUILD_DIR) immediately).
$(INTEGRATIONS_HASH_HDR): $(INTEGRATIONS_ASSET) scripts/gen-integrations-hash.sh | $(BUILD_DIR)
sh scripts/gen-integrations-hash.sh $(INTEGRATIONS_ASSET) $@

# ── Object file compilation (grammars need relaxed warnings) ─────

# Grammar + tree-sitter runtime: compiled without -Werror (upstream code has warnings)
Expand All @@ -728,7 +717,7 @@ PP_OBJ_TSAN = $(BUILD_DIR)/tsan_preprocessor.o

# ── Targets ──────────────────────────────────────────────────────

.PHONY: test test-par test-repro test-foundation test-tsan test-daemon-smoke cbm cbm-with-ui frontend ui-pack clean-c lint lint-tidy lint-cppcheck lint-format security
.PHONY: test test-par test-repro test-foundation test-tsan test-daemon-smoke cbm cbm-with-ui frontend embed clean-c lint lint-tidy lint-cppcheck lint-format security

$(BUILD_DIR):
mkdir -p $(BUILD_DIR)
Expand Down Expand Up @@ -871,9 +860,9 @@ $(UNIXCODER_OBJ): $(UNIXCODER_BLOB_SRC) vendored/nomic/code_vectors.bin | $(BUIL
OBJS_VENDORED_TEST = $(MIMALLOC_OBJ_TEST) $(SQLITE3_OBJ_TEST) $(TRE_OBJ_TEST) $(GRAMMAR_OBJS_TEST) $(TS_RUNTIME_OBJ_TEST) $(LSP_OBJ_TEST) $(PP_OBJ_TEST) $(LZ4_OBJ_TEST) $(ZSTD_OBJ_TEST) $(UNIXCODER_OBJ)
OBJS_VENDORED_TSAN = $(MIMALLOC_OBJ_TSAN) $(SQLITE3_OBJ_TSAN) $(TRE_OBJ_TSAN) $(GRAMMAR_OBJS_TSAN) $(TS_RUNTIME_OBJ_TSAN) $(LSP_OBJ_TSAN) $(PP_OBJ_TSAN) $(LZ4_OBJ_TSAN) $(ZSTD_OBJ_TSAN) $(UNIXCODER_OBJ)

$(BUILD_DIR)/test-runner: $(ALL_TEST_SRCS) $(TEST_PROD_SRCS) $(EXTRACTION_SRCS) $(AC_LZ4_SRCS) $(ZSTD_SRCS) $(SQLITE_WRITER_SRC) $(OBJS_VENDORED_TEST) $(PROJECT_HDRS) | $(BUILD_DIR)
$(BUILD_DIR)/test-runner: $(ALL_TEST_SRCS) $(PROD_SRCS) $(EXTRACTION_SRCS) $(AC_LZ4_SRCS) $(ZSTD_SRCS) $(SQLITE_WRITER_SRC) $(OBJS_VENDORED_TEST) $(PROJECT_HDRS) | $(BUILD_DIR)
$(CC) $(CFLAGS_TEST) -Itests -Itests/repro -o $@ \
$(ALL_TEST_SRCS) $(TEST_PROD_SRCS) \
$(ALL_TEST_SRCS) $(PROD_SRCS) \
$(EXTRACTION_SRCS) $(AC_LZ4_SRCS) $(ZSTD_SRCS) $(SQLITE_WRITER_SRC) \
$(OBJS_VENDORED_TEST) \
$(LDFLAGS_TEST)
Expand All @@ -899,9 +888,9 @@ test-focused: $(BUILD_DIR)/test-runner
# Mirrors test-runner's link line but uses repro_main.c (own main + counters)
# and TEST_REPRO_SRCS instead of ALL_TEST_SRCS. Exits non-zero while any bug is
# still reproduced (the expected state); bug-repro.yml surfaces it as a board.
$(BUILD_DIR)/test-repro-runner: $(TEST_REPRO_SRCS) $(TEST_PROD_SRCS) $(EXTRACTION_SRCS) $(AC_LZ4_SRCS) $(ZSTD_SRCS) $(SQLITE_WRITER_SRC) $(OBJS_VENDORED_TEST) $(PROJECT_HDRS) | $(BUILD_DIR)
$(BUILD_DIR)/test-repro-runner: $(TEST_REPRO_SRCS) $(PROD_SRCS) $(EXTRACTION_SRCS) $(AC_LZ4_SRCS) $(ZSTD_SRCS) $(SQLITE_WRITER_SRC) $(OBJS_VENDORED_TEST) $(PROJECT_HDRS) | $(BUILD_DIR)
$(CC) $(CFLAGS_TEST) -Itests -o $@ \
$(TEST_REPRO_SRCS) $(TEST_PROD_SRCS) \
$(TEST_REPRO_SRCS) $(PROD_SRCS) \
$(EXTRACTION_SRCS) $(AC_LZ4_SRCS) $(ZSTD_SRCS) $(SQLITE_WRITER_SRC) \
$(OBJS_VENDORED_TEST) \
$(LDFLAGS_TEST)
Expand Down Expand Up @@ -959,9 +948,9 @@ TSAN_OPTIONS ?= halt_on_error=1:report_thread_leaks=0
# Normal ASan/native/soak paths remain uncapped. High-worker TSan diagnostics
# invoke test-runner-tsan directly so release gates cannot drift accidentally.

$(BUILD_DIR)/test-runner-tsan: $(ALL_TEST_SRCS) $(TEST_PROD_SRCS) $(EXTRACTION_SRCS) $(AC_LZ4_SRCS) $(ZSTD_SRCS) $(SQLITE_WRITER_SRC) $(OBJS_VENDORED_TSAN) $(PROJECT_HDRS) | $(BUILD_DIR)
$(BUILD_DIR)/test-runner-tsan: $(ALL_TEST_SRCS) $(PROD_SRCS) $(EXTRACTION_SRCS) $(AC_LZ4_SRCS) $(ZSTD_SRCS) $(SQLITE_WRITER_SRC) $(OBJS_VENDORED_TSAN) $(PROJECT_HDRS) | $(BUILD_DIR)
$(CC) $(CFLAGS_TSAN) -Itests -Itests/repro -o $@ \
$(ALL_TEST_SRCS) $(TEST_PROD_SRCS) \
$(ALL_TEST_SRCS) $(PROD_SRCS) \
$(EXTRACTION_SRCS) $(AC_LZ4_SRCS) $(ZSTD_SRCS) $(SQLITE_WRITER_SRC) \
$(OBJS_VENDORED_TSAN) \
$(LDFLAGS_TSAN)
Expand Down Expand Up @@ -1048,40 +1037,29 @@ $(BUILD_DIR)/codebase-memory-mcp: $(MAIN_SRC) $(PROD_SRCS) $(EXTRACTION_SRCS) $(
cbm: $(BUILD_DIR)/codebase-memory-mcp
@echo "Built: $(BUILD_DIR)/codebase-memory-mcp"

# ── Build with external UI asset pack (requires Node.js) ────────
# ── Build with embedded UI (requires Node.js) ───────────────────

# The native image contains only a generated manifest (pack basename, SHA-256
# and byte length). Frontend bytes stay in a content-addressed sidecar next to
# the binary so release scanners can inspect them independently.
UI_ASSET_MANIFEST = $(BUILD_DIR)/generated/ui_asset_manifest.c
UI_ASSET_DIST ?= graph-ui/dist
UI_ASSET_PREBUILT ?= 0
ifeq ($(UI_ASSET_PREBUILT),1)
UI_ASSET_BUILD_PREREQ :=
else
UI_ASSET_BUILD_PREREQ := frontend
endif
PROD_SRCS_WITH_ASSETS = $(subst src/ui/asset_pack_stub.c,src/ui/asset_pack.c $(UI_ASSET_MANIFEST),$(PROD_SRCS))
# Swap embedded_stub.c for the generated embedded_assets.c
UI_SRCS_WITH_ASSETS = $(subst src/ui/embedded_stub.c,src/ui/embedded_assets.c,$(UI_SRCS))
PROD_SRCS_WITH_ASSETS = $(subst src/ui/embedded_stub.c,src/ui/embedded_assets.c,$(PROD_SRCS))

# Embedded asset object files (generated by embed script)
EMBED_OBJS = $(wildcard $(BUILD_DIR)/embedded/embed_*.o)

frontend:
cd graph-ui && npm ci && npm run build

$(UI_ASSET_MANIFEST): $(UI_ASSET_BUILD_PREREQ) scripts/pack-ui-assets.mjs | $(BUILD_DIR)
node scripts/pack-ui-assets.mjs $(UI_ASSET_DIST) $(BUILD_DIR) $@

ui-pack: $(UI_ASSET_MANIFEST)
embed: frontend
scripts/embed-frontend.sh graph-ui/dist $(BUILD_DIR)/embedded

# $(INTEGRATIONS_HASH_HDR): generated header included by integration_assets.c.
# The standard target gets it via $(PROJECT_HDRS); the UI target compiles in one
# shot and must list it too, or the build fails with "cbm_integrations_hash.h
# file not found" (seen on the Windows UI build).
cbm-with-ui: ui-pack $(INTEGRATIONS_HASH_HDR) $(OBJS_VENDORED_PROD)
cbm-with-ui: embed $(OBJS_VENDORED_PROD)
$(CC) $(CFLAGS_PROD) -o $(BUILD_DIR)/codebase-memory-mcp \
$(MAIN_SRC) $(PROD_SRCS_WITH_ASSETS) \
$(EXTRACTION_SRCS) $(AC_LZ4_SRCS) $(ZSTD_SRCS) $(SQLITE_WRITER_SRC) \
$(OBJS_VENDORED_PROD) \
$(wildcard $(BUILD_DIR)/embedded/embed_*.o) \
$(LDFLAGS)
@echo "Built with UI asset pack: $(BUILD_DIR)/codebase-memory-mcp"
@echo "Built with UI: $(BUILD_DIR)/codebase-memory-mcp"

clean-c: export BUILD_DIR := $(BUILD_DIR)
clean-c:
Expand Down Expand Up @@ -1114,7 +1092,7 @@ lint-tidy:
@$(CLANG_TIDY) --quiet $(LINT_SRCS) -- $(CFLAGS_COMMON) $(SYSROOT_FLAG)

# cppcheck: complementary analysis (config in .cppcheck)
lint-cppcheck: $(INTEGRATIONS_HASH_HDR)
lint-cppcheck:
@echo "=== cppcheck ==="
@$(CPPCHECK) --enable=warning,style,performance,portability \
--std=c11 --language=c \
Expand Down
Loading
Loading