feat(settings): define canonical typed schema - #114
Conversation
Teakowa
left a comment
There was a problem hiding this comment.
Changes required. Full one-pass audit against #109. The direction and ownership boundaries are good, but the current foundation still freezes several incorrect/overstated semantic contracts.
Blocker
-
Canonical
SettingIdnormalization is incomplete, so the new public IDs still encode target-specific path structure.canonical_id()normalizes only a narrow subset (enablePrimaryFire/enableSecondaryFire/enableAbility1/enableAbility2, and keys containingCooldown). Existing projected definitions such asenableAbility3,enableUlt,enablePassive,secondaryFireRechargeRate%,ability1EnemyKb%,ability1SelfKb%, andability2FuseTime%therefore keep slot/hero-path details in the supposedly canonical concept ID even thoughSettingTargetalready carries the logical slot. This conflicts with #109's identity rule and would force #110 to break IDs that #109 is intended to establish. Define and exercise the concept-identity mapping for the currently projected semantic surface (without concrete ability display names and without duplicating target structure), or do not expose unresolved path-derived IDs as canonical yet. -
Effective applicability does not implement the documented known-hero vs unknown distinction.
hero_setting_is_evidenced()returnsNonewhen a known hero has no entry for a key, andSettingDefinition::applicability()maps that toUnknown. For a wildcard hero definition such asability1EnemyKb%, the reviewed generated data contains the setting for Ashe but not Ana; querying that definition for Ana therefore becomesUnknown, while ADR-0006 explicitly says a known hero without a reviewed key isNotApplicable. The current test only covers placeholder entries (Some(false)), not an actually absent hero/key. Resolve the completeness/evidence contract and add a representative hero-specific exclusion case; do not infer applicability from whether a locale label happens to be usable. -
Unknown numeric bounds are silently promoted to exact effective semantics.
NumericBoundsdocumentsNoneas “current reviewed evidence does not establish that bound”, butNumericBounds::effective()returnsSome(EffectiveNumber { authored, effective: authored })when both bounds areNone. All current projected Number/Percent definitions use(None, None), so consumers can currently ask for an “effective” value and receive a false claim that no clamping occurs. Preserve unknownness until bounds/clamp behavior are evidenced. Also enforce or otherwise make unrepresentable invalid bound states (non-finite bounds /min > max) before this becomes a public semantic contract.
Major
-
gamemodes.generalis incorrectly modeled as a game-mode target.target_for()turns everygamemodes.<part>path intoMode(part), but the existing settings table explicitly documentsgeneralas a literal settings group, not a mode slot.SettingScope::GameModesis correct; the semantic target forgamemodes.general.*must not beMode("general"). -
Non-hero
en-USpresentation lookup is broken. The existing locale table intentionally does not duplicate English names, and the emitter has an expliciten-US => englishpath.SettingPresentation::localized_name()calls onlytable::localized_name(), so a normal definition such asmain.descriptionreturns noen-USspelling despite carryingenglish_name. Make the schema follow the existing locale contract and cover a normal non-heroen-USlookup. -
SettingProvenanceflattens distinct evidence sources into one generic claim. Hand-maintained table entries are fixture/oracle-evidenced, while generated entries/hero settings come from the reviewed workshop-data export, yet every projected definition reports the samesource = "reviewed workshop-rs settings table and generated settings data"andreviewed = true. #109 requires provenance as a semantic fact; it must identify the actual evidence class/source for the definition rather than implying every entry came from both. Keep this minimal, but machine-meaningful and accurate.
Minor
- Definition-side ability target typing regresses to strings and drops variants. Public
SettingTargetcorrectly usesLogicalSlot+ optionalAbilityVariant, butSettingTargetKind::HeroAbility { slot: String }and privateTargetPattern::HeroAbility { slot: String }introduce a second slot identity and cannot express a variant-specific definition. Use the existing canonical slot identity throughout; if current evidence has no variant-specific settings,Noneis fine, but the #109 foundation should not make the definition side structurally unable to represent the target contract it declares.
The added tests are useful but currently miss the failure modes above: known hero + absent hero-specific key, unknown bounds, gamemodes.general, normal en-US presentation, and broader concept-ID normalization.
CI / scope
The PR's CI is currently red in both stable and MSRV jobs at the pre-existing language_conformance::aggregate_values_count_matches_supported_inventory aggregate-count assertion; fmt/clippy and the real-project scenarios pass before that failure. This PR does not touch that inventory/test, so do not fold an unrelated cleanup into #109. Repair/rebaseline that repository gate separately, then rerun CI before merge.
No additional ownership, source-language dependency, parser/emitter rewrite, source-preservation, or repo-hygiene blockers found in the audited diff.
|
Addressed all review findings in follow-up commit
Local verification after the fixes: 23 settings tests passed, fmt, Clippy, catalog check, and diff check passed. The unrelated aggregate-count workspace gate remains unchanged and is tracked separately. |
Teakowa
left a comment
There was a problem hiding this comment.
Changes still required. Second full audit of the updated head (915bbef) against #109.
The update correctly fixes several previous findings: gamemodes.general is no longer a mode target; non-hero en-US presentation now follows the existing primary-locale behavior; provenance distinguishes fixture-backed vs workshop-data-generated definitions; and definition-side ability targets now reuse LogicalSlot / AbilityVariant. Unknown-all numeric bounds also no longer manufacture an effective value, and CI is green on the current merge context.
Blocker
-
Known-hero vs unknown applicability is still inconsistent, and the previous hero-specific exclusion case remains wrong for ability settings. The
HeroAbilitybranch first recognizes an unknown hero, but for a known hero it still mapshero_setting_is_evidenced(...) == NonetoUnknown. A projected hero-specific key such asability1EnemyKb%is evidenced for Ashe but absent for Ana; querying it forAna + Ability1therefore remainsUnknown, while ADR-0006 explicitly says a known hero without a reviewed key isNotApplicable. Conversely, the plainHerobranch now mapsNonedirectly toNotApplicablewithout first checking whether the hero itself is known, so an unknown/future hero becomesNotApplicableinstead ofUnknown. Apply one consistent rule to both branches: unknown hero =>Unknown; known hero + evidenced key => applicable/not-applicable according to the reviewed applicability evidence; known hero + absent key in a complete reviewed hero surface =>NotApplicable. Add tests for both a real known-hero/absent hero-specific key (e.g. Ana vs an Ashe-only setting) and an unknown hero on a non-ability hero setting. -
Canonical
SettingIdnormalization is still incomplete for the currently projected surface. The newability_concept()removesability1/2/3andsecondaryFireprefixes, butcanonical_id()still special-cases onlyenableSecondaryFire, not the existingenableGenericSecondaryFireentry. Both are mapped to the secondary-fire logical slot by the existing table, yet the latter is exposed assetting.hero.ability.enableGenericSecondaryFirerather than the sameability.enabledconcept. More generally, mechanically stripped suffixes such asEnemyKb/FuseTimeare being frozen as public canonical IDs without an asserted canonical vocabulary/casing contract. #109 is the stage that is supposed to establish these identities so #110 does not have to break them. Either finish the concept mapping for every currently exposed projected ability setting (with exact identity tests), or keep unresolved path-derived identities non-canonical/private until #110 supplies reviewed concepts. -
Partially-known numeric bounds still overstate the effective value.
Noneis documented as “evidence does not establish that bound”.effective()now correctly returnsNonewhen both bounds are unknown, but if only one side is known it always returns anEffectiveNumber. Example: withmin = Some(0),max = Noneand authored1000, the implementation reports effective1000even though the unknown maximum may clamp it. The mirror case exists for known max / unknown min. Preserve unknownness whenever the missing side could affect the authored value; alternatively modelunknownvs evidenced-unbounded as distinct states. Add partial-bound tests, not only all-unknown and fully-bounded cases.
Major
- Applicability is still derived from locale-label usability rather than an explicit applicability fact.
hero_setting_is_evidenced()decides support by checking whether any generated localized label is nonblank/non-placeholder. That happened to encode several current exclusions, but it conflates presentation completeness with semantic applicability and makes a missing/blank locale artifact silently becomeNotApplicable. #109 explicitly separates applicability from locale presentation, and the previous review asked to resolve this evidence contract rather than infer capability from label usability. If the workshop-data producer's blank/missing entries are an intentionally reviewed applicability oracle, represent/document that as applicability evidence; otherwise keep itUnknownuntil #110 has explicit applicability data. Do not make locale quality the durable semantic API.
Minor
-
The canonical documentation index does not link ADR-0006.
docs/README.mdis explicitly the canonical docs index and currently lists the accepted ADRs through ADR-0005. Since #109 requires this durable settings contract to be recorded in owner docs, add ADR-0006 to the architecture/authority index rather than leaving the accepted contract undiscoverable. -
The PR body is stale after the update/main fix. It still reports the old workspace-test failure and an independent QA result of “Blockers: none / Major: none”, while the current CI run is green and the PR has review findings. Refresh the verification/QA summary before merge so the PR does not preserve obsolete status claims.
Re-audited areas with no additional findings
- ownership/dependency direction remains clean; no OPY/DEL carrier semantics moved into
workshop-rs; Settings/SettingsNoderemain the source-preserving carrier;- no parser/emitter rewrite or unrelated architecture cleanup;
- value-domain kinds remain aligned with existing
KeyKindsemantics; NumericBounds::newnow rejects non-finite/reversed bound states;SettingTargetKindno longer creates a second stringly-typed slot identity;- current CI passes stable, MSRV, real-project scenarios, and catalog check.
Do not proceed to #110 until the remaining identity/applicability/unknown-value contracts above are closed; those are exactly the public semantic decisions #109 exists to settle.
|
Second review follow-up is complete in Addressed all six findings:
Local gates are green: settings pipeline 23/23, workspace clippy with |
Teakowa
left a comment
There was a problem hiding this comment.
Changes required. Third full audit against #109 at 11c4d3e. The previous review's partial-bound handling, known/future-hero branches, target typing, locale fallback, provenance split, ADR index, PR summary, and CI issues are materially improved. The remaining problems are now concentrated in the core semantic contract rather than repo hygiene.
Blocker
-
The hero-name projection is still being used as a complete applicability matrix, which makes ordinary hero settings
NotApplicablefor known heroes.hero_setting_applicability()searches onlyGENERATED_HERO_SETTING_NAMES; an absent row becomesNone, and both Hero/HeroAbility applicability branches map that toNotApplicablefor a known hero. But that generated file is not a complete per-hero settings inventory: the reviewed settings table contains ordinary hero keys such asheroes.<team>.<hero>.health%,enableAutomaticFire,enableScoping, and genericenablePrimaryFire, while the hero-name projection has nohealth%,enableAutomaticFire,enableScoping, or generic rows for most heroes. For example, the current test can resolve Ana's generic Primary Fire presentation, but the same definition's applicability for Ana isNotApplicablebecause there is no AnaenablePrimaryFirename row. Absence from a hero-specific name table cannot mean semantic exclusion. The #109 contract needs a real applicability evidence boundary: kit topology + explicit applicability/common/exclusion facts where reviewed; otherwise returnUnknownuntil #110 supplies the catalog data. Renamingis_applicable()and documenting blank labels as producer markers does not make the name dataset complete for keys that never appear in it. -
Canonical IDs are now over-normalized and conflate distinct Workshop settings.
enableAutomaticFire(No Automatic Fire) andenableScoping(No Scope) are both mapped tosetting.hero.ability.enabled, the same concept as the actual Primary/Secondary/Ability enable controls. These are distinct controls over automatic-fire/scoping behavior, not aliases for whether the ability itself is enabled. This loses semantic identity before #110 can populate the catalog. Likewiseability.primaryFireFreezeStackandability.passiveUnlimitedFuelstill duplicate logical-slot specificity thatSettingTargetalready carries. Canonicalization should remove target/display specificity without collapsing different setting concepts. Use reviewed concept identities (for example an automatic-fire/scoping/freeze-stacking/unlimited-fuel concept where evidence supports it), not anenable* => ability.enabledheuristic. -
SettingDefinition::applicability()still does not enforce the #109 kit-topology-first rule, and it ignores ability variants entirely. The method checks hero-name applicability evidence after matching the slot string, but never verifies that the hero actually has that logical slot/variant in the canonical gameplay topology. A target with an otherwise applicable hero/key/slot andvariant: Some("missing")can still returnApplicable. #109 explicitly says kit topology determines which logical slots exist before setting applicability is evaluated. Either integrate/accept a topology context and reject/mark unknown impossible targets, or change the public contract through an explicit design decision; silently assuming every supplied target is topology-valid does not satisfy the current issue.
Major
-
Target-aware presentation can return a concrete name for a target that the same definition says is not applicable.
localized_name()first tries the hero-specific name and then unconditionally falls back to the genericSettingPresentation. For the Ashe-onlyability1EnemyKb%definition queried against Ana, applicability isNotApplicable, butlocalized_name("en-US", Ana/Ability1)can fall back toCoach Gun Knockback Scalar Enemy. A target-aware resolver should not manufacture a misleading concrete presentation for a non-applicable target. Either gate target resolution by applicability or separate generic definition presentation from target-resolved presentation so the contract is unambiguous. -
ability.custom.*plus default scope/target fallbacks silently turn unreviewed future shapes into reviewed canonical facts. ADR-0006 says an unreviewed future ability suffix is emitted asability.custom.*, butfrom_entry()still wraps it in a normalSettingDefinitionwithreviewed: true. Similarly, unknown root/path shapes fall through toSettingScope::Workshop/TargetPattern::Global. Those are real semantic categories, not anUnknownbucket. This contradicts #109's requirement to preserve unknown/evidence-insufficient states and risks freezing placeholder identities that #110 later has to rename. Unknown semantic mappings should remain explicit/unsupported until reviewed rather than receive guessed canonical identities/targets. -
The canonical concept mapping has become a second hand-maintained catalog inside
schema.rs, crossing into #110's ownership.canonical_id()/ability_concept()now encode a long concrete list of current setting keys and exceptional mappings, while #110 explicitly owns assigning stable concepts and making one canonical typed dataset/generation path the source of truth. The long mirrored test list then duplicates the mapping again. #109 should establish theSettingDefinition/identity model and the mechanism by which reviewed catalog data supplies canonical concepts; it should not require a second code-level catalog that #110 must later migrate or reconcile.
Minor
- The doc comment above
hero_setting_applicability()still begins by describing “whether ... evidence contains a usable localized label” and immediately follows with a claim that this is semantic applicability rather than locale completeness. That contradiction reflects the underlying data-boundary problem above; once applicability comes from the correct evidence source, keep the helper documentation single-purpose.
CI / merge state
- Latest PR CI for
11c4d3eis green: stable, MSRV 1.85, real-project scenarios, and Catalog check all passed. - The branch is currently 3 commits ahead / 2 behind
main;mainhas since taken #113 and #116. Current PR metadata reports it non-mergeable, so refresh/rebase after the semantic fixes and rerun the merge-result CI.
No additional parser/emitter regression, source-preservation regression, source-language ownership violation, unrelated refactor, or test-count/snapshot-padding issue found in this pass. Do not start #110 until the applicability/identity/topology contract above is closed.
|
Third review follow-up is complete in Addressed all seven findings:
Local gates are green: settings pipeline 23/23, workspace clippy with |
Teakowa
left a comment
There was a problem hiding this comment.
Changes required. Full one-pass re-audit of 60e6845 against #109. The third-round fixes materially improve evidence handling: locale data is no longer treated as applicability evidence, topology now rejects missing slots/variants, unresolved applicability stays Unknown, target-aware presentation is gated for NotApplicable, and CI is green. However, the #109 public semantic model still has unresolved architecture/contract issues that would force #110 to redesign it.
Blocker
-
Team/common hero slot-specific settings cannot be represented without losing the logical slot. The reviewed generated inventory contains entries such as
heroes.<team>.enablePrimaryFireandheroes.<team>.enableUlt, in addition toheroes.<team>.<hero>.*.target_for()maps anyheroes, Team, ...path without aHerocomponent toTargetPattern::Team, whilesemantic_ability_slot_for_path()recognizes keys such asenablePrimaryFireasprimaryFire. That leaves a team-level ability definition with targetTeamand no slot. Today the raw key survives only because its provisionalability.custom.enablePrimaryFireID still contains the slot-specific path name. Once #110 does what it owns—normalizing this to a reusable concept such asability.enabled—the slot is lost. #110 would then have to add/change the public target model or put slot specificity back intoSettingId, both contrary to #109's boundary. Resolve the target model for Workshop common/team hero settings so slot-specific common settings can carry logical-slot semantics independently ofSettingId, and add representative coverage for bothheroes.<team>.enablePrimaryFireand a concrete hero-ability path. -
Unresolved identity is still encoded as a pseudo-
SettingIdplus an overloaded provenance flag instead of an explicit unknown identity state.SettingIdis documented as a locale-independent Workshop setting concept identity andSettingDefinitionas canonical, but every unresolved hero-ability entry still returns a path-derivedSettingIdundersetting.hero.ability.custom.*. The only signal that this is not canonical is string inspection plusSettingProvenance.reviewed = false. That also makes provenance carry two meanings: whether the evidence source was reviewed and whether semantic identity is resolved. ADR-0006 says no path-derived ID is presented as canonical, but the API currently does exactly that throughid(). Before #110 freezes data around this, represent identity unknownness explicitly (the exact API shape is an architecture choice) or do not expose an unresolved value as canonicalSettingId; keep provenance about provenance.
Major
- Topology lookup converts data/invariant failure into semantic
Unknownand deep-clones the gameplay catalog on every applicability query.hero_ability_exists()callsgameplay_data::builtin().ok(). A malformed/digest-invalid embedded gameplay dataset is not “insufficient setting evidence”; silently dropping that error changes a data failure intoApplicability::Unknown. Also,builtin()clones the cachedGameplayCatalog, so each hero-ability applicability query clones the gameplay dataset. This is a poor boundary for a tooling-facing query that #111/completion may call repeatedly. Use an error/invariant boundary that does not masquerade as semantic unknown and avoid cloning the entire catalog per query.
Minor
- ADR-0006 still says wildcard hero applicability is “resolved against the reviewed hero-setting data,” but this revision deliberately removed hero-setting presentation data as applicability evidence. The durable contract should state that the current #109 foundation only uses topology to disprove applicability and leaves topology-valid applicability
Unknownuntil #110 supplies explicit applicability evidence.
Verified / resolved
- prior presentation-as-applicability bug: resolved
- known/future hero false certainty: resolved by preserving
Unknown - missing slot/variant topology: now rejected
- over-collapsed ability identities: no longer silently merged
- target-aware presentation:
NotApplicableguarded - numeric unknown/partial-bound behavior remains correct
gamemodes.general, en-US, typed slot/variant, provenance source classes, and ADR index remain fixed- no new cross-repo ownership, parser/emitter, source-preservation, or unrelated-refactor issues found
- latest CI for
60e6845: stable, MSRV 1.85, real-project scenarios, and Catalog check all green
The branch is mergeable but still behind current main by two CI-only commits; that is not a semantic blocker given the current successful PR run.
|
Fourth review follow-up is complete in Addressed all four findings:
Local gates are green: settings pipeline 23/23, workspace clippy with |
Teakowa
left a comment
There was a problem hiding this comment.
Changes required. Full re-audit of c2ba062 against #109 and current main.
The two architecture findings from the previous review are materially fixed: team/common slot-bearing settings now preserve the logical slot through TeamAbility, unresolved ability identities are explicit through SettingIdentity::Unknown/id() -> None, and the gameplay topology lookup is borrowed and fallible instead of cloning the whole catalog or collapsing dataset errors into Unknown.
Blocker
-
applicability()still does source-target-kind matching rather than the effective hero/ability applicability required by #109. The current table contains common/team hero settings such asheroes.<team>.health%,heroes.<team>.enablePrimaryFire,heroes.<team>.enableUlt, etc.target_for_team()now correctly preserves a slot asTeamAbility, butSettingDefinition::applicability()only matchesTargetPattern::TeamwithSettingTarget::TeamandTargetPattern::TeamAbilitywithSettingTarget::TeamAbility. A consumer asking whether the commonhealth%definition applies to a concreteHero, or whether the commonenablePrimaryFiredefinition applies to a concreteHeroAbility, therefore falls through toNotApplicable.That is an exact false negative and exposes the common/team source organization that #109 explicitly says consumers must not need to understand. The #109 AC says effective hero/ability applicability must be queryable independently of common/exclusion/addition organization. The foundation should support the narrowing relation from common/team definitions to concrete hero/hero-ability targets (using team matching and gameplay topology where needed), returning
Unknownwhen applicability evidence is still incomplete rather thanNotApplicable. Add representative tests for at leastTeam -> HeroandTeamAbility -> HeroAbility.Relatedly, the
TeamAbilitybranch currently requiresexpected_variant == actual_variant; this makes a definition with no variant constraint reject a concrete variant, unlike theHeroAbilitybranch whereNoneis non-restrictive. Keep the optional-variant semantics consistent when fixing the common-to-concrete path.
Major
-
localized_name()silently drops the newly explicit gameplay-data failure.applicability()now correctly returnsResult<Applicability, GameplayDataError>, butlocalized_name()callsself.applicability(target).ok()?. A malformed/digest-invalid canonical gameplay dataset therefore becomesNone, indistinguishable from “no presentation / not applicable”. This recreates the exact failure-boundary problem the new fallible applicability API was intended to fix. Propagate the error (for example with a fallible target-aware presentation query), or otherwise keep a clearly separate best-effort API rather than silently converting a canonical-data failure into absence. -
ADR-0006 still documents the superseded identity contract. The accepted ADR says unresolved hero-ability settings are isolated under
setting.hero.ability.custom.*and “marked as semantically unreviewed”. The implementation now deliberately does the opposite:SettingIdentity::Unknown,id() -> None, while provenance remainsreviewed: truebecause the evidence record itself is reviewed. #109 requires the owner-side ADR to be the durable contract, so update that paragraph to describe the explicit unknown-identity state and keep identity review separate from provenance review.
Minor
gameplay_data::builtin_ref()expands the public gameplay API even though #109 only needs an internal borrowed lookup.gameplay_datais a public module, sopub fn builtin_ref()becomes a new consumer contract. If there is no independent consumer requirement for a borrowed'staticdataset API, preferpub(crate)(or another internal helper) and keep the #109 patch from broadening the gameplay API incidentally. If this is intentionally a public gameplay contract, document that intent rather than exposing it as an implementation side effect.
CI / merge readiness
The latest c2ba062 run is fully green: stable, Rust 1.85, Catalog check, and all five real-project scenarios pass. However, the branch is currently two commits behind main (#113 and #116, both CI-related), and the successful pull-request run records base SHA f43f1694, not current main 4b6d1d25. Before final merge, synchronize/retrigger so the final merge result is exercised under the current repository CI configuration. The stale PR-body sentence about the old aggregate-count baseline should disappear or be updated at the same time.
No additional ownership/dependency violations, parser/emitter/source-preservation regressions, unrelated refactors, or test-hygiene issues were found in this pass.
Normalize the projected ability concepts, preserve unknown numeric bounds, distinguish known exclusions from unknown heroes, and report accurate locale, target, slot, variant, and evidence semantics. Related to #109
Complete applicability, canonical identity, partial-bound, and documentation follow-ups for #109.
Keep applicability, topology, and unresolved identity explicit until the reviewed settings catalog is available in #110.
Add team ability targets, explicit unknown identities, and fallible borrowed gameplay topology queries for #109.
Support common-to-concrete target narrowing and preserve fallible presentation and identity semantics for #109.
c2ba062 to
368999c
Compare
|
Final review follow-up is complete in Addressed the remaining findings:
Verification on the rebased head:
All passed. |
Teakowa
left a comment
There was a problem hiding this comment.
Changes required. Full re-audit of the rebased head 368999c against #109.
The previous round is materially fixed: common Team / TeamAbility definitions now narrow to concrete hero targets, None variants are non-restrictive, target-aware presentation propagates gameplay-data failures, unresolved identity is explicit and separate from provenance, the borrowed gameplay lookup is crate-private, ADR-0006 reflects the new identity contract, and the branch is rebased onto current main. Current CI is fully green.
Blocker
-
Known missing logical slots are still downgraded to
Unknownwhen no variant is supplied.hero_ability_exists()currently returnscatalog.hero(hero).and_then(|hero| (!hero.abilities_in_slot(slot).is_empty()).then_some(true))forvariant == None. For a known hero whose topology does not contain the requested slot,abilities_in_slot()is empty, so this yieldsNone; bothTeamAbility -> HeroAbilityandHeroAbility -> HeroAbilitythen map that toApplicability::Unknown. That contradicts #109 and ADR-0006, which require kit topology to disprove impossible targets and state that missing slots/variants areNotApplicable.Preserve the distinction between an unknown hero (
None) and a known hero with a missing slot (Some(false)). A representative regression should cover a known hero + absent slot withvariant: None(the existing tests cover an explicit missing variant, which takes the other branch and therefore misses this case).
Minor
settings::table::is_generated_entry()is exposed publicly even though it is only an implementation helper for the schema projection.settings::tableis public, so the newpub fnbecomes a consumer-visible API that classifies entries by pointer identity against the current generated-table storage. #110 is explicitly allowed to replace/reconcile that storage strategy; consumers should obtain evidence provenance throughSettingDefinition::provenance(), not depend on this helper. Preferpub(crate)unless there is an independent public contract for it.
Verified / no additional findings
- common/team effective narrowing and optional-variant matching are now structurally correct;
localized_name()no longer swallowsGameplayDataErroron hero-aware resolution;SettingIdentity::Unknown/id() -> Nonecorrectly separates unresolved concept identity from reviewed provenance;- numeric unknown/partial-bound behavior remains sound;
- source-preserving
Settings/SettingsNode, parser/emitter ownership, and cross-repo boundaries remain intact; - no unrelated refactor or test-count/snapshot padding found;
- head
368999cis based on currentmain(4b6d1d25) and CI passes stable, Rust 1.85, Catalog check, and all real-project scenarios.
|
Follow-up for the remaining blocker is complete in
Focused settings tests, fmt, Clippy, and diff checks pass. |
Teakowa
left a comment
There was a problem hiding this comment.
Re-audited the full diff at 92c7c96 against #109 and the #109/#110 ownership boundary. No remaining findings.
The latest follow-up resolves both findings from the previous round:
hero_ability_exists()now preserves the required distinction between an unknown hero (None) and a known hero with a missing logical slot (Some(false)), so a known missing slot withvariant: Noneresolves toNotApplicable. The added regression exercises that exact branch.settings::table::is_generated_entry()is nowpub(crate), avoiding an unnecessary public pointer-identity/table-organization contract.
I also rechecked the rest of the PR rather than only the follow-up commit: common Team / TeamAbility narrowing, unconstrained None variants, explicit missing variants, gameplay-data error propagation, locale presentation behavior, unresolved identity vs provenance, unknown/partial numeric bounds, gamemodes.general, source-preserving Settings/SettingsNode boundaries, and ADR/docs alignment remain consistent with #109. I found no new ownership, dependency-direction, parser/emitter, test-quality, or scope regressions.
Current base is still main@4b6d1d25; the PR is mergeable, and all four CI jobs on 92c7c96 are green (stable quality, Rust 1.85 quality, catalog check, and five real-project scenarios).
The authenticated account is the PR author, so this is submitted as a COMMENT review rather than an approval. From the code-review side, this head is ready to merge.
Summary
Implements the typed Workshop settings semantic foundation for #109 while keeping incomplete semantic evidence explicit until #110.
TeamAbility; effective applicability narrowsTeamdefinitions to concrete heroes andTeamAbilitydefinitions to concrete hero abilities.Noneability variants as an unconstrained variant; canonical gameplay topology still rejects missing slots or explicit missing variants.SettingIdentity::Unknown(id() -> None) without path-derived pseudo-canonical IDs.Settings/SettingsNodesource-preserving and retains authored values when effective values are clamped.pub(crate)) because it supports settings queries without adding a public API contract.Verification
Branch
codex/issue-109-settings-semanticis rebased onto currentmainat4b6d1d25e2dbd73d7b6ad03596865166a74fb4ec.cargo fmt --all --check— passedcargo clippy --workspace --all-targets -- -D warnings— passedcargo test --workspace --all-targets— passedcargo run -p workshop-rs --bin workshop-catalog-gen -- check— passed (532 entries, 52 enum domains, 2 locales)git diff --check— passedADR-0006 now documents the independent axes of reviewed source evidence and resolved canonical identity.