Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
11 changes: 10 additions & 1 deletion .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,19 @@
# produced.
#
# This is about who gets asked, not who is allowed to contribute.
# The control loop is owned because that is the product. Process files are
# owned so agent rules cannot be rewritten in passing.

# Web/UI changes require a human visual check; see AGENTS.md.
# Web/UI changes still need a human visual check; see AGENTS.md.
# A GitHub review from the CODEOWNER does not replace looking at the page.
# Do not auto-request @erikarenhill; he is not a CODEOWNER.

# The household loop: measure, plan, dispatch, and the UI that explains it.
/go/internal/control/ @frahlg

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Cover the control-loop composition root

Add /go/cmd/ftw/ to this ownership block. As written, a PR changing go/cmd/ftw/main.go, site_dispatch_safety.go, or driver_failure_default.go matches none of these product CODEOWNER patterns, despite that package wiring the control tick and physical dispatch safeguards. Those central control changes would therefore bypass the mandatory owner review this commit is intended to establish.

AGENTS.md reference: AGENTS.md:L120-L123

Useful? React with 👍 / 👎.

/go/internal/mpc/ @frahlg
/go/internal/telemetry/ @frahlg
/web/ @frahlg

# Drivers and the Lua host.
/drivers/ @frahlg
/go/internal/drivers/ @frahlg
Expand Down
66 changes: 51 additions & 15 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,32 @@
# FTW project guide

FTW is a local-first home energy management system written in Go, with Lua
drivers and a compiled Energyplan worker.
FTW is a box in the house that measures, plans and dispatches battery, PV and
charging so the site stays safe and intelligible when the cloud, the optimizer
or a driver is gone.

That loop is the product. Everything else is an add-on. Work belongs in core
only when it makes that loop better this week, for a household, without a new
tariff model, a new protocol or a second safety authority.

The implementation is Go, with Lua drivers and a compiled Energyplan worker.

## Not this project

These are standing no's, not a backlog. A later theme can reopen one of them;
until then they wait, and they do not queue against master.

- Not a GIS or roof-drawing product. Irradiance that improves the plan is
core; a map of the house is not.
- Not a CPO. A local OCPP server that core commands is in; forwarding sessions
to an upstream operator waits.
- Not a Modbus server for other home-automation stacks.
- Not a worldwide tariff engine. Named household tariffs, after a written
contract, are enough.
- Not Matter, EnergyKit, V2X automation or a second commander on the site
until the household loop is boringly correct.
- A simulator is a test harness, not a second UI.

The optimizer proposes. It is not the product.

## Architecture

Expand All @@ -20,9 +45,9 @@ The repository has three explicit modules:
[`go/internal/mpc`](go/internal/mpc).
It proposes plans; core validates them and retains a Go fallback.

Keep new functionality in core unless it has a narrow versioned contract,
independent failure/update semantics and a safe unavailable state. Optional
modules never bypass core safety.
If work is not the household loop, it belongs outside core, and only with a
narrow versioned contract, independent failure and update semantics, and a
safe unavailable state. Optional modules never bypass core safety.

Read [docs/architecture.md](docs/architecture.md) for the system map and
[docs/site-convention.md](docs/site-convention.md) before changing power math.
Expand Down Expand Up @@ -78,21 +103,31 @@ landed on somebody else's finished work.
- **Check for open PRs touching the files you are about to change.** If one
exists, it has right of way: rebase onto it, or say so and pick different
work. Do not rewrite files out from under an open branch.
- **An open PR is a lock with an expiry.** Right of way is a reservation you
use. A PR whose base branch is already merged must be retargeted at
`master` or closed. Parking means the unique commits move, then the PR
closes. A branch that is not moving toward `master` is an abandoned
reservation, not a review queue.
- **"This already exists" is a claim that needs evidence of the right kind.**
For behaviour, that means a test or a run. For anything visual, it means
rendering both versions and comparing them — counting tokens, selectors
or symbols in the source does not establish that a UI change landed.
- **Prefer small PRs in one area.** Merging often only works when changes do
not overlap; a large cross-cutting pass conflicts with everything and ages
badly while it waits.
- **One live theme, small PRs inside it.** The default theme is the control
loop: measure, plan, dispatch. The repository owner may name a different
theme when opening that window. Merging often only works when changes do
not overlap. A large cross-cutting pass, or a green PR outside the theme,
waits; it does not queue against `master`.
- **Respect `.github/CODEOWNERS`.** An owner reviews what lands in their
area, whoever — or whatever — wrote it.
area, whoever — or whatever — wrote it. Control, planning, telemetry and
the UI are owned because that is the product, not because they are
process files.
- **Do not request GitHub reviews except CODEOWNERS.** Never request
@erikarenhill and never @mention people for attention — the GitHub
@erikarenhill and never @mention people for attention. The GitHub
Discord bot turns both into pings. See
[`APPROVAL_POLICY.md`](APPROVAL_POLICY.md).
- **Review web/UI changes in a browser.** A human must inspect the rendered
interface; AI review and reading the source code are not enough.
interface; AI review, a GitHub approve and reading the source code are not
enough.

Planning documents, design specs, task breakdowns and agent scratch notes
stay out of the repository; [`.github/check-no-planning-docs.sh`](.github/check-no-planning-docs.sh) enforces
Expand Down Expand Up @@ -145,10 +180,11 @@ because in this project review happens on the beta as much as in the
PR. Fast-tracking moves a review, it never removes it — the CODEOWNERS
owner still reviews what landed in their area, on the running beta.

Beta is the playground. Every merged change ships in the next beta;
testers run it on real sites and file what they find as issues or PRs,
each naming the beta it was seen on. Label a finding `release-blocker`
when the line must not promote to stable until it is fixed.
Beta is the playground for what landed in the live theme. Every merged
change ships in the next beta; testers run it on real sites and file what
they find as issues or PRs, each naming the beta it was seen on. Label a
finding `release-blocker` when the line must not promote to stable until it
is fixed. Green CI is not a reason to merge work outside the theme.

There is no release calendar. A beta promotes once it has run on the
validation sites for a few days with no open `release-blocker`, and
Expand Down
7 changes: 4 additions & 3 deletions APPROVAL_POLICY.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ attention. The GitHub Discord bot turns those into pings too.

## When not to request anyone

If no CODEOWNERS path matches, request nobody. Web/UI changes need a
human looking at the rendered page (see AGENTS.md); that is not a
GitHub review request.
If no CODEOWNERS path matches, request nobody.

A GitHub review from the web CODEOWNER is not the visual check. Web/UI
changes still need a human looking at the rendered page (see AGENTS.md).

Do not re-request a reviewer on later pushes of the same PR. Once is
enough.
Expand Down
3 changes: 3 additions & 0 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ safety boundary. Drivers translate hardware protocols. The optimizer proposes
plans and supplies primary forecasts. A failure or upgrade outside core must
never stop local measurement or make dispatch unsafe.

The product boundary — what that system is, and is not — lives in
[`AGENTS.md`](../AGENTS.md). This document is the system map.

## Module boundaries

| Module | Source | Runtime | Responsibility |
Expand Down
4 changes: 4 additions & 0 deletions docs/roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ work already in implementation or acceptance. **NEXT** has a defined contract
and entry gates. **LATER** items have no delivery promise; each must satisfy its
promotion gate before it can move forward.

Operating law for what may land is [`AGENTS.md`](../AGENTS.md): the household
loop is the product, there is one live theme, and a LATER row is not
permission to open a PR against `master`.

The permanent rules do not move between lanes: core owns safety and dispatch,
the site sign convention is unchanged, and local operation never depends on an
optional service. Planner output remains untrusted input. A failed or stale
Expand Down