From a0cc8c44660ec384d87bd552f8b216a9ae263a48 Mon Sep 17 00:00:00 2001 From: Joe S Date: Tue, 28 Apr 2026 16:15:47 -0700 Subject: [PATCH 1/2] update server ref agent docs, add server map --- .agents/server-map.md | 124 ++++++++++++++++++++++++++++++++++++++++++ .gitignore | 4 ++ AGENTS.md | 46 +++++++++++++++- 3 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 .agents/server-map.md diff --git a/.agents/server-map.md b/.agents/server-map.md new file mode 100644 index 00000000..9c9b22d7 --- /dev/null +++ b/.agents/server-map.md @@ -0,0 +1,124 @@ +# ClickHouse Server Navigation Map + +Source tree lives at `.server-src/` (gitignored). The version actually being investigated is recorded in `.server-ref`. + +## How to use this map + +This map is intentionally version-agnostic. ClickHouse's high-level layout (`src/IO/`, `src/DataTypes/`, `src/Formats/`, `src/Core/Settings.cpp`, `IDataType`, the `Serialization*` family, the format and compression factories) has been stable for years, so the entries below should apply across most modern server tags. The long tail drifts: newly added types, renamed settings, occasional file splits during refactors. + +Paths are relative to `.server-src/`. Before relying on a specific file or class pointer, sanity-check that it still exists at the tag in `.server-ref`. If a cited path is missing, tell the user the map is out of date for that area and suggest updating the map rather than guessing a replacement. + +Cite file and class or function names in your answers. Do not cite line numbers, they rot. + +## Native protocol (TCP wire format) + +- **Packet types and protocol constants**: `src/Core/Protocol.h` defines `Protocol::Client::Enum`, `Protocol::Server::Enum`, `Protocol::Compression`, and version constants for client/server handshake and Hello/Query/Data/Exception/EndOfStream framing. +- **TCP handler**: `src/Server/TCPHandler.cpp`, `src/Server/TCPHandler.h` implement the main packet loop, handshake, per-query state, and Data/Exception/Progress packet emission. +- **Block read/write over the wire**: `src/Formats/NativeReader.cpp`, `src/Formats/NativeWriter.cpp`. Native format is the payload inside Data packets: column count, then for each column name, type string, and serialized values. +- **Compressed transport wrapping**: `src/Compression/CompressedReadBuffer.cpp`, `src/Compression/CompressedWriteBuffer.cpp`. + +## Type system and binary serialization + +- **Core type interface**: `src/DataTypes/IDataType.h`. Every SQL type derives from `IDataType` and exposes metadata plus a serialization object. +- **Serialization interface**: `src/DataTypes/Serializations/ISerialization.h`. One type can have multiple serializations (default, sparse, subcolumn). Binary read/write lives on methods like `serializeBinaryBulk*` / `deserializeBinaryBulk*`. +- **Per-type implementations**: `src/DataTypes/DataTypeXXX.{cpp,h}` for each type. +- **Per-type serializations**: `src/DataTypes/Serializations/SerializationXXX.{cpp,h}`. +- **Type factory and text parsing of type strings**: `src/DataTypes/DataTypeFactory.cpp`. +- **Schema binary encoding** (used when transmitting types, e.g. Dynamic): `src/DataTypes/DataTypesBinaryEncoding.{cpp,h}`. + +## Specific types + +### Nullable + +`src/DataTypes/DataTypeNullable.{cpp,h}`, `src/DataTypes/Serializations/SerializationNullable.{cpp,h}`. Wire layout: null byte-mask (UInt8 per row, 0 for value present, 1 for NULL), then the nested column with all rows (null rows hold an undefined value). + +### LowCardinality + +`src/DataTypes/DataTypeLowCardinality.{cpp,h}`, `src/DataTypes/DataTypeLowCardinalityHelpers.cpp`, `src/DataTypes/Serializations/SerializationLowCardinality.{cpp,h}`. Wire layout has a multi-part header (version flags, index type) plus a dictionary of unique values and an indexes column (UInt8/UInt16/UInt32/UInt64 depending on dictionary size). Dictionary ordering is not stable across blocks; read the source before assuming. + +### Array + +`src/DataTypes/DataTypeArray.{cpp,h}`, `src/DataTypes/Serializations/SerializationArray.{cpp,h}`, `src/DataTypes/Serializations/SerializationArrayOffsets.{cpp,h}`. Wire layout: offsets column (UInt64, cumulative end-offsets per row), then the flattened element column. + +### Tuple and Nested + +`src/DataTypes/DataTypeTuple.{cpp,h}`, `src/DataTypes/Serializations/SerializationTuple.{cpp,h}`. Named and unnamed tuples serialize as parallel element columns, no wrapper. Nested is represented as a `Tuple` of `Array` columns with shared offsets. + +### Map + +`src/DataTypes/DataTypeMap.{cpp,h}`, `src/DataTypes/Serializations/SerializationMap.{cpp,h}`. Represented as `Array(Tuple(key, value))` on the wire. + +### Decimal + +`src/DataTypes/DataTypeDecimalBase.{cpp,h}`, `src/DataTypes/DataTypesDecimal.h`, `src/DataTypes/Serializations/SerializationDecimal.{cpp,h}`. Stored as fixed-width two's-complement integer (32/64/128/256-bit) with precision and scale carried in the type string. + +### Enum8 / Enum16 + +`src/DataTypes/DataTypeEnum.{cpp,h}`, `src/DataTypes/EnumValues.{cpp,h}`, `src/DataTypes/Serializations/SerializationEnum.{cpp,h}`. Name-to-value map lives in the type string. Wire format is the underlying Int8/Int16. + +### Date, Date32, DateTime, DateTime64 + +`src/DataTypes/DataTypeDate.{cpp,h}`, `src/DataTypes/DataTypeDate32.{cpp,h}`, `src/DataTypes/DataTypeDateTime.{cpp,h}`, `src/DataTypes/DataTypeDateTime64.{cpp,h}` and their `SerializationDate*` counterparts. `Date` is UInt16 days since 1970-01-01 (Unix epoch). `Date32` is Int32 days since 1970-01-01, extended range approximately 1900..2299. `DateTime` is UInt32 seconds since 1970-01-01 UTC. `DateTime64` is Int64 ticks at configurable precision 0..9. Timezone is part of the type string, not the wire payload. See also `src/DataTypes/TimezoneMixin.h` and `src/Common/DateLUTImpl.h` (`DATE_LUT_*` constants) for range and offset logic. + +### UUID + +`src/DataTypes/DataTypeUUID.{cpp,h}`, `src/DataTypes/Serializations/SerializationUUID.{cpp,h}`. Wire: 16 bytes, stored as UInt128. Byte order has historically tripped clients; confirm against the source before assuming. + +### String and FixedString + +`src/DataTypes/DataTypeString.{cpp,h}`, `src/DataTypes/DataTypeFixedString.{cpp,h}`, `src/DataTypes/Serializations/SerializationString.{cpp,h}`, `src/DataTypes/Serializations/SerializationFixedString.{cpp,h}`. String wire: VarUInt length prefix per value, then raw bytes. FixedString wire: fixed-width bytes, no length prefix. + +### JSON / Object + +`src/DataTypes/DataTypeObject.{cpp,h}`, `src/DataTypes/Serializations/SerializationObject.{cpp,h}`, `SerializationObjectDistinctPaths.{cpp,h}`, `SerializationObjectDynamicPath.{cpp,h}`, `SerializationObjectSharedData.{cpp,h}`, `SerializationJSON.{cpp,h}`. The newer JSON type uses a shared-data representation with dynamically tracked paths. Wire layout is not a plain string — confirm against the serialization code before implementing client read/write. + +### Variant and Dynamic + +`src/DataTypes/DataTypeVariant.{cpp,h}`, `src/DataTypes/DataTypeDynamic.{cpp,h}`, `src/DataTypes/Serializations/SerializationVariant.{cpp,h}`, `SerializationVariantElement.{cpp,h}`, `SerializationDynamic.{cpp,h}`, `SerializationDynamicElement.{cpp,h}`, `SerializationDynamicHelpers.{cpp,h}`. Variant: per-row discriminant byte selecting one of the variant type columns. Dynamic: self-describing variant with schema transmitted via `DataTypesBinaryEncoding`. + +### IPv4 and IPv6 + +`src/DataTypes/DataTypeIPv4andIPv6.{cpp,h}`, `src/DataTypes/Serializations/SerializationIPv4andIPv6.{cpp,h}`. Wire: UInt32 for IPv4, 16 bytes for IPv6. + +## Input/output formats + +- **Format factory and settings**: `src/Formats/FormatFactory.{cpp,h}`, `src/Formats/FormatSettings.h`. +- **Format base classes**: `src/Processors/Formats/IInputFormat.h`, `IOutputFormat.h`, `IRowInputFormat.h`, `IRowOutputFormat.h`. +- **Native**: `src/Formats/NativeReader.cpp`, `src/Formats/NativeWriter.cpp` (binary block-oriented, also used as TCP payload). +- **JSONEachRow**: `src/Processors/Formats/Impl/JSONEachRowRowInputFormat.{cpp,h}`, `JSONEachRowRowOutputFormat.{cpp,h}`. Compact variant: `JSONCompactEachRowRowInputFormat.{cpp,h}`. +- **TabSeparated**: `src/Processors/Formats/Impl/TabSeparatedRowInputFormat.{cpp,h}`, `TabSeparatedRowOutputFormat.{cpp,h}`. +- **CSV**: `src/Processors/Formats/Impl/CSVRowInputFormat.{cpp,h}`, `CSVRowOutputFormat.{cpp,h}`. +- **Values**: `src/Processors/Formats/Impl/ValuesBlockInputFormat.{cpp,h}`, `ValuesRowOutputFormat.{cpp,h}`. + +## Settings and context + +- **Settings declarations**: `src/Core/Settings.h` declares every runtime setting via macros. `src/Core/SettingsFields.h` defines the underlying field types. `src/Core/BaseSettingsFwdMacros.h` wires the macro infrastructure. +- **Version history**: `src/Core/SettingsChangesHistory.h` tracks when settings were added, renamed, or had their default changed. First stop when a behavior changes across versions. +- **Query context**: `src/Interpreters/Context.h` holds `Settings` plus other per-query execution state. TCP and HTTP handlers apply client-provided setting overrides at query start. +- **Client setting delivery**: settings ride on the Query packet on TCP (see `src/Server/TCPHandler.cpp` and `src/Core/Protocol.h`) and on URL parameters via HTTP (`src/Server/HTTP/`). + +## Errors and exceptions + +- **Error codes**: `src/Common/ErrorCodes.h`, `src/Common/ErrorCodes.cpp`. Enumerates every error code and its name. +- **Exception class**: `src/Common/Exception.{cpp,h}`, with extended utilities in `src/Common/ExceptionExt.{cpp,h}`. Carries code, message, optional stack trace. +- **Wire transmission**: errors are sent as the Exception server packet (see `Protocol::Server::Exception` in `src/Core/Protocol.h`); emission lives in `src/Server/TCPHandler.cpp`. + +## Compression + +- **Codec interface**: `src/Compression/ICompressionCodec.h`. +- **Wire codecs**: `src/Compression/CompressionCodecLZ4.cpp`, `src/Compression/CompressionCodecZSTD.cpp` are the two you will see from the TCP client path. Specialized codecs (Delta, DoubleDelta, Gorilla, GCD, T64) exist alongside them but are used in on-disk/column-level compression rather than default wire transport. +- **Compressed buffers**: `src/Compression/CompressedReadBuffer.{cpp,h}`, `CompressedWriteBuffer.{cpp,h}`. +- **Factory**: `src/Compression/CompressionFactory.{cpp,h}`, `CompressionFactoryAdditions.cpp`. + +## Server tests relevant to clients + +Tests live under `tests/` in the checkout. Filenames embed the feature under test, so `rg`-style globs on `tests/queries/0_stateless/` are the fastest way in. + +- **Type behavior**: `tests/queries/0_stateless/**.sql`, for example `*nullable*.sql`, `*low_cardinality*.sql`, `*decimal*.sql`, `*datetime*.sql`, `*variant*.sql`, `*dynamic*.sql`. +- **JSON/Object type**: `tests/queries/0_stateless/*json*.sql`, `*object*.sql`. +- **Format behavior**: `*csv*.sql`, `*tsv*.sql`, `*values*.sql`, `*native*.sql`. +- **Protocol and compression**: `*protocol*.sql`, `*compression*.sql`. +- **Settings**: `*settings*.sql`. +- **C++ unit tests**: `src/DataTypes/tests/`, `src/Formats/tests/`, `src/Common/tests/` when present. Search with `fd -t d tests src/`. + +Each test typically ships with a `.reference` file containing expected output. Those reference files are often the clearest spec of what the server guarantees. diff --git a/.gitignore b/.gitignore index 4dd3ff88..811c5635 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,7 @@ test.env # C extensions *.pyd + +# Local ClickHouse server source checkout for agent reference (see AGENTS.md) +/.server-src/ +.server-ref diff --git a/AGENTS.md b/AGENTS.md index 5290e437..80eb452c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -6,6 +6,7 @@ Required reading: - Before making substantial code changes, read `.agents/architecture.md`. - Before doing code review, review feedback, or PR analysis, read `.agents/review.md`. +- Before investigating server behavior, type serialization, wire protocol, format parsing, or settings handling, read `.agents/server-map.md` and follow the workflow in `Server Behavior Is Authoritative` below. Do not treat those docs as replacements for this file. They are required reference material. This file remains the source of truth for agent behavior. @@ -49,7 +50,50 @@ Act like an experienced maintainer of a public Python database driver. ## Server Behavior Is Authoritative -When in doubt about how the ClickHouse server actually behaves, how a type is serialized, how a setting takes effect, how an error is produced, or what a protocol detail means, go read the server source at `https://github.com/ClickHouse/ClickHouse`. That is the source of truth. Do not guess, do not infer from this client's code alone, and do not assume documentation is current. Check the server code itself. +When in doubt about how the ClickHouse server actually behaves, how a type is serialized, how a setting takes effect, how an error is produced, or what a protocol detail means, go read the server source. That is the source of truth. Do not guess, do not infer from this client's code alone, and do not assume documentation is current. + +### Local server source checkout + +A shallow clone of the ClickHouse server source should live at `.server-src/`, pinned to the tag recorded in `.server-ref` at the repo root. Both `.server-src/` and `.server-ref` are gitignored, so they will not be present on a fresh checkout. Treat the tag in `.server-ref` as the version you are comparing client behavior against. + +Server investigation work is much higher quality with the actual server source available locally. If you need it and it is missing, try to set it up before continuing. + +- If `.server-src/` or `.server-ref` is missing, tell the user that server investigation is best done against the real server source and that you recommend setting it up. Then try to create them. If the user has not specified a version, default to the most recent stable ClickHouse release tag. Write that tag to `.server-ref` and do a shallow clone of `https://github.com/ClickHouse/ClickHouse` at that tag into `.server-src/`. +- If you cannot set them up for any reason, tell the user plainly. You may continue without the local source, but flag in your answer that the investigation was done without it and the result is less reliable. +- Do not silently re-clone an existing `.server-src/` and do not fall back to reading GitHub ad hoc when a local checkout is present. +- If the user asks you to investigate against a different version, tell them the current `.server-ref` tag and ask whether to switch before proceeding. +- Cite the tag explicitly in your answer, for example: "at v26.3.9.8-lts, `JSONEachRowRowInputFormat::readRow` does X". + +### Navigation + +Before grepping blindly through the server tree, read `.agents/server-map.md`. It is a curated index of where client-relevant concerns live: wire protocol, type serialization, individual type implementations, formats, settings, errors, compression, and server tests. Use it as your first stop, then open the specific files it points at. + +If the map's pointers do not exist at the pinned tag, flag it plainly and tell the user before writing code that assumes them. + +### Always delegate server C++ reading to a sub-agent + +ClickHouse is a large C++ codebase. Reading it directly in the main conversation bloats context fast and crowds out the client-side code you are actually changing. Delegate it. + +Default workflow: + +1. In the main conversation, identify the **specific questions** you need answered about server behavior. Examples: "how is a `Decimal(76, 10)` value laid out on the wire", "does `JSONEachRow` emit trailing newlines on empty result sets", "what is the exact null-mask byte order for `Nullable(LowCardinality(String))`". +2. Look up the relevant entry points in `.agents/server-map.md`. +3. Spawn a sub-agent with a focused prompt that includes: + - The pinned tag from `.server-ref`. + - The specific questions, one at a time. + - A short list of files or directories from the map worth starting with. + - An instruction to cite files and function or class names, and to mark each answer as **confirmed** (read the function body) or **inferred** (only read a signature, comment, or test). +4. Work from the sub-agent's summary. Do not pull raw C++ into the main thread. +5. If the summary is insufficient, send a follow-up question to the same sub-agent rather than reading the code yourself. + +The main thread should stay focused on the client change. The sub-agent eats the C++ context. + +### What your answer must contain + +- The resolved server tag you compared against. +- Specific server paths and function or class names you relied on. Do not cite line numbers; they rot. +- A clear distinction between **confirmed** (you read the function body) and **inferred** (you only read a signature, comment, or test name). +- Specific client-side file and line references for the behavior you are reconciling. ## Change Style From bc25ec216ed8a3e89f19d4b1d7b4a3430ad17b2e Mon Sep 17 00:00:00 2001 From: Joe S Date: Tue, 28 Apr 2026 22:04:23 -0700 Subject: [PATCH 2/2] add server reader agent --- .claude/agents/clickhouse-server-reader.md | 44 ++++++++++++++++++++++ AGENTS.md | 31 +++++++-------- 2 files changed, 60 insertions(+), 15 deletions(-) create mode 100644 .claude/agents/clickhouse-server-reader.md diff --git a/.claude/agents/clickhouse-server-reader.md b/.claude/agents/clickhouse-server-reader.md new file mode 100644 index 00000000..ce103af2 --- /dev/null +++ b/.claude/agents/clickhouse-server-reader.md @@ -0,0 +1,44 @@ +--- +name: clickhouse-server-reader +description: Use when investigating how the ClickHouse server actually behaves at the C++ source level. This includes wire protocol details, type serialization layout, format parsing, settings handling, error production, and compression behavior. Hand off the specific questions you need answered and this agent will read the local server checkout and return a focused, cited summary so the main thread does not have to load C++ context. +tools: Read, Bash, Grep, Glob +model: sonnet +--- + +You read ClickHouse server C++ source to answer specific behavioral questions for a Python client maintainer. Your job is to keep large amounts of C++ out of the main conversation by reading the source yourself and returning a tight, well-cited summary. + +## Source location + +- Local checkout: `.server-src/` at the repo root. +- Version under investigation: read the tag from `.server-ref` at the repo root before doing anything else, and cite that tag in your final answer. +- If `.server-src/` or `.server-ref` is missing, stop and tell the caller. Do not pull from GitHub ad hoc and do not silently re-clone. + +## Navigation + +- Start from `.agents/server-map.md`. It is the curated index of where client-relevant concerns live (wire protocol, type serialization, per-type files, formats, settings, errors, compression, server tests). +- Use `rg` for searches inside `.server-src/`. It is the fastest tool for this tree. +- The map is intentionally version-agnostic. If a specific path it cites does not exist at the pinned tag, say so plainly in the answer rather than guessing a replacement, and suggest the map needs an update for that area. + +## What every answer must contain + +- The resolved server tag from `.server-ref`, cited explicitly. Example: "at v26.3.9.8-lts, `JSONEachRowRowInputFormat::readRow` does X". +- Specific server file paths and class or function names you relied on. Do not cite line numbers, they rot. +- A clear marker on every claim: **confirmed** (you read the function body) or **inferred** (you only read a signature, a comment, a test name, or the map). Do not blur the two. +- A direct answer to each question the caller asked. If you could not answer one, say which and why. + +## How to work + +- Treat each question independently. Do not bundle. +- Prefer reading function bodies over reading comments or signatures. A signature plus a comment is **inferred** at best. +- If a question depends on runtime configuration (a setting, a build flag, a version gate), find where that condition is checked and report both branches. +- When server tests under `tests/queries/0_stateless/` exercise the behavior, mention the test name and its `.reference` file. Test references are often the clearest spec of what the server guarantees. + +## What you do not do + +- Do not modify any files. +- Do not write or suggest client-side code changes. The caller will do that based on your findings. +- Do not speculate about behavior you did not read. If the source did not answer the question, say so. + +## Model note + +You default to a mid-tier model because most server reading is grep, navigate, summarize. If the caller's question is unusually subtle (intricate template metaprogramming, multi-file invariants, behavior that depends on subtle ordering across translation units) and you find yourself uncertain after a reasonable read, say so plainly in your summary. The caller can then re-spawn you with a stronger model rather than you guessing. diff --git a/AGENTS.md b/AGENTS.md index 80eb452c..e5dc28a4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -58,10 +58,11 @@ A shallow clone of the ClickHouse server source should live at `.server-src/`, p Server investigation work is much higher quality with the actual server source available locally. If you need it and it is missing, try to set it up before continuing. -- If `.server-src/` or `.server-ref` is missing, tell the user that server investigation is best done against the real server source and that you recommend setting it up. Then try to create them. If the user has not specified a version, default to the most recent stable ClickHouse release tag. Write that tag to `.server-ref` and do a shallow clone of `https://github.com/ClickHouse/ClickHouse` at that tag into `.server-src/`. +- If `.server-src/` or `.server-ref` is missing, tell the user that server investigation is best done against the real server source and that you recommend setting it up. Then try to create them. If the user has not specified a version, default to the most recent stable ClickHouse release tag. Write that tag to `.server-ref` and do a shallow clone of `https://github.com/ClickHouse/ClickHouse` at that tag into `.server-src/`. Example: `git clone --depth 1 --branch https://github.com/ClickHouse/ClickHouse.git .server-src` followed by writing `` to `.server-ref`. - If you cannot set them up for any reason, tell the user plainly. You may continue without the local source, but flag in your answer that the investigation was done without it and the result is less reliable. - Do not silently re-clone an existing `.server-src/` and do not fall back to reading GitHub ad hoc when a local checkout is present. -- If the user asks you to investigate against a different version, tell them the current `.server-ref` tag and ask whether to switch before proceeding. +- If the user asks you to investigate against a different version, tell them the current `.server-ref` tag and ask whether to switch before proceeding. **Switch in place, do not blow away the existing checkout.** Inside `.server-src/`, run `git fetch --depth 1 origin tag ` and then `git checkout `, and write `` to `.server-ref`. This reuses the existing `.git` directory and is much faster than re-cloning, especially when bouncing between tags. +- Re-cloning `.server-src/` from scratch is a last resort, reserved for cases where the existing checkout is corrupt or in an unrecoverable state. Tell the user before doing it. Do not treat it as routine. - Cite the tag explicitly in your answer, for example: "at v26.3.9.8-lts, `JSONEachRowRowInputFormat::readRow` does X". ### Navigation @@ -70,29 +71,29 @@ Before grepping blindly through the server tree, read `.agents/server-map.md`. I If the map's pointers do not exist at the pinned tag, flag it plainly and tell the user before writing code that assumes them. -### Always delegate server C++ reading to a sub-agent +### Always delegate server C++ reading to the `clickhouse-server-reader` sub-agent ClickHouse is a large C++ codebase. Reading it directly in the main conversation bloats context fast and crowds out the client-side code you are actually changing. Delegate it. +The project ships a custom sub-agent definition at `.claude/agents/clickhouse-server-reader.md` that owns the discipline (citation rules, confirmed vs inferred, tag resolution, navigation via `.agents/server-map.md`). Use it for all server source reading. + Default workflow: 1. In the main conversation, identify the **specific questions** you need answered about server behavior. Examples: "how is a `Decimal(76, 10)` value laid out on the wire", "does `JSONEachRow` emit trailing newlines on empty result sets", "what is the exact null-mask byte order for `Nullable(LowCardinality(String))`". -2. Look up the relevant entry points in `.agents/server-map.md`. -3. Spawn a sub-agent with a focused prompt that includes: - - The pinned tag from `.server-ref`. - - The specific questions, one at a time. - - A short list of files or directories from the map worth starting with. - - An instruction to cite files and function or class names, and to mark each answer as **confirmed** (read the function body) or **inferred** (only read a signature, comment, or test). -4. Work from the sub-agent's summary. Do not pull raw C++ into the main thread. -5. If the summary is insufficient, send a follow-up question to the same sub-agent rather than reading the code yourself. +2. Spawn the `clickhouse-server-reader` sub-agent with those questions. Keep the prompt focused on the questions themselves. The sub-agent already knows to read `.server-ref`, consult `.agents/server-map.md`, cite tag and paths, and mark each claim as **confirmed** or **inferred**. +3. Work from the sub-agent's summary. Do not pull raw C++ into the main thread. +4. If the summary is insufficient, send a follow-up question to the same sub-agent rather than reading the code yourself. +5. If the sub-agent flags that a question was unusually subtle and its read was uncertain, re-spawn it with a stronger model rather than guessing. The main thread should stay focused on the client change. The sub-agent eats the C++ context. -### What your answer must contain +### What the final answer must contain + +When you reconcile the sub-agent's findings into your reply to the user, preserve: -- The resolved server tag you compared against. -- Specific server paths and function or class names you relied on. Do not cite line numbers; they rot. -- A clear distinction between **confirmed** (you read the function body) and **inferred** (you only read a signature, comment, or test name). +- The resolved server tag the sub-agent compared against. +- The specific server paths and function or class names it relied on. No line numbers, they rot. +- The sub-agent's **confirmed** vs **inferred** distinction. Do not collapse them. - Specific client-side file and line references for the behavior you are reconciling. ## Change Style