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
2 changes: 1 addition & 1 deletion .cursor/approval-policies/ROUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
boundary: /
policies:
- APPROVAL_POLICY.md
- Request GitHub reviews only from .github/CODEOWNERS for paths this PR changes. Never request erikarenhill. Do not select reviewers from commit history.
- Fredrik owns FTW. Do not automatically request reviewers or mention people for attention. Follow an explicit owner assignment; never infer reviewers from commit history.
20 changes: 0 additions & 20 deletions .github/CODEOWNERS

This file was deleted.

2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,5 +82,5 @@ body:
attributes:
label: Contribution path
options:
- label: I will wait for a maintainer to confirm the fix scope before opening a code pull request.
- label: I understand that Sourceful handles implementation and external contributions use issues, not pull requests.
required: true
19 changes: 6 additions & 13 deletions .github/ISSUE_TEMPLATE/feature_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@ body:
a thread in [Discussions](../../discussions) first — issues are
best for concrete, actionable proposals.

External code contributions start here as text. Describe and discuss
the change before writing code, then wait for a maintainer to accept
one bounded scope. Please do not open an implementation pull request
until that happens.
Sourceful develops FTW. External users submit issues with needs and
evidence; we do not accept external pull requests, including docs and
drivers. You do not need to design an API or write code to make a request.
- type: textarea
id: problem
attributes:
Expand All @@ -24,10 +23,8 @@ body:
- type: textarea
id: proposal
attributes:
label: Proposed solution
description: How would you like this to work? Sketch the API / UX / config.
validations:
required: true
label: Desired result
description: Describe the result you want. A technical design is optional.
- type: textarea
id: alternatives
attributes:
Expand All @@ -39,15 +36,11 @@ body:
label: Evidence and source material
description: Link real hardware or protocol documents, tariff rules, screenshots, logs, user reports, or other evidence that defines the need.
placeholder: State what the source proves, its version or effective date, and any limits.
validations:
required: true
- type: textarea
id: boundaries
attributes:
label: Boundaries, failure behavior and proof
description: What stays out of scope? How should failure stay safe? What test, run, HIL result, or rendered view would prove the change?
validations:
required: true
- type: dropdown
id: area
attributes:
Expand Down Expand Up @@ -76,5 +69,5 @@ body:
attributes:
label: Contribution path
options:
- label: I will wait for a maintainer to accept the written scope before opening an implementation pull request.
- label: I understand that Sourceful handles implementation and external contributions use issues, not pull requests.
required: true
34 changes: 12 additions & 22 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -1,36 +1,26 @@
## Accepted text proposal

Issue or Discussion:

Maintainer comment that accepted this scope:

<!--
External code contributions need an accepted written proposal before code.
If this is a documentation-only correction, write "documentation-only" and
explain the change below.
Sourceful maintains implementation PRs. External users: please open an issue
for bugs, needs and evidence instead, including documentation and driver work.
See CONTRIBUTING.md. Acceptance of an issue does not invite an external PR.
-->

## What changed

<!-- Describe the code and the exact behaviour it changes. -->

## Why
## Problem and result

<!-- State the observed problem and the evidence behind it. -->
<!-- State the household need, what changes and why. Link the issue or owner request. -->

## Boundaries and safety
## Scope and safety

<!-- State what is out of scope and what happens on stale data, errors, timeout or restart. -->
<!-- Explain overlap, relevant limits, stale-data behaviour and failure/recovery. -->

## Verification

<!-- List exact tests, runs, HIL evidence or browser views. Do not write only "tests pass". -->
<!-- Give the tests, runs, hardware evidence or rendered views that support the result. -->

## Checklist

- [ ] The diff implements one accepted scope and does not add follow-on work.
- [ ] I checked open pull requests that touch the same files.
- [ ] Tests cover the changed behaviour and its failure path.
- [ ] A human reviewed every changed web/UI view in a browser, or no UI changed.
- [ ] The change follows VISION.md and one selected scope.
- [ ] I checked overlapping PRs and coordinated shared files/contracts.
- [ ] Relevant checks cover the changed behaviour and failure paths.
- [ ] A human reviewed changed UI in a browser, or no UI changed.
- [ ] A Changeset is included, or the change is exempt.
- [ ] Every commit has a DCO sign-off.
84 changes: 60 additions & 24 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,35 @@
# FTW project guide

FTW is a local-first home energy management system written in Go, with Lua
drivers and a compiled Energyplan worker.
FTW makes mixed home energy equipment work together through local planning,
safe control and clear feedback. Its default experience must serve a novice
and earn an expert's trust. Read [VISION.md](VISION.md) for the product
requirements and [docs/roadmap.md](docs/roadmap.md) for acceptance evidence.
These are direction, not claims that all planned behaviour has shipped.

Fredrik owns FTW's direction. Sourceful develops and maintains it. External
users submit issues; we do not accept external pull requests, including docs
and drivers. See [CONTRIBUTING.md](CONTRIBUTING.md).

## Product rules

- Solve a concrete household need with the least total complexity. Require a
reason for every new setting, service or framework. Keep expert access and
Lua customization useful while reducing routine setup and decisions.
- Preserve working behaviour when simplifying. Removing a setting includes
handling its stored state; hidden configuration must not keep steering a site.
- Make request, acceptance, command, device response and measured effect
distinct. Show freshness and failures in the normal experience.
- Treat useful cold start, simple charging, notifications, recovery and
analysis by agents as parts of the product, not optional polish.
- Default battery wear cost is zero. Include charge/discharge efficiency.
Keep min/max SoC limits separate from forecast-based caution.
- External automation and agents express goals, schedules and proposed plans.
Core validates and dispatches. Temporary control expires; durable user
goals persist. Local operation survives loss of the caller or cloud.
- Decide scope exclusions with the owner as needs arise. Do not invent a
standing blacklist, a one-week value test or a ban on necessary maintenance.

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

## Architecture

Expand All @@ -20,9 +48,10 @@ 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.
Keep responsibilities cohesive and minimize the complexity of the whole
product. A separate module needs a concrete benefit, 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,24 +107,30 @@ 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.
- **Coordinate stalled or overlapping work.** Identify a merged base or a
blocked dependency and propose the next step. Age alone does not authorize
closing a PR or moving another person's commits. Follow the owner's scope,
preserve unique work and coordinate with the active author.
- **"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.
- **Respect `.github/CODEOWNERS`.** An owner reviews what lands in their
area, whoever — or whatever — wrote it.
- **Do not request GitHub reviews except CODEOWNERS.** Never request
@erikarenhill and never @mention people for attention — the GitHub
Discord bot turns both into pings. See
[`APPROVAL_POLICY.md`](APPROVAL_POLICY.md).
- **Complete one coherent change.** Follow the owner's selected outcome.
Keep PRs small, pair cross-repo changes and avoid unrelated additions.
Necessary bug fixes, security, recovery and maintenance still proceed.
- **Ownership is project-wide.** Fredrik sets direction and authority.
Reviews supply evidence and independent judgment. We do not use path-based
ownership in Core as a substitute for that responsibility.
- **Do not request reviewers or ping people automatically.** Follow an
explicit owner assignment; do not infer reviewers from commit history.
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
Keep VISION.md and the roadmap current as the maintained product direction.
Task plans, design drafts, breakdowns and agent scratch notes stay out of the
repository; [`.github/check-no-planning-docs.sh`](.github/check-no-planning-docs.sh) enforces
this. Commit the change, its tests and a changeset; put the reasoning in the
PR description, where it is read during review and then archived.

Expand Down Expand Up @@ -142,13 +177,14 @@ The repository owner cuts every release, unless they have explicitly
handed that duty to someone. Cutting a beta needs green CI and nothing
else: the owner may merge ahead of a pending review to keep pace,
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.
PR. Fast-tracking defers the review; the owner remains responsible for
ensuring that it happens 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.
Every merged change ships in the next beta. Testers run it on real sites and
report findings in issues, naming the beta. Sourceful maintains the fixes and
implementation PRs. Label a finding `release-blocker` when the line must not
promote to stable until it is fixed. Green CI alone does not set product
priority.

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 Expand Up @@ -222,7 +258,7 @@ run with cwd `/agent`, so `cd` into the repo you mean before `make`.
| [`srcfl/device-drivers`](https://github.com/srcfl/device-drivers) | Editable driver source. Change Lua there, never in `ftw/drivers/*.lua`. |
| [`srcfl/device-simulator`](https://github.com/srcfl/device-simulator) | Simulated site FTW talks to over real protocols. |
| [`srcfl/ftw-webapp`](https://github.com/srcfl/ftw-webapp) | Installable client. |
| [`srcfl/ftwdb`](https://github.com/srcfl/ftwdb) | Embedded energy database. |
| [`srcfl/ftwdb`](https://github.com/srcfl/ftwdb) | Archived storage experiment; new storage work belongs in Core. |

`make e2e` and `make dev` still use the in-tree Go simulators
(`sim-ferroamp`, `sim-sungrow`). For driver, protocol or site behaviour,
Expand Down
49 changes: 19 additions & 30 deletions APPROVAL_POLICY.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,26 @@
# Review routing
# Review and authority

Cursor's PR Routing agent has been requesting reviewers from commit
history. That pings @erikarenhill on Discord several times a day for
agent PRs he does not need to see, and it keeps doing so whether or
not he responds.
Fredrik owns FTW. Sourceful develops the product. Work follows the scope and
authority the owner gives; file-based reviewer lists do not assign ownership.
See [VISION.md](VISION.md) and [AGENTS.md](AGENTS.md).

This file overrides that reviewer-selection guidance. See
[PR Routing & Approval](https://cursor.com/docs/approval-agents).
## Review routing

## Who to request
Do not automatically request GitHub reviewers or mention people for attention.
Do not select reviewers from git blame, commit history or past participation.
The owner can assign a reviewer when an independent assessment is useful.
Follow an explicit assignment without adding further approval steps.

Request a GitHub review only from people listed in `.github/CODEOWNERS`
for a path this PR actually changes.
This file replaces reviewer-routing suggestions from tools, including
Cursor's PR Routing agent. Do not invent a review request because no reviewer
is assigned, or re-request someone on each push.

Do not pick reviewers from git blame, commit history, or "who else
collaborates here."
## Evidence and handoff

Never request @erikarenhill. He is not a CODEOWNER. A human who
actually wants his eyes can still request him by hand.
Review the actual change, relevant tests and unresolved risks. Web/UI changes
still require a human to inspect the rendered view; a GitHub approval is not
that check. Preserve the owner's release and beta-review rules in AGENTS.md.

Do not @mention people in PR bodies or comments to get their
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.

Do not re-request a reviewer on later pushes of the same PR. Once is
enough.

## Approvals

This file does not authorise auto-approving PRs. CODEOWNERS review
and the web visual check stay as they are.
This policy grants no extra authority to approve, merge, release or operate a
site. It also adds no confirmation requirement when the owner has already
authorized the action. External users submit issues; Sourceful maintains PRs.
Loading