Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .githooks/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/usr/bin/env bash
set -euo pipefail

ROOT_DIR="$(git rev-parse --show-toplevel)"
cd "$ROOT_DIR"

./scripts/presubmit.sh fast
10 changes: 10 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1 +1,11 @@
# Default owner for all repository files.
* @galz10

# Security-sensitive quality gate surfaces.
/.github/CODEOWNERS @galz10
/.github/workflows/* @galz10
/.githooks/* @galz10
/scripts/install-hooks.sh @galz10
/scripts/maintainability-gate.sh @galz10
/scripts/presubmit.sh @galz10
/scripts/setup.sh @galz10
4 changes: 3 additions & 1 deletion .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ expected results, and edge cases. -->

<!-- Check all that apply before requesting review or merging. -->

- [ ] Builds successfully (`xcodebuild` / Xcode)
- [ ] `lint-docs` check is green
- [ ] `tests` check is green
- [ ] `maintainability` result reviewed (phase 1 report-only)
- [ ] Added/updated tests (if needed)
- [ ] Updated relevant documentation and README (if needed)
- [ ] Noted breaking changes (if any)
Expand Down
137 changes: 137 additions & 0 deletions .github/workflows/presubmit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
name: Presubmit

on:
pull_request:
branches:
- main
push:
branches:
- main

permissions:
contents: read

jobs:
lint-docs:
name: lint-docs
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
runs-on: macos-15
timeout-minutes: 20
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
fetch-depth: 0
persist-credentials: false

- name: Setup Node
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: '20'

- name: Install lint + docs tools
run: |
brew install swiftformat swiftlint lychee
npm install -g markdownlint-cli

- name: Resolve Swift lint diff range
id: diff-range
run: |
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
echo "range=${{ github.event.pull_request.base.sha }}...${{ github.event.pull_request.head.sha }}" >> "$GITHUB_OUTPUT"
elif [[ -n "${{ github.event.before }}" && "${{ github.event.before }}" != "0000000000000000000000000000000000000000" ]]; then
echo "range=${{ github.event.before }}...${{ github.sha }}" >> "$GITHUB_OUTPUT"
else
echo "range=HEAD" >> "$GITHUB_OUTPUT"
fi

- name: Run lint checks
env:
PRESUBMIT_SWIFT_CHANGED_ONLY: '1'
PRESUBMIT_DIFF_RANGE: ${{ steps.diff-range.outputs.range }}
PRESUBMIT_RUN_MAINTAINABILITY: '0'
run: ./scripts/presubmit.sh lint

- name: Run docs checks
env:
PRESUBMIT_MD_CHANGED_ONLY: '1'
PRESUBMIT_DIFF_RANGE: ${{ steps.diff-range.outputs.range }}
run: ./scripts/presubmit.sh docs

tests:
name: tests
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
runs-on: macos-15
timeout-minutes: 45
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
persist-credentials: false

- name: Install test prerequisites
run: |
brew install zig xcodegen

- name: Resolve Ghostty cache key
id: ghostty-cache
run: |
submodule_sha="$(git ls-tree HEAD ghostty | awk '{print $3}')"
if [[ "$submodule_sha" =~ ^[0-9a-f]{40}$ ]]; then
ghostty_sha="$submodule_sha"
else
ghostty_sha="$(git ls-remote https://github.com/manaflow-ai/ghostty.git refs/heads/main | awk '{print $1}')"
fi

if [[ ! "$ghostty_sha" =~ ^[0-9a-f]{40}$ ]]; then
echo "error: failed to resolve Ghostty SHA for cache key" >&2
exit 1
fi

echo "sha=$ghostty_sha" >> "$GITHUB_OUTPUT"

- name: Restore GhosttyKit cache
id: ghosttykit-cache-restore
uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: ~/.cache/idx0/ghosttykit
key: ghosttykit-${{ runner.os }}-${{ runner.arch }}-${{ steps.ghostty-cache.outputs.sha }}
restore-keys: |
ghosttykit-${{ runner.os }}-${{ runner.arch }}-

- name: Setup GhosttyKit
id: setup-ghosttykit
run: ./scripts/setup.sh

- name: Save GhosttyKit cache
if: steps.setup-ghosttykit.conclusion == 'success'
uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: ~/.cache/idx0/ghosttykit
key: ghosttykit-${{ runner.os }}-${{ runner.arch }}-${{ steps.ghostty-cache.outputs.sha }}

- name: Generate Xcode project
run: xcodegen generate

- name: Run test suite
run: ./scripts/presubmit.sh test

maintainability:
name: maintainability
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
runs-on: macos-15
timeout-minutes: 20
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
persist-credentials: false

- name: Install maintainability prerequisites
run: brew install ripgrep

- name: Run maintainability gate (phase 1 report-only)
run: |
if ! ./scripts/maintainability-gate.sh; then
echo "::warning::Maintainability gate reported issues (phase 1 report-only)."
fi
13 changes: 13 additions & 0 deletions .lychee.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
accept = [200, 201, 202, 203, 204, 206, 301, 302, 303, 307, 308, 403, 429]
exclude_all_private = true
include_mail = false
max_retries = 2
retry_wait_time = 2
timeout = 20
user_agent = "idx0-presubmit-link-checker"
exclude = [
"^http://localhost",
"^https://localhost",
"^http://127\\.0\\.0\\.1",
"^https://127\\.0\\.0\\.1"
]
9 changes: 9 additions & 0 deletions .markdownlint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"default": true,
"MD013": false,
"MD033": false,
"MD041": false,
"MD024": {
"siblings_only": true
}
}
6 changes: 6 additions & 0 deletions .swiftformat
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
--swiftversion 6.0
--indent 2
--linebreaks lf
--trimwhitespace always
--stripunusedargs closure-only
--exclude .build,.swiftpm,ghostty,GhosttyKit.xcframework,idx0.xcodeproj
14 changes: 14 additions & 0 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
included:
- idx0
- idx0Tests
- Sources

excluded:
- .build
- .swiftpm
- ghostty
- GhosttyKit.xcframework
- idx0.xcodeproj

disabled_rules:
- todo
26 changes: 14 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ Workspace with an embedded browser tile:
- macOS 14+
- Xcode (project generated for Xcode 26.3)
- `xcodegen`
- Metal toolchain component (`xcodebuild -downloadComponent MetalToolchain`)
- Xcode first-launch components (`xcodebuild -runFirstLaunch`)
- `zig` (only if you need to build `GhosttyKit.xcframework` from source)

## Quick Start (Source Build)
Expand All @@ -77,22 +77,22 @@ Workspace with an embedded browser tile:

```bash
brew install xcodegen
xcodebuild -downloadComponent MetalToolchain
xcodebuild -runFirstLaunch
```

2. Set up GhosttyKit dependency:
1. Set up GhosttyKit dependency:

```bash
./scripts/setup.sh
```

3. Generate the project:
1. Generate the project:

```bash
xcodegen generate
```

4. Open and run:
1. Open and run:

```bash
open idx0.xcodeproj
Expand Down Expand Up @@ -137,22 +137,24 @@ Protocol reference:
## Quality Gates

```bash
# Build + tests
xcodebuild -project idx0.xcodeproj -scheme idx0 -destination 'platform=macOS' test
# Install repo-managed hooks (one-time per clone)
./scripts/install-hooks.sh

# Maintainability policy gate
./scripts/maintainability-gate.sh
# Fast local checks (used by pre-commit)
./scripts/presubmit.sh fast

# Core coverage gate
./scripts/coverage-core.sh
# Full presubmit gates
./scripts/presubmit.sh lint
./scripts/presubmit.sh docs
./scripts/presubmit.sh test
```

## Troubleshooting

- Missing GhosttyKit framework:
- Run `./scripts/setup.sh` and confirm it ends with `==> Done`.
- Build errors for `metal`:
- Run `xcodebuild -downloadComponent MetalToolchain`.
- Run `xcodebuild -runFirstLaunch`.
- CLI tools not appearing:
- Confirm the binaries are on your shell `PATH`.
- If launching from Xcode, verify scheme `PATH` environment values.
25 changes: 16 additions & 9 deletions docs/contribution-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Prerequisites:

```bash
brew install zig xcodegen
xcodebuild -downloadComponent MetalToolchain
xcodebuild -runFirstLaunch
```

Project bootstrap:
Expand Down Expand Up @@ -45,18 +45,23 @@ Suggested branch naming:
- Architecture: `docs/architecture/*`
- Style: `docs/style-guide.md`
- Testing: `docs/testing-guide.md`
2. Confirm ownership boundary:
1. Confirm ownership boundary:
- UI only: `idx0/UI/**`
- Session/platform logic: `idx0/Services/Session/**`
- Workflow/inbox/review logic: `idx0/Services/Workflow/**`
- IPC/CLI contract: `idx0/App/IPCCommandRouter.swift`, `Sources/IPCShared/IPCContract.swift`, `Sources/idx0/idx0.swift`
3. Implement in smallest viable slice.
4. Add/update tests in `idx0Tests/**`.
5. Run local gates:
- `./scripts/maintainability-gate.sh`
- `xcodebuild ... test` (or targeted suites during iteration)
6. Update docs for behavioral, architectural, or protocol changes.
7. Submit PR with risk notes and verification commands.
1. Implement in smallest viable slice.
1. Add/update tests in `idx0Tests/**`.
1. Run local gates:

- `./scripts/install-hooks.sh` (one-time per clone)
- `./scripts/presubmit.sh fast` for quick local iteration
- `./scripts/presubmit.sh lint`
- `./scripts/presubmit.sh docs`
- `./scripts/presubmit.sh test` (or targeted suites during iteration)

1. Update docs for behavioral, architectural, or protocol changes.
1. Submit PR with risk notes and verification commands.

## 5. Change Playbooks

Expand Down Expand Up @@ -129,5 +134,7 @@ A change is done when:
- [ ] Scope is focused and reversible.
- [ ] Tests cover new behavior and regressions.
- [ ] `docs/` updated where behavior/contracts changed.
- [ ] `lint-docs` and `tests` checks are green.
- [ ] `maintainability` report has been reviewed.
- [ ] Commands used for verification listed in PR description.
- [ ] Risks/follow-ups explicitly noted.
Loading
Loading