Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
c3ffba8
refactor: move the Apple apps into apple/
datlechin Oct 18, 2026
6d07ee3
Merge remote-tracking branch 'origin/main' into refactor/apple-dir
datlechin Oct 18, 2026
14df2b3
build: resolve the Apple scripts and ignores from apple/
datlechin Oct 18, 2026
618d778
ci: run the Apple jobs and checks from apple/
datlechin Oct 18, 2026
0e6c8c4
docs: split the guides between the root and apple/
datlechin Oct 18, 2026
c09d7bb
Merge remote-tracking branch 'origin/main' into refactor/apple-dir
datlechin Oct 18, 2026
76ab8f8
ci(swiftlint): name each annotation's file from the repository root
datlechin Oct 18, 2026
997f4d7
fix(release): read the changelog of a tag cut before the move
datlechin Oct 18, 2026
81330d0
test(ci): pin the cadence check on a release cut before the move
datlechin Oct 18, 2026
5148527
docs(release): cover the 0.82 line across the move
datlechin Oct 18, 2026
2bd2e20
Merge remote-tracking branch 'origin/main' into refactor/apple-dir
datlechin Oct 18, 2026
de79d9c
Merge remote-tracking branch 'origin/main' into refactor/apple-dir
datlechin Oct 18, 2026
b87dbb3
Merge remote-tracking branch 'origin/main' into refactor/apple-dir
datlechin Oct 19, 2026
cb83aae
Merge remote-tracking branch 'origin/main' into refactor/apple-dir
datlechin Oct 19, 2026
26c255c
Merge remote-tracking branch 'origin/main' into refactor/apple-dir
datlechin Oct 19, 2026
6e5a226
Merge remote-tracking branch 'origin/main' into refactor/apple-dir
datlechin Oct 19, 2026
6b49ba7
Merge remote-tracking branch 'origin/main' into refactor/apple-dir
datlechin Oct 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
6 changes: 3 additions & 3 deletions .claude/rules/ai-mcp-security.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
---
paths:
- "TablePro/Core/AI/**/*"
- "TablePro/Core/MCP/**/*"
- "Packages/TableProMacCore/Sources/TableProMCP/**/*"
- "apple/TablePro/Core/AI/**/*"
- "apple/TablePro/Core/MCP/**/*"
- "apple/Packages/TableProMacCore/Sources/TableProMCP/**/*"
---

# AI and MCP
Expand Down
10 changes: 5 additions & 5 deletions .claude/rules/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ paths:

# Changelog

Unreleased changes are towncrier fragments in `changelog.d/`. A release turns them into a `CHANGELOG.md` section with `scripts/release/notes.py assemble` (`RELEASING.md`, Notes). The Linux app is a second towncrier project under the same rules, in `linux/changelog.d/` and `linux/CHANGELOG.md`; its release runs `towncrier build --dir linux` (`linux/docs/releasing.md`).
Unreleased changes are towncrier fragments in `apple/changelog.d/`. A release turns them into an `apple/CHANGELOG.md` section with `apple/scripts/release/notes.py assemble` (`apple/RELEASING.md`, Notes). The Linux app is a second towncrier project under the same rules, in `linux/changelog.d/` and `linux/CHANGELOG.md`; its release runs `towncrier build --dir linux` (`linux/docs/releasing.md`).

- **One file per user-visible change**, named `changelog.d/<PR>.<type>.md`: `<PR>` is the pull request that adds it, `<type>` is `added`, `changed`, `deprecated`, `removed`, `fixed` or `security`. A second entry of the same type in one PR adds a counter, as `towncrier create` does: `3452.fixed.1.md`, then `.2`. The counter does not order entries.
- **One file per user-visible change**, named `apple/changelog.d/<PR>.<type>.md`: `<PR>` is the pull request that adds it, `<type>` is `added`, `changed`, `deprecated`, `removed`, `fixed` or `security`. A second entry of the same type in one PR adds a counter, as `towncrier create` does: `3452.fixed.1.md`, then `.2`. The counter does not order entries.
- **One line, at most 120 characters, ending with a period.** Added and Changed name the new thing (`Open in Window for row inspector text fields.`); Fixed names the bug, not the fix (`Empty context menu when right-clicking a read-only inspector field.`). No file paths or type names.
- **No refs, no credit, no `- ` prefix.** towncrier links the PR named by the file and adds the bullet; `notes.py` adds ` by @login` when the PR's author is not a maintainer.
- **One entry per thing a user would notice.** Defects with the same visible symptom share an entry.
- **No fragment** for a fix to something still unreleased (edit that fragment instead) or for a docs-only change.
- **Only a `chore(release): vX.Y.Z` PR edits `CHANGELOG.md`**, and only a `chore(release): linux-vX.Y.Z` PR edits `linux/CHANGELOG.md`.
- **The lead block and `[CRITICAL]`**: `RELEASING.md`, Notes and Channels.
- `scripts/ci/check-changelog.py` checks both projects' fragment text, headings and lead blocks in Repo Hygiene, then `towncrier build --draft --version 0.0.0` renders the root fragments; `--dir linux` renders the Linux ones. towncrier refuses an unknown type and a non-numeric PR number (`ignore`, `issue_pattern`). In PR title, `--pr` checks that a PR into main names each new fragment after itself, that only a release PR edits a `CHANGELOG.md`, and that a release PR changes nothing else; a Linux one also sets the version.
- **Only a `chore(release): vX.Y.Z` PR edits `apple/CHANGELOG.md`**, and only a `chore(release): linux-vX.Y.Z` PR edits `linux/CHANGELOG.md`.
- **The lead block and `[CRITICAL]`**: `apple/RELEASING.md`, Notes and Channels.
- `scripts/ci/check-changelog.py` checks both projects' fragment text, headings and lead blocks in Repo Hygiene, then `towncrier build --draft --version 0.0.0` renders the fragments of each, with `--dir apple` and `--dir linux`. towncrier refuses an unknown type and a non-numeric PR number (`ignore`, `issue_pattern`). In PR title, `--pr` checks that a PR into main names each new fragment after itself, that only a release PR edits a `CHANGELOG.md`, and that a release PR changes nothing else; a Linux one also sets the version.
69 changes: 36 additions & 33 deletions .claude/rules/ci.md

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions .claude/rules/connection-window.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
---
paths:
- "TablePro/Core/Services/Infrastructure/**/*"
- "TablePro/Models/Connection/**/*"
- "TablePro/Core/Database/DatabaseManager*.swift"
- "Packages/TableProCore/Sources/TableProDatabase/**/*"
- "TablePro/Views/Main/**/*"
- "apple/TablePro/Core/Services/Infrastructure/**/*"
- "apple/TablePro/Models/Connection/**/*"
- "apple/TablePro/Core/Database/DatabaseManager*.swift"
- "apple/Packages/TableProCore/Sources/TableProDatabase/**/*"
- "apple/TablePro/Views/Main/**/*"
---

# Connection windows and sessions
Expand Down
6 changes: 3 additions & 3 deletions .claude/rules/data-grid.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
---
paths:
- "TablePro/Views/Results/**/*"
- "TablePro/Core/DataGrid/**/*"
- "TableProTests/Views/Results/**/*"
- "apple/TablePro/Views/Results/**/*"
- "apple/TablePro/Core/DataGrid/**/*"
- "apple/TableProTests/Views/Results/**/*"
---

# Data grid
Expand Down
18 changes: 9 additions & 9 deletions .claude/rules/data-sync-storage.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
---
paths:
- "TablePro/Core/**/*Storage*.swift"
- "TablePro/Core/**/*Sync*.swift"
- "TablePro/Core/Database/**/*"
- "TablePro/Core/Plugins/PluginMetadataRegistry*.swift"
- "TablePro/Core/Services/Query/**/*"
- "Packages/TableProCore/Sources/TableProSyncTransport/**/*"
- "CloudKit/**/*"
- "apple/TablePro/Core/**/*Storage*.swift"
- "apple/TablePro/Core/**/*Sync*.swift"
- "apple/TablePro/Core/Database/**/*"
- "apple/TablePro/Core/Plugins/PluginMetadataRegistry*.swift"
- "apple/TablePro/Core/Services/Query/**/*"
- "apple/Packages/TableProCore/Sources/TableProSyncTransport/**/*"
- "apple/CloudKit/**/*"
---

# Storage, sync and the database core

This path holds user data. A silent wrong answer here looks exactly like an empty database, so prove late-completion and cancellation behavior with a test.

- **A synced CKRecord type or field reaches CloudKit Production before anything writes it.** Both apps pin the container to Production, where nothing is auto-created, and CloudKit rejects a whole record that carries an undeclared field. Write fields only through `record.fields(SomeSyncField.self)`, never `record["..."]`. To ship one: add it in Development, deploy to Production in the Console, run `scripts/export-cloudkit-schema.sh`, commit `CloudKit/production-schema.ckdb`, then add it to the matching `verifiedInProduction`. `ProductionSchemaParityTests` checks code against the snapshot in both directions, not against the server, so never edit the snapshot by hand: `scripts/export-cloudkit-schema.sh --check` compares it with Production.
- **A storage format stays readable by the previous stable.** Sparkle never downgrades, and a beta user can turn betas off (`RELEASING.md`, Channels).
- **A synced CKRecord type or field reaches CloudKit Production before anything writes it.** Both apps pin the container to Production, where nothing is auto-created, and CloudKit rejects a whole record that carries an undeclared field. Write fields only through `record.fields(SomeSyncField.self)`, never `record["..."]`. To ship one: add it in Development, deploy to Production in the Console, run `apple/scripts/export-cloudkit-schema.sh`, commit `apple/CloudKit/production-schema.ckdb`, then add it to the matching `verifiedInProduction`. `ProductionSchemaParityTests` checks code against the snapshot in both directions, not against the server, so never edit the snapshot by hand: `apple/scripts/export-cloudkit-schema.sh --check` compares it with Production.
- **A storage format stays readable by the previous stable.** Sparkle never downgrades, and a beta user can turn betas off (`apple/RELEASING.md`, Channels).
- **Persist, then notify.** `SyncChangeTracker.markDeleted()` runs after the storage write, because its notification can start a sync that re-uploads the record from the stale file.
- **Concurrent schema loads await the one in-flight `loadTask`** in `SQLSchemaProvider`; never guard with a flag that returns without data.
- **Every metadata read goes through `DatabaseManager.withMetadataDriver`**, never `MetadataConnectionPool.shared` directly, so an embedded engine with `supportsConnectionPooling = false` (DuckDB, PGlite) stays on its session driver; a second connection to it is a different, empty database.
Expand Down
8 changes: 4 additions & 4 deletions .claude/rules/editor.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
---
paths:
- "Packages/TableProEditor/**/*"
- "TablePro/Theme/**/*"
- "TablePro/Views/Editor/**/*"
- "TablePro/Views/RowInspector/**/*"
- "apple/Packages/TableProEditor/**/*"
- "apple/TablePro/Theme/**/*"
- "apple/TablePro/Views/Editor/**/*"
- "apple/TablePro/Views/RowInspector/**/*"
---

# Editor
Expand Down
10 changes: 5 additions & 5 deletions .claude/rules/libs.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
---
paths:
- "Libs/**/*"
- "scripts/download-libs.sh"
- "scripts/publish-libs.sh"
- "apple/Libs/**/*"
- "apple/scripts/download-libs.sh"
- "apple/scripts/publish-libs.sh"
---

# Static libraries

- **`Libs/` is published only through `scripts/publish-libs.sh <rebuilt .a or .xcframework...>`.** Each run creates the next immutable `libs-<n>` release and writes `Libs/release` and both `checksums.sha256` files, which are committed together. Never edit them by hand: a stale `Libs/` silently reverts other libraries.
- **`apple/Libs/` is published only through `apple/scripts/publish-libs.sh <rebuilt .a or .xcframework...>`.** Each run creates the next immutable `libs-<n>` release and writes `apple/Libs/release` and both `checksums.sha256` files, which are committed together. Never edit them by hand: a stale `apple/Libs/` silently reverts other libraries.
- A published `libs-<n>` never changes; a fix is the next `<n>`. `libs-v1` stays frozen for older commits.
- **`scripts/download-libs.sh` fetches the release `Libs/release` names at `HEAD` and verifies every file against the checksums at `HEAD`** on every run; `--force` re-downloads.
- **`apple/scripts/download-libs.sh` fetches the release `apple/Libs/release` names at `HEAD` and verifies every file against the checksums at `HEAD`** on every run; `--force` re-downloads.
4 changes: 2 additions & 2 deletions .claude/rules/mongodb-driver.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
paths:
- "Plugins/MongoDBDriverPlugin/**/*"
- "Plugins/MQLExportPlugin/**/*"
- "apple/Plugins/MongoDBDriverPlugin/**/*"
- "apple/Plugins/MQLExportPlugin/**/*"
---

# MongoDB driver
Expand Down
10 changes: 5 additions & 5 deletions .claude/rules/mysql-driver.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
---
paths:
- "Plugins/MySQLDriverPlugin/**/*"
- "Packages/TableProCore/Sources/TableProMySQLCore/**/*"
- "TableProMobile/**/*MySQL*"
- "TableProMobile/**/*MariaDB*"
- "apple/Plugins/MySQLDriverPlugin/**/*"
- "apple/Packages/TableProCore/Sources/TableProMySQLCore/**/*"
- "apple/TableProMobile/**/*MySQL*"
- "apple/TableProMobile/**/*MariaDB*"
---

# MySQL and MariaDB driver

- **Every connect sets the session character set with `MariaDBCharacterSet.establishSession`**, because a server may ignore the handshake's charset. Outgoing SQL stays the UTF-8 bytes of the Swift string, and each result cell decodes by its field's own `charsetnr` through `MySQLColumnDecoding`.
- **`MySQLCharacterSet` is a transcription of the server's tables.** Change it only after running `scripts/probes/check-mysql-charset-decoding.sh` against a live server.
- **`MySQLCharacterSet` is a transcription of the server's tables.** Change it only after running `apple/scripts/probes/check-mysql-charset-decoding.sh` against a live server.
- **After a reconnect the user did not ask for, replay a statement only when `MySQLSessionFootprint.isClean`** (`mysqlMayReplay`): the new session has lost variables, `USE`, `sql_mode` and any open transaction. Statements whose answer is session-scoped (`LAST_INSERT_ID` and similar) and the bodies of `/*!NNNNN ... */` count toward the footprint.
14 changes: 7 additions & 7 deletions .claude/rules/native-bridges.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
---
paths:
- "Native/**/*"
- "Plugins/DamengDriverPlugin/**/*"
- "Plugins/HanaDriverPlugin/**/*"
- "scripts/build-dameng.sh"
- "scripts/build-hana.sh"
- "apple/Native/**/*"
- "apple/Plugins/DamengDriverPlugin/**/*"
- "apple/Plugins/HanaDriverPlugin/**/*"
- "apple/scripts/build-dameng.sh"
- "apple/scripts/build-hana.sh"
---

# Native bridges

- **First-party bridge code lives in `Native/<X>Bridge`**, built by `scripts/build-<x>.sh`, with output in a gitignored folder beside the source, never in `Libs/`.
- **First-party bridge code lives in `apple/Native/<X>Bridge`**, built by `apple/scripts/build-<x>.sh`, with output in a gitignored folder beside the source, never in `apple/Libs/`.
- **Rust may run in the app process; Go may not.** The Dameng staticlib is built with `panic = "unwind"`, and every export that does driver work wraps it in `catch_unwind`; a new export that does work takes the same guard. Go's `recover()` cannot catch a panic on a goroutine go-hdb starts, so HANA runs out of process as `tablepro-hana-helper`, one per driver session.
- **Toolchains and upstream code are pinned**: `rust-toolchain.toml`, `Cargo.lock` with `--locked`, the `toolchain` line of `go.mod`, `go.sum`. A protocol change for Dameng lands on the [TableProApp/rust-dameng](https://github.com/TableProApp/rust-dameng) fork first, then the pinned `rev` moves.
- **Every nested Mach-O is signed with Developer ID, the hardened runtime and a timestamp** before the main binary. The `HanaHelperEmbedding` copy phase in `project.yml` signs the HANA helper with the plugin's identity; the plugins' notary submission rejects any executable signed otherwise, and `scripts/release/notarize.sh` prints the log.
- **Every nested Mach-O is signed with Developer ID, the hardened runtime and a timestamp** before the main binary. The `HanaHelperEmbedding` copy phase in `apple/project.yml` signs the HANA helper with the plugin's identity; the plugins' notary submission rejects any executable signed otherwise, and `apple/scripts/release/notarize.sh` prints the log.
Loading
Loading