Skip to content

feat: add C++ streaming Responses pilot - #1368

Merged
0x4007 merged 7 commits into
developmentfrom
codex/contract-v1-g7db25bc5c5
Nov 13, 2026
Merged

0x4007 merged 7 commits into
developmentfrom
codex/contract-v1-g7db25bc5c5

Conversation

@0x4007

@0x4007 0x4007 commented Nov 13, 2026 •

Copy link
Copy Markdown
Member

Adds a bounded C++20 pilot for authenticated, streaming POST /v1/responses using direct deepseek-flash Chat translation. It preserves the recorded tool/history/event/usage and admission behavior, limits two active requests, and uses an isolated single-writer fixture journal with crash recovery. Buffered requests are explicitly unsupported by this pilot.

The qualification report and scorecard retain exact source/runtime/artifact identities, scope, measurements, and remaining gaps.

Actual Pi qualification completed a 3600.000226-second soak with 718 measured requests, followed by overload and idle checks. Final counts were 778 POSTs/dispatches/settlements with zero reserved, active, queued or unsettled requests. Gateway/namespace peak was 32.828125 MiB, with zero swap/OOM and observed host headroom of at least 112.1484375 MiB. Separate outside transport helpers had swap, including an observed 4 KiB increase, so strict whole-transport zero-new-swap is not claimed.

Candidate source is 7069c31b3f50d0552ef77e99b984f59fde479b13, tree 827f3281deaa0b36002d710c172a6b0e43d89a38. The stripped ARM64 package is 991,848 bytes, SHA-256 bbb18300ea225e2803bc1f95ce5576b42af862c135c828667fd163a191c5bfd3. Release clean/one-file builds measured 121.282 s / 5.539 s with the prepared SDK. Later report commits retain these runtime identities rather than relabelling the binary.

Validation includes release and ASan/UBSan six-case CTest suites, eight real process restarts, actual pinned Codex round trips, complete source-golden comparisons, TLS chain/hostname/SNI checks, genuine backpressure/cancellation, large inputs, focused tidy, scoped lint/format, and strict application TypeScript checking. The latter used the identical pinned TypeScript 6.0.3 compiler/configuration under supported Node 24.20.0 after resource-stalled Bun attempts; first-party application/fixture TypeScript remains Bun. Final report-only formatting/diff results are recorded separately.

This qualifies the synthetic, streaming-only runtime profile. Production credential/state/codec import, revocation/quota authority, single-writer failover, public ingress and a complete VPS-host outage remain unqualified. The separate recommendation is one bounded C++ VPS utility pilot, not a default language rewrite. The local Codex review timed out without a verdict; no findings were ingested, and review remains non-gating. Automatic post-merge CI is a separate hosted receipt; no workflow was manually dispatched or rerun.

@ubiquity-os

ubiquity-os Bot commented Nov 13, 2026

Copy link
Copy Markdown

Important

Ownership check: this pull request is left open.

@0x4007
0x4007 marked this pull request as ready for review November 13, 2026 10:37
@0x4007
0x4007 merged commit d6d0fea into development Nov 13, 2026
@ubiquity-os

ubiquity-os Bot commented Nov 13, 2026

Copy link
Copy Markdown

Important

Ownership check: this pull request is left open.

@coderabbitai

coderabbitai Bot commented Nov 13, 2026

Copy link
Copy Markdown

Explain Change →

Walkthrough

The pull request adds a C++20 pilot with request projection, streamed response translation, fixture state and control, an HTTP server, and upstream transport. It adds build presets, constrained build tooling, and tests for protocol behavior, conformance, recovery, and resource limits. Qualification reports record measured results and outstanding gaps. Separate TypeScript changes update test selection for lint configuration and include C++ test files in linting.

Pre-merge checks: Passed 4

Check name Status Explanation
Title check Passed The title "feat: add C++ streaming Responses pilot" matches the main change. The changeset adds a C++20 pilot for streaming POST /v1/responses, with its build, headers, sources, tests, and docs.
Description check Passed The description states that the PR adds a bounded C++20 pilot for streaming POST /v1/responses with DeepSeek Chat translation, a fixture journal, and qualification evidence. These topics match the cha…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description states that the PR adds a bounded C++20 pilot for streaming POST /v1/responses with DeepSeek Chat translation, a fixture journal, and qualification evidence. These topics match the changeset's C++ sources, tests, and research docs.

Finishing Touches

Generate unit tests (beta)

  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Warning

Review coverage is incomplete: 2 files could not be fully reviewed. Findings from completed review steps are included; see review info for details.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 15

Review info

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 1a6972b0-6f72-4251-b51c-ed8c58bf3847
Commits

Reviewing files that changed from the base of the PR and between 7aafe3d and 8d687e0.

Files selected for processing: 40

  • cpp/CMakeLists.txt
  • cpp/CMakePresets.json
  • cpp/README.md
  • cpp/include/pilot/control.hpp
  • cpp/include/pilot/core.hpp
  • cpp/include/pilot/network.hpp
  • cpp/include/pilot/state.hpp
  • cpp/include/pilot/translator.hpp
  • cpp/include/pilot/transport.hpp
  • cpp/src/core.cpp
  • cpp/src/fixture_control.cpp
  • cpp/src/fixture_state.cpp
  • cpp/src/main.cpp
  • cpp/src/payload_policy.cpp
  • cpp/src/project_input.cpp
  • cpp/src/project_tools.cpp
  • cpp/src/server.cpp
  • cpp/src/session.cpp
  • cpp/src/translator.cpp
  • cpp/src/transport.cpp
  • cpp/src/upstream.cpp
  • cpp/tests/candidate-process.ts
  • cpp/tests/conformance.ts
  • cpp/tests/fixture-control.ts
  • cpp/tests/mock.ts
  • cpp/tests/protocol_tests.cpp
  • cpp/tests/recovery.ts
  • cpp/tests/resources.ts
  • cpp/tools/build.py
  • cpp/tools/compiler-limit.py
  • docs/DECISIONS.md
  • docs/research/cpp-pi-standby-pilot-2026-11-13.json
  • docs/research/cpp-pi-standby-pilot-2026-11-13.md
  • docs/research/cpp-pi-standby-pilot-2026-11-13/build-receipt.json
  • docs/research/cpp-pi-standby-pilot-2026-11-13/local-receipt.json
  • docs/research/cpp-pi-standby-pilot-2026-11-13/pi-receipt.json
  • docs/research/cpp-pi-standby-pilot-2026-11-13/sources.json
  • scripts/test-scope.test.ts
  • scripts/test-scope.ts
  • tsconfig.lint.json
Files not reviewed due to moderation or processing errors: 2

  • cpp/src/translator.cpp
  • cpp/tests/protocol_tests.cpp

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

Comment thread cpp/src/fixture_state.cpp
check(wire.size()-pos>=4,"Incomplete final fixture frame retained; explicit recovery required");
std::uint32_t n=0;
for(unsigned k=0;k<4;++k)n=(n<<8)|static_cast<unsigned char>(wire[pos+k]);
check(n>64&&n<=2048&&wire.size()-pos-4>=n,"Incomplete or oversized fixture frame");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor · Stability & Availability · Quick win

Add a recovery path for a torn journal tail.

A SIGKILL between the frame prefix and the digest leaves an incomplete final frame in journal.bin. load() rejects that frame on every start, and the fixture cannot restart. No code path repairs the tail, and no recovery procedure is documented.

Choose one of these fixes:

  • Document the manual recovery step that the error message requires.
  • Add a guarded tail repair. Truncate only an incomplete trailing frame to the last complete frame boundary, then fsync before the journal opens for append. Keep checksum mismatches and sequence gaps fail-closed.

Comment thread cpp/src/fixture_state.cpp
throw;
}
} void State::snapshot_reset_journal() {
check(::ftruncate(journal_,0)==0,"Journal reset failed");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Major · Data Integrity & Integration · Heavy lift

Preserve journal entries written after snapshot publication.

When after_snapshot_rename holds a request, issue REVOKE_KEY, then release the fence. Session::run yields after publication (cpp/src/session.cpp, Line 337), so revocation appends a newer fsynced frame. This truncate deletes that frame although the snapshot lacks the revocation. Restart then restores the unrevoked state. Preserve entries above the snapshot sequence, or exclude mutations throughout the snapshot cycle. (raw.githubusercontent.com)

Comment thread cpp/src/project_input.cpp
auto const& o=item.as_object();
auto type=field(o,"type","message");
if(type=="reasoning") {
pending+=bounded_payload(reasoning(o),path,reject);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Major · Data Integrity & Integration · Quick win

Bound the accumulated reasoning payload.

Two reasoning items of 40,000 bytes each pass bounded_payload() separately. Their concatenation produces 80,000 bytes of reasoning_content, which Line 170 or Line 224 forwards without another check. The prompt-admission check can still accept this request.

Apply the payload policy to accumulated reasoning before attaching it to an assistant message. When truncation is disabled, reject an oversized aggregate.

Comment thread cpp/src/project_tools.cpp
}
} Prepared project(json::object const& raw,Limits const& limits,json::storage_ptr sp) {
static std::set<std::string> const allowed= {
"background","context_management","conversation","include","input","instructions","max_output_tokens","max_tool_calls","metadata","model","moderation","parallel_tool_calls","previous_response_id","prompt","prompt_cache_key","prompt_cache_options","prompt_cache_retention","reasoning","safety_identifier","service_tier","store","stream","stream_options","temperature","text","tool_choice","tools","top_logprobs","top_p","truncation","user","client_metadata"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Major · Data Integrity & Integration · Quick win

Reject previous_response_id until history resolution exists.

previous_response_id passes the allowlist at project_tools.cpp:145. project() never reads it, and Prepared has no field for it. The session passes the parsed request to project() at session.cpp:181 with no resolution step. The upstream body therefore contains only the new input. A continuation request runs without its referenced history and returns a normal success response.

Reject non-null values with a clear error. Add this check before projection starts:

Suggested fix

     for(auto const& x:raw)if(!allowed.contains(std::string(x.key())))throw Failure(400,"Unrecognized request argument supplied: "+std::string(x.key()));
+    if(!member(raw,"previous_response_id").is_null())throw Failure(400,"previous_response_id is not supported by this pilot","invalid_request_error","previous_response_id");
     Prepared r(sp);

Comment thread cpp/src/server.cpp
if(stopping)co_return;
throw boost::system::system_error(ec);
}
if(sockets>=8) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Major · Stability & Availability · Quick win

Reject successful accepts after shutdown starts.

An accept can complete before its continuation runs. If stop() runs in that interval with sockets == 0, drained() cancels the drain timer. This continuation still creates a session, which then has no 15-second shutdown bound. Recheck stopping after async_accept and close any late socket before creating a session. (boost.org)

Comment thread cpp/src/upstream.cpp
if(ec&&ec!=http::error::need_more&&ec!=http::error::need_buffer)throw boost::system::system_error(ec);
if(produced||parser.is_done()||(headers_only&&parser.is_header_done()))co_return;
}
if(eof){boost::system::error_code ec;parser.put_eof(ec);if(ec)throw boost::system::system_error(ec);co_return;}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Major · Stability & Availability · Quick win

Reject empty EOF before calling put_eof().

If upstream closes without sending response bytes, this branch calls put_eof() on an untouched parser. Boost 1.81 asserts got_some(), so the supported native-asan Debug build aborts the entire gateway. Detect this case and return the upstream-closed 502 failure before calling put_eof(). (raw.githubusercontent.com)

const lines = createInterface({ input: process.stdout });
const endpoint = await new Promise<string>((resolve, reject) => {
const timer = setTimeout(() => {
reject(new Error("Candidate readiness exceeded its bound"));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor · Stability & Availability · Quick win

Clean up the candidate when readiness fails.

If a live candidate emits no endpoint, this rejection leaves the child and control pipes open. The caller never receives finish. Stop and reap the child, close the pipes and readline interface, and save stderr before rejecting.

Comment thread cpp/tests/conformance.ts
import { openKv } from "../../src/storage/kv.ts";

initializeTestNativeKv({
artifactDirectory: "/home/codex/repos/ubiquity/ai.ubq.fi/.data/releases/d94fef52ccc76e0d5aa019154f11e47d5e10fba6/.native/kv",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Major · Functional Correctness · Quick win

Conformance tests need a release directory that CTest does not provide.

cpp/tests/conformance.ts calls initializeTestNativeKv at load time with a hardcoded /home/codex/repos/...releases/d94fef52.../.native/kv path. verifyNativeKvArtifact checks that directory and its provenance file before loading the native module, so a checkout without that release fails before the candidate starts. The socket, disconnect, and control CTest entries run this file, and no CMake step provisions the directory. cpp/tests/mock.ts:5 hardcodes the same path.

Read the artifact location from configuration, and keep expectedProvenanceSha256 as a required input so provenance verification still runs. The existing prepareTestNativeKv helper in scripts/test-native-kv.ts can supply that binding.

Comment thread cpp/tools/build.py
continue
for directory, _, files in os.walk(root):
for path in [Path(directory)] + [Path(directory) / value for value in files]:
st = path.lstat()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor · Stability & Availability · Quick win

Allow temporary files to disappear during sampling.

A compiler can remove a temporary file after os.walk() lists it but before lstat() runs. FileNotFoundError then aborts a valid build and stops budget monitoring while the child continues. Skip vanished entries during sampling; preserve other filesystem errors.

Comment thread cpp/tools/build.py
Comment on lines +90 to +94
child.terminate()
try:
child.wait(timeout=3)
except subprocess.TimeoutExpired:
child.kill()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Major · Stability & Availability · Quick win

Terminate the entire owned process tree on a budget breach.

This path signals only the immediate cmake or ctest process. Compiler, Bun, and candidate subprocesses can remain alive after the launcher exits or receives SIGKILL. Those subprocesses can continue consuming disk, memory, and time after monitoring stops.

Contain each phase and terminate its entire owned process tree. Reap the processes before reporting the budget failure. Apply the same cleanup when monitoring raises an exception.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant