Council Rank
Progression belongs to a Character, not a wallet-wide balance pooled across Profiles. Activities earn career XP; career levels provide career research points and contribute toward Council Rank Renown. Research turns those points into capabilities.
XP, career research points, and Renown
Section titled “XP, career research points, and Renown”These are different units:
| Value | Meaning |
|---|---|
| Career XP | Activity experience recorded in that career’s earned field. |
| Career level | The level stored on the Character, governed by the Game’s XP thresholds. |
| Career research points | One per career level; available points are level - spent, clamped to zero. |
| Council Rank Renown | A separate research currency; available Renown is earned - spent, clamped to zero. |
The six careers are Pilot, Data Runner, Mining, Building, Crafting, and Combat. The current PTR configuration awards one Renown per six career level gains across those careers. This counts levels gained, not unspent career points: spending a career point is not an exchange into Renown. For example, three Pilot and three Mining levels provide three research points in each career and one Renown before spending. Daily XP is a separate category, not one of these six careers.
Do not hardcode six for another deployment or future release. The Game exposes
xpDefinitions.renown.divisor and feederCategories. The Character’s
xp.councilRankLevelCarry records career-level progress toward the next Renown.
Stored Council Rank level and available Renown are distinct values.
Fetch balances and acquired nodes quickly
Section titled “Fetch balances and acquired nodes quickly”All Character-local inputs are already available from one Character account
read, with no Game or research catalog required. Repeated reads use the
context cache; use { refresh: true } when you need current state.
Requires an existing ctx and a known profileAddress (verified by the guide
snippet gates):
import { getCharacterForProfile, deriveCharacterResearchState,} from '@aephia/atlas-kit/identity';
const character = await getCharacterForProfile(ctx, profileAddress);const research = deriveCharacterResearchState(character);
research.careers.pilot.earnedXp;research.careers.pilot.level;research.careers.pilot.researchPointsAvailable;research.renown.available;research.nodes; // acquired { nodeId, level } rowsJSON.stringify(research); // bigint values become decimal stringsDo not calculate career points as earned - spent: career earned is raw
XP while career spent counts research points. Keep the arithmetic in bigint.
The helper returns an immutable, JSON-serializable projection without any extra
reads or cache. careers contains all six careers, with earnedXp, level,
researchPointsSpent and researchPointsAvailable. renown separately exposes
earned, spent, available, level and careerLevelCarry. Daily XP is not
included in the career balances; it remains available on character.xp.dailyXp.
nodes includes acquired nodes only, not a historical receipt of purchases.
An unlocked node without a stored nodeLevels entry defaults to level 1; a node
absent from unlockedNodes is not acquired. Stored levels are reported as-is, including 0; only a missing entry defaults
to 1. This preserves observed state rather than the official client’s minimum-1
normalization for synchronization estimates. The original stored rows remain on
character.modifiers.nodeLevels.
Catalog costs use category labels that map to projection fields as follows:
xpCosts[].category | Balance source |
|---|---|
pilot, mining, building, crafting, combat | careers.<same>.researchPointsAvailable |
data-runner | careers.dataRunner.researchPointsAvailable |
council-rank | renown.available |
daily | Not projected; character.xp.dailyXp.earned - spent, clamped to zero |
This mapping identifies balances; it does not check all node prerequisites or authorize a purchase.
The projection reports xpSequenceId, researchSequenceId and
pendingNodeUpdates from the input. It does not fetch definitions or assert that
the Character is synchronized. Refresh through getCharacterForProfile and
project again when the underlying read needs updating.
Add thresholds and node descriptions when needed
Section titled “Add thresholds and node descriptions when needed”Requires the same context and Profile address (verified by the guide snippet gates):
import { getCharacterProgressionForProfile, getResearchCatalog,} from '@aephia/atlas-kit/identity';
const progression = await getCharacterProgressionForProfile( ctx, profileAddress,);const renownRules = progression.xpDefinitions.renown;const thresholds = progression.xpDefinitions.levelThresholds;const catalog = await getResearchCatalog(ctx);The progression read joins Character XP to sequence-matched Game XP rules; it does not invent levels. These optional definition reads load the large Game account through the shared lazy registry. Reuse the context so definitions and Character reads can be cached/deduplicated; do not fetch a Game per career or per node. Separate Character/catalog reads are not an atomic chain snapshot.
Stored levels reflect the rules at character.xp.seqId. If that sequence differs
from the Game XP definitions, the progression read throws
RegistryOutOfSyncError. The Character must be synchronized with the current
game rules before relying on its levels; refreshing a read alone does not
synchronize on-chain state.
Catalog nodes expose xpCosts with category, minimumLevel, and costRaw.
Despite the field name, a career-category cost is career research points;
council-rank costs are Renown. Daily XP is a separate currency. Minimum level
is an eligibility threshold, not a deduction. Nodes also expose ATLAS and cargo
costs, prerequisite requiredTagIds, maxLevel, cost growth and modifier.
Node IDs and prerequisite tags must not be treated as interchangeable.
For context, these dated PTR definitions were read on October 11, 2026; they are not an eligibility or successful-purchase claim:
| Node | Points | Other requirements/costs |
|---|---|---|
| Fleet Size - Tier 1 (1) | 1 Renown | 0 ATLAS; prerequisite tag |
| X-Small Ships (31) | 1 Pilot research point | 350 ATLAS; prerequisite tag |
| Contested Space Scanning (18) | 1 Data Runner research point | Data Runner level 5; 350 ATLAS; cargo; prerequisite tag |
| Enemy Faction Scanning (19) | 1 Data Runner research point | Data Runner level 22; Combat level 5; 350 ATLAS; cargo; prerequisite tag |
The Points column lists only nonzero point costs. Zero-cost category entries carry level requirements only (including Council Rank level 0 for X-Small Ships and Combat level 5 for Enemy Faction Scanning).
The catalog had 243 definitions, not necessarily 243 visible nodes or 243 total spendable points. The game client can hide or disable nodes. Read current costs instead of assuming a universal 350 ATLAS fee or a fixed total tree price.
Join acquired node IDs to catalog id values for names and descriptions; retain
IDs that do not resolve rather than silently discarding acquired state. Applied
perks live in character.modifiers.values. fleetSize limits ship capacity
within a Fleet; fleetConcurrency limits Fleet count. Compare the latter with
character.counts.fleets when displaying remaining Fleet slots. That comparison
alone is not a complete action-eligibility check.
Treat these applied perks as current only when character.modifiers.seqId
matches catalog.sequenceId and character.modifiers.unupdatedCount === 0.
After a research-definition update, synchronization rebuilds the modifiers;
until it finishes, values such as Fleet concurrency may lag current rules.
Synchronize the Character in the game, then refresh it and the relevant
definitions before presenting those limits as current.
Unlock a research node
Section titled “Unlock a research node”Use planUnlockResearchNode to raise one node to its next level for your
Profile’s Character. Name the node and the level it will reach: a node you have
not unlocked reaches level 1, and a repeatable node (maxLevel 0) at level 3
reaches level 4. The planner never picks a level or unlocks prerequisites for
you.
This example is illustrative. Supply your application’s context, the System of a Starbase where your Character has a Starbase Player, and explicit authorization; it only prepares an inspectable Plan.
import { planUnlockResearchNode } from '@aephia/atlas-kit/identity/actions';import type { Address, SageContext } from '@aephia/atlas-kit/client';
declare const ctx: SageContext;declare const profile: Address, authority: Address, system: Address;
const plan = await planUnlockResearchNode(ctx, 62, { authorization: { profile, authority, keyIndex: 0 }, system, level: 1,});console.log(plan.describe());The unlock spends, all at once:
- the listed research points from each career, or Renown for Council Rank;
- the node’s ATLAS cost from the Character, grown by
costGrowthBasisPointsfor each level already held and rounded down (350 ATLAS at 10% growth costs 385 ATLAS from level 1 to 2); - any cargo cost from that Starbase Player’s cargo, grown and rounded the same way;
- lamports from the Profile for the Character’s extra storage. The unlock pays them as a locked rent deposit, separate from transaction fees.
The Character grows when the unlock adds entries it did not hold: a newly
unlocked node, a stored level, and any research tag, cargo category or rare
mineral the node grants. A repeated level whose grants the Character already
holds adds nothing. The program takes the growth’s rent from the Profile vault
with the signing key, and returns any surplus storage lamports on the Character
to the Profile. The Plan states the conservative Profile debit. A positive debit
needs a Profile AUTH key or a key that also holds drainSolVault, and Profile
lamports above the Profile’s own rent reserve.
Every required tag must already be on the Character, and each listed category
must be at its minimum level, even when it costs nothing. Any Starbase where the
Character has a current Starbase Player works, including another faction’s.
Use a direct Profile AUTH key or a doResearch key scoped to SAGE or the Game.
When something is missing, planning fails with the exact shortfall, such as the missing tags or how many research points the Character has. Daily XP costs are refused as unqualified.
A Character whose research or XP predates the current Game definitions is also
refused, because the resynchronized Character decides eligibility. The program
resynchronizes it itself at the start of the unlock, as it does for any action
that validates the Character, when at most 8 node levels are pending. Run such
an action and replan. With more pending levels, run the permissionless
syncCharacter instruction until no nodes remain.
Execution rechecks every requirement, both definition sequences, the ATLAS cost and the Profile storage debit before signing. The program adds the node’s tags and modifier to the Character, so read the Character after confirmed execution for the resulting limits. One unlock per Character fits in a transaction.
Limits of the current evidence
Section titled “Limits of the current evidence”The bindings contain per-career XP allowance banks, regeneration rates and bank ceilings. These support a refillable allowance model; they do not establish mainnet progression times or guarantee a particular activity’s awarded XP.
Research time is not a field in the current node definition. Locker-based fee waivers, Starbased XP migration, respec/refund rules and mainnet progression targets are not established here as active contracts. Do not infer them from older announcements.
The point arithmetic above matches researchPointsEarned and
spendableResearchPoints in the
retained official-client evidence
(excerpts and bundle SHA-256, inspected October 11, 2026).
The read-only PTR observations were at slots 59,198,431–59,198,438, Game XP
sequence 26 and research sequence 0. They establish stored configuration.
Unsigned simulations on October 19, 2026 verified the unlock’s deductions,
growth and failures
(research unlock evidence);
no research transaction was signed or submitted.
Reference
Section titled “Reference”identity— public progression and Character reads- You — Profile and Character relationships
- Crafting habs and claim stakes