|
| 1 | +# Suggested Improvements to Copilot Instructions |
| 2 | + |
| 3 | +Based on the comparison between the AI-generated approach (this PR) and the human-written approach (PR #294), here are suggestions to improve the Copilot instructions to help produce better results in the future. |
| 4 | + |
| 5 | +## Key Lessons Learned |
| 6 | + |
| 7 | +### 1. **Simpler is Better: Extend Existing Workflows Instead of Creating New Ones** |
| 8 | + |
| 9 | +**What I Did (Overly Complex):** |
| 10 | +- Created a completely new `.github/workflows/check-visionos.yml` workflow file |
| 11 | +- Added extensive diagnostic steps and special case handling |
| 12 | +- Tried to handle all edge cases in the workflow itself |
| 13 | + |
| 14 | +**What Should Have Been Done (PR #294 Approach):** |
| 15 | +- Extended the existing `.github/workflows/check.yml` with a new job |
| 16 | +- Used conditional execution: `if: github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'Ferric 🦀')` |
| 17 | +- Kept the workflow simple and focused on just the necessary steps |
| 18 | + |
| 19 | +**Instruction Improvement:** |
| 20 | +```markdown |
| 21 | +## Workflow Guidelines |
| 22 | + |
| 23 | +- **Prefer extending existing workflows** over creating new ones unless there's a strong reason |
| 24 | +- **Use conditional job execution** (`if:` clauses) rather than separate workflow files |
| 25 | +- **Keep workflows simple** - avoid extensive diagnostic steps unless debugging a specific issue |
| 26 | +- **Follow existing patterns** in the repo's workflows for consistency |
| 27 | +``` |
| 28 | + |
| 29 | +### 2. **Function Naming: Be Clear About What Functions Actually Do** |
| 30 | + |
| 31 | +**What I Did (Confusing):** |
| 32 | +- Tried to make `getInstalledTargets()` return tier 3 targets based on build-std availability |
| 33 | +- Created confusion about what "installed" means |
| 34 | + |
| 35 | +**What Should Have Been Done (PR #294 Approach):** |
| 36 | +- Renamed to `ensureAvailableTargets()` to better reflect that it checks availability, not just installation |
| 37 | +- Kept `getInstalledTargets()` doing exactly what it says - returning installed targets from rustup |
| 38 | +- Created separate `assertNightlyToolchain()` function for tier 3 validation |
| 39 | + |
| 40 | +**Instruction Improvement:** |
| 41 | +```markdown |
| 42 | +## Code Quality Guidelines |
| 43 | + |
| 44 | +- **Function names should precisely describe what they do** - avoid stretching function purposes |
| 45 | +- **When logic changes, consider renaming** - if a function does more than its name suggests, rename it |
| 46 | +- **Separate concerns** - create new functions rather than overloading existing ones |
| 47 | +- **Follow existing naming patterns** in the codebase (e.g., `ensureAvailableTargets` vs `ensureInstalledTargets`) |
| 48 | +``` |
| 49 | + |
| 50 | +### 3. **Minimal Changes: Don't Over-Engineer Solutions** |
| 51 | + |
| 52 | +**What I Did (Over-Engineered):** |
| 53 | +- Added complex build-std detection logic |
| 54 | +- Created extensive error messaging with multiple steps |
| 55 | +- Built comprehensive diagnostic capabilities |
| 56 | +- Tried to handle every possible edge case upfront |
| 57 | + |
| 58 | +**What Should Have Been Done (PR #294 Approach):** |
| 59 | +- Simple tier 3 target detection using a `Set` |
| 60 | +- Straightforward `assertNightlyToolchain()` check |
| 61 | +- Clear, concise error messages with actionable commands |
| 62 | +- Let users handle their own specific edge cases |
| 63 | + |
| 64 | +**Instruction Improvement:** |
| 65 | +```markdown |
| 66 | +## Simplicity Principles |
| 67 | + |
| 68 | +- **Start with the simplest solution that works** - don't over-engineer |
| 69 | +- **Use standard library features** when available (e.g., `Set.intersection()`) |
| 70 | +- **Avoid premature optimization** - don't add diagnostics unless there's a known problem |
| 71 | +- **Trust the user** - provide clear error messages but don't try to handle every edge case |
| 72 | +- **Incremental complexity** - add complexity only when actually needed, not preemptively |
| 73 | +``` |
| 74 | + |
| 75 | +### 4. **Target Management: Simple Data Structures Are Sufficient** |
| 76 | + |
| 77 | +**What I Did (Complex):** |
| 78 | +- Created `TIER_3_TARGETS` as a readonly array with complex type assertions |
| 79 | +- Added helper functions like `isTier3Target()` with type casting |
| 80 | +- Created conditional logic that checked if targets were in multiple places |
| 81 | + |
| 82 | +**What Should Have Been Done (PR #294 Approach):** |
| 83 | +- Simple `const THIRD_TIER_TARGETS: Set<TargetName> = new Set([...])` |
| 84 | +- Used `Set.intersection()` for checking which tier 3 targets are requested |
| 85 | +- Simple `has()` method for checking membership |
| 86 | + |
| 87 | +**Instruction Improvement:** |
| 88 | +```markdown |
| 89 | +## Data Structure Guidelines |
| 90 | + |
| 91 | +- **Use appropriate data structures** - `Set` for membership testing, not arrays |
| 92 | +- **Leverage built-in methods** - `Set.intersection()`, `Set.has()` vs custom helper functions |
| 93 | +- **Avoid unnecessary type gymnastics** - keep types simple and clear |
| 94 | +- **Consistency** - follow patterns already established in the codebase |
| 95 | +``` |
| 96 | + |
| 97 | +### 5. **Documentation: Link to Code, Not Just Docs** |
| 98 | + |
| 99 | +**What I Did:** |
| 100 | +- Added extensive JSDoc comments with links to Rust documentation |
| 101 | +- Created multi-step instructions in error messages |
| 102 | +- Verbose explanations throughout |
| 103 | + |
| 104 | +**What Should Have Been Done (PR #294 Approach):** |
| 105 | +- Minimal, focused comments |
| 106 | +- Simple function names that are self-documenting |
| 107 | +- Let `assertFixable` provide the command to run |
| 108 | +- Keep error messages concise and actionable |
| 109 | + |
| 110 | +**Instruction Improvement:** |
| 111 | +```markdown |
| 112 | +## Documentation Standards |
| 113 | + |
| 114 | +- **Self-documenting code** - good names reduce need for comments |
| 115 | +- **Concise error messages** - provide the fix command, not a tutorial |
| 116 | +- **Link to official docs only when necessary** - don't overdo it |
| 117 | +- **Follow existing documentation patterns** in the codebase |
| 118 | +``` |
| 119 | + |
| 120 | +### 6. **Testing Strategy: Use Existing Infrastructure** |
| 121 | + |
| 122 | +**What I Did:** |
| 123 | +- Created separate workflow for visionOS testing |
| 124 | +- Added custom diagnostic steps |
| 125 | +- Tried to test in isolation |
| 126 | + |
| 127 | +**What Should Have Been Done (PR #294 Approach):** |
| 128 | +- Added job to existing workflow: `test-ferric-apple-triplets` |
| 129 | +- Used conditional execution based on branch or label |
| 130 | +- Leveraged existing test infrastructure and patterns |
| 131 | + |
| 132 | +**Instruction Improvement:** |
| 133 | +```markdown |
| 134 | +## Testing Approach |
| 135 | + |
| 136 | +- **Use existing test infrastructure** - don't create parallel test systems |
| 137 | +- **Conditional testing** - use branch checks or labels to control when tests run |
| 138 | +- **Integration over isolation** - tests should work within the existing workflow |
| 139 | +- **Label-based triggers** - follow the pattern of using labels like 'Ferric 🦀' for opt-in testing |
| 140 | +``` |
| 141 | + |
| 142 | +## Recommended Additions to `.github/copilot-instructions.md` |
| 143 | + |
| 144 | +Add a new section: |
| 145 | + |
| 146 | +```markdown |
| 147 | +## Code Change Philosophy |
| 148 | + |
| 149 | +### Minimal, Incremental Changes |
| 150 | +- **Start simple** - implement the minimal solution that solves the problem |
| 151 | +- **Extend, don't replace** - modify existing code/workflows rather than creating new ones |
| 152 | +- **Follow patterns** - look at how similar problems are solved elsewhere in the codebase |
| 153 | +- **Incremental complexity** - add features only when actually needed |
| 154 | + |
| 155 | +### Rust/Cargo Integration |
| 156 | +- **Use `assertFixable`** for validation that has a clear fix command |
| 157 | +- **Target management** - use `Set` for collections of targets, leverage built-in methods |
| 158 | +- **Tier 3 targets** - these require nightly Rust with `rust-src` component |
| 159 | +- **Avoid complex detection logic** - simple checks are usually sufficient |
| 160 | + |
| 161 | +### Workflow Development |
| 162 | +- **Extend existing workflows** with new jobs rather than creating separate files |
| 163 | +- **Conditional execution** - use `if:` clauses for branch/label-based job triggers |
| 164 | +- **Keep it simple** - minimal steps, clear purpose, follow existing patterns |
| 165 | +- **Test efficiency** - use labels to control expensive test jobs |
| 166 | +``` |
| 167 | + |
| 168 | +## Summary |
| 169 | + |
| 170 | +The key difference between the two approaches is that PR #294 takes a **simpler, more direct approach** that: |
| 171 | +1. Extends existing infrastructure rather than building new |
| 172 | +2. Uses appropriate data structures and built-in methods |
| 173 | +3. Has clear, focused function responsibilities |
| 174 | +4. Avoids over-engineering and premature optimization |
| 175 | +5. Follows established patterns in the codebase |
| 176 | + |
| 177 | +These principles should guide future AI-assisted development to produce code that better matches the project's style and philosophy. |
0 commit comments