feat(semconv): donation-ready NuGet packages + runtime cutover - #156
Conversation
Brainstormed + researched plan. Key findings from Weaver exploration:
- semconv_grouped_attributes returns one synthetic group per root_namespace
- each mode works for per-namespace file generation
- attr.deprecated is structured {reason, renamed_to, note} — no external lookup needed
- String slicing attr.name[(ns|length+1):] derives local const names correctly
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Three NuGet packages added to packages/ and qyl.slnx:
- Qyl.OpenTelemetry.SemanticConventions (stable OTel attrs)
- Qyl.OpenTelemetry.SemanticConventions.Incubating (dev/experimental OTel attrs)
- Qyl.SemanticConventions (qyl custom attrs)
csharp_stable Weaver template confirmed end-to-end:
- application_mode: each → one file per root_namespace (90 files)
- HttpAttributes.g.cs: stable consts + RequestMethodValues nested class
- [Obsolete] annotations from native attr.deprecated.{reason,renamed_to,note}
- XML escaping for OTel upstream Markdown in doc comments
- All 12 reserved OTel attrs present (error.type, service.name, etc.)
- Build: 0 errors (116 CS1570 warnings from upstream Markdown docs, expected)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- csharp_incubating Weaver template (mirrors csharp_stable structure) - Filters non-stable attrs (development + experimental) via rejectattr - namespace: Qyl.OpenTelemetry.SemanticConventions.Incubating.Attributes.* - 90 Attributes/*.g.cs files generated (85 non-empty) - SchemaUrl.g.cs + SchemaVersion.g.cs generated - Template fixes applied to both csharp_stable and csharp_incubating: - global::System.Obsolete to avoid conflict with .Attributes.System namespace - Fallback for attrs whose name lacks namespace prefix (Other.state) - member.value | string | tojson for integer-valued enum members Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- eng/semconv/qyl/model/: 10 YAML files (ported from phase-c worktree) capability, run, project, team, issue, triage, fix_run, api_key, auth, storage Full attribute IDs (no deprecated prefix field), stability: experimental throughout - eng/semconv/templates/registry/csharp_qyl/: Weaver template set namespace: Qyl.SemanticConventions.Attributes.Qyl (single file, all qyl.* attrs) No stability filter; global::System.Obsolete; member.value | string | tojson - packages/Qyl.SemanticConventions/Attributes/Qyl/QylAttributes.g.cs: 27 constants - packages/Qyl.SemanticConventions/schemas/1.0.0.yaml: minimal OTel schema stub - Build: 0 errors on net10.0 + netstandard2.0 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
GenerateSemconv target in BuildPipeline.cs now: 1. git submodule update --init .tools/semconv-upstream 2. bootstrap-weaver.sh + run-weaver.sh (legacy semconv.ts/SQL/JSON) 3. Weaver csharp_stable → Qyl.OpenTelemetry.SemanticConventions 4. Weaver csharp_incubating → Qyl.OpenTelemetry.SemanticConventions.Incubating 5. Weaver csharp_qyl → Qyl.SemanticConventions 6. Copy .tools/semconv-upstream/schemas/1.40.0 → both OTel packages schemas/ All three csproj files: <EmbeddedResource Include="schemas/**" /> Schema files committed alongside generated C# for first-run greenness. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace "qyl.*", "gen_ai.*", "db.*" magic strings at the callsite with
generated constants from the three new packages:
- Qyl.SemanticConventions.Attributes.Qyl.QylAttributes for qyl.* keys
- Qyl.OpenTelemetry.SemanticConventions.Incubating.Attributes.GenAi for gen_ai.*
- Qyl.OpenTelemetry.SemanticConventions.Attributes.Db for db.* (stable)
- Qyl.OpenTelemetry.SemanticConventions.Attributes.Error/Exception for error.*, exception.*
Delete the three hand-written facade files under packages/Qyl.Contracts/Attributes/
(GenAiAttributes.cs, DbAttributes.cs, McpAttributes.cs) and migrate all
consumers (qyl.collector, qyl.mcp, qyl.instrumentation) to reference the
generated packages directly.
Strings with no generated equivalent are retained inline and documented:
- "duckdb" (qyl extension, not in upstream OTel registry)
- legacy db system values ("mssql", "oracle", "firebird") — upstream renamed
in 1.40 but value kept for consumer compatibility
- SQL uppercase operation names (db.operation.name is free-form upstream)
- "exception.escaped" (upstream obsoleted with no replacement)
- "gen_ai.client.token.usage" / "gen_ai.client.operation.duration"
(metric names; semconv registry covers attributes only)
Debug-build passes on the full solution. The pre-existing Release build
CS1591 wall in Qyl.Contracts/Generated/* is unchanged by this cutover.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Delete core/specs/telemetry/qyl-attrs.tsp and its imports from main.tsp and qyl-emit-config.tsp. The qyl-owned telemetry attribute registry now lives under eng/semconv/qyl/model/*.yaml (Weaver input) instead of as a TypeSpec marker model — the three new NuGet packages emitted by nuke GenerateSemconv are the runtime-visible form of the registry. Shrink @qyl/typespec-qyl-semconv-lint to a single diagnostic (QYL-LINT-001 upstream-collision). Rules 002–006 (bad-namespace, bad-naming, type-drift, stability-regression, cardinality-drift) are removed — Weaver owns those invariants via the registry schema now. TypeSpec devDeps documented in the brief (@typespec/events, @typespec/openapi, @typespec/openapi3, @typespec/sse, @typespec/streams, @typespec/versioning, openapi-typescript) remain in package.json: all seven are still in active use by the API contract pipeline, not the replaced semconv pipeline, and removing them breaks `tsp compile` + dashboard type generation. Only `@typespec/streams` was a candidate for outright removal (no direct imports in .tsp), but it's transitively required by `@typespec/http` — leaving it in place. Verification: - `npx tsp compile main.tsp` (with dotnet on PATH): 0 errors, 32 warnings (pre-existing PATCH convenience-method warnings) - `npm run build` on services/qyl.dashboard: passes - `npm test` on emitters/qyl-semconv-lint: 3 passed Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add package READMEs for the three Weaver-generated NuGet packages
(required by Directory.Build.props <PackageReadmeFile>README.md</>).
Fix NUKE GenerateSemconv platform detection: switch from
RuntimeInformation.OSDescription.Contains("Darwin") to
RuntimeInformation.IsOSPlatform(OSPlatform.OSX). On macOS 26+ the
OSDescription no longer reliably contains the literal "Darwin", so the
target was silently routing every Apple Silicon host to the Linux
Weaver binary path — reproducible both on this branch and on the
Phase-4 baseline (claude/adoring-tesla-a2d8b2).
Merge-gate outcome:
- dotnet build qyl.slnx (Debug): PASS (0 errors, 2847 warnings)
- dotnet build qyl.slnx -c Release: PRE-EXISTING FAIL (4615 CS1591
XML-doc errors in packages/Qyl.Contracts/Generated and the generator
projects, identical count as baseline 952efc1; zero non-doc errors
introduced by Phases 5-6)
- dotnet test tests/qyl.collector.tests: PRE-EXISTING ZERO-TESTS-RAN
(exit code 5 on baseline too; MTP harness discovery issue unrelated
to semconv)
- dotnet pack × 3: PASS
Qyl.SemanticConventions.1.0.0.nupkg 13,910 B
Qyl.OpenTelemetry.SemanticConventions.1.0.0.nupkg 49,406 B
Qyl.OpenTelemetry.SemanticConventions.Incubating.1.0.0.nupkg
210,939 B
- npm run build (services/qyl.dashboard): PASS
- npm test (core/specs/emitters/qyl-semconv-lint): PASS (3/3)
- nuke GenerateSemconv × 2 idempotency: PASS (empty
git status --porcelain on the generated tree after 2nd run)
- Reserved OTel attrs in stable package: 11/11 PRESENT
error.type · exception.{message,stacktrace,type} ·
server.{address,port} · service.name ·
telemetry.sdk.{language,name,version} · url.scheme
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
Important Review skippedReview was skipped due to path filters ⛔ Files ignored due to path filters (1)
CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughRemoved five diagnostics from the qyl-semconv-lint emitter, leaving only 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
Hoist the inline array literal into a `ReadOnlySpan<string>` collection expression to satisfy CA1861 (treated as error by qyl's CA policy). Adds `using System;` for the span type. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR introduces three new, donation-ready semantic-conventions NuGet packages (qyl-owned + OTel stable + OTel incubating), updates the NUKE GenerateSemconv pipeline to deterministically regenerate them via Weaver, and cuts runtime code over to the new generated typed constants (replacing the prior qyl.contracts.Attributes facades).
Changes:
- Add new packages:
Qyl.SemanticConventions,Qyl.OpenTelemetry.SemanticConventions, andQyl.OpenTelemetry.SemanticConventions.Incubating(generated constants + embedded schemas). - Update runtime/services to reference the new packages and migrate attribute-key usage to generated constants.
- Update
nuke GenerateSemconvto run Weaver directly for C# outputs (plus submodule bootstrap and schema copying).
Reviewed changes
Copilot reviewed 165 out of 245 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| services/qyl.mcp/qyl.mcp.csproj | Adds project refs to the new semconv packages. |
| services/qyl.mcp/Hosting/QylMcpServerRegistration.cs | Switches MCP tracing tags to generated semconv constants; tool type value now literal. |
| services/qyl.mcp/Client.cs | Switches schema URL source to SchemaUrl.Current from the new package. |
| services/qyl.dashboard/package-lock.json | Lockfile normalization (removes libc constraints entries). |
| services/qyl.collector/qyl.collector.csproj | Adds project refs to the new semconv packages. |
| services/qyl.collector/Telemetry/QylTelemetry.cs | Migrates metric name to QylAttributes.* constant. |
| services/qyl.collector/Telemetry/QylLogEnricher.cs | Migrates log enrichment key to QylAttributes.* constant. |
| services/qyl.collector/Storage/DuckDbStore.cs | Migrates counter names to QylAttributes.* constants. |
| services/qyl.collector/Ingestion/CodexTelemetryMapper.cs | Migrates to generated OTel constants for provider/op/error/exception; tool type value now literal. |
| services/qyl.collector/GlobalUsings.cs | Replaces qyl.contracts.Attributes with global usings for new generated attributes. |
| services/qyl.collector/Auth/TokenAuth.cs | Replaces Keycloak claims key literal with QylAttributes.KeycloakClaims. |
| qyl.slnx | Adds the three new packages to the solution. |
| packages/Qyl.SemanticConventions/** | New package: qyl-owned attribute keys + schema + generated version constant. |
| packages/Qyl.OpenTelemetry.SemanticConventions/** | New package: OTel stable attribute keys + schema + generated schema URL/version. |
| packages/Qyl.OpenTelemetry.SemanticConventions.Incubating/** | New package: OTel incubating attribute keys + schema + generated schema URL/version. |
| packages/Qyl.Contracts/Attributes/McpAttributes.cs | Removes old hand-maintained MCP semconv facade. |
| packages/Qyl.Contracts/Attributes/DbAttributes.cs | Removes old hand-maintained DB semconv facade. |
| internal/qyl.instrumentation/qyl.instrumentation.csproj | Adds project refs to the new semconv packages. |
| internal/qyl.instrumentation/Instrumentation/GenAiConstants.cs | Switches to incubating generated GenAI constants for provider/op/output type. |
| internal/qyl.instrumentation/Instrumentation/GenAi/GenAiInstrumentation.cs | Migrates tags to generated constants; metric instrument names now literals. |
| internal/qyl.instrumentation/Instrumentation/Db/SqlOperationParser.cs | Removes dependency on removed DB facade; uses literal SQL operation strings. |
| internal/qyl.instrumentation/Instrumentation/Db/DbInstrumentation.cs | Switches to generated DB constants; preserves some legacy db.system values via literals. |
| internal/qyl.instrumentation/Instrumentation/ActivityExceptionTelemetry.cs | Switches error/exception keys to generated constants (keeps exception.escaped as literal). |
| eng/semconv/templates/registry/** | Adds Weaver template sets for stable/incubating/qyl C# registries. |
| eng/semconv/qyl/model/*.yaml | Adds qyl-owned semconv registry YAML files (auth, issue, run, etc.). |
| eng/build/BuildPipeline.cs | Updates GenerateSemconv to generate the C# packages via Weaver and copy schemas. |
| core/specs/telemetry/qyl-attrs.tsp | Removes the prior TypeSpec-based qyl telemetry attribute registry marker. |
| core/specs/qyl-emit-config.tsp | Drops import of the qyl-semconv-lint package. |
| core/specs/main.tsp | Removes import of the removed telemetry registry marker. |
| core/specs/emitters/qyl-semconv-lint/src/index.ts | Reduces diagnostics surface (keeps only upstream-collision). |
| core/specs/emitters/qyl-semconv-lint/test/rules.test.ts | Reduces test coverage to only upstream collision. |
| core/specs/**/package-lock.json | Lockfile normalization (removes libc constraints entries). |
Files not reviewed (3)
- core/specs/emitters/qyl-semconv-lint/package-lock.json: Language not supported
- core/specs/package-lock.json: Language not supported
- services/qyl.dashboard/package-lock.json: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| activity?.SetTag(GenAiAttributes.OperationName, GenAiAttributes.OperationNameValues.ExecuteTool); | ||
| activity?.SetTag(GenAiAttributes.ToolName, toolName); | ||
| activity?.SetTag(GenAiAttributes.ToolType, GenAiAttributes.ToolTypes.Extension); | ||
| activity?.SetTag(GenAiAttributes.ToolType, "extension"); | ||
| activity?.SetTag(Rpc.Method, "tools/call"); |
There was a problem hiding this comment.
Hard-coded tool type value "extension" is now used directly. Since there are multiple call sites using well-known gen_ai.tool.type values and the generated semconv code doesn’t provide value constants for them, consider introducing a shared constant (or small helper) to keep these values consistent across the runtime.
| // Map tool type (Codex tools are function-based) | ||
| if (toolName is not null && !attributes.ContainsKey(GenAiAttributes.ToolType)) | ||
| { | ||
| attributes[GenAiAttributes.ToolType] = GenAiAttributes.ToolTypes.Function; | ||
| attributes[GenAiAttributes.ToolType] = "function"; | ||
| transformed = true; | ||
| } |
There was a problem hiding this comment.
Hard-coded tool type value "function" is now written into span attributes. With multiple call sites emitting gen_ai.tool.type and no generated value constants, consider centralizing these well-known values to avoid inconsistent spelling/casing over time.
| default: paramMessage`QYL-LINT-001: attribute '${"key"}' collides with upstream OTel namespace '${"prefix"}' — qyl attributes must live under 'qyl.'`, | ||
| }, | ||
| }, | ||
| "bad-namespace": { | ||
| severity: "error", | ||
| messages: { | ||
| default: paramMessage`QYL-LINT-002: attribute '${"key"}' must start with 'qyl.' — project-owned namespaces are forbidden outside that prefix`, | ||
| }, | ||
| }, | ||
| "bad-naming": { | ||
| severity: "error", | ||
| messages: { | ||
| default: paramMessage`QYL-LINT-003: attribute '${"key"}' violates OTel naming: lowercase letters, digits, underscores, dot-separated segments, no leading/trailing/doubled dots`, | ||
| }, | ||
| }, | ||
| "type-drift": { | ||
| severity: "error", | ||
| messages: { | ||
| default: paramMessage`QYL-LINT-004: attribute '${"key"}' declared as '${"typeA"}' here but as '${"typeB"}' at ${"otherSite"}`, | ||
| }, | ||
| }, | ||
| "stability-regression": { | ||
| severity: "error", | ||
| messages: { | ||
| default: paramMessage`QYL-LINT-005: attribute '${"key"}' stability regressed from '${"prior"}' to '${"current"}' — 'stable' is a one-way ratchet`, | ||
| }, | ||
| }, | ||
| "cardinality-drift": { | ||
| severity: "warning", | ||
| messages: { | ||
| default: paramMessage`QYL-LINT-006: attribute '${"key"}' cardinality differs across sites: '${"a"}' vs '${"b"}'`, | ||
| }, | ||
| }, | ||
| }, |
There was a problem hiding this comment.
This PR removes diagnostics/rules beyond upstream-collision, which means @qylAttr keys like acme.foo or qyl.Foo will no longer be rejected by this linter (only reserved-prefix collisions are caught). If this is intentional, consider updating the library’s docs/comments (and/or its name/README) to reflect the reduced validation scope so consumers don’t assume QYL-LINT-002..006 are still enforced.
|
|
||
| Schema URL: `https://schemas.qyl.io/1.0.0` | ||
|
|
There was a problem hiding this comment.
Schema URL in this README (https://schemas.qyl.io/1.0.0) does not match the embedded schema manifest (schemas/1.0.0.yaml declares https://qyl.dev/schemas/1.0.0). This will confuse consumers and makes it unclear which URL is authoritative. Align the README to the YAML (or update the YAML) so the package documentation and embedded schema agree.
| if (((string)schemaSource).Length > 0 && File.Exists(schemaSource)) | ||
| { | ||
| ReadOnlySpan<string> otelPackages = ["Qyl.OpenTelemetry.SemanticConventions", "Qyl.OpenTelemetry.SemanticConventions.Incubating"]; | ||
| foreach (var pkg in otelPackages) | ||
| { | ||
| var schemasDir = RootDirectory / "packages" / pkg / "schemas"; | ||
| Directory.CreateDirectory(schemasDir); | ||
| File.Copy(schemaSource, schemasDir / "1.40.0.yaml", overwrite: true); | ||
| } | ||
| } |
There was a problem hiding this comment.
The schema copy step is silently skipped when the source schema file isn't found. That can lead to generating/packing OTel semconv packages without the embedded schema resource, breaking the “deterministic pipeline” goal while still succeeding locally/CI. Consider failing the target if the schema file is missing (and/or logging an explicit warning with the expected path), and remove the redundant Length > 0 check.
| if (((string)schemaSource).Length > 0 && File.Exists(schemaSource)) | |
| { | |
| ReadOnlySpan<string> otelPackages = ["Qyl.OpenTelemetry.SemanticConventions", "Qyl.OpenTelemetry.SemanticConventions.Incubating"]; | |
| foreach (var pkg in otelPackages) | |
| { | |
| var schemasDir = RootDirectory / "packages" / pkg / "schemas"; | |
| Directory.CreateDirectory(schemasDir); | |
| File.Copy(schemaSource, schemasDir / "1.40.0.yaml", overwrite: true); | |
| } | |
| } | |
| if (!File.Exists(schemaSource)) | |
| { | |
| Log.Error("GenerateSemconv: required OTel schema file was not found at {SchemaSource}", schemaSource); | |
| throw new FileNotFoundException($"Required OTel schema file was not found: {schemaSource}", schemaSource); | |
| } | |
| ReadOnlySpan<string> otelPackages = ["Qyl.OpenTelemetry.SemanticConventions", "Qyl.OpenTelemetry.SemanticConventions.Incubating"]; | |
| foreach (var pkg in otelPackages) | |
| { | |
| var schemasDir = RootDirectory / "packages" / pkg / "schemas"; | |
| Directory.CreateDirectory(schemasDir); | |
| File.Copy(schemaSource, schemasDir / "1.40.0.yaml", overwrite: true); | |
| } |
| private static Histogram<long> TokenUsageHistogram => | ||
| field ??= ActivitySources.GenAiMeter.CreateHistogram<long>( | ||
| GenAiAttributes.Metrics.ClientTokenUsage, "{token}", "Token usage"); | ||
| "gen_ai.client.token.usage", "{token}", "Token usage"); | ||
|
|
||
| private static Histogram<double> OperationDurationHistogram => | ||
| field ??= ActivitySources.GenAiMeter.CreateHistogram<double>( | ||
| GenAiAttributes.Metrics.ClientOperationDuration, "s", "Operation duration"); | ||
| "gen_ai.client.operation.duration", "s", "Operation duration"); |
There was a problem hiding this comment.
These histogram instrument names were previously sourced from a typed constant, but are now hard-coded string literals. This is a regression against the PR goal of eliminating magic strings and increases the chance of subtle naming drift/typos. Consider reintroducing a single authoritative constant location for these metric names (e.g., an internal GenAiMetricNames class) and reference that from here.
| public static Activity? StartToolExecutionSpan( | ||
| string toolName, | ||
| string? callId = null, | ||
| string? toolType = GenAiAttributes.ToolTypes.Function) | ||
| string? toolType = "function") | ||
| { |
There was a problem hiding this comment.
toolType defaults to a free-form string literal ("function") and the same tool type values are also hard-coded elsewhere (e.g., "extension" in MCP and "function" in Codex mapping). Since the new generated semconv package doesn't provide value constants for gen_ai.tool.type, consider centralizing these well-known values in one place to avoid drift/typos across call sites.
There was a problem hiding this comment.
Actionable comments posted: 11
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@core/specs/emitters/qyl-semconv-lint/src/rules.ts`:
- Around line 20-28: The docblock says keys must be qyl-owned but the current
checkUpstreamCollision(program, records) logic no longer enforces a "qyl."
prefix and only checks RESERVED_PREFIXES; restore an explicit diagnostic that
requires every `@qylAttr` key string (from QylAttrRecord) to start with "qyl." and
emit a clear error when it does not, while keeping the existing
upstream-collision checks; update the checkUpstreamCollision function (and the
same logic that handles records around lines ~41-45) to first validate the
"qyl." prefix on the attribute name, then proceed to the RESERVED_PREFIXES
collision check so the rule enforces both ownership and upstream avoidance.
In `@eng/build/BuildPipeline.cs`:
- Line 91: The foreach currently allocates a new array in the loop header
(foreach (var pkg in new[] { "Qyl.OpenTelemetry.SemanticConventions",
"Qyl.OpenTelemetry.SemanticConventions.Incubating" })) which triggers CA1861;
fix it by replacing the inline array with a reuseable source such as a private
static readonly string[] field (e.g., private static readonly string[]
SemanticConventionPkgs = { "Qyl.OpenTelemetry.SemanticConventions",
"Qyl.OpenTelemetry.SemanticConventions.Incubating" }) and iterate over
SemanticConventionPkgs in the foreach, or alternatively call the operation
explicitly twice for each package name to avoid any array allocation; reference
the foreach block and the package names when applying the change.
- Around line 88-97: The current embedding block around schemaSource in
BuildPipeline.cs silently skips embedding when the upstream schema file is
missing; change it to fail fast by validating that schemaSource exists and
throwing a clear exception (e.g., FileNotFoundException or
InvalidOperationException) with the schemaSource path when
File.Exists(schemaSource) is false before attempting the foreach/Copy loop;
locate the schemaSource initialization and the conditional that currently checks
((string)schemaSource).Length > 0 && File.Exists(schemaSource) and replace the
silent no-op with an explicit throw so packages cannot be produced without the
embedded schema.
- Around line 59-63: The platform selection for the weaver binary in
BuildPipeline.cs incorrectly defaults all non-macOS to
"x86_64-unknown-linux-gnu"; update the logic around weaverArch/weaverBin to
validate OS and Architecture explicitly (using RuntimeInformation.IsOSPlatform
and RuntimeInformation.ProcessArchitecture) and throw a NotSupportedException
for unsupported OS/architecture combinations (e.g., Windows or Linux Arm64) to
mirror bootstrap-weaver.sh behavior so the BuildPipeline fails fast with a clear
error instead of selecting the wrong binary.
In `@eng/semconv/qyl/model/api_key.yaml`:
- Around line 10-13: The audit fingerprint for API keys in
eng/semconv/qyl/model/api_key.yaml is too short (sha256[:8]); update the spec
text and example to use a longer, collision-resistant fingerprint (at minimum
sha256[:16] for 64 bits, preferably sha256[:32] for 128 bits) or switch to a
stable server-side key id; specifically change the brief from "First 8
characters of the API key hash (sha256[:8])" to indicate the chosen longer slice
(e.g., "First 16 characters of the API key hash (sha256[:16])" or "First 32
characters (sha256[:32])") and update the examples array (e.g., from 'a1b2c3d4'
to a matching-length hex sample) and any consumers that parse or generate this
fingerprint (look for references to the api_key fingerprint field/name in
validation/parsing code).
In `@eng/semconv/qyl/model/auth.yaml`:
- Around line 7-12: Replace the experimental attribute id "qyl.keycloak.claims"
(serialized Keycloak JWT claims) with a small allow-list of non-sensitive
derived attributes: add attributes such as "qyl.keycloak.issuer" (string),
"qyl.keycloak.tenant" (string or optional), and "qyl.keycloak.subject_hash"
(string, stable hash of subject) and ensure the raw/serialized claims attribute
is removed; update any gating notes to state these derived attributes may be
emitted only when allowed and do not contain raw PII or secrets, and update any
documentation/comments referencing keycloak.claims to use the new derived
attributes (look for id "keycloak.claims" in the diff to locate the change).
In `@eng/semconv/qyl/model/capability.yaml`:
- Around line 21-23: The member with id 'follow_up' is missing the stability
tag; add "stability: experimental" to the 'follow_up' mapping (same level as
id/value/brief) so it matches the 'starting' member; ensure YAML indentation
aligns with the other members (i.e., add stability: experimental under the
follow_up entry alongside id/value/brief).
In `@eng/semconv/templates/registry/csharp_qyl/attributes.cs.j2`:
- Around line 37-41: The member-level Obsolete emission currently stringifies
member.deprecated; change it to mirror the attribute-level deprecation logic:
inspect member.deprecated for keys (renamed, obsoleted, note) and build a
structured message (e.g., "Renamed to <newName>" when renamed, "Obsoleted:
<reason>" when obsoleted, fallback to note) then pass that message into the
[global::System.Obsolete(..., false)] call for the constant whose identifier is
member.id and value is member.value so member-level deprecation messages match
attribute-level formatting.
In `@eng/semconv/templates/registry/csharp_qyl/weaver.yaml`:
- Around line 9-11: Remove the hardcoded params.schema_version from the template
and instead read the canonical schema version from a single build-owned source
(e.g., a NUKE variable or MSBuild property passed into generation as a
parameter), update generation to inject that value where schema_version was
used, and add a generation-time check that compares the model checksum (or
timestamps) against SchemaVersion.Current and fails the build if the model
changed without bumping that property so generation cannot silently use an
out-of-date SchemaVersion.Current.
In `@eng/semconv/templates/registry/csharp_stable/attributes.cs.j2`:
- Around line 1-50: The template duplicates nearly all Jinja logic; refactor by
extracting the shared rendering into a reusable macro file (e.g., create a
macros jinja file and import it) so the three templates (stable/incubating/qyl)
only differ by the stability filter. Move the XML-escaping/summary generation,
deprecation handling (the Obsolete branches), member loop that generates "{{
local_name }}Values" and member constants, and the local_name/_stripped logic
into a macro (accepting the attribute list or a stability argument), then have
attributes.cs.j2 call that macro with stable_attrs (or the appropriate filtered
list) instead of duplicating the block that generates public const string {{
local_name }} and the nested {{ local_name }}Values class.
- Around line 40-42: The template emits inconsistent Obsolete messages by
stringifying member.deprecated in attributes.cs.j2; update the conditional that
generates the [global::System.Obsolete(...)] for enum members to use the same
structured reason-based logic used earlier for attributes (the logic around
lines 23-30) instead of directly stringifying member.deprecated—i.e., detect
whether a deprecation reason exists and emit either Obsolete("reason", false) or
Obsolete(false) accordingly so enum member deprecation messages match attribute
deprecation messages.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 2b45da04-5839-4130-997e-2cada54d7dcb
⛔ Files ignored due to path filters (217)
core/specs/emitters/qyl-semconv-lint/package-lock.jsonis excluded by!**/package-lock.json,!**/package-lock.jsonand included bycore/**core/specs/package-lock.jsonis excluded by!**/package-lock.json,!**/package-lock.jsonand included bycore/**docs/superpowers/plans/2026-04-22-otel-semconv-weaver-pipeline.mdis excluded by none and included by noneinternal/qyl.instrumentation/Instrumentation/ActivityExceptionTelemetry.csis excluded by none and included by noneinternal/qyl.instrumentation/Instrumentation/Db/DbInstrumentation.csis excluded by none and included by noneinternal/qyl.instrumentation/Instrumentation/Db/SqlOperationParser.csis excluded by none and included by noneinternal/qyl.instrumentation/Instrumentation/GenAi/GenAiInstrumentation.csis excluded by none and included by noneinternal/qyl.instrumentation/Instrumentation/GenAiConstants.csis excluded by none and included by noneinternal/qyl.instrumentation/qyl.instrumentation.csprojis excluded by none and included by nonepackages/Qyl.Contracts/Attributes/DbAttributes.csis excluded by none and included by nonepackages/Qyl.Contracts/Attributes/GenAiAttributes.csis excluded by none and included by nonepackages/Qyl.Contracts/Attributes/McpAttributes.csis excluded by none and included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Android/AndroidAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/App/AppAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Artifact/ArtifactAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Aspnetcore/AspnetcoreAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Aws/AwsAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Az/AzAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Azure/AzureAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Browser/BrowserAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Cassandra/CassandraAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Cicd/CicdAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Client/ClientAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Cloud/CloudAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Cloudevents/CloudeventsAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Cloudfoundry/CloudfoundryAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Code/CodeAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Container/ContainerAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Cpu/CpuAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Cpython/CpythonAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Db/DbAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Deployment/DeploymentAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Destination/DestinationAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Device/DeviceAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Disk/DiskAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Dns/DnsAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Dotnet/DotnetAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Elasticsearch/ElasticsearchAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Enduser/EnduserAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Error/ErrorAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Event/EventAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Exception/ExceptionAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Faas/FaasAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/FeatureFlag/FeatureFlagAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/File/FileAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Gcp/GcpAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/GenAi/GenAiAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Geo/GeoAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Go/GoAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Graphql/GraphqlAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Heroku/HerokuAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Host/HostAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Http/HttpAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Hw/HwAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Ios/IosAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Jsonrpc/JsonrpcAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Jvm/JvmAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/K8s/K8sAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Linux/LinuxAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Mainframe/MainframeAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Mcp/McpAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Message/MessageAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Messaging/MessagingAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Net/NetAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Network/NetworkAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Nfs/NfsAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Nodejs/NodejsAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Oci/OciAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/OncRpc/OncRpcAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Openai/OpenaiAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Openshift/OpenshiftAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Opentracing/OpentracingAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Oracle/OracleAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/OracleCloud/OracleCloudAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Os/OsAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Otel/OtelAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Other/OtherAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Peer/PeerAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Pool/PoolAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Pprof/PprofAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Process/ProcessAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Profile/ProfileAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Rpc/RpcAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/SecurityRule/SecurityRuleAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Server/ServerAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Service/ServiceAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Session/SessionAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Signalr/SignalrAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Source/SourceAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/System/SystemAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Telemetry/TelemetryAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Test/TestAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Thread/ThreadAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Tls/TlsAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Url/UrlAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/User/UserAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/UserAgent/UserAgentAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/V8js/V8jsAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Vcs/VcsAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Webengine/WebengineAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Attributes/Zos/ZosAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/Qyl.OpenTelemetry.SemanticConventions.Incubating.csprojis excluded by none and included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/README.mdis excluded by none and included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/SchemaUrl.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/SchemaVersion.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions.Incubating/schemas/1.40.0.yamlis excluded by none and included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Android/AndroidAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/App/AppAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Artifact/ArtifactAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Aspnetcore/AspnetcoreAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Aws/AwsAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Az/AzAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Azure/AzureAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Browser/BrowserAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Cassandra/CassandraAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Cicd/CicdAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Client/ClientAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Cloud/CloudAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Cloudevents/CloudeventsAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Cloudfoundry/CloudfoundryAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Code/CodeAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Container/ContainerAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Cpu/CpuAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Cpython/CpythonAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Db/DbAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Deployment/DeploymentAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Destination/DestinationAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Device/DeviceAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Disk/DiskAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Dns/DnsAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Dotnet/DotnetAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Elasticsearch/ElasticsearchAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Enduser/EnduserAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Error/ErrorAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Event/EventAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Exception/ExceptionAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Faas/FaasAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/FeatureFlag/FeatureFlagAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/File/FileAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Gcp/GcpAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/GenAi/GenAiAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Geo/GeoAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Go/GoAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Graphql/GraphqlAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Heroku/HerokuAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Host/HostAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Http/HttpAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Hw/HwAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Ios/IosAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Jsonrpc/JsonrpcAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Jvm/JvmAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/K8s/K8sAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Linux/LinuxAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Mainframe/MainframeAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Mcp/McpAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Message/MessageAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Messaging/MessagingAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Net/NetAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Network/NetworkAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Nfs/NfsAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Nodejs/NodejsAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Oci/OciAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/OncRpc/OncRpcAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Openai/OpenaiAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Openshift/OpenshiftAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Opentracing/OpentracingAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Oracle/OracleAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/OracleCloud/OracleCloudAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Os/OsAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Otel/OtelAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Other/OtherAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Peer/PeerAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Pool/PoolAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Pprof/PprofAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Process/ProcessAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Profile/ProfileAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Rpc/RpcAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/SecurityRule/SecurityRuleAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Server/ServerAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Service/ServiceAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Session/SessionAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Signalr/SignalrAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Source/SourceAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/System/SystemAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Telemetry/TelemetryAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Test/TestAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Thread/ThreadAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Tls/TlsAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Url/UrlAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/User/UserAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/UserAgent/UserAgentAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/V8js/V8jsAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Vcs/VcsAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Webengine/WebengineAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Attributes/Zos/ZosAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/Qyl.OpenTelemetry.SemanticConventions.csprojis excluded by none and included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/README.mdis excluded by none and included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/SchemaUrl.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/SchemaVersion.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.OpenTelemetry.SemanticConventions/schemas/1.40.0.yamlis excluded by none and included by nonepackages/Qyl.SemanticConventions/Attributes/Qyl/QylAttributes.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.SemanticConventions/Qyl.SemanticConventions.csprojis excluded by none and included by nonepackages/Qyl.SemanticConventions/README.mdis excluded by none and included by nonepackages/Qyl.SemanticConventions/SchemaVersion.g.csis excluded by!**/*.g.csand included by nonepackages/Qyl.SemanticConventions/schemas/1.0.0.yamlis excluded by none and included by noneqyl.slnxis excluded by none and included by noneservices/qyl.collector/Auth/TokenAuth.csis excluded by none and included by noneservices/qyl.collector/GlobalUsings.csis excluded by none and included by noneservices/qyl.collector/Ingestion/CodexTelemetryMapper.csis excluded by none and included by noneservices/qyl.collector/Storage/DuckDbStore.csis excluded by none and included by noneservices/qyl.collector/Telemetry/QylLogEnricher.csis excluded by none and included by noneservices/qyl.collector/Telemetry/QylTelemetry.csis excluded by none and included by noneservices/qyl.collector/qyl.collector.csprojis excluded by none and included by noneservices/qyl.dashboard/package-lock.jsonis excluded by!**/package-lock.json,!**/package-lock.jsonand included by noneservices/qyl.mcp/Client.csis excluded by none and included by noneservices/qyl.mcp/Hosting/QylMcpServerRegistration.csis excluded by none and included by noneservices/qyl.mcp/qyl.mcp.csprojis excluded by none and included by none
📒 Files selected for processing (28)
core/specs/emitters/qyl-semconv-lint/src/index.tscore/specs/emitters/qyl-semconv-lint/src/rules.tscore/specs/emitters/qyl-semconv-lint/test/rules.test.tscore/specs/main.tspcore/specs/qyl-emit-config.tspcore/specs/telemetry/qyl-attrs.tspeng/build/BuildPipeline.cseng/semconv/qyl/model/api_key.yamleng/semconv/qyl/model/auth.yamleng/semconv/qyl/model/capability.yamleng/semconv/qyl/model/fix_run.yamleng/semconv/qyl/model/issue.yamleng/semconv/qyl/model/project.yamleng/semconv/qyl/model/run.yamleng/semconv/qyl/model/storage.yamleng/semconv/qyl/model/team.yamleng/semconv/qyl/model/triage.yamleng/semconv/templates/registry/csharp_incubating/attributes.cs.j2eng/semconv/templates/registry/csharp_incubating/schema_url.cs.j2eng/semconv/templates/registry/csharp_incubating/schema_version.cs.j2eng/semconv/templates/registry/csharp_incubating/weaver.yamleng/semconv/templates/registry/csharp_qyl/attributes.cs.j2eng/semconv/templates/registry/csharp_qyl/schema_version.cs.j2eng/semconv/templates/registry/csharp_qyl/weaver.yamleng/semconv/templates/registry/csharp_stable/attributes.cs.j2eng/semconv/templates/registry/csharp_stable/schema_url.cs.j2eng/semconv/templates/registry/csharp_stable/schema_version.cs.j2eng/semconv/templates/registry/csharp_stable/weaver.yaml
💤 Files with no reviewable changes (4)
- core/specs/main.tsp
- core/specs/emitters/qyl-semconv-lint/src/index.ts
- core/specs/qyl-emit-config.tsp
- core/specs/telemetry/qyl-attrs.tsp
📜 Review details
⏰ Context from checks skipped due to timeout of 120000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Agent
- GitHub Check: Analyze (csharp)
🧰 Additional context used
📓 Path-based instructions (2)
eng/**
⚙️ CodeRabbit configuration file
Build and deployment infrastructure. Review for: correct MSBuild property usage, Nuke build target dependencies, Docker multi-stage build efficiency, and CI/CD pipeline correctness. Flag hardcoded paths, secrets, or platform-specific assumptions.
Files:
eng/semconv/templates/registry/csharp_qyl/weaver.yamleng/semconv/templates/registry/csharp_stable/schema_version.cs.j2eng/semconv/templates/registry/csharp_qyl/schema_version.cs.j2eng/semconv/templates/registry/csharp_incubating/schema_version.cs.j2eng/semconv/qyl/model/project.yamleng/semconv/qyl/model/team.yamleng/semconv/templates/registry/csharp_incubating/schema_url.cs.j2eng/build/BuildPipeline.cseng/semconv/qyl/model/auth.yamleng/semconv/qyl/model/triage.yamleng/semconv/templates/registry/csharp_stable/schema_url.cs.j2eng/semconv/templates/registry/csharp_incubating/weaver.yamleng/semconv/qyl/model/issue.yamleng/semconv/qyl/model/capability.yamleng/semconv/qyl/model/storage.yamleng/semconv/templates/registry/csharp_stable/weaver.yamleng/semconv/qyl/model/fix_run.yamleng/semconv/qyl/model/api_key.yamleng/semconv/qyl/model/run.yamleng/semconv/templates/registry/csharp_stable/attributes.cs.j2eng/semconv/templates/registry/csharp_qyl/attributes.cs.j2eng/semconv/templates/registry/csharp_incubating/attributes.cs.j2
**/*.cs
📄 CodeRabbit inference engine (AGENTS.md)
**/*.cs: For arbitrary non-chat methods/metrics, use attribute-based instrumentation ([Traced]/[Meter]/[Counter]/etc.) only where no builder surface exists.
New.csfiles must be UTF-8 with BOM encoding..editorconfigdeclarescharset = utf-8-bomunder[*.cs].
Use// Copyright (c) 2025-2026 ancpluacopyright header on top of.csfiles.
XML documentation is required on all public methods and classes in C# files.
Use theAsyncsuffix for any method returningTask/ValueTask, including test methods.
Declare private classes assealedunless intentionally subclassed.
Environment variables useUPPER_SNAKE_CASE(e.g.,QYL_AGENT_MAX_DEPTH,OTEL_EXPORTER_OTLP_ENDPOINT).
C# 14 with preview features enabled. Use file-scoped namespaces, primary constructors, required init properties, pattern matching, switch expressions over if-else.
No suppression: No#pragma warning disable, no[SuppressMessage], no<NoWarn>(exception: upstream sample repos demonstrating experimental APIs).
Never use runtime reflection as a control mechanism,dynamic/ExpandoObject, blocking async (.Result/.Wait()), or any analyzer besidesANcpLua.Analyzers.
Do not suppressnull !when the code can be rewritten to avoid the suppression.
Never hand-register a tool. Instead, add[QylSkill]+[QylCapability]attributes and let the generator handle DI registration, MCP tool registration, and capability catalogs.
No attribute-based agent tracing—[AgentTraced]was removed in the 2026-04 collapse. Use fluent middleware instead.
InvestigationLineage(AsyncLocal) enforces max depth (3), root spawn budget (10), cycle detection. Tools callInvestigationLineage.TryEnter()before starting investigations.
Environment overrides for bounded autonomy:QYL_AGENT_MAX_DEPTH,QYL_AGENT_MAX_SPAWNS.
ConstructLoomToolEnveloperesults via the non-generic companion —LoomToolEnvelope.Ok(data)/LoomToolEnvelope.Fail<T>(error). NEVER `LoomToolEnvelope....
Files:
eng/build/BuildPipeline.cs
🧠 Learnings (12)
📓 Common learnings
Learnt from: CR
Repo: Alexander-Nachtmann/qyl PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-21T06:24:06.977Z
Learning: Applies to **/*.{csproj,package.json} : Do not replace external dependencies: `Microsoft.Agents.AI`, `Microsoft.Agents.AI.Hosting`, `Microsoft.Extensions.AI`, `ModelContextProtocol` 1.1.0, `OpenTelemetry` SDK 1.15.0 + Semantic Conventions 1.40, `DuckDB.NET` 1.5.0, `Base UI` 1.3.0 + `lucide-react`, `xUnit v3` + `Microsoft.Testing.Platform`.
Learnt from: CR
Repo: Alexander-Nachtmann/qyl PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-21T06:24:06.977Z
Learning: Applies to **/*{Chat,Agent,Client,Instrumentation,Telemetry}*.cs : Emit OTel GenAI semconv 1.40 with required attributes: `gen_ai.system`, `gen_ai.request.model`, `gen_ai.response.model`, `gen_ai.usage.input_tokens`, `gen_ai.usage.output_tokens`, `gen_ai.operation.name`, `gen_ai.tool.call.id`, `gen_ai.tool.name`, `gen_ai.agent.name`, `gen_ai.agent.id`.
Learnt from: CR
Repo: Alexander-Nachtmann/qyl PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-21T06:24:06.977Z
Learning: Applies to **/generators/**/*.cs : Use `IIncrementalGenerator` only. Enforce `ForAttributeWithMetadataName`, value-equatable models, raw strings over `SyntaxFactory`. Never store `ISymbol` in models.
Learnt from: CR
Repo: Alexander-Nachtmann/qyl PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-21T06:24:06.977Z
Learning: Applies to **/*{Builder,Composition,Startup,Program}.cs : Replace attribute-based agent telemetry (`[AgentTraced]` + generators) with MAF's fluent middleware pipeline: `.AsBuilder().UseOpenTelemetry("qyl.agent").Build()` at the composition root.
Learnt from: CR
Repo: Alexander-Nachtmann/qyl PR: 0
File: src/qyl.mcp/CLAUDE.md:0-0
Timestamp: 2026-04-21T00:49:29.212Z
Learning: Applies to src/qyl.mcp/**/*.cs : Use `System.Text.Json` instead of Newtonsoft for JSON serialization in C# code
📚 Learning: 2026-04-21T06:24:06.977Z
Learnt from: CR
Repo: Alexander-Nachtmann/qyl PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-21T06:24:06.977Z
Learning: Applies to **/*{Chat,Agent,Client,Instrumentation,Telemetry}*.cs : Emit OTel GenAI semconv 1.40 with required attributes: `gen_ai.system`, `gen_ai.request.model`, `gen_ai.response.model`, `gen_ai.usage.input_tokens`, `gen_ai.usage.output_tokens`, `gen_ai.operation.name`, `gen_ai.tool.call.id`, `gen_ai.tool.name`, `gen_ai.agent.name`, `gen_ai.agent.id`.
Applied to files:
eng/semconv/templates/registry/csharp_qyl/weaver.yamleng/semconv/templates/registry/csharp_stable/schema_version.cs.j2eng/semconv/templates/registry/csharp_qyl/schema_version.cs.j2eng/semconv/templates/registry/csharp_incubating/schema_version.cs.j2eng/build/BuildPipeline.cseng/semconv/templates/registry/csharp_stable/schema_url.cs.j2eng/semconv/templates/registry/csharp_incubating/weaver.yamleng/semconv/templates/registry/csharp_stable/weaver.yamleng/semconv/templates/registry/csharp_stable/attributes.cs.j2eng/semconv/templates/registry/csharp_qyl/attributes.cs.j2eng/semconv/templates/registry/csharp_incubating/attributes.cs.j2
📚 Learning: 2026-04-21T06:24:06.977Z
Learnt from: CR
Repo: Alexander-Nachtmann/qyl PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-21T06:24:06.977Z
Learning: Applies to **/*.{csproj,package.json} : Do not replace external dependencies: `Microsoft.Agents.AI`, `Microsoft.Agents.AI.Hosting`, `Microsoft.Extensions.AI`, `ModelContextProtocol` 1.1.0, `OpenTelemetry` SDK 1.15.0 + Semantic Conventions 1.40, `DuckDB.NET` 1.5.0, `Base UI` 1.3.0 + `lucide-react`, `xUnit v3` + `Microsoft.Testing.Platform`.
Applied to files:
eng/build/BuildPipeline.cscore/specs/emitters/qyl-semconv-lint/test/rules.test.tseng/semconv/templates/registry/csharp_stable/weaver.yamleng/semconv/templates/registry/csharp_stable/attributes.cs.j2
📚 Learning: 2026-04-21T00:49:29.212Z
Learnt from: CR
Repo: Alexander-Nachtmann/qyl PR: 0
File: src/qyl.mcp/CLAUDE.md:0-0
Timestamp: 2026-04-21T00:49:29.212Z
Learning: Applies to src/qyl.mcp/src/qyl.mcp.generators/**/*.cs : `src/qyl.mcp.generators/` must emit `QylToolManifest` with `ToolTypes[]`, `ToolDescriptors[]`, and `CreateTools()`
Applied to files:
eng/build/BuildPipeline.cseng/semconv/templates/registry/csharp_qyl/attributes.cs.j2
📚 Learning: 2026-04-21T06:24:06.977Z
Learnt from: CR
Repo: Alexander-Nachtmann/qyl PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-21T06:24:06.977Z
Learning: Applies to **/generators/**/*.cs : Use `IIncrementalGenerator` only. Enforce `ForAttributeWithMetadataName`, value-equatable models, raw strings over `SyntaxFactory`. Never store `ISymbol` in models.
Applied to files:
eng/build/BuildPipeline.cseng/semconv/templates/registry/csharp_stable/weaver.yamleng/semconv/templates/registry/csharp_stable/attributes.cs.j2eng/semconv/templates/registry/csharp_qyl/attributes.cs.j2eng/semconv/templates/registry/csharp_incubating/attributes.cs.j2
📚 Learning: 2026-04-21T06:24:06.977Z
Learnt from: CR
Repo: Alexander-Nachtmann/qyl PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-21T06:24:06.977Z
Learning: Use `nuke Generate` to regenerate TypeSpec + Roslyn outputs. It is idempotent—run it any time. It regenerates `.g.cs`, `openapi.yaml`, and DuckDB DDL.
Applied to files:
eng/build/BuildPipeline.cs
📚 Learning: 2026-04-21T06:24:06.978Z
Learnt from: CR
Repo: Alexander-Nachtmann/qyl PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-21T06:24:06.978Z
Learning: Dependency direction is one-way: `qyl.contracts` at the bottom (BCL-only), generators in their own projects (no runtime deps), runtime projects depend on contracts + generator outputs.
Applied to files:
eng/build/BuildPipeline.cs
📚 Learning: 2026-04-21T06:24:06.977Z
Learnt from: CR
Repo: Alexander-Nachtmann/qyl PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-21T06:24:06.977Z
Learning: Applies to **/tests/**{Generator,Generator.Tests}/**/*.cs : Test generators via `ANcpLua.Roslyn.Utilities` test infrastructure.
Applied to files:
eng/build/BuildPipeline.cs
📚 Learning: 2026-04-21T06:24:06.977Z
Learnt from: CR
Repo: Alexander-Nachtmann/qyl PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-21T06:24:06.977Z
Learning: Applies to **/*.{g.cs,g.tsp,g.sql,g.ts,g.yaml} : Never hand-edit `*.g.cs`, `*.g.tsp`, `*.g.sql`, `*.g.ts`, or `core/openapi/openapi.yaml`. Fix the generator input (TypeSpec model, attribute, routing table) instead.
Applied to files:
eng/semconv/templates/registry/csharp_incubating/weaver.yamleng/semconv/templates/registry/csharp_stable/weaver.yaml
📚 Learning: 2026-04-21T06:24:06.977Z
Learnt from: CR
Repo: Alexander-Nachtmann/qyl PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-21T06:24:06.977Z
Learning: Applies to **/qyl.mcp/Capabilities/Definitions/**/*.cs : `[QylCapabilityDefinition("id", QylSkillKind.X)]` on marker classes in `Capabilities/Definitions/` defines capability metadata.
Applied to files:
eng/semconv/qyl/model/capability.yaml
📚 Learning: 2026-04-21T06:24:06.977Z
Learnt from: CR
Repo: Alexander-Nachtmann/qyl PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-21T06:24:06.977Z
Learning: Applies to **/qyl.mcp/**/Tools/**/*.cs : `[QylCapability("id", Starting|FollowUp)]` on tool methods links tools to capabilities at compile time.
Applied to files:
eng/semconv/qyl/model/capability.yaml
📚 Learning: 2026-04-21T06:24:06.977Z
Learnt from: CR
Repo: Alexander-Nachtmann/qyl PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-21T06:24:06.977Z
Learning: Applies to **/*.cs : Never hand-register a tool. Instead, add `[QylSkill]` + `[QylCapability]` attributes and let the generator handle DI registration, MCP tool registration, and capability catalogs.
Applied to files:
eng/semconv/templates/registry/csharp_qyl/attributes.cs.j2
🪛 GitHub Actions: CI
eng/build/BuildPipeline.cs
[error] 91-91: CA1861: Prefer 'static readonly' fields over constant array arguments if the called method is called repeatedly and is not mutating the passed array (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1861)
🪛 GitHub Check: Backend (.NET)
eng/build/BuildPipeline.cs
[failure] 91-91:
Prefer 'static readonly' fields over constant array arguments if the called method is called repeatedly and is not mutating the passed array (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1861)
[failure] 91-91:
Prefer 'static readonly' fields over constant array arguments if the called method is called repeatedly and is not mutating the passed array (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1861)
🪛 GitHub Check: Schema Drift (TypeSpec → Generated)
eng/build/BuildPipeline.cs
[failure] 91-91:
Prefer 'static readonly' fields over constant array arguments if the called method is called repeatedly and is not mutating the passed array (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1861)
[failure] 91-91:
Prefer 'static readonly' fields over constant array arguments if the called method is called repeatedly and is not mutating the passed array (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1861)
🔇 Additional comments (5)
eng/semconv/qyl/model/storage.yaml (1)
1-23: LGTM.Schema structure is valid, naming follows OTel conventions, and the attributes are confirmed in use by
DuckDbStore.cs.eng/semconv/templates/registry/csharp_stable/weaver.yaml (1)
1-51: LGTM.Schema version 1.40.0 aligns with target OTel Semantic Conventions. Template configuration is correct. The commit hash hardcoding is acceptable given the stated refresh deferral.
eng/semconv/qyl/model/issue.yaml (1)
1-47: LGTM.Schema structure valid with consistent stability markers across all enum members.
eng/semconv/qyl/model/fix_run.yaml (1)
1-47: LGTM.Schema valid. Stability markers consistent.
eng/semconv/templates/registry/csharp_incubating/attributes.cs.j2 (1)
40-42: 🛠️ Refactor suggestion | 🟠 MajorSame member deprecation inconsistency.
Apply the structured reason-based handling to match attribute-level deprecation logic. See prior comment on stable template.
⛔ Skipped due to learnings
Learnt from: CR Repo: Alexander-Nachtmann/qyl PR: 0 File: AGENTS.md:0-0 Timestamp: 2026-04-21T06:24:06.977Z Learning: Applies to **/generators/**/*.cs : Use `IIncrementalGenerator` only. Enforce `ForAttributeWithMetadataName`, value-equatable models, raw strings over `SyntaxFactory`. Never store `ISymbol` in models.Learnt from: CR Repo: Alexander-Nachtmann/qyl PR: 0 File: AGENTS.md:0-0 Timestamp: 2026-04-21T06:24:06.977Z Learning: Applies to **/*.cs : C# 14 with preview features enabled. Use file-scoped namespaces, primary constructors, required init properties, pattern matching, switch expressions over if-else.Learnt from: CR Repo: Alexander-Nachtmann/qyl PR: 0 File: AGENTS.md:0-0 Timestamp: 2026-04-21T06:24:06.977Z Learning: Applies to **/*{Builder,Composition,Startup,Program}.cs : Resource attributes are required on every service with `AddService(serviceName, serviceVersion)` and `[service.instance.id]`, `[deployment.environment]` attributes.Learnt from: CR Repo: Alexander-Nachtmann/qyl PR: 0 File: AGENTS.md:0-0 Timestamp: 2026-04-21T06:24:06.977Z Learning: Applies to **/*.cs : No suppression: No `#pragma warning disable`, no `[SuppressMessage]`, no `<NoWarn>` (exception: upstream sample repos demonstrating experimental APIs).Learnt from: CR Repo: Alexander-Nachtmann/qyl PR: 0 File: AGENTS.md:0-0 Timestamp: 2026-04-21T06:24:06.977Z Learning: Applies to **/*{Chat,Agent,Client,Instrumentation,Telemetry}*.cs : Emit OTel GenAI semconv 1.40 with required attributes: `gen_ai.system`, `gen_ai.request.model`, `gen_ai.response.model`, `gen_ai.usage.input_tokens`, `gen_ai.usage.output_tokens`, `gen_ai.operation.name`, `gen_ai.tool.call.id`, `gen_ai.tool.name`, `gen_ai.agent.name`, `gen_ai.agent.id`.
| /** | ||
| * QYL-LINT-001 — attribute must live in the qyl registry namespace. | ||
| * | ||
| * The YAML attribute registry under eng/semconv/qyl/model/ is the source of | ||
| * truth for qyl-owned telemetry keys (regenerated by Weaver into the three | ||
| * runtime packages). Any `@qylAttr`-annotated key left inside the TypeSpec | ||
| * pipeline must not collide with an upstream OTel namespace. | ||
| */ | ||
| function checkUpstreamCollision(program: Program, records: readonly QylAttrRecord[]): void { |
There was a problem hiding this comment.
This no longer enforces the qyl. namespace.
After this change, @qylAttr("foo.bar", ...) passes as long as foo. is not in RESERVED_PREFIXES. That silently widens the contract from “qyl-owned registry keys only” to “any non-upstream namespace,” which contradicts the docblock here and the YAML registry ownership model. Restore the explicit qyl. prefix diagnostic instead of relying solely on upstream-collision.
Also applies to: 41-45
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@core/specs/emitters/qyl-semconv-lint/src/rules.ts` around lines 20 - 28, The
docblock says keys must be qyl-owned but the current
checkUpstreamCollision(program, records) logic no longer enforces a "qyl."
prefix and only checks RESERVED_PREFIXES; restore an explicit diagnostic that
requires every `@qylAttr` key string (from QylAttrRecord) to start with "qyl." and
emit a clear error when it does not, while keeping the existing
upstream-collision checks; update the checkUpstreamCollision function (and the
same logic that handles records around lines ~41-45) to first validate the
"qyl." prefix on the attribute name, then proceed to the RESERVED_PREFIXES
collision check so the rule enforces both ownership and upstream avoidance.
| var weaverArch = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) | ||
| ? (RuntimeInformation.ProcessArchitecture == Architecture.Arm64 | ||
| ? "aarch64-apple-darwin" : "x86_64-apple-darwin") | ||
| : "x86_64-unknown-linux-gnu"; | ||
| var weaverBin = (AbsolutePath)(RootDirectory / ".tools" / "weaver" / $"weaver-{weaverArch}" / "weaver"); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify platform matrix consistency between BuildPipeline and bootstrap script.
rg -n 'weaverArch|IsOSPlatform|ProcessArchitecture|x86_64-unknown-linux-gnu|apple-darwin' eng/build/BuildPipeline.cs -C3
rg -n 'case .*Darwin|Linux|Unsupported platform|WEAVER_ARCH' eng/semconv/bootstrap-weaver.sh -C3Repository: Alexander-Nachtmann/qyl
Length of output: 1850
Fix platform validation in weaver binary selection to match bootstrap script and fail fast on unsupported combinations.
The C# code (lines 59–63) silently defaults all non-macOS platforms to x86_64-unknown-linux-gnu, but bootstrap-weaver.sh (lines 44–50) explicitly rejects unsupported platform–architecture pairs. On Windows or Linux Arm64, the C# code selects the wrong weaver binary and fails with non-diagnostic errors downstream.
Bring the C# code into alignment with the shell script by explicitly validating OS and architecture, throwing NotSupportedException for unsupported combinations:
Suggested fix
- var weaverArch = RuntimeInformation.IsOSPlatform(OSPlatform.OSX)
- ? (RuntimeInformation.ProcessArchitecture == Architecture.Arm64
- ? "aarch64-apple-darwin" : "x86_64-apple-darwin")
- : "x86_64-unknown-linux-gnu";
+ var weaverArch = RuntimeInformation.IsOSPlatform(OSPlatform.OSX)
+ ? RuntimeInformation.ProcessArchitecture switch
+ {
+ Architecture.Arm64 => "aarch64-apple-darwin",
+ Architecture.X64 => "x86_64-apple-darwin",
+ _ => throw new NotSupportedException(
+ $"Unsupported macOS architecture: {RuntimeInformation.ProcessArchitecture}")
+ }
+ : RuntimeInformation.IsOSPlatform(OSPlatform.Linux)
+ ? RuntimeInformation.ProcessArchitecture switch
+ {
+ Architecture.X64 => "x86_64-unknown-linux-gnu",
+ _ => throw new NotSupportedException(
+ $"Unsupported Linux architecture: {RuntimeInformation.ProcessArchitecture}")
+ }
+ : throw new NotSupportedException(
+ $"Unsupported OS platform: {RuntimeInformation.OSDescription}");📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| var weaverArch = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) | |
| ? (RuntimeInformation.ProcessArchitecture == Architecture.Arm64 | |
| ? "aarch64-apple-darwin" : "x86_64-apple-darwin") | |
| : "x86_64-unknown-linux-gnu"; | |
| var weaverBin = (AbsolutePath)(RootDirectory / ".tools" / "weaver" / $"weaver-{weaverArch}" / "weaver"); | |
| var weaverArch = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) | |
| ? RuntimeInformation.ProcessArchitecture switch | |
| { | |
| Architecture.Arm64 => "aarch64-apple-darwin", | |
| Architecture.X64 => "x86_64-apple-darwin", | |
| _ => throw new NotSupportedException( | |
| $"Unsupported macOS architecture: {RuntimeInformation.ProcessArchitecture}") | |
| } | |
| : RuntimeInformation.IsOSPlatform(OSPlatform.Linux) | |
| ? RuntimeInformation.ProcessArchitecture switch | |
| { | |
| Architecture.X64 => "x86_64-unknown-linux-gnu", | |
| _ => throw new NotSupportedException( | |
| $"Unsupported Linux architecture: {RuntimeInformation.ProcessArchitecture}") | |
| } | |
| : throw new NotSupportedException( | |
| $"Unsupported OS platform: {RuntimeInformation.OSDescription}"); | |
| var weaverBin = (AbsolutePath)(RootDirectory / ".tools" / "weaver" / $"weaver-{weaverArch}" / "weaver"); |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@eng/build/BuildPipeline.cs` around lines 59 - 63, The platform selection for
the weaver binary in BuildPipeline.cs incorrectly defaults all non-macOS to
"x86_64-unknown-linux-gnu"; update the logic around weaverArch/weaverBin to
validate OS and Architecture explicitly (using RuntimeInformation.IsOSPlatform
and RuntimeInformation.ProcessArchitecture) and throw a NotSupportedException
for unsupported OS/architecture combinations (e.g., Windows or Linux Arm64) to
mirror bootstrap-weaver.sh behavior so the BuildPipeline fails fast with a clear
error instead of selecting the wrong binary.
| var schemaSource = RootDirectory / ".tools" / "semconv-upstream" / "schemas" / "1.40.0"; | ||
| if (((string)schemaSource).Length > 0 && File.Exists(schemaSource)) | ||
| { | ||
| foreach (var pkg in new[] { "Qyl.OpenTelemetry.SemanticConventions", "Qyl.OpenTelemetry.SemanticConventions.Incubating" }) | ||
| { | ||
| var schemasDir = RootDirectory / "packages" / pkg / "schemas"; | ||
| Directory.CreateDirectory(schemasDir); | ||
| File.Copy(schemaSource, schemasDir / "1.40.0.yaml", overwrite: true); | ||
| } | ||
| } |
There was a problem hiding this comment.
Do not allow schema embedding to fail silently.
Line 88-Line 97 no-ops when the upstream schema file is missing, which can produce packages without the embedded schema while still reporting success. This should be a hard failure.
Suggested fix
var schemaSource = RootDirectory / ".tools" / "semconv-upstream" / "schemas" / "1.40.0";
- if (((string)schemaSource).Length > 0 && File.Exists(schemaSource))
+ if (!File.Exists(schemaSource))
+ {
+ throw new FileNotFoundException($"Schema source not found: {schemaSource}");
+ }
+ foreach (var pkg in new[] { "Qyl.OpenTelemetry.SemanticConventions", "Qyl.OpenTelemetry.SemanticConventions.Incubating" })
{
- foreach (var pkg in new[] { "Qyl.OpenTelemetry.SemanticConventions", "Qyl.OpenTelemetry.SemanticConventions.Incubating" })
- {
- var schemasDir = RootDirectory / "packages" / pkg / "schemas";
- Directory.CreateDirectory(schemasDir);
- File.Copy(schemaSource, schemasDir / "1.40.0.yaml", overwrite: true);
- }
+ var schemasDir = RootDirectory / "packages" / pkg / "schemas";
+ Directory.CreateDirectory(schemasDir);
+ File.Copy(schemaSource, schemasDir / "1.40.0.yaml", overwrite: true);
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| var schemaSource = RootDirectory / ".tools" / "semconv-upstream" / "schemas" / "1.40.0"; | |
| if (((string)schemaSource).Length > 0 && File.Exists(schemaSource)) | |
| { | |
| foreach (var pkg in new[] { "Qyl.OpenTelemetry.SemanticConventions", "Qyl.OpenTelemetry.SemanticConventions.Incubating" }) | |
| { | |
| var schemasDir = RootDirectory / "packages" / pkg / "schemas"; | |
| Directory.CreateDirectory(schemasDir); | |
| File.Copy(schemaSource, schemasDir / "1.40.0.yaml", overwrite: true); | |
| } | |
| } | |
| var schemaSource = RootDirectory / ".tools" / "semconv-upstream" / "schemas" / "1.40.0"; | |
| if (!File.Exists(schemaSource)) | |
| { | |
| throw new FileNotFoundException($"Schema source not found: {schemaSource}"); | |
| } | |
| foreach (var pkg in new[] { "Qyl.OpenTelemetry.SemanticConventions", "Qyl.OpenTelemetry.SemanticConventions.Incubating" }) | |
| { | |
| var schemasDir = RootDirectory / "packages" / pkg / "schemas"; | |
| Directory.CreateDirectory(schemasDir); | |
| File.Copy(schemaSource, schemasDir / "1.40.0.yaml", overwrite: true); | |
| } |
🧰 Tools
🪛 GitHub Actions: CI
[error] 91-91: CA1861: Prefer 'static readonly' fields over constant array arguments if the called method is called repeatedly and is not mutating the passed array (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1861)
🪛 GitHub Check: Backend (.NET)
[failure] 91-91:
Prefer 'static readonly' fields over constant array arguments if the called method is called repeatedly and is not mutating the passed array (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1861)
[failure] 91-91:
Prefer 'static readonly' fields over constant array arguments if the called method is called repeatedly and is not mutating the passed array (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1861)
🪛 GitHub Check: Schema Drift (TypeSpec → Generated)
[failure] 91-91:
Prefer 'static readonly' fields over constant array arguments if the called method is called repeatedly and is not mutating the passed array (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1861)
[failure] 91-91:
Prefer 'static readonly' fields over constant array arguments if the called method is called repeatedly and is not mutating the passed array (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1861)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@eng/build/BuildPipeline.cs` around lines 88 - 97, The current embedding block
around schemaSource in BuildPipeline.cs silently skips embedding when the
upstream schema file is missing; change it to fail fast by validating that
schemaSource exists and throwing a clear exception (e.g., FileNotFoundException
or InvalidOperationException) with the schemaSource path when
File.Exists(schemaSource) is false before attempting the foreach/Copy loop;
locate the schemaSource initialization and the conditional that currently checks
((string)schemaSource).Length > 0 && File.Exists(schemaSource) and replace the
silent no-op with an explicit throw so packages cannot be produced without the
embedded schema.
| var schemaSource = RootDirectory / ".tools" / "semconv-upstream" / "schemas" / "1.40.0"; | ||
| if (((string)schemaSource).Length > 0 && File.Exists(schemaSource)) | ||
| { | ||
| foreach (var pkg in new[] { "Qyl.OpenTelemetry.SemanticConventions", "Qyl.OpenTelemetry.SemanticConventions.Incubating" }) |
There was a problem hiding this comment.
Resolve CI-breaking CA1861 at the package loop.
Line 91 allocates a new constant array in the loop header and currently fails CI (CA1861). Replace it with explicit calls or a cached static source to remove repeated allocation and clear the analyzer gate.
Suggested fix (explicit calls, no array allocation)
- foreach (var pkg in new[] { "Qyl.OpenTelemetry.SemanticConventions", "Qyl.OpenTelemetry.SemanticConventions.Incubating" })
- {
- var schemasDir = RootDirectory / "packages" / pkg / "schemas";
- Directory.CreateDirectory(schemasDir);
- File.Copy(schemaSource, schemasDir / "1.40.0.yaml", overwrite: true);
- }
+ static void CopySchema(AbsolutePath root, string packageName, AbsolutePath source)
+ {
+ var schemasDir = root / "packages" / packageName / "schemas";
+ Directory.CreateDirectory(schemasDir);
+ File.Copy(source, schemasDir / "1.40.0.yaml", overwrite: true);
+ }
+
+ CopySchema(RootDirectory, "Qyl.OpenTelemetry.SemanticConventions", schemaSource);
+ CopySchema(RootDirectory, "Qyl.OpenTelemetry.SemanticConventions.Incubating", schemaSource);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| foreach (var pkg in new[] { "Qyl.OpenTelemetry.SemanticConventions", "Qyl.OpenTelemetry.SemanticConventions.Incubating" }) | |
| static void CopySchema(AbsolutePath root, string packageName, AbsolutePath source) | |
| { | |
| var schemasDir = root / "packages" / packageName / "schemas"; | |
| Directory.CreateDirectory(schemasDir); | |
| File.Copy(source, schemasDir / "1.40.0.yaml", overwrite: true); | |
| } | |
| CopySchema(RootDirectory, "Qyl.OpenTelemetry.SemanticConventions", schemaSource); | |
| CopySchema(RootDirectory, "Qyl.OpenTelemetry.SemanticConventions.Incubating", schemaSource); |
🧰 Tools
🪛 GitHub Actions: CI
[error] 91-91: CA1861: Prefer 'static readonly' fields over constant array arguments if the called method is called repeatedly and is not mutating the passed array (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1861)
🪛 GitHub Check: Backend (.NET)
[failure] 91-91:
Prefer 'static readonly' fields over constant array arguments if the called method is called repeatedly and is not mutating the passed array (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1861)
[failure] 91-91:
Prefer 'static readonly' fields over constant array arguments if the called method is called repeatedly and is not mutating the passed array (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1861)
🪛 GitHub Check: Schema Drift (TypeSpec → Generated)
[failure] 91-91:
Prefer 'static readonly' fields over constant array arguments if the called method is called repeatedly and is not mutating the passed array (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1861)
[failure] 91-91:
Prefer 'static readonly' fields over constant array arguments if the called method is called repeatedly and is not mutating the passed array (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1861)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@eng/build/BuildPipeline.cs` at line 91, The foreach currently allocates a new
array in the loop header (foreach (var pkg in new[] {
"Qyl.OpenTelemetry.SemanticConventions",
"Qyl.OpenTelemetry.SemanticConventions.Incubating" })) which triggers CA1861;
fix it by replacing the inline array with a reuseable source such as a private
static readonly string[] field (e.g., private static readonly string[]
SemanticConventionPkgs = { "Qyl.OpenTelemetry.SemanticConventions",
"Qyl.OpenTelemetry.SemanticConventions.Incubating" }) and iterate over
SemanticConventionPkgs in the foreach, or alternatively call the operation
explicitly twice for each package name to avoid any array allocation; reference
the foreach block and the package names when applying the change.
| brief: > | ||
| First 8 characters of the API key hash (sha256[:8]). | ||
| Never log the full key. Used for audit trails only. | ||
| examples: ['a1b2c3d4'] |
There was a problem hiding this comment.
Use a longer fingerprint than sha256[:8] for audit correlation.
sha256[:8] is only 32 bits. Once the number of issued keys grows, collisions become realistic and the audit trail can attribute activity to the wrong credential. Standardize this field on a longer fingerprint (at least 64 bits, preferably 128 bits) or a stable server-side key id instead.
Proposed spec change
- First 8 characters of the API key hash (sha256[:8]).
+ First 32 characters of the API key hash (sha256[:32]).
Never log the full key. Used for audit trails only.
- examples: ['a1b2c3d4']
+ examples: ['a1b2c3d4e5f60718b9c0d1e2f3a4b5c6']📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| brief: > | |
| First 8 characters of the API key hash (sha256[:8]). | |
| Never log the full key. Used for audit trails only. | |
| examples: ['a1b2c3d4'] | |
| brief: > | |
| First 32 characters of the API key hash (sha256[:32]). | |
| Never log the full key. Used for audit trails only. | |
| examples: ['a1b2c3d4e5f60718b9c0d1e2f3a4b5c6'] |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@eng/semconv/qyl/model/api_key.yaml` around lines 10 - 13, The audit
fingerprint for API keys in eng/semconv/qyl/model/api_key.yaml is too short
(sha256[:8]); update the spec text and example to use a longer,
collision-resistant fingerprint (at minimum sha256[:16] for 64 bits, preferably
sha256[:32] for 128 bits) or switch to a stable server-side key id; specifically
change the brief from "First 8 characters of the API key hash (sha256[:8])" to
indicate the chosen longer slice (e.g., "First 16 characters of the API key hash
(sha256[:16])" or "First 32 characters (sha256[:32])") and update the examples
array (e.g., from 'a1b2c3d4' to a matching-length hex sample) and any consumers
that parse or generate this fingerprint (look for references to the api_key
fingerprint field/name in validation/parsing code).
| - id: follow_up | ||
| value: 'FollowUp' | ||
| brief: 'Capability that follows another in a workflow' |
There was a problem hiding this comment.
Missing stability: experimental on follow_up member.
The starting member (line 20) has stability: experimental, but follow_up does not. This inconsistency may cause generation issues depending on how the template filters members.
- id: follow_up
value: 'FollowUp'
brief: 'Capability that follows another in a workflow'
+ stability: experimental🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@eng/semconv/qyl/model/capability.yaml` around lines 21 - 23, The member with
id 'follow_up' is missing the stability tag; add "stability: experimental" to
the 'follow_up' mapping (same level as id/value/brief) so it matches the
'starting' member; ensure YAML indentation aligns with the other members (i.e.,
add stability: experimental under the follow_up entry alongside id/value/brief).
| {% if member.deprecated %} | ||
| [global::System.Obsolete({{ member.deprecated | string | tojson }}, false)] | ||
| {% endif %} | ||
| public const string {{ member.id | pascal_case }} = {{ member.value | string | tojson }}; | ||
| {% endfor %} |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Inconsistent deprecation handling for members vs attributes.
Attribute-level deprecation (lines 20-27) has structured reason-based logic (renamed, obsoleted, fallback to note), but member-level deprecation (line 38) just stringifies the entire member.deprecated object. This creates inconsistent [Obsolete] messages.
Compare with the attribute handling above it—member deprecation should follow the same pattern for uniform output.
{% for member in attr.type.members | sort(attribute="value") %}
/// <summary>{{ member.brief | replace('&', '&') | replace('<', '<') | replace('>', '>') | replace('\n', ' ') | trim }}.</summary>
{% if member.deprecated %}
+{% if member.deprecated.reason == "renamed" %}
+ [global::System.Obsolete("Replaced by {{ member.deprecated.renamed_to }}.", false)]
+{% elif member.deprecated.reason == "obsoleted" %}
+ [global::System.Obsolete("Removed, no replacement.", false)]
+{% else %}
+ [global::System.Obsolete({{ member.deprecated.note | replace('\n', ' ') | trim | tojson }}, false)]
+{% endif %}
- [global::System.Obsolete({{ member.deprecated | string | tojson }}, false)]
{% endif %}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@eng/semconv/templates/registry/csharp_qyl/attributes.cs.j2` around lines 37 -
41, The member-level Obsolete emission currently stringifies member.deprecated;
change it to mirror the attribute-level deprecation logic: inspect
member.deprecated for keys (renamed, obsoleted, note) and build a structured
message (e.g., "Renamed to <newName>" when renamed, "Obsoleted: <reason>" when
obsoleted, fallback to note) then pass that message into the
[global::System.Obsolete(..., false)] call for the constant whose identifier is
member.id and value is member.value so member-level deprecation messages match
attribute-level formatting.
| params: | ||
| schema_version: "1.0.0" | ||
| package_namespace: "Qyl.SemanticConventions" |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Move schema_version out of the template config and into a single build-owned source.
This literal becomes another manual source of truth. Once eng/semconv/qyl/model/**/*.yaml changes again, SchemaVersion.Current can silently lie unless someone remembers to bump this file in lockstep. Feed schema_version from the NUKE pipeline or a shared version prop, and fail generation when the model changes without a version bump. As per coding guidelines, eng/**: Build and deployment infrastructure. Review for: correct MSBuild property usage, Nuke build target dependencies, Docker multi-stage build efficiency, and CI/CD pipeline correctness. Flag hardcoded paths, secrets, or platform-specific assumptions.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@eng/semconv/templates/registry/csharp_qyl/weaver.yaml` around lines 9 - 11,
Remove the hardcoded params.schema_version from the template and instead read
the canonical schema version from a single build-owned source (e.g., a NUKE
variable or MSBuild property passed into generation as a parameter), update
generation to inject that value where schema_version was used, and add a
generation-time check that compares the model checksum (or timestamps) against
SchemaVersion.Current and fails the build if the model changed without bumping
that property so generation cannot silently use an out-of-date
SchemaVersion.Current.
| {%- set stable_attrs = ctx.attributes | selectattr("stability", "equalto", "stable") | list -%} | ||
| {%- if stable_attrs | length > 0 -%} | ||
| // <auto-generated/> | ||
| // Generated by qyl's Weaver pipeline from open-telemetry/semantic-conventions@{{ params.semconv_commit }} | ||
| // Schema: {{ params.schema_url }} | ||
| // Licensed under Apache-2.0 (inherited from OpenTelemetry upstream) | ||
| // </auto-generated> | ||
|
|
||
| // Copyright (c) 2025-2026 ancplua | ||
|
|
||
| namespace {{ params.package_namespace }}.Attributes.{{ ctx.root_namespace | pascal_case }}; | ||
|
|
||
| /// <summary>{{ ctx.display_name | default(ctx.root_namespace | pascal_case + " Attributes") }}.</summary> | ||
| public static class {{ ctx.root_namespace | pascal_case }}Attributes | ||
| { | ||
| {% for attr in stable_attrs | sort(attribute="name") %} | ||
| {%- set _stripped = attr.name[(ctx.root_namespace | length + 1):] -%} | ||
| {% set local_name = (_stripped if _stripped else attr.name) | replace(".", "_") | pascal_case %} | ||
| /// <summary>{{ attr.brief | replace('&', '&') | replace('<', '<') | replace('>', '>') | replace('\n', ' ') | trim }}.</summary> | ||
| {% if attr.note is defined and attr.note %} | ||
| /// <remarks>{{ attr.note | replace('&', '&') | replace('<', '<') | replace('>', '>') | replace('\n', ' ') | trim }}</remarks> | ||
| {% endif %} | ||
| {% if attr.deprecated %} | ||
| {% if attr.deprecated.reason == "renamed" %} | ||
| [global::System.Obsolete("Replaced by {{ attr.deprecated.renamed_to }}.", false)] | ||
| {% elif attr.deprecated.reason == "obsoleted" %} | ||
| [global::System.Obsolete("Removed, no replacement.", false)] | ||
| {% else %} | ||
| [global::System.Obsolete({{ attr.deprecated.note | replace('\n', ' ') | trim | tojson }}, false)] | ||
| {% endif %} | ||
| {% endif %} | ||
| public const string {{ local_name }} = "{{ attr.name }}"; | ||
| {% if attr.type is mapping and attr.type.members is defined %} | ||
|
|
||
| /// <summary>Values for <see cref="{{ local_name }}"/>.</summary> | ||
| public static class {{ local_name }}Values | ||
| { | ||
| {% for member in attr.type.members | sort(attribute="value") %} | ||
| /// <summary>{{ member.brief | replace('&', '&') | replace('<', '<') | replace('>', '>') | replace('\n', ' ') | trim }}.</summary> | ||
| {% if member.deprecated %} | ||
| [global::System.Obsolete({{ member.deprecated | string | tojson }}, false)] | ||
| {% endif %} | ||
| public const string {{ member.id | pascal_case }} = {{ member.value | string | tojson }}; | ||
| {% endfor %} | ||
| } | ||
| {% endif %} | ||
|
|
||
| {% endfor %} | ||
| } | ||
| {%- endif -%} |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Duplication across three templates.
The stable, incubating, and QYL templates share ~90% identical Jinja logic (XML escaping, deprecation handling, member generation). Only the stability filter differs. Consider extracting shared logic into a Jinja macro file to reduce maintenance burden and prevent drift between the three variants.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@eng/semconv/templates/registry/csharp_stable/attributes.cs.j2` around lines 1
- 50, The template duplicates nearly all Jinja logic; refactor by extracting the
shared rendering into a reusable macro file (e.g., create a macros jinja file
and import it) so the three templates (stable/incubating/qyl) only differ by the
stability filter. Move the XML-escaping/summary generation, deprecation handling
(the Obsolete branches), member loop that generates "{{ local_name }}Values" and
member constants, and the local_name/_stripped logic into a macro (accepting the
attribute list or a stability argument), then have attributes.cs.j2 call that
macro with stable_attrs (or the appropriate filtered list) instead of
duplicating the block that generates public const string {{ local_name }} and
the nested {{ local_name }}Values class.
| {% if member.deprecated %} | ||
| [global::System.Obsolete({{ member.deprecated | string | tojson }}, false)] | ||
| {% endif %} |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Same member deprecation inconsistency as other templates.
Line 41 stringifies member.deprecated directly instead of using the structured reason-based logic applied to attributes (lines 23-30). This produces different [Obsolete] message formats for attributes vs their enum members.
{% if member.deprecated %}
- [global::System.Obsolete({{ member.deprecated | string | tojson }}, false)]
+{% if member.deprecated.reason == "renamed" %}
+ [global::System.Obsolete("Replaced by {{ member.deprecated.renamed_to }}.", false)]
+{% elif member.deprecated.reason == "obsoleted" %}
+ [global::System.Obsolete("Removed, no replacement.", false)]
+{% else %}
+ [global::System.Obsolete({{ member.deprecated.note | replace('\n', ' ') | trim | tojson }}, false)]
+{% endif %}
{% endif %}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| {% if member.deprecated %} | |
| [global::System.Obsolete({{ member.deprecated | string | tojson }}, false)] | |
| {% endif %} | |
| {% if member.deprecated %} | |
| {% if member.deprecated.reason == "renamed" %} | |
| [global::System.Obsolete("Replaced by {{ member.deprecated.renamed_to }}.", false)] | |
| {% elif member.deprecated.reason == "obsoleted" %} | |
| [global::System.Obsolete("Removed, no replacement.", false)] | |
| {% else %} | |
| [global::System.Obsolete({{ member.deprecated.note | replace('\n', ' ') | trim | tojson }}, false)] | |
| {% endif %} | |
| {% endif %} |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@eng/semconv/templates/registry/csharp_stable/attributes.cs.j2` around lines
40 - 42, The template emits inconsistent Obsolete messages by stringifying
member.deprecated in attributes.cs.j2; update the conditional that generates the
[global::System.Obsolete(...)] for enum members to use the same structured
reason-based logic used earlier for attributes (the logic around lines 23-30)
instead of directly stringifying member.deprecated—i.e., detect whether a
deprecation reason exists and emit either Obsolete("reason", false) or
Obsolete(false) accordingly so enum member deprecation messages match attribute
deprecation messages.
…3c1f8d # Conflicts: # qyl.slnx
There was a problem hiding this comment.
♻️ Duplicate comments (2)
eng/build/BuildPipeline.cs (2)
57-64:⚠️ Potential issue | 🟠 MajorFail fast on unsupported Weaver platforms.
bootstrap-weaver.shonly supports macOS arm64/x64 and Linux x64, but this fallback still maps every non-macOS build tox86_64-unknown-linux-gnu. On Windows or Linux Arm64,GenerateSemconvwill select the wrong binary and fail later with a misleading process error instead of a clearNotSupportedException.Suggested fix
- var weaverArch = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) - ? (RuntimeInformation.ProcessArchitecture == Architecture.Arm64 - ? "aarch64-apple-darwin" : "x86_64-apple-darwin") - : "x86_64-unknown-linux-gnu"; + var weaverArch = + RuntimeInformation.IsOSPlatform(OSPlatform.OSX) + ? RuntimeInformation.ProcessArchitecture switch + { + Architecture.Arm64 => "aarch64-apple-darwin", + Architecture.X64 => "x86_64-apple-darwin", + _ => throw new NotSupportedException( + $"Unsupported macOS architecture: {RuntimeInformation.ProcessArchitecture}") + } + : RuntimeInformation.IsOSPlatform(OSPlatform.Linux) + ? RuntimeInformation.ProcessArchitecture switch + { + Architecture.X64 => "x86_64-unknown-linux-gnu", + _ => throw new NotSupportedException( + $"Unsupported Linux architecture: {RuntimeInformation.ProcessArchitecture}") + } + : throw new NotSupportedException( + $"Unsupported OS platform: {RuntimeInformation.OSDescription}");As per coding guidelines,
eng/**: Build and deployment infrastructure. Review for: correct MSBuild property usage, Nuke build target dependencies, Docker multi-stage build efficiency, and CI/CD pipeline correctness. Flag hardcoded paths, secrets, or platform-specific assumptions.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@eng/build/BuildPipeline.cs` around lines 57 - 64, The current platform mapping sets every non-macOS OS to "x86_64-unknown-linux-gnu" causing wrong binary selection (weaverArch/weaverBin) on unsupported platforms; update the logic in the block that computes weaverArch to explicitly handle supported combos (macOS x64/arm64 and Linux x64) and throw a NotSupportedException (or equivalent) for any other OS/Architecture (e.g., Windows, Linux Arm64) so GenerateSemconv fails fast with a clear error rather than selecting a wrong binary; ensure you reference the same variables weaverArch and weaverBin so downstream code uses the validated value.
88-99:⚠️ Potential issue | 🟠 MajorDo not silently ship packages without the embedded schema.
If
.tools/semconv-upstream/schemas/1.40.0is missing, this block becomes a successful no-op. That turns a bad generator environment into incomplete NuGet packages instead of a deterministic build failure.Suggested fix
var schemaSource = RootDirectory / ".tools" / "semconv-upstream" / "schemas" / "1.40.0"; - if (((string)schemaSource).Length > 0 && File.Exists(schemaSource)) + if (!File.Exists(schemaSource)) { - ReadOnlySpan<string> otelPackages = ["Qyl.OpenTelemetry.SemanticConventions", "Qyl.OpenTelemetry.SemanticConventions.Incubating"]; - foreach (var pkg in otelPackages) - { - var schemasDir = RootDirectory / "packages" / pkg / "schemas"; - Directory.CreateDirectory(schemasDir); - File.Copy(schemaSource, schemasDir / "1.40.0.yaml", overwrite: true); - } + throw new FileNotFoundException($"Schema source not found: {schemaSource}"); } + + ReadOnlySpan<string> otelPackages = ["Qyl.OpenTelemetry.SemanticConventions", "Qyl.OpenTelemetry.SemanticConventions.Incubating"]; + foreach (var pkg in otelPackages) + { + var schemasDir = RootDirectory / "packages" / pkg / "schemas"; + Directory.CreateDirectory(schemasDir); + File.Copy(schemaSource, schemasDir / "1.40.0.yaml", overwrite: true); + }As per coding guidelines,
eng/**: Build and deployment infrastructure. Review for: correct MSBuild property usage, Nuke build target dependencies, Docker multi-stage build efficiency, and CI/CD pipeline correctness. Flag hardcoded paths, secrets, or platform-specific assumptions.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@eng/build/BuildPipeline.cs` around lines 88 - 99, The current block around schemaSource and otelPackages can silently no-op when the upstream schema is missing; change it to fail the build instead of continuing quietly: check File.Exists(schemaSource) (or Directory.Exists if schemaSource should be a directory) and if the schema file is not present throw a clear exception (e.g., InvalidOperationException with a message referencing schemaSource and the required version) before iterating otelPackages; keep the existing logic that creates schemasDir and copies the file (refer to variables schemaSource, otelPackages, RootDirectory and the enclosing BuildPipeline code) so missing upstream schemas produce a deterministic build failure.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@eng/build/BuildPipeline.cs`:
- Around line 57-64: The current platform mapping sets every non-macOS OS to
"x86_64-unknown-linux-gnu" causing wrong binary selection (weaverArch/weaverBin)
on unsupported platforms; update the logic in the block that computes weaverArch
to explicitly handle supported combos (macOS x64/arm64 and Linux x64) and throw
a NotSupportedException (or equivalent) for any other OS/Architecture (e.g.,
Windows, Linux Arm64) so GenerateSemconv fails fast with a clear error rather
than selecting a wrong binary; ensure you reference the same variables
weaverArch and weaverBin so downstream code uses the validated value.
- Around line 88-99: The current block around schemaSource and otelPackages can
silently no-op when the upstream schema is missing; change it to fail the build
instead of continuing quietly: check File.Exists(schemaSource) (or
Directory.Exists if schemaSource should be a directory) and if the schema file
is not present throw a clear exception (e.g., InvalidOperationException with a
message referencing schemaSource and the required version) before iterating
otelPackages; keep the existing logic that creates schemasDir and copies the
file (refer to variables schemaSource, otelPackages, RootDirectory and the
enclosing BuildPipeline code) so missing upstream schemas produce a
deterministic build failure.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 9f1f7074-95ee-4105-8ffe-64094799136a
📒 Files selected for processing (1)
eng/build/BuildPipeline.cs
📜 Review details
🧰 Additional context used
📓 Path-based instructions (2)
**/*.cs
📄 CodeRabbit inference engine (AGENTS.md)
**/*.cs: For arbitrary non-chat methods/metrics, use attribute-based instrumentation ([Traced]/[Meter]/[Counter]/etc.) only where no builder surface exists.
New.csfiles must be UTF-8 with BOM encoding..editorconfigdeclarescharset = utf-8-bomunder[*.cs].
Use// Copyright (c) 2025-2026 ancpluacopyright header on top of.csfiles.
XML documentation is required on all public methods and classes in C# files.
Use theAsyncsuffix for any method returningTask/ValueTask, including test methods.
Declare private classes assealedunless intentionally subclassed.
Environment variables useUPPER_SNAKE_CASE(e.g.,QYL_AGENT_MAX_DEPTH,OTEL_EXPORTER_OTLP_ENDPOINT).
C# 14 with preview features enabled. Use file-scoped namespaces, primary constructors, required init properties, pattern matching, switch expressions over if-else.
No suppression: No#pragma warning disable, no[SuppressMessage], no<NoWarn>(exception: upstream sample repos demonstrating experimental APIs).
Never use runtime reflection as a control mechanism,dynamic/ExpandoObject, blocking async (.Result/.Wait()), or any analyzer besidesANcpLua.Analyzers.
Do not suppressnull !when the code can be rewritten to avoid the suppression.
Never hand-register a tool. Instead, add[QylSkill]+[QylCapability]attributes and let the generator handle DI registration, MCP tool registration, and capability catalogs.
No attribute-based agent tracing—[AgentTraced]was removed in the 2026-04 collapse. Use fluent middleware instead.
InvestigationLineage(AsyncLocal) enforces max depth (3), root spawn budget (10), cycle detection. Tools callInvestigationLineage.TryEnter()before starting investigations.
Environment overrides for bounded autonomy:QYL_AGENT_MAX_DEPTH,QYL_AGENT_MAX_SPAWNS.
ConstructLoomToolEnveloperesults via the non-generic companion —LoomToolEnvelope.Ok(data)/LoomToolEnvelope.Fail<T>(error). NEVER `LoomToolEnvelope....
Files:
eng/build/BuildPipeline.cs
eng/**
⚙️ CodeRabbit configuration file
Build and deployment infrastructure. Review for: correct MSBuild property usage, Nuke build target dependencies, Docker multi-stage build efficiency, and CI/CD pipeline correctness. Flag hardcoded paths, secrets, or platform-specific assumptions.
Files:
eng/build/BuildPipeline.cs
🧠 Learnings (13)
📓 Common learnings
Learnt from: CR
Repo: Alexander-Nachtmann/qyl PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-21T06:24:06.977Z
Learning: Applies to **/*.{csproj,package.json} : Do not replace external dependencies: `Microsoft.Agents.AI`, `Microsoft.Agents.AI.Hosting`, `Microsoft.Extensions.AI`, `ModelContextProtocol` 1.1.0, `OpenTelemetry` SDK 1.15.0 + Semantic Conventions 1.40, `DuckDB.NET` 1.5.0, `Base UI` 1.3.0 + `lucide-react`, `xUnit v3` + `Microsoft.Testing.Platform`.
Learnt from: CR
Repo: Alexander-Nachtmann/qyl PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-21T06:24:06.977Z
Learning: Applies to **/*{Chat,Agent,Client,Instrumentation,Telemetry}*.cs : Emit OTel GenAI semconv 1.40 with required attributes: `gen_ai.system`, `gen_ai.request.model`, `gen_ai.response.model`, `gen_ai.usage.input_tokens`, `gen_ai.usage.output_tokens`, `gen_ai.operation.name`, `gen_ai.tool.call.id`, `gen_ai.tool.name`, `gen_ai.agent.name`, `gen_ai.agent.id`.
Learnt from: CR
Repo: Alexander-Nachtmann/qyl PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-21T06:24:06.977Z
Learning: Applies to **/*{Builder,Composition,Startup,Program}.cs : Replace attribute-based agent telemetry (`[AgentTraced]` + generators) with MAF's fluent middleware pipeline: `.AsBuilder().UseOpenTelemetry("qyl.agent").Build()` at the composition root.
Learnt from: CR
Repo: Alexander-Nachtmann/qyl PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-21T06:24:06.977Z
Learning: Applies to src/qyl.contracts/**/*.cs : `Qyl.contracts` is at the bottom (BCL-only, no MAF, no OTel SDK). Do not let MAF types leak into `qyl.contracts`.
Learnt from: CR
Repo: Alexander-Nachtmann/qyl PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-22T13:16:07.510Z
Learning: Applies to **/*.generators/*.cs : Generator discipline: Use `IIncrementalGenerator` only, `ForAttributeWithMetadataName`, value-equatable models, and raw strings over `SyntaxFactory`. Never store `ISymbol` in models. Test generators via `ANcpLua.Roslyn.Utilities` test infrastructure.
Learnt from: CR
Repo: Alexander-Nachtmann/qyl PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-21T06:24:06.977Z
Learning: Applies to **/generators/**/*.cs : Use `IIncrementalGenerator` only. Enforce `ForAttributeWithMetadataName`, value-equatable models, raw strings over `SyntaxFactory`. Never store `ISymbol` in models.
📚 Learning: 2026-04-21T06:24:06.977Z
Learnt from: CR
Repo: Alexander-Nachtmann/qyl PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-21T06:24:06.977Z
Learning: Applies to **/*{Chat,Agent,Client,Instrumentation,Telemetry}*.cs : Emit OTel GenAI semconv 1.40 with required attributes: `gen_ai.system`, `gen_ai.request.model`, `gen_ai.response.model`, `gen_ai.usage.input_tokens`, `gen_ai.usage.output_tokens`, `gen_ai.operation.name`, `gen_ai.tool.call.id`, `gen_ai.tool.name`, `gen_ai.agent.name`, `gen_ai.agent.id`.
Applied to files:
eng/build/BuildPipeline.cs
📚 Learning: 2026-04-21T06:24:06.977Z
Learnt from: CR
Repo: Alexander-Nachtmann/qyl PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-21T06:24:06.977Z
Learning: Applies to **/*.{csproj,package.json} : Do not replace external dependencies: `Microsoft.Agents.AI`, `Microsoft.Agents.AI.Hosting`, `Microsoft.Extensions.AI`, `ModelContextProtocol` 1.1.0, `OpenTelemetry` SDK 1.15.0 + Semantic Conventions 1.40, `DuckDB.NET` 1.5.0, `Base UI` 1.3.0 + `lucide-react`, `xUnit v3` + `Microsoft.Testing.Platform`.
Applied to files:
eng/build/BuildPipeline.cs
📚 Learning: 2026-04-22T13:16:07.509Z
Learnt from: CR
Repo: Alexander-Nachtmann/qyl PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-22T13:16:07.509Z
Learning: Applies to **/*.g.{cs,tsp,sql,ts} : `nuke Generate` is idempotent and regenerates `.g.cs`, `openapi.yaml`, and DuckDB DDL. Never hand-edit generated files (`*.g.cs`, `*.g.tsp`, `*.g.sql`, `*.g.ts`, `core/openapi/openapi.yaml`). Fix the generator input instead.
Applied to files:
eng/build/BuildPipeline.cs
📚 Learning: 2026-04-21T06:24:06.977Z
Learnt from: CR
Repo: Alexander-Nachtmann/qyl PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-21T06:24:06.977Z
Learning: Applies to **/generators/**/*.cs : Use `IIncrementalGenerator` only. Enforce `ForAttributeWithMetadataName`, value-equatable models, raw strings over `SyntaxFactory`. Never store `ISymbol` in models.
Applied to files:
eng/build/BuildPipeline.cs
📚 Learning: 2026-04-22T13:16:07.510Z
Learnt from: CR
Repo: Alexander-Nachtmann/qyl PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-22T13:16:07.510Z
Learning: Applies to **/*.generators/*.cs : Generator discipline: Use `IIncrementalGenerator` only, `ForAttributeWithMetadataName`, value-equatable models, and raw strings over `SyntaxFactory`. Never store `ISymbol` in models. Test generators via `ANcpLua.Roslyn.Utilities` test infrastructure.
Applied to files:
eng/build/BuildPipeline.cs
📚 Learning: 2026-04-22T13:16:07.510Z
Learnt from: CR
Repo: Alexander-Nachtmann/qyl PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-22T13:16:07.510Z
Learning: Applies to **/*.cs : No suppression: Do not use `#pragma warning disable`, `[SuppressMessage]`, or `<NoWarn>`. Exception: upstream sample repos demonstrating experimental APIs. Use `WarningsAsErrors=CA1816;CA2012;CA2016` (or add more rules, never subtract).
Applied to files:
eng/build/BuildPipeline.cs
📚 Learning: 2026-04-22T13:16:32.373Z
Learnt from: CR
Repo: Alexander-Nachtmann/qyl PR: 0
File: services/qyl.mcp/CLAUDE.md:0-0
Timestamp: 2026-04-22T13:16:32.373Z
Learning: Applies to services/qyl.mcp/**/*.cs : `CreateTools(IServiceProvider, Func<Type, bool>)` emit must be preserved; two load-bearing consumers (`Tools/UseQylTools.cs` + `Tools/RcaTools.cs`) materialize `List<AIFunction>` for embedded-agent `UseFunctionInvocation` loops
Applied to files:
eng/build/BuildPipeline.cs
📚 Learning: 2026-04-21T06:24:06.977Z
Learnt from: CR
Repo: Alexander-Nachtmann/qyl PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-21T06:24:06.977Z
Learning: Applies to src/qyl.contracts/**/*.cs : `Qyl.contracts` is at the bottom (BCL-only, no MAF, no OTel SDK). Do not let MAF types leak into `qyl.contracts`.
Applied to files:
eng/build/BuildPipeline.cs
📚 Learning: 2026-04-21T06:24:06.977Z
Learnt from: CR
Repo: Alexander-Nachtmann/qyl PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-21T06:24:06.977Z
Learning: Use `nuke Generate` to regenerate TypeSpec + Roslyn outputs. It is idempotent—run it any time. It regenerates `.g.cs`, `openapi.yaml`, and DuckDB DDL.
Applied to files:
eng/build/BuildPipeline.cs
📚 Learning: 2026-04-22T13:16:32.373Z
Learnt from: CR
Repo: Alexander-Nachtmann/qyl PR: 0
File: services/qyl.mcp/CLAUDE.md:0-0
Timestamp: 2026-04-22T13:16:32.373Z
Learning: Applies to services/qyl.mcp/**/internal/qyl.mcp.generators/**/*.cs : Generator `internal/qyl.mcp.generators/` must emit `QylToolManifest` with `ToolTypes[]`, `ToolDescriptors[]`, `RegisterTools(...)`, `RegisterServices(...)`, and `CreateTools(...)`
Applied to files:
eng/build/BuildPipeline.cs
📚 Learning: 2026-04-21T06:24:06.978Z
Learnt from: CR
Repo: Alexander-Nachtmann/qyl PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-21T06:24:06.978Z
Learning: Dependency direction is one-way: `qyl.contracts` at the bottom (BCL-only), generators in their own projects (no runtime deps), runtime projects depend on contracts + generator outputs.
Applied to files:
eng/build/BuildPipeline.cs
📚 Learning: 2026-04-21T06:24:06.977Z
Learnt from: CR
Repo: Alexander-Nachtmann/qyl PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-21T06:24:06.977Z
Learning: Applies to **/tests/**{Generator,Generator.Tests}/**/*.cs : Test generators via `ANcpLua.Roslyn.Utilities` test infrastructure.
Applied to files:
eng/build/BuildPipeline.cs
Railway build failed with MSB9008 because the new semconv packages (shipped in #156/#157 — runtime cutover + analyzer) were ProjectReferenced from internal/qyl.instrumentation.csproj but the three service Dockerfiles never COPY'd them into the build context. Adds to each of services/{qyl.collector,qyl.mcp,qyl.loom}/Dockerfile: - packages/Qyl.SemanticConventions/ - packages/Qyl.OpenTelemetry.SemanticConventions/ - packages/Qyl.OpenTelemetry.SemanticConventions.Incubating/ - packages/Qyl.OpenTelemetry.SemanticConventions.Analyzers/ Both as csproj-only (layer-cached restore) and full-directory copies. Also wires Qyl.OpenTelemetry.SemanticConventions.Analyzers as an Analyzer ProjectReference into qyl.collector, qyl.mcp, qyl.loom, and qyl.instrumentation — the analyzer now fires QYLSC* diagnostics on any deprecated OTel tag-setter call site in those projects. qyl.loom picks up the three runtime semconv packages it was missing (needed for direct use of typed attribute constants). Housekeeping: drops a stray blank line in QylMcpServerRegistration.cs that was inside a using block. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
Ships three donation-ready NuGet packages for OTel semconv consumption and cuts the qyl runtime over to them end-to-end.
GenerateSemconvtarget — deterministic Weaver pipeline driven by embedded schemasPhase 7commit wires the gate; OSX platform fix included250 files, +11,805 / −1,194 LOC.
Scope
Target achieved: 100% — packages produce deterministically via
nuke GenerateSemconv, runtime compiles and runs on the typed constants, cutover verified by the orphan-scan CLI (shipped in PR #2) reporting 0 orphans.Missing to 100%: nothing blocking donation. Final semconv-1.40 refresh will happen naturally on the next upstream semconv release via Weaver regeneration.
Risk
5% — high confidence goal is met.
What's left to do or delete to reach 100%
Test plan
CLAUDE.md)nuke GenerateSemconvidempotent on a fresh clonedotnet build qyl.slnx -c Releasesucceeds🤖 Generated with Claude Code