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.
This commit is contained in:
87
.github/copilot-instructions.md
vendored
Normal file
87
.github/copilot-instructions.md
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user