Commit Graph

1216 Commits

Author SHA1 Message Date
admin 0b1b8d3445 v0.301.0: R-518, R-638, R-717 (MinAgent 0.131.0)
gates / gates (push) Successful in 54s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 15:49:58 +02:00
admin 66aee8939b Rules: the shared rule file's copies line names five copies (the agent repo has one now, 09 §3 decision 152)
gates / gates (push) Successful in 55s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 15:23:16 +02:00
admin ce2e31f4b2 R-717: name each test's red-proof file
The six red-proofs are saved under felhom.eu
documentation/audits/design-build-2026-10-06/E/red-*.txt; every test comment
now names its file and the reverted line.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 15:15:33 +02:00
admin 5b8656974b R-717: after_setup open_command — the family window reopens an app's DB-held sign-up switch
The command form ran only when the lock was SET, so a database switch closed by
`command` stayed closed through the household's 15-minute window. New twin
fields `open_command` + `open_success` (same service/user/args_env and the same
argv-safe expansion and success-marker rules as `command`/`success`).

- liftNativeLock (the window, via OpenSignupWindow → goNativeLock(false)): marks
  the gate record native_lock "opening" BEFORE anything opens, lifts the env,
  runs open_command; only full success records "lifted". A failed open closes
  the switch again at once and records after_setup {ok: false, step: open}; the
  app page shows its own line (app_info.signup_native_open_failed).
- The close: reconcileSignupBlocks (every 20 s and at controller start) runs
  `command` for any non-"applied" state once no window runs. A failed close
  after a window is logged ERROR ("may still be OPEN past the household's
  window") and retried every nativeLockOpenRetry (2 min) instead of 30.
- After a successful app update, verifyAndConclude → markNativeLockForReapply
  sets native_lock "" so the loop closes the switch again.
- A template with `command` but no `open_command` keeps today's window (env
  only) and logs once per app that its own switch cannot be reopened.

Tests: internal/stacks/after_setup_r717_test.go (7), web render + parity case.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 15:15:33 +02:00
admin 9c945688c0 R-638 option A: a replay meets the copy's own schema on the two side paths (09 §3 decision 154)
Slice 1 — the no-manifest fallback RestoreApp no longer starts the WHOLE stack
at the current definition before the replay (a newer app could migrate the
restored data underneath it). New order: resolve DB services from the live
compose -> stop -> volumes -> DB-only start (StartStackServices, the same
helper the unit restore uses, R-47) -> replay -> full start -> health wait.
A dump with no identifiable DB service is refused before any mutation (same
gate and message as the unit and off-site paths). A failed volume leg skips
the replay. restoreDockerVolumes now goes through the existing
volumeReplayFrom seam (nil in production) so the order is testable without
Docker.

Slice 2 — a unit restore whose volume leg failed no longer calls the
importer. Everything else on that failure path is unchanged: dataErr is
returned as "completed with data errors", the unit's definition is written
and the app is fully started.

No loader change, no new delete step. Red-proofs in felhom.eu
documentation/audits/design-build-2026-10-06/B/ (red-slice1-fallback-order.txt,
red-slice2-no-replay-after-volume-failure.txt).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 15:15:33 +02:00
admin 9d2d62831a R-518: a press with the local storage absent backs up nothing (never the off-site tier as a stand-in); an agent that flags no primary keeps the first tier
09 §3 decision 156 says the button makes the local copy only.
Test: TestManualRunTiers_NoPrimaryAvailable_BacksUpNothing (red-proved on the previous version).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 15:15:33 +02:00
admin d720495cd5 R-518: backup button copy says local copy, one short stop, off-site at night (hu+en)
The 'Mentes most' hint and its confirm stated the v0.296.0 measurements
(about 6 min / 9 apps, about 8 min / 12 apps) and that the off-site copy in
the same run makes it longer. Since decision 156 the press makes the local
copy only and resumes the apps at its snapshot, so the copy now says: a
short stop of about 1-1.5 minutes (longer with more apps), the apps run
again while the copy finishes, the off-site copy follows with the next
nightly backup. Parity fixtures updated in place;
TestR518_BackupButtonStatesTheMeasuredDowntime ->
TestR518_BackupButtonStatesTheShortLocalOnlyStop (new copy on page AND in
confirm, old minutes gone, ASCII fragments).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 15:15:33 +02:00
admin d8c2634472 R-518 option A: one stop per backup tier (09 §3 decision 156)
Each quiesce window now backs up ONLY the first due tier that starts and
resumes the apps at its snapshotted; the upload finishes with the apps
running. Any other due tier stays due and a later cycle (the next poll)
takes it in its own short window - never straight after the first.
This reverses R-82's 'ONE quiesce window for both due tiers'.

A manual press (TriggerNow) backs up the primary (local) tier only, picked
by the agent's Primary flag; the off-site tier follows at the next
scheduled night run. If no available tier is flagged primary, the first
available tier is backed up rather than nothing.

Unchanged: marker written before any stop, one unquiesce per window, the
max-quiesce bound, BUSY/start-error handling (the next tier is still tried
in the same window when a tier does not start), breaker and contention.

Tests: TestBothTiersDue_ExactlyOneQuiesceWindow ->
TestBothTiersDue_FirstCycleRunsOnlyFirstTier; TestNonLastTierSnapshot_
DoesNotResumeApp -> TestFirstTierSnapshot_ResumesAppWhileUploadContinues
(red on old code); new TestManualPress_RunsOnlyLocalTier (red on old
code), TestLeftoverTier_RunsInNextCycleInItsOwnWindow,
TestManualRunTiers_NoPrimaryAvailable_BacksUpFirstAvailable;
TestNotify_BothFailingTiersAreReported now runs two cycles.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 15:15:33 +02:00
admin 31242786af Instruction files kept true (09 §3 decision 150): stale gate lists, paths and facts corrected; no code change
gates / gates (push) Successful in 52s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 13:44:01 +02:00
admin 36088fd82e REPORT: the operator's ten answers (2026-10-06)
gates / gates (push) Successful in 54s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 12:28:46 +02:00
admin 871d05b84d v0.300.0: R-645, R-856 (MinAgent 0.131.0)
gates / gates (push) Successful in 48s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 11:57:06 +02:00
admin c393d8529a R-856: after a crash boot of the host, app mails wait ~15 minutes; a normal boot keeps 90 s (09 decision 143)
The dead-app check (source of app_start_failed and app_stopped_unhealthy) now gates on a crash-aware
boot grace (internal/crashboot): 15 min when the host crash guard's last boot was UNCLEAN and within
30 min of the controller start, otherwise 90 s. The fact is read from the agent's local API
(GET /host/crash-guard, agentapi.Client.CrashGuard). UNKNOWN - no agent, an older agent's 404, no
crash-guard state - is a normal boot. The decision is logged once ("boot grace ...: ... (R-856)").

NEEDS AN AGENT CHANGE to take effect: GET /host/crash-guard serving the guard's state.json fields
(present, last_boot_at, last_boot_unclean, tripped). Until then every box keeps 90 s.

Tests: TestR856_CrashBootHoldsTheMailsForTheLongGrace, TestR856_NormalBootKeeps90s,
TestR856_FactReadLateInTheNormalGraceStillCounts, TestR856_AgentProbeReadsTheCrashGuardState,
TestR856_CrashGuardDecodesAndAnOlderAgentIs404, TestR856_DeadAppCheckWaitsOnTheCrashAwareGrace,
TestR856_NormalGraceIsTheDeadAppBootGrace.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 11:39:25 +02:00
admin 2d63714eca R-645: the night backup skips an app whose pinned version is not the one it runs (09 decision 142)
Every night leg (DB dump, volume dump, recovery-unit capture, Tier-2 mirror) now leaves alone an app
whose app.yaml pin (pinned_images) differs from its running record (installed_images) - the state a
failed update leaves behind. A hold lifted by hand (--clear-restore-hold + restart) no longer lets the
capture write the just-failed definition over the good unit. Unknown (no pin, no record, a service not
observed) never skips. The log says it per leg; the backups page shows one amber line, hu + en
(backup.status.version_skip). Seam: backup.Manager.SetVersionCheck <- stacks.Manager.PinNotRunning.

Tests: TestR645_HandLiftedHoldKeepsTheGoodUnit (whole night run + Tier 2, unit tree fingerprint),
TestR645_VersionSkipSentence, TestR645_PinNotRunning_*, TestR645_BackupRowSaysTheNightBackupSkipsIt,
TestR645_VersionCheckIsWiredAtStartup.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 11:39:25 +02:00
admin 13bda270c3 REPORT: the morning after (2026-10-06)
gates / gates (push) Successful in 50s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 08:50:42 +02:00
admin ff4a99a0ab v0.299.0: R-889 (df's disk percent), R-585, R-621, R-516 (MinAgent 0.131.0)
gates / gates (push) Successful in 54s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 08:03:46 +02:00
admin bee2c2d815 R-889: every disk percent is df's (used / (used + available)); the tile says Rendszer, not Rendszer (/) (09 decision 138)
The box divided used by the whole filesystem, so the 5 % reserved for root made a full disk read ~5 points low
(61.8 of 68.7 GB = 90 % where df said 95 %) and the fill alarms fire late. One function, DFUsedPercent, now serves
GetDiskUsage, readDiskUsage, the recovery-unit headroom projection and the deploy page's free percent. Tests use
numbers measured on demo-hp 9201 (/mnt/sys_drive: old 21.5 %, df 23 %); a source scan refuses a percent divided by
the whole filesystem (red-proved by putting the old line back). The label measured the docker data volume, not /.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 08:03:21 +02:00
admin c67b26be28 CHANGELOG: unreleased — R-516 the bundle's last formal forms
gates / gates (push) Successful in 54s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 02:44:42 +02:00
admin 4c3c2037fd R-516: the formal forms the gate did not count are in the te-form; the gate's stems widened
49 Hungarian values on the debug (RESET prompt), storage, network-storage, security, system,
deploy, restore and remote-backup copy moved from the formal („ön") to the product's te-form
(„írd be", „add meg", „hozz létre", „biztosan eltávolítod", „engedélyezd", „próbáld", ...).
i18n_missing_gate.py's stem list widened by 33 stems (+ one listed third-person exception,
„sora adja meg"); it counted 61 on the previous bundle and counts 0 now, ceiling stays 0.
Decoys: a widened-stem form convicts, its te-form twin and the third-person phrase pass.
38 parity fixtures changed by exactly those bytes. Seven Go-side keys listed as REWORDED in the
go-parity map. Pinned by TestR516_WidenedFormalFormsAreGone; two tests that quoted the old
words follow them.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 02:37:34 +02:00
admin 2fc314d491 REPORT: the burn-down night (2026-10-06)
gates / gates (push) Successful in 49s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 02:13:03 +02:00
admin 0a960ba58d CHANGELOG: unreleased — burn-down night ctrl-d lane (R-585, R-621, R-516, R-426 controller decoys)
gates / gates (push) Successful in 53s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 02:08:50 +02:00
admin 7044b11804 R-426: decoys for docker-v and the shared reuse-refs, instructions and observations gates
docker-v: an unallowlisted `-v /etc:/x` in a NEW .go file two directories down
under internal/ and under cmd/ convicts; controls: the clean tree and the same
line in a _test.go pass. The three shared felhom.eu scripts run against a
scratch clone of THIS repo in a scratch workspace (siblings symlinked), the
felhom-agent b78a0ff pattern: a missing cited .go/.md path, a version literal
in CLAUDE.md effective text and R-419's prose-only Observations note convict;
the real files, the version inside an HTML comment and both genuine markers
pass. DECOY_SHARED_DIR judges a mutated copy for the red-proof. All four in
COVERS, so their EXEMPT entries in decoy_coverage_gate.py can go.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 02:01:13 +02:00
admin 2e5ef7e410 R-516 item 12: the last eleven formal forms in the dashboard copy use the te-form
launcher, layout remove-dialog, deploy, debug, import, remote-backup, shared
backups, system settings and the password-changed flash. Formal-form ceiling
13 -> 0 (the ratchet now refuses any new one the gate's stems see). 119 parity
fixtures changed by exactly those bytes. flash.login.password_changed listed
as REWORDED in the go-parity map; pinned by TestR516_FormalFormsAreGone.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 02:01:12 +02:00
admin e4774e6a06 R-516 items 7-10: one banner per drive, local times, te-form, health banners in the household's language
- item 7: the storage page shows the disconnect time in local time (fmtTimeStr), not the raw RFC3339 UTC.
- item 8: a disconnected drive no longer has two banners - the health check's warning for it is dropped
  when the dedicated alert.storage.disconnected banner was built (it stays on the wire).
- item 9: alert.deadapp.group says "nezd meg" (te-form); formal ceiling 14 -> 13.
- item 10: the disk/memory/CPU/temperature health banners show the dashboard's own sentence
  (health.* keys, hu + en) via HealthReport.WarningMsgs/IssueMsgs; the wire text is unchanged.
  checkResources split out of RunHealthCheck as the test seam.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 02:01:12 +02:00
admin 0f2eab7a3e R-621: the hold panel points at the log the hold kept
A held app's page now says, inside the hold panel, that the app's own log from
before it was stopped was kept, with a Napló link to the logs page that serves
it (0b93e1a). Shown only for an update hold with a non-empty kept log
(Manager.HoldLogKept). New copy through the bundle (hu + en), parity case
app_info_hold_log captured when born.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 02:01:12 +02:00
admin ff1758a21c R-585: the last customer-facing producers follow the household's language
backup_integrity_ok / backup_integrity_failed now take facts and push bundle
keys (Hungarian bytes unchanged - go-parity, pinned verbatim by
TestR585_IntegrityHungarianIsUnchanged). The interrupted-operation alert
(backup_failed, customer-enabled by default) used to send the operator's
ENGLISH sentence to every household; NotifyInterruptedOperation composes it
per language, the English byte-identical to the operator's log line. The
now-callerless NotifyBackupFailed is removed. local_api_endpoint_drift is
operator-only (no customer toggle) and already English by design - not
changed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 02:01:12 +02:00
admin 84d6ef706d v0.298.0: the burn-down night (MinAgent 0.131.0)
gates / gates (push) Successful in 50s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 00:30:36 +02:00
admin ef199c5705 CHANGELOG: unreleased — burn-down night ctrl-a lane (R-126, R-270, R-616, R-498, R-682, R-757, R-522, R-575, R-585 part, R-516 part, R-718)
gates / gates (push) Successful in 50s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 23:20:21 +02:00
admin c4f4019721 R-718: the close-sign-up and setup-gate cards say the app restarts once
Where the app has its own switch (after_setup.env), both presses restart
it; the cards now say so (app_info.restarts_once, hu+en). Two parity
cases born with the line.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 23:13:00 +02:00
admin d7efa7b54e R-516 items 1+4: the menu says Hibakeresés; the storage pages use the te-form
Item 1: the always-visible 'Debug' menu item reads 'Hibakeresés' in
Hungarian (key layout.hibakereses; English stays 'Debug'). Item 4: four
formal forms on the storage pages (Adjon hozzá, Csatlakoztasson,
Válassza ki x2, Önnek) are now te-form. The parity fixtures change by
exactly these bytes (a deliberate copy change, not a regeneration);
HU_FORMAL_CEILING 17 -> 14. Item 2 was already fixed (slice 1).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 23:13:00 +02:00
admin ca89e70d53 R-585 (part): three producers follow the household's language
db_dump_failed, the off-box backup_failed and offbox_enlarge_blocked
(whose sentence IS the household's mail - no hub customerMessages entry)
now take facts and push a bundle key, so an English household reads
English. Hungarian bytes unchanged (go-parity). Added to
convertedProducers.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 23:12:59 +02:00
admin b05be0ac11 R-575: the overcommit warning follows the reader's language
memoryVerdict returns the warning's bundle KEY (KeyMemoryOvercommitWarning)
and DeployStack hands it on; the API renders it per request
(deployWarningData). msgHU, whose only use this was, is gone.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 23:12:59 +02:00
admin b36a85ac04 R-522: a disconnected tunnel is told on the dashboard row
Since v0.292.0 (R-841) cloudflared's health check asks /ready, so a lost
connection reads unhealthy; the cloudflared row now also carries the tag
"Kivulrol nem erheto el" with a plain title, in hu+en. New parity case
dashboard_tunnel_offline (born as a key).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 23:12:59 +02:00
admin 1991c742a3 R-757: a secret only after_install reads is not invented for an installed app
InjectMissingFields skips a new generated secret that is in after_install's
env list and named by no compose definition: after_install does not run
again, so the app never received the value and the reveal would answer
a login the app does not have (calibre-web ADMIN_USER, 2026-10-01).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 23:12:59 +02:00
admin 4347983a72 R-682: a Remove cut off by a controller restart is finished at boot
RemoveStack journals itself before compose down and clears on every
return; at start a found journal finishes the remove through the same
RemoveStack (once, before the boot reconciler), keeping drive data and
backups even if the household had asked to delete them (no unattended
deletion at boot; logged).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 23:12:59 +02:00
admin 05a447ef02 R-498: the app page's first steps name the household's address, not wiki.DOMAIN
AppInfo.WithAddress fills the catalog placeholder (<label>.DOMAIN -> the
effective subdomain + customer domain, bare DOMAIN -> the domain) on a
copy; appDetailHandler applies it. Pinned per catalog template (both
languages) and on the rendered page.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 23:12:59 +02:00
admin 28a5203d01 R-616 (on top of R-615): the catalog clone stores no credentials
Replaces 365eff6 for main, which now carries R-615 (0b349e2). The plain
URL is cloned; the Basic credentials ride per git command as
http.<origin>.extraHeader via GIT_CONFIG_COUNT. R-615's origin compare
now compares credential-free forms against the configured URL, so a set
token never re-clones; a stored origin with user:token@ is rewritten
without it. Pinned by TestR616_* incl. TestR616_TokenSetSameRepoNoRecloneOriginClean.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 23:12:59 +02:00
admin 6fac245d24 R-270: the local_api drift detector also names a TOKEN-only divergence
A rotation that reached bootstrap.json but not controller.yaml left the
agent channel at 401 across restarts while the endpoint-only detector
stayed silent. The tokens are now compared (constant time, boolean only);
the token case gets its own banner key and operator message. Still
detection only - nothing is reconciled (R-78).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 23:12:59 +02:00
admin 33c397380e R-126: refuse a .fab export without a password to a network drive (09 decision 128)
An export to a registered network drive (Kind=network) with no bundle
password now answers 400 with a household sentence (hu+en); with a
password it runs; a local drive is unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 23:12:59 +02:00
admin 034a2b7363 CHANGELOG: unreleased — burn-down night ctrl-c lane (R-578, R-569, R-492, R-576, R-574, R-488, R-325)
gates / gates (push) Successful in 43s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 22:30:45 +02:00
admin daeed27223 R-325 (controller half): retrieval_promise_gate imports the shared stem list
STEMS now comes from felhom.eu/scripts/customer_copy_vocab.py (RETRIEVAL_STEMS), read the
way controller_gates.py reads the other shared checkers (CI clones felhom.eu beside this repo);
an absent or empty vocabulary is INCONCLUSIVE (exit 2), never a pass. Decoys: vocabulary
absent -> rc 2; an invented stem in a doctored shared list convicts a template using it.
hub_copy_gate.check_drift on this file now reads 'ok — single source'.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 22:24:23 +02:00
admin 8ce496f124 R-488: backup tests read ONE health-wait clock; package 444 s -> ~2 s
waitForHealthy's 3 s settle / 5 s poll / 90 s timeout become package vars (production values
unchanged, pinned by TestR488_HealthWaitDefaultsAreProduction); TestMain shortens them once.
Measured before: 51 of 599 tests held 442 of 444 s, two not-running fixtures 279 s alone.
newOffboxManager now installs a failing SSH fake: TestOffbox_ConfirmedReset was spawning a
real 'ssh felhom@nas.local' and waiting out its 10 s ConnectTimeout.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 22:24:23 +02:00
admin 391967bcf1 R-574: handler_debug.go literals classified; the 38 page-copy ones move to the bundle
39 Hungarian literals: 38 are debug-page copy (every writeDebugJSON message/error, rendered
into the result line by debug.html, plus the pre-0.83 agent notice rendered in the log
viewer) -> 30 debug.api.* keys (hu byte-equal, parity gate green; en added). One is PAYLOAD:
the 'Teszt esemény' text sent to the hub as the test event's message stays a literal. The
diagnostic dump carries no Hungarian. TestR574_DebugPageCopyFollowsTheLanguage pins hu bytes
and en rendering.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 22:24:23 +02:00
admin 074ddda352 R-576: go-parity gate also judges the CALL — arity vs printf verbs, and no key glued with +
Checks 4 (ARITY) and 5 (NO-CONCAT) in i18n_go_parity.py: at every message-helper call
(MsgError/MsgErrorf/Text/Msgf/msg/msgLang/msgHU/note) whose key is a literal hu.json knows,
the argument count must equal the Hungarian value's printf verbs; a known key literal may
never be an operand of +. 485 calls judged, 0 defects today. Decoys: a dropped argument and
a key+suffix concatenation on a real producer convict; a nested-paren argument is accepted.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 22:24:23 +02:00
admin 7b8216abac R-492: delete the always-empty cfg.Paths.HDDPath (field, env binding, every fallback)
Readers (report builder, health check, /api/system, web primaryHDDPath, metrics collector,
AutoDiscoverStoragePaths' fallback parameter) now use the storage registry only. An old
controller.yaml still carrying paths.hdd_path keeps loading (non-strict YAML), pinned by
TestR492_OldConfigWithHDDPathStillLoads.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 22:24:22 +02:00
admin d15ad105be R-569: stack-lifecycle handlers pick their status by error KIND, not English words
stop/start/restart/update, remove and delete matched "protected", "not found", "not deployed",
"still running", "not orphaned" in err.Error(). New sentinels in internal/stacks
(stack_errors.go) carried by the producers in manager.go/delete.go via util.KindErrorf (message
bytes unchanged); api.stackOpStatusFor maps them. Tests: reworded-message table per family,
wiring check over all three handlers, producers keep kind + words.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 22:24:22 +02:00
admin 9271f33359 R-578: settings-callback deadlock gate over every controller package
TestR578NothingTakesTheSettingsLockInsideASettingsCallback (internal/settings) derives from
source the *Settings methods that take s.mu, the callback runners among them, and per package
every helper that transitively reaches one; a call to any of those inside a func literal
passed to a runner (or a non-literal callback) fails with file:line. Decoy:
TestR578GateConvictsAHelperChain. REUSE.md lookalike row added.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 22:24:22 +02:00
admin f7c39c1700 CHANGELOG: unreleased — burn-down night ctrl-b lane (R-729/R-545, R-621, R-839, R-271, R-521, R-607/R-615, R-25)
gates / gates (push) Successful in 51s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 22:03:52 +02:00
admin 1355391c78 R-25 (controller half): drive init mounts the filesystem UUID the agent verified
agentapi FormatResult / FormatStatusResult gain fs_uuid (agent R-25 half). runStorageInit mounts
it — from the synchronous answer or the polled status — instead of re-resolving the UUID from the
/dev path, so a node that moved between format and mount cannot redirect the mount. An agent that
sends no field keeps the old resolve, logged as a WARN each time (the window is open then).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 21:55:37 +02:00
admin 0b349e2415 R-607 + R-615: the catalog sync follows a changed repo_url and rescans when the catalog moved
R-615: a changed git.repo_url was inert (the clone's stored origin was fetched for ever). The sync
now compares the configured URL with the clone's origin: another repository -> drop the cache and
clone it; the same repository with new credentials -> set-url.
R-607: a catalog move that changed no stack directory (a deployed, pinned app keeps its stored
definition) skipped the rescan, so CatalogImages and the update badge stayed stale, and the sync
said 'nincs változás'. The sync now notes the cache commit before and after, rescans when it moved,
says so, and returns catalog_moved.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 21:55:37 +02:00
admin 800b32ceec R-521: an app a lost drive stopped no longer mails app_start_failed one by one
One unplugged drive sent storage_disconnected plus an app_start_failed per app on it (five operator
mails). The dead-app job now hands the notifier the apps of a disconnected drive (its recorded
StoppedStacks plus apps whose HDD_PATH is that drive) as not down; the storage event already names
them. The dashboard's dead list is unchanged. The hub-side cooldown (F6/F7) and a household mail
for a lost drive are not in this change.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 21:55:37 +02:00