diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 3b63c702..d023106f 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -4,17 +4,25 @@ You are operating in a multi-repo, documentation-first architecture. You MUST STRICTLY follow this protocol for every response. Failure to do so will break the workspace rules. 1. **MANDATORY OUTPUT PREFIX:** Your response MUST begin on the very first line with this format: - `[LOADED_DOCS: N files (+K this turn: )]` + `[LOADED_DOCS: N files (+K this turn: )]` - `N` = total count of `.md` files currently in your context (across all loaded docs in this conversation) - `K` = count of `.md` files newly loaded during THIS response (may be 0) - - If `K > 0`: list the newly loaded **basenames only** (no paths) after `:` + - If `K > 0`: list the newly loaded files as **shortest unique short names** (see naming rule below) - If `K = 0`: write `[LOADED_DOCS: N files, no new loads]` - If `N = 0`: write `[LOADED_DOCS: NONE]` + **Short-name rule (for each loaded `.md` file):** + - **Default:** use the basename only. Works for all topic-prefixed companions (`LOGGING_ISSUES.md`, `BINARY_FEATURES.md`) and flat single-file topics (`ARCHITECTURE.md`, `GLOSSARY.md`, `CONVENTIONS.md`) — these are already unique. + - **For `README.md` files:** always include the immediate parent folder as prefix → `TOPIC/README.md` (e.g., `LOGGING/README.md`, `BINARY/README.md`). Never write a bare `README.md` in the prefix because multiple folders have one. + - **Cross-project disambiguation:** if two files share the same short name (rare — e.g., `docs/README.md` from two different projects), extend the prefix one more level: `PROJECT/docs/README.md`. Always use the shortest unique form. + - **Never use absolute paths.** Never include the `.github/` prefix for `copilot-instructions.md` — the `.github/` location is implicit. When multiple are loaded simultaneously (typical in `protocol-audit`), apply the cross-project disambiguation above: `AyCode.Core/copilot-instructions.md`, `FruitBankHybridApp/copilot-instructions.md`, etc. + **Examples:** - `[LOADED_DOCS: NONE]` — nothing loaded yet - `[LOADED_DOCS: 1 files, no new loads]` — only `copilot-instructions.md` loaded earlier, nothing new this turn - - `[LOADED_DOCS: 4 files (+3 this turn: LOGGING.md, LOGGING_ISSUES.md, LOGGING_TODO.md)]` — 3 new this turn + - `[LOADED_DOCS: 4 files (+3 this turn: LOGGING/README.md, LOGGING_ISSUES.md, LOGGING_TODO.md)]` — logger topic folder loaded + - `[LOADED_DOCS: 7 files (+3 this turn: SIGNALR/README.md, SIGNALR_ISSUES.md, SIGNALR_TODO.md)]` — SignalR topic loaded (LOGGING was already in context) + - `[LOADED_DOCS: 5 files (+2 this turn: ARCHITECTURE.md, GLOSSARY.md)]` — top-level reference docs loaded (flat, no folder prefix needed) This prefix is MANDATORY on **EVERY** response (not just the first, not just when loading happens). It serves two purposes: **(a)** user-visible compliance signal, and **(b)** self-commitment for the no-re-read rule — in subsequent turns you read your own prior prefix from the conversation to enforce Rule #3. Dropping the prefix breaks both. @@ -51,6 +59,22 @@ You are operating in a multi-repo, documentation-first architecture. You MUST ST 5. **EXPLICIT CONSENT FOR MODIFICATIONS:** NEVER rewrite, create, or delete any file (code, documentation, configuration, memory, or otherwise) without the user's explicit permission. If the user does not specifically request a code modification (e.g., using phrases like "we are just thinking," "what do you think," "let's plan"), you MUST ONLY provide text-based analysis and planning. You are FORBIDDEN from using file-modifying tools (`replace_string_in_file`, `edit_file`, `create_file`, etc.) until the user explicitly says "ok", "go ahead", "implement", or a similar unambiguous approval. +## Session Setup + +**Mandatory reads at session start** — in addition to this `copilot-instructions.md`, the agent MUST load the three workspace skills' `SKILL.md` files: + +- `docs-discovery/SKILL.md` — **reactive** (triggers on any domain question — must be ready BEFORE the first domain query arrives) +- `docs-check/SKILL.md` — **reactive** (triggers at the end of every code-modifying response) +- `protocol-audit/SKILL.md` — **on-demand** (triggers on explicit "audit protocol" command) + +**Path resolution**: if this repo is the canonical protocol host (see `@repo` block below — typically AyCode.Core), the paths are local: `.github/skills//SKILL.md`. Otherwise, prefix with this repo's `own-dep-repos` AyCode.Core path (see the `## Shared Agent Skills` section below for explicit paths). + +**Why mandatory**: workspace skills are NOT in Claude Code's native skill-registry / system-reminder. Without pre-loading their `SKILL.md` content, the agent cannot reliably recognize implicit triggers (e.g., "domain question → invoke docs-discovery" at the moment the question arrives, not retroactively). Pre-loading is a **one-time cost** per session (~10-13K tokens); Rule #3 (no-re-read) prevents repeated reads; re-read only if Rule #4 (Context Recovery) fires. + +**Amortization — critical, do NOT re-evaluate per-turn**: the Session Setup cost is measured over the ENTIRE session, not per single turn. A typical session has many turns; the first domain question alone already recoups the investment (alternative — repeated source-code `Grep`/`Read` per turn — costs 10-20K tokens *per turn* with lower output quality). Do NOT flag pre-loaded content as "wasteful" for turns that don't invoke it — the design depends on cross-turn amortization + Rule #3 (no-re-read) + on-demand specificity of Rule #4 (Context Recovery). This amortization is the **central token-economics principle** of the entire protocol stack. + +The first response's `[LOADED_DOCS: ...]` prefix must reflect **4 files** (this `copilot-instructions.md` + 3 SKILL.md). + ## Workspace Dependencies # own-dep-repos: "name: path" — paths are relative to this repo root (.github/..) @repo { @@ -74,7 +98,7 @@ You are operating in a multi-repo, documentation-first architecture. You MUST ST ## Shared Agent Skills -Skills defined in other repos that can be referenced from here: +Skills defined in other repos. **All three are pre-loaded at session start per the `## Session Setup` section above** (mandatory — ensures implicit triggers fire reliably): - **protocol-audit** — Cross-repo consistency audit for `.github/copilot-instructions.md` across all 5 repos. Location: `AyCode.Core/.github/skills/protocol-audit/SKILL.md` @@ -84,6 +108,10 @@ Skills defined in other repos that can be referenced from here: Location: `AyCode.Core/.github/skills/docs-discovery/SKILL.md` (see `own-dep-repos` above for the relative path to AyCode.Core) **Invoke proactively** before any domain-related coding task (see "Documentation-first coding" below). Honours the active repo's **no-re-read** rule. +- **docs-check** — Evaluate loaded `.md` files at the end of every code-modifying response: drift vs code, missing topic coverage, csproj-glob registration gaps for new `.md` files, and new issue/TODO candidates. Emits the `[DOCUMENTATION CHECK]` section. + Location: `AyCode.Core/.github/skills/docs-check/SKILL.md` + **Invoke at the end of every code-modifying response.** Read-only on loaded docs; all patches surface as proposals (Rule #5 approval required). + ## Protocol History Cumulative log of LLM-protocol decisions (rule changes, new skills, structural shifts): @@ -119,15 +147,12 @@ Before running any source-code `Grep` / `get_file` / `code_search` in response t 11. Do not suggest removal/rollback as a solution — find a fix for the problem. 12. All AyCode references are via **DLL** (not ProjectReference) — this is intentional. nopCommerce 4.80.9 requirement. 13. **No redundant code** — before writing new logic, check whether similar methods already exist in the current context. Reuse or extract shared logic into smaller methods rather than duplicating. -14. **Keep all .md documentation in sync (PASSIVE DETECTION & ASK FIRST)** — If you notice *any contradiction, error, or missing information* between the code and your currently loaded `.md` files, **briefly notify the user and ask for permission before making changes**. Do NOT automatically update `.md` files or trigger new searches yet. Once the user approves, you may actively search, read, and update the necessary docs in the correct layer. -**Identify missing documentation:** If you notice during your task that a frequently used pattern, underlying logic, or important behavior is missing from the docs, **and adding it would improve future LLM context-efficiency (saving searches/tokens)**, briefly notify the user to get approval. -**Topic-based separation:** When creating or expanding documentation, keep logically distinct features or domains in separate `.md` files (e.g., architecture, data model, billing) and only reference them in the main/index documents. Do not cram everything into a single monolithic file. Keep in mind: these `.md` files are primarily for LLM grounding and context providing. Keep them concise, structured, and focused on rules/patterns rather than human-readable prose. -**ENFORCEMENT:** At the end of EVERY code-modifying response, append a **`[DOCUMENTATION CHECK]`** section. Evaluate ONLY the `.md` files *already in your context*. State in 1-2 sentences if you found discrepancies or missing concepts, and ask if they should be documented. **DO NOT trigger searches or tool calls for this initial check**. -15. **MgGridBase** (AyCode.Blazor) is the canonical grid base for all data screens. New grids inherit `FruitBankGridBase`, set CRUD tags in the constructor, and use `MgGridWithInfoPanel` for layout. See `AyCode.Blazor.Components/docs/MGGRID.md` (in AyCode.Blazor repo) for the full technical reference. Do NOT create parallel grid base classes. +14. **Keep all .md documentation in sync** — at the end of EVERY code-modifying response, invoke the **`docs-check`** skill (`AyCode.Core/.github/skills/docs-check/SKILL.md`). It evaluates loaded `.md` files for drift vs code, missing topic coverage, csproj-glob registration gaps for new `.md` files, and new issue/TODO candidates — then emits the `[DOCUMENTATION CHECK]` section per its procedure (or `[DOCUMENTATION CHECK] None.` single-line when nothing to report). The skill encapsulates the full calibration (4 prerequisites, 3-item volume cap, no-ID rule, status-update-on-fix clause) and empty-state handling. Passive detection + ASK FIRST; all patches require user approval (Rule #5). Do NOT trigger new searches for this check. +15. **MgGridBase** (AyCode.Blazor) is the canonical grid base for all data screens. New grids inherit `FruitBankGridBase`, set CRUD tags in the constructor, and use `MgGridWithInfoPanel` for layout. See `AyCode.Blazor.Components/docs/MGGRID/README.md` (in AyCode.Blazor repo) for the full technical reference. Do NOT create parallel grid base classes. 16. **AyCode.Core** solution (`../../../Aycode/Source/AyCode.Core/`) contains all core framework code: SignalR base classes, serialization, binary protocol, data sources, logging. Types not defined in this solution likely live in AyCode.Core. 17. **AyCode.Blazor** solution (`../../../Aycode/Source/AyCode.Blazor/`) contains all UI framework code: MgGridBase, MgGridWithInfoPanel, toolbar, layout persistence, Blazor component infrastructure. UI base classes or components not found here likely live in AyCode.Blazor. 18. **Mango.Nop Libraries** (`../NopCommerce.Common/4.70/Libraries/`) — independent shared library with its own `.github/copilot-instructions.md` and `docs/`. Contains DTOs, entities, data access, and service base classes. DTO or entity base classes not found in this solution likely live in Libraries. 19. **FruitBank nopCommerce Plugin** (`../NopCommerce.Common/4.70/Plugins/Nop.Plugin.Misc.AIPlugin/`) is the server-side plugin running inside nopCommerce 4.80.9. Contains SignalR hubs/endpoints, measurement services, data access (DbTable classes), admin controllers, and AI services. Server-side endpoints and services are defined here. -20. **Documentation layering** — write `.md` documentation at the **defining layer** (where the code lives). Higher-layer `.md` files reference the base docs (e.g. `see AyCode.Core/docs/SIGNALR.md`) and document only project-specific overrides or extensions. Never duplicate base-layer descriptions in consumer-level docs. +20. **Documentation layering** — write `.md` documentation at the **defining layer** (where the code lives). Higher-layer `.md` files reference the base docs (e.g. `see AyCode.Core/AyCode.Services/docs/SIGNALR/README.md`) and document only project-specific overrides or extensions. Never duplicate base-layer descriptions in consumer-level docs. 21. **Do not re-read .md files** already in your context window. They only change if you modify them yourself (new content is already in context) or if the developer tells you they changed — in that case re-read them once. 22. **Folder navigation** — start from the root `README.md` for solution-level navigation. When you need to understand a folder's contents or find a type/class, read the `README.md` in that folder first — it indexes the local files and sub-folders. Follow this before grepping or reading source files. \ No newline at end of file diff --git a/FruitBank.Common/docs/README.md b/FruitBank.Common/docs/README.md new file mode 100644 index 00000000..de4dc8f6 --- /dev/null +++ b/FruitBank.Common/docs/README.md @@ -0,0 +1,15 @@ +# FruitBank.Common documentation + +Topic documentation for the `FruitBank.Common` project (shared types across Hybrid client). + +## Reference docs (flat) + +- [`GLOSSARY.md`](GLOSSARY.md) — Common domain terms for the Hybrid client side + +## Navigation + +Per the AI Agent Core Protocol (folder navigation rule), start from this README when browsing `docs/`. Currently only single-file reference. + +## See also + +- **Repo-level glossary**: `../../docs/GLOSSARY.md` diff --git a/FruitBankHybrid.Shared.Tests/ToonTests.cs b/FruitBankHybrid.Shared.Tests/ToonTests.cs index cec68f19..8f8b7576 100644 --- a/FruitBankHybrid.Shared.Tests/ToonTests.cs +++ b/FruitBankHybrid.Shared.Tests/ToonTests.cs @@ -24,26 +24,26 @@ namespace FruitBankHybrid.Shared.Tests; //1. "Headered List" (A biztonságos táblázatosítás) -//Az LLM-eknek nem kell minden sorban megismételni a mezőneveket, ha a lista elején egyszer definiálod a sorrendet. Ez nem találgatás, hanem egy lokális "szerződés". +//Az LLM-eknek nem kell minden sorban megismételni a mezőneveket, ha a lista elején egyszer definiálod a sorrendet.Ez nem találgatás, hanem egy lokális "szerződés". //Hagyományos (pazarló): //Kódrészlet //OrderItemDtos = [ // OrderItemDto { Id = 120, Quantity = 10, ProductName = "Áfonya" } -// OrderItemDto { Id = 121, Quantity = 5, ProductName = "Narancs" } +//OrderItemDto { Id = 121, Quantity = 5, ProductName = "Narancs" } //] -//Optimalizált (pontos és tömör): +//Optimalizált(pontos és tömör) : //Kódrészlet //OrderItemDtos: OrderItemDto[] = [ -// [ Id, Quantity, ProductName ] -// [ 120, 10, "Áfonya" ] -// [ 121, 5, "Narancs" ] +// [Id, Quantity, ProductName] +// [120, 10, "Áfonya"] +// [121, 5, "Narancs"] //] -// Miért jó ez? Az LLM a fejléc alapján (mint egy CSV-nél) rendeli hozzá az értékeket a típushoz. Mivel a típus (OrderItemDto) ott van a definícióban, a szemantikai kapcsolat nem vész el. +// Miért jó ez? Az LLM a fejléc alapján(mint egy CSV-nél) rendeli hozzá az értékeket a típushoz.Mivel a típus (OrderItemDto) ott van a definícióban, a szemantikai kapcsolat nem vész el. //2. Típus-öröklődés a listákban @@ -53,8 +53,8 @@ namespace FruitBankHybrid.Shared.Tests; //Kódrészlet //// A 'ProductDto' elhagyható az objektum elől, mert a sémából tudja -//ProductDto = { -// Id = 1 +//ProductDto = { +// Id = 1 // Name = "Áfonya..." // GenericAttributes = [ // { Id = 99, Key = "NetWeight", Value = "178.3" } @@ -62,13 +62,13 @@ namespace FruitBankHybrid.Shared.Tests; // ] //} -//3. Alapértelmezett értékek elhagyása (Implicit Defaults) +//3. Alapértelmezett értékek elhagyása(Implicit Defaults) -//Ha egy mező értéke megegyezik a @types-ban definiált default-value-val, vagy null/0/false, akkor azt teljesen hagyd ki a @data részből. +//Ha egy mező értéke megegyezik a @types - ban definiált default-value-val, vagy null/0/false, akkor azt teljesen hagyd ki a @data részből. // Szabály: Ami nincs ott, az az alapértelmezett. -// Token megtakarítás: A FruitBank példádban a GenericAttributes = (count: 0) [] sorok rengeteg helyet foglalnak. Ha üres, egyszerűen ne küldd el a mezőt. +// Token megtakarítás: A FruitBank példádban a GenericAttributes = < GenericAttributeDto[] > (count: 0)[] sorok rengeteg helyet foglalnak. Ha üres, egyszerűen ne küldd el a mezőt. //4. String Table helyett: "Object Anchoring" @@ -78,7 +78,7 @@ namespace FruitBankHybrid.Shared.Tests; // Első alkalommal: ProductDto { ... } -// Minden további alkalommal: ProductDto = @ProductDto:1 +//Minden további alkalommal: ProductDto = @ProductDto:1 //[ToonIgnore][ToonDataIgnore] [ToonDescription(Purpose = "Container model for Shipping, Order")] @@ -130,8 +130,8 @@ public sealed class ToonTests a.Orders = (await _signalRClient.GetAllOrderDtos())!.Where(x=>x.CreatedOnUtc > DateTime.UtcNow.AddDays(-70)).ToList(); a.Shippings = (await _signalRClient.GetShippings())!.Where(x=>x.Created > DateTime.UtcNow.AddDays(-70)).ToList(); - //var toon = AcToonSerializer.Serialize(a, FruitBankConstClient.DomainDescription, AcToonSerializerOptions.Default); - var toon = AcToonSerializer.SerializeTypeMetadata(FruitBankConstClient.DomainDescription); + var toon = AcToonSerializer.Serialize(a, FruitBankConstClient.DomainDescription, AcToonSerializerOptions.Default); + //var toon = AcToonSerializer.SerializeTypeMetadata(FruitBankConstClient.DomainDescription); Console.WriteLine(toon); Assert.IsNotEmpty(toon); diff --git a/FruitBankHybrid.Shared/Components/Grids/README.md b/FruitBankHybrid.Shared/Components/Grids/README.md index a7e82459..3c403b75 100644 --- a/FruitBankHybrid.Shared/Components/Grids/README.md +++ b/FruitBankHybrid.Shared/Components/Grids/README.md @@ -2,7 +2,7 @@ Domain-specific grid components, one per entity type. All inherit `FruitBankGridBase`. -> For the MgGrid framework reference see: `AyCode.Blazor/docs/MGGRID.md` +> For the MgGrid framework reference see: `AyCode.Blazor/AyCode.Blazor.Components/docs/MGGRID/README.md` ## FruitBankGridBase diff --git a/FruitBankHybrid.Shared/FruitBankHybrid.Shared.csproj b/FruitBankHybrid.Shared/FruitBankHybrid.Shared.csproj index a05e9eea..23279bd2 100644 --- a/FruitBankHybrid.Shared/FruitBankHybrid.Shared.csproj +++ b/FruitBankHybrid.Shared/FruitBankHybrid.Shared.csproj @@ -1,4 +1,4 @@ - + net10.0 @@ -72,4 +72,8 @@ + + + + \ No newline at end of file diff --git a/README.md b/README.md index 72c84e5f..8440fa5d 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,6 @@ All projects reference these via **DLL** (not ProjectReference). Full source is | Repo | Path | Key Docs | |---|---|---| | **AyCode.Core** (net9.0) | `../../../Aycode/Source/AyCode.Core/` | [copilot-instructions](../../../Aycode/Source/AyCode.Core/.github/copilot-instructions.md), [ARCHITECTURE](../../../Aycode/Source/AyCode.Core/docs/ARCHITECTURE.md) | -| **AyCode.Blazor** (net10.0) | `../../../Aycode/Source/AyCode.Blazor/` | [copilot-instructions](../../../Aycode/Source/AyCode.Blazor/.github/copilot-instructions.md), [MGGRID](../../../Aycode/Source/AyCode.Blazor/docs/MGGRID.md) | +| **AyCode.Blazor** (net10.0) | `../../../Aycode/Source/AyCode.Blazor/` | [copilot-instructions](../../../Aycode/Source/AyCode.Blazor/.github/copilot-instructions.md), [MGGRID](../../../Aycode/Source/AyCode.Blazor/AyCode.Blazor.Components/docs/MGGRID/README.md) | | **Mango.Nop Libraries** (net9.0) | `../NopCommerce.Common/4.70/Libraries/` | [copilot-instructions](../NopCommerce.Common/4.70/Libraries/.github/copilot-instructions.md), [ARCHITECTURE](../NopCommerce.Common/4.70/Libraries/docs/ARCHITECTURE.md) | | **FruitBank Plugin** (net9.0) | `../NopCommerce.Common/4.70/Plugins/Nop.Plugin.Misc.AIPlugin/` | [README](../NopCommerce.Common/4.70/Plugins/Nop.Plugin.Misc.AIPlugin/README.md) | diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 37b802ba..2d4ec719 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -67,7 +67,7 @@ User → DevExpress Grid → AcSignalRDataSource → SignalR (AcBinary) → DevA ## MgGrid — Grid System -All data screens use **MgGridBase** from AyCode.Blazor (see `AyCode.Blazor.Components/docs/MGGRID.md` (in AyCode.Blazor repo) for full technical docs). +All data screens use **MgGridBase** from AyCode.Blazor (see `AyCode.Blazor.Components/docs/MGGRID/README.md` (in AyCode.Blazor repo) for full technical docs). ### FruitBank Grid Hierarchy diff --git a/docs/CONVENTIONS.md b/docs/CONVENTIONS.md index ad0c452d..a7fae458 100644 --- a/docs/CONVENTIONS.md +++ b/docs/CONVENTIONS.md @@ -20,7 +20,7 @@ - **GenericAttributes** for extending nopCommerce entities with custom data (IsMeasurable, Tare, AverageWeight). - **Composition interfaces** for measurement traits: IMeasuringValues = IMeasuringWeights + IMeasuringQuantity. - **DevExpress DxGrid** with `AcSignalRDataSource` for real-time grid data. -- **MgGridBase** — canonical grid base from AyCode.Blazor (see `AyCode.Blazor.Components/docs/MGGRID.md` (in AyCode.Blazor repo)). Provides SignalR CRUD, layout persistence, master-detail, InfoPanel, fullscreen. +- **MgGridBase** — canonical grid base from AyCode.Blazor (see `AyCode.Blazor.Components/docs/MGGRID/README.md` (in AyCode.Blazor repo)). Provides SignalR CRUD, layout persistence, master-detail, InfoPanel, fullscreen. - **FruitBankGridBase** — project adapter that fixes `TId=int`, `TLoggerClient=LoggerClient`, adds per-user layout and master/detail defaults. - **FruitBankSignalRClient** as single hub client for all server communication. - **DatabaseClient** for client-side caching with ConcurrentDictionary tables. diff --git a/docs/GLOSSARY.md b/docs/GLOSSARY.md index b8eba883..dd1482c5 100644 --- a/docs/GLOSSARY.md +++ b/docs/GLOSSARY.md @@ -30,7 +30,7 @@ FruitBank extends them via: ## UI / Grid Components -For MgGrid framework terms (MgGridBase, MgGridWithInfoPanel, MgGridToolbarBase, MgGridDataColumn, MgGridInfoPanel, IMgGridBase, etc.) see `GLOSSARY.md` (in AyCode.Blazor repo) and `AyCode.Blazor.Components/docs/MGGRID.md` (in AyCode.Blazor repo). +For MgGrid framework terms (MgGridBase, MgGridWithInfoPanel, MgGridToolbarBase, MgGridDataColumn, MgGridInfoPanel, IMgGridBase, etc.) see `GLOSSARY.md` (in AyCode.Blazor repo) and `AyCode.Blazor.Components/docs/MGGRID/README.md` (in AyCode.Blazor repo). | Term | Definition | |---|---| diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 00000000..af3d0d37 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,22 @@ +# FruitBankHybridApp documentation + +Top-level documentation for the `FruitBankHybridApp` repo (Layer 3 — FruitBank MAUI/Blazor Hybrid client). + +## Reference docs (flat) + +- [`ARCHITECTURE.md`](ARCHITECTURE.md) — Repo architecture overview +- [`CONVENTIONS.md`](CONVENTIONS.md) — Coding conventions +- [`GLOSSARY.md`](GLOSSARY.md) — Domain glossary (FruitBank terms: Shipping, Order, StockTaking, MeasuringStatus, etc.) + +## Sub-projects with docs + +- `FruitBank.Common/docs/` — Common glossary (shared across Hybrid client-side) + +## Navigation + +Per the AI Agent Core Protocol (folder navigation rule), start from this README when browsing `docs/`. Single-file reference docs remain flat; multi-file topics would live in named subfolders (none currently at this level). + +## See also + +- **Server-side plugin**: `../../NopCommerce.Common/4.70/Plugins/Nop.Plugin.Misc.AIPlugin/docs/README.md` +- **Base framework** (AyCode.Core, AyCode.Blazor): see those repos' `docs/` folders.