agentleFS
Azure-SamplesAzure-Samples/chat-with-your-data-solution-accelerator/.github/copilot-instructions.md

chat-with-your-data-solution-accelerator

Copilot instructions1.2k starsChanged 2 years agoMITView on GitHub

These instructions are always loaded. Read them before doing anything else. You may fetch and read these for architectural patterns. Never copy code wholesale — adapt with attribution in a code comment when the pattern is non-trivial. Specifically:

  • Reads credentials

We split this copilot-instructions.md into the rules it gives an agent

4 rules. About 0 are common, 1 is distinctive, and 3 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈1

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 3

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Test-first contract: Every new method/class lands with at least a pytest (Python) or vitest/jest (TS) test file in the same turn.

    line 35
  2. Very specific:

    Multi-agent ready: All orchestrators implement the same async interface (src/backend/core/providers/orchestrators/base.py).

    line 38
  3. Distinctive:

    Use the dedicated agents for any non-trivial v2 work.

    line 69
  4. Very specific:

    [console]::beep is reserved for these two signals: Do not call it from any other tool invocation, do not bury it inside another command, …

    line 91

≈ “Common” is an estimate: at least 1 in 5 of the 3,669 Copilot instructions files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
copilot-instructions.md

Chat With Your Data (CWYD) — Repository Instructions

These instructions are always loaded. Read them before doing anything else.

Repository layout (truth)

  • cwyd-v1/ — v1 (legacy, frozen). Flask + Streamlit + Semantic Kernel + Prompt Flow + direct Azure OpenAI SDK. Do not extend. Only touch v1 to perform documented removals listed in v2/docs/development_plan.md §2.1. All v1 code, infra, docker, scripts, and tests live under cwyd-v1/.
  • Repo root (src/, infra/, docker/, scripts/, tests/, azure.yaml, pyproject.toml, package.json) — v2 (active development). FastAPI + LangGraph + Agent Framework + Foundry IQ, promoted from the old v2/ subtree to the repo root. All new work goes here.
  • infra/ (root) — v2 Bicep. The v1 Bicep lives under cwyd-v1/infra/.
  • tests/ (root) — v2 tests (shared gates, backend, frontend, functions, infra, integration, smoke). The v1 e2e/integration tests live under cwyd-v1/tests/.
  • v2/docs/ — the only tree still under v2/: v2 development plan, pillars, ADRs, bugs registry, and worklog.

Mandatory references — consult before editing

  1. v2/docs/development_plan.md — phase ordering, file paths, scope, removals, additions. Source of truth for what to build and when. Always read §0 Status snapshot + the head of §0.1 debt queue before proposing a task. As of 2026-05-11 the active phase is Phase 6 — Functions blueprints / modular RAG indexing pipeline (batch_start, batch_push, add_url, search_skill under src/functions/; ingestion-only extensions under src/functions/core/). Phases 1–5 + 5.5 are closed; #35d (FE admin merge) and #24 partial (FE SSE polish) are open and explicitly non-blocking for Phase 6. #35g (per-tenant overrides) is withdrawn as out of scope — the deployment is single-tenant, so per-tenant RuntimeConfig keying is a no-op; see ADR 0024.
  2. v2/docs/pillars_of_development.md — every new core element must declare its pillar (Stable Core, Scenario Pack, Configuration Layer, or Customization Layer) in the file/class docstring. Read-only product policy — never edited by agents.
  3. Repo memory cwyd-tech-stack.md — current stack truth (versions, services, package managers, test counts).

External pattern sources — read-only

You may fetch and read these for architectural patterns. Never copy code wholesale — adapt with attribution in a code comment when the pattern is non-trivial.

Specifically:

  • MACAE → managed-identity + RBAC + no-Key-Vault env-var pattern; agent-to-agent message bus; SSE streaming pattern.
  • CGSA → React/Vite + FastAPI plug-and-play surface; admin merged into frontend; reasoning visualization patterns.

Hard rules

  1. Step 0 — sync agent guidance before any change. Before any reorganization, refactor, or error fix, first read the agent instructions and prompt files that scope the change (this file + the relevant .github/instructions/v2-*.instructions.md). If the guidance is stale, contradicts the requested change, or is silent on a decision the change implies, propose an instruction update first and wait for user approval before touching code or other docs. Out-of-date guidance is the root cause of re-work, throwing away decisions, and re-introducing removed concepts.
  2. One unit per turn. Implement exactly one class OR one method per implementation turn. No "and while I'm here…" edits. Do not create multiple files of production code in a single turn unless they are a class + its test stub.
  3. Test-first contract. Every new method/class lands with at least a pytest (Python) or vitest/jest (TS) test file in the same turn. Tests must execute (pass or fail with a clear assertion), not just exist.
  4. Pillar awareness (no docstring header). Agents still classify every new module/class by its pillar (Stable Core, Scenario Pack, Configuration Layer, or Customization Layer) when reasoning about where a change belongs — but the classification is no longer emitted as a Pillar: / Phase: docstring header; that header requirement is retired. The pillars file (v2/docs/pillars_of_development.md) is read-only product policy — agents reference it, never edit it. Any proposed change to pillars must be raised with the user as a separate request.
  5. Plug-and-play via registry. Backend must run headless (no frontend dependency). Frontend must accept VITE_BACKEND_URL and consume the generated OpenAPI client. All swappable concerns (credentials, llm, embedders, parsers, search, chat_history, orchestrators) live under src/backend/core/providers/<domain>/ and self-register via @registry.register("key") against the generic Registry[T] in src/backend/core/registry.py. Caller code does domain.create(key, ...) — never if/elif provider dispatch, never lazy in-function imports of provider classes.
  6. Multi-agent ready. All orchestrators implement the same async interface (src/backend/core/providers/orchestrators/base.py). All emit events on the typed reasoning channel — never bury reasoning inside the answer string.
  7. Reasoning feed. SSE channels: reasoning, tool, answer, citation, error. The frontend renders reasoning in a collapsible panel; o-series output flows there.
  8. No banned tech / no removed features. Do not introduce: Streamlit, Prompt Flow, Semantic Kernel, Poetry, direct openai/AzureOpenAI SDK calls in v2, Key Vault for app secrets, one-click "Deploy to Azure" ARM button (v2 is azd-only), Azure Bot Service, Teams extension. The full removal list lives in v2/docs/development_plan.md §2.1 and is binding — never re-add a removed feature. Use Foundry IQ + RBAC + Managed Identity.
  9. Every phase ends green. azd up (or local docker compose up) must succeed at the end of each phase. Never leave a half-wired phase.
  10. Clean, modular, plug-and-play — anchored to dev_plan + pillars. v1 is spaghetti and is being replaced, never imitated. Every addition (file, package, container, sidecar, abstraction, config format) must cite (a) a task # in v2/docs/development_plan.md §3.4 or §4, and (b) a pillar in v2/docs/pillars_of_development.md. v1 (code/, docker/, infra/) is a reference only for §2.1 removals; do not copy v1 patterns. CGSA/MACAE are read-only architectural references — adapt, never wholesale-copy. Defaults: one runtime per container, no invented sidecars, no premature abstractions, plug-and-play preserved (backend-only and frontend-only profiles must both boot).
  11. Ask before changing structure. Any new top-level folder, new package in pyproject.toml/package.json, new module layout under src/**, or rename across the tree requires explicit user confirmation before the planner emits a Work Order or the implementer touches a file. Structural decisions are not for agents to make unilaterally.
  12. Naming-convention stability across languages. Once a symbol is named in source code, do not rename it casually — renames break diffs, history, and downstream references. Conventions (always followed; never invent a third style):
    • Bicep — camelCase for params, vars, modules, resources, outputs (e.g. containerAppsEnvName, acaWorkloadProfileName). Module symbolic names are camelCase nouns (backendContainerApp). Hoist any string literal repeated 2+ times to a var at the top of the section that uses it.
    • Python — snake_case for functions, methods, variables, modules; PascalCase for classes; UPPER_SNAKE_CASE for module-level constants; _leading_underscore for private. Match PEP 8 exactly. Closed-set string literals must be enum.StrEnum, not module constants. Whenever ≥2 related string literals form a closed set (type discriminators, modes, channels, status values, sibling partition keys), define class Foo(StrEnum) (Python 3.11+) and reference members instead of bare _FOO = "foo" / _BAR = "bar" constants. StrEnum subclasses str, so wire serialization (JSON, SQL params, dict keys) is unchanged and round-trip equality with raw strings still holds. Single-value constants (URLs, SQL templates, lone sentinels with no siblings) stay as UPPER_SNAKE_CASE. Pydantic Literal[...] type annotations on model fields are not affected — they are types, not runtime values. Registry-driven carve-out (added 2026-06-02 for entry-point discovery). When a settings field is typed as a StrEnum whose members are first-party keys of a Registry[T] provider domain (Hard Rule #4 dispatch surface) and that registry accepts third-party extensions via backend.core.discovery.load_entry_points("cwyd.providers.<domain>") at app startup, the field type MAY be widened to <MyEnum> | str so an operator can select a third-party-registered key via env var. Discipline: (a) the StrEnum still defines the well-known first-party set and every internal branch / comparison uses MyEnum.MEMBER — the str arm exists only so Pydantic accepts unknown registered keys; (b) validation happens at the registry boundary — <domain>_registry.registry.get(value) raises KeyError listing every registered key (first-party + third-party); (c) branches that fan out on the field membership use value in {MyEnum.A, MyEnum.B} (set-of-enum-members) — never a chain of equalities against bare strings; (d) closed-set fields that do not flow through Registry.get dispatch (env discriminators, SSE channels, status enums, partition keys, anything the codebase fully controls and that has no plugin extension point) remain hard StrEnum-only with no str arm — the carve-out applies only to settings fields whose values are registry keys. Today's registry-driven fields under this carve-out: DatabaseSettings.db_type: DbType | str (registry: providers.databases), SearchSettings.index_store: IndexStore | str (registry: providers.search). Future registry-driven settings inherit the same widening without re-amending this rule — the carve-out is structural, not field-by-field. Types are always available at runtime — if TYPE_CHECKING: and from __future__ import annotations are banned in v2/. All imports go in the regular import block; all annotations resolve to real symbols at class-definition time. No string-quoted forward references — use typing.Self (PEP 673) for self-refs, and import every type a module annotates with. Rationale: lazy / quoted annotations created two recurring failure modes during cleanup audit batch 2 — (a) silent drift where the runtime symbol disappeared but the string annotation kept type-checking green; (b) Pydantic v2 + LangGraph wiring that introspects __annotations__ at runtime and crashes on unresolved forward refs. No exceptions. If a genuine circular import surfaces (the only legitimate historical use case), fix it structurally by extracting the shared type to a leaf module (e.g. src/backend/core/types.py or a new src/backend/core/contracts/) — never reach for the guard. Such an extraction is a structural change and triggers Hard Rule #10 (ask the user first). The v2-wide invariant is enforced by tests/shared/test_no_type_checking_or_future_annotations.py (AST walk over every *.py in the code tree). Static type-checker enforcement is wired via CI (pyright --strict for src/backend/** + src/functions/core/**; see v2/docs/development_plan.old.md §0.1 Q13 for the original wiring trail; the live status tracker lives in v2/docs/development_plan.md §2.3). Any only at boundaries. pyright --strict is configured on src/backend/** + src/functions/core/**; CI fails on any drift from 0 errors / 0 warnings / 0 information. Explicit Any annotations are permitted only at three boundary classes: (a) third-party SDK responses whose shape we deliberately don't narrow (dict[str, Any] rows from asyncpg/cosmosdb/azure_search, openai/agent-framework Protocol stubs returning Any); (b) Pydantic metadata: dict[str, Any] fields on Chunk / *Event / ConversationRequest etc. where extensibility is the design; (c) **kwargs: Any on SDK Protocol stubs only — never in internal plumbing. Every cast(...) and every # pyright: ignore[...] / # type: ignore[...] must either (i) have an inline comment naming the SDK boundary it crosses, or (ii) map to a tracked debt row in v2/docs/development_plan.md §0.1. See also Hard Rule #15 (closed-set dict returns must be typed models) — together #11 and #15 are the type-discipline pair: #11 governs closed-set string literals (use StrEnum) and internal plumbing (no Any); #15 governs closed-set dict returns (use a BaseModel). The same boundary carve-outs (third-party SDK responses, externally-defined protocol payloads) apply to both.
    • TypeScript — camelCase for variables, functions, methods; PascalCase for types, interfaces, classes, React components; UPPER_SNAKE_CASE for module-level constants; no I-prefix on interfaces. File names: all first-party files under src/frontend/src/ and tests/frontend/ use .tsx regardless of JSX content (camelCase.tsx for utilities / hooks / api clients / models; PascalCase.tsx for React components). Tooling configs (vite.config.ts, tsconfig.json, etc.) stay at their tool-pinned names. Rationale + the consuming ADR are at v2/docs/adr/0013-frontend-strict-ts-and-tsx-everywhere.md.
    • Cross-cutting — environment variables are UPPER_SNAKE_CASE and prefixed (AZURE_*, VITE_*, CWYD_*). Azure resource names follow <type-abbrev>-<solutionSuffix> per infra/abbreviations.json. Names of public APIs (HTTP routes, OpenAPI operationIds, SSE event types, OrchestratorEvent fields) require user confirmation to rename once shipped.
  13. No mid-phase back-fills. Debt items discovered while working on Phase N are appended to v2/docs/development_plan.md §0.1 Debt Queue, not implemented inline. The queue is cleared in a single dedicated audit turn at the end of each phase. Within a phase, tasks execute in numeric order from §4 — no "and while we're here" additions, no out-of-order pulls from later phases. The only exception: a current task literally cannot proceed without the missed item; in that case a single back-fill turn is allowed and must be annotated in §0.1 with reason. Defect-versus-debt split (paired with Hard Rule #19). §0.1/§0.2 hold phase debt and tasks — deferred work, refactors, scoped follow-ups on the end-of-phase audit cadence. A defect (wrong or broken runtime behavior) is recorded in v2/docs/bugs.md, the canonical defect registry, not in §0.1; when a defect needs phase-audit visibility, §0.1 keeps a one-line pointer row referencing its BUG-#### id and the full detail stays in bugs.md. There is one source of truth per concern, never two.
  14. __init__.py is a package marker. The only permitted content is the module docstring (with the Pillar: / Phase: header). Forbidden: class/function definitions, instantiations (no registry = Registry(...)), __all__ lists, re-export imports (from .x import Y), side-effect imports (from . import concrete_a), module-level constants. Anything that needs that location (the Registry[...] instance for a provider domain, the eager imports that fire @registry.register(...), genuine domain helpers like credentials.select_default) lives in a sibling module — by convention registry.py for provider domains. Callers import the submodule explicitly: from backend.core.providers.<domain> import registry as <domain>_registry, then <domain>_registry.registry.get(key)(**kwargs). No create(key, **kwargs) sugar — it added zero behavior over Registry.get and was removed on 2026-05-20. Enforced by tests/shared/test_init_files_are_marker_only.py (AST walk; only allowed top-level node is ast.Expr(ast.Constant(str))). Rationale + migration plan + per-domain ledger live in v2/docs/development_plan.md §2.4 — that section is the single source of truth for this invariant.
  15. SDK boundary resilience. Every external SDK call (AzureError umbrella for Azure SDKs, openai.APIError, asyncpg.PostgresError, httpx.HTTPError, azure.core.exceptions.HttpResponseError) crossed inside a provider, pipeline, tool, router, or Functions blueprint must be wrapped in try/except <SDK error umbrella> with three obligations: (a) logger.exception(...) with structured extra={"operation": "<verb>", "provider": "<key>", ...domain-specific snake_case keys}; (b) re-raise the original exception (or wrap in a domain error that preserves __cause__); (c) never silently swallow — silent excepts are forbidden under all conditions and enforced by tests/test_no_silent_excepts.py. Cleanup paths (finally, async with __aexit__) own resource release; they do not own error reporting. Status checks (health, diagnostics) classify failures as pass | degraded | fail per src/backend/models/health.py and never let the SDK exception escape the router. Functions triggers have type-specific contracts: queue triggers return None and re-raise so the host's retry → poison policy engages (@log_queue_errors in src/functions/core/); HTTP triggers always return func.HttpResponse via @map_function_exceptions which owns the ValidationError → 422 / AzureError → 502 / Exception → 500 ladder. See .github/instructions/v2-backend-core.instructions.md §Resilience for the canonical code pattern.
  16. Closed-set dict returns must be typed models. When a function returns a dict (or list[dict]) whose keys are a fixed, known-at-author-time schema, define a Pydantic v2 BaseModel (frozen, extra="forbid") and return that, not dict[str, object] / dict[str, Any]. Wire-shape conversion happens at the SDK boundary via model.model_dump(...) — the model is the source of truth for the schema, the dict is a transport detail. Trigger heuristic: "if you can write the keys as a literal at the call site, the keys are fixed" — {"id": chunk.id, "content": chunk.content, "title": chunk.source, "content_vector": vector} is a struct; {header_name: header_value for header_name in dynamic_headers} is a dict. Even arity 1 earns a model — there is no "one field doesn't need a model" carve-out, because that door always becomes "two fields don't either." Boundary exceptions (no model required): (a) third-party SDK responses — dict[str, Any] rows from asyncpg, azure.cosmos, azure.search.documents per Hard Rule #11(a); (b) externally-defined protocol payloads whose shape is owned by another party — Easy Auth x-ms-client-principal claims blob, JWT payloads, OpenAPI extension dicts; (c) stdlib / SDK structural arguments typed Mapping[str, object] — logging.Logger.<level>(..., extra=...), azure.functions.HttpResponse(headers=...) — when the receiver requires a Mapping AND the caller spreads with ** to merge ad-hoc per-call fields; (d) test capture buffers — captured: dict[str, object] = {} accumulators in test stubs are not "returns" and are not covered. Helpers under boundary (c) must either be a single-call inline literal, or a constructor-style helper whose docstring cites this rule + the SDK boundary it crosses. Enforced by tests/shared/test_no_anonymous_dict_returns.py (AST walk over src/**/*.py): every FunctionDef.returns whose annotation matches dict[str, ...] (or wrappers like list[dict[...]], dict[...] | None) must either appear in the allow-list (registry of (module_path, function_qualname) tuples maintained alongside the gate, each with a one-line justification) or trigger a failing test. The allow-list grows only via a tracked debt-queue row in v2/docs/development_plan.md §0.1.
  17. No process narrative in production code. Comments and docstrings under src/** describe what the code is — not how it got there, what unit shipped it, what phase it lives in, or what work lands next. The repo's process state lives in v2/docs/development_plan.md, commit history, and tracked debt rows — not in source files that rot the moment a phase advances. Forbidden in production-code comments + docstrings: (a) forward-looking unit IDs and "next-work" pointers ("U11 lands next", "X lands in Phase 7", "future smoke / e2e tests can assert"); (b) bare unit IDs in any role (the token \bU\d+[a-z]?\b — U7g, U10c etc. — even inside a Phase header tail, even as a cross-module pointer parenthetical); (b2) dev_plan §4 task numbers (the token \btask\s+#\d+\b — task #20, task #41 etc. — even inside a Phase header tail, even as a parenthetical next to a live symbol name); (c) phase roll-forward narrative ("the Phase 6 blueprint set landed so far", "as of <date>", "so far" adjacent to Phase); (d) dev_plan section citations ("per [v2/docs/development_plan.md] §4.6.1" — the dev_plan is the work-tracker, not API docs); (e) self-narrative ("added in this turn", "removed in CU-009b"); (f) process date stamps ("2026-05-28", "REFACTOR-B (2026-05-06)") — git blame is the source of truth. Permitted (carve-outs):

    • inline # pyright: ignore[...] debt citations carrying a <DEBT-ID> token (e.g. # Debt (dev_plan §0.1 U8i-EMBEDDER-CTOR-DEBT): ...) — the gate carves out any line containing the substring -DEBT, anchoring the comment to a tracked debt row (Hard Rule #11/#15 contract).
    • standing-policy anchors ("per Hard Rule #15", "per Hard Rule #11(a)") — these cite live, stable policy that lives in a stable doc, not transient process.
    • architectural cross-module pointers naming live symbols ("Companion to functions.add_url.blueprint", "Consumed by the HTTP trigger in blueprint.py") — these describe relationships between symbols that still exist, with no unit-ID tag attached.
    • Azure SDK API version literals ("2024-12-01-preview", "api version 2025-04-01") — these are technical content the SDK pins on, not process dates; the gate distinguishes them by the trailing -preview / -ga suffix or by an api version context phrase anywhere in the surrounding docstring or comment block.

    Enforced by tests/shared/test_no_process_narrative_in_src.py (per-file gate; AST-walks docstrings + tokenize-walks comments under src/, runs a fixed regex set, applies the carve-outs above at line granularity except for the API version carve-out which is block-scoped). The gate has no growable allow-list — fix the comment, do not exempt the file. If a genuinely new carve-out class surfaces, raise it as a Hard Rule #16 amendment request before adding it to the gate.

  18. All imports at module top. All import / from X import Y statements must live at the top of the module, before any non-import statement (the only allowed prelude is the module docstring + the Pillar: / Phase: header it carries per Hard Rule #3). Forbidden: (a) imports inside def / async def / class bodies — no lazy imports of any kind, stdlib or third-party, even for "dev-ergonomics" profile splits (every package the v2 backend or functions can hit is already declared in pyproject.toml and installs unconditionally); (b) imports inside module-level if/else or try/except branches — no soft-dependency try/except ImportError shims, no profile-conditional if backend_only: import … branches; (c) if TYPE_CHECKING: blocks (already banned by Hard Rule #11; reiterated here so the two import rules read together); (d) from __future__ import annotations (also banned by #11). Imports follow PEP 8 grouping (stdlib → third-party → first-party) with a blank line between groups; ordering within a group follows the codebase's existing tooling defaults (ruff/isort). Circular imports are not a carve-out — fix them structurally by extracting the shared type/protocol to a leaf module per Hard Rule #11 precedent (src/backend/core/types.py or a new per-domain leaf under src/backend/core/), then top-import from both call sites. Such an extraction is a structural change and triggers Hard Rule #10 (ask the user first). Absolute rule with zero carve-outs — the gate's _EXEMPTIONS set is frozenset() and stays that way. Enforced by tests/shared/test_imports_at_top_only.py (AST walk over every *.py under src/ + scripts/ + tests/; every ast.Import / ast.ImportFrom node must have Module as its enclosing scope AND be preceded in module body only by other imports or by the module docstring). The gate has no growable allow-list — fix the import site, do not exempt the file. Cross-references: Hard Rule #11 (the TYPE_CHECKING / __future__ half of the same import discipline); tracked debt row IMPORTS-AT-TOP-DEBT in v2/docs/development_plan.md §0.1 (records the gate-landing and one-file-per-turn cleanup of pre-existing in-function imports across tests/).
  19. No environment-specific content in tracked files. Tracked files (source, tests, docs, ADRs, runbooks, Bicep / Terraform comments, fixtures, CI workflows) contain only generic development and deployment guidance. Forbidden in any tracked file: Azure subscription IDs, tenant IDs, UAMI client / principal IDs, Entra object IDs, user UPNs, resource group names, azd env names, deployment suffixes, individual resource names that embed the suffix, real internal IP addresses, env-specific FQDNs (Container Apps Environment domains, OpenAI account hostnames, etc.), local OS user-profile paths, and any SAS / connection-string / token that ties to a real account. Real values live exclusively in .azure/<AZD_ENV_NAME>/.env (gitignored) and the operator's az / azd session — discoverable via azd env get-values. Examples in docs / fixtures use the placeholder convention defined in v2/docs/adr/0019-no-env-specific-content-in-tracked-files.md: <AZURE_SUBSCRIPTION_ID>, <AZURE_TENANT_ID>, <AZURE_PRINCIPAL_UPN>, <AZURE_PRINCIPAL_OBJECT_ID>, <AZURE_UAMI_CLIENT_ID>, <AZURE_UAMI_PRINCIPAL_ID>, <RESOURCE_GROUP>, <AZD_ENV_NAME>, <SUFFIX>, <DATA_SUFFIX>, <REGION>, <ACA_ENV_DOMAIN>, <APPI_NAME>, <APPI_RESOURCE_GROUP>, <SAMPLE_STORAGE_ACCOUNT>, <INTERNAL_IP>. Carve-outs (allowed unchanged): RFC 1918 / IANA-reserved IP literals (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 127.0.0.1, 0.0.0.0, 169.254.0.0/16); AVM / SDK example placeholders inherited from upstream docs; all-zero / built-in role-definition GUIDs; synthetic test-fixture identifiers that obviously cannot be real (e.g. the cwyd001 suffix in tests/**, hard-coded mock UUIDs); public Microsoft sample infrastructure owned by the upstream repo (e.g. cwydcontainerreg.azurecr.io); API version literals (already carved out by Hard Rule #16 — the Azure SDK API version literals carve-out). Local per-developer artifacts (IDE-generated bicep-errors.txt, transient logs) must be added to .gitignore, not deleted-and-re-added. See ADR-0019 for the full rationale, exclusion list, and audit recipe.
  20. Durable file-based tracking — plans, daily work, and bugs never live in agent memory alone. Three repo-tracked artifacts are the canonical record; agent session memory is a scratchpad, never the system of record (history trapped in memory is lost when the session ends — this rule exists because that happened). (a) Daily worklog — v2/docs/worklog/YYYY-MM-DD.md, one file per working day named by the real current date (verify the date before naming the file; append to the same file as the day progresses, never open a second file for the same date). It captures the day's plan, completed work, bugs found/fixed, decisions, and next steps. The convention lives in v2/docs/worklog/README.md. (b) Defect registry — v2/docs/bugs.md, the canonical log of every observed defect (wrong or broken runtime behavior) with sequential zero-padded BUG-#### ids, root cause, and fix; closed-set Area/Severity/Status fields. See the defect-versus-debt split in Hard Rule #12. (c) Plans / Work Orders — any non-trivial plan, including a cwyd-planner Work Order, is written to the day's worklog in addition to any memory note, so the plan survives the session. The placeholder rule (Hard Rule #18) applies to all three. Whenever a plan is produced, a working day begins, or a bug is found/fixed, the corresponding repo file is created or updated in the same turn — not deferred to memory.
  21. Shared, standardized citation-format contract — scales to N orchestrators (ADR 0026). The orchestrator set is open (today langgraph + agent_framework; more register per Hard Rule #4), so the grounding prompt and the citation-response format are shared infrastructure defined once, never re-authored per orchestrator — registering the Nth orchestrator must add zero new prompt text and zero new formatter. Three invariants. (R1) One prompt input point. Every orchestrator grounds through resolve_cwyd_instructions(...) over the shared CWYD_DEFAULT_BODY; the fixed CWYD_GUARDRAIL owns the citation-format directive and the no-context fallback string. An orchestrator MUST NOT define its own grounding / system prompt or its own citation instruction — there is one prompt source for all N orchestrators. (R2) One response-format point. All citation shaping lives in src/backend/core/tools/citations.py — format_sources_block (client-side [docN] injection) and normalize_kb_citations (native 【N:M†source】 rewrite) — and both emit the same inline [docN] marker + Citation model on the typed citation SSE channel (Hard Rule #6). An orchestrator's run() produces (answer, citations) and delegates formatting to citations.py; it never formats markers inline, never invents a citation shape, never adds a second formatter. (R3) Backend-agnostic formatting; retrieval keyed by storage. Retrieval is dispatched by index_store through the registry (Hard Rule #4), but the emitted citation format is identical across Azure AI Search and pgvector. Every orchestrator/store cell is served: agent_framework + pgvector grounds app-side over BaseSearch.search (no Foundry IQ KB) through the same shared seam (ADR 0027 supersedes the ADR 0022 rejection rule), never given a divergent formatter or a silent fallback. Rationale: minimal maintenance — one prompt, one formatter, N orchestrators. Any new-orchestrator change that introduces a second prompt source or a second citation formatter violates this rule. Editing-surface detail (concrete function names + file paths) lives in .github/instructions/v2-backend-core.instructions.md §Orchestrator contract → Citations.

Workflow contract

Use the dedicated agents for any non-trivial v2 work. They enforce the rules above:

  • cwyd-planner — research + produce a one-unit work order (read-only).
  • cwyd-implementer — write exactly one unit + test stub.
  • cwyd-tester — fill the test, run it, report.

For trivial single-line edits, you may proceed directly — but still respect the test-first rule.

Local development

  • Python: uv sync from the repo root.
  • v2 dev stack: docker compose -f docker/docker-compose.dev.yml up.
  • v2 backend-only: docker compose -f docker/docker-compose.dev.yml --profile backend-only up.
  • v2 frontend-only: docker compose -f docker/docker-compose.dev.yml --profile frontend-only up (set VITE_BACKEND_URL).
  • CI validation image: docker build -f docker/Dockerfile.ci-validate -t cwyd-ci . then run.

Session conventions

  • End-of-turn beep is the agent's responsibility. GitHub Copilot does not execute Claude Code-style ~/.claude/settings.json Stop hooks, so the agent must emit the chime as its final tool call before handing the conversation back to the user. One call per turn, no exceptions, no duplicates:
    • Windows (default): run_in_terminal (sync, ~500ms) with [console]::beep(880,200); [console]::beep(1175,250) — two ascending tones.
  • Mid-turn waits for user input require a different beep. Whenever the agent is about to block on the user before the turn ends (calling vscode_askQuestions, sending an interactive prompt to a terminal via send_to_terminal, or otherwise pausing for a human reply mid-task), the agent must first emit a single low beep:
    • Windows (default): run_in_terminal with [console]::beep(660,250) (sync, ~250ms, distinct from the two-tone end-of-turn chime).
  • [console]::beep is reserved for these two signals. Do not call it from any other tool invocation, do not bury it inside another command, and do not skip it when wrapping up.

Download now (ZIP)

Trending

Quiet since March.thin dataabout the whole repository

Dec 2025: 0 mentionsJan 2026: 0 mentionsFeb 2026: 0 mentionsMar 2026: 1 mentionApr 2026: 0 mentionsMay 2026: 0 mentionsJun 2026: 0 mentionsJul 2026: 0 mentionsAug 2026: 0 mentionsSep 2026: 0 mentionsOct 2026: 0 mentionsNov 2026: 0 mentions
Dec 2025Jun 2026Nov 2026
Mentions a month of the Azure-Samples/chat-with-your-data-solution-accelerator repository that our weekly crawl found: only 12 in all, so this is a hint, not a trend. There is no adoption data for this file yet.

Who's talking about Azure-Samples/chat-with-your-data-solution-accelerator

The biggest 5 of 12 mentions linking to the repository that our crawl found. Each line is their own headline.

See all 12

Talked about on GitHub and Bluesky (12 times).

On GitHub · 11

6 more on GitHub
  • Where files are headingNew Copilot instructions files have more rules about branches and pull requests, and fewer about code style.

    Of the Copilot instructions files we read, the 2,297 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

Reviews can't be read right now.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.