FruitBankHybridApp/.github/copilot-instructions.md

18 KiB
Raw Blame History

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.

  1. 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 .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 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/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.

  2. 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, or get_file (for non-markdown files).
    • Your VERY FIRST AND ONLY allowed tool calls must be file_search or get_file targeting the .md documentation in the relevant docs/ folders or README.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 .md files that are already mapped in your context or LOADED_DOCS list (strictly maintain rule 3).
    • CROSS-REPO HARD-GATE: When navigating to an external repo (via own-dep-repos paths), read that repo's docs/ and README.md BEFORE 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 .md file (folder README.md, other repo docs/, 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.
  3. STRICT NO-RE-READ POLICY (ANTI-LOOP): You are PHYSICALLY FORBIDDEN from calling get_file or file_search on any .md file 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 .md file is in your context, it STAYS in your context.
    • Re-reading them wastes tokens and breaks the protocol.
    • ONLY re-read an .md file 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.
  4. CONTEXT RECOVERY (SMART READ): If the user asks a domain/architecture specific question and you realize the essential .md files 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 the docs/ 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/
  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 four workspace skills' SKILL.md files:

  • docs-discovery/SKILL.mdreactive (triggers on any domain question — must be ready BEFORE the first domain query arrives)
  • docs-check/SKILL.mdreactive (triggers at the end of every code-modifying response)
  • protocol-audit/SKILL.mdon-demand (triggers on explicit "audit protocol" command)
  • adr-author/SKILL.mdon-demand + LLM-suggested (triggers on explicit planning/design requests, or when the LLM flags an ADR-worthy conversation and the user confirms)

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 5 files (this copilot-instructions.md + 4 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.mddocs/ 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 in own-dep-repos are fully accessible — read their source code, docs, and .github/copilot-instructions.md freely 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 four 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 Activate from an AyCode.Core session, or read the SKILL.md directly and follow its steps.

  • docs-discovery — Load relevant .md documentation (main + _ISSUES + _TODO paired sets) BEFORE source-code search or modifications. Saves tokens vs. grep-based rediscovery. 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).

  • adr-author — Create Architecture Decision Records (ADRs) for architecturally significant design decisions. Structured interview (context → alternatives → trade-offs → decision → consequences) producing a durable docs/adr/NNNN-<slug>.md file (product decisions) or a new LLMP-DEC-N row in the protocol decision log (meta-protocol decisions). Location: AyCode.Core/.github/skills/adr-author/SKILL.md Invoke on explicit user request ("let's plan X", "decide Y vs Z", "design the W module") or proactively flag when the conversation looks ADR-worthy (user must confirm — never auto-invoke).

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

  1. FruitBank = fruit & vegetable wholesaler. The server side runs as a nopCommerce plugin — Customer, Order, Product, GenericAttribute are nopCommerce entities.
  2. Shipping = INBOUND delivery (supplier → warehouse). Order = OUTBOUND delivery (warehouse → customer). Never confuse the two directions.
  3. "Pallet" (XxxItemPallet) = a measurement record, NOT a physical pallet. Always created for every item, even non-measurable ones.

Measurement Logic

  1. IsMeasurable=false → weights are 0.0, only TrayQuantity is recorded. A Pallet record is still created.
  2. NetWeight = GrossWeight PalletWeight (TrayQuantity × TareWeight) — this formula is universal across ShippingItemPallet, OrderItemPallet, and StockTakingItemPallet.
  3. MeasuringStatus.Finnished — intentional legacy typo with double-n. Do NOT fix the spelling.
  4. MeasuringStatus progression: NotStarted(0) → Started(10) → Finnished(20) → Audited(30). OrderItemPallet adds Audited when RevisorId > 0.

Data Model

  1. GenericAttribute = polymorphic key-value store. KeyGroup = owner type name, EntityId = owner ID. ProductDto reads IsMeasurable, Tare, AverageWeight, IncomingQuantity, NetWeight from GenericAttributes.
  2. Three parallel measurement hierarchies share the same base (MeasuringItemPalletBase):
    • Shipping: ShippingItem → ShippingItemPallet
    • Order: OrderItemDto → OrderItemPallet (adds RevisorId for audit)
    • StockTaking: StockTakingItem → StockTakingItemPallet

Technical

  1. SignalR uses AcBinaryHubProtocol (custom binary), not default JSON.
  2. Do not suggest removal/rollback as a solution — find a fix for the problem.
  3. All AyCode references are via DLL (not ProjectReference) — this is intentional. nopCommerce 4.80.9 requirement.
  4. 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.
  5. 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.
  6. MgGridBase (AyCode.Blazor) is the canonical grid base for all data screens. New grids inherit FruitBankGridBase<TEntity>, 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.
  7. 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.
  8. 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.
  9. 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.
  10. 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.
  11. 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.
  12. 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.
  13. 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.