- 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
CompanionAppconfiguration section andCompanionApp__environment prefix. Migrate legacychat-testersections and prefixes, including environment-specific settings and model files. Retain thechat_testerdata-protection application name, preference cookie/browser-storage keys, and Cosmos database defaults to preserve existing data and preferences; keep dedicatedEVENTHUB_*overrides and proxyAZURE_APPCONFIG_*settings unchanged. - CompanionApp UI settings use the separate top-level
CompanionAppUIsection andCompanionAppUI__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:EventHubMonitorfor both startup enablement and options binding; standard overrides useCompanionApp__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 omitsfalsevalues. 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 fromhttps://arch-center.azureedge.net/icons/Azure_Public_Service_Icons_V24.zipand Microsoft's bundled terms remain alongside their PNG conversions;event-hub.pngandentra-id.pngreplace the former CSS-drawn symbols. Update the PNG files to change the displayed icons. Keep service labels beside icons and useobject-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
vprefix. 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.mdanddeploy.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 producedResourceGroupNotFoundin 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 grepas well asgit --no-pager diff; a pager can consume later terminal commands as interactive input. This WSL Git version does not supportgit 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=truerequire pass-through ARM authentication and deployer data-plane permissions. Encode key/label resource names with URL encoding, then replace~with~7Eand%with~. - For editable child-component textareas in Blazor Server, use
@bind:get/@bind:setwithoninputinstead 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.jsonas the canonical source for documentation concept definitions, defaults, units, reload types, status values, and protocol headers. - Treat
deployment/deploy.shstep 7 as the supported App Configuration setup path; it publishes every non-Hidden[ConfigOption]asWarm:orCold:in one import and updatesWarm:Sentinel. - App Configuration consumers must follow the proxy's established lifecycle: construct and configure one
DefaultAzureCredentialat startup, inject it, and reuse theConfigurationClient; do not construct credentials inside load operations. - Use
AZURE_APPCONFIG_REFRESH_INTERVAL_SECONDSas the canonical deployment and runtime polling variable; step 7 acceptsAZURE_APPCONFIG_REFRESH_SECONDSonly 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:
UserIDFieldNameselects the source JSON field,UserProfileHeadercarries the inbound lookup ID, andUniqueUserHeadersbuilds the queue-accounting ID. The taxonomy'sc-user-iddescription conflates them; confirm againstProfileEnricherandUserProfile.Parsebefore copying it into docs. - The
docs/nav/*.mdcontent-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#...-1anchors 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 intoInvestigatorPage.razor. - A focused validation command for CompanionApp changes is
dotnet build src/CompanionApp/CompanionApp.csproj /property:GenerateFullPaths=true /consoleloggerparameters:NoSummaryafter the user-owned directory/project moves. Before those moves, the project remains atsrc/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.csprojdirectly, so its Azure SDK pins must be compatible with the proxy's dependencies. A cached--no-restorebuild 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
ifcondition; a command-not-found result can enter theelsebranch and print a false validation success. - Anchor typo-validation patterns to word boundaries; a substring such as
assingalso matches valid words such asassignment. - 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 FileandAdd Filefor the same path in oneapply_patchcall; 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
stackallocbuffer, consume each span within the branch that created it; merging those spans into a shared local can trigger CS8352. - When an
out varparsed 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/healthand/echo/resourcewithout 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.Sdk3.7.0, large multiline standard output can crash the runner with duplicateStandardOutputPropertyentries. Write the report to a file during the test and print it from the launcher afterdotnet testexits. - 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 Fileblock; repeating the path in oneapply_patchcall can be rejected as a duplicate path. - For this APIM retry policy, classify a backend response and consume its
Retry-Afterheaders in the next cycle's previous-attempt path; dependencyResponse-retry-aftertelemetry can confirm the header existed when a later post-forward-requestexpression did not process that attempt. - Do not attribute a header in APIM
context.Responseto a specific retry attempt from a post-call snapshot alone; compare snapshots immediately before and afterforward-requestor correlate the APIM dependency operation. - In
test/LLMSimulator,func start --no-builddoes not discover functions because.azurefunctionsis generated underbin/output; use the normalfunc startpath 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/Aas missing evidence and continue to matchingAttempt-N-*fields; proxy-generated errors can exposex-MIDor only event/path correlation instead of a final HTTPS7P-ID. - A
JArrayattached to a stagedJObjectcan diverge from the context-owned APIM policy array; mutate the context-owned activity log directly when laterbackendLogrendering 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.jsonsupplies checked-in policy and stress defaults;policy-test.local.jsonoverlays matching test and proxy settings. Keep security values local and keep the base stress profile aligned withPolicyStressSettingswhen 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
InFlightto 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/LoadTestswithTestCategory("Load"); the default master run excludes them, and./run-regression-master.sh loadruns the consolidated load group. - For
MSTest.Sdk3.7.0 projects, run the generated test assembly directly when a method-leveldotnet test --filteris 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
/startupneed more than 30 seconds when profiles are disabled becauseUserProfilecloses 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-Backendevent with the expectedActiveHostsCountinstead of/startupwhen unrelated readiness participants are outside the test contract. - Circuit-breaker integration fixtures must not use
CBErrorThreshold=1unless testing admission backpressure: percentage-bucket truncation makes the parent breaker return backpressure at zero failures. Use a threshold of at least 2 to isolate childRetry-Afterbehavior. MSTest.Sdk3.7.0 emits appendable per-invocation TRX with--report-trx --report-trx-filename <name> --results-directory <dir>;TestContext.WriteLinecontent is available under each result'sStdOut.- 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/testsworkspace. - 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 onlyVS Code task can pass its UNC workspace path to WSL as//wsl.localhost/...and fail with MSB1009; validate from WSL withdotnet build src/SimpleL7Proxy/SimpleL7Proxy.csprojinstead. - Run terminal diagnostics sequentially because
run_in_terminalreuses shell state; disable Git pagers withgit --no-pagerfor 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; usegit grepfor tracked-file searches. - Build host and
Path_*route changes as one candidate snapshot; validate every host, route, andviareference before activation so a rejected warm update retains the last known-good snapshot. - Preserve each file's existing EOL convention. Use editor-native
apply_patchfor 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-eolfor 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 -lcthrough 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 thedotnetcommand name. git diff --checkdoes 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.shat build time, exports literal single-quoted values, and never executes imported shell text. Validate exact template-key parity, Bash syntax, and compatibility withdeploy.derived.shwithout 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.csprojtargetingnet10.0; after rebuilding, run focused tests throughtest/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: aBackgroundServicethat builds its ownWebApplication, clears configuration sources and logging providers, configures Kestrel/SocketTransportOptionsexplicitly, reads settings from environment variables, and ships with aDockerfilebuilt from thesrccontext plus abuild.shthat tags fromVERSIONinConstants.csand pushes to ACR. Themcr.microsoft.com/dotnet/aspnetimage has nocurl, so install it when the Dockerfile declares a curl HEALTHCHECK. - Enable Application Insights in these services with
Microsoft.ApplicationInsights.WorkerService2.23.0, registered only whenAPPINSIGHTS_CONNECTIONSTRINGis set, with adaptive sampling disabled. InjectTelemetryClient? telemetryClient = nullinto 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=valuepairs, not JSON. Keep typed validation and round-trippableToString()output; model prices useModelCostPerToken.<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
deploymentBicep entry points/modules withsrc/CompanionApp/Assets/Deployment/Bicepusing 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/tmpartifacts may be isolated. - CompanionApp Docker publishes must explicitly reference
Microsoft.AspNetCore.App.Internal.Assetsat the ASP.NET runtime servicing version and fail the image build whenblazor.web.jsorblazor.server.jsis missing or empty; a static-web-assets manifest alone does not make a prerendered page interactive. - Deployment
--MakeUniqstores 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":nullin 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, orcontent_filter_resultsspread across every chunk) must setCaptureAllLines = trueand should re-derive the usage object themselves from the fulllastLinesarray insideProcessLastLines, rather than trusting the base class'sprimaryLineparameter, to work around the primary-line search bug above without modifying shared code. SeeTokenomicsProcessor.cs. - Cached prompt tokens live at
usage.prompt_tokens_details.cached_tokensin OpenAI/Azure OpenAI responses (samples:test/nullserver/Python/4o-mini.txt,gpt5-nano-response.txt), not at the top level ofusage. src/SimpleL7Proxy/Tokenomics/TokenMetricsCache.AddMetricand the// submit stats to Tokenomicsplaceholder inProxyWorker.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 callsAddMetricfrom that placeholder yet.test/RegressionTests/TestTasks/TokenMetricsCacheTests.cshas pre-existing, already-broken tests independent of any Tokenomics feature work:RecordRequestOutcome_Tracks429RateAndLatencyDriftnever callsRollupAsync/StartAsync, so_requestSamplesByUseris never populated (samples only move there insideCollapseMetrics, run by the periodic background task) and its 429-rate/count/latency asserts always fail;StopAsync_DrainsBothMetricBuffersandRollup_UsesQueuedUtcDateAndRemovesExpiredPeriodsreflect on the private_metricsfield expecting a rawConcurrentQueue<(string,string,int,int,DateOnly)>[]tuple shape, butgit show HEAD:...TokenMetricsCache.csconfirms thePendingMetricstruct (withStatusCode/LatencyMs/TimestampUtc) was already the committed shape, so these tests were already failing before this session's changes. Verified viadotnet build+ runningSimpleL7Proxy.Test.exe --filter "FullyQualifiedName~TokenMetricsCacheTests"directly (MSTest.Sdk's Microsoft.Testing.Platform executable uses--filter, not--filter-class; the generated.dllonly appears after a build that isn't blocked by unrelated compile errors elsewhere in the test project — a--no-incrementalrebuild 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.cscalling an old 3-argModelSwapper.ValidateModelwhile the committed/working-tree signature already takes 5 args, from other in-flight work), verify it's pre-existing viagit status/git show HEAD:..., then move it aside withMove-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.fromisoformataccepts 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. Usedeployer().objectIdfor 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 nestedinclude-fragmentstatements. Keep v3.2 cache lookups and the per-policyDefaultModelinPriority-with-retry.xml, and split reusable behavior into section-specific fragments around those boundaries. - In this UNC workspace,
apply_patchcan 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 partialReadAsync(often a few KB), so large layers never finish and the idle source download connection times out. - With
Azure.Data.AppConfiguration.ConfigurationClient, useSettingSelector.LabelFilter = "\0"to select unlabeled keys. The SDK does not expose the configuration provider'sLabelFilter.Nullhelper; 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 withdotnet run --no-cache --file test/ManualTests/DeploymentEventHubChecks.csfrom the repository root. - Deployment Setup reuses
_panelHeadingas the post-renderFocusAsynctarget 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/*.bicepanddeployment/modules/*.bicepdirectly; keep/deploymentas the sole Bicep template source and do not recreate mirrored templates undersrc/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=trueremain 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 Actionusing its explicitadd_Changed/remove_Changedaccessors; confirm the assertion-success output because interactive compiler errors can still return exit code zero. HtmlRenderercannot 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
ValueTupleentries as struct tuples; destructure them withstruct (...)instead of accessingItemN. 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/.Containschecks; newerAssert.ThrowsExactly,Assert.IsEmpty, andAssert.ContainsAPIs 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
_selectedViewTabfield (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@forinside@{ }code blocks for HTML generation; instead move the variable definitions to C# before the opening HTML tag and reference the variable in@forat 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.