Imported from yeager-j/pdx-ts-sdk (
AGENTS.md). Install upstream withnpx skills add yeager-j/pdx-ts-sdk. Copyright stays with the author.
Repository guidance
Project purpose
@pdx-ts/sdk is a TypeScript SDK for generating Stellaris mods. Mod authors run ordinary
TypeScript at build time; the SDK records typed triggers, effects, content definitions, and file
layout, then serializes a launcher-ready mod in PDXScript.
The repository root is a private npm-workspaces root: it owns the shared inputs (vendor/,
fixtures/, examples/, the tsconfigs and the vitest config) and no source of its own.
Every package, generators included, is a workspace member: packages/sdk is the Stellaris-facing
SDK (@pdx-ts/sdk); packages/pdxscript is the standalone PDXScript parser/serializer used
underneath it; packages/codegen-cwt and packages/codegen-vanilla are the two private generators;
packages/stellaris-ids is the install-derived identifier package; packages/corpus is the
corpus evidence loop (the committed fixture, the extract and check commands, the gap and
observation ledgers, and the conformance gate). Every gate below runs from the repository root.
CONTEXT-MAP.md is the vocabulary authority: it names this repo's six
bounded contexts and links each one's glossary. When a word here is load-bearing, that is
where it is defined — this file states process, not meaning. Decisions that would otherwise
look arbitrary are recorded in docs/adr/.
Read README.md before making architectural changes.
Repository conventions
- Use npm
- Keep the project strict TypeScript and ESM. Internal relative imports include the
.tsextension. - The package is private and has not been released, so breaking changes are allowed and encouraged over band-aids or migrations.
- Prefer data-driven additions to registry-specific branches. Shared runtime machinery belongs in
packages/sdk/src/; source interpretation and emitted TypeScript belong inpackages/codegen-cwt/src/; deliberate exceptions belong in the audited overlay. - Keep changes focused. Do not update the CWT submodule, drift baselines, snapshots, or generated output unless the task requires the corresponding source change.
Code generation
packages/sdk/src/generated/ is committed generator output. Most files come from
packages/codegen-cwt/ (@pdx-ts/codegen-cwt); verified-build.ts comes from the hermetic
@pdx-ts/codegen-vanilla verified-build projection. Never edit generated files by hand.
packages/create-stellaris-mod/src/generated/package-version.ts and
packages/docs-site/lib/generated/sdk-docs-revision.ts are the exception: they hold a hash of
packages/sdk/src and are regenerated on every install, typecheck, test, and build, so they are
gitignored rather than committed.
The main inputs are:
vendor/cwtools-stellaris-config/, a pinned submodule of our CWT config fork, for rules and Stellaris documentation dumpspackages/codegen-cwt/src/policy/manifest.tsfor the content registries intentionally exposed by the SDKpackages/codegen-cwt/src/overlay/for reviewed departures from a mechanical reading of the rules- emitters and parsers under
packages/codegen-cwt/src/
Use:
npm run codegen
After generation:
- Read the codegen report. Unsupported, omitted, or collapsed fields must remain visible; do not hide them with filters.
- Inspect the complete
packages/sdk/src/generated/diff as a public-API change. - Commit generated output together with the source change that produced it.
- Keep generated headers and formatting generator-owned.
npm run codegen:check regenerates and then runs git diff --exit-code packages/sdk/src/generated.
It is the CI-style drift gate. During an intentional uncommitted codegen change, use
npm run codegen and inspect the diff; the check will correctly fail until the generated diff is
part of the comparison baseline (for example, staged or committed).
Do not run npm run codegen -- --rebaseline reflexively. Rebaseline
packages/codegen-cwt/src/drift-baseline.json only after reviewing and intentionally accepting drift between
the pinned rule sources and documentation dumps.
Vanilla identifier package
packages/stellaris-ids (@pdx-ts/stellaris-ids) is a separate, install-derived package
carrying every identifier vanilla Stellaris defines: content ids, scripted trigger/effect names
with their $PARAM$ lists, event ids and namespaces, sprite and sound names, resource keys. It is
generated by @pdx-ts/codegen-vanilla (packages/codegen-vanilla), a generator separate from
@pdx-ts/codegen-cwt: install-derived
versus CWT-derived are different sources, with different regeneration triggers and different
failure modes.
Adding a registry, adding a patch registry, closing a corpus gap
All three are recipes rather than ground rules, so they live as skills and load only when the task fires them:
add-registry(.agents/skills/add-registry/) — a new content registry:mod.<type>, itsDef/Itemtypes, the overlay rows, and the four kinds of evidence, from one manifest row.add-patch-registry(.agents/skills/add-patch-registry/) — whole-object patching for a registry: the oracle-backed rule row, the parse row, and theCONTENT_PATCH_REGISTRIESoverlay row that generates the wholepatchXsurface.close-corpus-gap(.agents/skills/close-corpus-gap/) — lowering a field the game writes and no author can produce, retiring itspackages/corpus/src/gaps.tsrow: measuring the real shape against the install before encoding it, and where the generic model absorbs it.
patchX is not a consequence of mod.x existing: a patch is a whole-object
override whose load order and emission are verified per registry, and the
overlay row is the permission. Do not add mod.patchAscensionPerk merely
because mod.ascensionPerk exists.
PDXScript parser
Parser work belongs in packages/pdxscript/. Read packages/pdxscript/README.md and
packages/pdxscript/GRAMMAR.md before changing it.
Keep the package syntax-only and game-semantics-free. It preserves order and duplicate keys, reports repairs to malformed shipped input, and promises semantic rather than byte-identical round trips. Parser changes should retain the per-claim tests, full-vanilla fixpoint, jomini differential, and fast-check property gates described in that package.
Important design boundaries
ADRs are located in docs/adr.
What remains here are working rules rather than definitions:
- Diagnostics are throws or
mod.warningsdata — never console output. src/features.tsdeclares a project's module tree: it re-exports each feature module'sfeature;mod.featuretakes one Item namespace or a shallow array of Items and namespaces, whilemod.compileandproject.buildtake Feature arrays or namespaces (ADR-0008). Nothing walks the filesystem for Features. Source layout is not identity.- Cross-content references should remain branded objects where the generated rules know the registry. Use raw strings only for intentional vanilla or third-party references supported by the API.
- Generated content ids and nested definition ids must use the mod prefix.
- Preserve the localization duplicate-key checks and the BOM-prefixed Stellaris localization output.
- Unsupported game semantics should fail loudly rather than be guessed.
Verification
For ordinary SDK changes, run:
npm run typecheck
npm test
npm run build
Also run npm run codegen whenever codegen inputs or implementation change, and inspect the
result. Use npm run example when changing synthesis behavior or the quickstart example.
For changes to packages/pdxscript, also run npm run test:vanilla. npm test skips the
full-vanilla fixpoint and the jomini differential when no Stellaris install is present, and those
two are the package's only evidence that it reads real files the way the game does. That command
refuses to skip them; npm run release:check requires it.
Prefer focused Vitest runs while iterating, but finish with the full relevant gates. Snapshot changes are review evidence: update them only when the serialized output change is intentional, then inspect their contents rather than accepting them blindly.
Agent skills
Issue tracker
Issues are tracked in the @pdx-ts/sdk Linear team through the Linear MCP connector. See docs/agents/issue-tracker.md.
Domain docs
This is a multi-context repository. Start with CONTEXT-MAP.md, then read the relevant package context and ADRs. See docs/agents/domain.md.
Codex Code Review Rules
Apply the code-style Skill (.agents/skills/code-style/SKILL.md) when reviewing code. Use the Diagnostics section of the Skill as a rubric, literally. Create a temporary file and list the diagnostics. As you review the diff, list any violations under the correct diagnostic item with a code citation and reasoning.