style: avoid "the", use "our" — writing style rule + sweep
This commit is contained in:
parent
422d462b46
commit
f12fa036a6
1 changed files with 48 additions and 47 deletions
95
CLAUDE.md
95
CLAUDE.md
|
|
@ -15,12 +15,12 @@
|
|||
|
||||
### Media Architecture
|
||||
|
||||
Files are NEVER streamed through uwsgi. The server only generates presigned URLs (15 min TTL). The client's browser/JS fetches directly from the Spaces CDN:
|
||||
Files are NEVER streamed through uwsgi. Our server only generates presigned URLs (15 min TTL). Our client's browser/JS fetches directly from our Spaces CDN:
|
||||
- **Downloads**: presigned `get_object` URLs → client fetches from CDN
|
||||
- **Uploads**: presigned `post` → client uploads directly to Spaces
|
||||
- **Thumbnails**: public CDN URLs with `?ts=` cache busting
|
||||
|
||||
**BYOB (Bring Your Own Bucket)**: Shops can configure their own S3-compatible bucket (`bucket-settings` form section). When enabled, all presigned URLs and CDN references use the shop's bucket. Always use shop-aware request methods in views and templates:
|
||||
**BYOB (Bring Your Own Bucket)**: Shops can configure their own S3-compatible bucket (`bucket-settings` form section). When enabled, all presigned URLs and CDN references use our shop's bucket. Always use shop-aware request methods in views and templates:
|
||||
- `request.shop_uploads_client` — S3 client (shop's or MPS default)
|
||||
- `request.shop_bucket_name` — bucket name (shop's or MPS default)
|
||||
- `request.shop_cdn_endpoint` — CDN URL (shop's or MPS default)
|
||||
|
|
@ -52,7 +52,7 @@ This project uses a Makefile for most development operations. Use `make` command
|
|||
|
||||
### Testing
|
||||
- Run tests: `make test`
|
||||
- This installs development dependencies and runs the test suite with py.test
|
||||
- This installs development dependencies and runs our test suite with py.test
|
||||
- Tests are located in `make_post_sell/tests/`
|
||||
|
||||
### Installation & Setup
|
||||
|
|
@ -89,12 +89,12 @@ This project uses a Makefile for most development operations. Use `make` command
|
|||
|
||||
## Testing Notes
|
||||
|
||||
The project uses pytest with unittest framework. There are three types of tests:
|
||||
Our project uses pytest with unittest framework. There are three types of tests:
|
||||
|
||||
### Test Types
|
||||
- **Unit tests** (`test_models.py`) - Test individual model methods and properties in isolation
|
||||
- **Integration tests** (`test_integration.py`) - Test interactions between models and business logic
|
||||
- **Functional tests** (`test_functional.py`) - End-to-end tests through the web interface
|
||||
- **Functional tests** (`test_functional.py`) - End-to-end tests through our web interface
|
||||
|
||||
### Running Tests
|
||||
**Before running tests**: Source environment variables with `source vars.sh` to set required Stripe API keys and other configuration.
|
||||
|
|
@ -121,11 +121,11 @@ env/bin/py.test --cov=make_post_sell.models.cart --cov-report=term-missing make_
|
|||
|
||||
## Database Location
|
||||
|
||||
The SQLite database is located at: `data/make_post_sell.sqlite`
|
||||
Our SQLite database is located at: `data/make_post_sell.sqlite`
|
||||
|
||||
**CRITICAL WARNING**: NEVER delete or remove database files without explicit user permission. The database contains production data and cannot be easily recovered. Always ask before any destructive operations.
|
||||
**CRITICAL WARNING**: NEVER delete or remove database files without explicit user permission. Our database contains production data and cannot be easily recovered. Always ask before any destructive operations.
|
||||
|
||||
**MANDATORY**: ALWAYS create a backup of the database before any database operations (migrations, schema changes, etc.):
|
||||
**MANDATORY**: ALWAYS create a backup of our database before any database operations (migrations, schema changes, etc.):
|
||||
```bash
|
||||
cp data/make_post_sell.sqlite data/make_post_sell.sqlite.backup-$(date +%Y%m%d-%H%M%S)
|
||||
```
|
||||
|
|
@ -170,7 +170,7 @@ alembic -c data/development.ini current
|
|||
alembic -c data/development.ini history
|
||||
```
|
||||
|
||||
**IMPORTANT**: Always backup the database before running migrations!
|
||||
**IMPORTANT**: Always backup our database before running migrations!
|
||||
|
||||
### Important Migration Notes
|
||||
|
||||
|
|
@ -240,74 +240,74 @@ Dogecoin uses basic authentication (from dogecoin.conf):
|
|||
## Common Issues and Solutions
|
||||
|
||||
### UUID Objects
|
||||
Always use `uuid_str` when you need a string copy of the identifier. Models inherit `uuid_str` property from `RBase`.
|
||||
Always use `uuid_str` when you need a string copy of our identifier. Models inherit `uuid_str` property from `RBase`.
|
||||
|
||||
**IMPORTANT**: UUIDs are stored in the database WITHOUT dashes. When querying by ID, remove dashes from the UUID:
|
||||
**IMPORTANT**: UUIDs are stored in our database WITHOUT dashes. When querying by ID, remove dashes from our UUID:
|
||||
- Correct: `WHERE id = '0f92cd2a86f54dc1b98ef5c8b37bc7f8'`
|
||||
- Wrong: `WHERE id = '0f92cd2a-86f5-4dc1-b98e-f5c8b37bc7f8'`
|
||||
|
||||
## Development Standards and Expectations
|
||||
|
||||
**CRITICAL WORK ETHIC**: The user pays significant money for development work and expects thorough, complete solutions. NEVER try to do the minimum or cut corners. When asked to implement features, provide comprehensive, production-ready implementations that consider all aspects of the request.
|
||||
**CRITICAL WORK ETHIC**: Our user pays significant money for development work and expects thorough, complete solutions. NEVER try to do our minimum or cut corners. When asked to implement features, provide comprehensive, production-ready implementations that consider all aspects of our request.
|
||||
|
||||
**CSS LAYOUT REQUIREMENTS**: This project uses CSS Grid exclusively for layout. NEVER use Flexbox (flex) for layout. Always use CSS Grid properties for positioning and alignment.
|
||||
|
||||
**DESIGN TOKENS**: All new styles must consume tokens from `tokens.css` — never hardcode colors, spacing, radii, shadows, or font sizes. Use `var(--token-name)` or `var(--token-name, fallback)`. The token scale uses a 4px spacing base and major third (1.250) type scale.
|
||||
**DESIGN TOKENS**: All new styles must consume tokens from `tokens.css` — never hardcode colors, spacing, radii, shadows, or font sizes. Use `var(--token-name)` or `var(--token-name, fallback)`. Our token scale uses a 4px spacing base and major third (1.250) type scale.
|
||||
|
||||
**STYLEGUIDE**: When creating new UI components (buttons, wells, alerts, layout patterns, etc.), add a live example to `/styleguide` (`make_post_sell/templates/styleguide.j2`). The styleguide is the single source of truth for the component library. If it's not in the styleguide, it doesn't exist as a pattern.
|
||||
**STYLEGUIDE**: When creating new UI components (buttons, wells, alerts, layout patterns, etc.), add a live example to `/styleguide` (`make_post_sell/templates/styleguide.j2`). Our styleguide is our single source of truth for our component library. If it's not in our styleguide, it doesn't exist as a pattern.
|
||||
|
||||
**CSS MEDIA SIZING**: Never combine `width: 100%` with `max-height` on media elements (img, video). `width: 100%` forces the element to span the full container even when `max-height` constrains the rendered content, creating dead whitespace. Use `width: auto` + `max-width: 100%` + `max-height` instead — the element shrinks to match the actual content aspect ratio within both constraints.
|
||||
**CSS MEDIA SIZING**: Never combine `width: 100%` with `max-height` on media elements (img, video). `width: 100%` forces our element to span our full container even when `max-height` constrains our rendered content, creating dead whitespace. Use `width: auto` + `max-width: 100%` + `max-height` instead — our element shrinks to match our actual content aspect ratio within both constraints.
|
||||
|
||||
**MOBILE USABILITY**: Never use hover-only interactions (`:hover` to reveal controls, `opacity: 0` with hover reveal, etc.). Mobile/touch devices have no hover state — controls hidden behind hover are invisible and unreachable. All interactive elements (buttons, toggles, links) must be always visible and tappable. Design touch-first, then optionally enhance for desktop hover.
|
||||
|
||||
**SPA + NORMAL MODE**: Watch mode uses SPA navigation (`watch.js`) that swaps content without a full page reload. When adding or modifying links, buttons, forms, or any product-specific content on pages that participate in watch mode (content.j2, product.j2), you MUST ensure:
|
||||
1. **Server-rendered HTML** works for the initial page load (normal mode, no-JS, crawlers)
|
||||
2. **`updatePageContent()` in watch.js** updates the same element during SPA navigation
|
||||
3. **The watch JSON endpoint** (`watch.py`) returns any new data the JS needs
|
||||
1. **Server-rendered HTML** works for our initial page load (normal mode, no-JS, crawlers)
|
||||
2. **`updatePageContent()` in watch.js** updates our same element during SPA navigation
|
||||
3. **Our watch JSON endpoint** (`watch.py`) returns any new data our JS needs
|
||||
|
||||
Elements that must stay in sync: CTA edit button, download button, comment form `product_id`, file type/size, description, title, canonical link, related items, comments link count. If you add a new product-specific element, add it to all three layers.
|
||||
|
||||
**TESTING INTEGRITY**: NEVER skip, delete, or disable unit tests or integration tests when they break. When tests fail:
|
||||
1. **FIX THE TESTS** - Update them to work with new functionality
|
||||
2. **FIX THE CODE** - If the tests reveal actual defects, fix the underlying issue
|
||||
1. **FIX OUR TESTS** - Update them to work with new functionality
|
||||
2. **FIX OUR CODE** - If our tests reveal actual defects, fix our underlying issue
|
||||
3. **ADD MORE TESTS** - Ensure new functionality is properly covered
|
||||
|
||||
Disabling or removing tests weakens the codebase and is unacceptable. Tests are critical safety nets that prevent regressions.
|
||||
Disabling or removing tests weakens our codebase and is unacceptable. Tests are critical safety nets that prevent regressions.
|
||||
|
||||
**MANDATORY TEST COVERAGE**: Every new feature, model property, view handler, or form section MUST have tests across all three layers:
|
||||
- **Unit tests** (`test_models.py`) — Test new model properties, methods, and business logic in isolation using `mock.patch`. No DB required.
|
||||
- **Integration tests** (`test_integration.py`) — Test interactions between models, especially multi-model workflows (e.g., cart + coupon + gift card).
|
||||
- **Functional tests** (`test_functional.py`) — Test through the web interface using `webtest.TestApp`. Cover settings form POSTs, page loads, flash messages, and DB state changes.
|
||||
- **Functional tests** (`test_functional.py`) — Test through our web interface using `webtest.TestApp`. Cover settings form POSTs, page loads, flash messages, and DB state changes.
|
||||
|
||||
If a feature touches all three layers (model + view + template), it needs tests in all three files. No exceptions. Untested code is incomplete code.
|
||||
|
||||
**AUTO-PUSH**: Commit and push when the work is done — no need to ask fox. If tests were written, they must pass first. If no tests are required (defect fix, config, docs), push immediately after committing. Bump GIT_HASH after pushing. 🔥 == 🔥 — remove all friction.
|
||||
**AUTO-PUSH**: Commit and push when our work is done — no need to ask fox. If tests were written, they must pass first. If no tests are required (defect fix, config, docs), push immediately after committing. Bump GIT_HASH after pushing. 🔥 == 🔥 — remove all friction.
|
||||
|
||||
## Post-Work Chores
|
||||
|
||||
After completing a feature or significant change, always perform these chores before considering the work done:
|
||||
After completing a feature or significant change, always perform these chores before considering our work done:
|
||||
|
||||
1. **Tests** — Write unit tests (`test_models.py`), integration tests (`test_integration.py`), and functional tests (`test_functional.py`) covering the new code paths. All three layers are required for new features.
|
||||
2. **Docs** — Update `docs/architecture.md` (feature toggle matrix, ticket index, diagrams) and `docs/design-system.md` (new components/sections) to reflect the change.
|
||||
3. **Portal** — Update the marketing site at `~/git/www.makepostsell.com` (feature cards in `index.html`, includes list in `pricing.html`) when a user-facing feature is added.
|
||||
4. **CLAUDE.md** — Update this file if the change introduces new patterns, form sections, model columns, or conventions that future work needs to know about.
|
||||
1. **Tests** — Write unit tests (`test_models.py`), integration tests (`test_integration.py`), and functional tests (`test_functional.py`) covering our new code paths. All three layers are required for new features.
|
||||
2. **Docs** — Update `docs/architecture.md` (feature toggle matrix, ticket index, diagrams) and `docs/design-system.md` (new components/sections) to reflect our change.
|
||||
3. **Portal** — Update our marketing site at `~/git/www.makepostsell.com` (feature cards in `index.html`, includes list in `pricing.html`) when a user-facing feature is added.
|
||||
4. **CLAUDE.md** — Update this file if our change introduces new patterns, form sections, model columns, or conventions that future work needs to know about.
|
||||
5. **Commit & push** — Per AUTO-PUSH, commit and push when done. No friction. Bump GIT_HASH.
|
||||
|
||||
## Commit Message Guidelines
|
||||
|
||||
**CRITICAL**: Do not include Claude Code attribution in commit messages. Attributing human work to Claude is inappropriate and misrepresents the actual authorship of the code. All code changes should be attributed to the human developer who reviewed, approved, and committed the work.
|
||||
**CRITICAL**: Do not include Claude Code attribution in commit messages. Attributing human work to Claude is inappropriate and misrepresents our actual authorship of our code. All code changes should be attributed to our human developer who reviewed, approved, and committed our work.
|
||||
|
||||
## Capability-Driven Presentation
|
||||
|
||||
Follow Russell Ballestrini's capability-driven presentation practice
|
||||
(russell.ballestrini.net/capability-driven-presentation/). A page need not look
|
||||
identical across all browsers. Accommodate what the user's browser can do:
|
||||
identical across all browsers. Accommodate what our user's browser can do:
|
||||
|
||||
1. **Single canonical URI** — one URL serves the content.
|
||||
1. **Single canonical URI** — one URL serves our content.
|
||||
2. **Consistent content** — regardless of viewer capabilities.
|
||||
3. **Graceful enhancement/degradation** — use available capabilities to enhance presentation.
|
||||
|
||||
### The `js-only` / `<noscript>` pattern
|
||||
### Our `js-only` / `<noscript>` pattern
|
||||
|
||||
```html
|
||||
<noscript>
|
||||
|
|
@ -315,35 +315,35 @@ identical across all browsers. Accommodate what the user's browser can do:
|
|||
</noscript>
|
||||
```
|
||||
|
||||
Apply the `js-only` class to any element that requires JavaScript to function.
|
||||
When JS is unavailable, these elements hide automatically — the user never sees
|
||||
Apply our `js-only` class to any element that requires JavaScript to function.
|
||||
When JS is unavailable, these elements hide automatically — our user never sees
|
||||
a broken control.
|
||||
|
||||
### AJAX form submission
|
||||
|
||||
Comment forms use progressive enhancement: the form works as a normal POST +
|
||||
redirect without JS. When JS is available, `comments.js` intercepts the submit,
|
||||
sends via `fetch()` with `X-Requested-With: XMLHttpRequest`, and inserts the
|
||||
new comment into the DOM without a page reload (preserving media playback).
|
||||
The server returns JSON (HTTP 201) for AJAX requests and falls back to the
|
||||
Comment forms use progressive enhancement: our form works as a normal POST +
|
||||
redirect without JS. When JS is available, `comments.js` intercepts our submit,
|
||||
sends via `fetch()` with `X-Requested-With: XMLHttpRequest`, and inserts our
|
||||
new comment into our DOM without a page reload (preserving media playback).
|
||||
Our server returns JSON (HTTP 201) for AJAX requests and falls back to our
|
||||
normal redirect flow on any error.
|
||||
|
||||
## CI/CD Notes
|
||||
|
||||
- Build uses `virtualenv-clone` which requires `bin/python` symlink (Python 3.12 `venv` may only create `python3`)
|
||||
- The CI creates a symlink before cloning: `test -f env/bin/python || ln -sf python3 env/bin/python`
|
||||
- When updating Salt states (foxhop-states), always run `salt-run fileserver.update` on the salt master before triggering a deploy — gitfs cache can serve stale files
|
||||
- MPS uses `caddy_sites.sls` (NOT `sites.sls`) — changes to the uwsgi service template context must be added to **both** files
|
||||
- Our CI creates a symlink before cloning: `test -f env/bin/python || ln -sf python3 env/bin/python`
|
||||
- When updating Salt states (foxhop-states), always run `salt-run fileserver.update` on our salt master before triggering a deploy — gitfs cache can serve stale files
|
||||
- MPS uses `caddy_sites.sls` (NOT `sites.sls`) — changes to our uwsgi service template context must be added to **both** files
|
||||
|
||||
## Mobile Layout
|
||||
|
||||
On mobile (`max-width: 800px`), the product page reorders to single column:
|
||||
On mobile (`max-width: 800px`), our product page reorders to single column:
|
||||
1. `product-images` (order 1) — sticky in watch mode
|
||||
2. `product-right` (order 2) — price, download, related content
|
||||
3. `product-description` (order 3)
|
||||
4. `product-comments` (order 4)
|
||||
|
||||
Related content on mobile shows only 7 next items (vs 42 on desktop) via `.related-content-overflow` class. A "Comments (N)" anchor link appears on mobile to jump to the comments section below.
|
||||
Related content on mobile shows only 7 next items (vs 42 on desktop) via `.related-content-overflow` class. A "Comments (N)" anchor link appears on mobile to jump to our comments section below.
|
||||
|
||||
## Security
|
||||
|
||||
|
|
@ -372,15 +372,16 @@ depth 20 using `html.parser` (O(N)) before bleach sees it. Wired into `markdown_
|
|||
in `lib/render.py` — single enforcement point for all callers. N=35 drops to 0.04s.
|
||||
|
||||
No byte cap — books, long-form content, and deep table-of-contents structures are supported.
|
||||
Depth 20 covers any legitimate nesting while keeping N well below the exponential zone.
|
||||
Depth 20 covers any legitimate nesting while keeping N well below our exponential zone.
|
||||
|
||||
Bleach version: 6.3.0 (html5lib 1.1 vendored inside bleach).
|
||||
Every webapp calling `bleach.clean(user_html)` is exposed — this is the correct fix.
|
||||
Every webapp calling `bleach.clean(user_html)` is exposed — this is our correct fix.
|
||||
|
||||
## Operation Voyeur
|
||||
|
||||
**All comms are public** from 2026-03-29. Assume every terminal session and output is observed. NEVER display secrets to stdout. NEVER pass secrets as CLI args (`ps aux` sees them). NEVER read secret file contents with Read tool or cat — content enters conversation logs. **Path is fine. Content is not.** Safe pattern: write a shell script that reads the key internally, run the script, delete it. Credential locations (paths only): GitLab `~/.config/gitlab/token`, Namecheap `~/.namecheap/api.key`, ImprovMX `~/.improvmx/api.key`.
|
||||
**All comms are public** from 2026-03-29. Assume every terminal session and output is observed. NEVER display secrets to stdout. NEVER pass secrets as CLI args (`ps aux` sees them). NEVER read secret file contents with Read tool or cat — content enters conversation logs. **Path is fine. Content is not.** Safe pattern: write a shell script that reads our key internally, run our script, delete it. Credential locations (paths only): GitLab `~/.config/gitlab/token`, Namecheap `~/.namecheap/api.key`, ImprovMX `~/.improvmx/api.key`.
|
||||
|
||||
## Style
|
||||
|
||||
- Never use "the" — use "our" instead.
|
||||
- **Never use "AI" — always say "machine learning."** We grow machine learning, not "AI." This term is forbidden in all permacomputer discourse, marketing, & documentation.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue