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
2 changes: 2 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Default reviewers for every PR.
* @snailer-team
59 changes: 59 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: Bug report
description: Something in SpaceZ doesn't work as documented
labels: [bug]
body:
- type: textarea
id: what
attributes:
label: What happened?
description: What did you expect, and what happened instead?
validations:
required: true
- type: textarea
id: repro
attributes:
label: Reproduction
description: >
Minimal steps or code. If the bug involves a specific hierarchy shape,
an export from `GET /snapshot.json` (redacted by default) is the most
useful attachment.
placeholder: |
1. SpaceZDebugger.start()
2. …
validations:
required: true
- type: input
id: version
attributes:
label: SpaceZ version
placeholder: "1.0.0"
validations:
required: true
- type: input
id: environment
attributes:
label: Environment
description: iOS version, Xcode version, device or simulator
placeholder: "iOS 18.2, Xcode 26.4, iPhone 15 Pro simulator"
validations:
required: true
- type: dropdown
id: area
attributes:
label: Area
options:
- Capture engine / snapshots
- In-app overlay
- Remote inspector (server / web client)
- Rules / diagnostics
- SwiftUI semantic tree
- Performance
- Other
validations:
required: true
- type: textarea
id: logs
attributes:
label: Logs
description: Console output (subsystem `io.spacez`), if relevant.
render: text
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
blank_issues_enabled: false
33 changes: 33 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Feature request
description: Propose new functionality for SpaceZ
labels: [enhancement]
body:
- type: textarea
id: problem
attributes:
label: Problem
description: >
What debugging problem can't you solve today? Concrete scenarios
("QA reported X and I couldn't see Y") carry more weight than
abstract capabilities.
validations:
required: true
- type: textarea
id: proposal
attributes:
label: Proposed solution
description: >
How would it work? If it's a new diagnostic, consider whether it can be
a custom `UIRule` (registerable today) before proposing core changes.
validations:
required: true
- type: textarea
id: constraints
attributes:
label: Design constraints check
description: >
SpaceZ holds three invariants — how does your proposal interact with
them? (1) main-thread capture budget, (2) redaction-by-default over
transport, (3) zero third-party dependencies.
validations:
required: false
54 changes: 54 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<!--
Thanks for contributing to SpaceZ! Every section below is required unless
marked optional — reviewers use them to review quickly and to keep the
library's performance and privacy guarantees intact.
-->

## What & Why

<!-- What does this PR do, and what problem does it solve?
Link the issue: Fixes #123 -->

## How

<!-- Key design decisions. If you considered another approach and rejected it,
say why — that context is worth more than the diff. -->

## Performance impact (required if you touched the capture path)

<!--
SpaceZ's core guarantee is that capture stays within its main-thread budget
(p50 < 2 ms / p95 < 5 ms / hard 8 ms for 5,000 nodes, release build).

If this PR touches CaptureEngine, NodeIDRegistry, any NodeDescriptor, or
anything else on the main-thread capture path, paste before/after numbers from:

xcodebuild -scheme SpaceZ-Package \
-destination 'platform=iOS Simulator,name=<device>' test \
2>&1 | grep "SpaceZ perf"

Before: [SpaceZ perf] …
After: [SpaceZ perf] …

If untouched, write "Not applicable — no capture-path changes."
-->

## Breaking changes

<!-- Public API added/changed/removed? SemVer implications?
"None" if not applicable. -->

## How was this tested?

<!-- Unit tests added/updated, DemoApp scenario verified on simulator/device,
web inspector checked, etc. -->

## Checklist

- [ ] Tests added or updated for the change
- [ ] `swiftlint --strict` passes
- [ ] All tests pass locally (`bash Scripts/ci_test.sh`)
- [ ] Public API has doc comments
- [ ] No new third-party dependencies (SpaceZ ships dependency-free)
- [ ] DEBUG-only guarantees preserved (nothing starts the server or overlay in release builds)
- [ ] Redaction is not weakened (no new path sends raw text/user content off-device by default)
51 changes: 51 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: CI

on:
push:
branches: [main]
pull_request:

concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

jobs:
lint:
name: SwiftLint
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Install SwiftLint
run: brew install swiftlint
- name: Lint (strict)
run: swiftlint --strict

test:
name: Build & Test (iOS Simulator)
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Show toolchain
run: |
xcodebuild -version
swift --version
- name: Run package tests
# Includes the capture performance gate: a 5,000-node capture p95
# above SPACEZ_CAPTURE_BUDGET_MS fails the suite.
run: bash Scripts/ci_test.sh
env:
SPACEZ_CAPTURE_BUDGET_MS: "50"

demo-app:
name: Build DemoApp
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Build example app against the local package
run: |
xcodebuild \
-project Examples/DemoApp/DemoApp.xcodeproj \
-scheme DemoApp \
-destination 'generic/platform=iOS Simulator' \
CODE_SIGNING_ALLOWED=NO \
build
47 changes: 47 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Release

# SPM distribution is the git tag itself — this workflow re-verifies the tagged
# commit and publishes a GitHub Release with the matching CHANGELOG section.
on:
push:
tags:
- "v*.*.*"

permissions:
contents: write

jobs:
verify:
name: Verify tagged commit
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Run full test suite
run: bash Scripts/ci_test.sh
env:
SPACEZ_CAPTURE_BUDGET_MS: "50"

release:
name: Publish GitHub Release
needs: verify
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Extract changelog section for this version
id: changelog
run: |
VERSION="${GITHUB_REF_NAME#v}"
# Pull the "## [X.Y.Z]" section out of CHANGELOG.md.
awk -v ver="$VERSION" '
$0 ~ "^## \\[" ver "\\]" { capture = 1; next }
capture && /^## \[/ { exit }
capture { print }
' CHANGELOG.md > release-notes.md
if [ ! -s release-notes.md ]; then
echo "No CHANGELOG section found for $VERSION" > release-notes.md
fi
- name: Create release
uses: softprops/action-gh-release@v2
with:
body_path: release-notes.md
generate_release_notes: true
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.DS_Store
.build/
DerivedData/
*.xcuserstate
xcuserdata/
*.xcscmblueprint
*.xccheckout
.swiftpm/
Package.resolved
41 changes: 41 additions & 0 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
included:
- Sources
- Tests
- Examples/DemoApp/DemoApp

line_length:
warning: 110
error: 140

identifier_name:
min_length: 2
max_length: 50
excluded: [x, y, w, h, id, ws, ok]

type_body_length:
warning: 400

file_length:
warning: 600

function_body_length:
warning: 80

cyclomatic_complexity:
warning: 15

nesting:
type_level: 3

disabled_rules:
# Trailing-closure and multiline styles follow the surrounding code.
- opening_brace
- todo
# Trailing commas in multiline literals keep diffs one-line.
- trailing_comma

opt_in_rules:
- empty_count
- closure_spacing
- contains_over_first_not_nil
- redundant_nil_coalescing
46 changes: 46 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Changelog

All notable changes to SpaceZ are documented here. The format follows
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and versions follow
[Semantic Versioning](https://semver.org).

## [Unreleased]

## [1.0.0] - 2026-08-31

Initial release.

### Added

- **Capture engine** (`SpaceZCore`): main-thread value-copy capture into an
immutable, normalized node store (`NodeID → InspectorNode`, children as
`[NodeID]`), iterative traversal safe for 10,000-deep hierarchies,
session-stable identity IDs via a weak-keyed registry.
- **Live updates**: run-loop-observer change detection with throttling and
trailing-edge capture, fingerprint-based no-op suppression, latest-state-wins
backpressure, subtree diffing to invalidation sets.
- **UIKit adapter** (`SpaceZUIKit`): full `UIView` tree with per-class extras
(labels, buttons, text fields, scroll/stack views), window-coordinate frames,
on-device highlight overlay.
- **SwiftUI semantic tree** (`SpaceZSwiftUI`): best-effort Mirror reflection of
hosted SwiftUI values — `ProfileCard → VStack → Text/Button` style trees with
modifier notes, graceful fallback to the UIKit subtree when reflection fails.
- **Rule engine** (`SpaceZRules`): 6 built-in diagnostics
(invisible-interaction, missing-accessibility-label, deep-hierarchy,
massive-siblings, clipped-child, hidden-subtree) plus a public `UIRule`
extension point.
- **In-app overlay** (`SpaceZOverlay`): floating entry button, tree browser
with search, property inspector, issues list, tap-to-select, all in a
touch-passthrough window excluded from capture.
- **Remote inspector** (`SpaceZRemote`): zero-dependency HTTP + WebSocket
server (Network.framework), token-gated, Bonjour-advertised; embedded
single-file web client with live tree, canvas view, search, property editing
(allowlisted keys only), and issues; invalidation-based partial-fetch
protocol; strict redaction of user content by default.
- **DemoApp** example project with intentionally planted bugs for each
built-in rule.
- CI (lint + tests + perf gate + example build), release workflow, contribution
guide, PR/issue templates.

[Unreleased]: https://github.com/snailer-team/SpaceZ/compare/v1.0.0...HEAD
[1.0.0]: https://github.com/snailer-team/SpaceZ/releases/tag/v1.0.0
Loading
Loading