Add CI, Renovate config, changelog, and lockfiles; refresh docs #20

Merged
claude-bot merged 5 commits from chore/project-hygiene into main 2026-07-17 01:50:25 +00:00
Contributor

Addresses #3, #4, #5, #6, and #19.

Two findings reshaped this work: the roadmap had zero unchecked items, so remaining work was pulled from the audit docs instead; and Renovate was already running (onboarding PR #2, opened 2026-06-23), so this tunes it rather than standing it up.

Reproducible builds (#19)

The repo had no lockfiles and no .gitignore. Every dependency uses a caret range, so npm install resolved a fresh tree each run - CI, local dev, and the Docker image could build different dependency trees from identical source. This also made Renovate mostly ineffective: in-range minor/patch PRs changed nothing real, and lockFileMaintenance was a no-op.

Both package-lock.json files were generated with npm install --package-lock-only in node:20-alpine, matching the version both Dockerfiles pin. Both are lockfileVersion 3 (224 and 91 packages) and record all platform variants of @rollup/rollup-* (musl, gnu, win32, darwin), so npm ci resolves correctly regardless of host platform.

CI (#3)

.forgejo/workflows/ci.yml runs frontend tests, backend tests, and the production build on PRs to main and pushes to main, with concurrency cancellation for superseded runs.

  • node:20-alpine, matching both Dockerfiles - not a newer version.
  • No Postgres service. All three backend test files import createMemoryRepository from src/repository.memory.js; none reference repository.pg.js or DATABASE_URL. The suite never touches a live database.

Verified by running the exact pipeline in node:20-alpine: npm ci succeeded for both packages, 46 frontend tests passed, 22 backend tests passed, production build succeeded.

Renovate (#4)

renovate.json gates all majors behind dependency-dashboard approval, which is what prevents the 13 queued major PRs (React 19, Vite 8, Tailwind 4, Express 5, node 26, postgres 18) from landing at once. Also: weekly off-hours schedule, grouped React/Vite/CSS/Docker updates, concurrency limits, auto-merge for devDependency patch+minor and production patch.

Note: merging this marks the repo onboarded, so Renovate should close PR #2 automatically.

Changelog (#5)

CHANGELOG.md reconstructs 0.1.0 -> 1.0.0 from the 38 commits (2026-05-08 to 2026-06-03) in Keep a Changelog format. It states plainly that pre-1.0.0 versions are a retroactive reading of the commit log and were never tagged - they are not checkout-able. No retroactive tags applied.

Docs (#6)

  • roadmap.md - reframed as historical. Notes that a checked box means scope delivered, not capability live: Milestones 7 and 8 shipped an adapter framework and a manual/CSV path, not live integrations.
  • implementation-audit.md - re-dated from 2026-05-13, which predated the server-side calculation work it described. Inverter Modeling moved out of Missing, where it listed 11 implemented features under a heading saying its gaps were None. Fixed a stale caveat claiming Emporia data is dropped on reload (true only unauthenticated). Tab list said 8; App.jsx:47 has 11.
  • calculation-logic-audit.md - formulas and every rate constant verified accurate and left unchanged. Only the structure was wrong: it described src/App.jsx as the calculation coordinator, which stopped being true when calculation moved to the shared runtime. Added Where Calculations Run; documented per-circuit whole-home exclusion under outage, explicitly noting it does not affect bill savings.
  • README.md - migration table listed 3 of 7 migrations and attributed calculation results to 001 rather than 004. Rebuilt from actual DDL. Added Contributing section and the missing Reports tab.

Also verified, and not a bug: two migrations share the 003_ prefix. migrate.js keys each by full filename and sorts lexicographically, so ordering is deterministic. Documented as a naming smell.

Review notes

  • CI cannot actually run until a Forgejo Actions runner picks up this repo. Worth confirming one is available.
  • Auto-merge is configured but only meaningful once CI is green - reasonable to merge this, watch one CI run, then rely on it.

🤖 Generated with Claude Code

Addresses #3, #4, #5, #6, and #19. Two findings reshaped this work: the roadmap had **zero unchecked items**, so remaining work was pulled from the audit docs instead; and **Renovate was already running** (onboarding PR #2, opened 2026-06-23), so this tunes it rather than standing it up. ## Reproducible builds (#19) The repo had no lockfiles and no `.gitignore`. Every dependency uses a caret range, so `npm install` resolved a fresh tree each run - CI, local dev, and the Docker image could build different dependency trees from identical source. This also made Renovate mostly ineffective: in-range minor/patch PRs changed nothing real, and `lockFileMaintenance` was a no-op. Both `package-lock.json` files were generated with `npm install --package-lock-only` in `node:20-alpine`, matching the version both Dockerfiles pin. Both are lockfileVersion 3 (224 and 91 packages) and record all platform variants of `@rollup/rollup-*` (musl, gnu, win32, darwin), so `npm ci` resolves correctly regardless of host platform. ## CI (#3) `.forgejo/workflows/ci.yml` runs frontend tests, backend tests, and the production build on PRs to `main` and pushes to `main`, with concurrency cancellation for superseded runs. - **node:20-alpine**, matching both Dockerfiles - not a newer version. - **No Postgres service.** All three backend test files import `createMemoryRepository` from `src/repository.memory.js`; none reference `repository.pg.js` or `DATABASE_URL`. The suite never touches a live database. **Verified by running the exact pipeline in `node:20-alpine`:** `npm ci` succeeded for both packages, 46 frontend tests passed, 22 backend tests passed, production build succeeded. ## Renovate (#4) `renovate.json` gates **all majors behind dependency-dashboard approval**, which is what prevents the 13 queued major PRs (React 19, Vite 8, Tailwind 4, Express 5, node 26, postgres 18) from landing at once. Also: weekly off-hours schedule, grouped React/Vite/CSS/Docker updates, concurrency limits, auto-merge for devDependency patch+minor and production patch. > **Note:** merging this marks the repo onboarded, so Renovate should close PR #2 automatically. ## Changelog (#5) `CHANGELOG.md` reconstructs 0.1.0 -> 1.0.0 from the 38 commits (2026-05-08 to 2026-06-03) in Keep a Changelog format. It states plainly that pre-1.0.0 versions are a retroactive reading of the commit log and were never tagged - they are not checkout-able. No retroactive tags applied. ## Docs (#6) - **roadmap.md** - reframed as historical. Notes that a checked box means scope delivered, not capability live: Milestones 7 and 8 shipped an adapter framework and a manual/CSV path, not live integrations. - **implementation-audit.md** - re-dated from 2026-05-13, which predated the server-side calculation work it described. `Inverter Modeling` moved out of `Missing`, where it listed 11 implemented features under a heading saying its gaps were `None`. Fixed a stale caveat claiming Emporia data is dropped on reload (true only unauthenticated). Tab list said 8; `App.jsx:47` has 11. - **calculation-logic-audit.md** - formulas and every rate constant verified accurate and left unchanged. Only the structure was wrong: it described `src/App.jsx` as the calculation coordinator, which stopped being true when calculation moved to the shared runtime. Added `Where Calculations Run`; documented per-circuit whole-home exclusion under outage, explicitly noting it does **not** affect bill savings. - **README.md** - migration table listed 3 of 7 migrations and attributed calculation results to `001` rather than `004`. Rebuilt from actual DDL. Added Contributing section and the missing Reports tab. Also verified, and **not** a bug: two migrations share the `003_` prefix. `migrate.js` keys each by full filename and sorts lexicographically, so ordering is deterministic. Documented as a naming smell. ## Review notes - CI cannot actually run until a Forgejo Actions runner picks up this repo. Worth confirming one is available. - Auto-merge is configured but only meaningful once CI is green - reasonable to merge this, watch one CI run, then rely on it. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
The repo had no lockfiles and no gitignore. Every dependency uses a caret
range, so npm install resolved a fresh tree on each run and CI, local dev,
and the Docker image could each build against different dependency versions
from identical source.

Generated both package-lock.json files with npm install --package-lock-only
in node:20-alpine, matching the version both Dockerfiles pin. Verified npm ci,
both test suites, and the production build all pass against them.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CI runs the frontend suite, backend suite, and production build on pull
requests to main and pushes to main, using npm ci against the new lockfiles.
Pinned to node:20-alpine to match the deployed runtime. No Postgres service
is needed - the backend suite runs against the in-memory repository.

Renovate has been running against this repo since June but was never
configured, and with default settings wanted to open 13 PRs at once, nearly
all majors. This config requires dashboard approval for every major update,
schedules PRs weekly off-hours, groups related dependencies, and limits
concurrency. Committing renovate.json to main marks the repo onboarded, which
should close the pending onboarding PR automatically.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
No git tags existed and both package.json files read 1.0.0 regardless of what
shipped, so there was no record of what changed between versions.

Reconstructs 0.1.0 through 1.0.0 from the 38 commits spanning 2026-05-08 to
2026-06-03, in Keep a Changelog format. Pre-1.0.0 entries are marked plainly
as a retroactive reading of the commit log rather than releases that were
tagged at the time. No retroactive tags applied.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Refresh docs and move work tracking to Forgejo issues
All checks were successful
CI / test (pull_request) Successful in 1m1s
206114af25
The roadmap had every one of its checkboxes marked complete but was still
presented as live planning, while the actual remaining work sat in the audit
docs. Remaining work now lives in Forgejo issues and milestones.

roadmap.md: reframed as a historical record. Notes that a checked box means
scope delivered, not capability live - Milestones 7 and 8 shipped an adapter
framework and a manual/CSV path, not live integrations. Open Questions link
to their issues.

implementation-audit.md: re-dated from 2026-05-13, which predated the
server-side calculation work it described. Moved the Inverter Modeling
section out of Missing, where it listed eleven implemented features under a
heading stating its remaining gaps were None. Corrected a stale caveat
claiming Emporia data is dropped on reload, which is true only for
unauthenticated local use. Tab list said eight tabs; App.jsx has eleven.

calculation-logic-audit.md: formulas and rate constants verified accurate
against the code and left unchanged. Corrected the structural claims - it
described src/App.jsx as the calculation coordinator, which stopped being
true when calculation moved to the shared runtime. Added a section on where
calculations run, and documented per-circuit whole-home exclusion under
outage, noting it does not affect bill savings.

README.md: migration table listed three of seven migrations and attributed
calculation results to 001 rather than 004. Rebuilt from the actual DDL.
Added a Contributing section and the missing Reports tab.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Match house CI conventions: ubuntu-latest and qualified action URLs
All checks were successful
CI / Frontend tests, backend tests, and build (pull_request) Successful in 1m4s
2804be56f9
Checked the runner labels actually in use across the other repos on this
Forgejo rather than assuming. Three corrections:

runs-on: docker -> ubuntu-latest. Thirteen of fifteen repos use
ubuntu-latest; only TeaLeaves and iac-repo use the docker label, and both
pair it with an explicit container image.

actions/checkout@v4 -> https://data.forgejo.org/actions/checkout@v4. The
unqualified form relies on the instance default action URL; every other repo
here fully qualifies it.

Dropped the node:20-alpine container in favour of setup-node on the runner
image. Alpine is musl, and act_runner injects a glibc node to execute JS
actions inside the job container, so checkout could have failed at runtime.
TeaLeaves uses bookworm rather than alpine for the same reason. setup-node
also brings npm caching, keyed on both lockfiles.

Node 20 still matches what both Dockerfiles pin.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Author
Contributor

CI conventions corrected (2804be5)

Checked the runner labels actually in use across this Forgejo rather than assuming. The original workflow used runs-on: docker, which is the minority convention here — 13 of 15 repos use ubuntu-latest; only TeaLeaves and iac-repo's renovate job use docker, and both pair it with an explicit container: image.

Checking that surfaced two further problems that would have bitten at runtime:

1. Unqualified action reference. I had uses: actions/checkout@v4. Every other repo here fully qualifies it as https://data.forgejo.org/actions/checkout@v4. The bare form depends on the instance's default action URL resolving as expected.

2. Alpine container vs JS actions. I had container: node:20-alpine. act_runner injects a glibc-built node into the job container to execute JS actions, and Alpine is musl — so checkout could have failed at runtime. Notably TeaLeaves uses node:24-bookworm, not Alpine, for its containerised job. Dropped the container entirely in favour of setup-node on the runner image, which matches the dominant pattern and adds npm caching keyed on both lockfiles.

Node 20 still matches what both Dockerfiles pin.

Also adopted the house ci- prefix on the concurrency group and the workflow_dispatch trigger.

The VSCode Actions extension flags root.concurrency as invalid. It's a false positive — verified the YAML parses correctly with PyYAML, and Quest-Board uses the identical unquoted form in production on this instance.

Caveat on verification: the earlier container run proved npm ci, both suites, and the build pass against the lockfiles. It could not exercise runs-on selection, action resolution, or the npm cache — those only prove out on a real runner. Worth watching the first run land.

## CI conventions corrected (2804be5) Checked the runner labels actually in use across this Forgejo rather than assuming. The original workflow used `runs-on: docker`, which is the minority convention here — **13 of 15 repos use `ubuntu-latest`**; only `TeaLeaves` and `iac-repo`'s renovate job use `docker`, and both pair it with an explicit `container:` image. Checking that surfaced two further problems that would have bitten at runtime: **1. Unqualified action reference.** I had `uses: actions/checkout@v4`. Every other repo here fully qualifies it as `https://data.forgejo.org/actions/checkout@v4`. The bare form depends on the instance's default action URL resolving as expected. **2. Alpine container vs JS actions.** I had `container: node:20-alpine`. act_runner injects a glibc-built node into the job container to execute JS actions, and Alpine is musl — so `checkout` could have failed at runtime. Notably `TeaLeaves` uses `node:24-bookworm`, not Alpine, for its containerised job. Dropped the container entirely in favour of `setup-node` on the runner image, which matches the dominant pattern and adds npm caching keyed on both lockfiles. Node 20 still matches what both Dockerfiles pin. Also adopted the house `ci-` prefix on the concurrency group and the `workflow_dispatch` trigger. > The VSCode Actions extension flags `root.concurrency` as invalid. It's a false positive — verified the YAML parses correctly with PyYAML, and `Quest-Board` uses the identical unquoted form in production on this instance. **Caveat on verification:** the earlier container run proved `npm ci`, both suites, and the build pass against the lockfiles. It could not exercise `runs-on` selection, action resolution, or the npm cache — those only prove out on a real runner. Worth watching the first run land.
claude-bot deleted branch chore/project-hygiene 2026-07-17 01:50:25 +00:00
Sign in to join this conversation.
No description provided.