From bbdda79ef9d6c2fa22039a75b5fed5e1ee46e0ca Mon Sep 17 00:00:00 2001 From: Aaron Scott Date: Mon, 7 Sep 2026 08:11:21 -0400 Subject: [PATCH 1/3] docs(fork): start the fork log MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Upstream moved 254 commits in the nine days since the merge base (`f1198ffa`, 2026-08-29) while this fork moved 47, and none of the 47 have been contributed back. Without a record, an upstream fix gets re-derived here and a deliberate deviation gets "corrected" back by someone who read it as drift. Triage is by scope rather than by commit — 254 individual decisions is not a thing anyone finishes. The decisions themselves are left open; what this commit adds is the shape, the snapshot, and the two findings worth having before the next merge: `statutory` is 74 commits of a subsystem this fork has no requirement for, and `app/components/editor` is the collision zone, where the fork's 20 phone-capture commits meet upstream's 14 statutory-driven ones. Linked from CLAUDE.md rather than docs/README.md: that map is upstream's file, and a fork-only row in it would conflict on every merge. Co-Authored-By: Claude Opus 5 --- CLAUDE.md | 2 + docs/develop/fork-log.md | 97 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 docs/develop/fork-log.md diff --git a/CLAUDE.md b/CLAUDE.md index 55f926b9..bc00a779 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,6 +6,8 @@ API in-process and delegates page routes to React Router v8 SSR. **Docs**: `docs/README.md` is the map — `docs/operate/` (deploy, upgrade, configure) · `docs/develop/` (architecture, testing, design system) · `docs/reference/` (API, database, roles, deployment modes) · `docs/concepts/` (how the engine works) · `docs/integrations/` (external services) · `docs/compliance/` (data handling). Docs here cover the **engine**: deploying it, operating it, changing it, integrating it. Using the product day to day is documented at , which serves self-hosted and hosted deployments alike. +**This checkout is a fork.** `origin` is `NCHILLC/OpenInspection` (private), `upstream` is `InspectorHub/OpenInspection`. What has been taken from upstream, skipped, or deliberately diverged on is recorded in [`docs/develop/fork-log.md`](docs/develop/fork-log.md) — read it before merging upstream or before "fixing" behaviour that looks like drift. It is linked from here rather than from `docs/README.md` on purpose: that map is upstream's, and a fork-only row in it would conflict on every merge. + ## Commands ```bash diff --git a/docs/develop/fork-log.md b/docs/develop/fork-log.md new file mode 100644 index 00000000..c5008d77 --- /dev/null +++ b/docs/develop/fork-log.md @@ -0,0 +1,97 @@ +# Fork log + +`NCHILLC/OpenInspection` (`origin`) is a private fork of +`InspectorHub/OpenInspection` (`upstream`). This file records what has been +taken from upstream, what has been deliberately skipped, and where the two have +diverged on purpose. + +It exists because the alternative is re-deriving those answers from a diff every +time upstream moves. Without it, a fix that upstream already made gets +rewritten here, and a deviation this fork chose gets "fixed" back to upstream's +behaviour by someone who assumed it was drift. + +**This is a decision log, not a changelog.** Only entries where a judgement was +made belong here. A commit range taken wholesale with nothing to say about it +does not need a line. + +## Refreshing the numbers + +```bash +git fetch upstream +git rev-list --left-right --count upstream/main...main # upstream-only, fork-only +git log -1 --format='%h %ad %s' --date=short $(git merge-base upstream/main main) +git cherry upstream/main main # '-' marks fork commits upstream already has +``` + +`git cherry` is the reason the PR template forbids squashing: a squash rewrites +the branch's commits, and `git cherry` then reports landed work as unmerged. + +## Snapshot — 2026-09-07 + +| | | +|---|---| +| Merge base | `f1198ffa`, 2026-08-29 (upstream PR #324) | +| Upstream-only commits | 254 | +| Fork-only commits | 47 | +| Fork commits upstream already has | 0 — nothing has been contributed back | + +Divergence is nine days old and upstream is moving fast: 254 commits in that +window. The triage below is by **scope**, not by commit, because 254 individual +decisions is not a thing anyone will finish. + +## Upstream work, by scope + +| Scope | Commits | Decision | +|---|---|---| +| `statutory` | 74 | **undecided — the big one.** A whole subsystem: statutory form definitions, readiness checks, publishing, an editor surface and the first statutory E2E. Nothing in the fork depends on it. Taking it means carrying a subsystem the fork has no requirement for; skipping it means every future upstream merge conflicts against a version of the editor that assumes it exists. | +| `editor` | 14 | **undecided — see collision zone below.** | +| `gates` | 13 | recommend taking. Gate and lint work is exactly what the fork wants more of, and it rarely conflicts. | +| `marketplace` | 9 | undecided. Likely on the removal list. | +| `perf` | 8 | recommend taking. | +| `mcp` | 6 | undecided. Named on the eval's removal list. | +| `auth` | 6 | recommend taking — security-path changes are the worst class to re-derive. | +| `templates` | 5 | undecided; overlaps fork template work. | +| everything else | ~40 across `ui`, `tenancy`, `settings`, `routing`, `deps`, `ci`, `cron`, … | case by case | + +Counts are `--no-merges` and exclude 22 merge commits. + +## Collision zone: `app/components/editor` + +The one area both sides are actively changing, and the reason a blind merge will +hurt. + +- **Fork**: 20 of its 47 commits are scoped `editor`, touching 60 files under + `app/components/editor`. The subject is *field capture on a phone* — camera, + offline photo queueing, shutter gestures, mobile layout, a way out of the + unsaved-changes blocker. +- **Upstream**: 14 `editor` commits, nearly all of them *statutory-driven* — + statutory groups as slots, item nesting, sub-item CRUD, revision display. + +Same directory, different concerns, so most conflicts will be textual rather +than semantic. Two exceptions worth checking before assuming that: + +- `fix(editor): the Inspection Details overview rendered nothing on a phone` — + upstream fixing a mobile bug this fork may have already solved differently. +- `refactor(editor): template item CRUD delegates to the shared tree ops` — a + structural refactor under files the fork has rewritten. + +## Fork deviations + +What this fork changed and intends to keep. Add a line when a change is a +deliberate departure rather than work upstream simply has not done yet. + +| Area | What | Why it diverges | +|---|---|---| +| `editor` (20 commits) | Field capture on a phone: camera, offline defect photos, shutter gesture handling, mobile layouts | Upstream's field surface is responsive web; this fork treats crawlspace capture as a core requirement — see the capture-first decision in `architecture.md` | +| `ratings` (4) | "Not inspected" reasons, Safety-Major level | — | +| `intake` (3) | Graded defects filed by position, severity preserved on import | — | +| CI | `verify` also runs on pushes to `main` | Fork commits directly to `main`; upstream works through PRs | + +## Rules + +- One line per decision, citing a commit or range (`git log a..b`), never a + migration number or a PR number from the other repository without its owner + (`InspectorHub/OpenInspection#324`). +- Record skips as explicitly as takes. "We looked and said no" and "we never + looked" are the same silence otherwise. +- Update the snapshot when you fetch, not when you remember. From d39ea9b3701ce3910298f538cc590c536c40d44c Mon Sep 17 00:00:00 2001 From: Aaron Scott Date: Mon, 7 Sep 2026 08:22:11 -0400 Subject: [PATCH 2/3] docs(fork): document the upstream mirror branch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `upstream-track` on origin holds exactly `upstream/main` — all 254 of upstream's commits, none of this fork's — so upstream can be run, deployed and diffed without touching the working line. Never commit to it; fast-forward only. It tracks origin rather than upstream on purpose. Tracking upstream would make `git pull` a convenient refresh and `git push` an attempt to write to somebody else's repository, and the second one is not worth the first. Co-Authored-By: Claude Opus 5 --- docs/develop/fork-log.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/docs/develop/fork-log.md b/docs/develop/fork-log.md index c5008d77..cf48681e 100644 --- a/docs/develop/fork-log.md +++ b/docs/develop/fork-log.md @@ -26,6 +26,37 @@ git cherry upstream/main main # '-' marks fork commit `git cherry` is the reason the PR template forbids squashing: a squash rewrites the branch's commits, and `git cherry` then reports landed work as unmerged. +## The upstream mirror + +`upstream-track` is a branch on `origin` holding **exactly** `upstream/main` — +all of upstream's commits, none of this fork's. It exists so upstream can be +run, deployed and diffed without touching the working line. + +Two rules, and they are the whole contract: + +- **Never commit to it.** A commit here turns the mirror into a third divergent + line, which is the one thing it exists to prevent. +- **Fast-forward only.** If a refresh ever refuses to fast-forward, something + has been committed to it — fix that rather than forcing the update. + +```bash +git fetch upstream +git push origin upstream/main:refs/heads/upstream-track # refresh the mirror +git switch upstream-track && git merge --ff-only upstream/main # or locally +``` + +It tracks `origin/upstream-track`, **not** `upstream/main`, and that is not an +oversight to correct: tracking upstream would make a stray `git push` on this +branch aim at somebody else's repository. Refresh with the explicit commands +above. + +CI does not run on it: the `push` trigger is scoped to `main`, deliberately. +Upstream tests its own commits, and a mirror burning runner minutes to confirm +that is waste. + +When an upstream scope in the table below is decided as **take**, this branch is +what you merge from. + ## Snapshot — 2026-09-07 | | | From 96497f88105d04c9ac70e473d9ea5892a7401ee7 Mon Sep 17 00:00:00 2001 From: Aaron Scott Date: Mon, 7 Sep 2026 09:38:41 -0400 Subject: [PATCH 3/3] docs(fork): check upstream before debugging, and check gh before claiming CI is unreadable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two rules, both earned the same day. Upstream is 250+ commits ahead and moving fast, so a failure here has often already been diagnosed and fixed there. Re-deriving costs more than the three-command lookup. Today's eslint timeout was investigated locally before anyone asked whether upstream had already hit it — it had not, but that was luck, not method. The second rule is narrower: the connector's Checks 403 is real, but it was asserted from a note rather than tested, and repeated several times as though verified. `gh` is installed and authenticated and reads CI fine. Check the tool before reporting the limitation. Co-Authored-By: Claude Opus 5 --- CLAUDE.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/CLAUDE.md b/CLAUDE.md index bc00a779..c5976c9d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -8,6 +8,45 @@ API in-process and delegates page routes to React Router v8 SSR. **This checkout is a fork.** `origin` is `NCHILLC/OpenInspection` (private), `upstream` is `InspectorHub/OpenInspection`. What has been taken from upstream, skipped, or deliberately diverged on is recorded in [`docs/develop/fork-log.md`](docs/develop/fork-log.md) — read it before merging upstream or before "fixing" behaviour that looks like drift. It is linked from here rather than from `docs/README.md` on purpose: that map is upstream's, and a fork-only row in it would conflict on every merge. +## Check upstream BEFORE debugging anything + +**Before investigating any error, bug, failing test or red gate: look for the +fix upstream first.** This fork sits 250+ commits behind a fast-moving upstream, +so the odds that a failure has already been diagnosed and fixed there are high, +and re-deriving a fix costs far more than the lookup does. Not optional, and not +a judgement call about how obvious the symptom looks. + +```bash +git fetch upstream +git log main..upstream/main --oneline --no-merges -i --grep='' +git log main..upstream/main --oneline --no-merges -- +``` + +A hit: cherry-pick or port it, and record the decision in +[`docs/develop/fork-log.md`](docs/develop/fork-log.md). A miss is worth knowing +too — it means the bug is this fork's own, and once fixed it belongs in the fork +log as a deviation. Either way the lookup takes seconds and its answer changes +what you do next. + +**Reading CI requires the `gh` CLI, not the GitHub MCP connector.** The +connector's token has no Checks permission: `pull_request_read` does expose a +`get_check_runs` method, but it and `get_status` both return +`403 Resource not accessible by integration` (verified 2026-09-07). Confirm `gh` +before reporting that CI results are unavailable — do not repeat the limitation +from memory without checking: + +```bash +gh auth status # expect: Logged in to github.com account NCHILLC +gh pr checks --repo NCHILLC/OpenInspection +gh run view --job --log-failed +``` + +Installed via `winget install --id GitHub.cli`. It may be missing from an +existing shell's PATH if that shell started before the install — call it as +`"/c/Program Files/GitHub CLI/gh.exe"` rather than concluding it is absent. A +timed-out job archives no log, so `--log-failed` returns EMPTY for one; use +`gh run view --job ` and read the annotation instead. + ## Commands ```bash