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
4 changes: 2 additions & 2 deletions .claude/skills/fix-issue/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ Write `<tree>/.analysis/<slug>/plan.md`, under 80 lines, opening with a progress
- the tests that fail before the fix, in the targets the profile's Done section says to check first;
- the changelog fragment, docs, localization and screenshots the change needs.

**Rules read.** List the files `plan.md` touches. Read `<tree>/AGENTS.md` and the platform guide the profile's Done section names, then every `<tree>/.claude/rules/*.md` whose row in the root Area rules table matches one of them, and name them on a `Rules read:` line in `plan.md`. A file added later gets the same check before you edit it. The tree's copies are the ones that apply; a harness may have loaded another checkout's.
**Rules read.** List the files `plan.md` touches. Read `<tree>/AGENTS.md` and the platform guide the profile's Done section names, then every `<tree>/.claude/rules/*.md` whose `paths:` header matches one of them, and name them on a `Rules read:` line in `plan.md`. A file added later gets the same check before you edit it. The tree's copies are the ones that apply; a harness may have loaded another checkout's.

In Full mode the `critic` lane attacks the plan; fold in what survives an evidence check. Then implement.

Expand Down Expand Up @@ -123,7 +123,7 @@ Fix what is real and inside the scope boundary without asking. A real finding ab

1. **Stage explicit paths**, never `git add -A`, `.` or a directory, and compare `git -C <tree> diff --cached --stat` with what you changed.
2. **Run `scripts/check-banned-words.sh --staged`**, and the same script over the PR body file.
3. **Commit, then push, in separate calls**, after `git -C <tree> branch --show-current` in a call of its own. The PR title becomes the squash commit subject; its format, types and scopes are in the top comment of `.github/pull_request_template.md`. Never override the git identity. If SSH fails: `git -c credential.helper='!gh auth git-credential' push https://github.com/TableProApp/TablePro.git <branch>`.
3. **Commit, then push, in separate calls**, after `git -C <tree> branch --show-current` in a call of its own. The PR title becomes the squash commit subject; its format and types are in the top comment of `.github/pull_request_template.md`. Never override the git identity. If SSH fails: `git -c credential.helper='!gh auth git-credential' push https://github.com/TableProApp/TablePro.git <branch>`.
4. **Open the PR, ready for review**: `gh pr create --repo TableProApp/TablePro --base <base> --head <branch> --title "<subject>" --body-file <file>`, where `<base>` is the profile's pull request base. The body follows `.github/pull_request_template.md` and reads in under a minute. It is not a log: no investigation story, no review history, no list of every test run.
5. **Screenshots**, only when the change is visible: before and after, light and dark, from an isolated build captured the way the profile's Screen section says. Look at each one before using it. Attach with `gh pr create --attach './after.png#After'` and reference it as `![After](./after.png)`.

Expand Down
3 changes: 1 addition & 2 deletions .claude/skills/fix-issue/references/platform-apple.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ The macOS app and the iOS app, with everything they build from. Every profile ha

## Done

- The tree's `apple/AGENTS.md`, the root `AGENTS.md` it points to, and every `.claude/rules/` file the root Area rules table matches to what you edit (`SKILL.md`, Phase 2, Rules read). The per-change checklist is the Every change section of `apple/AGENTS.md`. Under Claude Code, `apple/CLAUDE.md` loads it once a file under `apple/` is read; read it by path anyway in Phase 0.
- The tree's `apple/AGENTS.md`, the root `AGENTS.md` it points to, and every `.claude/rules/` file whose `paths:` header matches what you edit (`SKILL.md`, Phase 2, Rules read). The per-change checklist is the Every change section of `apple/AGENTS.md`. Under Claude Code, `apple/CLAUDE.md` loads it once a file under `apple/` is read; read it by path anyway in Phase 0.
- Before naming a test in `plan.md`, read `.claude/rules/tests.md` (Where a test goes): a path rule loads only once a matching file is open. Add a UI flow only when `.claude/rules/ui-tests.md` (What earns a UI flow) says so.

## Native standard
Expand All @@ -43,7 +43,6 @@ The macOS app and the iOS app, with everything they build from. Every profile ha
| `l10n` | none | strings, or plugin or package messages, changed. Passes only when every plugin and package string is in both the macOS and iOS catalogs, and prints the `--add` command for each target that failed |
| `docs` | `[docs-checkout]`, default `tablepro-docs` beside the main checkout | AGENTS Every change 4 applies, or a menu, shortcut, driver list or docs.tablepro.app link changed |

- `agent-docs` runs on every platform; AGENTS Every change 5 says when.
- Pick tests by the types you changed, not the test files you edited: `verify.sh` finds a type name in every test target of the tree.
- Extra review pass: the ABI pass when PluginKit changed.
- Test names, verdicts, the remedies `verify.sh` does not print, and red CI checks: `references/verification-apple.md`.
Expand Down
4 changes: 2 additions & 2 deletions .claude/skills/fix-issue/references/verification-apple.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Verification on Apple

Read this when a verdict, a test name or a red CI check needs explaining. The commands, the verdict words and the verdict rules are in `apple/AGENTS.md`, Commands; when each step runs is in `references/platform-apple.md`, Verify.
Read this when a verdict, a test name or a red CI check needs explaining. The commands are in `apple/AGENTS.md`, Commands; when each step runs is in `references/platform-apple.md`, Verify.

## Usage

Expand Down Expand Up @@ -89,7 +89,7 @@ Read this when a verdict, a test name or a red CI check needs explaining. The co

## Lint

- `lint` is SwiftLint only. `agent-docs` is its own step, so a stale doc reference never turns a code lint red; `AGENTS.md`, Writing style and docs, says what it checks.
- `lint` is SwiftLint only.
- `apple/.swiftlint.yml` `included:` holds six roots: `TablePro`, `Packages`, `Plugins`, `TableProMobile`, `TableProTests`, `TableProUITests`.
- Some folders lint with fewer rules through a nested `only_rules` config: `.claude/rules/ci.md`, Writing workflow and lint code.
- A directory outside `included:` lints nothing and reports 0 violations; the step names it under "NOT LINTED". Pass files.
Expand Down
16 changes: 0 additions & 16 deletions .claude/skills/fix-issue/scripts/verify.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
#
# Usage:
# verify.sh [options] <step> [args] # a step of the platform, listed below
# verify.sh [options] agent-docs # the agent docs (check-doc-symbols.sh lists them) against the tree
# verify.sh tail <log> [lines] # re-read a stored log without rerunning
# verify.sh parse <log> # re-read the verdict for a stored log
#
Expand Down Expand Up @@ -216,21 +215,6 @@ case "$STEP" in
emit "$1" "-"
;;

agent-docs)
# Kept out of `lint`, so one stale reference on main never turns a code lint red.
log="$(new_log agent-docs)"
run_logged "$log" "$REPO_ROOT/scripts/check-doc-symbols.sh"
code=$?
if [ $code -eq 0 ]; then
STATUS=PASS
note "$(tail -1 "$log")"
else
STATUS=FAIL
note "$(grep -E '^((apple|linux)/)?(CLAUDE|AGENTS|CONTRIBUTING|RELEASING)|^\.claude|^\.github' "$log" | sed 's/^/ /' | head -10)"
fi
emit "$log" $code
;;

*)
load_platform
platform_step "$@"
Expand Down
31 changes: 5 additions & 26 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,11 @@
<!--
Title: <type>(<scope>): <description>, with ! before the colon for a breaking change. It becomes the squash commit subject.
Types: feat, fix, refactor, perf, test, docs, build, ci, chore, style, revert.
Scopes, when one fits: ai-chat, ai-providers, mcp, copilot, inline-suggest, editor, datagrid, tabs, coordinator, sidebar, connections, connection-form, welcome, settings, toolbar, hig, ssh, ios, windowing, perf, launch, plugins, plugin-<name>, changelog, claude-md, docs, ci, release.
Platform scopes: ios for the iOS app, linux or linux-<area> for the Linux app. windows is kept for a Windows app, so window management is windowing.
Body: 80 to 150 words, 250 at most, screenshots aside. Delete these comments and any optional heading you do not use.
Leave out review history, test lists and counts, the investigation story and file-by-file change logs.
Use none of the terms in scripts/banned-words.txt.
-->
<!-- Title: type(scope): description. Types: feat, fix, refactor, perf, test, docs, build, ci, chore, style, revert. -->

## Why
## Summary

<!-- Bug: what the user saw, then the cause in one or two sentences. Feature: what the user could not do before. -->
<!-- What changed, as bullets. -->

## Change
## Test plan

<!-- One to four bullets, in the user's terms first. One bullet per fix when the PR carries several. -->

## Verified

<!-- One or two lines: the test that fails on main and passes here, and any check on a real build. Name each existing test this PR changed because it pinned behavior the PR changes on purpose. A new end-to-end flow without a UI test says why. -->

## Screenshots

<!-- Optional. Only when the UI changes: before and after, light and dark when color is involved. -->

## Not in this PR

<!-- Optional. A known gap, a follow-up, or a risk the reviewer should weigh. One line each. -->
<!-- The test that fails on main and passes here, and any check on a real build. -->

Fixes #
<!-- One keyword per issue ("Fixes #1, fixes #2"), "Refs #N" for one this does not close. Delete the line when there is no issue. -->
76 changes: 16 additions & 60 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,77 +1,33 @@
# TablePro

Native database clients, one per platform, sharing no code: `apple/` holds the macOS and iOS apps (Swift, AppKit and SwiftUI), `linux/` the Linux app (Rust, GTK 4). This guide holds the rules both follow. Claude Code loads it through `CLAUDE.md`, Codex directly.

Each app has its own guide beside its code: `apple/AGENTS.md` and `linux/AGENTS.md`. Claude Code loads one through its `CLAUDE.md` once it reads a file in that folder; Codex reads one when started there, so otherwise read the guide before working in its folder.

## Principles

1. **Security first.** Validate at system boundaries; never introduce injection, credential exposure or a widened permission by accident.
2. **Fix the cause, not the symptom.** Diagnose (add logging if needed), then fix the cause. No workaround left behind.
3. **Tests define behavior.** Every testable change has a test. When a test fails, fix the code, never the test. A test that pins behavior the PR changes on purpose is updated in the same PR and named in its description.
Native database clients that share no code: `apple/` holds the macOS and iOS apps (Swift), `linux/` the Linux app (Rust, GTK 4). Read `apple/AGENTS.md` or `linux/AGENTS.md` before working in that folder. Claude Code loads it through the folder's `CLAUDE.md`, Codex only when started there.

## Repository map

- `apple/`: the macOS and iOS apps, their plugins, packages, native bridges, scripts and changelog.
- `linux/`: the GTK 4 Linux app, built with Meson and Cargo, with its own changelog.
- `.github/`: workflows, actions, the PR template, `plugin-registry.json` and the CI baselines.
- `.claude/`: the path-scoped rules (Area rules below) and the `fix-issue` and `release` skills.
- `scripts/`: what both apps share: `banned-words.txt` with `check-banned-words.sh`, `check-doc-symbols.sh`, the PR title, changelog and changed-path checks in `scripts/ci`, and the towncrier pin in `scripts/release`.
- `appcast.xml`: the legacy feed apps up to 0.81 read from `main` (`apple/RELEASING.md`, Channels). It stays at the root.
- Docs site: TableProApp/docs, cloned beside this repo as `../tablepro-docs`, under its own `AGENTS.md` and `STYLE.md`.

## Verification
- `apple/`, `linux/`: each app with its scripts and changelog.
- `.github/`: workflows, actions, the PR template and `plugin-registry.json`.
- `.claude/`: the path-scoped rules and the `fix-issue` and `release` skills, which Codex sees through `.agents/skills/`.
- `scripts/`: `banned-words.txt` with `check-banned-words.sh`, the PR title and changed-path checks in `scripts/ci`, and the towncrier pin in `scripts/release`.
- `appcast.xml`: the legacy feed apps up to 0.81 read from `main` (`apple/RELEASING.md`, Channels).
- Docs site: TableProApp/docs, cloned beside this repo as `../tablepro-docs`, under its own `AGENTS.md`.

`.claude/skills/fix-issue/scripts/verify.sh` runs every step from the repository root, keeps the full log and prints `PASS`, `FAIL` or `INCONCLUSIVE`. It picks the platform from the machine; `--platform linux` names one. `INCONCLUSIVE` is never a pass. Steps per platform: the `fix-issue` references, `platform-apple.md` and `platform-linux.md`.

## Writing style and docs
## Principles

- All writing: short sentences, plain words, specific numbers and names, no em dash, no filler.
- `scripts/banned-words.txt` is the list; never copy its terms. `scripts/check-banned-words.sh --staged` checks a staged change.
- One home per fact; others point to it by repo path and section. No drifting counts or timings; a plan is not a fact.
- Code comments say why, never what. Delete what-comments in code you touch.
- A path in a platform's docs is relative to its folder; a root doc writes it from the repository root.
- Budgets: a platform guide 16 KiB, a rule 200 lines, a `SKILL.md` 500, a skill description 1,536 characters.
- `verify.sh agent-docs` checks backticked names in the guides, `CONTRIBUTING.md`, `RELEASING.md`, `.github/pull_request_template.md` and `.claude/`. Run it when one changes. Never state a plugin count in prose.
- Tests define behavior. When a test fails, fix the code, never the test. A test that pins behavior the PR changes on purpose is updated in the same PR and named in its description.
- Verify with `.claude/skills/fix-issue/scripts/verify.sh` from the repository root. It prints `PASS`, `FAIL` or `INCONCLUSIVE`; `INCONCLUSIVE` is never a pass.
- Writing: short sentences, plain words, no em dash, no term from `scripts/banned-words.txt`. Code comments say why, never what.
- One home per fact; other docs point to it by path and section.

## Commits and PRs

- The PR title is the squash commit subject; branch commits use the same format. The body follows `.github/pull_request_template.md`, whose top comment holds the format, types and scopes. The `PR title` check (`scripts/ci/check-pr-title.py`) enforces the format, not scopes.
- A user-visible change adds a fragment to its app's `changelog.d/`; only a release PR edits a `CHANGELOG.md`. Format: `.claude/rules/changelog.md`.
- The PR title is the squash commit subject, `type(scope): description`. The body follows `.github/pull_request_template.md`.
- A rename or signature change updates every caller and test in the same commit.
- Agents merge on green with `gh pr merge <N> --auto --squash`. They create a `release/*` branch or a tag only when the maintainer says to release, and use `--admin` only on the maintainer's word.

## CI

- A PR into `main` or `release/*` merges on green macOS Tests, iOS and Package Tests, SwiftLint, Repo Hygiene, PR title and Linux. Nothing bypasses them.
- Read why a CI check failed before any re-run.
- Workflows: `.claude/rules/ci.md`. Red checks: `.claude/skills/fix-issue/references/verification-apple.md` and `verification-linux.md`, Reading CI.
A PR merges once its required checks pass: `.claude/rules/ci.md`, or `gh api repos/TableProApp/TablePro/rules/branches/main` for the live list. Read why a check failed before any re-run.

## Area rules

Claude Code loads a rule when it reads or edits a file the rule covers. Under Codex, before editing a file, read every rule whose row matches it. Each row is the rule's `paths:` with a trailing `/**/*` dropped; `verify.sh agent-docs` keeps them equal.

| Rule | Read before editing |
| --- | --- |
| `ai-mcp-security.md` | `apple/TablePro/Core/AI`, `apple/TablePro/Core/MCP`, `apple/Packages/TableProMacCore/Sources/TableProMCP` |
| `changelog.md` | `**/CHANGELOG.md`, `**/changelog.d`, `**/towncrier.toml` |
| `ci.md` | `.github/workflows`, `.github/actions`, `.github/actionlint.yaml`, `scripts/ci`, `apple/scripts/ci`, `scripts/release`, `apple/scripts/release`, `apple/.swiftlint.yml`, `**/.swiftlint.yml` |
| `connection-window.md` | `apple/TablePro/Core/Services/Infrastructure`, `apple/TablePro/Models/Connection`, `apple/TablePro/Core/Database/DatabaseManager*.swift`, `apple/Packages/TableProCore/Sources/TableProDatabase`, `apple/TablePro/Views/Main` |
| `data-grid.md` | `apple/TablePro/Views/Results`, `apple/TablePro/Core/DataGrid`, `apple/TableProTests/Views/Results` |
| `data-sync-storage.md` | `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` |
| `editor.md` | `apple/Packages/TableProEditor`, `apple/TablePro/Theme`, `apple/TablePro/Views/Editor`, `apple/TablePro/Views/RowInspector` |
| `libs.md` | `apple/Libs`, `apple/scripts/download-libs.sh`, `apple/scripts/publish-libs.sh` |
| `mongodb-driver.md` | `apple/Plugins/MongoDBDriverPlugin`, `apple/Plugins/MQLExportPlugin` |
| `mysql-driver.md` | `apple/Plugins/MySQLDriverPlugin`, `apple/Packages/TableProCore/Sources/TableProMySQLCore`, `apple/TableProMobile/**/*MySQL*`, `apple/TableProMobile/**/*MariaDB*` |
| `native-bridges.md` | `apple/Native`, `apple/Plugins/DamengDriverPlugin`, `apple/Plugins/HanaDriverPlugin`, `apple/scripts/build-dameng.sh`, `apple/scripts/build-hana.sh` |
| `plugin-system.md` | `apple/Plugins`, `apple/Packages/TableProCore/Sources/TableProPluginKit`, `apple/Packages/TableProCore/Sources/TableProMySQLCore`, `apple/Packages/TableProCore/Sources/TableProPostgreSQLCore`, `apple/Packages/TableProCore/Sources/TableProRedisCore`, `apple/Packages/*/Package.swift`, `apple/project.yml`, `apple/TableProMobile/project.yml`, `apple/Configs/PluginKit.xcconfig`, `.github/plugin-registry.json`, `apple/scripts/*plugin*` |
| `redis-driver.md` | `apple/Plugins/RedisDriverPlugin`, `apple/Packages/TableProCore/Sources/TableProRedisCore` |
| `split-views.md` | `apple/TablePro/**/*Split*.swift`, `apple/TablePro/Core/Services/Infrastructure/WorkspacePane*.swift` |
| `tests.md` | `apple/TableProTests`, `apple/TableProUITests`, `apple/Plugins/*Tests`, `apple/Packages/*/Tests`, `apple/TableProMobile/TableProMobileTests`, `apple/TestPlans`, `apple/scripts/ci/check-test-plans.py`, `apple/scripts/clean-test-residue.sh` |
| `theme.md` | `apple/TablePro/Theme`, `apple/TablePro/Views`, `apple/TablePro/Core/Services/Infrastructure/*Window*`, `apple/Packages/TableProCore/Sources/TableProTheme` |
| `ui-lifecycle.md` | `apple/TablePro/Views`, `apple/TablePro/ViewModels`, `apple/TablePro/Core/Services/Infrastructure`, `apple/Packages/TableProEditor` |
| `ui-tests.md` | `apple/TableProUITests`, `apple/TestPlans/UI.xctestplan` |
| `welcome-library.md` | `apple/TablePro/Views/Welcome`, `apple/TablePro/ViewModels/WelcomeViewModel*.swift`, `apple/Packages/TableProCore/Sources/TableProConnectionLibrary` |

## Skills

`fix-issue` takes a problem to one green PR and holds `verify.sh` and its references; `release` ships a macOS version (the Linux runbook is `linux/docs/releasing.md`). Both live in `.claude/skills/`; Codex sees them through `.agents/skills/`.
Before editing a file, read each `.claude/rules/*.md` whose `paths:` header matches it. Claude Code loads them itself.
Loading
Loading