17 KiB
FruitBankHybridApp — Domain Rules
🛑 AI AGENT CORE PROTOCOL (CRITICAL ENFORCEMENT)
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.
-
MANDATORY OUTPUT PREFIX: Your response MUST begin on the very first line with this format:
[LOADED_DOCS: N files (+K this turn: <comma-separated short names>)]N= total count of.mdfiles currently in your context (across all loaded docs in this conversation)K= count of.mdfiles newly loaded during THIS response (may be 0)- 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
.mdfile):- 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.mdfiles: always include the immediate parent folder as prefix →TOPIC/README.md(e.g.,LOGGING/README.md,BINARY/README.md). Never write a bareREADME.mdin the prefix because multiple folders have one. - Cross-project disambiguation: if two files share the same short name (rare — e.g.,
docs/README.mdfrom 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 forcopilot-instructions.md— the.github/location is implicit. When multiple are loaded simultaneously (typical inprotocol-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]— onlycopilot-instructions.mdloaded earlier, nothing 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.
-
HARD-GATE DELAY (DOCS BEFORE CODE) & TOOL EXECUTION BLOCK:
- If
[LOADED_DOCS: NONE]applies, you MUST STOP and you are STRICTLY FORBIDDEN to use the following tools:code_search,get_symbols_by_name,find_symbol, orget_file(for non-markdown files). - Your VERY FIRST AND ONLY allowed tool calls must be
file_searchorget_filetargeting the.mddocumentation in the relevantdocs/folders orREADME.md. - Do not answer the user's core question until the
[LOADED_DOCS]list is populated with the base architecture files. - CRITICAL EXCEPTION: Do NOT re-read
.mdfiles that are already mapped in your context orLOADED_DOCSlist (strictly maintain rule 3). - CROSS-REPO HARD-GATE: When navigating to an external repo (via
own-dep-repospaths), read that repo'sdocs/andREADME.mdBEFORE searching its source code. The hard-gate applies to EVERY repo you enter, not just your own. - PER-QUESTION DOC-FIRST: Before searching source code for any user question, check whether there is a relevant
.mdfile (folderREADME.md, other repodocs/, etc.) that has NOT yet been loaded. Read it first — it tells you where to look in the code, saving searches and tokens. Only after loading relevant docs should you search/read source files.
- If
-
STRICT NO-RE-READ POLICY (ANTI-LOOP): You are PHYSICALLY FORBIDDEN from calling
get_fileorfile_searchon any.mdfile that is already listed in your[LOADED_DOCS]prefix.- Definition: A doc is "in your context" ONLY if you have read its actual file content via a tool call in THIS conversation. Prior session summaries, compacted messages, and memory entries do NOT count — they are lossy compressions.
- Once an
.mdfile is in your context, it STAYS in your context. - Re-reading them wastes tokens and breaks the protocol.
- ONLY re-read an
.mdfile if the user EXPLICITLY states "the file has changed on disk, read it again". - If the user simply mentions a glossary term or requests info found in a loaded doc, answer directly from memory. DO NOT search for it again.
-
CONTEXT RECOVERY (SMART READ): If the user asks a domain/architecture specific question and you realize the essential
.mdfiles are NO LONGER in your current context (they dropped out of memory), you MUST automatically re-read the necessary documentation before answering. Do NOT wait for the user to explicitly tell you to re-read them. Prioritize scanning thedocs/folders to recover the lost context.Auto-detection triggers (MUST treat ALL docs as NOT loaded):
- Session starts with a summary of a previous conversation (context recovery/compaction)
- Message compaction or context compression occurred mid-session
- You cannot quote the exact content of a doc you claim to know
When any trigger fires → reset
[LOADED_DOCS: NONE]and re-read per Rule #2.
Directories to read (when recovering context):
docs/(in this repository root)../NopCommerce.Common/4.70/Plugins/Nop.Plugin.Misc.AIPlugin/docs/
-
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>/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 { name = "FruitBankHybridApp" type = "product" layer = 2 own-dep-repos = [ "AyCode.Core: ../../../Aycode/Source/AyCode.Core", "AyCode.Blazor: ../../../Aycode/Source/AyCode.Blazor", "Mango.Nop Libraries: ../NopCommerce.Common/4.70/Libraries" ] }
This is the single source of truth for domain rules. Do not duplicate these elsewhere. For detailed docs see:
README.md→docs/For core framework rules see:.github/copilot-instructions.md(in AyCode.Core repo) For UI framework rules see:.github/copilot-instructions.md(in AyCode.Blazor repo) For nopCommerce library rules see:.github/copilot-instructions.md(in Mango.Nop Libraries repo) For nopCommerce plugin (server side) rules see:../NopCommerce.Common/4.70/Plugins/Nop.Plugin.Misc.AIPlugin/README.md(in Mango.Nop Plugins repo) External repos inown-dep-reposare fully accessible — read their source code, docs, and.github/copilot-instructions.mdfreely when you need type definitions, base classes, or context. Do not limit yourself to the current workspace.
Shared Agent Skills
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.mdacross all 5 repos. Location:AyCode.Core/.github/skills/protocol-audit/SKILL.mdActivate from an AyCode.Core session, or read the SKILL.md directly and follow its steps. -
docs-discovery — Load relevant
.mddocumentation (main +_ISSUES+_TODOpaired sets) BEFORE source-code search or modifications. Saves tokens vs. grep-based rediscovery. Location:AyCode.Core/.github/skills/docs-discovery/SKILL.md(seeown-dep-reposabove 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
.mdfiles at the end of every code-modifying response: drift vs code, missing topic coverage, csproj-glob registration gaps for new.mdfiles, and new issue/TODO candidates. Emits the[DOCUMENTATION CHECK]section. Location:AyCode.Core/.github/skills/docs-check/SKILL.mdInvoke 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):
AyCode.Core/.github/LLM_PROTOCOL_DECISIONS.md
Read this file when you need to understand why a rule is the way it is, or before proposing a protocol change — it may save a debate about something already resolved.
Documentation-first coding
Before running any source-code Grep / get_file / code_search in response to a domain-related request, invoke the docs-discovery skill (path above). Scans docs/ folders in THIS repo AND in referenced repos (via own-dep-repos) via Glob, loads paired .md sets as a unit. Rule-number-agnostic — refers to rule NAMES (no-re-read, folder-navigation, explicit-consent) which are stable across repos.
Business Domain
- FruitBank = fruit & vegetable wholesaler. The server side runs as a nopCommerce plugin — Customer, Order, Product, GenericAttribute are nopCommerce entities.
- Shipping = INBOUND delivery (supplier → warehouse). Order = OUTBOUND delivery (warehouse → customer). Never confuse the two directions.
- "Pallet" (
XxxItemPallet) = a measurement record, NOT a physical pallet. Always created for every item, even non-measurable ones.
Measurement Logic
- IsMeasurable=false → weights are 0.0, only
TrayQuantityis recorded. A Pallet record is still created. - NetWeight = GrossWeight − PalletWeight − (TrayQuantity × TareWeight) — this formula is universal across ShippingItemPallet, OrderItemPallet, and StockTakingItemPallet.
- MeasuringStatus.Finnished — intentional legacy typo with double-n. Do NOT fix the spelling.
- MeasuringStatus progression: NotStarted(0) → Started(10) → Finnished(20) → Audited(30). OrderItemPallet adds Audited when RevisorId > 0.
Data Model
- GenericAttribute = polymorphic key-value store.
KeyGroup= owner type name,EntityId= owner ID. ProductDto reads IsMeasurable, Tare, AverageWeight, IncomingQuantity, NetWeight from GenericAttributes. - Three parallel measurement hierarchies share the same base (
MeasuringItemPalletBase):- Shipping: ShippingItem → ShippingItemPallet
- Order: OrderItemDto → OrderItemPallet (adds RevisorId for audit)
- StockTaking: StockTakingItem → StockTakingItemPallet
Technical
- SignalR uses AcBinaryHubProtocol (custom binary), not default JSON.
- Do not suggest removal/rollback as a solution — find a fix for the problem.
- All AyCode references are via DLL (not ProjectReference) — this is intentional. nopCommerce 4.80.9 requirement.
- 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.
- Keep all .md documentation in sync — at the end of EVERY code-modifying response, invoke the
docs-checkskill (AyCode.Core/.github/skills/docs-check/SKILL.md). It evaluates loaded.mdfiles for drift vs code, missing topic coverage, csproj-glob registration gaps for new.mdfiles, 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. - MgGridBase (AyCode.Blazor) is the canonical grid base for all data screens. New grids inherit
FruitBankGridBase<TEntity>, set CRUD tags in the constructor, and useMgGridWithInfoPanelfor layout. SeeAyCode.Blazor.Components/docs/MGGRID/README.md(in AyCode.Blazor repo) for the full technical reference. Do NOT create parallel grid base classes. - 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. - 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. - Mango.Nop Libraries (
../NopCommerce.Common/4.70/Libraries/) — independent shared library with its own.github/copilot-instructions.mdanddocs/. Contains DTOs, entities, data access, and service base classes. DTO or entity base classes not found in this solution likely live in Libraries. - 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. - Documentation layering — write
.mddocumentation at the defining layer (where the code lives). Higher-layer.mdfiles 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. - 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.
- Folder navigation — start from the root
README.mdfor solution-level navigation. When you need to understand a folder's contents or find a type/class, read theREADME.mdin that folder first — it indexes the local files and sub-folders. Follow this before grepping or reading source files.