Skip to content

Latest commit

 

History

History
171 lines (170 loc) · 48.2 KB

COPILOT_LEARNINGS.md

File metadata and controls

171 lines (170 loc) · 48.2 KB

Copilot Learnings

  • For a Blazor app rename, update AssemblyName, RootNamespace, explicit C#/Razor namespaces, and the scoped CSS asset name together. Language-server namespace rename can miss Razor files; use editor-native edits for open buffers so later saves do not restore old identifiers.
  • CompanionApp operational settings use the CompanionApp configuration section and CompanionApp__ environment prefix. Migrate legacy chat-tester sections and prefixes, including environment-specific settings and model files. Retain the chat_tester data-protection application name, preference cookie/browser-storage keys, and Cosmos database defaults to preserve existing data and preferences; keep dedicated EVENTHUB_* overrides and proxy AZURE_APPCONFIG_* settings unchanged.
  • CompanionApp UI settings use the separate top-level CompanionAppUI section and CompanionAppUI__ environment prefix: PopupHelp, SectionTooltips, Documentation, TopicDocumentation, AppConfigurationRules, and Hosts. The existing CompanionAppOptions binds only its AppConfigurationRules and Hosts properties from this UI section; operational settings remain independent.
  • EventHubMonitor is nested under CompanionApp in both base and Development settings. Its existing options class uses CompanionApp:EventHubMonitor for both startup enablement and options binding; standard overrides use CompanionApp__EventHubMonitor__.... The former root section is not a fallback.
  • Validate CompanionApp JSON by configuration-provider filenames: appsettings, chat-models, and vision-models, including environment variants. Other root files with a .json extension can contain newline-delimited telemetry rather than a single configuration object.
  • The current WSL jq paths(scalars) export filter omits false values. Validate Boolean settings directly; do not interpret a missing exported flag as configuration-migration data loss or silently change export behavior outside scope.
  • Generate deployment default-name suffixes once in DeploymentSetupPage.OnInitialized, not during rendering or export. Use the same five lowercase alphanumeric characters for new resources, without separators for ACR/storage; preserve image names, DNS zones, and existing Service Bus/Cosmos references. New setups get fresh defaults; all stages from one setup must keep the same names. Random suffixes reduce collisions but do not establish Azure name availability.
  • Deployment Review loads replaceable PNG icons from src/CompanionApp/wwwroot/images/azure/. The original Azure Architecture Center V24 SVGs from https://arch-center.azureedge.net/icons/Azure_Public_Service_Icons_V24.zip and Microsoft's bundled terms remain alongside their PNG conversions; event-hub.png and entra-id.png replace the former CSS-drawn symbols. Update the PNG files to change the displayed icons. Keep service labels beside icons and use object-fit: contain; do not recolor the Azure assets or use them as the project's logo.
  • Match exact current text and a unique nearby anchor when patching Razor markup. A patch with mismatched context can land inside a code method despite reporting success; an immediate focused build detects this before additional edits.
  • Staged Deployment Setup exports are 01-bootstrap.json (groups/ACR), 02-publish-images.sh (explicit subscription, selected build method, image verification), and 03-application.json (existing groups/ACR). Image tags must match the publisher's v prefix. Do not leave ARM dependsOn entries pointing at resources created only by another stage.
  • Bicep Deployment Setup exports checked-in bootstrap/main/module Bicep assets plus a generated parameters.json consumed by both deployment stages. Its deploy.sh creates the selected ACR and imports pinned releases. Because a system identity does not exist before its Container App, the application stage first creates the app with public pinned images, grants its emitted principal AcrPull, App Configuration Data Reader, and selected async roles, then updates the app to ACR images with registry identity system. Do not emit Host1, Port, or AZURE_CLIENT_ID as Container App environment variables; configure backends through App Configuration. Keep App Configuration value population as a separate Companion App step, resource-group deduplication case-insensitive, and the Portal and Standalone workflows independent.
  • Edit the website's Bicep download templates in src/CompanionApp/Assets/Deployment/README.template.md and deploy.template.sh, not inline C# or the standalone deployment menu. CompanionApp embeds these assets; rebuild and restart it after template changes. DeploymentBicepBundle replaces {{DEPLOYMENT_NAME}} and {{LOCATION}} with complete shell-quoted values, so do not quote the tokens again. Preserve the final newline in each asset.
  • Recovery instructions must use the original subscription and the script's exact deployment name; checking status does not require the bundle or restart the deployment. Existing downloaded ZIPs are not updated by source changes.
  • Assign Bash command-substitution results before marking variables readonly so failed substitutions are not masked. Generated deployment-script tests must mock az, preserve its argument boundaries and exit codes, and cover help/input errors without contacting Azure.
  • Validate Markdown emitted by C# raw strings for unindented headings and code fences, not just expected text. If an indentation-only patch preserves the wrong spacing, replace the raw-string block including its delimiters and check the generated output again.
  • Integrated-browser tooling can omit native download events even when Blazor creates the correct download Blob. Check the app error state and Blob bytes, then validate the captured ZIP and compile its Bicep entry point; do not treat an event timeout alone as an application failure.
  • Portal ARM exports that create resource groups must use the subscription deployment schema at the root, with root group declarations and direct subscriptionResourceId('Microsoft.Resources/resourceGroups', ...) dependencies from service deployments. Both resource-group-root wrapper variants produced ResourceGroupNotFound in user testing, including the variant containing group declarations and deployments together in an embedded subscription template. Portal scope follows the root schema. Local structure checks do not establish live Azure validation success.
  • For .NET 10 file-based checks with project references, rebuild the referenced project explicitly and use dotnet run --no-cache --file ...; cached runs can exercise an older referenced assembly.
  • Use git --no-pager grep as well as git --no-pager diff; a pager can consume later terminal commands as interactive input. This WSL Git version does not support git grep -m; scope the paths or filter the output instead.
  • ARM resource names cannot contain runtime reference() calls. Pass generated values into an embedded template as parameters before using them in resource names.
  • App Configuration ARM key-values with disableLocalAuth=true require pass-through ARM authentication and deployer data-plane permissions. Encode key/label resource names with URL encoding, then replace ~ with ~7E and % with ~.
  • For editable child-component textareas in Blazor Server, use @bind:get / @bind:set with oninput instead of a value attribute plus an input callback; rapid typing can lose characters when parent rerenders echo older values. Test actual keyboard typing, not only Playwright fill.
  • Reusing a Razor popup requires checking parent-page CSS dependencies, including help icons and hidden tooltip content. Keep ConfigurationHelp styles in the shared component so help text does not become inline content on another page.
  • Native dialogs containing only fixed-position popup content need explicit dimensions. Scope browser assertions to the specific dialog class because Blazor can also render a reconnect dialog.
  • Never run patches against the same files in parallel; combine edits into one patch to avoid competing contexts.
  • For Deployment Setup browser checks, wait for the selected panel's controls after clicking a tab. Compare switch wrapper bounds, not the smaller checkbox bounds, when checking row alignment.
  • Treat taxonomy/concepts.json as the canonical source for documentation concept definitions, defaults, units, reload types, status values, and protocol headers.
  • Treat deployment/deploy.sh step 7 as the supported App Configuration setup path; it publishes every non-Hidden [ConfigOption] as Warm: or Cold: in one import and updates Warm:Sentinel.
  • App Configuration consumers must follow the proxy's established lifecycle: construct and configure one DefaultAzureCredential at startup, inject it, and reuse the ConfigurationClient; do not construct credentials inside load operations.
  • Use AZURE_APPCONFIG_REFRESH_INTERVAL_SECONDS as the canonical deployment and runtime polling variable; step 7 accepts AZURE_APPCONFIG_REFRESH_SECONDS only as a legacy input alias.
  • The Environment Variable Defaults (JSON) printed by App Configuration step 7 maps environment-variable names to code defaults and can be retained as an ACA startup fallback template; it is not a copy of effective App Configuration values (use KVSet export for that).
  • High-level understanding tone: Follow docs/nav/01-understand-the-proxy.md. Begin with the reader's problem and the system's role, then explain the end-to-end flow through active, cause-and-effect language. Introduce terms in context and connect mechanisms to outcomes. Defer commands, configuration keys, defaults, and implementation caveats to task-specific documentation. Remain factual and avoid promotional claims.
  • Operator tone: Assume technical literacy. Lead with the task, prerequisites, supported path, and expected result. Use direct, neutral instructions with exact commands, settings, defaults, units, observable signals, and recovery steps. Explain why an action matters only when that prevents an operational mistake. Do not narrate obvious commands or repeat one workflow as a summary, prose instructions, and a checklist. Organize content around setup, change, verify, and troubleshoot; avoid marketing language, self-congratulation, and unnecessary conceptual background.
  • When copyediting the CompanionApp README, preserve the user's conversational, reader-focused voice, including connections such as "for your scenario". Prefer light grammar and clarity edits over compressed rewrites; keep technical requirements, examples, and navigation intact.
  • Operational warnings must name when the risk applies, give a concrete impact example, and provide the recovery procedure; prefer the Azure service's native restore UI and official Microsoft documentation over vague instructions to "back up" data.
  • When deployment generates a configuration catalog, teach operators to discover exact keys and labels from the deployed store before showing CLI examples; do not require them to infer or memorize setting names.
  • Keep deployment parameters, menu steps, prerequisites, and deployment-script side effects in deployment/README.md; feature operator guides should link to that section and focus on runtime behavior, day-two changes, verification, and troubleshooting.
  • Validate taxonomy-linked docs for behavioral semantics as well as literal setting values; stale descriptions can remain even when defaults match.
  • Profile identity requires separate controls: UserIDFieldName selects the source JSON field, UserProfileHeader carries the inbound lookup ID, and UniqueUserHeaders builds the queue-accounting ID. The taxonomy's c-user-id description conflates them; confirm against ProfileEnricher and UserProfile.Parse before copying it into docs.
  • The docs/nav/*.md content-brief files treat their question checklists as content contracts, so when filling gaps, keep the original guidance text and add the answer directly under each question for easy review.
  • In docs/nav/*.md, Quick Answers headings are often duplicated in Full Answers; use #...-1 anchors in quick links so they jump to the full-answer section instead of self-linking to the quick tile.
  • In CompanionApp, the error dashboard behavior is owned primarily by Components/Shared/Response/ErrorResultPanel.razor; keep status-text normalization, chart behavior, hover previews, and error-detail modal behavior in that component instead of spreading UI logic into InvestigatorPage.razor.
  • A focused validation command for CompanionApp changes is dotnet build src/CompanionApp/CompanionApp.csproj /property:GenerateFullPaths=true /consoleloggerparameters:NoSummary after the user-owned directory/project moves. Before those moves, the project remains at src/ChatTester/chat_tester.csproj.
  • In CompanionApp's per-page Interactive Server configuration editor, test enhanced sidebar navigation explicitly: page-level NavigationLock alone did not intercept it. The page's JS module guards links while drafts are pending; native dialogs need explicit Escape handling in the integrated browser.
  • Configuration popup Escape handling must target only the topmost dialog: host/event-picker Cancel discards buffered edits, section Close retains staged edits, and leave-dialog Cancel preserves the current draft. Test nested focus return and both Tab directions; exclude visibility-hidden tooltip links from focus targets.
  • App Configuration label drafts must be separate from cached saved settings; use case-sensitive label identity and write all new settings, including empty values, only on explicit save. BypassConfig falls back to a live read when its disk cache is missing; it does not disable cloud writes.
  • CompanionApp references SimpleL7Proxy.csproj directly, so its Azure SDK pins must be compatible with the proxy's dependencies. A cached --no-restore build can succeed with MSB3277 conflicts while a fresh restore fails with NU1605 downgrades; do not infer restore success or change package pins outside the requested scope.
  • When splitting a Razor page into separate pages, remove old backing members/events in the original page in the same edit to avoid orphaned references that can trigger misleading design-time Razor errors.
  • Check that a search command exists before using it as an if condition; a command-not-found result can enter the else branch and print a false validation success.
  • Anchor typo-validation patterns to word boundaries; a substring such as assing also matches valid words such as assignment.
  • When validating a Markdown subsection, split on its known heading, then stop at the next peer heading. Splitting at the opening heading can discard the body; a lazy regex ending at $ with the multiline flag can stop at a blank line and report missing content incorrectly.
  • Do not combine Delete File and Add File for the same path in one apply_patch call; the patch correction can merge old and new content. Delete and add in separate patch calls when a full replacement is necessary.
  • Do not advertise POCs as completing within a fixed time unless that duration was validated from a clean environment including all prerequisites; distinguish quick verification from Azure provisioning and policy setup.
  • When a rule condition formats computed values into a stackalloc buffer, consume each span within the branch that created it; merging those spans into a shared local can trigger CS8352.
  • When an out var parsed inside a chained Boolean expression is needed afterward, assign the nullable result in the successful branch instead of relying on definite assignment through the chain.
  • Use test/nullserver/Python/stream_server.py --port <port> for local process tests; it supports random ports plus /health and /echo/resource without response assets.
  • Run the integrated 1,000-request priority harness with bash test/RegressionTests/run-priority-load.sh; it starts the null server, proxy, and one parallel curl process, then prints per-priority statistics.
  • Write generated curl config files as BOM-free UTF-8. Curl 7.81 silently ignores the first directive when a UTF-8 BOM precedes it.
  • With MSTest.Sdk 3.7.0, large multiline standard output can crash the runner with duplicate StandardOutputProperty entries. Write the report to a file during the test and print it from the launcher after dotnet test exits.
  • For APIM policy reviews, treat successful acceptance by the target gateway as controlling evidence; report conflicts with generic policy-reference restrictions as compatibility risks instead of asserting rejection.
  • Preserve the APIM empty-200 retry guard: it handles a known PTU endpoint API failure that returns HTTP 200 with no content; broaden success handling around that guard, not through it.
  • Put multiple edits to the same file under one Update File block; repeating the path in one apply_patch call can be rejected as a duplicate path.
  • For this APIM retry policy, classify a backend response and consume its Retry-After headers in the next cycle's previous-attempt path; dependency Response-retry-after telemetry can confirm the header existed when a later post-forward-request expression did not process that attempt.
  • Do not attribute a header in APIM context.Response to a specific retry attempt from a post-call snapshot alone; compare snapshots immediately before and after forward-request or correlate the APIM dependency operation.
  • In test/LLMSimulator, func start --no-build does not discover functions because .azurefunctions is generated under bin/output; use the normal func start path for local endpoint validation.
  • When SimpleL7Proxy model detection is enabled, put the model in the JSON body and let the proxy emit x-LLMModel; adding the same client header creates duplicate values and can make APIM fall back to its default catalog entry.
  • Treat proxy telemetry value N/A as missing evidence and continue to matching Attempt-N-* fields; proxy-generated errors can expose x-MID or only event/path correlation instead of a final HTTP S7P-ID.
  • A JArray attached to a staged JObject can diverge from the context-owned APIM policy array; mutate the context-owned activity log directly when later backendLog rendering reads that context variable.
  • An empty HTTP 200 means retry under the normal backend-selection rules; do not force failover or exclude the current backend unless the contract explicitly changes.
  • test/RegressionTests/configs/policy-test.json supplies checked-in policy and stress defaults; policy-test.local.json overlays matching test and proxy settings. Keep security values local and keep the base stress profile aligned with PolicyStressSettings when changing the standard stress run.
  • In policy stress results, classify terminal HTTP 429 responses as incomplete, not failed; final drain still requires every started request to complete and InFlight to reach zero.
  • In policy stress results, medium-priority HTTP 412 is an expected request-TTL outcome; permit its count explicitly while continuing to reject other failures such as HTTP 408.
  • Keep load workloads in test/RegressionTests/LoadTests with TestCategory("Load"); the default master run excludes them, and ./run-regression-master.sh load runs the consolidated load group.
  • For MSTest.Sdk 3.7.0 projects, run the generated test assembly directly when a method-level dotnet test --filter is ignored: dotnet path/to/Tests.dll --filter "Name=TestMethod".
  • Rebuild RegressionTests after changing source or helpers before invoking its generated test assembly directly; direct assembly execution does not compile pending changes.
  • Local proxy tests that wait on /startup need more than 30 seconds when profiles are disabled because UserProfile closes its readiness gate on a fixed 30-second timer; use at least a 45-second timeout.
  • Focused backend integration tests can wait for the S7P-Backend event with the expected ActiveHostsCount instead of /startup when unrelated readiness participants are outside the test contract.
  • Circuit-breaker integration fixtures must not use CBErrorThreshold=1 unless testing admission backpressure: percentage-bucket truncation makes the parent breaker return backpressure at zero failures. Use a threshold of at least 2 to isolate child Retry-After behavior.
  • MSTest.Sdk 3.7.0 emits appendable per-invocation TRX with --report-trx --report-trx-filename <name> --results-directory <dir>; TestContext.WriteLine content is available under each result's StdOut.
  • Keep explicit MSTest title/description fields separate from generated fallback metadata so repeated HTML report regeneration remains idempotent, especially for data-row input descriptions.
  • Before implementing a user-facing report or UI, confirm the information hierarchy and acceptance criteria. For regression reports, prioritize test title, description, outcome, and duration; keep commands, assemblies, TRX, and console logs in secondary diagnostics.
  • Preserve intentional control points, comments, and TODO direction in existing code. Wire requested behavior into them instead of removing or redesigning them unless the user explicitly requests a refactor.
  • Keep edits small enough for line-by-line review. Do not combine requested behavior with optional cleanup, abstraction changes, or design improvements.
  • Develop parsers and report renderers against representative fixtures covering passed, failed, skipped, parameterized, and output-producing tests. Run expensive integration tests only after fixture-based checks pass.
  • Treat a zero-test filtered regression execution as a configuration failure. Build once per master execution and reuse the generated test assembly for subsequent filters.
  • When command output is truncated or appears incomplete, inspect exit status, generated artifacts, timestamps, and running processes before rerunning or changing code.
  • Only pass execution IDs returned by terminal tools to output or cancellation tools. If a command returns no output and no ID, inspect terminal status or running processes; never invent an ID or stop unrelated servers.
  • If the same ad hoc operation is needed twice, implement a supported reusable command before doing it a third time.
  • Treat generated HTML and reports as validation artifacts. Make durable changes in their generator, then regenerate the artifact.
  • When VS Code's active buffer and the on-disk file disagree, preserve the user's active edit and verify through editor-aware tools before applying a patch.
  • Once the requested acceptance criteria and focused validations pass, stop. Do not expand scope without a new request.
  • Home panel clicks can be lost during Blazor prerendering; gate them with RendererInfo.IsInteractive. Keep Home's onboarding panel in document flow: its global fixed overlay intercepts panel clicks on narrow screens. Test real pointer clicks with onboarding active, not only DOM visibility.
  • CompanionApp's per-page Interactive Server navigation can retain Home across routes without a parameter change. Derive hub selection from the URL, refresh on NavigationManager.LocationChanged, and unsubscribe on disposal; test area-to-area navigation, direct loads, and browser Back/Forward.
  • CompanionApp's Test hub and expanded navigation expose URL test (/url-tester), Stress test (/stress-test), and Abort test (/abort-test). Preserve all three choices instead of replacing them with a generic link to the separate tabbed /tests workspace.
  • Emit Razor ARIA Boolean values as explicit "true" and "false" strings; Boolean attribute binding can render an empty attribute. Check the rendered toggle state and ensure collapsed navigation removes hidden links from keyboard tab order.
  • In integrated browser tests, access browser-only URL/location APIs through page.evaluate. Wait for the expected computed CSS value when checking animated highlights; reading immediately after a class change can sample the transition.
  • Compare responsive card widths to their current grid tracks, not another page's pixel widths; vertical scrollbars change available width. Check hidden active navigation links with an attached-state wait, and wait for the destination heading before navigating away.
  • The shell: build SimpleL7Proxy only VS Code task can pass its UNC workspace path to WSL as //wsl.localhost/... and fail with MSB1009; validate from WSL with dotnet build src/SimpleL7Proxy/SimpleL7Proxy.csproj instead.
  • Run terminal diagnostics sequentially because run_in_terminal reuses shell state; disable Git pagers with git --no-pager for non-interactive checks.
  • After extracting a large declaration with apply_patch, inspect both source boundaries before proceeding; malformed context markers can be inserted literally even when the patch reports success.
  • This repository's WSL environment does not include rg; use git grep for tracked-file searches.
  • Build host and Path_* route changes as one candidate snapshot; validate every host, route, and via reference before activation so a rejected warm update retains the last known-good snapshot.
  • Preserve each file's existing EOL convention. Use editor-native apply_patch for content changes and never use shell commands to normalize or rewrite files.
  • Keep the repository's autocrlf setting during git diff --check. Disabling it on this Windows/WSL worktree can classify every CRLF line as trailing whitespace; use -c core.whitespace=cr-at-eol for a CRLF-aware check instead of rewriting file endings.
  • Normalize CRLF only in memory for content assertions. Verify configuration exports against expected keys and values, not a guessed minimum catalog size.
  • The main solution and ARM export harness reference src/CompanionApp/CompanionApp.csproj. If the user-owned moves are still pending, validate against the actual current project path rather than moving files on the user's behalf.
  • When invoking WSL bash -lc through PowerShell, write critical executable paths explicitly instead of relying on an intermediate Bash variable; wrapper quoting can remove the variable and turn the next option into the dotnet command name.
  • git diff --check does not inspect untracked files; run a direct trailing-whitespace check on newly created scripts and documents until they are tracked.
  • Deployment Setup embeds deployment/deploy.parameters.example.sh at build time, exports literal single-quoted values, and never executes imported shell text. Validate exact template-key parity, Bash syntax, and compatibility with deploy.derived.sh without running Azure deployment steps.
  • Wrap Razor event-handler lambdas containing string literals in explicit @(...) expressions to avoid attribute parsing errors.
  • Transfer generated browser test artifacts directly to a temporary file instead of manually copying large Base64 payloads; transcription errors invalidate byte-level checks.
  • The active regression project is test/RegressionTests/SimpleL7Proxy.Test.csproj targeting net10.0; after rebuilding, run focused tests through test/RegressionTests/bin/Debug/net10.0/SimpleL7Proxy.Test.dll. Confirm the working directory and exact project path before trusting execution-worker discovery.
  • After splitting a responsive layout, remove breakpoint overrides that assumed the old column widths. Validate the replacement on both sides of each affected breakpoint; base styles alone can look correct while wide-screen rules reintroduce wrapping and excess height.
  • Standalone sidecar services (src/HealthProbe, src/MetricsServer) follow one pattern: a BackgroundService that builds its own WebApplication, clears configuration sources and logging providers, configures Kestrel/SocketTransportOptions explicitly, reads settings from environment variables, and ships with a Dockerfile built from the src context plus a build.sh that tags from VERSION in Constants.cs and pushes to ACR. The mcr.microsoft.com/dotnet/aspnet image has no curl, so install it when the Dockerfile declares a curl HEALTHCHECK.
  • Enable Application Insights in these services with Microsoft.ApplicationInsights.WorkerService 2.23.0, registered only when APPINSIGHTS_CONNECTIONSTRING is set, with adaptive sampling disabled. Inject TelemetryClient? telemetryClient = null into the hosted service so it resolves when telemetry is enabled and stays null otherwise.
  • Confirm the active terminal shell before choosing command syntax. A Windows VS Code session with a PowerShell extension terminal can still execute tool commands in WSL Bash.
  • ProfileEnricher evaluates every top-level rule against the same pre-rule context; header outputs do not feed later conditions, and later outputs overwrite same-named headers. RuleCondition treats missing fields as matches for notEquals and notContains, so negative comparisons do not enforce header presence.
  • In Windows-hosted VS Code, use the workspace UNC path (\\wsl.localhost\Ubuntu-22.04\home\nagendra\repos\SimpleL7Proxy\...) for file tools. Linux /home/... paths belong to the WSL terminal; file tools can resolve them on Windows instead, outside the repository.
  • TokenomicsSettings uses comma- or semicolon-separated key=value pairs, not JSON. Keep typed validation and round-trippable ToString() output; model prices use ModelCostPerToken.<URI-escaped model>=Input:<price>|CachedInput:<price>|Output:<price>, while a legacy scalar maps to output pricing.
  • Blazor hot reload cannot replace or delete a component static field (ENC0033). Preserve the field shape and filter obsolete values during an active session, or restart the app before validating the replacement.
  • A Blazor hot-reload error overlay intercepts browser input. Restart the app before interaction testing after a rude edit instead of forcing clicks through the overlay.
  • Compare deployment Bicep entry points/modules with src/CompanionApp/Assets/Deployment/Bicep using matching relative inventories and CRLF-normalized content; preserve each tree's existing line endings. Generate temporary bundles in the shared terminal when a later command must inspect them because execution-worker /tmp artifacts may be isolated.
  • CompanionApp Docker publishes must explicitly reference Microsoft.AspNetCore.App.Internal.Assets at the ASP.NET runtime servicing version and fail the image build when blazor.web.js or blazor.server.js is missing or empty; a static-web-assets manifest alone does not make a prerendered page interactive.
  • Deployment --MakeUniq stores and reuses one four-digit suffix, truncates only deployment-created names to Azure limits before appending it, and preserves concrete Service Bus/Cosmos references.
  • Keep App Configuration endpoints empty on bootstrap Container App revisions. Assign the system identities their App Configuration roles first, then provide the endpoints only to final revisions; an early unauthorized managed-identity request can leave authorization cached after RBAC is created.
  • When extracting a worker loop, classify fields by the methods that read and mutate them, not by the copied constructor. Backend header caches, streaming dependencies, and the expulsion token/flag stay with the backend worker; the loop must observe that same eviction state. Mutable cleanup-error events belong to the loop's failure handling, not to shared static state.
  • During a C# class extraction in this UNC workspace, editor diagnostics can miss the new source type and Test Explorer can report no tests even when the SDK build and direct test assembly succeed. Validate the project and focused tests before changing source inclusion to address an editor-only diagnostic.
  • For isolated settings validation during unrelated compile failures, SDK Roslyn can compile the current source in memory through dotnet fsi. Reference the last built proxy only for unchanged dependencies, exercise the newly compiled type, and report the full-build blocker separately.
  • JsonStreamProcessor.CopyToAsync's primary-line search (src/Shared-parser/StreamProcessor/JsonStreamProcessor.cs) breaks at the first chronological line containing the substring "usage", but OpenAI/Azure OpenAI streaming responses emit a literal "usage":null in nearly every delta chunk before the real numbers arrive in the final chunk. This can make the shared loop select an early null-usage chunk instead of the final one; flagged to the user but left unfixed pending their own review, since it's shared logic affecting every processor beyond the requested scope.
  • New processors needing full-stream signals (e.g. Azure OpenAI's jailbreak flag, present only in the first chunk's prompt_filter_results, or content_filter_results spread across every chunk) must set CaptureAllLines = true and should re-derive the usage object themselves from the full lastLines array inside ProcessLastLines, rather than trusting the base class's primaryLine parameter, to work around the primary-line search bug above without modifying shared code. See TokenomicsProcessor.cs.
  • Cached prompt tokens live at usage.prompt_tokens_details.cached_tokens in OpenAI/Azure OpenAI responses (samples: test/nullserver/Python/4o-mini.txt, gpt5-nano-response.txt), not at the top level of usage.
  • src/SimpleL7Proxy/Tokenomics/TokenMetricsCache.AddMetric and the // submit stats to Tokenomics placeholder in ProxyWorker.StreamResponseAsync's finally block are the intended wiring point between response-stream stats (request.EventData) and Tokenomics budget/quota enforcement, but as of this session nothing in production code actually calls AddMetric from that placeholder yet.
  • test/RegressionTests/TestTasks/TokenMetricsCacheTests.cs has pre-existing, already-broken tests independent of any Tokenomics feature work: RecordRequestOutcome_Tracks429RateAndLatencyDrift never calls RollupAsync/StartAsync, so _requestSamplesByUser is never populated (samples only move there inside CollapseMetrics, run by the periodic background task) and its 429-rate/count/latency asserts always fail; StopAsync_DrainsBothMetricBuffers and Rollup_UsesQueuedUtcDateAndRemovesExpiredPeriods reflect on the private _metrics field expecting a raw ConcurrentQueue<(string,string,int,int,DateOnly)>[] tuple shape, but git show HEAD:...TokenMetricsCache.cs confirms the PendingMetric struct (with StatusCode/LatencyMs/TimestampUtc) was already the committed shape, so these tests were already failing before this session's changes. Verified via dotnet build + running SimpleL7Proxy.Test.exe --filter "FullyQualifiedName~TokenMetricsCacheTests" directly (MSTest.Sdk's Microsoft.Testing.Platform executable uses --filter, not --filter-class; the generated .dll only appears after a build that isn't blocked by unrelated compile errors elsewhere in the test project — a --no-incremental rebuild fixed a stale/missing-dll apphost issue after temporarily removing an unrelated broken file).
  • When one file in a shared, multi-session repo has a signature mismatch unrelated to the current task (e.g. test/RegressionTests/TestTasks/ModelRemapTests.cs calling an old 3-arg ModelSwapper.ValidateModel while the committed/working-tree signature already takes 5 args, from other in-flight work), verify it's pre-existing via git status/git show HEAD:..., then move it aside with Move-Item, run the relevant tests, and restore it to the exact same path before finishing — do not edit it to fix the unrelated mismatch.
  • .NET JSON timestamps can contain seven fractional-second digits, while Python's datetime.fromisoformat accepts at most six. Validation scripts must validate the seventh digit, then truncate to microseconds before parsing.
  • Current Bicep supports deployer(), which exposes the initiating user, service principal, or managed identity. Use deployer().objectId for deterministic RBAC assignments to the deployment principal instead of parsing Azure CLI account state or adding a generated principal-ID parameter.
  • For CompanionApp UI validation, use the focused CompanionApp build rather than workspace-wide tests. Reuse the user-provided server; if a fresh instance is required, verify its fingerprinted static assets over HTTP before navigating the shared browser to its port.
  • A fixed nested popup inside a modal with transform/backdrop-filter and overflow clipping uses that modal as its containing block. While the nested popup is open, remove those containing-block and clipping properties from the parent modal, or render the popup through a viewport-level portal.
  • APIM policy fragments cannot contain cache-lookup-value, <base />, section wrappers, or nested include-fragment statements. Keep v3.2 cache lookups and the per-policy DefaultModel in Priority-with-retry.xml, and split reusable behavior into section-specific fragments around those boundaries.
  • In this UNC workspace, apply_patch can report a successful deletion while an untracked file remains unchanged. Verify file absence after deletion; when an isolated retry still fails and deletion is explicitly authorized, remove only the verified obsolete file directly.
  • CompanionApp ImageSyncService must stage each downloaded layer in a seekable temp file before ContainerRegistryContentClient.UploadBlobAsync. With a non-seekable network stream the SDK issues one PATCH per partial ReadAsync (often a few KB), so large layers never finish and the idle source download connection times out.
  • With Azure.Data.AppConfiguration.ConfigurationClient, use SettingSelector.LabelFilter = "\0" to select unlabeled keys. The SDK does not expose the configuration provider's LabelFilter.Null helper; escape backslashes, asterisks, and commas when filtering by an exact label.
  • CompanionApp Event Hub provisioning belongs to its Bicep bundle and follows DEPLOY_COMPANION_APP. Keep the bootstrap monitor disabled until hub-scoped Event Hubs Data Receiver access is assigned to its system identity; only the final revision enables it. Validate exports with dotnet run --no-cache --file test/ManualTests/DeploymentEventHubChecks.cs from the repository root.
  • Deployment Setup reuses _panelHeading as the post-render FocusAsync target for every tab. Each rendered panel state (form groups, Review architecture, Review/Deployment validation-error alert, Deployment bundle) must attach @ref="_panelHeading" tabindex="-1" to one element; otherwise the reference points to a removed element and Blazor throws "Unable to focus an invalid element", terminating the circuit.
  • TokenomicsSettings and ModelTokenPricing are compiled by Shared-parser. Exclude the identical legacy TokenomicsSettings.cs from SimpleL7Proxy compilation; compiling both copies causes CS0436 warnings in the proxy and CS0433 errors in CompanionApp.
  • CompanionApp-generated Bicep bundles embed deployment/*.bicep and deployment/modules/*.bicep directly; keep /deployment as the sole Bicep template source and do not recreate mirrored templates under src/CompanionApp/Assets.
  • Host summary columns must recognize schema-defined booleans even when every host omits the key; render the configured default so hosts with implicit enabled=true remain toggleable.
  • CompanionApp monitor settings and proxy Event Hub settings are separate. Startup seeds Cold:Logging:EventHub:* from enabled monitor configuration only when the label does not exist. Existing labels must remain untouched, including blank or missing destination settings.
  • For SDK F# Interactive checks supplied through stdin, use interactive input terminated by ;;, not --exec /dev/stdin (which requires a seekable stream). Subscribe to C# event Action using its explicit add_Changed/remove_Changed accessors; confirm the assertion-success output because interactive compiler errors can still return exit code zero.
  • HtmlRenderer cannot instantiate a component with an explicit Interactive Server render mode. Validate those components through the running CompanionApp rather than treating unsupported static-renderer checks as evidence of a component failure.
  • For isolated report text/attribute privacy checks without starting a server, invoke the freshly compiled component's BuildRenderTree with RenderTreeBuilder and inspect its frames after OnParametersSet. F# Interactive also requires Microsoft.AspNetCore.Components.Web.dll for generated event callbacks. This checks generated content, not browser layout or interaction.
  • SDK F# Interactive exposes C# dashboard ValueTuple entries as struct tuples; destructure them with struct (...) instead of accessing ItemN. When checking rendered CompanionApp HTML, allow scoped CSS attributes between a class attribute and the closing >; literal class-to-text matches can miss valid markup.
  • TokenomicsSummaryEvent outcome preparation removes policy-decision fields, including PolicyAction. Keep synthetic policy decisions as separate records when generating a fixed-size sample that must retain action coverage; serialize with ProxyEvent.ConvertToJson and explicitly supply MID, Type, and numeric Status, matching the event-client envelope.
  • MSTest can remove its deployment directory after a run, including sample artifacts created beneath TestContext.TestResultsDirectory. Write samples that must remain on disk to a unique directory under Path.GetTempPath(), and attach and log the absolute path.
  • EventHubMonitorTests uses MSTest.Sdk 3.7.0 assertions: use Assert.ThrowsException<T> and collection .IsEmpty/.Contains checks; newer Assert.ThrowsExactly, Assert.IsEmpty, and Assert.Contains APIs are unavailable.
  • EventHubReader's general event dictionaries are case-insensitive, but Tokenomics summary fields and file replay use ordinal keys. Validate the ordinal immutable copy before aggregation so differently cased required fields cannot pass validation and then fail snapshot generation.
  • Tokenomics UI tabs: Tab selection state must be stored in a component-level _selectedViewTab field (string type) and toggled via an event handler method. In Razor, use @onclick="@(() => SelectViewTab("TabName"))" (with inner wrapping @(...) around the lambda) to avoid quote-escape issues in the HTML attribute. Avoid bare @onclick="() => SelectViewTab(\"TabName\")" as backslash escapes can trigger compiler errors. Conditional content within tab cards uses @if/_selectedViewTab == "tab" blocks to render tab-specific visualizations without breaking the parent card structure. For tab-specific axis scaling (e.g., Tokens tab without cached), calculate the local maximum before rendering HTML (not inside @{}), then pass it to nested markup via variable scope. Do NOT use @for inside @{ } code blocks for HTML generation; instead move the variable definitions to C# before the opening HTML tag and reference the variable in @for at the HTML level.
  • SpendTrend data must be pre-computed alongside token Trend data using the same daily/hourly bucketing logic. Extract spend from the trendByBucket aggregates dictionary and create an array of (Date, Spend) tuples with consistent date labels. This alignment ensures spend and token charts use the same X-axis buckets and timestamps.
  • The Tokenomics report catalog is navigation metadata, not event data. TokenomicsEventReplay must include the existing eight-report catalog in every live/replay snapshot, including zero-event periods; otherwise the reports sidebar renders only its heading. Inspect the snapshot collection before blaming CSS or component imports.
  • Policy Decisions and Outcomes uses deduplicated PolicyDecision records, not RequestOutcome records, with one row per evaluation. Preserve period and tenant/user/original-or-final-model filters. TimestampUtc is evaluation time; current telemetry does not capture configured actions, limits, governance flags or policy/config version. Show "Not captured" rather than inferring historical values from current settings. AllowedWithChanges displays as Modified; preserve Throttled and Pending outcomes instead of labeling them Allowed.
  • Policy report outcome KPIs/charts count the latest recorded evaluation per MID within the selected period; policy actions and the recent table count every evaluation. Do not label a latest policy evaluation as the final backend result or translate Requeued into the mockup's unsupported "Required" outcome. CSV export follows the recent-table outcome filter, includes all matching evaluations rather than only the visible page, and neutralizes spreadsheet formula prefixes.
  • Policy replay seed data must vary traffic volume and outcome mix independently; evenly cycling scenarios makes every chart flat and every tenant identical. Preserve retry MID/user/tenant, increment EvaluationSequence, carry forward model/priority, and schedule reevaluation after the recorded delay. Critical/high-priority scenarios must respect the configured priority thresholds. Keep unsupported telemetry fields absent rather than manufacturing historical metadata.
  • Model Routing and Substitution correlates in-window policy evaluations and RequestOutcome records by MID, counts requests once, uses the earliest recorded requested model and the latest outcome-reported or policy-selected model. Model filtering must retain every record for a matching request so original/selected models and usage remain correlated. ModelReplacementAllowed is not currently emitted: neither ModelChanged, BackendCallAllowed nor rejection proves substitution permission. Cost comparisons require UsageAvailable and both model prices; label current-price, same-usage counterfactual estimates explicitly and report coverage.
  • Capacity and Queue Pressure can reuse RoutingEvents for correlated policy/outcome records. Current summaries do not emit utilization, capacity threshold, queue depth/maximum/high-depth threshold, or actual queue-wait duration. Winning Capacity*/Queue* conditions identify observed flags, not measured utilization; other conditions do not prove an unconstrained request. RetryAfterMs is requested scheduling delay, not actual wait. Compare recorded-pressure versus unknown-state cohorts and preserve separate request counts, evaluation counts, and latest backend outcomes.
  • Latency, Errors and Throttling uses one latest timestamped RequestOutcome per MID, not policy evaluations or backend attempts, for HTTP rates and measured latency. Missing outcomes remain separate; rates use captured HTTP statuses. Error rate excludes 429 (4xx/5xx only) and throttling rate counts HTTP 429, not a Throttled policy decision. Use nearest-rank percentiles, include measured zero, exclude invalid/nonfinite/negative durations with a visible warning, and leave unsampled timeline buckets as gaps. Policy RetryAfterMs is requested scheduling delay; backend Retry-After headers, throttle/wake timestamps and normal-period baselines are not emitted and must not be inferred.
  • Governance report categories must follow TokenomicsHandler's actual winning-condition semantics: AdministratorOverride means AdministratorOverride OR ApprovedException; DailyQuotaGovernance means daily-quota exceeded plus IncidentResponse OR AuditInvestigation OR ComplianceRequired; entitled-tenant budget conditions mean PremiumTenant OR EnterpriseTenant. CapacityCriticalWorkload does not establish incident response. Separate flags, reasons, actors, approval references, dedicated audit IDs and quota balances are absent from current summaries. MID/DecisionId are request/evaluation correlations, not audit approval IDs. Attribute usage and recorded Cost once per distinct governed MID, require UsageAvailable, report coverage, and do not assume the Cost field's currency or billing validity.
  • Abuse and Content-Filter Activity must use AbuseDetected policy conditions and explicit positive RequestOutcome flags, not generic AtRiskRequests, quota rejections or HTTP status alone. Retain any positive across a MID's outcomes while showing latest policy/HTTP results separately; false/missing flags can be defaults and never prove scan coverage or safety. Filtering plus 2xx does not prove sanitization. Detailed filter categories/review actions/policy versions are absent. Count repeat activity across distinct requests, require captured identity, and attribute latest-outcome usage once per MID. Display/export keyed process-lifetime HMAC user/request aliases, tenant-scoped subject identities, no raw IDs or arbitrary error/prompt/response text; aliases are pseudonyms, not guaranteed anonymity, and shared filters/tenant names remain unchanged.
  • Never call read_agent with a placeholder or guessed identifier. Use only an actual agent ID returned by task or a runtime notification; when no agent was launched, validate directly.
  • AtRiskRequests identification in TokenomicsEventReplay looks for decisions where PolicyAction is "Reject", "Requeue", or ContentFilterReason is non-empty. Map policy actions to human-readable statuses: "Reject"→"Blocked", "Requeue"→"Throttled", others→"Flagged". Include user, model, reason, and timestamp from decision fields. Limit results to top 10 to avoid overwhelming the UI with large flagged-request datasets.