Compose Advanced Leader Skills and Strongholds with optional Tech

This commit is contained in:
Quintine committed 2026-10-04 09:50:55 +11:00
1 parent 3c7725c3a5
commit f259488a9a
19 files changed
+1570 -54

No files matched your search

+2 -2
View File
@@ -1,4 +1,4 @@
import { classicTechLeaderSkillsProfile, nativeExpansionLeaderSkillsProfile, nativeTechLeaderSkillsProfile, noOtherLeaderSkillModules, type LeaderSkillProfile } from './leader-skill-profile';
import { classicTechLeaderSkillsProfile, nativeExpansionLeaderSkillsProfile, nativeTechLeaderSkillsProfile, noOtherLeaderSkillModules, strongholdLeaderSkillsProfile, type LeaderSkillProfile } from './leader-skill-profile';
export type BureaucratPaymentKind = 'auction' | 'shipment' | 'bribe' | 'revival';
export type BureaucratPaymentSource = {
event: string;
@@ -38,7 +38,7 @@ export function bureaucratPaymentModeSupported(game: LeaderSkillProfile): boolea
return (noOtherLeaderSkillModules(game) &&
(!game.expansions.length ||
(game.expansions.length === 1 && game.expansions[0] === 'choam') ||
nativeExpansionLeaderSkillsProfile(game))) || classicTechLeaderSkillsProfile(game) || nativeTechLeaderSkillsProfile(game);
nativeExpansionLeaderSkillsProfile(game))) || classicTechLeaderSkillsProfile(game) || nativeTechLeaderSkillsProfile(game) || strongholdLeaderSkillsProfile(game);
}
export function bureaucratUsed(
used: readonly BureaucratPaymentUse[],
+10 -6
View File
@@ -1,4 +1,4 @@
import { advancedMoritaniLeaderSkillsProfile, advancedNativeLeaderSkillsProfile, classicTechLeaderSkillsProfile, nativeExpansionLeaderSkillsProfile, nativeTechLeaderSkillsProfile, ordinaryLeaderSkillModeSupported } from './leader-skill-profile';
import { advancedMoritaniLeaderSkillsProfile, advancedNativeLeaderSkillsProfile, classicTechLeaderSkillsProfile, nativeExpansionLeaderSkillsProfile, nativeTechLeaderSkillsProfile, ordinaryLeaderSkillModeSupported, strongholdLeaderSkillsProfile } from './leader-skill-profile';
import { bribeTimingBlock, maximumBribe, type BribeOptions } from './bribe-options';
import { quoteSpicePlacement, stormExposesTerritory, stormSectorAfter, wormConsumesForces } from './disaster-rules';
import { isStormCardDistance, type StormCardComponent } from './storm-cards';
@@ -7845,8 +7845,8 @@ function bankerIncomeProfile(g: Game): boolean {
new Set(g.players.map(p => p.faction)).size === g.players.length &&
((!g.expansions.length && g.players.every(p => FACTIONS.some(f => f.id === p.faction && f.expansion === 'base'))) ||
nativeExpansionLeaderSkillsProfile(g)) &&
!g.nexusCards && !g.homeworlds && (!g.techTokens || classicTechLeaderSkillsProfile(g) || nativeTechLeaderSkillsProfile(g)) &&
!g.strongholdCards && !g.discoveryEnabled && !g.discoveries && !g.discoveryStash &&
!g.nexusCards && !g.homeworlds && (!g.techTokens || classicTechLeaderSkillsProfile(g) || nativeTechLeaderSkillsProfile(g) || strongholdLeaderSkillsProfile(g)) &&
(!g.strongholdCards || strongholdLeaderSkillsProfile(g)) && !g.discoveryEnabled && !g.discoveries && !g.discoveryStash &&
!g.greatMaker && !g.ecazTreachery && !g.semutaPreview && !g.mentatQuestionPreview &&
((!g.moritaniAssassinatePreview && !g.moritaniAssassinate) || advancedMoritaniLeaderSkillsProfile(g)) && !g.advancedPreview &&
!g.kullPreview && !g.nexusKullPreview && !g.guildBetrayalPreview && !g.richeseBetrayalPreview &&
@@ -9393,7 +9393,7 @@ export function initializeLeaderSkillsGameForAudit(state: Game): Game {
export function initializeSpiceBankerIncomeGameForAudit(state: Game): Game {
requireRule(bankerIncomeProfile(state) && !state.leaderSkills &&
!state.spiceBankerIncomePreview && state.spiceBankerIncome === undefined,
'Spice Banker income requires a fresh classic or supported native lobby with Leader Skills alone.');
'Spice Banker income requires a fresh classic or supported native skill lobby without unsupported optional modules.');
requireFreshSetup(state, state.expansions.length > 0);
const g = structuredClone(state);
g.leaderSkills = createLeaderSkills(random);
@@ -9420,10 +9420,14 @@ function initializeSetupGameForAudit(state: Game, homeworlds: boolean, nexus = f
homeworldShipmentIntegrity(state);
const g = structuredClone(state);
requireFreshSetup(g, homeworlds || nexus || ix || factions);
const skillTech = leaderSkills && (classicTechLeaderSkillsProfile(g) || nativeTechLeaderSkillsProfile(g));
const skillStronghold = leaderSkills && strongholdLeaderSkillsProfile(g);
const skillTech = leaderSkills && (classicTechLeaderSkillsProfile(g) || nativeTechLeaderSkillsProfile(g) || skillStronghold);
requireRule(!g.techTokens || (skillTech &&
JSON.stringify(g.techTokens) === JSON.stringify(createTechTokens())),
'Leader Skills with Tech Tokens requires a fresh supported classic/native three-through-six-seat lobby with unused tokens.');
requireRule(!g.strongholdCards || strongholdFactions || (skillStronghold &&
JSON.stringify(g.strongholdCards) === JSON.stringify(createStrongholdCards())),
'Leader Skills with Stronghold Cards requires a fresh supported Advanced lobby with unused cards.');
requireRule(
(homeworlds || nexus || ix || choam || factions || g.expansions.length === 0) &&
(choam || factions || !g.expansions.includes('choam')) &&
@@ -9433,7 +9437,7 @@ function initializeSetupGameForAudit(state: Game, homeworlds: boolean, nexus = f
(nexus || !g.nexusCards) &&
(ecazTreachery || !g.ecazTreachery) &&
(!g.techTokens || skillTech) &&
(strongholdFactions || !g.strongholdCards) &&
(strongholdFactions || skillStronghold || !g.strongholdCards) &&
(homeworlds || !g.homeworlds) &&
g.players.every((p) =>
FACTIONS.some(
+28 -4
View File
@@ -29,14 +29,16 @@ export function noOtherLeaderSkillModules(game: LeaderSkillProfile): boolean {
!game.discoveryEnabled && !game.strongholdCards && !game.techTokens && !game.ecazTreachery;
}
/** E1/E2 native skills may add Tech alone; each native predicate retains its original roster/decks. */
/** E1/E2 native skills may add Tech and Advanced Strongholds; original roster/decks remain. */
function nativeLeaderSkillModulesSupported(game: LeaderSkillProfile): boolean {
if (noOtherLeaderSkillModules(game)) return true;
const players = game.players;
if (!game.techTokens || !players || players.length < 3 || players.length > 6 ||
if ((!game.techTokens && !game.strongholdCards) || !players ||
players.length < (game.techTokens ? 3 : 2) || players.length > 6 ||
(game.strongholdCards && game.advanced !== true) ||
game.expansions.length < 1 || game.expansions.length > 2 ||
game.homeworlds || game.nexusCards || game.discoveries || game.discoveryEnabled ||
game.strongholdCards || game.ecazTreachery || game.semutaPreview ||
game.ecazTreachery || game.semutaPreview ||
game.moritaniAssassinatePreview || game.advancedPreview || game.kullPreview ||
game.nexusKullPreview || game.guildBetrayalPreview || game.richeseBetrayalPreview ||
game.nexusIxianReplacementPreview || game.nexusIxianBetrayalPreview ||
@@ -69,6 +71,28 @@ export function classicTechLeaderSkillsProfile(game: LeaderSkillProfile): boolea
return true;
}
/** Original Advanced Strongholds, with optional Tech, for classic or supported E1/E2 skills. */
export function strongholdLeaderSkillsProfile(game: LeaderSkillProfile): boolean {
if (!game.strongholdCards || game.advanced !== true) return false;
if (game.expansions.length) return advancedNativeLeaderSkillsProfile(game);
const players = game.players;
if (!players || players.length < (game.techTokens ? 3 : 2) || players.length > 6 ||
game.homeworlds || game.nexusCards || game.discoveries || game.discoveryEnabled ||
game.ecazTreachery || game.semutaPreview || game.moritaniAssassinatePreview ||
game.advancedPreview || game.kullPreview || game.nexusKullPreview ||
game.guildBetrayalPreview || game.richeseBetrayalPreview ||
game.nexusIxianReplacementPreview || game.nexusIxianBetrayalPreview ||
game.nexusHarkonnenBetrayalPreview) return false;
for (let i = 0; i < players.length; i++) {
for (let j = 0; j < i; j++) if (players[j].faction === players[i].faction) return false;
let classic = false;
for (const faction of FACTIONS)
if (faction.id === players[i].faction && faction.expansion === 'base') { classic = true; break; }
if (!classic) return false;
}
return true;
}
/** Bounded integration of the ordinary Moritani roster, not Advanced assassination. */
export function basicMoritaniLeaderSkillsProfile(game: LeaderSkillProfile): boolean {
return game.advanced === false && game.expansions.length === 1 &&
@@ -233,5 +257,5 @@ export function nativeTechLeaderSkillsProfile(game: LeaderSkillProfile): boolean
export function ordinaryLeaderSkillModeSupported(game: LeaderSkillProfile): boolean {
return (noOtherLeaderSkillModules(game) &&
(!game.expansions.length || nativeExpansionLeaderSkillsProfile(game))) ||
classicTechLeaderSkillsProfile(game) || nativeTechLeaderSkillsProfile(game);
classicTechLeaderSkillsProfile(game) || nativeTechLeaderSkillsProfile(game) || strongholdLeaderSkillsProfile(game);
}
+2 -2
View File
@@ -1,7 +1,7 @@
import { treacheryDeck, type Card } from './cards';
import { richeseCards } from './richese-cards';
import { quoteTupileIntelligenceAnswer } from './tupile-intelligence-answer';
import {classicTechLeaderSkillsProfile,nativeExpansionLeaderSkillsProfile,nativeTechLeaderSkillsProfile,noOtherLeaderSkillModules,type LeaderSkillProfile} from './leader-skill-profile';
import {classicTechLeaderSkillsProfile,nativeExpansionLeaderSkillsProfile,nativeTechLeaderSkillsProfile,noOtherLeaderSkillModules,strongholdLeaderSkillsProfile,type LeaderSkillProfile} from './leader-skill-profile';
export class MentatQuestionError extends Error {}
export const MENTAT_EMPTY_HAND =
@@ -43,7 +43,7 @@ export function mentatQuestionModeSupported(game: LeaderSkillProfile): boolean {
return (noOtherLeaderSkillModules(game) &&
(!game.expansions.length ||
(game.expansions.length === 1 && game.expansions[0] === 'choam') ||
nativeExpansionLeaderSkillsProfile(game))) || classicTechLeaderSkillsProfile(game) || nativeTechLeaderSkillsProfile(game);
nativeExpansionLeaderSkillsProfile(game))) || classicTechLeaderSkillsProfile(game) || nativeTechLeaderSkillsProfile(game) || strongholdLeaderSkillsProfile(game);
}
function inventory(expansions: readonly string[]): Card[] {
return [
+8 -4
View File
@@ -3180,6 +3180,7 @@ export const RULE_TOPICS: RuleTopic[] = [
'The mobile card copies a currently controlled stronghold, even if another faction still holds that location’s card. Holding a card after leaving its location does not itself make that location an eligible copy. The choice is public and fixed before battle plans; a sole eligible advantage is announced automatically.',
'Arrakeen pays only for actual support and creates no personal cash. CHOAM force-payment income includes the bank contribution, subject to its normal traitor and donor exclusions. Carthag does not protect an empty or Worthless defense, stop Poison Tooth, or remove a Shield’s Lasgun explosion risk.',
'Sietch Tabr uses the opposing dial, excluding leaders and other bonuses. A single traitor victory qualifies; mutual destruction does not. Tuek pays after an ordinary loss or a single traitor outcome as well as a win; a double traitor gives neither faction spice. Habbanya also decides a tied Stone Burner comparison.',
'Fresh Advanced local development tables may combine all fourteen Leader Skills with Stronghold Cards in classic or supported Ixian, Tleilaxu, CHOAM and Richese skill rosters, two through six players; optional Tech Tokens needs three through six. Original deck/cache and end-Mentat claims remain. Arrakeen pays bank support, not personal income; only the remaining actual payer debit qualifies separate normal Banker income. Skill rescue preserves the original support charge, then card cleanup and Tech reward finish before Face Dance. Modified/copied Diplomat defenses and active skill/Stone interpretations stay guarded; public activation, E3/other overlays and save conversion remain separate.',
'The six effects, public ownership and pre-plan choice are integrated in development games. Enable Stronghold Cards in an Advanced preview lobby. Complete Advanced compliance and every expansion interaction remain under verification.',
],
example:
@@ -3197,7 +3198,7 @@ export const RULE_TOPICS: RuleTopic[] = [
area: 'Implementation',
status: 'Partial',
detail:
'All six local effects and end-Mentat custody are integrated. Full optional-module combinations remain under review.',
'All six local effects and end-Mentat custody are integrated. Fresh Advanced classic/supported E1/E2 skill rosters additionally compose all14 skills and optional original Tech, preserving subsidy, typed rescue, native income and reward order. Full optional-module combinations remain open.',
evidence: [
'game/stronghold-cards.ts',
'game/stronghold-battle.ts',
@@ -3232,10 +3233,12 @@ export const RULE_TOPICS: RuleTopic[] = [
area: 'Verification',
status: 'Partial',
detail:
'Focused ownership, payment, defense, ties and income checks pass. Whole-game and all-combination acceptance remains unfinished.',
'Dated standalone cases remain. Skills/Stronghold adds21 meaningful cases,277 affected and72 final fixture-consumer cases, types/lint/build, twelve actual programs and22 genuine paired/triple games (6672 actions/no rejection,171 JSON continuations). Human390px real subsidy/Banker/Mentat and HMS copied support/typed Suk/Tech preserve original outcomes on refresh. Full/deployed acceptance remains unfinished.',
evidence: [
'tests/stronghold-cards.test.ts',
'tests/stronghold-engine.test.ts',
'tests/classic-skills-stronghold-runtime.test.ts',
'tests/native-skills-stronghold-runtime.test.ts',
],
},
],
@@ -3281,7 +3284,7 @@ export const RULE_TOPICS: RuleTopic[] = [
'Fremen reserve arrivals and Guild cross-planet or return shipments do not trigger Heighliners. A stopped shipment never arrives and cannot trigger it. Bene Gesserit accompanying forces do arrive from off planet and can trigger the token even after a Guild shipment.',
'A battle winner takes one tech token from the defeated faction after casualties and played-card decisions. With several available tokens, the winner chooses. A winner still takes the token if no winning forces survive. Mutual destruction has no winner and transfers no token.',
'Owning all three tokens counts as one additional stronghold at victory checks. An alliance cannot combine separate token holdings to qualify: one member must own the complete set. Multiple sides reaching the victory target can share the win.',
'Token ownership and pending income are public and persist with the room. The fresh classic Leader Skills composition retains original three-through-six-seat Basic/Advanced setup and effects. Skill rescue or board-spice awards finish before the original mandatory token reward; normal Banker remains a separate source-to-Mentat opt-in. Two-player token setup, native factions, other optional modules and full combined acceptance remain unfinished.',
'Token ownership and pending income are public and persist with the room. Fresh supported classic or E1/E2 native Leader Skills tables retain original three-through-six-seat Basic/Advanced setup and effects; Advanced may also retain Stronghold Cards. Skill rescue or board-spice awards finish before the mandatory original winner token reward and later Face Dance. Banker remains a separate source-to-Mentat opt-in. CHOAM’s separate native opening payout is not ordinary poverty Charity. Two-player tokens, E3/other combinations and full combined acceptance remain unfinished.',
],
example:
'You own Heighliners and Axlotl Tanks. When Emperor ships from reserves, place two spice on Heighliners. A later shipment adds nothing. Collect the two spice when Shipping and Movement ends.',
@@ -4590,6 +4593,7 @@ export const RULE_TOPICS: RuleTopic[] = [
'Basic Moritani retains base opponents including Harkonnen. Its separate bounded Advanced classic/non-Harkonnen roster now composes the original assassination preview and all fourteen skills: winner Suk rescue and Rihani choice finish first, then an eligible different trained disc may be assassinated with its exact card return and printed bounty. No casualties repeat; original set-aside and one private Mentat replacement remain. See Moritani with Leader Skills for the exact scope.',
'Fresh Advanced profiles compose native Ixians, Tleilaxu, CHOAM and/or Richese with classic opponents and distinct required family decks. All fourteen skills and native starts remain. Auditor stays unskilled; cyborg casualties, original CHOAM support and Richese capped marker revelation remain physical. Foreign revival creates no new skill. Native Ixian Technology on Richese lots, own mixed No-Field, captured replacement, Advanced Atreides Suk/KH and unrelated overlays retain their guards.',
'Fresh three-through-six-seat Basic/Advanced development tables may compose all fourteen Leader Skills with the three original Tech Tokens: classic factions or the already-supported native Ixian, Tleilaxu, CHOAM and Richese skill rosters with their original required decks. Starting cards, cache, native skill/Traitor choices and printed or first-Storm token assignment stay genuine. Existing leader-skills and banker-income local entry preserve unused selected tokens; E3, other overlays, public activation and saved-game conversion remain separate.',
'Fresh Advanced classic or supported E1/E2 native two-through-six-seat skill tables may also retain all six original Stronghold Cards, with optional Tech at three or more seats. Original end-Mentat claims and retained local advantages remain. Arrakeen changes actual payer cost, not physical rescue or normal Banker eligibility; bank-funded support still counts in native CHOAM income. Played Carthag defenses and normal disciplines, holder-only ties and opposing-dial or played-Worthless earnings use original outcome rules. Public activation, E3/other overlays, modified Diplomat defenses and active skill/Stone interpretations stay separate.',
'With this optional module, starting Treachery Cards are dealt after prediction and before skill assignment. Every faction privately receives two skills, keeps one, returns the other to the shuffled deck, and assigns its chosen card to an eligible leader. Skill and leader become public before traitor selection.',
'Before Battle Plans, leave the skilled leader face up to keep its normal effect, or move it behind the shield for possible use. A face-up leader cannot be selected for the plan. Concealing it while choosing another leader gives neither effect. A leader that must be used because no alternative remains moves behind the shield automatically.',
'Warmaster, Master of Assassins, Swordmaster of Ginaz, Killer Medic and Prana-Bindu Adept are connected. They give another leader +1 for the matching physical card role, or the surviving assigned leader +3. These bonuses do not stack to +4. They change battle strength, not the printed disc value or leader bounty.',
@@ -4617,7 +4621,7 @@ export const RULE_TOPICS: RuleTopic[] = [
{ area:'Player controls',status:'Partial',detail:'Private card/leader selection, readable inspectors, public battle posture and revival draw/decline, Planetologist range/gather controls, Special weapon selection and Suk Graduate physical rescue choices are connected. Rihani has private history and separate keep-new/reveal-old controls; automatic battle effects need no confirmation. Smuggler has explicit ordinary shipping opt-out and No-Field companion opt-in with physical-versus-priced force counts, plus automatic surviving-leader battle collection with reveal-time guidance. Banker exposes separate sealed spending and authorized inspection. Sandmaster exposes explicit legal routes, per-territory collection choices and an optional worm-destination checkbox. Diplomat offers a named committed Worthless choice or decline after public reveal, and a separate surviving-loser destination/normal/elite retreat or decline. Bureaucrat offers redirect or full payment with explicit recipient amounts and deferred bribe custody. Remaining effect controls are missing.',evidence:['components/leader-skills.tsx','components/planetologist-movement.tsx','components/suk-graduate.tsx','components/rihani-decipherer.tsx','components/mentat-question.tsx','components/bureaucrat-payment.tsx','components/leader-skill-battle-guide.tsx','components/smuggler-shipment.tsx','components/spice-banker.tsx','components/sandmaster-movement.tsx','components/sandmaster-worm.tsx','components/diplomat-defense.tsx','components/diplomat-retreat.tsx','components/game-table.tsx'] },
{ area:'AI',status:'Partial',detail:'All four profiles use private offers, legal visibility/revival actions and Planetologist movement/battle candidates and legal Suk Graduate rescues, Rihani exchanges, shared battle scoring, Smuggler reserve/owned No-Field shipments and unmodified collection plans, Sandmaster route and worm collection, funded Banker commitments and optional Diplomat copying from public revealed defenses or choosing legal losing-battle retreat. Bureaucrat uses the public payee alliance to redirect enemy income or preserve allied income. These are legal prototype paths; complete skill strategy and difficulty calibration remain unfinished.',evidence:['game/bots.ts'] },
{ area:'Documentation',status:'Partial',detail:'All fourteen faces and common rules are recorded. Skilled capture follows public physical-card custody; replacement entitlement and other material timing interpretations remain explicit.',evidence:['docs/LEADER_SKILLS_RULES.md','docs/LEADER_SKILLS_CAPTURE.md','docs/LEADER_SKILLS_RUNTIME.md','docs/PLANETOLOGIST_RULES.md','docs/SUK_GRADUATE_RULES.md','docs/LEADER_BATTLE_EFFECTS.md','docs/MENTAT_QUESTION.md','docs/BUREAUCRAT_PAYMENTS.md','docs/SMUGGLER_SHIPMENT.md','docs/SPICE_BANKER_RUNTIME.md','docs/SANDMASTER_WORM.md','docs/DIPLOMAT_DEFENSE.md'] },
{ area:'Verification',status:'Partial',detail:'Dated classic Skills/Tech evidence:25 cases,146 affected cases, eight genuine Basic/Advanced3..6 games (2712 actions,69 JSON continuations) and human Smuggler/payment/Mentat/Suk/two-token reward. Native E1/E2 adds52 meaningful cases,261 passing shared cases plus the corrected exact obsolete rejection, types/lint/build, nine actual programs and seventeen genuine3-seat games (fifteen native,5733 accepted actions/no rejection,149 JSON continuations). Human390px mixed cyborg Suk rescue, original Tech before real-source Face Dance, and Richese marker5/free companion/price1 use original controls and preserve outcomes on refresh. Full combinations, assurance, public and deployed acceptance stay open.',evidence:['tests/leader-skills-engine.test.ts','tests/leader-skills-capture.test.ts','tests/leader-battle-effects.test.ts','tests/suk-graduate.test.ts','tests/mentat-question.test.ts','tests/bureaucrat-payment.test.ts','tests/smuggler-battle.test.ts','tests/spice-banker.test.ts','tests/advanced-native-skills.test.ts','tests/fixture-advanced-native-skills.ts','tests/skills-tech-payments-runtime.test.ts','tests/skills-tech-battle-runtime.test.ts','tests/ix-choam-skills-tech-runtime.test.ts','tests/tleilaxu-skills-tech-runtime.test.ts','tests/richese-skills-tech-runtime.test.ts','docs/LEADER_SKILLS_RUNTIME.md'] },
{ area:'Verification',status:'Partial',detail:'Dated classic Skills/Tech evidence:25 cases,146 affected, eight genuine games (2712 actions,69 JSON continuations) and human payment/Mentat/Suk/token choice. Native Skills/Tech:52 meaningful cases, seventeen genuine3-seat games (5733 actions/no rejection,149 JSON continuations) and human typed rescue/FaceDance/marker companion. Advanced Skills/Stronghold adds21 meaningful cases,277 affected,72 final fixture-consumer cases, types/lint/build, twelve actual programs and22 genuine paired/triple games (6672 actions/no rejection,171 JSON continuations). Human390px actual bank2/own4 with trained rescue and Banker12→13 at Mentat, plus HMS declared bank1/own0/typed Suk/sole Axlotl, preserve original outcomes on refresh. Full combinations, assurance, public and deployed acceptance stay open.',evidence:['tests/leader-skills-engine.test.ts','tests/leader-skills-capture.test.ts','tests/leader-battle-effects.test.ts','tests/suk-graduate.test.ts','tests/mentat-question.test.ts','tests/bureaucrat-payment.test.ts','tests/smuggler-battle.test.ts','tests/spice-banker.test.ts','tests/advanced-native-skills.test.ts','tests/fixture-advanced-native-skills.ts','tests/skills-tech-payments-runtime.test.ts','tests/skills-tech-battle-runtime.test.ts','tests/ix-choam-skills-tech-runtime.test.ts','tests/tleilaxu-skills-tech-runtime.test.ts','tests/richese-skills-tech-runtime.test.ts','tests/classic-skills-stronghold-runtime.test.ts','tests/native-skills-stronghold-runtime.test.ts','docs/LEADER_SKILLS_RUNTIME.md'] },
],
},
{