Logbook
Newest first. Entries are appended, never edited; anything that turns out to be wrong is corrected by a later entry and still stays where it is. Failures appear here at the same size as progress – where it does not go forward is the more interesting part.
There is nothing to buy yet, and no price to quote. Anyone who wants to know how far this goes can read along – or have it sent, at most once a month.
Yesterday’s milestone entry carried two wrong facts. Both were caught by the runtime agent, which checked this site against the repository it describes instead of against the entry that announced it.
befunde/m0-register.md: “8 Stellen”). I wrote
six from a commit message two days old and did not count.A third correction belongs here even though it was not a number: I wrote that the pack “keeps the lower value”. It keeps both values and decides nothing about which is true; the gate bounds at 2,500 anyway. That is a decision about acting, not about the number — and merging the two is exactly the move this project exists to catch.
The entry it corrects is about a milestone whose criterion is measured, not asserted. Both wrong facts were asserted from commit messages rather than counted from the artefact, on a page whose whole argument is that a value without its source is an opinion. The old entry stays where it is, marked — removing it would make this project’s own record the one thing on the site that cannot be checked.
The product summary sent out on 26 October carries “sechs Stellen” and names 4 October as the date of the last test-set run. The run was on the 21st; the excerpt that fed every page with that date had drifted since 9 October while claiming of itself “generated, not typed” — and no generator existed. One now does, in the runtime repository. The summary is corrected, and anyone who received the earlier version has two wrong facts in their inbox.
Later correction on 26 October 2026 — see “Two numbers in the milestone entry were wrong, and one of them was mine twice”. This entry stays as it was written.
The Anker SOLIX Solarbank 4 E5000 Pro is installed, connected and released for Modbus. Since 25 October the probe polls the real device on the local network instead of the stand-in. On the same day a PV array was connected to the PV1 input. Milestone 01 is reached — the first of five, declared on 10 September 2026, six weeks before it could be checked.
The criterion from 10 September reads: “A real asset is named, with a data source and with permission to use its data. No invented data sheet, no example asset.” Clause by clause:
Three weeks ago the architecture map had two boxes waiting for hardware. It has none.
The probe does not only read values, it derives where the device disagrees with the source it is documented by. Six such places were found. The sharpest: one register reports 3,000 W where both the annex and the data sheet say 2,500 W.
The cheap move would have been to widen the limit until the warning goes away. The pack keeps 2,500 and keeps both readings standing until a source decides. This is the entire point of the exercise, arriving on day one of real hardware: a schema written against an imagined object could never have produced this disagreement, because an imagined object agrees with its data sheet by construction.
The NOUS A1T arrived, sits in the socket, and is read by the runtime: one
device, hostname tasmota-76BEC1, polled over plain HTTP on the local network
every five seconds. Its readings land in the measurement store under their own
source name, meter, separate from everything the battery says about itself.
The box on the architecture map has therefore moved from
“hardware not here” to “runs” — the first box on that map to do so since
30 September.
Two days ago this log said that what the device actually reports — “including whether it gives the direction of flow or only its magnitude — will be measured when it arrives, not copied from a shop page”.
It was measured. The answer is magnitude only. The measuring chip reports
power without a sign, so the quantity is called meter_power_abs and every
comparison with the battery is a comparison of amounts. That is a real loss:
an amount cannot tell charging from discharging. It is written into the name
of the quantity rather than into a footnote, because a value called
meter_power would have been believed to carry a direction it does not have.
The live cockpit disagreed with itself. The status strip at the top has said pack 0.2.0 and 14/14 tests since 9 October. The parts list directly below it kept saying “None of them exists yet”, with the schema, the runtime and the test set marked planned — a state that has been false since 28 September, when all three came into being.
This is the same failure the entry of 9 October describes: a value that is maintained by hand stays where it is until someone moves it. That entry fixed the strip and the architecture page and said the gap “had spread across the site in three versions”. It missed the fourth, one section further down the same page. Finding the same mistake twice is worth recording precisely because the first fix claimed to have caught it.
Two changes:
What stays as it was, deliberately: the test object remains being procured, the two agents remain planned, and every milestone remains open. Built is not the same as shown to work — nothing here has been proven by a foreign agent, and the refusal counter still stands at zero.
Two NOUS A1T metering sockets are ordered (16 A, 3,680 W, Tasmota preinstalled). One of them is meant to become the box on the architecture map that has said “not bought yet” since 30 September: the independent meter.
The pack will carry values such as output power, and the cheapest place to get them is the battery’s own interface. But a verdict that says “the action stayed within its limit” is worth little if the only witness is the device that acted. The runtime specification (BRR-010) therefore calls a second source non-negotiable: the meter reads what actually flows at the socket, and the state service treats a disagreement between meter and battery as unknown — not as a tie that the prettier number wins.
The last line is literal: this entry rests on an order confirmation and the vendor’s description, nothing else. Every number from this device enters the pack only after it has been read from the device.
Until today the status strip said what it said on day 0: no schema, no runtime, no users, zero reasoned refusals. That had been wrong since 28 September, when pack, gate, journal and test suite were written. Nobody had set a new value, so the strip kept showing the old one. That is how it is built, and it is the strip’s only weakness: it is accurate only if someone writes the entry.
The same gap had spread across the site in three versions. The front page
description said “nothing”, the architecture page said 13 of 13 tests from 30
September, the investor page said 14 of 14 from 4 October. The last one is
correct. It comes from the hash-chained journal of the runtime
(../26_Battery_Reality_Runtime/protokoll/pruefsatz.jsonl, last entry
pruefsatz_ende, 2026-10-04T16:35Z, 14 cases, 14 passed, no wrong approvals,
no wrong refusals). The architecture page now reads its numbers from the same
excerpt, so it cannot fall a run behind again.
This is a line of thinking, not a decision. It is written down because it changes who we would sell to, and that is too large a question to keep in a chat window.
Two questions from Andreas on the same day. First: if the end state is a machine that runs and markets an asset without a human in the loop, does that not make us a direct marketer – an AI‑native one? Second, after a longer answer: did I mean an operator when I said operations manager?
The second question is the useful one. The two are different roles in German law, and the difference decides what kind of company this would be.
Anlagenbetreiber – the operator in the legal sense. § 3 No. 2 EEG: „whoever, independently of ownership, uses the installation to generate electricity from renewable energy.” The permit is addressed to them, the EEG claims are theirs, the grid connection contract is theirs – and under § 8a (2) No. 5 EEG it is the Anlagenbetreiber who is liable when the agreed feed-in limit is exceeded.
Betriebsführer – an operations management service provider, working for the operator, usually under power of attorney. Liable to the operator by contract, not to the authority.
Eigentümer – the owner. All three can be different parties, and in a community wind farm they usually are.
The thing that keeps people in this process is not that the trading is hard. The trading is automated. People are there wherever somebody has to carry responsibility: who signs the registration, who checks the invoice, who tracks whether this grid operator settles in energy or in money, who is liable when a connection limit is exceeded.
If that is right, then: only the party that carries the liability can replace its own staff with a machine. A software vendor never can. It can sell a tool and hope the customer dares to cut staff; the customer carries the risk, so the customer does not dare.
That argument points further than we first took it. As an operations manager we carry our own performance risk and keep what the machine saves – a cost advantage, capped by what competitors charge. As the operator under a lease, our revenue is the spread between what the asset earns and what the owner is paid, and the machine improves the spread. The first is a service business. The second grows with the software.
No owner leases an installation to someone whose gate has never run. As an operations manager we get the same installations, the same documents and the same work, without anyone having to hand over the operator role. After two years we would have what the step needs: a history of checked decisions, an error rate, and an insurer who has seen the gate.
Nothing measured. Reasoned refusals: zero. No company has been founded, no asset is under management, no owner has been asked. What changed is only the shape of the question we are testing: not will someone buy the layer, but possibly will someone let us run their installation with it.
Both are the same open point in the end – whether anyone needs this.
Until today, every sentence on this page about why this project should exist came from us. Today someone who does this for a living said something about it, and it is the kind of answer that is worth more than agreement.
He is Head of BESS – he runs battery storage and knows optimisation from the inside. No name here, it was a private conversation. In substance:
Optimising a battery is long since solved. There is high-speed trading, there are finished algorithms, a great deal is automated already and without any AI. Where work is still done by hand is elsewhere: market communication, settlement, origination.
The first sentence of our problem statement reads, word for word: “Computing what to do with a battery is solved and sold.” That is now confirmed by someone outside this project, and it is the first time anything here has been.
Our second sentence is “Computing whether an action may be executed is not.” He did not name it. His list of open problems is a different list from ours.
Someone not naming a pain is not proof that the pain does not exist. But we do not get to explain it away either, so here is the honest version of both the explanation and its weakness.
The explanation: a Head of BESS runs his own assets with his own software. In that position the permission question was answered once, by his own engineers, for his own fleet – and it stays answered. Our claim only bites when the agent is foreign and the asset is foreign. Neither is true in his world.
Why that explanation is dangerous: it is exactly the shape of argument that rescues any unconfirmed thesis. Anyone who uses it owes the counter-test, and ours is specific: an aggregator or a direct marketer, running assets that do not belong to them. If the permission question is cheap for them too, the hypothesis is in trouble.
A sentence used to stand in the hypothesis section: “this value exists only under one premise – that there will be foreign agents acting on assets they did not build.” It was deleted yesterday, during a round of cutting, as a duplicate of another refutation condition. That was a mistake – the other condition says something else – and it meant the premise under the most pressure was the one condition no longer written down anywhere.
It is back, as the fifth way this can be refuted: if foreign agents never arrive at all, this is a schema nobody reads.
If optimisation is solved, why does Fraunhofer IEE put €3.9 bn a year on the table as unused storage flexibility? The obvious reconciliation is that he is describing the large, professionally operated plants, while that number comes from the long tail of 2.6 million mostly small systems – where per-asset engineering never pays for itself.
That would sharpen our story considerably. It also comes from a single conversation and nobody has confirmed it. It stays out of the argument on this page until someone does.
Unchanged. Reasoned refusals: zero. What moved is not the mechanism but the burden of proof – away from does it work and towards does anyone need it.
Until today this site called itself a research project, documented in the open, and the foot of every page said no commercial intent — a personal experiment. That came from a decision on day 0, in Andreas’ own words: “this is simply my favourite project, I don’t want to earn money with it.”
Today he reversed it: this is the hypothesis for a startup. We intend to earn money with it and to win investors. The label is gone from the front page, the foot of every page, and the imprint.
The question at the top of this page is the same, word for word. So is the measure beside it: does a foreign agent, using this schema, understand a real battery well enough to refuse an action it is not allowed to carry out?
That is not a courtesy to the old framing. It is the business. The thing we want to sell is the layer that carries the refusal — the one an owner uses to grant permission to an agent they did not build. If a foreign agent cannot be bounded, there is nothing to sell, and the number in the status bar stays at zero until one is. It still reads zero today.
The logbook also stays as it is: appended, never edited, failures at the same size as progress. A commercial intent is a reason to keep that, not to drop it. The entries from before today keep their old wording and are not back-dated — including the ones that say this project is not meant to earn money. They were true when they were written.
Two things we should name rather than let a reader find.
The first: no commercial intent was free to claim and easy to believe. We have given up the cheapest credibility this project had, and the only thing that can replace it is evidence — a refusal that actually happened, a limit with a source, a second asset we did not describe ourselves.
The second: we have no evidence yet that anyone will pay for this. Not one conversation with a payer, no price tested. The thesis about where the money is — that permission is the unoccupied slot in this value chain — is at exactly the stage this whole site exists to be honest about. It is a good sentence. It is not yet a finding.
The pack has an object. Ordered today, delivery expected in about a week:
Small. Deliberately so: this is an object we own, can measure, can open up and can publish about without asking anyone for permission. Milestone 1 asks for a real asset with a data source and the right to use its data — a grid-scale battery borrowed from an operator would have given us the second half of that only on paper.
The same set is sold with the Solarbank 2 Pro and the 3 Pro. Those two do not expose Modbus. The 4 Pro does: Anker maintains its own Home Assistant integration over local Modbus TCP on port 502, read and write — operating mode, power setpoints, output control — with no cloud in the path. It has to be switched on in the vendor’s app first.
That switch is the digital layer in one gesture. The access exists because the manufacturer grants it, in an app that belongs to the manufacturer, and a firmware release can take it back. Nothing here is an accusation — it is the thing this project claims has to be described rather than assumed. An agent that cannot tell refused from unreachable does not have this layer, and on this device the difference has an owner.
The unit can discharge at 2,500 W. As a plug-in solar system it may feed 800 W into the grid. The asset could, and it may not — and the two numbers come from different worlds: one from a data sheet, the other from the rules for plug-in generation.
That is the shape of refusal this project exists for, and it arrived with the delivery note rather than being invented for a demonstration. It is the first candidate for milestone 4, which asks for a refusal that needs two layers and names both.
The normative layer of a balcony system is thin, and pretending otherwise would be the kind of claim this page removes rather than adds. No prequalification, no control reserve, no redispatch, no direct marketing. What is real: the registration duty in the Marktstammdatenregister, the 800 W limit, the connection rules that come with it. Small, checkable limits with a source — which is worth more than a large invented one.
Milestone 1 stays open. Ordered is not delivered, and delivered is not answering. It is met when the device stands, the local interface responds, and the asset record exists.
Two layers of the five are not written: the digital one and the institutional one. Until today the page labelled them “the two layers the pack does not contain”, which reads as out of scope. It is not what was meant, and it contradicted the paragraph below it, which calls Layer 4 “the next stage, not a footnote”. The label now says still to be written.
Both are in scope. They are in different states, and the difference matters.
It was marked presupposed until yesterday because the original version addressed a direct marketer, who already has EMS access, schedule data and market data. For a private operator that inverts. The data connection is not a precondition, it is the first thing that becomes real — before the schema, before any runtime.
What is still missing is the description: where the data comes from, at what rate, with what latency, who else holds a write path, and how an agent tells a refusal from an unreachable source. That last one is not a detail. From the outside the two look identical: nothing happens.
On 2026-09-10 this log said the mandate question was trivial for a private setup — the battery belongs to the household, so there is only one principal. That is wrong. There are at least five, and every one of them is real at 5 kWh:
The structure is identical to the 20 MW case. Only the amounts are smaller: an agent acts on an asset, and the consequences land on a person who is not in the loop.
A consumer device keeps a write path for its manufacturer that the owner cannot cancel without losing functions.
The owner is not the only principal, and cannot revoke the other one.
On a grid-scale asset the same question would be settled in a contract. Here it stands bare. For testing the idea, that makes this the better case, not the weaker one.
Milestone 05 is declared: a refusal that comes neither from physics, nor from law, nor from price — the action is executable, permitted and worthwhile, and the agent still may not carry it out.
It is deliberately declared without a target date. Every other milestone has a window; this one has a predecessor instead. A date here would be a guess dressed as a plan.
Nothing is built. The status above is unchanged.
The project gets its own address: reality-pack.dev. Not
battery-reality-pack.energy, and not a subdomain of an existing one.
.energyIt would have contradicted a sentence in the first screen of this page: “It is the first case, not the goal.” An address that commits to energy says the opposite of that. Energy is where the layers happen to be hardest and best documented — it is not what the schema is about.
It would also have named Pack #001 only. A PV plant, a wind turbine, a data centre and a charging park are already named in the repository as conceivable further packs; each would have needed its own domain. And the renewal price is roughly five times that of the alternative, every year, for a project with no revenue that is meant to stay readable after the twelve months are over.
It would have been free and, today, perfectly honest. The argument against it is the measure of this project: a foreign agent. A schema that lives under a company’s domain reads as that company’s schema. For something meant to be consumed by people who were not involved in writing it, a neutral address is a small but real signal.
The obvious objection to buying an address for a schema that does not exist is that it is an advance on something unbuilt. It is not, and the distinction is worth keeping: the build rule binds what is delivered, not what is reserved. An unused domain makes no claim to anyone. A page that asserts things it cannot hold does.
The site configuration still carries no site value, so the delivered pages
emit neither a canonical URL nor an og:url. Checked today: the domain has no
DNS delegation and answers nothing. Pointing metadata at an address that does
not respond would be exactly the kind of claim this project keeps removing from
its own files.
That one line gets set when the domain actually answers. Deployment itself is a separate question and not decided here.
While there is only one pack, the page stays at the root. A /battery path gets
created when there is a second pack for it to be distinguished from — an index
page above a single entry is structure without content.
The status above is unchanged. An address is not a schema.
Going through the layers turned up three errors. All three sat in our own files, all three were found by reading, none ever produced an error message.
The README said: “a machine-readable representation of a real asset across five layers”, followed by a table with five rows. The page has always said: Layer 0 presupposed, Layer 4 roadmap, three are included.
Both texts were written on the same day. Nobody lied — the sentence had two jobs and did only one: it defines what a Reality Pack is in general, and directly below it says that this one is Pack #001. A reader concludes five.
That is exactly the promise the build rule forbids — stated in the same file, two sections further down. A promise may only say what the artefact holds. Corrected: the table now has a third column, and the sentence before it says three.
The digital layer was marked presupposed. Choosing a real device showed it is nothing of the sort: it is decided by the purchase. The same manufacturer’s range offers devices with an open local interface and devices without. With the latter the access belongs to someone else’s cloud, which can throttle or withdraw it.
And the consequence the word “presupposed” conceals: an agent that cannot tell a refusal from an outage does not have this layer. From outside the two look identical — nothing happens.
The state is now called procured. Not a nicer word, a truer one.
An entry dated 2026-09-10 said “Layer 5” twice. The stack counts from zero: 0 digital, 1 physical, 2 normative, 3 economic, 4 institutional. There is no fifth. Corrected.
Three errors, found by laying our own files side by side. None of them would have surfaced through a build, a test or a checksum, because none of them is a technical defect. All three are statements that had stopped being true.
That is the same class as the button which pointed at a deleted section two days ago, and the same as the duplicated status display in the footer: rules only bind going forward. Backwards, someone has to look. The build rule was in the README from the start — it did not prevent the promise two paragraphs above it.
The status above stays unchanged. A corrected sentence is not progress, it is the withdrawal of an advance.
The test object includes solar panels, up to 2,000 Wp — the ceiling of the simplified rules. The inverter is already inside the battery, which brings four MPPT trackers and accepts up to 5,000 Wp of solar input. So what is missing is panels and a mount, nothing else.
They are not part of this experiment because they generate electricity. They are part of it because without them two layers stay empty.
A battery on its own is fully known: state of charge, power limits, temperature — all measured, nothing forecast. There would be no uncertainty in the interface that could be declared.
That would remove the sentence the whole undertaking hangs on: an agent does not need the answer, it needs the declared boundary of the answer. With panels a quantity enters that the agent cannot command and has to predict. Only against that does it show whether the schema is more than a data sheet in JSON.
The battery alone would still be subject to registration: every stationary battery storage system must be entered in the Marktstammdatenregister — regardless of size, commissioning date and actual feed-in. So Layer 2 would not be zero.
But everything concrete hangs on generation: the 800 W feed-in limit, the 2,000 Wp module ceiling, the aggregation per metering point. That is precisely the rule set on which the idea of two devices failed — this project’s best evidence so far. Without panels it would not be there.
Whether a battery that charges exclusively from the grid and never feeds in fits cleanly into that rule set could not be settled. German renewables law defines a plug-in solar device as modules, inverter, connection cable and plug — a battery does not appear in the definition.
That is itself a Layer 2 finding: a real, purchasable configuration for which the rule has no clear category. Not “forbidden”, not “permitted”, but not provided for. An agent that depends on an unambiguous answer has none here — and must be able to say so instead of picking one.
| Configuration | The question put to the agent |
|---|---|
| Battery only, dynamic tariff | Is electricity cheap right now? One source, one decision. |
| With panels | Do I take the cheap hour now — or keep capacity free for tomorrow’s sun? |
Only then do two uncertain sources compete for the same storage. That is the question stated further down this page: which permissible action is worth most?
The status above stays unchanged. Still nothing bought, nothing built and nothing refused.
Decided: the test object will be an Anker SOLIX Solarbank 4 E5000 Pro (5 kWh, ~€1,600), together with a dynamic electricity tariff. It has not been bought, so milestone 1 stays open.
It has what matters for a foreign program: an official local Modbus TCP interface, read and write, enabled in the manufacturer’s app. No cloud detour, no reverse engineering. For home batteries, local write access is the exception, not the rule.
The dynamic tariff is not an add-on, it is the reason. It makes Layer 3 real: hourly exchange prices are a limit nobody in this house set. A refusal that goes back to a rule we wrote ourselves proves nothing.
What is not real about this asset belongs here just as much: Layer 2 is simulated. The device feeds in at 800 W and is therefore far below the 4.2 kW at which § 14a EnWG applies — it will never receive a control command from a grid operator. The rules it has to be measured against are ones we write ourselves. That is a weakness of the test object, not of the schema, and it stands here so that nobody later mistakes it for a success.
The idea was to stack two devices to get past 4.2 kW and make Layer 2 bite. It failed on three independent grounds, and the failure is the best evidence so far for this project’s thesis:
An agent that reads only the data sheet plans 2,500 W of feed-in and is wrong. An agent that adds the second box arrives at 5,000 W and is wrong not by a factor but categorically: the result is not a larger number, it is a different legal regime. The same hardware may do different things depending on how it is installed and registered. A schema that describes only the device cannot answer that question in principle.
Two observations for the schema design fell out along the way:
Noted, not decided. It is the only asset at household scale I know of where Layers 2 and 3 come from outside:
The price has to be named honestly: roughly €8,000 to €12,000 installed instead of €2,000, against a profit share of up to €100 a year. Financially that is not a business. It would be an expenditure for insight, and it only pays once the schema carries at the small asset at all. Before that it would be an advance.
The status above is not changed by this entry: no schema, no runtime, no users, zero reasoned refusals. A purchase decision is not a refusal.
The experiment starts today, and today none of it exists: no schema, no runtime, no users. That is why the four values above stand where they stand.
What does exist is a question, a frame of twelve months, and four milestones whose criteria are fixed today — before anything was measured, so that they cannot move later.
What happened today: the technical description of the Battery Reality Pack was moved here from the Agent Reality Stack. It stood there as a product page. This project sells nothing, so the commercial layer has been removed — pilot, annual licence, operating contract, channels, the booking prompt. The technical content stands unchanged below it.
Three promises stood on that page which it did not keep. Two are corrected: an unfilled placeholder for a monetary amount sat in the middle of the delivered text and is gone — not repeated here, so the string does not end up back in the text nobody wants it in. The “refusal demo” executes nothing and now says so itself: there are five hand-written examples. The third promise was that the page answered with 404 on the production host while being advertised. That is no longer a promise either: this page is deployed nowhere.
The beginning of an experiment is a beginning. Anyone reading back in twelve months should be able to see what was not there on this day.