- Modified process_user_avatar method to enqueue Domain::UserAvatarJob for avatar downloads - Made Domain::UserAvatarJob concrete (removed abstract!) with generic HTTP client - Added smart avatar management: handles new avatars, URL changes, and pending re-enqueues - Added comprehensive test coverage for all avatar scenarios - Updated HTTP mocking in specs to use HttpClientMockHelpers pattern - Fixed caused_by_entry handling for chained HTTP requests - Updated .cursorrules with proper HTTP mocking documentation including caused_by_entry: :any The job now automatically downloads user avatars when scanning Bluesky users.
253 lines
11 KiB
Plaintext
253 lines
11 KiB
Plaintext
# How to use this codebase
|
||
|
||
- Run `bin/tapioca dsl` after changing a model or concern.
|
||
- Run `bin/tapioca gems` after changing the Gemfile.
|
||
- Run `srb tc` after making changes to Ruby files to ensure the codebase is typechecked.
|
||
- Run `bin/rspec <path_to_spec_file>` after a spec file is modified.
|
||
- Run `tapioca dsl` if models or concerns are modified.
|
||
- Run `bin/rspec <path_to_spec_file>` to run tests for a single file.
|
||
- There are no view-specific tests, so if a view changes then run the controller tests instead.
|
||
- For instance, if you modify `app/models/domain/post.rb`, run `bin/rspec spec/models/domain/post_spec.rb`. If you modify `app/views/domain/users/index.html.erb`, run `bin/rspec spec/controllers/domain/users_controller_spec.rb`.
|
||
- At the end of a long series of changes, run `just test`.
|
||
- If specs are failing, then fix the failures, and rerun with `bin/rspec <path_to_spec_file>`.
|
||
- If you need to add logging to a Job to debug it, set `quiet: false` on the spec you are debugging.
|
||
|
||
# Typescript Development
|
||
|
||
- React is the only frontend framework used.
|
||
- Styling is done with Tailwind CSS and FontAwesome.
|
||
- Put new typescript files in `app/javascript/bundles/Main/components/`
|
||
|
||
# HTTP Mocking in Job Specs
|
||
|
||
When writing specs for jobs that make HTTP requests, use `HttpClientMockHelpers.init_http_client_mock()` instead of manually creating doubles:
|
||
|
||
```ruby
|
||
# CORRECT: Use HttpClientMockHelpers
|
||
let(:client_mock_config) do
|
||
[
|
||
{
|
||
uri: "https://example.com/api/first-endpoint",
|
||
status_code: 200,
|
||
content_type: "application/json",
|
||
contents: first_response_body,
|
||
},
|
||
{
|
||
uri: "https://example.com/api/second-endpoint",
|
||
status_code: 200,
|
||
content_type: "application/json",
|
||
contents: second_response_body,
|
||
caused_by_entry: :any, # Use this for chained requests
|
||
},
|
||
]
|
||
end
|
||
|
||
before do
|
||
@log_entries =
|
||
HttpClientMockHelpers.init_http_client_mock(
|
||
http_client_mock,
|
||
client_mock_config,
|
||
)
|
||
end
|
||
|
||
# WRONG: Don't create doubles manually
|
||
expect(http_client_mock).to receive(:get).and_return(
|
||
double(status_code: 200, body: response_body, log_entry: double),
|
||
)
|
||
```
|
||
|
||
This pattern:
|
||
|
||
- Creates real HttpLogEntry objects that can be serialized by ActiveJob
|
||
- Follows the established codebase pattern
|
||
- Avoids "Unsupported argument type: RSpec::Mocks::Double" errors
|
||
- Use `caused_by_entry: :any` for HTTP requests that are chained (where one request's log entry becomes the `caused_by_entry` for the next request)
|
||
|
||
# === BACKLOG.MD GUIDELINES START ===
|
||
|
||
# Instructions for the usage of Backlog.md CLI Tool
|
||
|
||
## 1. Source of Truth
|
||
|
||
- Tasks live under **`backlog/tasks/`** (drafts under **`backlog/drafts/`**).
|
||
- Every implementation decision starts with reading the corresponding Markdown task file.
|
||
- Project documentation is in **`backlog/docs/`**.
|
||
- Project decisions are in **`backlog/decisions/`**.
|
||
|
||
## 2. Defining Tasks
|
||
|
||
### **Title**
|
||
|
||
Use a clear brief title that summarizes the task.
|
||
|
||
### **Description**: (The **"why"**)
|
||
|
||
Provide a concise summary of the task purpose and its goal. Do not add implementation details here. It
|
||
should explain the purpose and context of the task. Code snippets should be avoided.
|
||
|
||
### **Acceptance Criteria**: (The **"what"**)
|
||
|
||
List specific, measurable outcomes that define what means to reach the goal from the description. Use checkboxes (`- [ ]`) for tracking.
|
||
When defining `## Acceptance Criteria` for a task, focus on **outcomes, behaviors, and verifiable requirements** rather
|
||
than step-by-step implementation details.
|
||
Acceptance Criteria (AC) define _what_ conditions must be met for the task to be considered complete.
|
||
They should be testable and confirm that the core purpose of the task is achieved.
|
||
**Key Principles for Good ACs:**
|
||
|
||
- **Outcome-Oriented:** Focus on the result, not the method.
|
||
- **Testable/Verifiable:** Each criterion should be something that can be objectively tested or verified.
|
||
- **Clear and Concise:** Unambiguous language.
|
||
- **Complete:** Collectively, ACs should cover the scope of the task.
|
||
- **User-Focused (where applicable):** Frame ACs from the perspective of the end-user or the system's external behavior.
|
||
- _Good Example:_ "- [ ] User can successfully log in with valid credentials."
|
||
- _Good Example:_ "- [ ] System processes 1000 requests per second without errors."
|
||
- _Bad Example (Implementation Step):_ "- [ ] Add a new function `handleLogin()` in `auth.ts`."
|
||
|
||
### Task file
|
||
|
||
Once a task is created it will be stored in `backlog/tasks/` directory as a Markdown file with the format
|
||
`task-<id> - <title>.md` (e.g. `task-42 - Add GraphQL resolver.md`).
|
||
|
||
### Additional task requirements
|
||
|
||
- Tasks must be **atomic** and **testable**. If a task is too large, break it down into smaller subtasks.
|
||
Each task should represent a single unit of work that can be completed in a single PR.
|
||
|
||
- **Never** reference tasks that are to be done in the future or that are not yet created. You can only reference
|
||
previous
|
||
tasks (id < current task id).
|
||
|
||
- When creating multiple tasks, ensure they are **independent** and they do not depend on future tasks.
|
||
Example of wrong tasks splitting: task 1: "Add API endpoint for user data", task 2: "Define the user model and DB
|
||
schema".
|
||
Example of correct tasks splitting: task 1: "Add system for handling API requests", task 2: "Add user model and DB
|
||
schema", task 3: "Add API endpoint for user data".
|
||
|
||
## 3. Recommended Task Anatomy
|
||
|
||
```markdown
|
||
# task‑42 - Add GraphQL resolver
|
||
|
||
## Description (the why)
|
||
|
||
Short, imperative explanation of the goal of the task and why it is needed.
|
||
|
||
## Acceptance Criteria (the what)
|
||
|
||
- [ ] Resolver returns correct data for happy path
|
||
- [ ] Error response matches REST
|
||
- [ ] P95 latency ≤ 50 ms under 100 RPS
|
||
|
||
## Implementation Plan (the how)
|
||
|
||
1. Research existing GraphQL resolver patterns
|
||
2. Implement basic resolver with error handling
|
||
3. Add performance monitoring
|
||
4. Write unit and integration tests
|
||
5. Benchmark performance under load
|
||
|
||
## Implementation Notes (only added after working on the task)
|
||
|
||
- Approach taken
|
||
- Features implemented or modified
|
||
- Technical decisions and trade-offs
|
||
- Modified or added files
|
||
```
|
||
|
||
## 6. Implementing Tasks
|
||
|
||
Mandatory sections for every task:
|
||
|
||
- **Implementation Plan**: (The **"how"**) Outline the steps to achieve the task. Because the implementation details may
|
||
change after the task is created, **the implementation notes must be added only after putting the task in progress**
|
||
and before starting working on the task.
|
||
- **Implementation Notes**: Document your approach, decisions, challenges, and any deviations from the plan. This
|
||
section is added after you are done working on the task. It should summarize what you did and why you did it. Keep it
|
||
concise but informative.
|
||
|
||
**IMPORTANT**: Do not implement anything else that deviates from the **Acceptance Criteria**. If you need to
|
||
implement something that is not in the AC, update the AC first and then implement it or create a new task for it.
|
||
|
||
## 2. Typical Workflow
|
||
|
||
```bash
|
||
# 1 Identify work
|
||
backlog task list -s "To Do" --plain
|
||
|
||
# 2 Read details & documentation
|
||
backlog task 42 --plain
|
||
# Read also all documentation files in `backlog/docs/` directory.
|
||
# Read also all decision files in `backlog/decisions/` directory.
|
||
|
||
# 3 Start work: assign yourself & move column
|
||
backlog task edit 42 -a @{yourself} -s "In Progress"
|
||
|
||
# 4 Add implementation plan before starting
|
||
backlog task edit 42 --plan "1. Analyze current implementation\n2. Identify bottlenecks\n3. Refactor in phases"
|
||
|
||
# 5 Break work down if needed by creating subtasks or additional tasks
|
||
backlog task create "Refactor DB layer" -p 42 -a @{yourself} -d "Description" --ac "Tests pass,Performance improved"
|
||
|
||
# 6 Complete and mark Done
|
||
backlog task edit 42 -s Done --notes "Implemented GraphQL resolver with error handling and performance monitoring"
|
||
```
|
||
|
||
### 7. Final Steps Before Marking a Task as Done
|
||
|
||
Always ensure you have:
|
||
|
||
1. ✅ Marked all acceptance criteria as completed (change `- [ ]` to `- [x]`)
|
||
2. ✅ Added an `## Implementation Notes` section documenting your approach
|
||
3. ✅ Run all tests and linting checks
|
||
4. ✅ Updated relevant documentation
|
||
|
||
## 8. Definition of Done (DoD)
|
||
|
||
A task is **Done** only when **ALL** of the following are complete:
|
||
|
||
1. **Acceptance criteria** checklist in the task file is fully checked (all `- [ ]` changed to `- [x]`).
|
||
2. **Implementation plan** was followed or deviations were documented in Implementation Notes.
|
||
3. **Automated tests** (unit + integration) cover new logic.
|
||
4. **Static analysis**: linter & formatter succeed.
|
||
5. **Documentation**:
|
||
- All relevant docs updated (any relevant README file, backlog/docs, backlog/decisions, etc.).
|
||
- Task file **MUST** have an `## Implementation Notes` section added summarising:
|
||
- Approach taken
|
||
- Features implemented or modified
|
||
- Technical decisions and trade-offs
|
||
- Modified or added files
|
||
6. **Review**: self review code.
|
||
7. **Task hygiene**: status set to **Done** via CLI (`backlog task edit <id> -s Done`).
|
||
8. **No regressions**: performance, security and licence checks green.
|
||
|
||
⚠️ **IMPORTANT**: Never mark a task as Done without completing ALL items above.
|
||
|
||
## 9. Handy CLI Commands
|
||
|
||
| Purpose | Command |
|
||
| ---------------- | ---------------------------------------------------------------------- |
|
||
| Create task | `backlog task create "Add OAuth"` |
|
||
| Create with desc | `backlog task create "Feature" -d "Enables users to use this feature"` |
|
||
| Create with AC | `backlog task create "Feature" --ac "Must work,Must be tested"` |
|
||
| Create with deps | `backlog task create "Feature" --dep task-1,task-2` |
|
||
| Create sub task | `backlog task create -p 14 "Add Google auth"` |
|
||
| List tasks | `backlog task list --plain` |
|
||
| View detail | `backlog task 7 --plain` |
|
||
| Edit | `backlog task edit 7 -a @{yourself} -l auth,backend` |
|
||
| Add plan | `backlog task edit 7 --plan "Implementation approach"` |
|
||
| Add AC | `backlog task edit 7 --ac "New criterion,Another one"` |
|
||
| Add deps | `backlog task edit 7 --dep task-1,task-2` |
|
||
| Add notes | `backlog task edit 7 --notes "We added this and that feature because"` |
|
||
| Mark as done | `backlog task edit 7 -s "Done"` |
|
||
| Archive | `backlog task archive 7` |
|
||
| Draft flow | `backlog draft create "Spike GraphQL"` → `backlog draft promote 3.1` |
|
||
| Demote to draft | `backlog task demote <task-id>` |
|
||
|
||
## 10. Tips for AI Agents
|
||
|
||
- **Always use `--plain` flag** when listing or viewing tasks for AI-friendly text output instead of using Backlog.md
|
||
interactive UI.
|
||
- When users mention to create a task, they mean to create a task using Backlog.md CLI tool.
|
||
|
||
# === BACKLOG.MD GUIDELINES END ===
|