Skip to content

Commit 5303a77

Browse files
authored
Merge pull request #18 from ngallodev/sync/upstream-step4
Sync with upstream codebase-memory-mcp (665 → 0 behind) via real merges, MCP features ported to CLI
2 parents 1a0f85f + eaec36c commit 5303a77

288 files changed

Lines changed: 672431 additions & 190304 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/_lint.yml‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@ permissions:
1010

1111
jobs:
1212
lint:
13-
runs-on: ubuntu-latest
13+
# Pinned, not ubuntu-latest: the LLVM install below adds an
14+
# apt.llvm.org llvm-toolchain-NOBLE repo, which is 24.04 by name. When
15+
# GitHub moves ubuntu-latest to the next LTS this job breaks on a day
16+
# nobody chose. Pin the runner to the release the repo line already names.
17+
runs-on: ubuntu-24.04
1418
# 15 min proved too tight on a slow runner day and a timed-out lint reads
1519
# as "cancelled", which the release graph must treat as a hard stop; keep
1620
# a bound, but one only a genuine hang can hit (normal runtime ~5 min).
@@ -60,7 +64,8 @@ jobs:
6064
# provability (never suppressed — the NOLINT ban applies here too).
6165
# Vendored-tree diagnostics are path-filtered, mirroring .cppcheck.
6266
lint-mem:
63-
runs-on: ubuntu-latest
67+
# Pinned for the same reason as `lint`: llvm-toolchain-noble-21 below.
68+
runs-on: ubuntu-24.04
6469
timeout-minutes: 60
6570
steps:
6671
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

‎.github/workflows/_memwaste.yml‎

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
# Reusable: the waste sanitizer (memory + CPU waste), REPORT-ONLY.
2+
#
3+
# What runs (scripts/memwaste.sh, memwaste-scaling.py, memwaste-ratchet.py):
4+
# mode=pr Linux: the event lane (memory waste + CPU work) indexing this
5+
# repository at the checked-out commit, and the CPU scaling lane
6+
# (src/ replicated 2x against 4x, per-function counter ratios).
7+
# mode=full the same, plus the event lane on macOS and Windows and the access
8+
# lane (read/write verdicts per allocation) on Linux.
9+
#
10+
# The corpus is the repository itself: pinned by the commit, no network, and a
11+
# real mix of C, C++, Python, JavaScript and vendored code.
12+
#
13+
# REPORT-ONLY: every job uploads its report and prints the ratchet comparison
14+
# against scripts/memwaste-baseline.json, but nothing here can turn a PR red --
15+
# the ratchet runs without --enforce and the PR's ci-ok gate does not depend on
16+
# these jobs. A job fails only when the MEASUREMENT is unsound (a table
17+
# overflowed, frees the layer never saw): that is a defect of the tool, and a
18+
# red job is how it gets noticed. Switching the ratchet to --enforce is a
19+
# separate, deliberate change once the numbers have been stable across reruns.
20+
name: Memwaste
21+
22+
on:
23+
workflow_call:
24+
inputs:
25+
mode:
26+
description: "pr (Linux event + scaling) or full (all platforms, access lane)"
27+
type: string
28+
default: pr
29+
30+
permissions:
31+
contents: read
32+
33+
jobs:
34+
event-linux:
35+
runs-on: ubuntu-latest
36+
timeout-minutes: 60
37+
steps:
38+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
39+
- name: Install deps
40+
run: sudo apt-get update && sudo apt-get install -y zlib1g-dev python3 clang llvm
41+
- name: Event lane on this repository
42+
run: |
43+
# `cmd | tee` reports TEE's status: without this a failing lane
44+
# (a missing exec bit, a build error) passes the step and only
45+
# surfaces as the ratchet not finding its JSON.
46+
set -o pipefail
47+
mkdir -p "$RUNNER_TEMP/memwaste-event"
48+
scripts/memwaste.sh "$GITHUB_WORKSPACE" --top 40 --out "$RUNNER_TEMP/memwaste-event" \
49+
| tee "$RUNNER_TEMP/memwaste-event/report.txt"
50+
- name: Ratchet (report-only)
51+
run: python3 scripts/memwaste-ratchet.py --out "$RUNNER_TEMP/memwaste-event" --venue ${{ inputs.mode }}-linux
52+
- name: Upload report
53+
if: ${{ always() }}
54+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
55+
with:
56+
name: memwaste-event-linux-${{ inputs.mode }}
57+
path: |
58+
${{ runner.temp }}/memwaste-event/report.txt
59+
${{ runner.temp }}/memwaste-event/memwaste.json
60+
${{ runner.temp }}/memwaste-event/index.json
61+
if-no-files-found: warn
62+
63+
scaling-linux:
64+
runs-on: ubuntu-latest
65+
timeout-minutes: 60
66+
steps:
67+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
68+
- name: Install deps
69+
run: sudo apt-get update && sudo apt-get install -y zlib1g-dev python3 clang llvm
70+
- name: CPU scaling lane (src/ at 2x against 4x)
71+
# Report-only: the script exits 1 when it flags a super-linear function.
72+
continue-on-error: true
73+
run: |
74+
# `cmd | tee` reports TEE's status: without this a failing lane
75+
# (a missing exec bit, a build error) passes the step and only
76+
# surfaces as the ratchet not finding its JSON.
77+
set -o pipefail
78+
mkdir -p "$RUNNER_TEMP/memwaste-scaling"
79+
python3 scripts/memwaste-scaling.py --corpus src --replicas 2 \
80+
--out "$RUNNER_TEMP/memwaste-scaling" | tee "$RUNNER_TEMP/memwaste-scaling/report.txt"
81+
- name: Upload report
82+
if: ${{ always() }}
83+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
84+
with:
85+
name: memwaste-scaling-linux-${{ inputs.mode }}
86+
path: ${{ runner.temp }}/memwaste-scaling/report.txt
87+
if-no-files-found: warn
88+
89+
access-linux:
90+
if: ${{ inputs.mode == 'full' }}
91+
runs-on: ubuntu-latest
92+
timeout-minutes: 120
93+
steps:
94+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
95+
- name: Install deps
96+
run: sudo apt-get update && sudo apt-get install -y zlib1g-dev python3 clang llvm
97+
- name: Access lane on this repository
98+
run: |
99+
# `cmd | tee` reports TEE's status: without this a failing lane
100+
# (a missing exec bit, a build error) passes the step and only
101+
# surfaces as the ratchet not finding its JSON.
102+
set -o pipefail
103+
mkdir -p "$RUNNER_TEMP/memwaste-access"
104+
scripts/memwaste.sh "$GITHUB_WORKSPACE" --lane access --top 40 --sort untouched \
105+
--out "$RUNNER_TEMP/memwaste-access" | tee "$RUNNER_TEMP/memwaste-access/report.txt"
106+
- name: Upload report
107+
if: ${{ always() }}
108+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
109+
with:
110+
name: memwaste-access-linux-${{ inputs.mode }}
111+
path: |
112+
${{ runner.temp }}/memwaste-access/report.txt
113+
${{ runner.temp }}/memwaste-access/memwaste.json
114+
if-no-files-found: warn
115+
116+
event-macos:
117+
if: ${{ inputs.mode == 'full' }}
118+
runs-on: macos-14
119+
timeout-minutes: 60
120+
steps:
121+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
122+
- name: Event lane on this repository
123+
run: |
124+
# `cmd | tee` reports TEE's status: without this a failing lane
125+
# (a missing exec bit, a build error) passes the step and only
126+
# surfaces as the ratchet not finding its JSON.
127+
set -o pipefail
128+
mkdir -p "$RUNNER_TEMP/memwaste-event"
129+
scripts/memwaste.sh "$GITHUB_WORKSPACE" --top 40 --out "$RUNNER_TEMP/memwaste-event" \
130+
| tee "$RUNNER_TEMP/memwaste-event/report.txt"
131+
- name: Ratchet (report-only)
132+
run: python3 scripts/memwaste-ratchet.py --out "$RUNNER_TEMP/memwaste-event" --venue full-macos
133+
- name: Upload report
134+
if: ${{ always() }}
135+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
136+
with:
137+
name: memwaste-event-macos-${{ inputs.mode }}
138+
path: |
139+
${{ runner.temp }}/memwaste-event/report.txt
140+
${{ runner.temp }}/memwaste-event/memwaste.json
141+
if-no-files-found: warn
142+
143+
event-windows:
144+
if: ${{ inputs.mode == 'full' }}
145+
runs-on: windows-latest
146+
timeout-minutes: 90
147+
steps:
148+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
149+
- uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # v2
150+
with:
151+
msystem: CLANG64
152+
path-type: inherit
153+
install: >-
154+
mingw-w64-clang-x86_64-clang
155+
mingw-w64-clang-x86_64-llvm
156+
mingw-w64-clang-x86_64-zlib
157+
mingw-w64-clang-x86_64-python3
158+
make
159+
git
160+
coreutils
161+
- name: Event lane on this repository
162+
shell: msys2 {0}
163+
run: |
164+
# `cmd | tee` reports TEE's status: without this a failing lane
165+
# (a missing exec bit, a build error) passes the step and only
166+
# surfaces as the ratchet not finding its JSON.
167+
set -o pipefail
168+
out="$(cygpath -u "$RUNNER_TEMP")/memwaste-event"
169+
mkdir -p "$out"
170+
CC=clang CXX=clang++ scripts/memwaste.sh "$(cygpath -u "$GITHUB_WORKSPACE")" --top 40 --out "$out" \
171+
| tee "$out/report.txt"
172+
- name: Ratchet (report-only)
173+
shell: msys2 {0}
174+
run: python3 scripts/memwaste-ratchet.py --out "$(cygpath -u "$RUNNER_TEMP")/memwaste-event" --venue full-windows
175+
- name: Upload report
176+
if: ${{ always() }}
177+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
178+
with:
179+
name: memwaste-event-windows-${{ inputs.mode }}
180+
path: |
181+
${{ runner.temp }}/memwaste-event/report.txt
182+
${{ runner.temp }}/memwaste-event/memwaste.json
183+
if-no-files-found: warn

‎.github/workflows/_test.yml‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,9 @@ jobs:
257257
# parallel suite — catches what an older compiler-rt can miss. Same
258258
# canonical scripts/test.sh wave as every other leg.
259259
test-diag:
260-
runs-on: ubuntu-latest
260+
# Pinned for the same reason as the lint jobs: the pinned diagnostic
261+
# toolchain below installs from llvm-toolchain-noble-21.
262+
runs-on: ubuntu-24.04
261263
timeout-minutes: 120
262264
steps:
263265
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

‎.github/workflows/codeql.yml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
run: sudo apt-get update && sudo apt-get install -y zlib1g-dev
3030

3131
- name: Initialize CodeQL
32-
uses: github/codeql-action/init@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9
32+
uses: github/codeql-action/init@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4.38.0
3333
with:
3434
languages: c-cpp
3535
build-mode: manual
@@ -38,6 +38,6 @@ jobs:
3838
run: scripts/build.sh
3939

4040
- name: Perform CodeQL Analysis
41-
uses: github/codeql-action/analyze@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9
41+
uses: github/codeql-action/analyze@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4.38.0
4242
with:
4343
category: "/language:c-cpp"

‎.github/workflows/dry-run.yml‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ on:
4545
description: 'Skip candidate scan; mark unscanned and default to stripped'
4646
type: boolean
4747
default: false
48+
skip_memwaste:
49+
description: 'Skip the waste sanitizer (report-only) and the fuzz smoke'
50+
type: boolean
51+
default: false
4852
soak_level:
4953
description: 'Soak: full (quick+asan), quick (10min), none'
5054
type: choice
@@ -107,6 +111,38 @@ jobs:
107111
with:
108112
broad_platforms: true
109113

114+
# ── Waste sanitizer, REPORT-ONLY (independent island) ─────────
115+
# Event lane on Linux, macOS and Windows, access lane and the per-function
116+
# scaling lane on Linux. Uploads reports; fails only when the measurement is
117+
# unsound (a defect of the tool itself).
118+
memwaste:
119+
if: ${{ inputs.skip_memwaste != true }}
120+
uses: ./.github/workflows/_memwaste.yml
121+
with:
122+
mode: full
123+
124+
# ── Fuzz smoke (independent island) ───────────────────────────
125+
# A fixed number of executions from a fixed seed per target, so the verdict is
126+
# a function of the commit (O9). A crash here is a real defect in a parser
127+
# that reads untrusted input; its reproducer is uploaded.
128+
fuzz:
129+
if: ${{ inputs.skip_memwaste != true }}
130+
runs-on: ubuntu-latest
131+
timeout-minutes: 90
132+
steps:
133+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
134+
- name: Install deps
135+
run: sudo apt-get update && sudo apt-get install -y zlib1g-dev clang llvm libclang-rt-dev
136+
- name: Fuzz smoke (extract, cypher, config)
137+
run: scripts/fuzz.sh all --runs 20000 --seed 1
138+
- name: Upload reproducers
139+
if: ${{ failure() }}
140+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
141+
with:
142+
name: fuzz-artifacts
143+
path: build/fuzz/artifacts-*/
144+
if-no-files-found: ignore
145+
110146
# ── Soak tests (optional, parallel with smoke) ────────────────
111147
soak:
112148
if: ${{ inputs.soak_level != 'none' && !cancelled() && needs.build.result != 'failure' && needs.build.result != 'skipped' }}

‎.github/workflows/nightly-soak.yml‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,27 @@ permissions:
3535
contents: read
3636

3737
jobs:
38+
# Fuzz exploration: new inputs are the point here, so it runs for a time
39+
# budget instead of a fixed count. NON-GATING like the soak; a crash uploads
40+
# its reproducer, which becomes a fixed-seed regression input once fixed.
41+
fuzz:
42+
if: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }}
43+
runs-on: ubuntu-latest
44+
timeout-minutes: 120
45+
steps:
46+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
47+
- name: Install deps
48+
run: sudo apt-get update && sudo apt-get install -y zlib1g-dev clang llvm libclang-rt-dev
49+
- name: Fuzz exploration (30 min per target)
50+
run: scripts/fuzz.sh all --max-total-time 1800 --seed 0
51+
- name: Upload reproducers
52+
if: ${{ failure() }}
53+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
54+
with:
55+
name: fuzz-artifacts-nightly
56+
path: build/fuzz/artifacts-*/
57+
if-no-files-found: ignore
58+
3859
soak:
3960
uses: ./.github/workflows/_soak.yml
4061
with:

‎.github/workflows/pr.yml‎

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,29 @@ jobs:
6464
run: |
6565
# The full .diff endpoint rejects large-but-valid PRs at 20k lines.
6666
# The paginated files endpoint remains filename-only for this gate.
67-
FILES=$(gh api --paginate "repos/$REPO/pulls/$PR/files?per_page=100" --jq '.[].filename')
67+
if FILES=$(gh api --paginate "repos/$REPO/pulls/$PR/files?per_page=100" --jq '.[].filename'); then
68+
echo "file list: pulls/files API"
69+
else
70+
# The files endpoint renders the diff server-side too, and answers
71+
# 422 "this diff is taking too long to generate" for a PR that
72+
# regenerates a vendored parser (#2246: a 42 MB sql/parser.c) --
73+
# so does the compare endpoint. The PR merge ref's first parent is
74+
# the base, so a name-only diff across it is the same file list.
75+
# depth 2 + blob:none fetches commits and trees only (well under
76+
# 1 MB, under a second); nothing from the PR is checked out or run.
77+
echo "::notice::pulls/files API failed; file list taken from refs/pull/$PR/merge"
78+
CHANGES_GIT="$RUNNER_TEMP/changes.git"
79+
git init -q --bare "$CHANGES_GIT"
80+
git --git-dir="$CHANGES_GIT" fetch -q --depth=2 --filter=blob:none \
81+
"https://github.com/$REPO" "refs/pull/$PR/merge"
82+
FILES=$(git --git-dir="$CHANGES_GIT" diff --name-only --no-renames FETCH_HEAD^1 FETCH_HEAD)
83+
fi
6884
printf '%s\n' "$FILES"
69-
if printf '%s\n' "$FILES" | grep -qE '^(src/|internal/|install\.(sh|ps1)|scripts/build\.sh|scripts/smoke-test\.sh|scripts/smoke-local\.sh|scripts/smoke-fixture-server\.py|scripts/gen-third-party-notices\.sh|scripts/env\.sh|test-infrastructure/vm/(vm-smoke\.sh|windows-user-path-guard\.ps1)|Makefile\.cbm)'; then
85+
# A here-string, not a pipe: under this shell's pipefail, grep -q
86+
# exits on its first match, printf dies of SIGPIPE once the list
87+
# outgrows the pipe buffer, and the MATCH is then reported as a
88+
# failure -- product=false, smoke skipped, on the largest PRs.
89+
if grep -qE '^(src/|internal/|install\.(sh|ps1)|scripts/build\.sh|scripts/smoke-test\.sh|scripts/smoke-local\.sh|scripts/smoke-fixture-server\.py|scripts/gen-third-party-notices\.sh|scripts/env\.sh|test-infrastructure/vm/(vm-smoke\.sh|windows-user-path-guard\.ps1)|Makefile\.cbm)' <<<"$FILES"; then
7090
echo "product=true" >> "$GITHUB_OUTPUT"
7191
else
7292
echo "product=false" >> "$GITHUB_OUTPUT"
@@ -154,6 +174,17 @@ jobs:
154174
CCACHE_DIR: ${{ github.workspace }}/.ccache
155175
CCACHE_MAXSIZE: 1000M
156176

177+
# ── Waste sanitizer, REPORT-ONLY: memory + CPU waste on this repository and
178+
# the per-function scaling lane (Linux). Deliberately NOT in ci-ok's needs:
179+
# it uploads evidence and prints the ratchet, it never blocks a merge. Only
180+
# product-code PRs pay for it. ──
181+
memwaste:
182+
needs: [changes]
183+
if: ${{ !cancelled() && needs.changes.outputs.product == 'true' }}
184+
uses: ./.github/workflows/_memwaste.yml
185+
with:
186+
mode: pr
187+
157188
ci-ok:
158189
# The one required context (besides dco) — fails unless every PR stage
159190
# succeeded, so matrix renames can never silently deadlock merges. `skipped`

0 commit comments

Comments
 (0)