diff --git a/.github/instructions/adr.instructions.md b/.github/instructions/adr.instructions.md new file mode 100644 index 0000000..88570d9 --- /dev/null +++ b/.github/instructions/adr.instructions.md @@ -0,0 +1,12 @@ +--- +description: "Use when editing files under docs/adr/. Enforces ADR immutability and supersession rules." +applyTo: "docs/adr/**" +--- +# ADR Editing Rules + +ADRs are append-only history. To create a new ADR, use the `new-adr` skill. + +- **Accepted ADRs are immutable.** Do not change `Context`, `Decision Drivers`, `Considered Options`, or `Decision Outcome` after acceptance — write a new ADR that supersedes instead. +- **Permitted edits to accepted ADRs**: typo/grammar fixes, adding links to related ADRs, and updating the `status` field as part of supersession or deprecation. +- **Superseding**: set the predecessor's frontmatter to `status: superseded by ADR-NNNN`, update its `date`, and add a back-link in its body. Never delete the predecessor. +- **Filenames are permanent.** Do not renumber or rename existing ADRs even if numbers have gaps. diff --git a/.github/instructions/analyzers.instructions.md b/.github/instructions/analyzers.instructions.md new file mode 100644 index 0000000..8be2e49 --- /dev/null +++ b/.github/instructions/analyzers.instructions.md @@ -0,0 +1,31 @@ +--- +description: "Use when editing analyzer or code-style configuration: .editorconfig, .globalconfig, stylecop.json, .DotSettings." +applyTo: ".editorconfig,.globalconfig,stylecop.json,*.DotSettings" +--- +# Analyzer & Style Configuration + +These files are the source of truth for code style and analyzer severity. Changes have wide blast radius. + +> [!IMPORTANT] +> **Ask for explicit permission before editing.** State the rule(s), the new severity, and the rationale; wait for approval. Do not touch these files as part of unrelated work. The stated rationale belongs in the PR description. + +## Guardrails + +- **Do not relax a rule to silence a single occurrence.** Fix the code, or suppress narrowly with a justification comment in the offending file. +- New rules start at the **strictest justifiable severity**; downgrade later only with evidence. +- Never disable an entire analyzer category. + +## File Roles + +| File | Purpose | +| --- | --- | +| `.editorconfig` | Per-language formatting, naming rules, and analyzer severities scoped by file glob. | +| `.globalconfig` | Repo-wide analyzer severities not needing file-pattern scoping. | +| `stylecop.json` | StyleCop-specific settings (file headers, ordering, documentation). | +| `Solution.sln.DotSettings` | ReSharper/Rider mirror — **derived**, follows the others; do not lead changes here. | + +## Coordination + +- **A rule has one source of truth** across `.editorconfig`, `.globalconfig`, and `stylecop.json` — never duplicate. +- When a rule must appear in multiple files for IDE parity (e.g., mirrored to `Solution.sln.DotSettings`), severities **must match exactly**. Drift is a bug. +- StyleCop rules: configuration in `stylecop.json`, severity in `.editorconfig`. diff --git a/.github/instructions/documentation.instructions.md b/.github/instructions/documentation.instructions.md new file mode 100644 index 0000000..a320d58 --- /dev/null +++ b/.github/instructions/documentation.instructions.md @@ -0,0 +1,47 @@ +--- +description: "README.md authoring: structure, callouts, diagrams, and assets." +applyTo: "**/README.md" +--- +# README Style + +## Structure + +Follow this ordering when sections apply; omit those that don't: + +1. **Title** (`# `) and one-sentence purpose. +1. **Getting Started** — minimal commands to consume or run the project. +1. **Features** / **Capabilities** — bulleted highlights. +1. **Configuration** — build args, environment variables, MSBuild properties. +1. **Usage Examples** — code or CLI snippets. +1. **Recommendations** / **Caveats** — known limitations, in callouts. +1. **Reference link definitions** at the bottom. + +## Conventions + +- Do not hard-wrap prose; one paragraph per line. +- Ordered lists: write every item as `1.` and let the renderer auto-number. +- Use reference-style links for external URLs in prose, with definitions at the bottom of the file. Inline links are fine in tables and for in-repo relative paths. +- Keep code examples minimal — strip boilerplate unless it is the point. + +## Callouts + +Use [GitHub-flavoured alerts](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts) for emphasis; reserve plain `>` blockquotes for quoted text. + +| Alert | Use for | +| --- | --- | +| `> [!NOTE]` | Neutral context the reader should know | +| `> [!TIP]` | Optional best-practice | +| `> [!IMPORTANT]` | Required for correct usage | +| `> [!WARNING]` | Risk of breakage or data loss | +| `> [!CAUTION]` | Security or destructive-action risk | + +## Mermaid Diagrams + +- Match diagram type to intent: `flowchart` (processes), `sequenceDiagram` (interactions over time), `classDiagram` (type relationships), `erDiagram` (data models). +- Keep diagrams under ~15 nodes; split larger ones. +- No custom styling — defaults render in both light and dark modes. + +## Assets + +- Repo-wide assets in `/docs/assets/`; project-scoped assets in the project's own `docs/assets/`. +- Prefer **SVG** for diagrams and logos; PNG only for raster screenshots. diff --git a/.github/instructions/observability.instructions.md b/.github/instructions/observability.instructions.md new file mode 100644 index 0000000..338fae4 --- /dev/null +++ b/.github/instructions/observability.instructions.md @@ -0,0 +1,26 @@ +--- +description: "Use when adding tracing, metrics, or feature flags: ActivitySource/Meter setup, semantic-convention tags, OTLP exporter config, OpenFeature client usage and flag-key naming." +--- +# Observability & Feature Flags + +## OpenTelemetry + +- One **`ActivitySource`** per logical component, named `Kritikos..`. Declare as `static readonly` on a dedicated `Telemetry` static class within the component (avoid scattering sources across every type). +- One **`Meter`** per component, alongside its `ActivitySource`. The names **may** match when both belong to the same component. +- Always wrap `StartActivity(...)` in a `using` — leaked activities skew downstream timings. +- **Activity names**: + - When [OpenTelemetry semantic conventions](https://opentelemetry.io/docs/specs/semconv/) cover the operation (HTTP, DB, messaging, RPC), follow semconv exactly (`HTTP GET`, `db.query`, `messaging.process`). + - For custom operations not covered by semconv: `` in PascalCase (`ProcessOrder`, `LoadConfiguration`). Avoid generic verbs like `Handle` or `Execute`. +- **Tags / attributes**: lowercase dotted, follow semantic conventions where they exist (`http.request.method`, `db.system`, `messaging.destination.name`). Project-specific tags use the `kritikos..` namespace. +- **Metric instruments**: snake_case names with units in the suffix (`orders_processed_total`, `request_duration_seconds`). Always set `unit` and `description` at creation. +- **Resource attributes**: when a shared registration helper is added, it should populate `service.name` from `AssemblyName` and `service.version` from the GitVersion-computed `InformationalVersion`. Do not set them manually at call sites. +- **Exporter**: OTLP over gRPC, endpoint via `OTEL_EXPORTER_OTLP_ENDPOINT`. Do not register console exporters in `Release` builds. +- **Sampling**: parent-based with `TraceIdRatioBased` (1.0 in dev, configurable in prod). Do not set custom samplers without justification. + +## OpenFeature + +- Resolve flags through the configured OpenFeature client (obtained via DI, or `Api.Instance.GetClient()` if no DI integration is wired). Never call provider SDKs directly. +- **Flag keys**: `kebab-case`, prefixed by domain (`orders-allow-partial-fulfilment`, `auth-require-mfa`). Keys are stable contracts — treat renames like API breaking changes. +- Always pass `defaultValue:` — `client.GetBooleanValue("flag", defaultValue: false, context)`. +- **Evaluation context** is built once per request via the configured context provider — do not assemble ad-hoc contexts inline. +- Long-lived flags (kill switches, licensing) live in code; short-lived flags (rollouts, experiments) must have a removal date in their description and a tracking issue. diff --git a/.github/instructions/solution.instructions.md b/.github/instructions/solution.instructions.md new file mode 100644 index 0000000..14ca646 --- /dev/null +++ b/.github/instructions/solution.instructions.md @@ -0,0 +1,28 @@ +--- +description: "Use when adding, removing, or moving projects, or when editing the solution file or VS Code workspace." +applyTo: "*.slnx,*.sln,Solution.code-workspace" +--- +# Solution Conventions + +`Solution.slnx` (XML) is the canonical solution format. The legacy `.sln` is not used; do not regenerate it. + +## Adding & Removing Entries + +Any project, configuration, or asset file added to, removed from, or renamed in a tracked location **must** be reflected in `Solution.slnx` in the same commit. New top-level folders also require an entry in `Solution.code-workspace`. + +Place entries in the virtual folder matching the on-disk location: + +| On-disk location | Virtual folder | +| --- | --- | +| `src/**`, `samples/**`, `tests/**` (projects + their `Directory.Build.props`) | `/src/`, `/samples/`, `/tests/` | +| Repo-root config files (`.editorconfig`, `Directory.*.props`, `GitVersion.yml`, etc.) | `/Configuration/` | +| Repo-root assets (`README.md`, `LICENSE.md`, `icon.png`, logos) | `/Assets/` | + +Reserved virtual folder names must not be renamed. + +## Renames + +- Update the `.slnx` entry, the on-disk path, and any `ProjectReference` paths in dependent projects in the same commit. +- Never leave dangling `` or project entries. + +After any `.slnx` change, run `dotnet build` to confirm all referenced projects load.