- Do not ask the user to “confirm” or “if it looks good” until the code compiles locally with zero build errors.
- After making changes that affect Swift sources or Xcode integration, validate by building the active scheme.
- If the project cannot be built in your environment, clearly state what prevented the build, and provide the exact file and line references you validated.
- If test automation or QA scripts force macOS Appearance to Dark Mode, always restore macOS Appearance back to
Systemat the end of the run. - In Codex Desktop, Swift/Xcode build and test commands commonly need access to Xcode cache directories that are outside the workspace sandbox. For
xcodebuild, SwiftPM, or XCTest runs, request approved Xcode access up front when the command is expected to touch DerivedData, ModuleCache, SourcePackages, simulator caches, or other Xcode-managed cache paths. If a first run fails only because sandboxing blocked one of those paths, rerun the exact same command with approved Xcode access and report it as a sandbox access retry, not as a code or test failure. - Prefer narrow approved command prefixes for trusted repo-local Xcode workflows, such as the canonical AgentSessions build/test commands and
./scripts/xcode_test_stable.sh. Do not use broad auto-approval rules for arbitrary Xcode-looking commands; if a command falls outside the trusted prefixes, request explicit approved Xcode access for that command.
I'll make the following changes:
- File X: Add/modify Y because Z
- File A: Remove B because C
[Immediately proceed with code changes - user has ESC window during explanation]
- Edited file.swift...
Correct: Explain what will be done → Code → Results
❌ Don't: Start with "• Edited file.swift..." before explaining ❌ Don't: Ask "Should I proceed?" or wait for confirmation ❌ Don't: Begin analyzing/thinking without stating the plan upfront
✅ Do: "I'll tighten probe detection by requiring Probe WD for /status sessions and limiting marker matching. This reduces false positives." [then immediately start coding] ✅ Do: State the approach clearly, then flow directly into implementation ✅ Do: Give user the ESC window by printing plan first, but maintain momentum
When user says "plan mode++" - ONLY provide the plan and stop. Wait for explicit approval before coding.
This applies to ALL coding requests. The explanation is for transparency and ESC opportunity, not for breaking flow.
Treat a change as “significant” and always run a build locally before presenting results when any of the following are true:
- Added, moved, or renamed any Swift file (app or tests).
- Modified more than ~40 lines of Swift across the app, or touched 2+ top‑level areas (e.g., Views + Services, Model + Views).
- Introduced or changed concurrency boundaries (actors, Task, async/await), or cross‑module interactions.
- Altered window/layout/toolbar structure or target membership (PBXBuildFile/target Sources).
- Changed build settings, target configuration, Info.plist, or added resources.
It is acceptable to present without building for clearly minor edits, for example:
- One‑line fixes that do not affect types/signatures, string/label copy changes, comment/doc updates, or pure Markdown/JSON assets.
- In case of doubt, prefer to build.
Suggested build steps
- Xcode: Product → Build (active scheme).
- CLI:
xcodebuild -project AgentSessions.xcodeproj -scheme AgentSessions -configuration Debug build(or use your configured build task).
- Prefer the stable test wrapper:
./scripts/xcode_test_stable.sh. - Equivalent direct command:
xcodebuild -project AgentSessions.xcodeproj -scheme AgentSessions -configuration Debug -destination 'platform=macOS,arch=arm64' -derivedDataPath "$PWD/.deriveddata-tests" -parallel-testing-enabled NO clean test
- Rationale: isolates test artifacts/signing state from shared
DerivedData, which avoids intermittentAgentSessionsTests.xctestnested-signature failures.
- Use Conventional Commits for every commit (feat, fix, docs, chore, etc.).
- Include trailers in the commit body:
Tool: Cursor|Codex|Xcode|Manual|Claude|FigmaModel: <model-id>Why: <1 line if behavior/structure changed>
- If you change user‑visible behavior or UI, add:
- A bullet under
[Unreleased]indocs/CHANGELOG.md. - A 1–2 bullet note in
docs/summaries/YYYY-MM.md.
- A bullet under
- Never use emoji in user-facing documentation, including:
- README.md
- GitHub release notes
- CHANGELOG.md
- Other user-facing documentation
- Use clear, concise language without emoji decoration.
- All findings in audits, plans, and reports must be evidence-backed — include file paths, line numbers, or exact output that substantiates each claim.
- Uncertainty must be explicitly labeled as hypothesis (e.g., "Hypothesis: X may cause Y because Z"), never presented as verified fact.
- Avoid probabilistic wording ("likely", "probably", "seems to") for claims that have been verified — use definitive language for verified facts and hypothesis labels for unverified ones.
- When adding/moving/renaming Swift files (app or tests), ensure they are added to
AgentSessions.xcodeprojwith both aPBXFileReferenceand aPBXBuildFilein the correct target. Missing entries will break builds with "Cannot find … in scope".
When creating new Swift files, use the tested Ruby script to add them to the Xcode project:
Script Location
scripts/xcode_add_file.rb - Adds a Swift file to a target with proper PBXFileReference and PBXBuildFile entries.
Usage Examples
Add file to main app target under GitInspector group:
./scripts/xcode_add_file.rb AgentSessions.xcodeproj AgentSessions \
AgentSessions/GitInspector/Models/InspectorKeys.swift \
AgentSessions/GitInspector/ModelsAdd file to test target:
./scripts/xcode_add_file.rb AgentSessions.xcodeproj AgentSessionsTests \
AgentSessionsTests/GitInspectorViewModelTests.swift \
AgentSessionsTestsAdd multiple files:
./scripts/xcode_add_file.rb AgentSessions.xcodeproj AgentSessions \
AgentSessions/GitInspector/Utilities/ColorExtensions.swift \
AgentSessions/GitInspector/Utilities
./scripts/xcode_add_file.rb AgentSessions.xcodeproj AgentSessions \
AgentSessions/GitInspector/Views/StatusHeroSection.swift \
AgentSessions/GitInspector/ViewsVerification Always build after adding files to verify they're properly integrated:
xcodebuild -project AgentSessions.xcodeproj -scheme AgentSessions \
-configuration Debug -destination 'platform=macOS' buildCRITICAL: After ANY modification to project.pbxproj
If you modify AgentSessions.xcodeproj/project.pbxproj directly (NOT using the Ruby script):
- ALWAYS resolve package dependencies first:
xcodebuild -resolvePackageDependencies -project AgentSessions.xcodeproj -scheme AgentSessions
- THEN verify the build succeeds:
xcodebuild -project AgentSessions.xcodeproj -scheme AgentSessions -configuration Debug build
- If package resolution fails or reports "Missing package product", the project.pbxproj was corrupted. Restore from git and use the Ruby script instead.
- If content may exceed the window height, place the main content in a vertical
ScrollViewand keep footer/action controls outside the scroll region so actions remain visible. - Use the shared spacing tokens and dynamic system colors. Avoid ad‑hoc paddings; prefer consistent section spacing and card padding.
- For subtle SwiftUI/AppKit visual changes, first identify the actual rendering layer that paints the visible UI. Do not assume a nearby palette, token, or model value is authoritative. Trace modifiers, custom
NSViewRepresentableviews, layout managers, drawing overrides, cached attributed strings, and alternate render modes as needed; patch the layer that actually draws the pixels, then verify the diff touches that layer.
- Avoid shelling out when a safe
Process+ argument list is possible. Use timeouts and clear, inline error messages for failures. - Never run network operations without an explicit user action and clear UX affordances.
- Do not add feature flags, rollout flags, kill switches, or behavior gates unless the user explicitly asks for feature flags in the current request.
- When uncertain, implement the behavior directly without flags and call out any risks in the summary.
- For remote documentation, header, or API inspection tasks, delegate the fetch to a sub-agent first so the main agent remains responsive.
- Use a hard timeout of 20 seconds per delegated fetch attempt.
- If no useful output is returned within 20 seconds, cancel the attempt and immediately switch to a fallback source.
- Fallback order is: local repository docs/files, then a narrower targeted remote source.
- Do not run repeated unbounded retries; after fallback failure, report the limitation promptly and continue with best-effort local reasoning.
When you search logs, filenames, or code and when you build scripts that might rename/move/delete files, follow these rules. They exist to prevent over‑matching (regex accidents) and accidental data loss.
- Prefer ripgrep (
rg) with fixed‑string mode for markers/tokens:rg -nF "[MY_MARKER v1]" path -g '**/*.jsonl'
- If you must use regex: escape or anchor and include a quick test.
- Brackets
[],(),.,+,?,|,^,$are metacharacters. - For JSON keys, match with quotes and minimal context:
rg -n '"key"\s*:\s*"value"'.
- Brackets
- Always quote variables to prevent globbing and word‑splitting in shell:
grep -F -- "$needle" "$file"(notgrep $needle $file).
- Scope searches with globs and roots; never scan
$HOMEblindly:rg -nF "$MARK" "$ROOT" -g '**/*.jsonl'.
- Verify with a small sample before proceeding:
rg -nF "$MARK" | head -n 20and open a couple of files.
- Produce a brief “confusion matrix” for any non‑trivial match set:
- Count by reason (e.g.,
marker_only,path_only,both). - Show 3 sample paths per bucket.
- Count by reason (e.g.,
- Save manifests for later review (plain text or JSONL).
-
Dry‑run by default
- Every destructive script starts in dry‑run and prints counts, sample paths, and the exact command it would run.
-
Two‑signal match for deletion
- Require at least two independent signals (e.g., marker AND working directory) before deleting. A single grep hit is insufficient.
-
Typed confirmation with exact count
- To proceed, user must pass
--executeand type a confirmation string that includes the count (e.g.,delete 22 files).
- To proceed, user must pass
-
Random sample preview for large sets
- If deleting >20 items, print a random sample of 20 with the fields that justify deletion (e.g., first user line, cwd) before confirmation.
-
Narrow scope and guard rails
- Restrict deletes to an explicit root; refuse to run on
/,$HOME, or a missing/empty$ROOT. - Use
find ... -print0 | xargs -0to handle spaces/newlines safely. - Never run
rm -rfon interpolated paths without printing and pausing first.
- Restrict deletes to an explicit root; refuse to run on
-
Logging and rollback aids
- Save a timestamped manifest of everything scheduled for deletion (and a copy of stdout) to
scripts/probe_scan_output/or a similar audit folder. - Prefer moving to a quarantine folder first (with timestamp) when feasible; hard‑delete only after a second confirmation.
- Save a timestamped manifest of everything scheduled for deletion (and a copy of stdout) to
-
Tests / fixtures (for repo scripts)
- Add positive and negative fixtures that prove the matcher is literal when required (e.g., markers with
[]). - In CI, fail if expanding the pattern increases matches against the fixture corpus unexpectedly.
- Add positive and negative fixtures that prove the matcher is literal when required (e.g., markers with
- Literal marker search in JSONL:
rg -nF "[AS_MARKER v1]" "$ROOT" -g '**/*.jsonl' | cut -d: -f1 | sort -u
- JSON key/value search (escaped quotes):
rg -n '"(cwd|project)"\s*:\s*".*MyProbeDir' "$ROOT" -g '**/*.jsonl'
- Null‑safe deletion (dry‑run):
find "$ROOT" -type f -name '*.jsonl' -print0 | xargs -0 -n100 echo rm -v(prints planned deletes)