Files
felhom.eu/REPORT.md
T
admin 985f0ba63c
gates / gates (push) Successful in 30s
Record the guards, the narrowing, and the two things I could not do
R-273's owed guards are both built and closed. R-291 records what CI stopped
covering and why, so it can be widened deliberately rather than discovered.
R-292 is new and was found by a test failing for the wrong reason:
artifact_sha_invalid conflates "version missing", "registry unreachable" and
"bad sha" into one message. v0.102.0 works around it by ORDERING -- the probes
run first, so an unreachable registry is reported as unreachable -- but the
message itself is untouched.

CONTEXT gains the rule this session is about: a check and the policy it enforces
must read the same number from the same place, or they drift and the drift looks
like a defect in something else. Two corollaries, both of which cost something:
a bounded check must print what it stopped covering on every run, and an
unreadable policy is INCONCLUSIVE rather than unbounded.

Stated in the report rather than glossed: Part 4 (finding receipts for the twelve
downgraded claims) was NOT done and is a shortfall, not a decision -- splitting
it would have produced exactly the half-checked green the exercise exists to
prevent. Part 5 was droppable and dropped. The tag-push green is not re-proved
tonight and is not claimed; the evidence offered is runs 190 and 216.
2026-08-09 19:28:45 +02:00

153 lines
9.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# REPORT — the guards, and one thing I could not establish (2026-08-09 evening)
No machine touched. Both demo boxes stayed offline and in transit; nothing here needed them.
**Parts 1, 2 and 3 are done. Part 4 and Part 5 are NOT done** — see §6 and §8. Part 5 was marked
droppable and was dropped; **Part 4 was not marked droppable and I ran out of session before it**,
which is a shortfall rather than a decision.
---
## 1. Part 1.1 — the deleter: **NOT ESTABLISHED**
**This prompt's account is not corroborated by any source I can reach**, and the prompt itself said
not to take its word for it.
| claim in the prompt | what I found |
|---|---|
| "the register records … pruned to the newest ten … 33 deletions, all HTTP 204" | **No such row exists.** The only prune-adjacent row is **R-210**, which is `WAITING-ON-OPERATOR`, says in terms *"Nothing was deleted; this is a list, not an action"*, and concerns **local Docker images on DooPlex**, not the Gitea registry |
| "newest ten per package" | **Not visible in the current state.** `felhom-agent` generic holds 10, but `felhom-controller` and `felhom-hub` container packages hold **19 each** |
Everything else I could reach is silent, and silence here is not evidence of anything:
`package_cleanup_rule` is **empty**; `package_version` has **no soft-delete column**, so a deletion
leaves no row; Gitea's `action` feed carries **no package operation at all** across 2026-08-08 →
2026-08-09 and nothing whatever on the evening of 08-08; the Gitea pod has **53 days uptime, 0
restarts**.
**And I withdrew one of my own claims.** R-287 said *"no DELETE on the packages API appears in 48 h of
Gitea router logs"*. Re-checked: `kubectl logs --since=72h` returns nothing older than **2026-08-09
16:35** and contains **zero** `api/packages` lines even for requests I made myself. **The log never
covered the window, so its silence was never evidence.** Withdrawn in the register.
**What remains established, unchanged:** `v0.120.0` downloadable at 2026-08-08 14:29 UTC (run 267
printed `ok v0.120.0`), 404 by 2026-08-09 09:30 UTC (run 284), and `0.128.0` published at 14:47 UTC —
eighteen minutes after the good run. **It may be unestablishable from this side: Gitea keeps no
package-deletion trail.**
Per §8 I halted that part's attribution and carried on; the rest is independent.
## 2. The number, and the two places that read it
`felhom-agent/scripts/retention-policy.json``generic_versions_kept: 10`.
Read by **`scripts/check-published-versions.py`** (bounds its assertion) and referenced by the prune
procedure. The file states, in its own header, that ten is an **observed state and not a located
ruling**, and that the principled bound is the hub's vouched `min_agent` floor — nothing can install
below it — which needs network the gate does not have.
**What CI no longer covers:** *a released version older than the retention window is no longer
asserted downloadable.* Its **git tag and config tree are still asserted**; only the binary's presence
is dropped. The check **prints the dropped versions every run**:
```
11 released version(s); retention policy keeps the newest 10
NOT ASSERTED (older than the retention window …): 0.120.0
^ these versions still have git TAGS … what is no longer asserted is the BINARY's presence.
```
Three controls: green at 10 naming what it dropped (**exit 0**); widened to 11 the evicted version
re-enters and convicts (**exit 1**, `FAIL v0.120.0`); the policy file removed → **exit 2 INCONCLUSIVE**,
naming the path it tried — never silently unbounded.
## 3. `felhom-agent` green
```
reuse-refs OK · instructions OK · published OK · release-complete OK · all agent gates OK
```
**At `main`: green**, pushed as `53d047a`, and the pre-push hook ran the same entry point.
**At a tag: not re-proved tonight, and I will not claim it.** The available evidence is that the gate
is ref-independent — it enumerates from the Gitea tags API, and runs **190** (`v0.126.0`) and **216**
(`v0.127.0`) were tag pushes that passed. Minting a tag purely to prove it would have published a
release, which this session forbids.
## 4. Red-proofs
| # | mutation | asserted applied | outcome |
|---|---|---|---|
| 1 | **tag check removed** | `grep -c` → 1 | **scenario A FAILED, reporting `flash = "artifacts_set"`** — Friday's exact defect returned: the manifest saved with no tag |
| 2 | package check removed | `grep -c` → 1 | scenario B FAILED, `flash = "artifacts_set"` |
| 3 | inconclusive branch mapped onto success | `grep -c` → 2 | scenario E FAILED |
All reverted; `grep -c MUTATION`**0**; all seven tests green again.
**Red-proof 3, stated precisely rather than flatteringly:** with the inconclusive branch mapped onto
success the save did **not** complete — it fell through to `artifact_sha_invalid`. So the mutation
proves the guard is load-bearing for *the message the operator sees*, not for the save itself. That is
the honest reading, and it is exactly the defect scenario E exists to prevent: the operator being told
"missing or invalid" when the truth is "I could not reach the registry".
## 5. The five scenarios, as the operator sees them
| | outcome | the message |
|---|---|---|
| **A** tag missing | REFUSED | *"Refused: that version has no usable git tag. The installer fetches an agent's config files from `raw/tag/v<version>/configs/`, so a version published without its tag makes every fresh install and reinstall fail at step 5 of 8 — as root, on a virgin machine. … Fix it by pushing the tag: `git tag -a v<version> <released-commit> && git push origin v<version>`"* |
| **B** package pruned | REFUSED | *"Refused: that version's artifact is not downloadable. The version is tagged but its package is not in the registry, so a box would 404 fetching the binary itself. … Publish it — `bash scripts/release-agent.sh <version>`"* |
| **C** no checksum | REFUSED | the pre-existing *"Couldn't set the checksum …"* — see the note below |
| **D** both good | **SAVES**, `artifacts_set`, byte-identical behaviour | — |
| **E** registry unreachable | REFUSED | *"Refused: could not verify — this does not mean anything is missing. … It refuses rather than saving with a warning, because a warning beside a success reads as a success. … There is deliberately no override: the registry is on your own server, so if it is unreachable the vouch can wait."* |
**Scenario C changed shape because my first draft modelled nothing real,** and that is worth recording.
With a Gitea client configured, `resolveArtifactSHA` fetches the sha **authoritatively and ignores what
was submitted** — so "submit an empty sha" cannot produce an empty stored sha. The genuine shape is
Gitea answering with no `sha256`, and the **existing** refusal already owns it. The test now pins the
guarantee (*the manifest is unchanged*) rather than a mechanism I had invented.
**No override was built, and none is wanted.** §8's halt condition did not trigger.
## 6. Part 4 — NOT DONE
The twelve downgraded claims were not re-examined and no receipts were searched for. **The honest-grey
count is therefore still the twelve from last night, unverified in either direction**, and
`where-felhom-stands.*` is untouched. This is the session's shortfall: Parts 13 took the budget, and
splitting Part 4 in half would have produced exactly the kind of half-checked green the whole exercise
exists to prevent.
**Whether the "code moved under the proof" rule can fire at all** is therefore still open from last
night, where it fired **zero** times out of twelve — every downgrade came from missing evidence, not
from decayed evidence. My reading remains that it *can* fire but will stay rare until rows cite
evidence at all, which is R-290.
## 7. Hub deployed
**v0.102.0**, live and verified: deploy image `gitea.dooplex.hu/admin/felhom-hub:0.102.0`, rollout
complete, and the page footer reads `0.102.0`. Manifest commit **`36bcd12`**; code commit `b55fc17`.
The image was verified **served by the registry before** the manifest was bumped, not after. ArgoCD's
`felhom` app has `automated.enabled: false`, so the sync was triggered explicitly — **no
`kubectl set image` at any point.**
## 8. Part 5 — dropped, as marked
Not started. It was explicitly droppable and it is the only part that touches customer-facing wording,
which is where a rushed edit does most harm.
## 9. Register
**Ceiling R-290 → R-292.** Opened **R-291** (the narrowing, with its reason, so it can be widened
deliberately) and **R-292** (`artifact_sha_invalid` conflates three facts — found by scenario E
failing, worked around by ordering, message untouched). Closed: **R-273's owed-guards tail**, both
guards built. Corrected: **R-287**, twice.
## 10. Observations — noticed, not acted on
- **R-292 is the interesting one.** A test I wrote to check a new guard failed for a reason that had
nothing to do with the guard, and that reason was a real pre-existing defect. The five scenarios
earned their keep before the feature shipped.
- **The golden gets no tag probe.** It is fetched by version and has no config tree, so a tag probe
would assert something the installer never does. Deliberate, and stated in the code.
- **The gate is skipped entirely when no Gitea client is configured**, or a hub without registry
credentials could never vouch anything. Pinned by its own test, and worth knowing: the guard is only
as present as the client is.
- `check-release-complete` runs in `--fast`, so a missing tag is now caught by the **pre-push hook**,
earlier than CI.