Skip to content

Quickstart: compile an English pilot package

This walkthrough is for implementation collaborators who already have approved repository access. It proves the current English path, shows the recommended authoring order, and compiles a new package without treating compilation as publication or runtime installation.

阅读中文版

Prerequisites

Run commands from the repository root. The compiler requires Python 3.11+ and uv; the playable local application also requires Node.js 20.19+ and Docker. Use npm run setup if the repository dependencies have not yet been prepared.

1. Prove the compiler with the English canary

The repository's Orbital Garden Relay canary is deliberately synthetic and lives under test fixtures. Compile it with its fixture content root:

bash
uv run --project apps/api meet-u-compile-pilot \
  --content-root apps/api/tests/fixtures \
  --output-root /tmp/meet-u-orbital-bundles \
  --package-id orbital-garden-relay \
  --version 1

A successful result is JSON with "status":"succeeded", paths to the canonical IR and runtime-bundle content, and a content digest. It also says "activatable":false; that is expected.

Verify that the existing content-addressed output exactly matches a fresh compile:

bash
uv run --project apps/api meet-u-compile-pilot \
  --content-root apps/api/tests/fixtures \
  --output-root /tmp/meet-u-orbital-bundles \
  --package-id orbital-garden-relay \
  --version 1 \
  --check

--check does not create the expected output for the first time. Run the ordinary compile first, keep the same output root, and then run --check.

2. Create the package directory

Production-tree source packages use this path:

text
content/creator-sources/my-pilot/v1/

Use a package ID made from lowercase letters, digits, and hyphens, beginning with a letter or digit. The path, compiler argument, and source-package.yaml identity must agree exactly:

yaml
package:
  id: my-pilot
  version: 1

Create all seven fixed YAML filenames listed in the technical package overview. The manifest's six module references are closed literals; the compiler does not accept alternate names or omit a module.

Use the v1 field reference for every field and nested type. The source models reject unknown fields, so do not infer field names from the broader proposal specification.

3. Author meaning before wiring IDs

Write a short Creator brief before filling YAML. Settle these questions:

  1. Who is the character, and what makes their choice recognizably theirs?
  2. Why can the remote user communicate with them without entering the world?
  3. What can the user ask, challenge, comfort, or influence—and what can they never directly do?
  4. What is the bounded dilemma, and which decisions remain faithful?
  5. What objective outcome follows each allowed decision?
  6. What does the character observe, choose to disclose, and later tell the user?
  7. What exact visual and Journal evidence makes the causal chain legible?

This brief is the human-created dramatic foundation. The compiler checks its typed expression; it does not invent missing drama.

4. Fill the seven files in dependency order

A. source-package.yaml

Declare the schema version, package identity, six fixed module references, at least one external provenance reference, and non-empty semantic_parity.preserves and semantic_parity.excludes lists.

This is the manifest shape for the example package:

yaml
schema_version: meet_u.creator_source_package.v1

package:
  id: my-pilot
  version: 1
  display_name: My Pilot
  ip_title: My Original IP
  default_locale: en-US
  primary_character_id: my_character
  arc_id: first_dilemma

modules:
  character: character.yaml
  relationship: relationship.yaml
  arc: arc.yaml
  dialogue: dialogue.yaml
  visual: visual.yaml
  acceptance: acceptance.yaml

provenance:
  - role: semantic_normalization_authority
    ref: creator-private://my-pilot/reviewed-brief-v1

semantic_parity:
  preserves:
    - "REPLACE: specific meaning retained from Creator material or an accepted decision"
  excludes:
    - "REPLACE: mechanics or historical behavior intentionally outside this source"

The manifest also names the primary character and arc IDs. Reuse those exact IDs in character.yaml, relationship.yaml, and arc.yaml.

Every REPLACE value above must be replaced before review. The example creator-private reference is only a placeholder for a durable, access-controlled source record; it does not define an intake storage scheme. Provenance must truthfully identify the source of the normalized meaning; it is not a box to check. The current role vocabulary is unusually narrow. If a new IP's source cannot honestly use one of the allowed roles, do not invent a reference or mislabel the source just to compile—record the contract gap first. See the provenance role boundary for the complete current list and limitation.

B. character.yaml

Define identity, values, goals, contradiction, boundaries, prohibited portrayals, decision tendencies, knowledge limits, disclosure posture, voice, and constructive refusal. Write these as portrayal constraints and dramatic meaning, not as instructions to obey the user.

The constructive_refusal.style_anchor is also the exact text referenced by the current CHAT_ONLY recovery surface. Keep it truthful and useful even when no user-requested effect is permitted.

C. relationship.yaml

Describe the user as a remote confidant and keep the fixed v1 channel flags false: the user has no physical presence; NPCs cannot receive, verify, or answer user messages; and the character cannot forward the raw message.

Choose a small, semantic influence_vocabulary, such as support, challenge, or respected boundary meanings appropriate to this character. These IDs are evidence categories, not keywords and not commands that select a decision.

Add the optional reciprocal promise or invented shared context only when the story genuinely needs it. Every extra semantic mechanism adds cross-file obligations.

D. arc.yaml

Author in this order:

  1. narrative time, world facts, locations, NPCs, and one narrative deadline;
  2. the current Arc Progression V1 phase and its initial character beliefs;
  3. character decisions, each with typed eligibility, qualitative influence fit, one typed action, and one outcome ID;
  4. one deterministic outcome for every decision; and
  5. at least one character-owned follow-up option for every outcome.

Although arc.progression is optional in the base source model, it is required by the only current CLI build target, local_owner_synthetic_preview. Its decision phase must cover every decision exactly once and use the declared world deadline as its single horizon.

Write narrative_time.anchor_local_time and the deadline's narrative_local_time as ISO local times such as "05:20". Quote them so the YAML parser preserves text. If a reciprocal promise has a narrative due time, quote its ends_local_time the same way.

The terminal no_eligible_guidance.public_projection.text must include en-US for an English package. It may also contain zh-CN, but the rest of the package is not translated automatically.

E. dialogue.yaml

Write the exact Creator opening, guided ordinary-dialogue obligations, recovery declarations, one semantic-lock dialogue entry per arc follow-up, and exact Journal copy.

Keep opening.generated_reply_suggestions: false for the current pilot work. The schema can carry a boolean, but accepted product decisions leave broader suggested-reply enablement open; a compilable true value is not authorization to ship that interaction.

For an English package, both recovery.degraded_chat.locale and every recovery.chat_only[].locale must be en-US. Every fact ID in a must_not_disclose_fact_ids list must exist in the arc fact graph.

Across the CHAT_ONLY surfaces, cover the three required immediate recovery contexts exactly once: ordinary_no_effect, capability_boundary, and their combined set. The same exact constructive-refusal anchor may serve all three, as both current example packages do.

The Journal is exhaustive: provide exactly one statement for every influence kind, decision ID, and outcome ID. Statements describe the validated causal record; they must not credit the user with the character's action or the world result.

F. visual.yaml

Declare visual identity, one portrait asset, and exactly one depiction per outcome. Assets must already exist. Package-local paths begin with assets/; the only allowed external alternative is the same package/version's historical pilots/<package-id>/v<version>/assets/ namespace, written relative to the selected content root. For --content-root content, for example, write source_path: pilots/my-pilot/v1/assets/portrait.png; the corresponding repository file is under content/pilots/..., but content/ is not part of the YAML value.

visible_fact_ids may include only externally visible facts committed by that outcome. Put private or visually misleading facts in forbidden_fact_ids. Asset provenance is required authorial traceability; it is not asset approval.

The current compiler accepts .avif, .gif, .jpeg, .jpg, .png, .svg, and .webp assets. The suffix comparison is case-insensitive, and the emitted bundle path is derived from the asset ID and normalized suffix.

G. acceptance.yaml

Write meaning-level cases that distinguish useful user positions, expected influence kinds, allowed decision space, and forbidden effects. Add paraphrase ranges that should preserve meaning across different wording.

Never write quoted phrases as routes. Acceptance cases are evaluation evidence; they cannot directly choose stance, action, outcome, or reply.

5. Compile the package

For the example identity above:

bash
uv run --project apps/api meet-u-compile-pilot \
  --content-root content \
  --output-root /tmp/meet-u-my-pilot-bundles \
  --package-id my-pilot \
  --version 1

After it succeeds, rerun the same command with --check:

bash
uv run --project apps/api meet-u-compile-pilot \
  --content-root content \
  --output-root /tmp/meet-u-my-pilot-bundles \
  --package-id my-pilot \
  --version 1 \
  --check

The compiler reads the whole source and asset closure, validates cross-file meaning, lowers deterministic canonical IR, and emits content-addressed runtime bundle files. It does not call an LLM.

6. Read failures from the outside inward

Error familyWhat to check first
Invalid or duplicate YAMLIndentation, quoting, unique mapping keys, UTF-8 text, and whether the document root is a mapping
Semantic contract violationThe field path in the Pydantic error and the exact type/closed value in the field reference; unknown fields are rejected
Forbidden Creator source fieldRemove runtime, provider, prompt, approval, lifecycle, or raw-text routing configuration from Creator YAML
Package identity mismatchDirectory ID/version, CLI arguments, manifest package identity, primary character references, and arc ID
Unknown or inconsistent referenceTrace the ID across relationship, arc, dialogue, visual, and acceptance modules; do not fix it by inventing a second near-duplicate ID
Missing Arc Progression V1Add arc.progression, a world deadline, full decision coverage, and the default-locale no-eligible projection
Locale catalog or recovery mismatchUse exactly en-US or zh-CN; make every recovery locale equal package.default_locale
Incomplete or ambiguous CHAT_ONLY recoveryCover the immediate ordinary-no-effect, capability-boundary, and combined obligation sets exactly once across all chat_only surfaces
Missing or unsafe assetCheck file existence, case, package-local assets/ path, absence of symlinks or .., and outcome coverage
Unsupported media suffixUse .avif, .gif, .jpeg, .jpg, .png, .svg, or .webp
Journal coverage mismatchProvide one and only one statement for every influence kind, decision, and outcome
--check bundle mismatchCompile once to that output root, keep the same source/compiler/policy inputs, and check that the expected digest directory still exists

Source values must be canonical: mapping keys are strings, floating-point numbers are forbidden, integers must be JavaScript-safe, and booleans should be YAML booleans rather than quoted strings. Declared paths cannot be absolute, escape their allowed root, contain symlinks, or collide after Unicode/case normalization.

7. Stop at the correct boundary

A green compile proves that one frozen source graph can be lowered under the current compiler and platform policy. It does not prove rights, Creator approval, asset approval, behavioral qualification, release eligibility, or activation. Continue with compilation and lifecycle before making any broader claim.

Creator-authored stories. Character-first experiences.