Imported from ErikM1974/pricing-indexfile-2025 (
AGENTS.md). Install upstream withnpx skills add ErikM1974/pricing-indexfile-2025. Copyright stays with the author.
AGENTS.md
Guidance for Codex when working in this repository.
π΄ Working directories (moved off OneDrive 2026-09-18)
Work in these paths. They are plain local folders β no OneDrive, no sync.
| Project | Path |
|---|---|
| Pricing Index (this repo) | C:\dev\pricing-index |
| caspio-pricing-proxy | C:\dev\caspio-pricing-proxy |
| inksoft-transform (was "Python Inksoft") | C:\dev\inksoft-transform |
The old copies under OneDrive - Northwest Custom Apparel\2025\ are RETIRED and
carry a RETIRED-MOVED-TO-C-DEV.md marker. If you find yourself in one, stop and switch.
π΄ Never run a git repo from OneDrive. It truncated the git index (1,323 files reported
deleted while they sat on disk), forked tracked files into -Eriklaptop conflict copies from a
second machine, and left a duplicate develop 94 commits stale.
π A checkout with no .env silently skips 22 credential-dependent unit tests (26 skipped
vs 4), so a gate run there is weaker than it looks.
CSS for every new or changed page
Read the current design-system guide before writing page markup or styles. This applies to Astra and every other coding agent working here.
- Reuse the existing page family's layout and shared controls. Start new staff pages from
templates/page-template.html; use a reviewed sibling for storefronts, calculators and quote builders. - Use canonical
tokens.cssandcomponents.css, the unified body attributes and scoped family styles. Add only necessary page-specific arrangements; do not copy shared component rules, invent a second token scale or stack override stylesheets. - Register every new app page in
scripts/css/migration-manifest.json(pilotsis the historical name of the reviewed-page list), including its actual styles, measured byte budget, tested states and existing browser-test file. The census guard rejects unregistered application pages. - Follow the guide's checks and visual review before marking a page complete. Do not silence a guard, raise a budget or add an exception merely to make checks pass. Generated print layouts, email templates and embedded providers keep their own recorded owners.
π΄ Top 8 Never-Break Rules
- NO version-suffix files β Never create
-backup,-FINAL,-FIXED,-old,-v2. Use Git branches. - NO test files in root β ALL tests go in
/tests/(ui/api/unit subdirectories). No exceptions. - NO inline code β Zero
<style>or<script>tags with content in HTML files. - NO silent API failures β Always show errors when an API fails. Never fall back to cached/stale data silently. Wrong pricing is worse than an error.
- ALWAYS update ACTIVE_FILES.md β Every file create/delete/move updates documentation immediately.
- USE CONFIG for API URLs β Don't hardcode
caspio-pricing-proxyURL. UseAPP_CONFIG.API.BASE_URL. - SYNC calculator + quote builder prices β If both exist for a method, test identical inputs match.
- SYNC all 4 quote builders β A change to one (DTG/DTF/EMB/SCP) usually applies to all four. Always check.
Pre-Flight Checklist
Before creating a file:
- Test file? β
/tests/. Calculator? β/calculators/. Quote builder? β/quote-builders/. Dashboard? β/dashboards/. Page? β/pages/. - Shared JS/CSS? β
/shared_components/{js,css}/. Page-specific? β same folder as the HTML. - Root HTML allowed ONLY for
index.html,cart.html,product.html. Everything else β subdirectory. - Use kebab-case. External JS/CSS only (no inline).
- Check ACTIVE_FILES.md for existing functionality first.
Before committing:
- Remove
console.logdebug statements. - Update ACTIVE_FILES.md (and
shared_components/js/GUIDE.mdfor new shared JS). - No hardcoded API URLs.
- Pricing change? Verify
printQuote()andsaveAndGetLink()use the same inputs asrecalculatePricing(). - Quote builder change? Check if it applies to the other 3 (see Quote Builder Sync below).
- ManageOrders discovery? Document per ManageOrders Documentation Routing.
After fixing a bug:
- Append entry to LESSONS_LEARNED.md: Problem / Root Cause / Solution / Prevention.
- LESSONS_LEARNED hard limit: 300 lines. If over 250 lines before adding, archive oldest resolved entry to
/memory/LESSONS_LEARNED_ARCHIVE.md(no limit). - Keep only: recurring bugs, active architecture rules, gotchas likely to recur. Archive: one-time fixes, historical migrations.
Auto-Update Memory (Don't Ask, Just Do)
Memory updates are part of completing the task β not a separate ask-permission step.
- Bug fixes β append to LESSONS_LEARNED.md; update MEMORY.md only if the fix changes documented behavior.
- API / integration changes (ManageOrders, Caspio, Stripe, ShopWorks) β update the relevant section/topic file.
- New features β one-liner in MEMORY.md or full detail in topic file (>2 lines β topic file).
- Notify Erik in one sentence: "Updated LESSONS_LEARNED.md and MEMORY.md."
- Memory rules in detail:
~/.Codex/projects/.../memory/MEMORY.md(auto-loaded each session).
File-Lifecycle Automation
On every create/delete/move/rename:
- Update ACTIVE_FILES.md (path, addition, removal β match action to event).
- Update
shared_components/js/GUIDE.mdif it's in that directory. - On delete/rename:
grepfor the filename in HTML/JS, fix orphaned references. - On server.js route change: update the route TOC comment block at the top of server.js.
Dead code detection (flag, don't auto-delete): JS files with zero <script> references; files unchanged 6+ months with no references; any *.bak, *.backup, -FINAL files found.
API Error Handling (Erik's #1 Rule)
// NEVER β silent fallback
try {
const data = await fetchAPI();
} catch (error) {
const data = getCachedData(); // NO! Customer sees wrong price.
}
// ALWAYS β visible failure
try {
const data = await fetchAPI();
} catch (error) {
showErrorBanner('Unable to load pricing. Please refresh.');
console.error('API failed:', error);
throw error;
}
Related Projects (Sibling Repos)
| Project | Location | URL / Port |
|---|---|---|
| Pricing Index (this repo) | . |
port 3000 local / Heroku sanmar-inventory-app |
| caspio-pricing-proxy (backend API) | ../caspio-pricing-proxy |
https://caspio-pricing-proxy-ab30a049961a.herokuapp.com Β· port 3002 local |
| Python Inksoft (InkSoft β ShopWorks) | ../inksoft-transform |
https://inksoft-transform-8a3dc4e38097.herokuapp.com Β· Flask Β· deploy git subtree push --prefix web heroku main |
Cross-project sync: When modifying ManageOrders push logic, check if the same change applies in Python Inksoft (web/). Shared patterns: size suffixes (_2X, _3XL), OnSite payload, TaxTotal=0, gift certs as line items.
Critical Patterns
π΅ Pricing = API, never hardcoded (Erik's rule, 2026-06-03) β ALL quote builders
Every price, fee, charge, upcharge, percentage, and config value in EVERY quote builder (EMB/SCP/DTF/DTG + Order Form) MUST come from the backend API β never a hardcoded number in the front end. Caspio is the single source of truth so Erik changes a price in Caspio and every builder reflects it with no deploy.
- Service fees / setup / digitizing / monogram / rush %, etc. β Caspio
Service_Codestable via proxyGET /api/service-codes(src/routes/service-codes.js; supports?code=,/tier/:code/:qty, full CRUD). Frontend pattern:loadServiceCodePrices()+getServicePrice(code, fallback)(seeembroidery-quote-builder.js). - Decoration / garment / cap / AL / full-back pricing β
/api/pricing-bundle+{method}-pricing-service.js(calculateALPrice, etc.). - A hardcoded number is allowed ONLY as a fallback when the API is unreachable, and it MUST surface a visible warning (Erik's #1 rule: never a silent wrong price).
- When you add ANY new charge to a builder, wire it to the API FIRST. Audit target: Rush 25%, LTM, 3D-puff/laser upcharges, and all SCP/DTF/DTG fees are still being migrated to this.
Two Color-Field System (inventory-critical)
| Field | Use for | Example |
|---|---|---|
| COLOR_NAME | UI display, customer quotes | "Brilliant Orange" |
| CATALOG_COLOR | API queries, ShopWorks PO, inventory | "BrillOrng" |
catalogColor: product.CATALOG_COLOR // β
Inventory works
catalogColor: product.COLOR_NAME // β "Unable to verify"
Multi-SKU Products (PC54 example)
PC54 has SKUs PC54, PC54_2X, PC54_3X mapped to Size01βSize06. PC54_2X uses Size05, NOT Size06. Mis-mapping silently breaks ShopWorks line items.
Embroidery Tier Structure
- Tiers: 1-7 / 8-23 / 24-47 / 48-71 / 72+
- LTM threshold:
qty <= 7(NOT< 24like DTG/DTF β common mistake) - Caps and garments tier separately β never combine qty for a tier discount.
- 5-tier structure +
MarginDenominator 0.57+LTM_Fee $50. Detail: emb-builder-details.md.
Quote Builder Sync (all 4 builders)
Files: quote-builders/{dtg,dtf,embroidery,screenprint}-quote-builder.html + matching shared_components/js/*-quote-builder.js. Shared utils: quote-builder-utils.js. Shared CSS: quote-builder-common.css.
π§ Before changing ANY quote-builder element, read memory/quote-builder-architecture.md β the shared-vs-per-builder manifest + change-routing cheat sheet. Key: invoice/PDF/totals/tax = ONE shared file embroidery-quote-invoice.js β changes hit all 4 at once. DTG uses a separate (inline-form) architecture, so trio UI changes don't reach it automatically.
Sync these across all 4: CSS/layout/spacing Β· table structure Β· fee/charges panel Β· customer info panel Β· modal styling Β· utility functions in quote-builder-utils.js.
Do NOT sync (method-specific): pricing logic Β· location selection UI Β· logo/artwork config Β· *-pricing-service.js / *-quote-service.js Β· updateDiscountType() / updateAdditionalCharges() / updateFeeTableRows().
After any builder change, ask: "Does this apply to the other 3? Should this move to quote-builder-utils.js? Does it affect printQuote() or saveAndGetLink()?"
Quick Reference
- API Proxy:
https://caspio-pricing-proxy-ab30a049961a.herokuapp.com - Quote Prefixes:
DTG Β· RICH Β· EMB Β· EMBC Β· CEMB Β· LT Β· PATCH Β· SPC Β· SSC Β· WEB Β· OF - Dev:
npm start(port 3000)
Security Checklist
When adding endpoints or rendering user data:
- SQL injection: use
sanitizeFilterInput()for Caspio filter params. - XSS: use
escapeHTML()when rendering external/user data viainnerHTML. - CORS: update
ALLOWED_ORIGINSin server.js for new domains. - Rate limit: sensitive endpoints use
strictLimiter.
Policies Hub β Employee Handbook sync
Before publishing any NEW or substantially-changed Policies Hub policy/procedure, do a two-way Employee Handbook check (the 22-chapter employee-handbook policy + its chapter policies, also Employee-Handbook-Latest.pdf):
- No contradiction β scan the handbook; it is the higher authority on HR/employment topics, so reword the policy to defer (never restate or contradict it), or flag the conflict to Erik.
- Keep the handbook current β if the new/changed policy introduces or alters something the handbook should reflect, propose the matching handbook update so it doesn't drift, and surface it to Erik. Steps:
policies-hub-update-playbook.mdβ "Handbook cross-check" +handbook-sync-workflow.md.
ManageOrders Documentation Routing
| Discovery type | Destination |
|---|---|
| New fields, endpoints, implementations | /memory/MANAGEORDERS_COMPLETE_REFERENCE.md |
| Bugs, gotchas, workarounds | /memory/LESSONS_LEARNED.md (Order Processing & ShopWorks) |
| CRM / Order Entry capabilities | /memory/MANAGEORDERS_CRM_CAPABILITY_REFERENCE.md |
| 3-Day Tees StripeβShopWorks flow | /memory/3-day-tees/ORDER_PUSH_FLOW.md |
These files are the single source of truth across all 3 NWCA projects.
Documentation Entry Points
- December Finish Line project guide β attached planning folders, current financial reports, assumptions, and website integration notes; read when working on 2026 profit, Q4 sales, or December Finish Line.
- /memory/CROSS_PROJECT_HUB.md β start here for cross-project work
- /memory/LESSONS_LEARNED.md β check first when debugging
- /memory/INDEX.md β master navigation
- /memory/GLOSSARY.md β shared terminology
For deep research, use the Task tool with subagent_type='Explore'.
When in doubt:
- Check the Top 8 Never-Break Rules above.
- Check ACTIVE_FILES.md before creating anything new.
- Use the Explore agent to look up detailed docs.