fix(pine): write HA bookkeeping fields in seeded config entries

HA's config-entries store already carries the current schema minor_version,
so entries we append are never migrated — a missing created_at is an
unguarded KeyError in config_entries.async_initialize that crash-loops HA
at boot (hit on framework-pt during install verify). Write created_at/
modified_at/discovery_keys/subentries on both the anthropic and wyoming
entries.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
archipelago 2026-07-22 04:54:20 -04:00
parent 72f7c38701
commit 2116600e24

View File

@ -24,6 +24,13 @@
use serde_json::{json, Value};
use tracing::{info, warn};
/// Timestamp in the exact format HA writes to `.storage`
/// (`2026-07-22T08:29:35.123456+00:00` — micros, `+00:00` offset), safe for
/// Python's `datetime.fromisoformat`.
fn ha_now() -> String {
chrono::Utc::now().to_rfc3339_opts(chrono::SecondsFormat::Micros, false)
}
const HA_CONFIG_DIR: &str = "/var/lib/archipelago/home-assistant";
const HA_STORAGE_DIR: &str = "/var/lib/archipelago/home-assistant/.storage";
const NODE_SECRETS_DIR: &str = "/var/lib/archipelago/secrets";
@ -444,8 +451,11 @@ async fn seed_claude_conversation(storage: &std::path::Path) -> ClaudeSeed {
let id = |raw: [u8; 16]| hex::encode(raw);
// Shape mirrors what HA 2026.7's anthropic config flow creates (entry
// version 2.4 with conversation + ai_task subentries); HA fills any
// missing bookkeeping fields on load.
// version 2.4 with conversation + ai_task subentries). Bookkeeping
// fields (created_at/modified_at/discovery_keys) must be written here:
// the store already carries HA's current schema minor_version, so HA
// never migrates appended entries — a missing created_at is a
// KeyError that crash-loops HA at boot.
entries.push(json!({
"entry_id": id(rand::random()),
"version": 2,
@ -459,6 +469,9 @@ async fn seed_claude_conversation(storage: &std::path::Path) -> ClaudeSeed {
"source": "user",
"unique_id": null,
"disabled_by": null,
"created_at": ha_now(),
"modified_at": ha_now(),
"discovery_keys": {},
"subentries": [
{
"subentry_id": id(rand::random()),
@ -555,7 +568,11 @@ async fn seed_wyoming_config_entries(storage: &std::path::Path) -> bool {
"pref_disable_polling": false,
"source": "user",
"unique_id": null,
"disabled_by": null
"disabled_by": null,
"created_at": ha_now(),
"modified_at": ha_now(),
"discovery_keys": {},
"subentries": []
}));
info!("pine/HA seed: added wyoming config entry {title} ({host}:{port})");
added = true;