This project is a solo hobby app, but we use professional workflow standards so the codebase stays maintainable over time.
mainis stable.- Code changes start on a typed feature branch matching the commit prefix:
feature/<topic>— new functionalityfix/<topic>— bug fixeschore/<topic>— cleanup, dead code removal, refactoring with no behavior changedocs/<topic>— documentation only (can also go directly tomain)
- Do not push any branch or
mainwithout explicit approval.
Use clear conventional commit prefixes:
feat:new behaviorfix:bug fixrefactor:internal cleanup with no behavior changedocs:documentation changeschore:project/tooling maintenance
Before pushing:
- Local macOS build passes (
xcodebuildmcp macos build). - Run full local tests (
xcodebuildmcp macos test) for risky behavior changes (conversation flow, streaming, persistence, networking, usage accounting) and before final push checkpoints. - UI changes include a manual UX check.
- Any changed behavior is documented.
- Risks and follow-up work are recorded in notes/changelog.
- Source of truth: Apple SwiftUI Documentation and current Apple HIG direction.
- Prefer native SwiftUI components, Liquid Glass/material surfaces, and SF Symbols.
When changes touch transcript rendering, streaming, or input behavior:
- Validate long-chat scrolling (including while typing).
- Validate streaming auto-scroll and stop/regenerate flows.
- Use the consolidated regression checklist in
/Users/josh/Projects/JChat/Docs/PROJECT_GUIDE.mdbefore push.
- For code changes, create branch:
git checkout -b codex/<topic>. For docs-only changes, work onmain. - Implement one scoped change or small related group of changes.
- Run local checks.
- Commit freely with clear messages.
- Request explicit approval before any push.
- Push only after approval, then merge locally when ready.
- After merge, delete the merged feature branch locally and on origin.
Branch cleanup commands:
git branch -d codex/<topic>
git push origin --delete codex/<topic>This app is a hobby project, so speed matters. Use this simple rule:
Direct Codex(just ask "do that thing"): default for small, low-risk tweaks.Codex Plan mode: use when you need options/tradeoffs before coding.OpenSpec: use when behavior, cost/accounting, state flow, or user-facing UX logic is changing.
Quick decision guide:
- Tiny tweak (about 5-10 minutes, low risk): use
Direct Codex. - Unclear approach or multiple good options: use
Codex Plan modefirst, then execute. - Anything you might need to explain/reverse later: use
OpenSpec. - If uncertain, start direct; upgrade to Plan mode or OpenSpec only if scope grows.
Keep OpenSpec lightweight when used:
- Prefer
/opsx:ff <name>for fast artifact setup. - Keep proposal/design/tasks short and practical.
- Batch a few related small tweaks into one change to reduce overhead.
Source-of-truth boundary:
Docs/: product/user documentation.openspec/: planning artifacts and decision history.
You may use multiple AI tools (Codex, Claude Code, etc.). Keep a clean boundary:
.codex/: Codex-specific config, prompts, and skills..claude/: Claude-specific config/prompts..gemini/(or others): tool-specific config only.Docs/: shared human-readable project docs.openspec/: shared change artifacts and decision history.
Rules to prevent mess:
- Do not duplicate full policy text across tool folders.
- Keep one canonical policy in
CONTRIBUTING.md, and reference it from tool-specific files. - If two docs conflict, update canonical first, then update references.
- Prefer small links and short summaries over copy-paste blocks.
- CI is disabled by choice for this solo workflow.
- Local validation is the quality gate.
- No PR flow is used.
Canonical commands and defaults:
/Users/josh/Projects/JChat/Docs/PROJECT_GUIDE.md
Policy notes:
- Prefer macOS XcodeBuildMCP workflows in this repo.
- Use
xcodebuildmcpfor all Xcode tasks in this repo; do not use rawxcodebuild. - Avoid simulator-target validation in the default iteration loop.
- If a client does not expose wrapper tools, run
xcodebuildmcp ...directly in terminal. - Do not keep re-setting project/scheme defaults on every new thread once they are configured.