Files
shopdb-flask/.github/copilot-instructions.md
cproudlock 603872ff76 Add Copilot custom instructions
Repo-level instructions so GitHub Copilot follows the LOCKED naming rules
(lowercase concatenated DB columns, allowed-acronym list, banned shorthand),
the ASCII-only style policy, and the plugin/migration/contract architecture.
Without this Copilot suggests snake_case columns, em-dashes, and
db.create_all(), which the naming hook and CI then reject. Distilled from
CONTRIBUTING.md; that file stays the authority.
2026-07-17 20:56:41 -04:00

4.0 KiB

Copilot instructions for shopdb-flask

Follow these when suggesting code. They are enforced by a naming/style hook and by CI (.github/workflows/ci.yml) - suggestions that break them fail the build. CONTRIBUTING.md is the full authority; this is the short version.

Naming (LOCKED - the hook rejects violations)

  • DB tables: lowercase, concatenated, plural. No underscores, no dashes. machines, networkdevices, businessunits - NOT machine_types, BusinessUnits.
  • DB columns: lowercase, concatenated, singular. No underscores. machineid, lastzabbixsync, isactive - NOT machine_id, last_zabbix_sync.
  • Foreign keys: referenced table (singular) + id: locationid, vendorid.
  • Booleans: is/has prefix: isactive, isshopfloor.
  • Index names: idx_<table>_<column> (underscores allowed here only).

Python

  • A variable, attribute, function, or dict key that holds a DB value MUST match the column name exactly - do NOT convert to snake_case. Column machineid -> Machine.machineid, {"machineid": 1}, local machineid.
  • Pure code that does NOT mirror a DB field uses normal snake_case (PEP 8): loop_count, current_user, validate_input().
  • Classes: PascalCase, spelled out (NetworkDevice, AssetType).

JavaScript / Vue

  • A JS variable holding an API field value matches the API key exactly - do NOT camelCase it. API {"machineid": 1} -> response.machineid, never machineId.
  • Components: PascalCase (AssetDetail.vue). CSS classes: lowercase-with-dashes.

API

  • Endpoints: lowercase plural nouns, no underscores/dashes: /api/networkdevices.
  • Query params + response keys match column names: ?locationid=5, {"machineid": 1, "lastzabbixsync": "..."}.

Allowed acronyms only

Universal: id url api http https json jwt sql os ip dns csv pdf cors ttl uuid html css orm. Domain: cmm cnc pc usb vnc winrm ssh ssl tls tcp udp smtp ldap vlan sso dnc focas clm mtconnect. Anything else: spell it out.

Banned shorthand

Never use cfg ctx mgr req res env util helper or db as a standalone variable name. Spell out: config context manager request response environment utilities. _bp is fine only as a suffix with a meaningful prefix (printers_bp).

Style (ASCII only)

  • NO emojis anywhere - code, comments, strings, UI.
  • NO em-dashes, en-dashes, Unicode arrows, or smart quotes. Plain ASCII only.
  • Comments default to NONE. Add one only when the WHY is non-obvious; keep inline #/// comments terse. Docstrings stay normal English.
  • Dark theme is the default; keep UI functional and professional.

Architecture (do not violate)

  • Plugins are the product. Plugin code lives in plugins/<name>/{models,api,services,schemas}/ with a manifest.json (single source of truth: name, version, dependencies, api_prefix) and a BasePlugin subclass in plugin.py.
  • Plugins never import core internals. Use the contract surface shopdb.api (e.g. from shopdb.api import db, Asset, success_response). Adding to that surface is a contract-version bump + a docs/PLUGIN-HOOKS update in the same PR.
  • Migrations, never db.create_all(). The core Alembic chain is in migrations/versions/; each plugin owns its own chain under plugins/<name>/migrations/. New schema = a new migration with an idempotent guard and a real downgrade. Migrations must run clean on strict MySQL 8.
  • Asset model is the platform contract. Physical things are an Asset plus a plugin subtype row linked by assetid (FK, ON DELETE CASCADE). Consumables with quantities are standalone tables, not assets.
  • Ledger pattern: a cached quantityonhand moves in the SAME commit as the signed transaction row it reflects.

Before you finish a change

Run the three gates (CI runs the same):

python -m pytest tests/ -q
cd frontend && npx vitest run && npm run build && cd ..
bash scripts/check-naming-and-style.sh

Commits: short present-tense subject, body says WHY. No AI/tool attribution in commit messages, code comments, or docs.