Skip to content

Commit 0395b7c

Browse files
Merge remote-tracking branch 'origin/integration/human-team-memory-v1' into codex/setup-onboarding-v08
2 parents fc63282 + 28cdc79 commit 0395b7c

8 files changed

Lines changed: 1417 additions & 33 deletions

File tree

.github/workflows/ci.yml

Lines changed: 108 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,15 @@ jobs:
123123
if-no-files-found: ignore
124124
retention-days: 7
125125

126-
release-performance:
127-
# Runtime budgets are characterized and enforced only on this exact image.
128-
# Node 24 remains compatibility coverage in the check matrix above.
126+
release_performance_attempt_1:
127+
name: release-performance-attempt-1
128+
# Runtime budgets are characterized only on this exact image and Node patch.
129+
# A potentially material crossing is confirmed by a separately allocated job.
129130
runs-on: ubuntu-24.04
130131
timeout-minutes: 60
132+
outputs:
133+
requires_confirmation: ${{ steps.decision.outputs.requires_confirmation }}
134+
artifact_name: ${{ steps.decision.outputs.artifact_name }}
131135
steps:
132136
- uses: actions/checkout@v5
133137
- uses: actions/setup-node@v5
@@ -136,11 +140,109 @@ jobs:
136140
cache: npm
137141
- run: npm ci
138142
- run: npx playwright install --with-deps chromium
139-
- name: Enforce release performance budgets
143+
- run: npm run build
144+
- name: Measure the first release-performance attempt
140145
env:
141146
MEX_ENFORCE_RELEASE_BUDGETS: "1"
142-
run: npm run benchmark:release
143-
- name: Upload release benchmark report
147+
run: >-
148+
node scripts/release-benchmark/ci-orchestrator.mjs attempt
149+
--report test-results/release-benchmark/attempt-1/report.attempt-1.json
150+
--manifest test-results/release-benchmark/attempt-1/manifest.json
151+
- name: Publish the bounded confirmation decision
152+
id: decision
153+
shell: bash
154+
run: |
155+
REQUIRED="$(node scripts/release-benchmark/ci-orchestrator.mjs retry-required --manifest test-results/release-benchmark/attempt-1/manifest.json)"
156+
echo "requires_confirmation=$REQUIRED" >> "$GITHUB_OUTPUT"
157+
echo "artifact_name=release-performance-attempt-1-$GITHUB_RUN_ATTEMPT" >> "$GITHUB_OUTPUT"
158+
- name: Upload first release benchmark evidence
159+
if: always()
160+
uses: actions/upload-artifact@v4
161+
with:
162+
name: ${{ steps.decision.outputs.artifact_name }}
163+
path: test-results/release-benchmark/attempt-1/
164+
if-no-files-found: ignore
165+
retention-days: 14
166+
167+
release_performance_attempt_2:
168+
name: release-performance-attempt-2
169+
needs: release_performance_attempt_1
170+
if: needs.release_performance_attempt_1.outputs.requires_confirmation == 'true'
171+
runs-on: ubuntu-24.04
172+
timeout-minutes: 60
173+
outputs:
174+
artifact_name: ${{ steps.evidence.outputs.artifact_name }}
175+
steps:
176+
- uses: actions/checkout@v5
177+
- uses: actions/setup-node@v5
178+
with:
179+
node-version: 22.22.0
180+
cache: npm
181+
- run: npm ci
182+
- run: npx playwright install --with-deps chromium
183+
- run: npm run build
184+
- name: Measure the fresh-runner confirmation attempt
185+
env:
186+
MEX_ENFORCE_RELEASE_BUDGETS: "1"
187+
run: >-
188+
node scripts/release-benchmark/ci-orchestrator.mjs attempt
189+
--report test-results/release-benchmark/attempt-2/report.attempt-2.json
190+
--manifest test-results/release-benchmark/attempt-2/manifest.json
191+
- name: Publish the bounded evidence identity
192+
id: evidence
193+
shell: bash
194+
run: echo "artifact_name=release-performance-attempt-2-$GITHUB_RUN_ATTEMPT" >> "$GITHUB_OUTPUT"
195+
- name: Upload second release benchmark evidence
196+
if: always()
197+
uses: actions/upload-artifact@v4
198+
with:
199+
name: ${{ steps.evidence.outputs.artifact_name }}
200+
path: test-results/release-benchmark/attempt-2/
201+
if-no-files-found: ignore
202+
retention-days: 14
203+
204+
release-performance:
205+
# Preserve this final job name as the stable release gate. It always runs so
206+
# a skipped, cancelled, or malformed producer cannot silently bypass CI.
207+
needs: [release_performance_attempt_1, release_performance_attempt_2]
208+
if: always()
209+
runs-on: ubuntu-24.04
210+
timeout-minutes: 10
211+
steps:
212+
- uses: actions/checkout@v5
213+
- uses: actions/setup-node@v5
214+
with:
215+
node-version: 22.22.0
216+
- name: Download first release benchmark evidence
217+
continue-on-error: true
218+
uses: actions/download-artifact@v4
219+
with:
220+
name: ${{ needs.release_performance_attempt_1.outputs.artifact_name }}
221+
path: test-results/release-benchmark/attempt-1/
222+
- name: Download fresh-runner confirmation evidence
223+
if: needs.release_performance_attempt_1.outputs.requires_confirmation == 'true'
224+
continue-on-error: true
225+
uses: actions/download-artifact@v4
226+
with:
227+
name: ${{ needs.release_performance_attempt_2.outputs.artifact_name }}
228+
path: test-results/release-benchmark/attempt-2/
229+
- name: Finalize release performance without a confirmation
230+
if: needs.release_performance_attempt_1.outputs.requires_confirmation != 'true'
231+
run: >-
232+
node scripts/release-benchmark/ci-orchestrator.mjs finalize
233+
--first-report test-results/release-benchmark/attempt-1/report.attempt-1.json
234+
--first-manifest test-results/release-benchmark/attempt-1/manifest.json
235+
--output test-results/release-benchmark/report.json
236+
- name: Finalize release performance with fresh-runner confirmation
237+
if: needs.release_performance_attempt_1.outputs.requires_confirmation == 'true'
238+
run: >-
239+
node scripts/release-benchmark/ci-orchestrator.mjs finalize
240+
--first-report test-results/release-benchmark/attempt-1/report.attempt-1.json
241+
--first-manifest test-results/release-benchmark/attempt-1/manifest.json
242+
--second-report test-results/release-benchmark/attempt-2/report.attempt-2.json
243+
--second-manifest test-results/release-benchmark/attempt-2/manifest.json
244+
--output test-results/release-benchmark/report.json
245+
- name: Upload final release benchmark report
144246
if: always()
145247
uses: actions/upload-artifact@v4
146248
with:

.mex/patterns/release-performance-gate.md

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ edges:
1212
- target: "patterns/safe-graph-snapshot-evolution.md"
1313
condition: "when changing Graph maintenance or corpus inspection"
1414
grounds_to: []
15-
last_updated: 2026-08-29
15+
last_updated: 2026-09-02
1616
---
1717

1818
# Release Performance Gate
@@ -43,7 +43,9 @@ calibration environment.
4343
before and after ordinary reads.
4444
5. Use the first healthy pinned report as characterization. Freeze runtime,
4545
time, RSS, and heap limits at `ceil(p95 * 1.15)` and built asset limits at
46-
`ceil(bytes * 1.05)`, then rerun the same pinned job in enforcement mode.
46+
`ceil(bytes * 1.05)`. During CI enforcement, collect a potentially material
47+
confirmation in a separately allocated pinned hosted job at the exact same
48+
repository HEAD; two child processes on one VM are not independent evidence.
4749
6. Commit the budget file, its versioned schema/golden, and the retained runner
4850
identity together. Never copy wall-clock numbers from a local machine.
4951
7. When a new deterministic team fixture adds canonical and checkout-local
@@ -69,6 +71,10 @@ calibration environment.
6971
- Corpus byte caps prevent runaway allocation, but maintenance should also
7072
release source bodies and parser state as each file or bounded compiler batch
7173
completes.
74+
- Back-to-back confirmation processes on one hosted VM share CPU steal,
75+
throttling, and I/O contention. Keep the raw reports as artifacts, pass only
76+
a bounded retry decision between jobs, and make missing or same-allocation
77+
confirmation evidence fail operationally.
7278
- An unavailable-route placeholder can already have a frozen asset or heap
7379
budget. Replacing it with a real lazy workbench should initially fail only
7480
that route's owned leaves; do not reinterpret the placeholder budget as a
@@ -89,8 +95,9 @@ calibration environment.
8995

9096
If asset hashes change unexpectedly, inspect the built chunks for React
9197
development sentinels before recalibrating. If runtime enforcement is noisy,
92-
confirm the exact OS/architecture/Node patch and fixture digest; do not widen a
93-
budget until the retained raw samples show a real regression or stable shift.
98+
confirm the exact OS/architecture/Node patch, fixture digest, repository HEAD,
99+
and distinct hosted-job allocations; do not widen a budget until the retained
100+
raw samples show a real regression or stable shift.
94101

95102
## Update Scaffold
96103

docs/design/release-performance-baseline.md

Lines changed: 52 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,19 @@ bytes respectively. Initial CSS/fonts and every unrelated route/runtime budget
9797
remain unchanged. A clean pinned enforcing run on the final exact head remains
9898
required before release.
9999

100+
The fresh-runner confirmation topology was added after PR run
101+
[`33616707003`](https://github.com/mex-memory/mex/actions/runs/33616707003)
102+
and integration push run
103+
[`33619416840`](https://github.com/mex-memory/mex/actions/runs/33619416840)
104+
produced materially different Graph, Wiki, and Search failure sets for Git
105+
commits with the same tree SHA
106+
`950182277ee98719ec6971618cb83b597323e468`. The earlier confirmation logic
107+
started two child processes back-to-back on one hosted VM, so sustained host
108+
contention could satisfy both sides of the exact-metric rule. This hardening
109+
changes only confirmation allocation and provenance: `budgets.json`, sample
110+
counts, material thresholds, category floors, and calibration formulas remain
111+
byte-for-byte unchanged.
112+
100113
## Runner contract
101114

102115
`npm run benchmark:release` builds the package and writes the bounded JSON
@@ -178,18 +191,31 @@ Deterministic failures remain immediate: built-asset bytes, outbound requests,
178191
database-to-input ratios, and any unknown runtime metric never receive a retry.
179192
The read and maintenance nonmutation contracts likewise remain ordinary hard
180193
tests. A first pass containing only wall-clock, RSS, CPU, or browser-heap
181-
breaches triggers one independent full benchmark pass on the same pinned
182-
runner and exact repository HEAD only when at least one crossing could still
183-
become material. A crossing is potentially material when its p95 is strictly
184-
above the material threshold and at least two of its raw samples are also
185-
strictly above that threshold. If every first-pass crossing is below the
186-
threshold or has fewer than two supporting samples, enforcement records the
187-
advisories and passes without spending another full benchmark run. CI fails a
188-
noisy metric only when that exact metric breaches again, both p95 measurements
189-
exceed its material threshold, and both attempts have at least two supporting
190-
raw samples. This avoids treating the single maximum selected by nearest-rank
191-
p95 over either ten timing samples or five memory samples as
192-
distribution-level evidence. The committed p95 budgets remain the raw
194+
breaches requests one independent full benchmark pass only when at least one
195+
crossing could still become material. In CI that conditional confirmation runs
196+
in a separately allocated Ubuntu 24.04 hosted job, not as another process on
197+
the first job's VM. Both jobs measure the exact same repository HEAD and pinned
198+
Node version; a final fail-closed aggregation job validates their bounded raw
199+
reports and runner-allocation records before applying the existing exact-metric
200+
rule. A missing, malformed, same-runner, or different-HEAD confirmation is an
201+
operational failure rather than a pass. The local `npm run benchmark:release`
202+
command remains self-contained and uses its existing in-process orchestration.
203+
Producer-specific artifact identities allow GitHub's failed-only rerun to reuse
204+
valid evidence from an earlier attempt of the same workflow run. Aggregation
205+
accepts only the same run and SHA, nondecreasing producer attempts, and evidence
206+
no newer than the finalizer attempt.
207+
208+
A crossing is potentially material when its p95 is strictly above the material
209+
threshold and at least two of its raw samples are also strictly above that
210+
threshold. If every first-pass crossing is below the threshold or has fewer
211+
than two supporting samples, enforcement records the advisories and passes
212+
without allocating a confirmation runner. CI fails a noisy metric only when
213+
that exact metric breaches on the fresh confirmation runner, both p95
214+
measurements exceed its material threshold, and both attempts have at least two
215+
supporting raw samples. This avoids treating the single maximum selected by
216+
nearest-rank p95 over either ten timing samples or five memory samples as
217+
distribution-level evidence, while preventing one contended VM from supplying
218+
both sides of the confirmation. The committed p95 budgets remain the raw
193219
alert/crossing line and are not recalibrated. For each exact metric key, the
194220
blocking threshold is
195221
`budget + max(15% of budget, minimum excess)`:
@@ -217,16 +243,20 @@ inconsistent raw sample evidence, are never retried as budget noise.
217243
Enforcement exits 0 for a pass, 1 for a budget failure, and 2 when a pass cannot
218244
produce a valid bounded report.
219245

220-
The dedicated `release-performance` CI job installs Chromium on the pinned
221-
runner, enforces the budgets, and retains the final report plus both attempt
222-
reports when confirmation was required. It also retains the first raw attempt
223-
when advisory sample support makes a second pass unnecessary. Runtime
224-
candidates in that report are `ceil(p95 * 1.15)` independently for each fixture profile,
225-
route, read, and maintenance operation. The committed values are copied exactly
226-
from the first healthy retained pinned report; its enforcing rerun must pass
227-
before Checkpoint A is considered green. Future recalibration uses the same
228-
retained-report workflow. Do not derive runtime limits from an unpinned local
229-
run or collapse fixture profiles into one worst-case envelope.
246+
The dedicated CI topology uses `release-performance-attempt-1`, a conditional
247+
`release-performance-attempt-2`, and the final required
248+
`release-performance` aggregation job. Each measuring job installs Chromium on
249+
the pinned image and retains its raw report and bounded decision manifest for
250+
14 days. The final job retains the combined report; it runs even if a producer
251+
was cancelled or failed so missing evidence cannot silently skip the gate. The
252+
first raw attempt is still retained when advisory sample support makes a second
253+
runner unnecessary. Runtime candidates in that report are `ceil(p95 * 1.15)`
254+
independently for each fixture profile, route, read, and maintenance operation.
255+
The committed values are copied exactly from the first healthy retained pinned
256+
report; its enforcing rerun must pass before Checkpoint A is considered green.
257+
Future recalibration uses the same retained-report workflow. Do not derive
258+
runtime limits from an unpinned local run or collapse fixture profiles into one
259+
worst-case envelope.
230260

231261
The report is capped at 2 MiB. Response bodies, child-process diagnostics,
232262
recorded request paths, asset lists, and violation lists also have explicit

0 commit comments

Comments
 (0)