Compare commits
3
Commits
main
..
904cb073a2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
904cb073a2 | ||
|
|
fe06b90117 | ||
|
|
e5213248a8 |
+1
-2
@@ -44,5 +44,4 @@ __pycache__/
|
|||||||
*.py[cod]
|
*.py[cod]
|
||||||
|
|
||||||
.pi
|
.pi
|
||||||
.mesh
|
.mesh
|
||||||
.worktrees/
|
|
||||||
@@ -69,27 +69,11 @@ The `.agents/skills/` directory contains repo-specific skill files. Key skills:
|
|||||||
|
|
||||||
Use `skill` tool to load one when the task matches.
|
Use `skill` tool to load one when the task matches.
|
||||||
|
|
||||||
## Agent skills
|
|
||||||
|
|
||||||
### Issue tracker
|
|
||||||
|
|
||||||
Track issues in this repository's Gitea Issues using `tea`. See
|
|
||||||
`docs/agents/issue-tracker.md`.
|
|
||||||
|
|
||||||
### Triage labels
|
|
||||||
|
|
||||||
Use the five canonical triage labels without overrides. See
|
|
||||||
`docs/agents/triage-labels.md`.
|
|
||||||
|
|
||||||
### Domain docs
|
|
||||||
|
|
||||||
Use the single-context domain documentation layout. See `docs/agents/domain.md`.
|
|
||||||
|
|
||||||
## Verify commands
|
## Verify commands
|
||||||
|
|
||||||
Run in order after source changes:
|
Run in order after source changes:
|
||||||
|
|
||||||
```bash
|
```
|
||||||
npm run check # svelte-kit sync + svelte-check (typecheck)
|
npm run check # svelte-kit sync + svelte-check (typecheck)
|
||||||
npm run build # secretless Vite production build
|
npm run build # secretless Vite production build
|
||||||
```
|
```
|
||||||
|
|||||||
-271
@@ -1,271 +0,0 @@
|
|||||||
# SHD.build Domain
|
|
||||||
|
|
||||||
SHD.build is an independent community intelligence platform for _The Division
|
|
||||||
Resurgence_. This glossary defines the language used for player planning, shared
|
|
||||||
content, Game Data, governance, equipment, progression, and modeled mechanics.
|
|
||||||
|
|
||||||
## Product and people
|
|
||||||
|
|
||||||
**SHD.build**: The community platform described by this glossary. Always
|
|
||||||
capitalize `SHD` and write the product name as `SHD.build`. _Avoid_: SHD Build,
|
|
||||||
SHD Builder
|
|
||||||
|
|
||||||
**Agent**: Any person using SHD.build, whether anonymous or authenticated.
|
|
||||||
_Avoid_: User, visitor, player when referring to product access
|
|
||||||
|
|
||||||
**Anonymous Agent**: An Agent who is not signed in to SHD.build. _Avoid_:
|
|
||||||
Visitor, guest
|
|
||||||
|
|
||||||
**Registered Agent**: An Agent with an SHD.build account. _Avoid_: Registered
|
|
||||||
user, member
|
|
||||||
|
|
||||||
**Modeling Session**: An interactive agentic work session that prepares one
|
|
||||||
Mechanic Program at a time for a Registered Agent to confirm in chat before the
|
|
||||||
session submits it through an existing ISAC action. _Avoid_: Agent, Modeling
|
|
||||||
Client, bulk job
|
|
||||||
|
|
||||||
**Contributor**: A Registered Agent who has accepted the contributor guidelines
|
|
||||||
and may submit proposed Game Data changes for review. _Avoid_: Editor when the
|
|
||||||
Agent cannot change Canonical Game Data directly
|
|
||||||
|
|
||||||
**Operator**: A Registered Agent performing an authorized task in ISAC.
|
|
||||||
Contributor, reviewer, moderator, and administrator authority remain distinct
|
|
||||||
from this situational term. _Avoid_: Admin as a generic name for anyone using
|
|
||||||
ISAC
|
|
||||||
|
|
||||||
**Oversight**: The human review function for proposed Game Data, moderated
|
|
||||||
Community Content, and identity assets. Use the qualified names Data Oversight,
|
|
||||||
Community Oversight, Guide Oversight, and Avatar Oversight when the review area
|
|
||||||
matters. _Avoid_: Moderation as a name for every review function
|
|
||||||
|
|
||||||
## Planning and shared content
|
|
||||||
|
|
||||||
**Builder**: The planning tool an Agent uses to configure a Loadout and inspect
|
|
||||||
supported calculations. _Avoid_: Build when referring to the tool
|
|
||||||
|
|
||||||
**Loadout**: A complete planned character configuration, including selected
|
|
||||||
Equipment, progression choices, and combat assumptions. A Loadout may exist
|
|
||||||
without becoming a saved Build. _Avoid_: Build when persistence, ownership, or
|
|
||||||
sharing matters
|
|
||||||
|
|
||||||
**Loadout Draft**: An editable Loadout that has not become a saved Build.
|
|
||||||
Anonymous and Registered Agents may both work with drafts. _Avoid_: Build draft
|
|
||||||
|
|
||||||
**Build**: A saved, owned, and shareable planning artifact whose central content
|
|
||||||
is a Loadout. A Build may be Private, Unlisted, or Public and may derive from
|
|
||||||
another Build. _Avoid_: Loadout when persistence, ownership, or sharing matters
|
|
||||||
|
|
||||||
**Guide**: A revisioned long-form community article that may include snapshots
|
|
||||||
of one or more Builds. A Guide is prose-led content rather than a Loadout
|
|
||||||
container. _Avoid_: Build guide when referring to every Guide
|
|
||||||
|
|
||||||
**News Article**: A revisioned editorial or syndicated article published through
|
|
||||||
the News channel. _Avoid_: Guide, post
|
|
||||||
|
|
||||||
**Article Revision**: An immutable edition of a Guide or News Article. Editors
|
|
||||||
select one revision for publication while later revisions may await review.
|
|
||||||
_Avoid_: Version when referring to published article history
|
|
||||||
|
|
||||||
**Community Content**: Agent-authored comments, profile biographies, custom
|
|
||||||
avatars, and Guides governed by the shared moderation lifecycle. _Avoid_:
|
|
||||||
User-generated content, UGC
|
|
||||||
|
|
||||||
**Community Note**: A visible comment that Community Oversight pins to a Public
|
|
||||||
Database discussion. It remains Community Content and follows the same removal
|
|
||||||
rules as other comments. _Avoid_: Official correction, staff note
|
|
||||||
|
|
||||||
**Content Report**: An Agent's request for Oversight to review visible Community
|
|
||||||
Content, with no immediate change to the content's visibility. _Avoid_: Takedown
|
|
||||||
request
|
|
||||||
|
|
||||||
**Public Database**: The Agent-facing reference view of Canonical Game Data.
|
|
||||||
_Avoid_: Database when the term could mean application storage
|
|
||||||
|
|
||||||
## Game Data and governance
|
|
||||||
|
|
||||||
**Game Data**: Community-maintained structured facts about _The Division
|
|
||||||
Resurgence_ used by the Public Database, Builder, Builds, and contribution
|
|
||||||
workflow. _Avoid_: Source data, builder data, reference data
|
|
||||||
|
|
||||||
**Canonical Game Data**: The authoritative, approved body of Game Data. _Avoid_:
|
|
||||||
Live data, production data
|
|
||||||
|
|
||||||
**Canonical Record**: One authoritative record within Canonical Game Data.
|
|
||||||
_Avoid_: Approved proposal
|
|
||||||
|
|
||||||
**Contribution Proposal**: A pending request from a Contributor to create or
|
|
||||||
change Canonical Game Data. Approval still requires the proposed change to
|
|
||||||
satisfy the canonical rules for its record family. _Avoid_: Draft record,
|
|
||||||
pending record
|
|
||||||
|
|
||||||
**ISAC**: The operational console for Game Data, contribution review, community
|
|
||||||
governance, identity and access management, audit history, and system
|
|
||||||
operations. _Avoid_: Admin panel, calculation engine
|
|
||||||
|
|
||||||
**Registry**: An ISAC workspace containing one family of related records and its
|
|
||||||
management controls. _Avoid_: Table, list page
|
|
||||||
|
|
||||||
**Audit Event**: An immutable account of a consequential operation or review
|
|
||||||
decision, including the actor, target, and change evidence. _Avoid_: Audit-log
|
|
||||||
row, activity log
|
|
||||||
|
|
||||||
**Compensating Reversion**: A new operation that restores an earlier state while
|
|
||||||
preserving the original Audit Event and recording the reversal. _Avoid_:
|
|
||||||
Rollback, undo when either implies rewriting history
|
|
||||||
|
|
||||||
## Equipment and progression
|
|
||||||
|
|
||||||
**Equipment**: The items and enhancements selected for a Loadout, including
|
|
||||||
Weapons, Gear, Weapon Mods, Gear Mods, Skill Chips, and an OS Protocol. _Avoid_:
|
|
||||||
Item when the equipment relationship matters
|
|
||||||
|
|
||||||
**Gear**: Equippable protective equipment assigned to a character slot. Gear may
|
|
||||||
provide core values, Attributes, a Brand Set, a Talent, and augmentation
|
|
||||||
capacity. _Avoid_: Armor as a collective name for all Gear
|
|
||||||
|
|
||||||
**Body Armor**: The canonical name for the equippable torso Gear slot. _Avoid_:
|
|
||||||
Vest
|
|
||||||
|
|
||||||
**Weapon**: An equippable firearm with a Weapon Category, damage and handling
|
|
||||||
properties, progression values, and applicable Talents and Mods. _Avoid_: Gun
|
|
||||||
when referring to the modeled record
|
|
||||||
|
|
||||||
**Weapon Category**: The classification that groups Weapons as Shotgun, Rifle,
|
|
||||||
MMR, AR, LMG, or SMG. _Avoid_: Weapon type, weapon family
|
|
||||||
|
|
||||||
**Weapon Mod**: An enhancement fitted to a compatible Weapon slot. Regular and
|
|
||||||
Exotic Weapon Mods follow different selection rules. _Avoid_: Attachment
|
|
||||||
|
|
||||||
**Gear Mod**: An enhancement fitted to Gear according to the Gear's available
|
|
||||||
mod capacity. _Avoid_: Tactical Augment
|
|
||||||
|
|
||||||
**Tactical Augment**: A numbered augmentation position recorded on selected Gear
|
|
||||||
in a Loadout. _Avoid_: Gear Mod
|
|
||||||
|
|
||||||
**Attribute**: A named measurable game property with defined units and
|
|
||||||
calculation meaning. _Avoid_: Stat when referring to the canonical Attribute
|
|
||||||
catalog
|
|
||||||
|
|
||||||
**Core Attribute**: One of the three primary character alignments: Firepower,
|
|
||||||
Toughness, or Engineering. _Avoid_: Main stat, primary stat
|
|
||||||
|
|
||||||
**Brand Set**: A Gear identity whose bonuses depend on how many pieces from that
|
|
||||||
set the Loadout equips. _Avoid_: Gear set
|
|
||||||
|
|
||||||
**Quality**: The item classification Standard, Specialized, Superior, or
|
|
||||||
High-end. Quality governs available or scaled properties for applicable
|
|
||||||
Equipment. _Avoid_: Rarity
|
|
||||||
|
|
||||||
**Exotic**: A special scope used by certain Weapons, Talents, and Weapon Mods.
|
|
||||||
Exotic is not a fifth Quality. _Avoid_: Exotic quality
|
|
||||||
|
|
||||||
**Item Level**: An Equipment progression coordinate used to resolve
|
|
||||||
level-dependent values. _Avoid_: Tier, Quality
|
|
||||||
|
|
||||||
**Equipment Tier**: The T0, T1, or T2 progression band that controls Equipment
|
|
||||||
capabilities and values. _Avoid_: Talent Tier, Item Level
|
|
||||||
|
|
||||||
**Talent Tier**: The Tier I or Tier II value variant of a Talent. _Avoid_:
|
|
||||||
Equipment Tier, T1, T2 when the distinction could be unclear
|
|
||||||
|
|
||||||
**Reference Level**: The Item Level at which an observed value or range applies.
|
|
||||||
_Avoid_: Base level
|
|
||||||
|
|
||||||
**Hidden Base**: A level-independent value inferred from observed Equipment
|
|
||||||
values and the game's progression rules. _Avoid_: Displayed Value, Raw Value
|
|
||||||
|
|
||||||
**Raw Value**: A calculated value before the presentation rules that reproduce
|
|
||||||
the game's displayed number. _Avoid_: Hidden Base, Displayed Value
|
|
||||||
|
|
||||||
**Displayed Value**: The player-visible number produced after applying the
|
|
||||||
game's presentation rules to a Raw Value. _Avoid_: Raw Value
|
|
||||||
|
|
||||||
**OS Protocol**: A single equipped progression item with a Quality, Core
|
|
||||||
Attribute alignment, primary effect, inherited secondary profile, and
|
|
||||||
upgradeable Talent. _Avoid_: Protocol when the operating-system meaning could be
|
|
||||||
inferred
|
|
||||||
|
|
||||||
**Skill**: A selectable combat capability associated with a Specialization.
|
|
||||||
Skills may own Skill Chip Sets and may have explicit compatibility relationships
|
|
||||||
with another Skill. _Avoid_: Ability or Specialization Ability for the
|
|
||||||
selectable game concept
|
|
||||||
|
|
||||||
**Signature Skill**: A Specialization's defining Skill, distinguished from its
|
|
||||||
other selectable Skills. _Avoid_: Signature ability
|
|
||||||
|
|
||||||
**Skill Chip**: An Equipment selection that modifies the Skill occupying its
|
|
||||||
Loadout position. Skill Chips belong to a Skill Chip Set and may provide
|
|
||||||
primary, secondary, and set effects. _Avoid_: Chip when the equipment family is
|
|
||||||
unclear
|
|
||||||
|
|
||||||
**Skill Chip Set**: A reusable Skill Chip definition associated with a Skill,
|
|
||||||
including its set bonus and optional Talent. An explicit compatibility
|
|
||||||
relationship may let another Skill equip the set. _Avoid_: Skill set
|
|
||||||
|
|
||||||
**Specialization**: A character progression identity containing Focuses, Skills,
|
|
||||||
and progression choices. _Avoid_: Class
|
|
||||||
|
|
||||||
**Focus**: A path within a Specialization aligned to one Core Attribute and
|
|
||||||
defining a selection of Skills and progression choices. _Avoid_: Subclass,
|
|
||||||
specialization path
|
|
||||||
|
|
||||||
**Talent**: A named conditional behavior owned by its source, such as a Weapon,
|
|
||||||
Gear item, OS Protocol, or Skill Chip Set. Different Talent sources may use
|
|
||||||
different progression variants. _Avoid_: Perk, passive
|
|
||||||
|
|
||||||
## Modeled mechanics
|
|
||||||
|
|
||||||
**Mechanic Program**: The structured, source-owned description of a Talent or
|
|
||||||
other conditional behavior. It captures the conditions, state changes, and
|
|
||||||
outcomes needed to evaluate that behavior. _Avoid_: Script, Trigger record
|
|
||||||
|
|
||||||
**Event**: An observed occurrence on a combat timeline that a Mechanic Program
|
|
||||||
may inspect. _Avoid_: Trigger when referring to the occurrence itself
|
|
||||||
|
|
||||||
**Trigger Condition**: The criteria that an Event must satisfy before a mechanic
|
|
||||||
can proceed toward Activation. A Trigger Condition is part of a Mechanic
|
|
||||||
Program, not a standalone Game Data record. _Avoid_: Trigger as an entity
|
|
||||||
|
|
||||||
**Activation**: A successful mechanic occurrence after its Event, conditions,
|
|
||||||
chance, and Cooldown requirements resolve. _Avoid_: Proc when precision matters
|
|
||||||
|
|
||||||
**Cooldown**: The period after a successful Activation during which the same
|
|
||||||
mechanic cannot activate again. A failed chance does not begin the Cooldown.
|
|
||||||
_Avoid_: Delay
|
|
||||||
|
|
||||||
**Mechanic State**: A value retained across Events for one mechanic, such as a
|
|
||||||
flag, count, stack, duration, mark, or resource. _Avoid_: Runtime state when
|
|
||||||
discussing game behavior
|
|
||||||
|
|
||||||
**Outcome**: The effect emitted by an activated mechanic, such as an Attribute
|
|
||||||
change, damage, restoration, resource change, or marker. _Avoid_: Effect when
|
|
||||||
the source Talent and emitted result could be confused
|
|
||||||
|
|
||||||
**Combat Profile**: The encounter assumptions and observed rates used to project
|
|
||||||
a Loadout's combat performance. _Avoid_: Simulation when no event simulation
|
|
||||||
occurs
|
|
||||||
|
|
||||||
**Scenario Input**: An explicit encounter assumption required to evaluate a
|
|
||||||
mechanic whose result cannot be determined from the Loadout alone. _Avoid_:
|
|
||||||
Guess, default assumption
|
|
||||||
|
|
||||||
**Ready**: The mechanic readiness state indicating that typed Game Data can
|
|
||||||
evaluate the mechanic without additional Scenario Inputs. _Avoid_: Complete
|
|
||||||
|
|
||||||
**Requires Assumptions**: The mechanic readiness state indicating that
|
|
||||||
evaluation needs one or more explicit Scenario Inputs. _Avoid_: Ready,
|
|
||||||
unsupported
|
|
||||||
|
|
||||||
**Captured Only**: The mechanic readiness state indicating that SHD.build
|
|
||||||
preserves the authored behavior but cannot calculate it. _Avoid_: Unsupported
|
|
||||||
when the behavior has still been recorded
|
|
||||||
|
|
||||||
**Extra Health**: Temporary Health granted in addition to an Agent's normal
|
|
||||||
Health. Each grant remains distinct from later changes to the current Extra
|
|
||||||
Health total. _Avoid_: Health, healing, bonus armor
|
|
||||||
|
|
||||||
**Hit Taken**: A hit received by an Agent, including one absorbed by Extra
|
|
||||||
Health. A Hit Taken does not require normal Health loss. _Avoid_: Taking Damage
|
|
||||||
|
|
||||||
**Taking Damage**: A loss of an Agent's normal Health. A hit absorbed by Extra
|
|
||||||
Health does not count as Taking Damage. _Avoid_: Hit Taken
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
# Domain docs
|
|
||||||
|
|
||||||
Engineering skills must consult this repository's domain documentation before
|
|
||||||
exploring code.
|
|
||||||
|
|
||||||
## Read before exploring
|
|
||||||
|
|
||||||
- Read `CONTEXT.md` at the repository root.
|
|
||||||
- If `CONTEXT-MAP.md` exists, use it to find the `CONTEXT.md` files relevant to
|
|
||||||
the task.
|
|
||||||
- Read ADRs under `docs/adr/` that affect the area you will change. In a
|
|
||||||
multi-context repository, also check `src/<context>/docs/adr/`.
|
|
||||||
|
|
||||||
If these files do not exist, proceed without comment. Do not suggest creating
|
|
||||||
them before the project resolves domain terms or architectural decisions. The
|
|
||||||
`/domain-modeling` skill, reached through `/grill-with-docs` and
|
|
||||||
`/improve-codebase-architecture`, creates them when needed.
|
|
||||||
|
|
||||||
## File structure
|
|
||||||
|
|
||||||
This repository uses the single-context layout:
|
|
||||||
|
|
||||||
```text
|
|
||||||
/
|
|
||||||
├── CONTEXT.md
|
|
||||||
├── docs/adr/
|
|
||||||
│ ├── 0001-event-sourced-orders.md
|
|
||||||
│ └── 0002-postgres-for-write-model.md
|
|
||||||
└── src/
|
|
||||||
```
|
|
||||||
|
|
||||||
A repository with multiple bounded contexts can use this layout:
|
|
||||||
|
|
||||||
```text
|
|
||||||
/
|
|
||||||
├── CONTEXT-MAP.md
|
|
||||||
├── docs/adr/
|
|
||||||
└── src/
|
|
||||||
├── ordering/
|
|
||||||
│ ├── CONTEXT.md
|
|
||||||
│ └── docs/adr/
|
|
||||||
└── billing/
|
|
||||||
├── CONTEXT.md
|
|
||||||
└── docs/adr/
|
|
||||||
```
|
|
||||||
|
|
||||||
## Use glossary terms
|
|
||||||
|
|
||||||
Use the terms defined in `CONTEXT.md` in issue titles, refactor proposals,
|
|
||||||
hypotheses, and test names. Do not substitute synonyms that the glossary
|
|
||||||
rejects.
|
|
||||||
|
|
||||||
If a needed concept is absent, reconsider whether the project uses that concept.
|
|
||||||
If it represents a real gap, record it for `/domain-modeling`.
|
|
||||||
|
|
||||||
## Flag ADR conflicts
|
|
||||||
|
|
||||||
Call out any proposal that conflicts with an ADR:
|
|
||||||
|
|
||||||
> _Contradicts ADR-0007 (event-sourced orders), but worth reopening because…_
|
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
# Issue tracker: Gitea
|
|
||||||
|
|
||||||
Issues and specs for this repo live as Gitea issues. Use the
|
|
||||||
[`tea`](https://gitea.com/gitea/tea) CLI for all operations.
|
|
||||||
|
|
||||||
## Repository context
|
|
||||||
|
|
||||||
Run commands inside the clone so `tea` can infer the repository and login from
|
|
||||||
its Git remote. If the clone has multiple Gitea remotes or logins, pass
|
|
||||||
`--remote <name>` or `--login <name>`. Use `--repo <owner>/<repo>` only outside
|
|
||||||
the clone.
|
|
||||||
|
|
||||||
Before the first operation, verify the instance with
|
|
||||||
`tea logins list --output json`. If it is missing, ask the user to run
|
|
||||||
`tea login add`; never ask for or handle their access token.
|
|
||||||
|
|
||||||
## Conventions
|
|
||||||
|
|
||||||
- **Create an issue**: `tea issues create --title "..." --description "..."`.
|
|
||||||
For a multi-line body, use shell command substitution around a quoted heredoc:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
tea issues create --title "..." --description "$(cat <<'EOF'
|
|
||||||
Multi-line issue body.
|
|
||||||
EOF
|
|
||||||
)"
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Read an issue with comments**:
|
|
||||||
`tea issues <number> --comments --fields index,state,author,url,title,body,assignees,labels,comments --output json`.
|
|
||||||
- **List issues**:
|
|
||||||
`tea issues list --state open --fields index,state,author,url,title,body,assignees,labels,comments --output json`,
|
|
||||||
adding `--labels "label-one,label-two"`, `--assignee <user>`, or another
|
|
||||||
supported filter as needed. Paginate with `--page` and `--limit`; do not
|
|
||||||
assume the default first 30 results are complete.
|
|
||||||
- **Comment on an issue**: `tea comments add <number> --description "..."`.
|
|
||||||
- **Apply or remove labels**: `tea issues edit <number> --add-labels "..."` or
|
|
||||||
`--remove-labels "..."`. Separate multiple labels with commas.
|
|
||||||
- **Assign or unassign**: `tea issues edit <number> --add-assignees "..."` or
|
|
||||||
`--remove-assignees "..."`.
|
|
||||||
- **Close**: post the closing explanation with
|
|
||||||
`tea comments add <number> --description "..."`, then run
|
|
||||||
`tea issues close <number>`.
|
|
||||||
- **Reopen**: `tea issues reopen <number>`.
|
|
||||||
- **Raw API fallback**: use `tea api '<endpoint>'` only for a Gitea feature
|
|
||||||
without a first-class `tea` command. Prefer `{owner}` and `{repo}`
|
|
||||||
placeholders so repository context remains explicit.
|
|
||||||
|
|
||||||
Use `--output json` for machine-readable reads. Do not scrape table output.
|
|
||||||
|
|
||||||
## Pull requests as a triage surface
|
|
||||||
|
|
||||||
**PRs as a request surface: no.** _(Set this to `yes` if this repo treats
|
|
||||||
external pull requests as feature requests; `/triage` reads this flag.)_
|
|
||||||
|
|
||||||
When set to `yes`, PRs use the same labels and states as issues:
|
|
||||||
|
|
||||||
- **Read a PR with comments and diff**:
|
|
||||||
`tea pulls <number> --comments --fields index,state,author,url,title,body,diff,assignees,labels,comments --output json`.
|
|
||||||
- **List open PRs**:
|
|
||||||
`tea pulls list --state open --fields index,state,author,author-id,url,title,body,assignees,labels,comments --output json`.
|
|
||||||
Determine whether an author is external from the repository's Gitea membership
|
|
||||||
data; the PR listing does not classify author membership.
|
|
||||||
- **Comment**: `tea comments add <number> --description "..."`.
|
|
||||||
- **Apply or remove labels**: `tea pulls edit <number> --add-labels "..."` or
|
|
||||||
`--remove-labels "..."`.
|
|
||||||
- **Close**: `tea pulls close <number>`.
|
|
||||||
|
|
||||||
Gitea pull requests use the repository's issue index space, so `#42` may refer
|
|
||||||
to either surface. If the context is unclear, inspect it with
|
|
||||||
`tea pulls 42 --output json`; if that command reports no PR, read it with
|
|
||||||
`tea issues 42 --output json`.
|
|
||||||
|
|
||||||
## When a skill says "publish to the issue tracker"
|
|
||||||
|
|
||||||
Create a Gitea issue with `tea issues create`.
|
|
||||||
|
|
||||||
## When a skill says "fetch the relevant ticket"
|
|
||||||
|
|
||||||
Run
|
|
||||||
`tea issues <number> --comments --fields index,state,author,url,title,body,assignees,labels,comments --output json`.
|
|
||||||
|
|
||||||
## Wayfinding operations
|
|
||||||
|
|
||||||
`/wayfinder` uses one **map** issue with linked **child** issues. These
|
|
||||||
conventions store relationships in issue bodies, so they work across Gitea
|
|
||||||
versions.
|
|
||||||
|
|
||||||
- **Map**: create one issue labelled `wayfinder:map` containing the Notes,
|
|
||||||
Decisions-so-far, and Fog sections. Use
|
|
||||||
`tea issues create --labels "wayfinder:map"` with its title and description.
|
|
||||||
- **Child ticket**: start the body with `Part of #<map>` and apply a
|
|
||||||
`wayfinder:<type>` label: `research`, `prototype`, `grilling`, or `task`. Add
|
|
||||||
each child as a task-list item in the map body to preserve frontier order.
|
|
||||||
- **Blocking**: put `Blocked by: #<n>, #<n>` near the top of the child body. A
|
|
||||||
ticket becomes unblocked after every referenced blocker closes.
|
|
||||||
- **Frontier query**: list all open children, order them by the map's task list,
|
|
||||||
and discard tickets with an open blocker or an assignee. Select the first
|
|
||||||
remaining ticket. Fetch each referenced blocker; do not infer its state from
|
|
||||||
map text.
|
|
||||||
- **Claim**: resolve the active username with `tea whoami`, then run
|
|
||||||
`tea issues edit <n> --add-assignees "<username>"` as the session's first
|
|
||||||
write. Do not assume `@me` works.
|
|
||||||
- **Resolve**: run `tea comments add <n> --description "<answer>"`, close the
|
|
||||||
child with `tea issues close <n>`, then append a context pointer and link to
|
|
||||||
the map's Decisions-so-far section.
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
# Triage labels
|
|
||||||
|
|
||||||
Engineering skills use five canonical triage roles. This table maps each role to
|
|
||||||
the label string in this repository's issue tracker.
|
|
||||||
|
|
||||||
| Canonical role | Tracker label | Meaning |
|
|
||||||
| ----------------- | ----------------- | -------------------------------------- |
|
|
||||||
| `needs-triage` | `needs-triage` | A maintainer must evaluate the issue |
|
|
||||||
| `needs-info` | `needs-info` | Waiting for more information |
|
|
||||||
| `ready-for-agent` | `ready-for-agent` | Fully specified and ready for an agent |
|
|
||||||
| `ready-for-human` | `ready-for-human` | Requires human implementation |
|
|
||||||
| `wontfix` | `wontfix` | Maintainers will not act on the issue |
|
|
||||||
|
|
||||||
When a skill names a canonical role, use the corresponding tracker label.
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { dev } from '$app/environment';
|
||||||
import { json, type Handle, type HandleServerError } from '@sveltejs/kit';
|
import { json, type Handle, type HandleServerError } from '@sveltejs/kit';
|
||||||
import { stringify } from 'devalue';
|
import { stringify } from 'devalue';
|
||||||
import { randomUUID } from 'node:crypto';
|
import { randomUUID } from 'node:crypto';
|
||||||
@@ -15,6 +16,15 @@ import {
|
|||||||
} from '$lib/server/data-moderation';
|
} from '$lib/server/data-moderation';
|
||||||
|
|
||||||
export const handle: Handle = async ({ event, resolve }) => {
|
export const handle: Handle = async ({ event, resolve }) => {
|
||||||
|
// THROWAWAY PROTOTYPE: fixture-only review must not open the shared database.
|
||||||
|
if (
|
||||||
|
dev &&
|
||||||
|
event.url.pathname === '/database' &&
|
||||||
|
event.url.searchParams.get('prototype') === 'model-status'
|
||||||
|
) {
|
||||||
|
return resolve(event);
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
event.url.pathname === '/admin' ||
|
event.url.pathname === '/admin' ||
|
||||||
event.url.pathname.startsWith('/admin/')
|
event.url.pathname.startsWith('/admin/')
|
||||||
|
|||||||
@@ -1,10 +1,26 @@
|
|||||||
|
import { dev } from '$app/environment';
|
||||||
import { getSessionUser } from '$lib/server/auth/session';
|
import { getSessionUser } from '$lib/server/auth/session';
|
||||||
import { hasPermission } from '$lib/server/auth/authorization';
|
import { hasPermission } from '$lib/server/auth/authorization';
|
||||||
import type { LayoutServerLoad } from './$types';
|
import type { LayoutServerLoad } from './$types';
|
||||||
import { notificationSummary } from '$lib/server/notifications';
|
import { notificationSummary } from '$lib/server/notifications';
|
||||||
import { getSiteAccessSettings } from '$lib/server/site-access';
|
import { getSiteAccessSettings } from '$lib/server/site-access';
|
||||||
|
|
||||||
export const load: LayoutServerLoad = async ({ cookies }) => {
|
export const load: LayoutServerLoad = async ({ cookies, url }) => {
|
||||||
|
// THROWAWAY PROTOTYPE: fixture-only review must not open the shared database.
|
||||||
|
if (dev && url.pathname === '/database' && url.searchParams.get('prototype') === 'model-status') {
|
||||||
|
return {
|
||||||
|
user: null,
|
||||||
|
isacAccess: false,
|
||||||
|
notifications: { unread: 0 },
|
||||||
|
siteAccess: {
|
||||||
|
comingSoonEnabled: false,
|
||||||
|
accountCreationEnabled: true,
|
||||||
|
sections: { news: true, database: true, builds: true, guides: true, builder: true },
|
||||||
|
updatedAt: 'prototype'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const user = await getSessionUser(cookies);
|
const user = await getSessionUser(cookies);
|
||||||
return {
|
return {
|
||||||
user,
|
user,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { dev } from '$app/environment';
|
||||||
import { getDatabase } from '$lib/server/database';
|
import { getDatabase } from '$lib/server/database';
|
||||||
import { getRegistrySearch } from '$lib/server/pagination';
|
import { getRegistrySearch } from '$lib/server/pagination';
|
||||||
import { databaseCategories } from '$lib/database/categories';
|
import { databaseCategories } from '$lib/database/categories';
|
||||||
@@ -16,6 +17,11 @@ const tables = {
|
|||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export const load: PageServerLoad = async ({ url }) => {
|
export const load: PageServerLoad = async ({ url }) => {
|
||||||
|
// THROWAWAY PROTOTYPE: avoid opening the shared database for fixture-only review.
|
||||||
|
if (dev && url.searchParams.get('prototype') === 'model-status') {
|
||||||
|
return { registries: [], total: 0, search: '', searchResults: [] };
|
||||||
|
}
|
||||||
|
|
||||||
const database = await getDatabase();
|
const database = await getDatabase();
|
||||||
const { search, pattern } = getRegistrySearch(url);
|
const { search, pattern } = getRegistrySearch(url);
|
||||||
const counts = await Promise.all(
|
const counts = await Promise.all(
|
||||||
|
|||||||
@@ -1,6 +1,16 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { dev } from '$app/environment';
|
||||||
|
import { page } from '$app/state';
|
||||||
|
import ModelStatusPrototype from './ModelStatusPrototype.prototype.svelte';
|
||||||
|
import type { PrototypeVariant } from './model-status.prototype';
|
||||||
|
|
||||||
let { data } = $props();
|
let { data } = $props();
|
||||||
const onlineRegistries = $derived(data.registries.filter((registry) => registry.count > 0).length);
|
const onlineRegistries = $derived(data.registries.filter((registry) => registry.count > 0).length);
|
||||||
|
const prototypeVariant = $derived.by<PrototypeVariant | null>(() => {
|
||||||
|
if (!dev || page.url.searchParams.get('prototype') !== 'model-status') return null;
|
||||||
|
const variant = page.url.searchParams.get('variant');
|
||||||
|
return variant === 'A' || variant === 'B' || variant === 'C' ? variant : null;
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
@@ -8,6 +18,9 @@
|
|||||||
<meta name="description" content="Community-maintained The Division Resurgence attributes, talents, brands, gear, weapons, mods, protocols, skill chips, and specializations data."/>
|
<meta name="description" content="Community-maintained The Division Resurgence attributes, talents, brands, gear, weapons, mods, protocols, skill chips, and specializations data."/>
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
|
{#if prototypeVariant}
|
||||||
|
<ModelStatusPrototype variant={prototypeVariant} />
|
||||||
|
{:else}
|
||||||
<main class="page community-index-page">
|
<main class="page community-index-page">
|
||||||
<header class="catalogue-hero community-index-hero">
|
<header class="catalogue-hero community-index-hero">
|
||||||
<div><p class="eyebrow"><span></span> ISAC PUBLIC ARCHIVE</p><h1>RESURGENCE <em>DATABASE.</em></h1><p>Explore equipment, talents, modifications, and gameplay effects from The Division Resurgence.</p></div>
|
<div><p class="eyebrow"><span></span> ISAC PUBLIC ARCHIVE</p><h1>RESURGENCE <em>DATABASE.</em></h1><p>Explore equipment, talents, modifications, and gameplay effects from The Division Resurgence.</p></div>
|
||||||
@@ -54,3 +67,4 @@
|
|||||||
{/each}
|
{/each}
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
|
{/if}
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import ModelStatusPrototypeSwitcher from './ModelStatusPrototypeSwitcher.prototype.svelte';
|
||||||
|
import ModelStatusVariantA from './ModelStatusVariantA.prototype.svelte';
|
||||||
|
import ModelStatusVariantB from './ModelStatusVariantB.prototype.svelte';
|
||||||
|
import ModelStatusVariantC from './ModelStatusVariantC.prototype.svelte';
|
||||||
|
import type { PrototypeVariant } from './model-status.prototype';
|
||||||
|
|
||||||
|
let { variant }: { variant: PrototypeVariant } = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- THROWAWAY PROTOTYPE: three issue #5 variants on the existing /database route. -->
|
||||||
|
<main class="page model-status-prototype">
|
||||||
|
{#if variant === 'A'}
|
||||||
|
<ModelStatusVariantA />
|
||||||
|
{:else if variant === 'B'}
|
||||||
|
<ModelStatusVariantB />
|
||||||
|
{:else}
|
||||||
|
<ModelStatusVariantC />
|
||||||
|
{/if}
|
||||||
|
</main>
|
||||||
|
<ModelStatusPrototypeSwitcher current={variant} />
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { goto } from '$app/navigation';
|
||||||
|
import { page } from '$app/state';
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
import { prototypeVariantNames, type PrototypeVariant } from './model-status.prototype';
|
||||||
|
|
||||||
|
let { current }: { current: PrototypeVariant } = $props();
|
||||||
|
const variants: PrototypeVariant[] = ['A', 'B', 'C'];
|
||||||
|
|
||||||
|
const cycle = (direction: -1 | 1) => {
|
||||||
|
const currentIndex = variants.indexOf(current);
|
||||||
|
const next = variants[(currentIndex + direction + variants.length) % variants.length];
|
||||||
|
const params = new URLSearchParams(page.url.searchParams);
|
||||||
|
params.set('prototype', 'model-status');
|
||||||
|
params.set('variant', next);
|
||||||
|
void goto(`${page.url.pathname}?${params.toString()}${page.url.hash}`, {
|
||||||
|
keepFocus: true,
|
||||||
|
noScroll: true,
|
||||||
|
replaceState: true
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
const handleKeydown = (event: KeyboardEvent) => {
|
||||||
|
if (event.key !== 'ArrowLeft' && event.key !== 'ArrowRight') return;
|
||||||
|
if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) return;
|
||||||
|
if (event.target instanceof HTMLElement && event.target.closest('input, textarea, select, [contenteditable]:not([contenteditable="false"])')) return;
|
||||||
|
event.preventDefault();
|
||||||
|
cycle(event.key === 'ArrowLeft' ? -1 : 1);
|
||||||
|
};
|
||||||
|
window.addEventListener('keydown', handleKeydown);
|
||||||
|
return () => window.removeEventListener('keydown', handleKeydown);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- THROWAWAY PROTOTYPE: development-only variant switcher for issue #5. -->
|
||||||
|
<nav class="prototype-switcher" aria-label="Model status prototype variants">
|
||||||
|
<button type="button" onclick={() => cycle(-1)} aria-label="Show previous prototype variant">←</button>
|
||||||
|
<strong aria-live="polite" title={prototypeVariantNames[current]} aria-label={`Variant ${current}: ${prototypeVariantNames[current]}`}>{current}</strong>
|
||||||
|
<button type="button" onclick={() => cycle(1)} aria-label="Show next prototype variant">→</button>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.prototype-switcher{position:fixed;z-index:1000;right:14px;bottom:14px;display:grid;grid-template-columns:36px 34px 36px;height:36px;border:1px solid var(--shd-border-strong);box-shadow:0 7px 20px #000a;background:var(--shd-bg);color:var(--shd-text)}.prototype-switcher button{display:grid;place-items:center;border:0;background:var(--shd-surface-raised);color:var(--shd-orange);font:800 17px/1 var(--shd-font-mono);cursor:pointer}.prototype-switcher button:first-child{border-right:1px solid var(--shd-border)}.prototype-switcher button:last-child{border-left:1px solid var(--shd-border)}.prototype-switcher button:hover{background:var(--shd-surface-active);color:var(--shd-orange-hover)}.prototype-switcher button:active{transform:translateY(1px);filter:brightness(.82)}.prototype-switcher button:focus-visible{position:relative;z-index:1;outline:2px solid var(--shd-focus-ring);outline-offset:2px}.prototype-switcher>strong{display:grid;place-items:center;color:var(--shd-text);font:900 12px/1 var(--shd-font-mono);letter-spacing:.6px}@media(max-width:520px){.prototype-switcher{right:8px;bottom:8px}}@media(prefers-reduced-motion:reduce){.prototype-switcher button{transition:none}}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import {
|
||||||
|
modelStatusFixtures,
|
||||||
|
publicBehavior,
|
||||||
|
publicStatus
|
||||||
|
} from './model-status.prototype';
|
||||||
|
|
||||||
|
const quickViewFixtures = [modelStatusFixtures[0], modelStatusFixtures[3]];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- THROWAWAY PROTOTYPE: issue #5, variant A. -->
|
||||||
|
<div class="prototype-a">
|
||||||
|
<header class="prototype-heading">
|
||||||
|
<div>
|
||||||
|
<p><span></span> DEVELOPMENT PROTOTYPE · ISSUE #5 · VARIANT A</p>
|
||||||
|
<h1>MODELING <em>STATUS.</em></h1>
|
||||||
|
</div>
|
||||||
|
<p>Integrated card hierarchy keeps the public state in the identity header and gives behavior one primary reading block.</p>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<section aria-labelledby="a-card-heading">
|
||||||
|
<header class="surface-heading">
|
||||||
|
<div><span>01 / CARD PRESENTATION</span><h2 id="a-card-heading">DATABASE CARDS</h2></div>
|
||||||
|
<small>ALL MECHANIC OWNERS · PUBLIC STATE ONLY</small>
|
||||||
|
</header>
|
||||||
|
<div class="card-grid">
|
||||||
|
{#each modelStatusFixtures as fixture}
|
||||||
|
<article class="model-card">
|
||||||
|
<header>
|
||||||
|
<div><small>{fixture.owner}</small><h3>{fixture.name}</h3><span>{fixture.context}</span></div>
|
||||||
|
<strong class:not-modeled={publicStatus(fixture) === 'NOT MODELED'}>{publicStatus(fixture)}</strong>
|
||||||
|
</header>
|
||||||
|
<div class="behavior-block">
|
||||||
|
<small>{publicStatus(fixture) === 'MODELED' ? 'MODELED BEHAVIOR' : 'AUTHORED DESCRIPTION'}</small>
|
||||||
|
<p>{publicBehavior(fixture)}</p>
|
||||||
|
</div>
|
||||||
|
<footer><span>READ-ONLY FIXTURE</span><b>VIEW DETAILS →</b></footer>
|
||||||
|
</article>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section aria-labelledby="a-detail-heading">
|
||||||
|
<header class="surface-heading">
|
||||||
|
<div><span>02 / DETAIL PRESENTATION</span><h2 id="a-detail-heading">QUICK VIEW</h2></div>
|
||||||
|
<small>MODELED TEXT FIRST · AUTHORED FALLBACK WHEN NOT MODELED</small>
|
||||||
|
</header>
|
||||||
|
<div class="quick-view">
|
||||||
|
{#each quickViewFixtures as fixture}
|
||||||
|
<article>
|
||||||
|
<header><div><small>{fixture.owner}</small><h3>{fixture.name}</h3></div><strong class:not-modeled={publicStatus(fixture) === 'NOT MODELED'}>{publicStatus(fixture)}</strong></header>
|
||||||
|
<div><span>BEHAVIOR</span><p>{publicBehavior(fixture)}</p></div>
|
||||||
|
<dl><div><dt>RECORD</dt><dd>{fixture.context}</dd></div><div><dt>DISPLAY SOURCE</dt><dd>{publicStatus(fixture) === 'MODELED' ? 'Modeled behavior' : 'Authored description'}</dd></div></dl>
|
||||||
|
</article>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section aria-labelledby="a-search-heading">
|
||||||
|
<header class="surface-heading">
|
||||||
|
<div><span>03 / GLOBAL SEARCH PRESENTATION</span><h2 id="a-search-heading">SEARCH RESULTS</h2></div>
|
||||||
|
<small>{modelStatusFixtures.length} FIXTURE MATCHES</small>
|
||||||
|
</header>
|
||||||
|
<div class="search-results">
|
||||||
|
{#each modelStatusFixtures as fixture}
|
||||||
|
<div class="search-result">
|
||||||
|
<small>{fixture.owner}</small><strong>{fixture.name}</strong><span>{publicBehavior(fixture)}</span><b class:not-modeled={publicStatus(fixture) === 'NOT MODELED'}>{publicStatus(fixture)}</b>
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.prototype-a{display:grid;gap:28px;padding:20px 0 110px}.prototype-heading{min-height:150px;display:grid;grid-template-columns:minmax(0,1fr) minmax(280px,420px);align-items:end;gap:24px;padding:24px;border:1px solid var(--shd-border);border-top:2px solid var(--shd-orange);background:var(--shd-surface)}.prototype-heading p{margin:0;color:var(--shd-text-muted);font:var(--shd-type-supporting)/1.5 var(--shd-font-editorial)}.prototype-heading>div>p{color:var(--shd-orange);font:900 var(--shd-type-telemetry)/1 var(--shd-font-sans);letter-spacing:1px}.prototype-heading>div>p span{display:inline-block;width:22px;border-top:2px solid currentColor;vertical-align:middle}.prototype-heading h1{margin:10px 0 0;font-size:clamp(34px,5vw,64px);line-height:.9;letter-spacing:-1px}.prototype-heading h1 em{color:var(--shd-orange);font-style:normal}.prototype-a>section{display:grid;gap:10px}.surface-heading{min-height:46px;display:flex;align-items:end;justify-content:space-between;gap:16px;padding-bottom:9px;border-bottom:1px solid var(--shd-border)}.surface-heading>div{display:flex;align-items:baseline;gap:12px}.surface-heading span,.surface-heading small{color:var(--shd-text-muted);font-size:var(--shd-type-telemetry);font-weight:800;letter-spacing:.8px}.surface-heading h2{margin:0;font-size:20px;letter-spacing:.6px}.card-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px}.model-card{min-width:0;display:flex;flex-direction:column;border:1px solid var(--shd-border);border-top:2px solid var(--shd-border-strong);background:var(--shd-surface)}.model-card>header{min-height:92px;display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:start;gap:10px;padding:14px;border-bottom:1px solid var(--shd-border)}.model-card header small,.quick-view header small{display:block;margin-bottom:6px;color:var(--shd-text-muted);font-size:var(--shd-type-telemetry);font-weight:900;letter-spacing:.8px}.model-card h3,.quick-view h3{margin:0;font-size:18px;line-height:1.05}.model-card header span{display:block;margin-top:7px;color:var(--shd-text-dim);font-size:var(--shd-type-telemetry)}.model-card header strong,.quick-view header strong,.search-result b{padding:5px 7px;border:1px solid var(--shd-success);color:var(--shd-success);font-size:10px;line-height:1;letter-spacing:.7px;white-space:nowrap}.model-card header strong.not-modeled,.quick-view header strong.not-modeled,.search-result b.not-modeled{border-color:var(--shd-border-strong);color:var(--shd-text-muted)}.behavior-block{flex:1;margin:12px;padding:12px;border-left:2px solid var(--shd-success);background:var(--shd-model-surface)}.model-card:has(.not-modeled) .behavior-block{border-left-color:var(--shd-text-dim)}.behavior-block small{color:var(--shd-text-dim);font-size:10px;font-weight:900;letter-spacing:.9px}.behavior-block p{margin:7px 0 0;color:var(--shd-text);font:var(--shd-type-supporting)/1.5 var(--shd-font-editorial)}.model-card>footer{display:flex;justify-content:space-between;gap:10px;padding:10px 12px;border-top:1px solid var(--shd-border-soft);color:var(--shd-text-dim);font-size:10px;font-weight:900;letter-spacing:.6px}.model-card>footer b{color:var(--shd-orange)}.quick-view{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}.quick-view>article{border:1px solid var(--shd-border);background:var(--shd-surface-raised)}.quick-view article>header{display:flex;align-items:start;justify-content:space-between;gap:16px;padding:16px;border-bottom:1px solid var(--shd-border)}.quick-view article>div{padding:18px 16px}.quick-view article>div span{color:var(--shd-text-muted);font-size:10px;font-weight:900;letter-spacing:1px}.quick-view article>div p{max-width:62ch;margin:8px 0 0;font:18px/1.55 var(--shd-font-editorial)}.quick-view dl{display:grid;grid-template-columns:1fr 1fr;margin:0;border-top:1px solid var(--shd-border)}.quick-view dl>div{padding:10px 16px;border-left:1px solid var(--shd-border)}.quick-view dl>div:first-child{border-left:0}.quick-view dt{color:var(--shd-text-dim);font-size:10px;font-weight:900;letter-spacing:.8px}.quick-view dd{margin:4px 0 0;color:var(--shd-text-muted);font-size:var(--shd-type-telemetry)}.search-results{border:1px solid var(--shd-border);background:var(--shd-model-surface)}.search-result{display:grid;grid-template-columns:190px minmax(150px,.7fr) minmax(260px,1.6fr) auto;align-items:center;gap:12px;min-height:58px;padding:8px 12px;border-top:1px solid var(--shd-border-soft)}.search-result:first-child{border-top:0}.search-result>small{color:var(--shd-orange);font-size:var(--shd-type-telemetry);font-weight:900;letter-spacing:.5px}.search-result>strong{font-size:var(--shd-type-supporting)}.search-result>span{color:var(--shd-text-muted);font:var(--shd-type-telemetry)/1.4 var(--shd-font-editorial)}
|
||||||
|
@media(max-width:1000px){.card-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.search-result{grid-template-columns:minmax(140px,.7fr) minmax(0,1fr) auto}.search-result>small{grid-column:1/-1}.search-result>span{grid-column:2}}
|
||||||
|
@media(max-width:700px){.prototype-heading,.quick-view,.card-grid{grid-template-columns:1fr}.prototype-heading{align-items:start}.surface-heading{align-items:start}.surface-heading>div{display:grid;gap:4px}.surface-heading>small{display:none}.search-result{grid-template-columns:1fr auto}.search-result>small,.search-result>span{grid-column:1/-1}}
|
||||||
|
</style>
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,93 @@
|
|||||||
|
// THROWAWAY PROTOTYPE for issue #5. Fixture lifecycle data must never become a public API.
|
||||||
|
export type PrototypeVariant = 'A' | 'B' | 'C';
|
||||||
|
export type PublicModelStatus = 'MODELED' | 'NOT MODELED';
|
||||||
|
|
||||||
|
type MechanicLifecycle =
|
||||||
|
'ready' | 'requires_assumptions' | 'captured_only' | 'absent';
|
||||||
|
|
||||||
|
export type ModelStatusFixture = {
|
||||||
|
id: string;
|
||||||
|
owner:
|
||||||
|
| 'Talent'
|
||||||
|
| 'OS Protocol Talent'
|
||||||
|
| 'Skill Chip Talent'
|
||||||
|
| 'Specialization tree-rank effect';
|
||||||
|
name: string;
|
||||||
|
context: string;
|
||||||
|
internal: {
|
||||||
|
lifecycle: MechanicLifecycle;
|
||||||
|
current: boolean;
|
||||||
|
};
|
||||||
|
modeledText?: string;
|
||||||
|
authoredText: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const modelStatusFixtures: ModelStatusFixture[] = [
|
||||||
|
{
|
||||||
|
id: 'talent-ready',
|
||||||
|
owner: 'Talent',
|
||||||
|
name: 'Predatory Advance',
|
||||||
|
context: 'Weapon Talent · Tier I',
|
||||||
|
internal: { lifecycle: 'ready', current: true },
|
||||||
|
modeledText:
|
||||||
|
'On enemy kill: gain +15% Weapon Damage for 10 s. Refreshes and stacks up to 3 times.',
|
||||||
|
authoredText:
|
||||||
|
'Killing an enemy grants 15% weapon damage for 10s. Stacks up to 3 times.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'protocol-assumptions',
|
||||||
|
owner: 'OS Protocol Talent',
|
||||||
|
name: 'Emergency Weave',
|
||||||
|
context: 'Superior OS Protocol · Talent',
|
||||||
|
internal: { lifecycle: 'requires_assumptions', current: true },
|
||||||
|
modeledText:
|
||||||
|
'When armor breaks: restore 20% Armor over 5 s. Cooldown: 20 s.',
|
||||||
|
authoredText:
|
||||||
|
'When armor is broken, restore 20% armor over 5s. Cooldown: 20s.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'chip-captured',
|
||||||
|
owner: 'Skill Chip Talent',
|
||||||
|
name: 'Rapid Instruction',
|
||||||
|
context: 'Tactical Skill Chip Set · 3-piece talent',
|
||||||
|
internal: { lifecycle: 'captured_only', current: true },
|
||||||
|
modeledText: 'After skill use: gain +8% Skill Haste for 12 s.',
|
||||||
|
authoredText: 'Using a skill grants 8% Skill Haste for 12s.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'specialization-absent',
|
||||||
|
owner: 'Specialization tree-rank effect',
|
||||||
|
name: 'Perfect Cadence · Rank 3',
|
||||||
|
context: 'Sharpshooter · Precision branch',
|
||||||
|
internal: { lifecycle: 'absent', current: true },
|
||||||
|
authoredText:
|
||||||
|
'After reaching 5 hits without missing, your next shot deals 25% increased damage.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'talent-stale',
|
||||||
|
owner: 'Talent',
|
||||||
|
name: 'Measured Focus',
|
||||||
|
context: 'Gear Talent · Tier II',
|
||||||
|
internal: { lifecycle: 'ready', current: false },
|
||||||
|
modeledText:
|
||||||
|
'After a headshot: gain +8% Critical Hit Damage for 8 s, stacking up to 3 times.',
|
||||||
|
authoredText:
|
||||||
|
'Headshots grant 10% Critical Hit Damage for 8s. Stacks up to 4 times.',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const publicStatus = (fixture: ModelStatusFixture): PublicModelStatus =>
|
||||||
|
fixture.internal.current && fixture.internal.lifecycle !== 'absent'
|
||||||
|
? 'MODELED'
|
||||||
|
: 'NOT MODELED';
|
||||||
|
|
||||||
|
export const publicBehavior = (fixture: ModelStatusFixture): string =>
|
||||||
|
publicStatus(fixture) === 'MODELED' && fixture.modeledText
|
||||||
|
? fixture.modeledText
|
||||||
|
: fixture.authoredText;
|
||||||
|
|
||||||
|
export const prototypeVariantNames = {
|
||||||
|
A: 'Integrated card hierarchy',
|
||||||
|
B: 'Evidence rail',
|
||||||
|
C: 'Registry rows',
|
||||||
|
} satisfies Record<PrototypeVariant, string>;
|
||||||
Reference in New Issue
Block a user