feat: expand profiles and weapon configuration
Validate and deploy production / validate (push) Successful in 26s
Validate and deploy staging / validate (push) Successful in 25s
Validate and deploy production / deploy (push) Failing after 1m10s
Validate and deploy staging / deploy (push) Failing after 8s

This commit is contained in:
JB
2026-07-28 00:11:40 -04:00
parent 0b3be3587b
commit a434cbe60c
37 changed files with 2209 additions and 800 deletions
+132 -39
View File
@@ -389,9 +389,13 @@ direct URL. Do not present authentication as a way around a disabled section.
### Agent and authentication surfaces
- Account pages should read as an agent dossier: identity and access at the top,
activity metrics beside it, archives in the primary column, and security
controls in a narrower console column.
- The canonical signed-in account surface is the owner’s public Agent profile at
`/agents/{slug}`. `/account` is a compatibility route that redirects there;
the full notification inbox remains at `/account/notifications`.
- Owners see the same dossier and conversation that visitors see, plus inline
bio editing and a compact Account Control widget in the right rail. Do not
create a separate profile-editing dashboard or remove community context while
the owner manages their profile.
- Dense account consoles use a tabbed control surface for profile, credentials,
linked identities, and account lifecycle actions. Only one panel is shown at
a time; validation failures reopen the panel containing the failed action.
@@ -446,8 +450,10 @@ direct URL. Do not present authentication as a way around a disabled section.
- ISAC user dossiers reuse the same linked-identity node. Administrative
unlinking requires a scoped identity-management capability, produces an audit
event, and must never remove the user's only available sign-in method.
- On small screens, the split frame becomes a single column and account controls
move before archival content.
- On small screens, the split frame becomes one column. Show the public dossier
and archives first, followed by Account Control, notifications, and Recent
Discussion. Place Profile Messages at the bottom. Give owners a mobile-only
header link to Account Control.
- Public display names and private login usernames are distinct. Display names
support normalized Unicode and relaxed visible characters. They are unique
under the product's normalized identity key and generate readable,
@@ -458,38 +464,89 @@ direct URL. Do not present authentication as a way around a disabled section.
### Public Agent profiles
Public Agent profiles are community dossiers, not account-control screens. Lead
with the shared `AgentIdentityLink` in its large state: circular portrait,
display name, explicit `SHD.BUILD AGENT PROFILE` context, and a directional
link cue. Place assigned site-role badges beneath the identity as a labeled
semantic list. Show role names only, in alphabetical order, and omit the list
when the Agent has no assigned roles. Badges use the shared raised surface,
explicit role text, and a small orange diamond; they wrap without truncating
long or multiple role names. Never expose role descriptions, permissions,
direct grants, or access scopes on public profiles. The profile owner may
receive an `EDIT MY PROFILE` action in the header. Keep public content totals
in a compact telemetry strip below the identity header, then place the field
bio, public builds, published guides, and recent discussion in the primary
column. Profile messages occupy the narrower communications column and may
remain sticky where the viewport has room.
Public Agent profiles are community dossiers. The owner view extends the same
page with account controls without changing its public hierarchy. Lead with the
shared `AgentIdentityLink` in its large state: circular portrait, display name,
and assigned role badges. Place role badges to the right of the display name on
desktop and below the name on mobile. Show role names only, in alphabetical
order, and omit the list when the Agent has no assigned roles. Badges use the
shared raised surface, explicit role text, and a small orange
diamond; they wrap without truncating long or multiple role names. Never expose
role descriptions, permissions, direct grants, or access scopes on public
profiles. The owner header contains the visibility switch, its information
control, and a mobile-only Account Control link. Present the primary identity
and its actions directly on the page canvas
without a card surface, border, or decorative accent rule. Give the identity and
actions content-sized responsive tracks so long names, multiple roles, and
mobile actions cannot overlap the public content totals. Keep those totals in a
compact telemetry strip below the identity header. Use four columns on desktop
and two columns on mobile. Place the field bio in the primary column and keep
its mobile Edit Bio action compact within the section header. Put Public Builds
and Published Guides side by side directly
beneath the bio; stack them on narrow screens. Their cards stay within their own
half of the primary column. Profile Messages follow the archive pair within the
same column and must not inherit height from the right rail.
Recent Discussion occupies the narrower activity rail. Owner-only Account
Control and notification-preview widgets appear above it. The profile preview
shows unread notifications only; the full inbox retains notification history.
Recent-discussion
entries use compact destination cards because each entry links to content
elsewhere on the site. Show only the discussion type, destination title, comment
date, and open action; do not repeat the message body in this rail. Reset nested
card headers to content height and align the destination identity with its date;
do not inherit the application header's fixed height or surface treatment.
Profile messages continue directly
beneath the biography in the primary column so the conversation begins without
dead space.
Use `AgentIdentityLink` for author attribution on builds, guides, comments, and
other community records. Its compact and default states combine the circular
portrait, public display name, optional contextual metadata, and a clear link
cue. Hover and focus-visible states may turn the name and cue orange. The
portrait remains circular at every size; selectors may use square tactical
thumbnails only where the avatar rules explicitly allow them.
portrait, public display name, assigned public role badges, and optional
contextual metadata. Role badges remain beside the display name in comment
headers and other author attributions; an empty role list renders no badge. The
display name supplies the link affordance through its hover and focus-visible
states; do not add a trailing arrow. Use the primary orange token for the
portrait border, with a two-pixel edge that remains legible against the page
canvas. The default author portrait is 44 pixels; compact identities may use 30
pixels. The portrait remains circular at every size; selectors may use square
tactical thumbnails only where the avatar rules explicitly allow them.
Public-profile links use the stored readable slug, URL-encoded as one path
segment. A display-name change updates the canonical slug. Legacy UUID routes
remain valid and redirect to the canonical address; UUIDs remain the internal
identity for mutations, relationships, and audit evidence.
Public biographies and community comments use the shared `MarkdownEditor` and
`MarkdownContent` pair. The editor supplies a small formatting toolbar,
remaining-character count, concise help, a readable editorial typeface, and a
minimum 44px touch target for toolbar actions on narrow screens. It supports
headings, lists, quotes, links, emphasis, and inline code. Raw HTML is escaped.
Public biographies use the shared `MarkdownEditor` and `MarkdownContent` pair.
The editor supplies formatting controls, a remaining-character count, concise
help, and a readable editorial typeface. Profile messages and replies use the
compact `CommentComposer`: one textarea, a Markdown notice, a character count,
and submit or cancel actions. Rendered Markdown supports headings, lists,
quotes, links, bold, italics, and inline code. Load the required editorial font
weights and italic face because the global type system disables synthetic font
styles. Raw HTML is escaped.
Profile conversations begin with a collapsed `LEAVE A MESSAGE` action. A reply
opens the same editor beneath the selected message, and only one editor remains
open. Comments sit on the page canvas without cards, section surfaces, or
detached author headers. Align each body and action row with the username rather
than the avatar gutter. Keep Reply visible below the message. Place Follow or
Unfollow, Report, and the author-only Remove action in a shared ellipsis menu
beside Reply. The menu uses a 44-pixel trigger, returns focus when
closed, supports Escape and directional-key navigation, and becomes a fixed
bottom panel on narrow screens. Keep destructive actions neutral at rest and use
the danger color on hover or keyboard focus. Render conversations
in depth-first reading order: newest root conversations first and each branch
oldest-first. Use one-pixel guide lines and restrained indentation for replies,
then cap visual indentation on narrow screens while retaining the logical
parent chain. If an author or moderator removes a message that has replies, show
a bodyless `MESSAGE REMOVED` placeholder so readers can follow the remaining
conversation. Following applies to the top-level conversation and sends inbox
notifications for visible descendant replies, excluding the reply author and
any recipient already receiving the direct-reply notification. Send reply
notifications to the direct parent author and link to the specific reply.
Recent-discussion links target the exact comment anchor instead of the
containing profile or content page.
Public user-generated content uses the shared `ContentReport` control when the
viewer is authenticated and does not own the content. Keep the control visually
@@ -538,8 +595,10 @@ record is absent without implying an error.
Profile visibility is an explicit public or hidden account setting. A hidden
profile is excluded from public discovery and cannot receive new profile
messages. Hiding it does not remove the Agent's display name or portrait from
public builds, guides, or comments they authored. State this consequence beside
the visibility control so the setting does not imply retroactive anonymity.
public builds, guides, or comments they authored. Put the compact textual
`PUBLIC` or `HIDDEN` switch in the owner’s identity header and explain the
consequence in an adjacent information popover. Display-name restrictions use
the same popover pattern instead of persistent instructional copy.
Community forms use `PendingForm` to block duplicate submissions. Pending
actions retain their label context, validation errors preserve entered text,
@@ -808,8 +867,10 @@ Repository agents and contributors should follow the maintenance checklist in
### Agent avatars
Agent portraits use a circular crop in identity headers and square tactical
thumbnails in selectors. Preset choices appear in a compact four-column grid;
the active choice uses the orange action border and an explicit pressed state.
thumbnails in selectors. Account Control shows the current portrait first and
keeps preset and upload controls behind an explicit Edit Avatar action. Preset
choices appear in a compact four-column grid; the active choice uses the orange
action border and an explicit pressed state.
Custom images are normalized server-side to a metadata-free 256 × 256 WebP.
Selectors must retain visible hover, focus-visible, pressed, pending, and
disabled states, and collapse naturally with their containing account console.
@@ -826,13 +887,12 @@ navigation links use the same height, typography, and interaction motion.
Complex progression definitions use a stacked control-surface editor: identity
and fixed values first, then parallel tier cards, mutually exclusive talent
pools, fixed base bonuses, and the augmentation sequence. Tier cards retain
pools, and the augmentation sequence. Tier cards retain
identical row ordering so values can be compared horizontally on wide screens
and stack without changing meaning on narrow screens. System-derived augment
steps appear as read-only numbered cells; editable effects use the shared
attribute/value row pattern. Exotic is a status layered onto a weapon family,
never a replacement for the family classification. Fixed base bonuses remain
visually separate from tactical augmentation effects. Exotic definitions add a
never a replacement for the family classification. Exotic definitions add a
dedicated exotic-only talent after the two standard talent pools; their sixth
augmentation cell communicates that this talent advances to Tier II.
The exotic talent is owned by exactly one exotic weapon and is authored inline
@@ -842,6 +902,14 @@ Tier I/II previews, and the shared source-owned mechanic program editor. The Tal
Registry may display an owned exotic talent for discovery, but routes editing
back to its weapon rather than opening the shared-talent editor.
Place shared weapon-category bonuses above the weapon registry in one collapsed
profile console. Its six category buttons show the three inherited Attribute
values and open one category editor. The editor keeps Attribute identities
fixed and exposes only their positive numeric values. Saving closes the editor;
validation preserves its values and error state. Standard and Exotic weapons
inherit the profile for their underlying Shotgun, Rifle, MMR, AR, LMG, or SMG
category. Do not repeat these controls inside individual weapon editors.
Large relationship sets use the searchable assignment control instead of
checkbox walls. It keeps assigned records visible as removable chips, filters
available records by identity, renders at most thirty results at once, and
@@ -1426,6 +1494,25 @@ large enough that scanning a dropdown is inefficient. The selected record,
pending-contribution state, keyboard focus, and remove interaction must remain
explicit in both modes.
Records with established visual identity may supply an optional square icon.
Standard assignment lists show it at 32 pixels in result rows and 24 pixels in
selected chips. An icon-first multiselect may use the `visual-grid` presentation
for a finite visual registry. Its compact tiles use a 38-pixel icon without
persistent tile text. Hover and keyboard focus reveal the record name, while
the accessible label includes the name and assignment state. The orange inset
edge marks selected tiles. Weapon Talent 1 and Talent 2 pools and the Backpack
and Body Armor talent pools use this grid. Use the shared missing-item artwork
when a record lacks an icon. Render the full eligible set without a search,
result-count row, item cap, or internal scroll region; the section header owns
the selected count. Reflow tiles without changing keyboard order.
Use the `toggle-grid` presentation for a small fixed registry whose text labels
are the primary recognition aid. Each 44-pixel-or-taller option uses checkbox
semantics and shows only the record name. The orange action edge marks the
selected state, and the accessible label includes that state. Weapon mod slot
selectors use this presentation so an operator can toggle each slot by clicking
its name. Keep all options visible and preserve DOM order as the grid reflows.
Every ISAC relationship to an Attribute uses `SearchableAssignment`; native
attribute dropdowns are not permitted because the registry is expected to
contain hundreds of records. Use full mode for primary editor sections and
@@ -1679,10 +1766,16 @@ persistence controls and shared-loadout columns stack vertically.
When compatibility depends on two independent dimensions, keep those
dimensions explicit rather than presenting a flattened list. Weapon
definitions configure their available Weapon Mod slots per tier. T0 requires
four distinct slots; T1 and T2 require five. Weapon Mod definitions then
configure one slot plus one or more compatible weapon categories. The UI and
validation must require both dimensions to match.
definitions configure one shared set of five Weapon Mod slots for T1 and T2.
T0 uses the same set minus one explicitly selected slot. A T2-native weapon
shows only its applicable shared-slot control, and tiers below the native tier
remain unavailable. Operators may save an unverified shared set or T0 exclusion
when they cannot inspect the weapon in-game. Mark an active weapon `CONFIG
REQUIRED` until every available tier has its full slot count, and keep verified
assignments editable. Reject unknown slot types and counts above the tier limit.
Weapon Mod definitions then configure one slot plus one or more compatible
weapon categories. The UI and validation must require both dimensions to match
once the weapon definition is complete.
Weapon Mod definitions use the shared segmented-choice control for the bounded
eight-slot vocabulary, with a full-width row on desktop and two columns on
+26 -3
View File
@@ -255,6 +255,26 @@ active Administrator. A later critical transition may alert again; repeated
scheduler runs within the same episode do not. Provider errors preserve the
last known balance and never expose the API key or raw response body.
# Weapon category bonuses
`weapon_category_attribute_bonuses` stores three ordered fixed Attribute
contributions for each Shotgun, Rifle, MMR, AR, LMG, and SMG category. Each
profile grants 5% Weapon Critical Hit Chance and 50% Weapon Critical Hit Damage.
Shotgun, Rifle, AR, LMG, and SMG grant 40% Headshot Damage; MMR grants 70%.
Weapon records do not own copies of these rows. Both builder catalog loaders
attach the matching category profile when they hydrate a weapon. Exotic weapons
retain an underlying category and inherit the same profile as a standard weapon
of that type. The combat summary preserves the existing equipped-weapon
semantics: each equipped weapon contributes its inherited profile to the
Agent's accumulated Attributes.
ISAC exposes one category-profile editor above the weapon registry. Operators
may change the three positive values, while the Attribute identities and order
remain fixed. Each successful save appends a
`game_data/weapon_bonus_profile.updated` audit event with the complete previous
and resulting profile.
# Weapon-owned exotic talents
Standard weapon talent pools remain reusable across weapons and use Talent 1 /
@@ -291,9 +311,12 @@ the existing `game_data` audit history.
### Weapon Mods and tiered weapon slots
`weapon_mod_slots` records each weapon's available slot vocabulary per tier.
Canonical validation requires four unique slots for T0 and five for T1/T2 for
every tier at or above the weapon's native tier. Regular Weapon Mods declare a
single slot type and one or more compatible base weapon categories through
The editor captures one shared set for T1/T2 and the single shared slot omitted
at T0, then expands that input into the normalized per-tier rows. Operators may
save partial rows when the in-game configuration is unavailable. ISAC derives
`CONFIG REQUIRED` until every available tier contains four unique slots at T0
or five at T1/T2. Regular Weapon Mods declare a single slot type and one or more
compatible base weapon categories through
`weapon_mod_compatible_categories`; eligibility requires both a category match
and the slot to exist on the equipped weapon at its selected tier.