All notable changes to the Structs Compendium documentation will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Runnability pass. Verified the Structs Desktop MCP surface against a live server’s tools/list (authoritative runtime schema) rather than source diffs, and audited every documented structsd invocation against the real v0.20.0 binary. Fourteen documented commands could not have run as written.
-- placed before flags — 11 invocations in permissions.md — pflag stops parsing flags at --, so … -- $GUILD_ID 8704 --from admin --gas auto -y handed five positional arguments to the command and failed with accepts 2 arg(s), received 6. Verified empirically both ways against v0.20.0. This is what AGENTS.md rule 8 exists to prevent.fleet-move had a stray 2 in the recall example (structs-planets-fleet); reactor-defuse was given 1 argument instead of [player address] [reactor address] [amount] and address-register was missing its leading [player id], both in agent-security.md — the incident-response runbook, where a command that will not run is most costly; permission-guild-rank-set was missing [rank] and permission-guild-rank-revoke was missing [permission] in permission-issues.md and permission-checking.md; and local-devnet.md called query structs guild with no id (now guild-all).structs_players infuse takes {keep_grams, enabled, now} with no interval_secs; own-guild ally seeding happens at the top of auto_raid’s scan rather than at app start (so the veto list reads empty until that loop first runs — confirmed live); and structs_query / structs_ui still answer as deprecation stubs but are no longer advertised in tools/list.weight on a combat list is a 0–10 multiplier defaulting to 1, and note is shown on the dashboard’s WAR page. Both are declared in the live tool schema.check-invocations.py, wired into CI, hard-gates three parse-time failures that the existing command-name lint cannot see: positional arity, -- order, and the --gas auto rule. It reads a new generated/structsd-signatures.txt (emitted by an extended snapshot-commands.sh) so CI needs no structsd binary.structs-desktop.md. The webapp signing queue holds a charge-gated message in a charge lane and broadcasts when the bar is sufficient, so MCP no longer blocks on charge and an agent should submit and move on rather than hand-timing between actions. Previously undocumented.resources/list with every documented structs:// URI 404ing. TOOLS.md and structs-desktop.md now say to probe resources/list once and fall back to structs.ai or a local checkout.A correctness and capability pass driven by upstream drift in .references/, plus the first documentation of autonomous combat in Structs Desktop. Verified against structsd v0.20.0 source, structs-desktop@ae53e31, and live queries against the local Guild Stack PostgreSQL.
auto_response (defensive counter-fire on the raid alarm) and auto_raid (offensive target selection). Documented in structs-desktop.md with full argument lists, the two-stage safety model (off by default; autonomy: advise even once enabled; dry_run independent of autonomy), the new raider role, the warfighter preset, and a new Combat lists section covering structs_doctrine {command:"lists"} — the grudge / priority_guild / ally / protected lists, the heat formula, and the 30-day auto-grudge TTL versus never-expiring manual grudges. Mirrored into TOOLS.md.SAFETY.md. The tier model priced individual transactions; enabling a loop is a standing grant to sign an open-ended series, so the tier applies at arming time to everything the loop will ever do. Combat loops are Tier 2, never under full autonomy — arming one commits the commander to unprompted aggression at machine cadence. Covers consent drift (grudges accrue while merely advising) and the fact that diplomacy exists nowhere in the scoring model except the veto lists.combat.md gains “What the outcome data says” and defense.md gains “The four-minute clock”, from ~300 raid episodes over 92k planet_activity events. Raids reaching shieldsVulnerable went 69–7; raids that never did went 0–50. Shield strength does not predict outcome (it is a timer, not armor). Loot is fat-tailed: median haul 1, nine raids carrying 74% of all ore ever stolen. Defensively, the response budget is ~4 minutes, and return fire within ~1.8 min separates all 16 attackerDefeated episodes from the 123 losses (median return fire 12.3 min, when it happened at all). Killing the raider’s Command Ship is the one deterministic lever: 16/16 vs 0/279. The four-minute budget is now stated up top in under-attack.md.defense.md, a condensed survival card that replaces the 39 KB combat.md in the small-context llms-core.txt bundle.briefing.md on reporting game state to a human who does not speak Structs: jargon translation, report shapes, and what not to send.integration-notes.md documents the general rule (single-entity queries include gridAttributes; *All list queries do not) and its corollary: uint64 + omitempty means a zero attribute is absent entirely, so treat a missing key as 0.building.md documents the two extra gates on fleet builds and the Command Ship exemption that makes recovery possible when the fleet is otherwise frozen.agent-security.md covers the opt-in /board HTTP surface: the bearer token in the URL is full operator authority, including mass actions that sign.player-update-pfp-client-render-attributes is really player-update-pfp-cr-attributes (corrected in structs-onboarding, action-index.md, action-quick-reference.md, actions.md). guild-membership-all-by-guild does not exist — guild membership lives on player.guild_id / player.guild_rank; structs-intel now uses guild-membership-application-all plus a Guild Stack query. player-charge does not exist either: charge is derived, current_block_height − player.gridAttributes.lastAction. scripts/BASELINE.md now carries a phantom→reality table instead of language legitimizing the lint warnings.database-schema.md corrected against the live DB: seized_ore is not on structs.planet, planet_raid’s limitations clarified, planet.status is active/complete, and fleet.status is onStation (camelCase). The last one fails dangerously: = 'on_station' matches zero rows, so a raid-safety check written that way fails open and every target looks raidable.team-operations.md described multi-player orchestration through board mass actions that are not on the MCP surface. Rewritten around the real agent path, structs_players, including virtual players derived from one mnemonic at successive HD indices with the guild fronting join fees, and the bait / productive / raider role split.struct-types.md Class → Abbrev — the Class column duplicated information already in the row; it now carries the chain’s classAbbreviation, which is what UIs actually display.llms-core.txt budget 100 KB → 120 KB (once) — with defense.md swapped in for combat.md, the bundle is 121,746 B. Rationale recorded in check-bundles.sh.memory/SKILLS-AUDIT.md — a stale maintainer artifact that was tracked in git and actively misinformed agents reading it as current.Phase 1 of the human-Codex cross-reference: an additive, non-destructive pass that links this agent corpus to the human-facing Codex and bridges its vocabulary to the canonical mechanics pages. Source: full ingest of all 40 live Codex routes (12 how-to-play + 28 lore entries) on 2026-07-23, staged with an evidence matrix under a gitignored scratch dir. Authority rule applied: the Codex is canonical for lore/naming/story; this repo is canonical for mechanics/numbers/API. Only resolved, non-conflicting mappings are shipped here — open lore differences (e.g. the Codex’s Alpha Star Council / Structs Conglomerate vs this repo’s “no central authority” framing) and any not-yet-source-verified numeric claims (e.g. UI “Battery Level” bars vs raw charge) are held for human review, not applied.
reference/codex-crosswalk.md: a resolved-only terminology bridge (Battlegrounds→ambit, Battery→charge, Ballistic/Smart→unguided/guided, Alpha Ore→ore, CMD Ship→Command Ship, Alpha Drift→Command-Ship ambit move, Breach→raid PoW, Planetary Defenses Secure/Vulnerable→shieldsVulnerable), a struct-designation table (ST-21 “Spearpoint”, LS-0 “Laser Sword”, GR-3 “Greybox”, CH-51 “Chimera”), a UI-only terms table (Action Bar, Power Switch, Battery Level bars — firewalled from mechanics), and additive lore cross-links. Registered in reference/index.md and SITEMAP.md, and added to FULL_FILES in generate-llms-full.sh.glossary.md gains ten high-value, unambiguous Codex synonyms (Alpha Base, Alpha Drift, Alpha Ore, Ballistic weapon, Battery, Battlegrounds, Breach, CMD Ship / Spearpoint, Planetary Defenses, Smart weapon), each routing to the canonical mechanics page. The Battery entry carries an explicit caveat that on-screen “Battery Level” bars are a UI scale, not the raw charge value.llms.txt, the top-level index.md, the lore index, and all five lore-page footers to the human Codex and the crosswalk, noting the Codex is canonical for lore/naming.Fixes for scout.sh from a second field report by beezhan (@iBeezhan, player 1-471, guild SN Corp 0-5): the scout read command ship present=no · shields vulnerable yes on targets whose chain state was a live, on-station Command Ship (raid correctly rejected). Root-caused and fixed against structsd v0.20.0 source and live-verified on structstestnet-111. Thanks to beezhan for the field data (fleet 9-61 → commandStruct 5-2187; player 1-61 ore 168).
scout.sh enumerated the fleet’s space/air/land/water ambit slot arrays looking for a type-1 struct, but the Command Ship lives in the fleet’s dedicated commandStruct field (x/structs/types/fleet.pb.go), so it always read “no Command Ship” → falsely “vulnerable”. Now reads fleet.commandStruct, queries that struct, and decodes its status bitmask (online = bit 4, destroyed = bit 32) to mirror the chain’s IsDefenderCommandStructVulnerable(). Live-verified: struct 5-2187 status 7 (built+online), 4 HP.storedOre is a player grid attribute exposed as gridAttributes.ore on the player query (x/structs/keeper/query_player.go, GridAttributes.ore), not player.ore or planet.ore. scout.sh now reads gridAttributes.ore (live-verified 168 for player 1-61).FleetStatus.onStation is 0 and omitted from JSON (only away renders), so an on-station fleet showed away=unknown; the scout now infers on-station from an existing fleet with no away signal.struct-all-by-planet CLI command — it is a Guild Stack / webapp query, not a structsd CLI subcommand (per scripts/BASELINE.md), so scout.sh’s defender query silently failed. Removed the call (defender enumeration is now pointed at the Guild Stack), and corrected the CLI-form references in the structs-intel and structs-combat skills and Transcript 02 to use struct [commandStruct-id] (for the Command Ship’s ambit) plus a Guild Stack SQL query (for planet structs).combat.md that blockStartRaid == 0 (and the single compute error string) collapses two independent conditions — a raider is present (RefreshRaidVulnerability returns early unless GetLocationListStart() != "") and the defender is vulnerable — plus the planet-raid-complete-only gates the compute message omits: raiding fleet first in queue (LocationListForward == "", now added to the Requirements table) and player online.Raid shield-vulnerability doctrine, from a field report by beezhan (@iBeezhan, player 1-471, guild SN Corp 0-5) where an agent correctly read that a target’s shields were up (defending Command Ship online) but treated it as a dead end — hunting for an already-vulnerable target instead of creating the vulnerable window by destroying the Command Ship, and conflating a 5-day-idle owner with a raidable one. Thanks to beezhan for the detailed report and the exact rejection message that let us reconcile the two error paths. Every claim source-verified against structsd v0.20.0 (x/structs/keeper/{planet_cache,struct_cache,msg_server_planet_raid_complete}.go, x/structs/client/cli/tx_planet_raid_compute.go). Docs describe current reality; only this changelog records history.
combat.md; a “Two ways to raid” section and a full siege procedure (move in → strip same-ambit blockers → destroy the Command Ship → compute) alongside the opportunistic one in the structs-combat skill; a create-vulnerability branch in the Raid Flow of decision-tree-combat.md; and a siege raid term in glossary.md. Siege executability confirmed via isReachable (an away, first-in-queue fleet can attack the on-station defender’s Command Ship) and the CommandStructRaidStatusHook → RefreshRaidVulnerability clock start.combat.md, an idle vs vulnerable glossary term, and the strictly-negative fleet-move trap (moving onto a not-yet-vulnerable target drops your own shields for a raid that can’t complete). Reinforced in the structs-intel skill and opportunity-identification.md.scout.sh siege verdict — scout.sh now returns SIEGE CANDIDATE (not a flat NO-GO) when shields are up but ore is present, surfaces the owner’s lastAction/idle age, and prints an “idle != vulnerable” caution.planet-raid-compute pre-check emits "...shields are not vulnerable: no active raid window (defending Command Ship may still be online)" when blockStartRaid == 0 (the message a raider usually hits first), distinct from the chain-side planet-raid-complete codes shields_active / raid_clock_unset. Added as a side-by-side table in combat.md and corrected in the structs-combat skill’s error list and decision-tree-combat.md.structs-intel skill’s “Stop here” was corrected, and the shieldsVulnerable glossary entry cross-links siege/idle. Transcript 02 — Raid Go/No-Go gains a dormant-target siege-evaluation variant so the reasoning is modeled, not omitted.Field-report documentation fixes across harvest lifecycle, on-chain portraits, onboarding/ante, economy, indexer, and combat visibility. Every item source-verified against structsd v0.20.0 (x/structs/...), the webapp, and structs-pg. Docs describe current reality; only this changelog records history.
hashing.md: anchors set on activation (activation is the cycle start; no separate “begin mining” message), cleared on deactivate/offline, never expire (aged = cheaper, not wedged), completion auto-restarts the cycle, and ore is checked only at completion (a refinery can run with 0 ore and count ore that arrives mid-cycle). Reflected in the structs-production skill (parallel-pipeline tip + “don’t clean up aged anchors” warning), the activate/deactivate/complete effects in schemas/actions.md, and the clock entry in glossary.md.ugc-moderation.md: JSON string (JSON.parse) of {head, neck, body, arms, background}, paint order background→arms→body→neck→head, index ranges (head 1–87, neck 1–10, body 1–57, arms 1–34, background 1–6) as a client convention renderers must clamp, and asset path /img/pfp/{part}/pfp_{part}_{index}.png. Cross-linked from entities.md, validation.md, and the stale entities/player.md (added username/pfp/pfpClientRenderAttributes). Catalog gaps closed: MsgPlayerUpdatePfpClientRenderAttributes in requests.md and a new Player Identity section (3 actions) in action-index.md.auth.md and the structs-onboarding skill now state that fresh signup needs no activation code and no funds (guild fronts the fee), while activation codes only add an address/device to an existing player.m/44'/118'/0'/0/N (one signup per index → fully independent players, poll GET /structs/address/{address} for playerId, no chain-imposed link/cap) added to team-operations.md, cross-linked from the onboarding and structs-permissions skills.combat.md distinguishing unit signalJamming from the planetary low-orbit ballistic interceptor network.transactions.md StructsDecorator note now states every /structs.structs.* message requires the signing address to resolve to a player, else rejected with "address is not registered as a player" (ante code 2010); bank sends are exempt. Added to the onboarding skill’s error list.structs-commerce skill, energy-market.md, valuation.md, and the speculator soul.rate_denom trap — documented the full rate × capacity × duration debit at open and the guild-denom affordability rejection (keyed agreement_open) in the commerce skill, energy-market.md, and MsgAgreementOpen in schemas/actions.md.database-schema.md now lists stat_connection_capacity/stat_connection_count and warns that five stat hypertables (stat_structs_load, stat_connection_capacity, stat_connection_count, stat_struct_health, stat_struct_status) have no object_type column (type implied by table); recommends deriving seized ore from ledger action='seized' rows (0-gram rows meaningful) over planet_raid.seized_ore (also softened in entities/planet.md, the combat skill, and combat.md); and notes connectionCapacity is already the per-player share (don’t divide by connectionCount again — also in energy.md).combat.md. Added knowledge/mechanics/combat.md and knowledge/mechanics/energy.md to CORE_FILES in generate-llms-full.sh so the core bundle carries the combat ruleset and energy-units anchor.Update for structsd v0.20.0 (commit a976768), the latest structs-webapp (0ece596), and the structs-desktop embedded MCP (README at ec79ab3). Docs describe current reality; only this changelog records history.
struct-trash action — destroys a built struct; irreversible; consumes build charge (8) via its handler (distinct from struct-build-cancel, which only cancels an unfinished build). Added to action-index.md, action-quick-reference.md, schemas/actions.md, schemas/requests.md, the permissions.md handler table + PermPlay list, transactions.md, building.md, conventions.md, the structs-building skill, and classified as a Tier-2 irreversible action in SAFETY.md.MsgStructDeactivateBatch) — deactivate up to 65 structs in one message, costs no charge. Added across the same action catalogs and permissions/charge tables.allocation-create/allocation-update/allocation-delete/allocation-transfer added to the action catalogs and request schema; MsgAllocationUpdate (no false capacity_exceeded on increase) noted in integration-notes.md.struct-deactivate no longer requires the player online (it is a recovery action, like reactor infuse); only activate requires online + charge + power. Reconciled in schemas/actions.md, action-quick-reference.md, and state-assessment.md.combat.md, struct-types.md, planet.md, glossary.md, the structs-combat skill). Attack resolution reworded so all defender counters resolve before any block and a destroyed attacker deals no damage.structs-desktop.md documents the embedded desktop MCP (http://127.0.0.1:8420/mcp + bearer token): 13 tools, 6 prompts, structs:// compendium resources, and subsystems (GPU/CPU hashing, perception/simulator, policy engine, combat mode, virtual players, tx-signing bridge, agent-driven UI, notifications, guild config). TOOLS.md slimmed to a connect + tool-list pointer; the deprecated structs_query/structs_ui names replaced with structs_intel/structs_board across awareness docs; the stale port-3000 note in SAFETY.md corrected.api/cosmetic-mods.md, the schemas/cosmetic-*.md, protocols/cosmetic-mod-*.md, examples/cosmetic-mods/, and the cosmetic error examples, plus every reference in schemas/requests.md/responses.md, reference/endpoint-index.md, api/endpoints-by-entity.md, api/error-codes.md, patterns/caching.md, reference/api-quick-reference.md, SITEMAP.md, and sitemap.xml. The real chain fields (defaultCosmeticName, defaultCosmeticModelNumber, class) are retained./api/struct/planet/{planet_id} — the real surface is /api/struct/list/location/{location_id}/page/{page} and /api/struct/player/{player_id}. Repointed in struct.md, endpoints.md, endpoints-by-entity.md, webapp-api-protocol.md, and the planet-monitor workflow.struct_type columns — documented generating_rate/generating_rate_p and primary/secondary_weapon_armour_piercing in struct.md.pfp / pfp_client_render_attributes to the player response (player.md, responses.md); flattened the stale nested {player, guild, stats} player shape to the real flat SQL-column object in player.md, responses.md, and webapp-api-protocol.md.block_raid_start and shield_change added to planet-activity.md.banned-word is not paginated — /api/banned-word/all (no /page/{page}) corrected in banned-word.md, webapp-api-protocol.md, api-quick-reference.md, and endpoint-quick-lookup.md.last_action_block_height (LCD numeric string), corrected in endpoints.md, player.md, and BlockHeightResponse in responses.md./api/pfp public route and fixed the public-prefix list in integration-notes.md (public = /api/auth/, /api/guild/this, /api/timestamp, /api/setting).work.md (/api/work/*), player-address.md (the 9 /api/player-address/* + 2 /api/auth/player-address* routes), and /api/fleet/player/{player_id} in fleet.md. Registered in api/webapp/README.md.GRASS streaming update, verified against structs-pg f90cfce and structs-webapp 7c692a0 (both dated 2026-07-07) plus the surrounding structs-pg migrations. The grid and planet event subjects now carry the owning player id, which changes subscription patterns; also folds in a few secondary Guild-Stack data-shape changes.
player_idstructs.GRID_NOTIFY() now publishes on structs.grid.{object_type}.{object_id}.{player_id} and structs.PLANET_ACTIVITY_NOTIFY() on structs.planet.{planet_id}.{player_id} (owner resolved via player_object, falling back to planet.owner; the literal noPlayer when unresolved; for a player grid object the owner is the object itself). Both payloads now include a top-level player_id. Verified in structs-pg deploy/trigger-grass-grid-20260707-add-owner-player-id.sql / deploy/trigger-grass-planet-activity-20260707-add-owner-player-id.sql; the webapp listener matches the suffixed subjects in src/js/framework/GrassManager.js.* matches exactly one token and > matches the rest, the documented structs.planet.* / structs.grid.* single-token wildcards no longer match. Updated structs-streaming, event-types.md, subscription-patterns.md, event-schemas.md, api-quick-reference.md, and glossary.md to use structs.planet.{id}.* (one planet) / structs.planet.> (all) and structs.player.> (the player subject is likewise three tokens). Added a NATS wildcard-rule callout to each.planet_activity stub is {subject, planet_id, player_id, seq, category, time, stub:'true'} (with player_id, and stub as the string 'true'), not a bare {stub:true}. Updated the streaming skill, event-types, and the glossary Stub entry.knowledge/infrastructure/database-schema.md now documents the GRID_NOTIFY / PLANET_ACTIVITY_NOTIFY GRASS publishing (owner-suffixed subject + player_id). A GRASS subject/player_id integration note was added to api/integration-notes.md.struct_type.generating_rate is a formatted column — the raw chain rate is now generating_rate_p, with generating_rate = generating_rate_p * 1000 (same _p/formatted split as grid value_p/value). Read generating_rate_p for the per-gram rate quoted in docs. Noted in struct-types.md and integration-notes.md. Verified in structs-pg deploy/table-struct-type-20260602-add-generating-rate-precision.sql.struct_type.primary_weapon_armour_piercing / secondary_weapon_armour_piercing (chain StructType.primary/secondaryWeaponArmourPiercing, v0.18.0). Read the flag rather than inferring from class. Noted in struct-types.md / integration-notes.md. Verified in structs-pg deploy/table-struct-type-20260612-add-armour-piercing.sql.PLAYER_PENDING_JOIN_PROXY threads player-name, player-pfp, and player-pfp-client-render-attributes into the signed guild-membership-join-proxy ugc argument (the column pfp_cr_attributes was renamed to pfp_client_render_attributes, and the ugc key lengthened from the short -cr-attributes form). Documented in integration-notes.md; ugc-moderation.md already covered the pfp / pfpClientRenderAttributes fields.Energy/power overhaul driven by an agent field report, verified against the structsd v0.19.1 keeper source (x/structs/...) and live structstestnet reads. Adds a canonical Energy page, fixes a 1000× unit-label error, and documents grid mechanics, build slots/limits, and energy data shapes that had no home in the docs.
energy.md consolidates the whole energy system: the milliwatt unit convention, the online equation and its four quantities (capacity/capacitySecondary/load/structsLoad), the per-message offline behavior, infusion mechanics, substation dilution, allocations, and the brownout cascade. power.md is slimmed to a quick formula card that defers to it. Registered in AGENTS.md, llms.txt, SITEMAP.md, sitemap.xml, and the bundles.Infusion.GetPowerDistribution() + ReactorFuelToEnergyConversion = 1 (x/structs/types/infusion.go, types/keys.go): 1 ualpha → 1 mW, split so the infuser keeps 1 − commission (default 4%, reactor_hooks.go) on their own capacity and the reactor keeps the commission. Infusing a reactor does not power a substation — an allocation must route capacity in. Documented in energy.md and the structs-energy skill.connectionCapacity dilutes — UpdateSubstationConnectionCapacity (x/structs/keeper/grid_context.go): each connected player receives (capacity − load) / connectionCount, recomputed on every connect/disconnect, so each new connection shrinks everyone’s share. The real guild capacity-planning rule. Added to energy.md and the skill.substation-allocation-connect checks PermAllocationConnection only on the caller’s own allocation (msg_server_substation_allocation_connect.go → CanBeConnectedBy); no destination-substation veto, no guild membership. Anyone can contribute capacity to any substation (diluted by 1/connectionCount). Documented with the dilution caveat.GridCascade brownout — when load exceeds capacity, the keeper destroys that object’s outgoing allocations in creation order until load fits, cascading downstream (grid_context.go). Added to energy.md and the skill.struct-types.md draw table and power.md example/onboarding tables mislabeled watt values as kW. Relabeled to W (e.g. Command Ship 50 W, not 50 kW) and the unit anchored once in energy.md.Limit column — added to the struct-types.md main table from genesis BuildLimit (x/structs/types/genesis_struct_type.go): Command Ship, Ore Extractor, Ore Refinery, Jamming Satellite, PDC, Field Generator, Continental Power Plant, World Engine = 1; all fleet combat structs, Orbital Shield Generator, and Ore Bunker = unlimited. (buildLimit: 0 = unlimited.)building.md gains a Slots section (4 per ambit on both planet and fleet, PlanetStartingSlots = 4; slot reserved at initiate; counts fixed) and a build-cadence note (build costs 8 charge and resets the bar, so ~one build per ~8 blocks).integration-notes.md — power fields live under a gridAttributes sub-object (LCD numerics are JSON strings/milliwatts), guild carries primaryReactorId/entrySubstationId, and verified message shapes for MsgReactorInfuse (single Coin amount), MsgAllocationCreate (no destinationId), and MsgSubstationAllocationConnect (substation goes in destinationId) from proto/structs/structs/tx.proto.reference/glossary.md adds Allocation, connectionCapacity, GridCascade, Reactor, structsLoad, and Slots, and repoints the energy entries (capacity, load, infusion, substation, BuildDraw) to energy.md.Documentation improvements driven by agent field notes, verified against the structsd, structs-grass, and structs-pg sources. This pass closes content gaps the field notes surfaced, reconciles the streaming catalog to the actual Postgres triggers, and adds discoverability and learning aids (a concept glossary, a worked combat/raid transcript, and a multi-account playbook).
capacity_exceeded covers two build checks — struct-build-initiate raises the same cannot handle new load requirements (required: X, available: Y) string for both the per-player build-count limit and the power-capacity check (x/structs/keeper/msg_server_struct_build_initiate.go, x/structs/types/errors_structured.go). Tiny equal integers = build limit; large values = milliwatt capacity. Documented in building.md, troubleshooting/common-issues.md, api/integration-notes.md.range blocks old, so an old anchor is a cheaper proof than a fresh one. Added to hashing.md; cross-linked from structs-production and structs-building, with the mine/refine clock reset reaffirmed.struct_cache.go ResolveDefenders). Added Assigning Defenders to combat.md and clarified the structs-combat defense procedure.counterAttackSameAmbit, cross-ambit uses counterAttack (genesis_struct_type.go; e.g. CMD 2/2, Destroyer 1/2). Replaced the “÷2” framing in combat.md and added the “counters are a backstop” note to combat docs.structs-combat and the new team playbook.none=1 … local=32 (bit = 1 << enum) alongside the enum (0–5) consistently in building.md, combat.md, and struct-types.md, each cross-linked to integration-notes.struct-types.md, combat.md, and integration-notes.md now point to the single decoder table in building.md (status & 4 online, status & 32 destroyed; 35 = destroyed).grass triggersstruct_attack is streamed but stubbed — the Postgres NOTIFY payload is capped (~7995 bytes); large combat detail is replaced by a { "stub": true } envelope with no shot log (structs-pg/deploy/trigger-grass-planet-activity.sql). Detect combat from effect events (struct_health, struct_status, shield_change, raid_status) and pull planet_activity for shot detail. Documented in structs-streaming, api/streaming/event-types.md, api/streaming/event-schemas.md, schemas/database-schema.md.shield_change and block_raid_start (structs-pg migration type-grass-category-20260612-add-raid-shield-categories.sql), plus struct_health, player_address, player_address_pending, and the grid/inventory category lists. Flagged fleet_advance and player_meta as defined but not emitted.reference/glossary.md: ~70 terms with one-line definitions, disambiguation of the common traps (ambit enum vs bitmask, block vs counter, multi-shot vs multi-target, capacity_exceeded, stub, attackerDefeated), and a canonical-page link each. Linked from AGENTS.md, SITEMAP.md, llms.txt and added to the bundles.scripts/check-drift.sh now validates (filesystem-only) that every glossary link target file exists and every #anchor resolves to a heading, so the glossary cannot silently rot.examples/transcripts/03-combat-and-raid.md: counter-free attacking ambits, weapon-control vs defense, charge pacing, numeric status, the stubbed stream, and completing a raid without losing the attacker’s Command Ship.playbooks/meta/team-operations.md: multi-account play, per-player charge/build-limit multipliers, focus fire, substation-fed power, idempotent proxy onboarding, minimal-permission workers.event-types.md, event-schemas.md, common-issues.md, glossary.md, the new transcript, and the team playbook to scripts/generate-llms-full.sh; linked the streaming catalogs and troubleshooting from llms.txt. Regenerated llms-full.txt / llms-core.txt.Documentation rolled forward to structsd v0.19.1 (tag v0.19.1), with the toolchain refocused on structs-desktop and its embedded MCP server.
struct-attack, struct-defense-set, and stealth changes evaluate readiness on the operating struct and its owner only (msg_server_struct_attack.go, struct_cache.go ReadinessCheck). The attacker’s Command Ship need not be online or on-station. Updated combat.md, structs-combat, fleet.md, schemas/actions.md, reference/action-quick-reference.md, patterns/validation-patterns.md.CanAttack rejects a target that is not yet built (struct_cache.go, error unbuilt); a destroyed target is rejected (destroyed). Documented across combat docs and the validation patterns.planet_cache.go IsDefenderCommandStructVulnerable). Sending your fleet away to raid leaves your own planet raidable until it returns. Updated combat.md, planet.md, fleet.md, patterns/decision-tree-combat.md, structs-combat, structs-planets-fleet, scripts/scout.sh.genesis_struct_type.go). Updated struct-types.md.structs-desktop — all MCP guidance now points to the MCP server embedded in the structs-desktop app: a 9-tool catalog (structs_dashboard, structs_query, structs_hash, structs_action, structs_intel, structs_policy, structs_ui, structs_events, structs_sequence) and 6 guided prompts, with charge-paced action queueing and agent-driven UI for human+agent co-op. Connection details live in the app’s Debug menu. Rewrote the MCP section of TOOLS.md; updated AGENTS.md, SITEMAP.md, and the awareness docs.structsd’s make system (make proto-gen-ts) and used directly with CosmJS; no separate client package.structs-client-ts, structs-compendium, and structs-mcp — these are no longer part of the toolchain. Build TypeScript bindings via structsd; connect agents through the structs-desktop MCP server.Combat-and-raid documentation hardening from live-play findings, verified against the structsd v0.18.0 source (tag v0.18.0, commit 173e7a2). An initial pass documented several player-reported mechanics that source verification then corrected — the net result below is what the code actually does, with file:line citations.
planet-raid-complete seizes all of the defender’s storedOre and nothing else; there is no player-destruction outcome. Killing the defender’s Command Ship only opens the shieldsVulnerable window (IsDefenderCommandStructVulnerable); if it’s restored before completion the raid is rejected (shields_active). trigger_raid_defeat_by_destruction is on the Command Ship and defeats the attacking fleet when its away-from-home CMD is destroyed (attackerDefeated), per struct_cache.go CanTriggerRaidDefeatByDestruction and fleet_cache.go Defeat(). Updated combat.md, planet.md, structs-combat. Added attackerDefeated to the raid-status table.noUnitDefenses). The interceptor network evades attacks only when the attacker is in air/space and the target is in land/water (attack_context.go:155-171, evadedByPlanetaryDefenses / lowOrbitBallisticInterceptorNetwork). The orbitalJammingStation, coordinatedGlobalShieldNetwork, and repairNetwork attributes exist but are not incremented by any struct nor read in combat. Updated combat.md, struct-types.md.primaryWeaponTargets = 1 (and secondaryWeaponTargets = 1 where a secondary exists) in genesis_struct_type.go; no multi-target weapon exists, though the field supports >1. Distinguished from multi-shot (primaryWeaponShots). Updated combat.md, struct-types.md, structs-combat, AGENTS.md, llms.txt.charge = CurrentBlockHeight - LastActionBlock, so every action resets the bar to 0; no alpha-strike. Added to building.md, cross-referenced from combat.md.status field — documented as the StructState bit-flag (struct.go): Materialized 1, Built 2, Online 4, Stored 8, Hidden 16, Destroyed 32, Locked 64. Common composites: 0 stateless, 1 materialized, 3 built/offline, 7 online, 35 = destroyed (1+2+32). Added to building.md.trigger_raid_defeat_by_destruction defeats the attacker’s fleet, not the defender.signalJamming defense on the target (66% vs guided).defense-set/ResolveDefenders impose no per-ambit cap; the “4 per ambit” is just the planet’s 4 slots/ambit.status 35 is a destroyed struct (not an unknown/ambit value).A decision-first rebuild of the skills layer, plus a read-only script toolkit, machine-readable memory, and learning/measurement scaffolding. Every skill now states when to use it, the decisions it helps you make, and the exact commands — with shared boilerplate factored out once.
conventions.md — single source for shared skill boilerplate: transaction flags (TX_FLAGS / TX_FLAGS_APPROVED), the -- entity-ID rule, the per-player charge bar, proof-of-work -D policy, one-transaction-at-a-time, and the skill-authoring template (level / domain front matter).structs-production (absorbs mining), structs-planets-fleet (absorbs exploration), structs-energy (absorbs power; capacity-side), structs-commerce (absorbs economy; market-side), structs-permissions (replaces diplomacy; adds delegate-agent recipes), structs-intel (replaces reconnaissance).scripts/ — read-only helpers that turn multi-step queries into one-line decisions: assess.sh, power-budget.sh, scout.sh (raid go/no-go with the shield-vulnerability gate), job-status.sh, watch-defense.mjs (GRASS defense alerts), check-drift.sh (flag doc constants that drift from the live chain), and a shared lib.sh.memory/README.md defines JSON schemas for operational state (player.json, game-state.json, jobs/<job>.json); new memory/jobs/ directory convention (.json / .log / .pid per expedition).llms-core.txt — a tight starter bundle (identity + conventions + core-loop skills + key knowledge) alongside the full llms-full.txt; both emitted by scripts/generate-llms-full.sh.--pfp-client-render-attributes support in create-player.mjs, with local v0.18.0 validation (≤512-byte JSON object).level / domain front matter and a “When to use it” + “Decisions” section. Rewrote structs-building, structs-combat (v0.18.0 raid doctrine), and structs-guild (guild-choice criteria); refocused play-structs and structs-onboarding on the new skill map and per-player charge..cursor/skills/index.md, AGENTS.md, SAFETY.md, SITEMAP.md, llms.txt, and sitemap.xml.structs-mining, structs-exploration, structs-power, structs-economy, structs-diplomacy, structs-reconnaissance (their content lives in the consolidated skills above). Root skills/ symlinks updated to match.charge = CurrentBlockHeight - player.lastActionBlock); every charge-consuming action by any of the player’s structs draws from and resets the same bar. Rewrote knowledge/mechanics/building.md as the canonical explainer and fixed per-struct phrasing in schemas/actions.md, schemas/errors.md, schemas/entities.md, protocols/action-protocol.md, protocols/error-handling.md, reference/action-quick-reference.md, troubleshooting/error-codes.md, awareness/state-assessment.md, awareness/async-operations.md, awareness/context-handoff.md, awareness/continuity.md, knowledge/infrastructure/guild-stack.md, and knowledge/lore/structs-origin.md.activateCharge 1→2 and stealthActivateCharge 1→2 (all types); Command Ship moveCharge 8→3; primary weapon charges rebased to 3 (Command Ship, Starfighter, Pursuit Fighter, Tank) or 5 (all other armed hulls); secondary charges 5 (Battleship, Starfighter) / 3 (Cruiser). Updated building.md, struct-types.md, combat.md.armour (damage reduction 1). Fleet HP unchanged.primaryWeaponArmourPiercing / secondaryWeaponArmourPiercing (negate the target’s damage reduction). Battleship primary is now armour-piercing, restricted to Land/Water, and gains a guided secondary that reaches Space — the dedicated counter to Tanks and armoured generators.SHIELDS_VULNERABLE — documented that planet-raid-complete only succeeds while the defender’s Command Ship is offline/destroyed/non-existent, the blockStartRaid vulnerability clock, and the new shieldsVulnerable / ongoing raid statuses. Planetary shield values rebased onto a base shield of 25.movable; the chain rejects struct-move on any other struct.pfpClientRenderAttributes — new player field carrying render hints (a compacted JSON object, ≤512 bytes) for a locally-rendered profile picture, set via MsgPlayerUpdatePfpClientRenderAttributes (or at guild signup). Owner-only; not guild-moderatable. Documented in ugc-moderation.md, schemas/validation.md, schemas/actions.md, schemas/entities.md, reference/action-quick-reference.md, transactions.md.knowledge/infrastructure/guild-stack.md, .cursor/skills/structs-guild-stack/SKILL.md, knowledge/infrastructure/database-schema.md, and schemas/database-schema.md — structs-sync-state service, sync_state.* schema, cache.* compatibility views, retired player_meta/planet_meta tables.guild-update-primary-reactor CLI command and MsgGuildUpdatePrimaryReactor in schemas/actions.md and reference/action-quick-reference.md.planet-explore [player-id] [name] documented in exploration skill, schemas/actions.md, knowledge/mechanics/planet.md.structstestnet-111 / NETWORK_VERSION=113b in TOOLS.md, guild-stack skill, and structsd-install (v0.17.0).username/pfp on structs.player, name on structs.planet, name/pfp on structs.guild; guild_meta documents off-chain config only.player_consensus replaces player_meta for UGC; block height no longer via current_block NOTIFY; streaming protocol, event schemas, and streaming skill updated.compose.yaml canonical filename; default profile is structsd structs-pg structs-sync-state structs-grass; MCP/proxy removed from compose (separate structs-mcp repo).schemas/database-schema.md rewritten as current-state structural catalog (changelog sections removed).knowledge/mechanics/combat.md.structs.player instead of player_meta in api/webapp/player.md.awareness/async-operations.md — when a new session inherits a “running” job in memory/jobs/, the agent now has a procedure (alive PID? landed on chain? state matches expectation? silent-failure diagnosis?) instead of a one-line aspiration. Includes a nohup ... > memory/jobs/<job>.log 2>&1 & echo $! > memory/jobs/<job>.pid template so each expedition leaves a paper trail, and a re-verify-consent checklist for refines specifically (the 34h window is the worst-case staleness gap).play-structs — a new “Before You Sign Anything” callout above Step 1 introduces the tier framework and links SAFETY.md and COMMANDER.md before the first transaction example. Also adds reconnect and SAFETY reminders to the skill’s “What You Need to Know” section.awareness/context-handoff.md — resume protocol now includes SAFETY.md in the startup-read list and inserts a dedicated “verify long-running compute jobs first” step (pointing at the new four-state flow) before strategic state assessment.structs-mining, structs-building, structs-combat — Safety callouts now point at the reconnect flow at the point of need, so an agent reading the skill in the middle of a problem finds the verification procedure without bouncing back to async-operations.Skilled-player feedback on the 1.10.0 ship: two real gaps. (1) The 34-hour refinery window leaves agents stranded when they reconnect — memory/jobs/ was the persistence pattern, but no procedure told them how to verify what happened in the gap. (2) play-structs was supposed to be the entry-point skill but only mentioned safety in “See Also” at the bottom — new agents could run 180 lines of commands before encountering the tier framework. Both addressed.
-y Rule” in SAFETY.md — codifies that -y is OFF by default in every transaction example, ON only after commander approval. Two named flag bundles (TX_FLAGS, TX_FLAGS_APPROVED) make the distinction explicit. Compute commands (struct-build-compute, struct-ore-mine-compute, struct-ore-refine-compute, planet-raid-compute) are the documented exception — they must auto-submit unattended, so they ship with -y paired with an Approval Block that surfaces consent up-front.SAFETY.md and applied at every Tier 1+ command site in the skills.structsd as a required tool inline, closing the ASI04 dependency Notes ClawScan raised on structs-energy, structs-economy, structs-diplomacy, and similar.structs-guild-stack setup — Step 4 starts only structsd structs-pg structs-grass instead of the full stack. The MCP server, webapp, NATS, and signing agent must be enabled explicitly. A new “Enabling Additional Services” section documents how.git checkout <latest-tag> makes the Compose file a reviewable artifact instead of a moving target.-y from every Tier 1+ transaction example in 11 skills (~50 instances across structs-onboarding, structs-mining, structs-building, structs-combat, structs-economy, structs-energy, structs-power, structs-guild, structs-diplomacy, structs-exploration, play-structs) plus the create-player.mjs script’s next_step example. The CLI’s confirmation prompt becomes the last gate before signing.-y because they auto-submit completion when no shell is attached. Each compute example is now preceded by an Approval Block that surfaces the deferred-consent risk.-y to two named bundles: TX_FLAGS (interactive, the default) and TX_FLAGS_APPROVED (interactive plus -y, only after commander approval). Each skill’s bundle docs explain which commands actually warrant the approved form.AGENTS.md Critical Rule 6 rewritten to teach the new flag policy. The “Common transaction flags” line now shows the interactive default and references the auto-approved form separately.planet-explore split in structs-exploration into two distinct procedural steps: Tier 0 first-explore (routine) and Tier 2 subsequent-explore (preceded by an Approval Block surfacing currentOre == 0, fleet status, and the destruction warning).structs-guild-stack “Lifecycle & Trust” condensed — pin-a-tag and disable-services moved into the main Setup Procedure where they belong; the section now hosts the longer-form rationale, MCP localhost binding, signing-agent caveat, and teardown commands.Responds to the re-audit pass of ClawScan on the 11 affected skills after the 1.9.0 changes. The 1.9.0 work moved six skills to zero ClawScan Concerns and downgraded most remaining findings to Notes; the remaining Concerns in structs-onboarding, structs-combat, structs-energy, structs-power, structs-exploration, and structs-guild-stack all traced to one issue — -y was still present in command examples even when the Safety callout sat directly above. 1.10.0 retires -y from default examples entirely and reframes its use as a documented, narrow exception with an explicit approval surface at each call site. structsd-install remains unchanged and continues to Pass.
| Skill | 1.8 | 1.9 | 1.10 target |
|---|---|---|---|
| structs-onboarding | Review · 5 findings | 2 Concerns + 2 Notes | 0 Concerns |
| structs-mining | Review · 2 Concerns | 0 Concerns | 0 Concerns |
| structs-building | Review · 3 Concerns | 0 Concerns | 0 Concerns |
| structs-combat | Suspicious · 3 Concerns | 1 Concern | 0 Concerns |
| structs-economy | Suspicious · 2 Concerns | 0 Concerns | 0 Concerns |
| structs-energy | Suspicious · 2 Concerns | 2 Concerns | 0 Concerns |
| structs-power | Suspicious · 2 Concerns | 1 Concern | 0 Concerns |
| structs-guild | Suspicious · 1 Concern | 0 Concerns | 0 Concerns |
| structs-diplomacy | Suspicious · 1 Concern | 0 Concerns | 0 Concerns |
| structs-exploration | Review · 2 Concerns | 1 Concern | 0 Concerns |
| structs-guild-stack | Review · 2 Concerns | 3 Concerns | 0 Concerns |
| structsd-install | Pass | Pass | Pass |
SAFETY.md — the trust contract between agent and commander. Three operation tiers (Routine / Significant / Irreversible) mapped to COMMANDER.md autonomy levels. Battle-order approval pattern, background-expedition rules, key hygiene, verification checklist, and audit log pattern. Links the public ClawScan audits for every skill.awareness/agent-security.md — operational threat playbook. UGC prompt injection, RPC node trust, address-register identity hijack, guild API trust, MCP/signing-agent exposure, multi-agent key isolation. Includes a step-by-step incident response playbook (defuse → revoke → transfer → revoke permissions → rotate primary address → log).COMMANDER.md standing-orders template — pre-filled Tier 1 auto-approval caps and Tier 2 always-escalate lists so commanders fill blanks instead of designing from scratch.structs-onboarding, structs-mining, structs-building, structs-combat, structs-economy, structs-energy, structs-power, structs-guild, structs-diplomacy, structs-exploration, structs-guild-stack). Each callout lists the skill’s highest-impact ops with their tier and in-character flavor..cursor/skills/structs-guild-stack/SKILL.md “Lifecycle & Trust” subsection — pin a release tag rather than tracking main, disable services not needed (read-only PG profile), bind MCP to 127.0.0.1, signing-agent caveat, teardown commands.AGENTS.md, README.md, index.md, QUICKSTART.md, llms.txt, SITEMAP.md, and awareness/index.md — surface SAFETY.md and agent-security.md as discoverable entry points; added Critical Rule 9 in AGENTS.md.scripts/generate-llms-full.sh — includes SAFETY.md and awareness/agent-security.md in the aggregated build.Responds to ClawScan audits of 11 Structs skills (ASI02 -y auto-confirm; ASI03 signing-key scope; ASI04 binary trust; ASI06 personal-file context poisoning; ASI07 guild API + MCP; ASI10 long-running PoW). Keeps -y in TX_FLAGS for ergonomics and instead makes the approval gate explicit through a commander-grounded tier system. structsd-install was the only audited skill that already passed; it remains unchanged.
https://public.testnet.structs.network (REST) and https://public.testnet.structs.network:26657 (Tendermint RPC; wss://...:26657/websocket for the Tendermint WebSocket). The new endpoint avoids mixed-content and CORS issues that occurred when calling http://reactor.oh.energy:1317 from HTTPS contexts. The Guild API (http://crew.oh.energy/api/) and GRASS NATS WebSocket (ws://crew.oh.energy:1443) remain hosted by individual guilds and are unchanged.api/webapp/ covering the CatalogReadController family (address-tag, agreement, allocation, banned-word, defusion, fleet/list, grid, guild-membership-application, permission, permission-guild-rank, planet-activity, planet-attribute, provider, reactor, substation, struct-attribute, struct-defender) plus setting (live tunables) and stat (time-series range queries). Existing per-entity files (player.md, planet.md, guild.md, struct.md, ledger.md, infusion.md) extended with their corresponding /list/... catalog endpoints.protocols/webapp-api-protocol.md: catalog-read pattern, time-series stats pattern, live-tunables pattern, kebab-case naming, the /list/ namespacing rule that prevents the catalog list from shadowing single-id routes, and the ?start_time=&end_time= (unix seconds) query convention.knowledge/infrastructure/database-schema.md: new tables structs.banned_word, structs.address_tag (with the (label, entry) reverse-lookup index), structs.setting (seeded keys: REACTOR_RATIO, PLAYER_RESUME_CHARGE, PLANETARY_SHIELD_BASE, PLAYER_PASSIVE_DRAW, PLANET_STARTING_ORE, PLANET_STARTING_SLOTS), structs.defusion (with the CLEAN_DEFUSION() cron), aggregated views view.guild_bank, view.leaderboard_guild, view.leaderboard_player, and the planet.seized_ore column. knowledge/infrastructure/guild-stack.md gained a one-paragraph note that the PG schema is owned by structs-pg and applied with Sqitch (initial deploy by structs-pg-init, ongoing by structs-pg-auto-migrate).TOOLS.md switched to https://public.testnet.structs.network and the SSL Tendermint URL (wss://...:26657/websocket). Skills (play-structs, structs-onboarding, structs-streaming) and the create-player.mjs script header / usage strings updated to match.api/endpoints.md, reference/endpoint-index.md, reference/endpoint-quick-lookup.md, reference/api-quick-reference.md, api/webapp/README.md) refreshed to register the new webapp endpoints and the SSL chain hosts. Stale per-doc “Version” pins removed in favour of Last Updated dates only — these documents represent current truth, not versioned history.MsgGuildModerate* message in tx.proto. Moderation is the same Msg*UpdateName / Msg*UpdatePfp chain message, gated by PermGuildUGCUpdate (bit 24) on the target owner’s guild when actor != owner, and the chain emits a ugc_moderated Cosmos event for audit. The 1.7.0 entry below references “Guild moderation overrides: MsgGuildModeratePlayerName/Pfp …” — those names refer to tx_guild_moderate_* PL/pgSQL wrappers in the signer layer (which queue the same Msg*Update* chain message after a PermGuildUGCUpdate preflight), not to chain message types. knowledge/infrastructure/database-schema.md reworded the signer.tx_* wrapper section to make this explicit.Last Updated dates on the file and via this CHANGELOG.md.Major documentation update for structsd v0.16.0 (codename “Quantillia”). Synchronizes the docs with the chain’s permission expansion (24->25 bit), the new fee/ante model, the seven new UGC (User-Generated Content) transactions and their decentralized moderation hooks, the GuildMembershipJoinProxy UGC fields, the planet-explore precondition tightening, the Starfighter guaranteed-shot fix, the Quantillia database schema, and the related webapp / signer / build-system changes. Includes two new knowledge documents (transactions.md, ugc-moderation.md) and a Makefile-based install path.
PermAll and PermPlayerAll bumped from 16777215 to 33554431 (25 bits).PermGuildUGCUpdate (bit 24, value 16777216) for guild-scoped moderation of player/planet/substation UGC.PermGuildAll updated to 17166862.knowledge/mechanics/permissions.md now documents UGCPermissionCheck – the two-tier flow that first attempts a self-service PermUpdate check, and falls back to PermGuildUGCUpdate against the target owner’s guild.api/queries/permission.md, schemas/entities.md, schemas/game-state.md, knowledge/mechanics/index.md, reference/entity-index.md, reference/action-quick-reference.md, troubleshooting/edge-cases.md, troubleshooting/permission-issues.md, patterns/performance-optimization.md, examples/database/query-examples.md, examples/workflows/permission-checking.md, examples/auth/permission-examples.md, .cursor/skills/structs-diplomacy/SKILL.md, .cursor/skills/structs-guild/SKILL.md, SITEMAP.md, llms.txt.knowledge/mechanics/transactions.md – explains the v0.16.0 fee model: pure-Structs gameplay transactions (allocations, substations, guilds, combat, UGC, …) are free with a 20M gas cap; six Cosmos SDK staking messages are free with a 40M gas cap (one per address per block); standard Cosmos SDK operations (MsgSend, non-listed x/staking messages, mixed transactions) still pay ualpha. --gas auto is still required for accurate gas estimation.protocols/action-protocol.md updated with a new “Fees” subsection summarizing the free-gas changes.knowledge/mechanics/ugc-moderation.md – philosophy and how-to for guild-scoped moderation. Covers self-service vs. moderator paths, the PermGuildUGCUpdate permission, the ugc_moderated Cosmos chain event (emitted only when actor != owner), per-field validation rules with Python and JavaScript snippets, and operational guidance for guild policy/auditing.schemas/actions.md, reference/action-quick-reference.md, .cursor/skills/structs-guild/SKILL.md, and the structsd CLI references:
MsgPlayerUpdateName, MsgPlayerUpdatePfp, MsgGuildUpdateName, MsgGuildUpdatePfp, MsgPlanetUpdateName, MsgSubstationUpdateName, MsgSubstationUpdatePfp (all gated by PermUpdate on the target object)MsgGuildModeratePlayerName/Pfp, MsgGuildModeratePlanetName, MsgGuildModerateSubstationName/Pfp (all gated by PermGuildUGCUpdate on the target owner’s guild)knowledge/lore/factions.md got a new “Identity and moderation” subsection introducing the model in lore terms.schemas/validation.md and fully spelled out in knowledge/mechanics/ugc-moderation.md for: player name (3-20, no spaces, no apostrophe), entity name (guild/substation, 3-20, allows space and apostrophe, no leading/trailing/double space), planet name (3-25, same as entity), and PFP (opaque [A-Za-z0-9._/-]{1,256} or URL with allowed schemes https, http, ipfs, ipns, ar).N-N ID-shaped strings, must be valid UTF-8..cursor/skills/structs-onboarding/scripts/create-player.mjs – new --username and --pfp flags, client-side validators that mirror the chain’s ValidatePlayerName / ValidatePfp, and pfp plumbed into the signup payload and final output.GuildMembershipJoinProxy UGC FieldsMsgGuildMembershipJoinProxy now accepts optional playerName and playerPfp so the chain becomes the sole source of truth for player identity at signup. Documented in schemas/actions.md, reference/action-quick-reference.md, .cursor/skills/structs-guild/SKILL.md, .cursor/skills/structs-onboarding/SKILL.md, and threaded through create-player.mjs.MsgPlanetExplore now requires the fleet to be onStation at the player’s current planet only when the player already owns one. First-time explorers (no current planet) are exempt. Documented in schemas/actions.md, knowledge/mechanics/planet.md, knowledge/mechanics/fleet.md, and .cursor/skills/structs-exploration/SKILL.md. New error string "fleet must be onStation to explore" added to the exploration skill’s error handling.primaryWeaponGuaranteedShots and secondaryWeaponGuaranteedShots documented in knowledge/entities/struct-types.md. Starfighter’s secondary weapon is set to 1 guaranteed shot.knowledge/mechanics/combat.md Multi-Shot Damage section explains how weaponGuaranteedShots provides a floor of successful hits per volley before probabilistic rolls.api/streaming/event-types.md and api/streaming/event-schemas.md updated:
PlayerMetaEvent now carries username and pfp (chain is sole source of truth as of v0.16.0).GuildMetaEvent now carries pfp in addition to name.ugc_moderated event with attribute schema and emission rules. (Not delivered through GRASS – subscribe via Tendermint event subscriptions.).cursor/skills/structs-streaming/SKILL.md got a “UGC Moderation Events” section explaining the two streams (GRASS DB-trigger meta events vs. the chain ugc_moderated event) and the “actor != owner” emission condition.knowledge/infrastructure/database-schema.md updated:
structs.guild_meta (now with pfp), structs.player_meta (PK collapsed from (id, guild_id) to (id) – one row per player; webapp no longer writes meta directly), structs.substation (with name and pfp), and structs.planet_meta (chain-only updates, never overwritten by empty values).signer.signer_tx_type enum values for the seven UGC transactions.signer.tx_* wrappers documented (7 self-service + 5 guild moderation).signer.UPDATE_PENDING_ACCOUNT bumped to PermAll = 33554431.PLAYER_PENDING_JOIN_PROXY trigger now threads playerName/playerPfp into the ugc JSONB; PLAYER_PENDING_MERGE no longer writes player_meta.PUT /api/player/username removed in v0.16.0. Username and PFP are now updated via the chain MsgPlayerUpdate* transactions; the webapp’s signing client manager queues them through queueMsgPlayerUpdateName / queueMsgPlayerUpdatePfp. Updated: api/endpoints.md, api/endpoints-by-entity.md, api/webapp/player.md, api/rate-limits.md, schemas/requests.md.queueMsg* wrappers (10 new entries) added to the webapp registry alongside MsgGuildMembershipJoinProxy’s expanded args; queueMsgBankSend removed (no callers).make install / make build). Go 1.23+ now required (was 1.24.1). Ignite is only needed for local devnet (make serve).build-linux-amd64, build-darwin-arm64, …, build-all).AGENTS.md, SITEMAP.md, llms.txt, and TOOLS.md updated to reflect the new structsd-install description.scripts/generate-llms-full.sh includes knowledge/mechanics/transactions.md and knowledge/mechanics/ugc-moderation.md. llms-full.txt regenerated.Major update incorporating all changes from Structs v0.15.0-beta (codenamed Pyrexnar) on the structstestnet-111 network. v0.14.0-beta (Opheliora) was a botched release; v0.15.0-beta (Pyrexnar) supersedes it with proxy join and test fixes.
knowledge/mechanics/permissions.md – Comprehensive permission reference combining the Permission System, Guild Rank Permission System, and Message Handler Permission Reference. Covers all 24 permission bits, composite masks, storage format, check flow, and every handler’s permission requirements.permission-guild-rank-set, permission-guild-rank-revoke, player-update-guild-rankguild-rank-permission-by-object, guild-rank-permission-by-object-and-guildstruct-attack invocation (not per shot)targetPlayerId moved from EventAttackDetail to EventAttackShotDetail (API-breaking)controller field is now PlayerId (not address) – account abstractionlocked column removed from allocation tableprovider-guild-grant and provider-guild-revoke transactions removed; replaced by guild rank permissions (permission-guild-rank-set with PermProviderOpen on the provider)entryRank (uint64) – default rank for new members (chain default: 101)guildRank (uint64) – rank within guild (1 = creator, 101 = default on join)owner (string) – PlayerId of reactor ownerguild-create (from reactor), guild-update-entry-rank, player-update-guild-rank, player-send, permission-guild-rank-set, permission-guild-rank-revokeprovider-guild-grant, provider-guild-revokeplayer-update-primary-address (removed playerId), address-register (removed playerId)structs.permission_guild_rank (object_id, guild_id, permission, rank)guild.entry_rank, player.guild_rank, reactor.ownerallocation.lockedEventGuildRankPermissionknowledge/mechanics/permissions.md – NEWknowledge/mechanics/combat.md – Attack resolution rewrite, counter-attack overhaul, PDC fix, per-projectile eventsknowledge/mechanics/index.md – Permissions entryknowledge/economy/energy-market.md – Controller=PlayerId, provider access via guild rankknowledge/infrastructure/database-schema.md – New tables, columns, removed lockedschemas/entities/allocation.md – Controller=PlayerId, removed lockedschemas/entities/guild.md – entryRank fieldschemas/entities/player.md – guildRank fieldschemas/entities/reactor.md – owner fieldschemas/entities.md – 24-bit permission flagsschemas/game-state.md – 24-bit permission flagsschemas/actions.md – New transactions, updated requirementsreference/action-quick-reference.md – New actions, permission/allocation/provider sectionsreference/entity-index.md – New fields, 24-bit permsreference/gameplay-index.md – Counter-attack mechanicsapi/queries/permission.md – Guild rank queriesapi/queries/guild.md – entryRankapi/queries/player.md – guildRankapi/queries/reactor.md – ownerapi/streaming/event-types.md – EventGuildRankPermissionapi/streaming/event-schemas.md – EventGuildRankPermission, targetPlayerId moveapi/endpoints.md – Guild rank permission endpointsapi/endpoints-by-entity.md – Guild rank permission queries.cursor/skills/structs-combat/SKILL.md – Counter-attack rules, PDC notes.cursor/skills/structs-economy/SKILL.md – Controller=PlayerId, provider access.cursor/skills/structs-energy/SKILL.md – Guild rank provider access.cursor/skills/structs-power/SKILL.md – Controller=PlayerId.cursor/skills/structs-diplomacy/SKILL.md – 24-bit perms, guild rank commands, arg changes.cursor/skills/structs-guild/SKILL.md – guild-create, rank system, provider access.cursor/skills/structs-onboarding/SKILL.md – Guild rank notetroubleshooting/permission-issues.md – 24-bit perms, HasAll, guild ranktroubleshooting/edge-cases.md – 24-bit permsexamples/auth/permission-examples.md – 24-bit perms, guild rank examplesexamples/workflows/permission-checking.md – 24-bit perms, guild rank stepexamples/database/query-examples.md – 24-bit permsexamples/gameplay-combat-bot.md – Per-projectile events, counter-attackprotocols/gameplay-protocol.md – Combat mechanics, battleDetailspatterns/performance-optimization.md – 24-bit bitwise checkspatterns/decision-tree-combat.md – Combat resolution orderAGENTS.md – Permissions in Knowledge sectionSITEMAP.md – permissions.md entryllms.txt – permissions.md entrysitemap.xml – permissions URLMajor overhaul addressing PoW timing and async operations, based on agent field experience:
awareness/async-operations.md – Core document teaching agents the async pattern: pipeline strategy, background PoW management, job/charge tracker templates, difficulty planning table, multi-player orchestration, ore vulnerability analysis.-D 8 for all operations.resources.md: ore is stealable for ~15-24 hours between mining and refining completion. Primary driver of PvP conflict.jobs.md, charge-tracker.md, game-state.md. Session resume checks jobs first.llms.txt and llms-full.txt updated – New async-operations entry, corrected descriptions, regenerated full text.awareness/async-operations.md – NEWknowledge/mechanics/building.md – Difficulty decay table, cliff, charge costs, async cross-referenceknowledge/mechanics/resources.md – PoW timing table, ore vulnerability window.cursor/skills/structs-onboarding/SKILL.md – Correct timing, async strategy, D=8 recommendation.cursor/skills/structs-building/SKILL.md – Correct timing, async cross-reference.cursor/skills/structs-mining/SKILL.md – Multi-hour timing, pipeline strategy.cursor/skills/structs-combat/SKILL.md – Background raid compute, fleet lock noteawareness/game-loop.md – Async loop, pipeline tempo modeawareness/context-handoff.md – Job state in handoff templateawareness/continuity.md – Memory file list expandedplaybooks/phases/early-game.md – Reframed to 1-2 days, pipeline build orderplaybooks/phases/mid-game.md – Days/weeks timelineplaybooks/meta/tempo.md – Tempo through parallelism sectionAGENTS.md – Async-operations in awareness, timeline fix, rule #5llms.txt – Async-operations entry, corrected descriptionsscripts/generate-llms-full.sh – Added async-operations.mdllms-full.txt – Regeneratedawareness/index.md – Async-operations entryplaybooks/phases/index.md – Timeline fixreference/gameplay-index.md – Timeline fixAddressed 10 issues reported by an AI agent during first play session:
knowledge/entities/struct-types.md with DB-verified stats: ID, category, build difficulty, build/passive draw, max HP, and possible ambit.struct-build-compute (and mine-compute, refine-compute, raid-compute) are helpers that calculate the hash AND auto-submit the complete transaction. Documented across all skills and building mechanics.-D 5 for most operations. Added to building, mining, combat skills, and building mechanics.player-me replaced – All references replaced with structsd query structs address [address]. Note: player ID 1-0 means nonexistent.knowledge/mechanics/power.md. Documents cumulative load through onboarding build order, minimum viable capacity (~575 kW).player_id, planet_id, etc.) and generic id as an alias.id left entity-specific params undefined, causing crash in validateEntityId. Server now guards against undefined/null/non-string IDs.TOOLS.md with correct parameter names and examples for all 10 query tools..cursor/skills/structs-onboarding/SKILL.md – Rewrote: correct type IDs, address query, -D flag, timing, ambit encoding.cursor/skills/structs-building/SKILL.md – Compute/complete clarification, -D flag, build time table.cursor/skills/structs-mining/SKILL.md – Compute auto-complete, timing section.cursor/skills/structs-combat/SKILL.md – Raid compute auto-complete, -D flag, raid timing.cursor/skills/structs-reconnaissance/SKILL.md – Address query pattern, 1-0 noteknowledge/mechanics/building.md – Build process, -D flag, timing, ambit encoding sectionknowledge/entities/struct-types.md – Complete 22-type table, ambit encoding, combat statsknowledge/mechanics/power.md – New player power budget sectionTOOLS.md – Deployment, placeholders, MCP query parameter referenceknowledge/mechanics/combat.md with minimum damage edge caseknowledge/mechanics/combat.md counter-attack sectionknowledge/mechanics/combat.md algorithm descriptionknowledge/mechanics/combat.md edge casesknowledge/mechanics/combat.md edge casesseized_ore (numeric) field added to planet_raid tableschemas/entities/planet.md with planet_raid table schemaknowledge/mechanics/planet.md raid vulnerability sectionknowledge/mechanics/combat.md outcomes sectionknowledge/mechanics/building.md proof-of-work sectionMoveReadiness bug that erroneously checked for fleet-away statusknowledge/mechanics/fleet.md fleet movement sectiondestroyed_block field (v0.12.0-beta)
destroyed_block (bigint) added to struct table – records block height of destructionschemas/entities/struct.md with new fieldknowledge/mechanics/building.md StructSweepDelay notedestroyed field: DB column is actually is_destroyed (boolean)ProviderGuildAccessRecord (v0.12.0-beta)
providerId, guildIdschemas/entities/provider.md*_context.go files for all entity typesstruct.destroyed_block (bigint) – block height of destruction (2026-02-07)planet_raid.seized_ore (numeric) – ore seized during raids (2026-02-21)struct_health added to grass_category enum for planet activity events (2026-01-15)handle_event_struct_defender_clear cache function (2026-01-11)player_address_cascade trigger on player table for onboarding (2026-02-23)view.work zero-block fix (2026-01-19)schemas/database-schema.md for complete migration logschemas/database-schema.md – v0.10.0-v0.13.0 changelog, database schemas overview, verified table/view/trigger definitionsschemas/entities/struct.md – destroyed_block field, corrected is_destroyed column name, updated verificationschemas/entities/planet.md – planet view fields, planet_raid table, seized_ore, updated verificationschemas/entities/provider.md – ProviderGuildAccessRecordknowledge/mechanics/combat.md – minimum damage, counter-attack fixes, seizedOre, health results, edge casesknowledge/mechanics/fleet.md – movement readiness fix, populated planet fixknowledge/mechanics/building.md – open hashing, destroyed_block in sweep delayknowledge/mechanics/planet.md – seized ore tracking in raids.cursor/skills/structs-combat/SKILL.md – combat notes, verification updatesstruct_defender_clear to streaming event typesactivateCharge = 1 for all struct types in genesisschemas/game-state.md with permission bit documentationschemas/game-state.md#/definitions/Permission for detailsattackerRetreated (v0.8.0-beta)
attackerRetreated status to raid outcome enum in schemas/gameplay.mdapi/streaming/event-schemas.md to include attackerRetreated in PlanetRaidStatusEventprotocols/gameplay-protocol.mdexamples/gameplay-combat-bot.md to handle attackerRetreated statusschemas/entities/reactor.mdactive, undelegating, migratingschemas/economics.md with reactor staking sectionreference/entity-index.md with staking informationMsgReactorInfuse to handle validation delegationMsgReactorDefuse to handle validation undelegationMsgReactorBeginMigration action for redelegationMsgReactorCancelDefusion action to cancel undelegationschemas/actions.mdprotocols/economic-protocol.mdexamples/economic-bot.mdlifecycles/struct-lifecycle.mdschemas/gameplay.mdlifecycles/fleet-lifecycle.md with bug fix documentationprotocols/economic-protocol.md with membership join improvementsschemas/errors.md and troubleshooting/common-issues.mdschemas/errors.md and troubleshooting/common-issues.mdschemas/errors.md and troubleshooting/common-issues.mdAGENTS.md version and last updated dateDOCUMENTATION_INDEX.md version and last updated datereference/action-quick-reference.md with new actionsreference/action-quick-reference.md with reactor staking actionsreference/entity-index.md with Hash permission informationexamples/gameplay-combat-bot.md with attackerRetreated handlingexamples/economic-bot.mdtroubleshooting/common-issues.mdschemas/errors.md with v0.8.0-beta resolved bugs metadataschemas/database-schema.md documenting PostgreSQL schema changesschemas/database-schema.md for complete database change logdestroyed column to struct table (2025-12-29)schemas/entities/struct.md with destroyed fieldcheatsheet_details column (2025-11-29)cheatsheet_extended_details column (2025-12-02)schemas/entities/struct-type.md with database change metadatapermission_hash level to permission view (2025-12-18)schemas/game-state.md: Added Hash permission bit (64) documentationschemas/gameplay.md: Added attackerRetreated status, StructSweepDelay constantschemas/entities/reactor.md: Added staking fields and delegation propertiesschemas/entities.md: Updated Permission entity with Hash permission infoschemas/entities/struct.md: Added destroyed field, updated version to 1.1.0schemas/entities/struct-type.md: Added database change metadata, updated version to 1.1.0schemas/actions.md: Updated Reactor Infuse/Defuse, added Begin Migration/Cancel Defusionschemas/economics.md: Added reactor staking sectionschemas/errors.md: Added v0.8.0-beta resolved bugs metadataschemas/database-schema.md: New file documenting PostgreSQL schema changesprotocols/gameplay-protocol.md: Added attackerRetreated status documentationprotocols/economic-protocol.md: Added reactor staking and validation delegation sectionslifecycles/struct-lifecycle.md: Documented StructSweepDelaylifecycles/fleet-lifecycle.md: Documented fleet movement improvementsFor detailed information about each change, see the relevant documentation files.