Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ jobs:
- name: Typecheck
run: npm run typecheck

- name: Build publishable packages
run: npm run build:packages

- name: Build playground
run: npm run build

Expand Down
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.2.0] - 2026-07-15

### Added

- **Canonical timing modes**: `flow`, `settle`, `drive`, `snap`, and `linear`
now describe continuous motion, deliberate rests, acceleration, and sharp
arrivals. The v0.1 easing spellings remain accepted as deprecated aliases.
- **Third-party validation CLI**: `npx posecode-parser@0.2.0 validate <path>`
recursively checks `.posecode` libraries, with `--strict` and `--json` modes
for CI.
- **Embed compatibility metadata**: the CDN bundle exports `version`,
`languageVersion`, and `validatePosecode()`. Player ready/error events now
include structured version and diagnostic details, while host elements expose
a machine-readable loading/ready/error state.
- **Release contract checks**: CI builds the publishable package chain so a
source-only language change cannot land without a valid CDN bundle.
- **Realistic human figure**: the playground, landing hero, and `<posecode-player>` embeds now render a fully rigged, textured human character (hands with articulated fingers, sneakers, face) instead of the procedural capsule mannequin. All solving (FK, ground-lock, pins, reach-IK) still runs on the driver skeleton, rebuilt to the character's exact proportions and retargeted bone-for-bone every frame; the procedural figure remains as an automatic fallback (and via `?figure=classic` / `character="off"`).
- **Self-collision resolution**: a capsule-based de-penetration pass keeps forearms/hands out of the torso, head, and legs (and shins out of each other), clamped to healthy ROM, so limbs no longer pass through the body mid-movement.
- **Solid props**: props now declare blocking faces (the wall's surface, the chair's backrest and seat edge, the box's near face) and a contact pass keeps the body out of them — translating the whole figure along the face normal, or bending the offending leg's hip clear (ROM-clamped). Limbs pinned/gripped/reached to a prop anchor stay exempt as declared support. A new `solid-props` eval invariant (independent geometry re-derivation) guards every prop movement against this bug class.
Expand Down
34 changes: 16 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ A `.posecode` file describes movement as timed phases with targeted joint action

| 1. Write `.posecode` | 2. Render the movement |
| :--- | :--- |
| **`posecode`** `exercise "Body-weight squat"`<br />**`rig`** `humanoid`<br />**`pose`** `start = standing`<br /><br />**`step`** `"Descend" 1.6s ease-in-out`:<br />&nbsp;&nbsp;`hips: flex 80`<br />&nbsp;&nbsp;`knees: flex 95`<br />&nbsp;&nbsp;`ankles: dorsiflex 14`<br />&nbsp;&nbsp;`ground-lock: feet`<br />&nbsp;&nbsp;`cue "Sit the hips back"`<br /><br />**`step`** `"Drive up" 1.2s ease-out`:<br />&nbsp;&nbsp;`hips: flex 0`<br />&nbsp;&nbsp;`knees: flex 0`<br />&nbsp;&nbsp;`ankles: dorsiflex 0`<br />&nbsp;&nbsp;`ground-lock: feet`<br /><br />**`repeat`** `8` | <img src="docs/media/squat.gif" width="340" alt="Squat animation" /> |
| **`posecode`** `exercise "Body-weight squat"`<br />**`rig`** `humanoid`<br />**`pose`** `start = standing`<br /><br />**`step`** `"Descend" 1.6s settle`:<br />&nbsp;&nbsp;`hips: flex 80`<br />&nbsp;&nbsp;`knees: flex 95`<br />&nbsp;&nbsp;`ankles: dorsiflex 14`<br />&nbsp;&nbsp;`ground-lock: feet`<br />&nbsp;&nbsp;`cue "Sit the hips back"`<br /><br />**`step`** `"Drive up" 1.2s drive`:<br />&nbsp;&nbsp;`hips: flex 0`<br />&nbsp;&nbsp;`knees: flex 0`<br />&nbsp;&nbsp;`ankles: dorsiflex 0`<br />&nbsp;&nbsp;`ground-lock: feet`<br /><br />**`repeat`** `8` | <img src="docs/media/squat.gif" width="340" alt="Squat animation" /> |

---

Expand Down Expand Up @@ -355,33 +355,31 @@ npm install posecode-render
Example:

```ts
import { parsePosecode } from "posecode-parser";
import { PosecodeRenderer } from "posecode-render";
import { parse } from "posecode-parser";
import { createViewer } from "posecode-render";

const source = `
exercise "Lateral raise"
rig humanoid
pose start = standing
posecode exercise "Lateral raise"
rig humanoid
pose start = standing

step "Raise" 1.4s ease-in-out:
shoulders: abduct 90
step "Raise" 1.4s settle:
shoulders: abduct 90
`;

const result = parsePosecode(source);
const { ir, errors, warnings } = parse(source);

if (!result.ok) {
console.error(result.errors);
if (!ir || errors.length > 0) {
console.error(errors);
} else {
const renderer = new PosecodeRenderer({
container: document.querySelector("#viewer"),
});

renderer.load(result.document);
renderer.play();
console.warn(warnings);
const viewer = createViewer(document.querySelector("#viewer"));
viewer.load(ir);
viewer.play();
}
```

> Adjust this example to match the current exported APIs before submission.
The `#viewer` element is an HTML `<canvas>`.

---

Expand Down
3 changes: 2 additions & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ We actively support and fix security issues in the following versions of Posecod

| Version | Supported |
| ------- | --------- |
| v0.1.x | Yes |
| v0.2.x | Yes |
| v0.1.x | Security fixes only |

---

Expand Down
2 changes: 1 addition & 1 deletion editors/vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"private": true,
"displayName": "Posecode",
"description": "Language support for the Posecode (.posecode) kinematic motion DSL: syntax highlighting, range-of-motion diagnostics, completion, and hover.",
"version": "0.1.0",
"version": "0.2.0",
"license": "MIT",
"engines": {
"vscode": "^1.85.0"
Expand Down
50 changes: 28 additions & 22 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "posecode-monorepo",
"version": "0.1.0",
"version": "0.2.0",
"private": true,
"description": "Posecode: a kinematic motion protocol for LLMs. Describe 3D human movement as text; render it in the browser.",
"license": "MIT",
Expand All @@ -15,6 +15,7 @@
"coverage": "vitest run --coverage",
"dev": "npm run dev -w playground",
"build": "npm run build -w playground",
"build:packages": "npm run build -w posecode-parser && npm run build -w posecode-share && npm run build -w posecode-render && npm run build -w posecode-embed && npm run build -w posecode-mcp",
"prepare:xbot": "node scripts/prepare-xbot.mjs",
"eval": "tsx packages/posecode-eval/src/cli.ts",
"video:cut2": "remotion render video/cut2/index.tsx PosecodeCut2 docs/launch-media/posecode-cut2-builder-16x9.mp4 --public-dir video/cut2/public --codec h264 --crf 16",
Expand Down
36 changes: 31 additions & 5 deletions packages/posecode-embed/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ the movement as an animated 3D figure, right where a share link would have gone.
## Quick start (CDN, no build step)

```html
<script src="https://unpkg.com/posecode-embed/dist/posecode-embed.js"></script>
<script src="https://unpkg.com/posecode-embed@0.2.0/dist/posecode-embed.js"></script>

<!-- 1. From a share token (what a posecode.org permalink carries) -->
<posecode-player doc="cG9zZWNvZGUgZXhlcmNpc2Ug…"></posecode-player>
Expand All @@ -22,10 +22,10 @@ the movement as an animated 3D figure, right where a share link would have gone.
posecode exercise "Lateral raise"
rig humanoid
pose start = standing
step "Raise" 1.4s ease-out:
step "Raise" 1.4s settle:
shoulders: abduct 90
elbows: flex 10
step "Lower" 1.6s ease-in:
step "Lower" 1.6s drive:
shoulders: abduct 0
elbows: flex 0
repeat 8
Expand All @@ -35,6 +35,10 @@ posecode exercise "Lateral raise"
The script auto-registers the element and boots each player when it scrolls into
view. That's it.

Pin a package version in production, as above, so a deployment always uses a
known parser/render pair. A `src` URL can be relative or absolute; cross-origin
movement files must be served with CORS permission.

## With a bundler

```bash
Expand Down Expand Up @@ -86,11 +90,33 @@ Boolean attributes accept `false` / `0` / `no` / `off` to turn them off, so

```js
const player = document.querySelector("posecode-player");
player.addEventListener("posecode:ready", () => player.viewer.pause());
player.addEventListener("posecode:error", (e) => console.warn(e.detail.error));
player.addEventListener("posecode:ready", (e) => {
console.log(e.detail.version, e.detail.languageVersion, e.detail.warnings);
player.viewer.pause();
});
player.addEventListener("posecode:error", (e) => {
console.warn(e.detail.code, e.detail.error, e.detail.errors);
});

player.toggle(); // play / pause
player.viewer; // the underlying render Viewer (null until booted)
```

The host element reflects `data-posecode-state="loading|ready|error"`, plus the
package and language versions, for integration tests and monitoring. Existing
listeners that only read `event.detail.error` remain compatible.

CDN users can validate source without creating WebGL:

```js
const result = Posecode.validatePosecode(source);
console.log(Posecode.version, Posecode.languageVersion, result.errors);
```

For a movement library in CI, run:

```bash
npx posecode-parser@0.2.0 validate --strict ./movements
```

MIT-licensed, part of [Posecode](https://github.com/posecode-dev/posecode).
6 changes: 3 additions & 3 deletions packages/posecode-embed/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "posecode-embed",
"version": "0.1.0",
"version": "0.2.0",
"description": "Embed a live 3D Posecode movement anywhere with one <script> tag \u2014 the <posecode-player> web component.",
"license": "MIT",
"type": "module",
Expand Down Expand Up @@ -32,8 +32,8 @@
"three.js"
],
"dependencies": {
"posecode-parser": "0.1.0",
"posecode-render": "0.1.0",
"posecode-parser": "0.2.0",
"posecode-render": "0.2.0",
"posecode-share": "0.1.0"
},
"devDependencies": {
Expand Down
15 changes: 15 additions & 0 deletions packages/posecode-embed/src/compat.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/** Public compatibility metadata and no-render validation for CDN consumers. */

import { parse, POSECODE_VERSION } from "posecode-parser";
import type { ParseResult } from "posecode-parser";

/** Version of the posecode-embed package/bundle. */
export const version = "0.2.0";

/** Version of the Posecode language understood by this bundle. */
export const languageVersion = POSECODE_VERSION;

/** Validate source without creating a renderer or WebGL context. */
export function validatePosecode(source: string): ParseResult {
return parse(source);
}
Loading
Loading