- Project version:
0.7.0-alpha.0, read fromgradle.properties(projectVersionis the source of truth) - JDK: 21, managed by
mise.tomlastemurin-21 - Node.js: 22, required by
docs/package.json - pnpm: 9.12.1 or newer for the docs module
- Gradle: 9.7.1 through
./gradlew - Build scripts: Kotlin DSL
- OpenSpec schema:
spec-driven, configured inopenspec/config.yaml
Common commands:
# Core module tests
./gradlew :xtream-codec-core:test
# Run one test class
./gradlew :module:test --tests "io.example.FullyQualifiedTestName"
# Debug/demo module test
./gradlew :debug:xtream-codec-core-debug:test \
--tests "io.github.hylexus.xtream.debug.codec.core.demo005.DemoMessage005Test"
# Full local build with slow checks disabled
./gradlew build \
-P xtream.backend.build.checkstyle.enabled=false \
-P xtream.backend.build.errorprone.enabled=false
# Full build with checkstyle
./gradlew clean build -P xtream.backend.build.checkstyle.enabled=true
# Update project version references outside release notes
./gradlew updateVersionThe default local settings in gradle.properties disable checkstyle and Error Prone:
xtream.backend.build.checkstyle.enabled=falsextream.backend.build.errorprone.enabled=false
If JAVA_HOME points to a removed JDK, use the JDK resolved by mise before running Gradle:
JAVA_HOME="$(mise where java)" ./gradlew <task>xtream-codec-dependencies/ # Dependency BOM/constraints
xtream-codec-base/ # Shared base APIs, expressions, utilities
xtream-codec-core/ # Annotation-driven codec
xtream-codec-server-reactive/ # Async non-blocking TCP/UDP server
ext/jt/ # JT/T 808 and JT/T 1078 extensions
quick-start/ # Runnable quick-start applications
debug/ # Debug entities, protocol demos, and focused tests
docs/ # VuePress documentation site
openspec/ # Change proposals, specs, and archived changes
build-script/ # Shared Gradle, checkstyle, license, and publishing scripts
debug/ is part of the verification and documentation workflow. Do not ignore it when a change touches demos,
documentation examples, or debug-module tests.
The docs site is VuePress/Vite:
cd docs
pnpm docs:dev # local server
pnpm docs:build # production build
pnpm docs:clean-dev # dev server with a clean VuePress cachedocs/src/.vuepress/config.ts defines source-code import aliases:
@project→ repository root@core-test→xtream-codec-core/src/test/java@core-debug-test→debug/xtream-codec-core-debug/src/test/java@core-debug→debug/xtream-codec-core-debug/src/main/java@src→docs/src/code-snippet
When a Java test, demo, or type is referenced by a docs page, annotate the type with:
@ReferencedByDocs("guide/core/annotation-driven/example.md")The path is relative to docs/src/. Keep the annotation path and the VuePress @[code](...) import path in sync.
The docs build must be run when changing referenced source snippets.
Use the OpenSpec CLI and the repository-local skills for change work:
# Discover active changes
openspec list --json
# Create a new change; do not manually scaffold openspec/changes/<name>
openspec new change "<change-name>"
# Check artifacts and implementation task progress
openspec status --change "<change-name>" --json
openspec instructions apply --change "<change-name>" --json
# Validate a change or all specs
openspec validate "<change-name>" --strict
openspec validate --specs
# Archive after implementation and task completion
openspec instructions archive --change "<change-name>" --jsonFor a new capability, the main spec must contain one ## Purpose section and one ## Requirements section.
Requirements use ### Requirement: and scenarios use exactly #### Scenario:. Do not append a second
## ... Requirements section; merge additional requirements into the main ## Requirements section before archive.
When archiving a change with delta specs:
- Compare each delta under
openspec/changes/<name>/specs/with its corresponding main spec underopenspec/specs/. - Sync new or modified requirements into the main spec.
- Validate the synced main spec and the change with
--strict. - Move the completed change to
openspec/changes/archive/YYYY-MM-DD-<change-name>/.
Don't assume. Don't hide confusion. Surface tradeoffs.
Before implementing:
- State your assumptions explicitly. If uncertain, ask.
- If multiple interpretations exist, present them - don't pick silently.
- If a simpler approach exists, say so. Push back when warranted.
- If something is unclear, stop. Name what's confusing. Ask.
Minimum code that solves the problem. Nothing speculative.
- No features beyond what was asked.
- No abstractions for single-use code.
- No "flexibility" or "configurability" that wasn't requested.
- No error handling for impossible scenarios.
- If you write 200 lines and it could be 50, rewrite it.
Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, simplify.
Touch only what you must. Clean up only your own mess.
When editing existing code:
- Don't "improve" adjacent code, comments, or formatting.
- Don't refactor things that aren't broken.
- Match existing style, even if you'd do it differently.
- If you notice unrelated dead code, mention it - don't delete it.
When your changes create orphans:
- Remove imports/variables/functions that YOUR changes made unused.
- Don't remove pre-existing dead code unless asked.
The test: Every changed line should trace directly to the user's request.
Define success criteria. Loop until verified.
Transform tasks into verifiable goals:
- "Add validation" → "Write tests for invalid inputs, then make them pass"
- "Fix the bug" → "Write a test that reproduces it, then make it pass"
- "Refactor X" → "Ensure tests pass before and after"
For multi-step tasks, state a brief plan:
1. [Step] → verify: [check]
2. [Step] → verify: [check]
3. [Step] → verify: [check]
Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification.
These rules must be followed in ALL generated code.
When adding @since to JavaDoc, use the stable public release line, not the current pre-release artifact version.
- Current artifact version:
0.7.0-alpha.0(projectVersion=0.7.0-alpha.0ingradle.properties) - Current public API
@sincetarget:0.7.0 - New APIs added now →
@since 0.7.0 - Strip pre-release suffixes such as
-alpha.*,-beta.*, and-rc.*fromprojectVersionfor Javadoc. - Do NOT hardcode outdated versions; always check
gradle.propertiesfirst and derive the stable release line.
// Correct (new code):
/**
* @since 0.7.0
*/
default boolean isDerived() { return false; }
// Wrong (version doesn't match gradle.properties):
/**
* @since 0.7.0-alpha.0
*/
default boolean isDerived() { return false; }@Nullable is a type-use annotation. It MUST be placed immediately before the type it modifies, NOT on a separate line before the method declaration.
// Correct — @Nullable before the return type:
public @Nullable String getDisplayName() { ... }
default @Nullable Object getProperty(Object instance) { ... }
public static @Nullable String getVariable(String name) { ... }
// Wrong — @Nullable on its own line before default/modifier:
// @Nullable ← wrong
// default Object getProperty(...) { ... }
// Wrong — @Nullable separated from the return type by a modifier:
// @Nullable private String name; ← wrong
// private @Nullable String name; ← correct (no modifier between @Nullable and the type)Rationale: Per Jspecify 1.0, type-use annotations should be adjacent to the annotated type to avoid ambiguity about what they modify.
All code comments (including JavaDoc, inline comments, TODO, FIXME, etc.) MUST be written in Simplified Chinese unless the comment targets an international audience (e.g., SPI interface docs meant for external contributors).
// Correct (简体中文):
// 将状态码转换为业务枚举
@Nullable
StatusEnum resolveStatusCode(int code);
// Wrong (English comments in Chinese project):
// Convert status code to business enum
@Nullable
StatusEnum resolveStatusCode(int code);When adding or substantially updating a class-level Javadoc:
- Preserve existing
@authorentries. - Add
@author Codex (AI)when Codex contributed to the change. - Do not replace the human author's attribution with the AI attribution.
- Inspect
git status --shortbefore editing. - Never revert or clean unrelated user changes.
- Use
apply_patchfor manual file edits. - Keep changes scoped to the request; remove only imports or code made unused by your own change.
- Before finishing, run the narrowest relevant tests,
git diff --check, and the relevant style/docs validation.