Skip to content

feat: S1 skill parity — v1 envelope, journaled tasks, safe downloads, Creative Lab, live-verified 0.3.0 - #5

Merged
AltaMills merged 26 commits into
mainfrom
feat/skill-parity-s1
Sep 8, 2026
Merged

AltaMills merged 26 commits into
mainfrom
feat/skill-parity-s1

Conversation

@AltaMills

Copy link
Copy Markdown
Contributor

Summary

S1 of the skill-parity programme: meshy covers the execution capabilities of the three Meshy Skills (meshy-3d-agent and friends) so agents can run tasks through one audited CLI.

  • meshy.cli/v1 envelope on every command (--output-schema v1), stable exit codes 0–13/130, error.code taxonomy; legacy output/file layout kept (additive fields only)
  • task verbs create/get/wait/stream/list/delete/download for every resource, incl. uv-unwrap, text-to-motion, animate and all Creative Lab products; make two-step chain; SSE stream with contiguous sequence numbers
  • operation journal: one POST per submission, replay detection (operation_replayed), credential/payload conflicts (operation_conflict), recovery commands that replay verbatim
  • safe downloads: frozen authorised write boundary (--workspace / --project), atomic no-overwrite commits, OBJ/MTL texture relinking with two-step arbitration, project metadata/snapshots
  • local tooling: project, inspect faces, mesh prepare-print, slicer detect/open, doctor, resources; bundled skills/meshy-cli/SKILL.md
  • auth profiles (API key and OAuth PKCE with silent refresh), --api-key-file, MESHY_API_KEY

Design record: docs/skill-parity/ (decisions D-001…D-060, endpoint contracts, capability matrix, verification, live-verification, review handoff, migration notes).

Review

  • Codex review rounds 1–6: 32 findings fixed with regression tests (tests/codex-review-round*.test.ts); rounds 7 and 8 accepted (evidence meshy-agent-integrations-research/reviews/cli-s1-e567646, …/cli-s1-1d9f109)
  • Live verification on a real account (2026-09-08): API key + OAuth, text/image-to-3d, refine/remesh/retexture/rigging/animate, UV unwrap, all Creative Lab products, Bambu Studio open; two live defects (L01 null timestamps, L02 legacy -o naming) fixed and re-verified; 327 credits; record in docs/skill-parity/live-verification.json
  • Platforms: macOS arm64 and Linux arm64/x64 (OrbStack, Node 24) tarball smoke 29/29; Windows x64 not run (owner's decision)

Validation

  • pnpm run typecheck
  • pnpm test (558 passed, 0 skipped)
  • pnpm run build; dist/index.js --version matches package.json (0.3.0)
  • pnpm pack → tarball smoke on macOS and Linux
  • git diff --check clean against fd94490

Compatibility

Additive: legacy command output and the -o file layout are unchanged except for the documented fixes (Creative Lab part/bundle file names). Node ≥ 24 as before. Version 0.3.0 (bumped in e7c26fc); publish runs through release.yml after merge.

🤖 Generated with Claude Code

AltaMills and others added 26 commits September 7, 2026 14:28
…ixtures

Freeze the S1 baseline before any behaviour change: repo/skills SHAs, Node/pnpm,
baseline test results (363 pass), read-only meshyd cross-check notes, the
frozen endpoint contract for the 16 task resources + 8 Creative Lab stage
resources + balance/animation-catalog/showcases queries, design decisions
D-001..D-024, legacy→CLI migration notes with intentional differences, and the
synthetic fixtures (OBJ oracle, rigging task, SSE error stream).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… and unified error exit

- add the meshy.cli/v1 envelope (result.ts), CliError with the stable code
  vocabulary and exit codes 10-13/130, classifyError for every thrown type
- global flags: --output-schema, --api-key-file, --workspace,
  --no-update-check, --base-url-creative-lab; Commander parse errors now exit 2
  through the same exit as command failures (legacy payload or v1 envelope)
- runtime: no cross-call cache, buildLocalRuntime for credential-free commands,
  schema resolution (legacy default for 0.2.0 commands, v1-only for new ones)
- config: --api-key-file (dotenv-style, only MESHY_API_KEY, strict), creative-lab
  and public-web base derivation, stored-profile origin policy
- update check skipped for local commands, dry-run and --no-update-check;
  update-state cache honours MESHY_CONFIG_DIR
- SIGINT becomes a cooperative abort (exit 130); stdout is flushed before exit
- balance/api/delete gain v1 output and --save-json (exclusive publish)
- atomic-file (link-based exclusive publish) and paths (realpath containment)
- tests: env-file grammar, error classification, black-box CLI contract with a
  loopback API; pretest builds dist so subprocess tests run current sources

--env-file is deliberately not the flag name: Node scans the whole argv for it
and loads the file itself (decisions D-025).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- transport.ts: per-family transports with path validation (no scheme-relative,
  userinfo, foreign-origin or '..' paths), redirect refusal, body-inclusive
  deadlines, body caps and failure phases (connect = never sent)
- resource-registry.ts: 16 task resources + 4×2 Creative Lab stages, query
  resources and local tools; docs/skill-parity/endpoint-contracts.json is
  asserted against it
- MeshyClient built from the registry; Creative Lab transport derived from the
  v1 origin with the stored-profile origin policy; public catalog transport
  never carries a credential; per-resource endpoint classes removed
- TaskSchema gains face_count/consumed_credits/thumbnail_urls/alpha_thumbnail_url;
  task-view.ts builds the v1 TaskView from raw JSON (missing stays null)
- media normalisation moves to the merged payload (declared fields only),
  accepts data: URIs, enforces size/format limits; texture_image_url covered
- new commands: animation-catalog list (no key, local search), showcases list
  (single billable GET, alias warning); resources index is registry-driven
- tests: transport boundaries, registry-vs-docs, TaskView, catalog/showcases
  black-box, media normalisation

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…E stream, make async, uv-unwrap, creative-lab

- task-command: create/get/wait/stream/delete/list in both schemas; get of any
  status is exit 0; wait/stream FAILED exit 1 with the task kept; --timeout 0 is
  one query; --save-json/--include-raw; SIGINT → 130 with resume command
- operation-store + lock: journal written before the POST; 5xx / malformed 2xx /
  lost response → submission_unknown (exit 10) with reconcile guidance, never a
  retry; --operation-id replays or conflicts; no key material on disk
- stream.ts: WHATWG-style SSE parser (byte splits, CRLF, UTF-8, multi-line
  data, comments) and streamTask with total/idle deadlines; error events after
  HTTP 200 mapped by status_code; ndjson task/outcome events with sequence
- poll.ts: monotonic deadline, cancellable sleep, finite timeout validation
- make: --async is one POST with pending_steps, --stop-after-first keeps the old
  behaviour, both together refused; steps journaled
- new commands: uv-unwrap (exclusive source, GLB-only) and creative-lab
  figure|lamp|keychain|fridge-magnet prototype|build with per-product option
  validation; --data parse errors are usage errors
- tests: sse, operation-store (incl. cross-process race), task-lifecycle,
  uv/creative-lab/make black-box; capability matrix marks 20 items implemented

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…le placement

- artifacts.ts: stable asset keys for model formats (lamp parts as STL/ZIP,
  keychain/fridge-magnet OBJ as an unextracted ZIP bundle), images, textures,
  primary/multi-view/alpha thumbnails, rig + nested basic_animations, motion
  clips, printability reports; unknown URLs are listed, never fetched; OBJ
  declares MTL/texture dependencies; legacy key aliases
- download.ts: fetchToTemp with http(s)-only, no credentials, hop-by-hop
  redirect re-validation, private-network refusal, streaming size cap and
  sha256; MIME-driven extension reconciliation; magic/HTML content checks;
  exclusive publish via link with realpath containment (leaf symlinks refused
  before fetching); legacy -o wrapper keeps the 0.2.0 layout on the same core
- meshy download: sources task-json | url | resource+task-id, selectors
  --asset/--model-format/--kind/--all/--list, --output vs --output-dir,
  --overwrite, --with-dependencies/--geometry-only, one bounded URL refresh
  for API sources, partial manifests on failure
- tests: enumeration/selection units and black-box downloads (T-060..T-071)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…project bookkeeping

- project-store.ts: metadata.json v2 (resource/endpoint/parent/status/task_json/
  operation_id per task), legacy v1 files read as-is and migrated on first write
  with a .bak copy and unknown fields preserved; history.json stays a rebuildable
  index; (task_id, stage) de-duplication; project lock → commit → root lock →
  index refresh, never nested the other way; index failures reported as
  index_dirty instead of rolling metadata back; safe folder slugs and relative
  file paths only; damaged JSON is never overwritten
- meshy project init | record | show | list | rebuild-index (local, no key)
- --project/--stage on create/get/wait/stream: record the id immediately for
  async creates, snapshot task_<id>.json for full tasks; download --project
  defaults the output dir to the project and records the files
- tests: layout, legacy migration, de-dup, cross-process concurrency, index
  repair, path safety, CLI black-box (T-072..T-077)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ctor

B06 inspect faces: verdict pass|fail|unknown from the task's face_count only
(missing/null/string → unknown, exit 13; over the limit → exit 12); --max-faces
is required; sources task-json (no network) or one GET through the registry;
a failing verdict describes a remesh and never runs one.

B07 mesh prepare-print: streaming two-pass OBJ transform (Y-up → Z-up, scale to
--height-mm, XY centred, grounded at Z=0), normals rotated only, extra vertex
fields and face/UV indices preserved, LF/CRLF kept; default <stem>.print.obj,
--in-place explicit; NaN/Infinity/degenerate/empty → validation with no output;
mtllib/texture dependencies copied across directories or refused unless
--geometry-only; validated against the independent fixture oracle.
B07 slicers: seven registered slicers with multicolor metadata; detection rules
for darwin/win32/linux through an injectable environment; open launches the
detected path only (shell:false, single argv, no default-app fallback).

B08 doctor: local by default (versions, credential sources as booleans, base
URLs, workspace, .env candidates named not read); --check-api makes one free
GET /balance (exit 3 / 7 on failure); --check-slicers runs detection.

Also: decisions D-026..D-028, capability matrix 33/35 implemented, in-process
command tests forward the test runner's frames to the real stdout.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… origin-policy test

Candidate version for the S1 skill-parity release (not published). README and
skills/meshy-cli/SKILL.md describe the new commands, the v1 envelope, the exit
codes 10-13/130, --api-key-file and the money rules; .env.example lists the
Creative Lab base and the config dir. Adds T-105: a stored profile is refused
for a Creative Lab base on another origin while an explicit key is allowed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…3.0 candidate

Binds every check to code HEAD e7c26fc: install/typecheck/test (502 pass)/
build, npm pack (meshy-cli-0.3.0.tgz, sha256 recorded), tarball install into
a temporary prefix with 29 smoke checks, one real unauthenticated public
catalog query; live account/OS/GUI checks recorded as not_run. Capability
matrix: 35/35 implemented, review not_run. REVIEW_HANDOFF.md follows the
package template with sanitised sample outputs and the Codex review prompt.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
F01 every failure after the server accepted a task (save-json, polling 5xx,
    download, project record) keeps result.task_id/submission/next; -o,
    --save-json and --project are checked before the POST (zero requests on
    a detectable conflict)
F02 make submits through the shared submitCreate primitive: a journal write
    failure after acceptance is local_io (11) with the known id
F03 --workspace is the root of every write: task -o (get/wait/stream/create/
    make), project init/record/rebuild-index, --project on task verbs and
    download
F04 OBJ dependency copies are proven inside the write root on real paths
    before mkdir and again before publish (symlinked materials/ refused)
F05 credential fingerprint binds to a one-way digest of the API key or the
    OAuth subject (token rotation keeps the identity)
F06 payload fingerprint hashes decoded data-URI bytes (equal-length images
    no longer collide; wrong test assertion replaced)
F07 wait deadline bounds every in-flight GET and the sleep; late replies are
    timeouts, PollResult.task may be null before the first response
F08 Creative Lab options/output merge field by field across --data,
    --options and typed flags (nestedObjectKeys)
F09 downloaded OBJ/MTL references are rewritten to the saved names and
    reported (material_links, relinked manifest entries, unresolved warning)
F10 stream -o downloads in ndjson/json/pretty; one outcome line on failure

Also: operation-store race test released through a barrier (real
contention), SSE fixture trailing blank line + .gitattributes, mkdir
failures are local_io, tests/codex-review-round1.test.ts mirrors probes
R01–R12 as positive regressions, decisions D-029..D-037, migration notes,
README and bundled SKILL.md updated.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
verification.json re-bound to code HEAD 0388fe8 (install/typecheck/test
522 pass/build/pack sha256 6a05293a…/tarball install + 29 smoke checks,
live catalog GET re-run) with review_rounds[0] (reviewed 6273d9a,
changes_requested, 10 findings fixed, reproduce.mjs re-run: 0/12 reproduce);
capability matrix marks 21 capabilities with round_1 fixes and re-review
pending; REVIEW_HANDOFF.md adds §0 finding→fix→test→probe table, post-fix
sample outputs and the re-review prompt. Live account/OS/GUI checks stay
not_run.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
R2-F01 --workspace confines every write: report-only -o (saveReportOnly
        checks before mkdir), downloadAssets checks before creating the
        directory, and the implicit history root is confined — with
        --workspace equal to the project dir, metadata is recorded and the
        index skipped (index.updated=false, index_dirty) instead of writing
        history.json into the parent
R2-F02 material relinking maps textures by the server-side file name (then
        stem, channel word, MTL key), one candidate only; ambiguous maps stay
        as written with candidates, material_links.status=incomplete and a
        material_reference_ambiguous warning; legacy -o uses the same resolver
R2-F03 stream: save-json/project failures after the SSE events are part of
        the single terminal outcome (ndjson outcome with the next sequence,
        one envelope for json/pretty)
R2-F04 task/make -o downloads return a per-file manifest; a failure keeps the
        original class, HTTP status and recovery and carries the files already
        written (downloads.state=partial) instead of files: []
R2-F05 the abort signal reaches fetchToTemp for every task -o and make
        download: Ctrl-C aborts the transfer, removes the temp file, skips
        relink/sidecar and exits 130 with task id, submission, next and the
        committed files; index.ts keeps result/recovery when re-wrapping
R2-F06 OAuth identity: auth login mints a login_id kept across refresh and
        replaced by re-login; journal identity = user_id, else login_id; a
        profile with neither is refused a replay (operation_conflict,
        credential_unverified, recovery meshy auth login)
R2-F07 poll deadline tests drive the injected now/sleep clock (exact expiry,
        early/late wake, deadline-bound timeout); the real-timer smoke asserts
        only that no GET starts after the deadline

Also: saveTaskSnapshot computes task_json in the real-path frame; round-1
R10 expectation follows the preserved HTTP class (404 → not_found/5);
tests/codex-review-round2.test.ts mirrors probes N01–N08; decisions
D-038..D-044, migration notes §3.2, README and bundled SKILL.md updated.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
verification.json re-bound to code HEAD cf8905d (install/typecheck/test
535 pass/build/pack sha256 3077563a…/tarball install + 29 smoke checks,
git diff --check, poll.test.ts 8/8 repeats, live catalog GET) with
review_rounds[1] (reviewed 730132b, changes_requested, 7 findings fixed,
round2-probes.mjs re-run 0/8, round1-probes.mjs re-run 0/12); capability
matrix marks 13 capabilities with round-2 fixes; REVIEW_HANDOFF.md carries
the round-2 finding→fix→test→probe table, post-fix samples and the
re-review prompt. Live account/OS/GUI checks stay not_run.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
R3-F01 the legacy sidecar (meta.json / <stem>_meta.json) is published like an
        asset: root re-proven at publication, symlink refused, exclusive atomic
        writeJsonFile — a target planted after the preflight is never followed
        or truncated; the committed model stays in the manifest
R3-F02 legacy-schema post-processing (create/wait/get/stream/make -o) runs in
        the task context: additive task_id/operation_id payload fields, real
        submission, next and partial manifest, hint names the task on stderr
R3-F03 texture identity follows the server-side name before any saved-name
        match; a generated name that belongs to another source is ambiguous
        (note, warning, incomplete); channel rules refuse when several distinct
        references compete for the only texture of a channel
R3-F04 relink, digest refresh and sidecar publication share one failure
        handler: partial manifest with on-disk digests and failed_step; the
        same for meshy download's relink
R3-F05 the abort signal reaches relinkMaterials/rewriteLines (checked before
        reads, after each chunk, before publication) and the sidecar step:
        Ctrl-C during the rewrite is interrupted/130 with committed files kept,
        temp file removed, no sidecar
R3-F06 download --project computes recorded files in the real-path frame so an
        aliased project directory records its assets without a false
        files_outside_project warning

tests/codex-review-round3.test.ts mirrors probes C01–C06 (plus relink abort
unit tests and make interrupt); decisions D-045..D-050, migration notes §3.3,
README and bundled SKILL.md updated.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The smoke asserted GET start times taken by a fresh performance.now() inside
the endpoint against the deadline; call overhead of a few microseconds after a
remaining>0 decision made it fail once in a full run (+0.003 ms). The test now
records the last value the injected now() returned before each GET — the very
reading the loop used — and asserts it lies before the deadline. 12/12
repeats pass; the deterministic fake-clock tests are unchanged.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
verification.json re-bound to code HEAD 235d6de (install/typecheck/test
542 pass/build/pack sha256 f29e8a16…/tarball install + 29 smoke checks,
git diff --check, poll.test.ts 12/12 and review suites 3/3 repeats, live
catalog GET) with review_rounds[2] (reviewed 566f3bd/cf8905d,
changes_requested, 6 findings fixed in 30536d8, round3-probes.mjs re-run
0/6, round2 0/8, round1 0/12, reviewer's verify-original-regressions.py
20/20, stream-finalization-check passed); capability matrix marks 10
capabilities with round-3 fixes; REVIEW_HANDOFF.md carries the round-3
finding→fix→test→probe table, post-fix samples and the re-review prompt.
Live account/OS/GUI checks stay not_run.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… test gap R4-T01

R4-F01 material-links: resolve every distinct (key, reference) pair on its own
first, then arbitrate heuristic hits on the texture they actually reach — a
texture that any other distinct reference contends for (by a hit of either kind
or as an ambiguity) serves none of them, and a reference that different keys
would send to different textures is not rewritten; identity matches (source
name, saved name, source stem) are never vetoed. One shared note per group, one
warning per reason, order of the references irrelevant.

R4-F02 download --project: preflight metadata.json (present, regular file,
parses) and --stage before any transfer; wrap the record phase so a failure
keeps the whole result (source, selection, manifest with on-disk digests,
saved_json) plus project.action="failed" with the error and a record_project
recovery whose command is the exact `meshy project record …` invocation (also
the hint). The task verbs' --project attachment reports the same recovery.
Nothing is rolled back, re-downloaded or re-submitted; index_dirty keeps its
meaning.

R4-T01 tests: make's task_id / submission.operation_id / executed[-1] /
legacy operation_id are reconciled with the last accepted journal record using
distinct step ids (legacy and v1, asset 503 and SIGINT, POST GET POST GET GET,
refine.preview_task_id = step 1); C06 keeps the create/wait/get scenarios.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…mits

The R03/F07 subprocess check "expiry during the sleep" asserted at most two
polls. When the final budget-cut sleep wakes a fraction before the deadline the
loop may issue one more deadline-bound GET (the early-wake case D-044 documents),
which made the check fail about once in six runs on this host. It now asserts
the invariants a real clock can prove: every GET the server saw started within
the budget, the second waited the full interval, a third can only sit at the
deadline itself, and the counted polls match the GETs seen (at most one cut off).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
verification.json, capability-matrix.json and REVIEW_HANDOFF.md bound to code
HEAD 68690f9 (fix 93e55bc + test stabilisation): pnpm test 547/547, typecheck,
diff --check, poll ×12, round-1 ×8, rounds 2–4 ×3, reviewer script copies
(round1 0/12, round2 0/8, round3 0/6, round4 D01/D02 fixed, D03 positive,
context checks 5/5, stream check, verify-original-regressions 20/20), tarball
smoke 29/29. Live account / Windows / Linux / slicer / paid checks stay not_run.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
R5-F01 project-store / download / task-command: the record_project recovery
command carries the invocation's resolved --workspace (shell-quoted like every
other argument), from both callers. A replayed recovery never writes further
than the command that failed: with a workspace equal to the project it records
metadata, skips the parent's history index (index_dirty) and creates no lock
or temp file outside. Without an explicit workspace nothing is appended.

R5-F02 material-links: arbitration first reconciles every reference across
its keys — identity evidence is key-independent and wins; otherwise each key's
channel rule yields a candidate set (a hit, an ambiguity's candidates, nothing
for a key whose channel has no texture) and all sets must be the same single
texture, else every line of that reference stays as written with its own
candidates and one cross-key note ("one reference names one file") — then the
round-4 cross-reference contention applies to the reconciled hits.

R5-F03 task-command: the project checks run inside the recovery context, with
task id, journal operation, stage and workspace known first. A project that no
longer resolves inside the workspace (or became a symlink) is a boundary
failure: the error names the task and operation and says nothing was
recorded, but hands out no command that would cross the boundary. metadata.json
missing / damaged / locked after the preflight gets the one `meshy project
record …` command with --operation-id and --workspace (also the legacy hint),
across get / wait / stream / create --async / sync create. download applies the
same metadata assertion before its record step (local_io, not not_found), with
the file list computed first so the command still names what landed.

Tests: codex-review-round5 (E01 verbatim replay incl. a workspace path with a
space and a quote, no-workspace semantics kept; E02 both orders + the 8x2
arbitration matrix; E03 20-entry legacy/v1 × verb × missing/damaged matrix
with journal reconciliation and verbatim replay; escaped-project boundary).
codex-review-round4: D02 replays the command verbatim; R4-T01 asserts the
SIGINT manifest as failed + [model_glb failed].

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
verification.json, capability-matrix.json and REVIEW_HANDOFF.md bound to code
HEAD 7b7c24c (fix R5-F01–R5-F03): pnpm test 552/552, typecheck, diff --check
on fd94490 and the tree, poll ×12, round-1 ×8, rounds 2–5 ×3, reviewer script
copies (round1 0/12, round2 0/8, round3 0/6, round4 0/3 with D03 positive,
round5 E01/E02×2/E03 fixed, material matrix 16/16, project-entry matrix 20/20
record_project, verify-original-regressions 20/20, verify-round3-4 8/8,
context checks 5/5, stream check), tarball smoke 29/29. Live account /
Windows / Linux / slicer / paid checks stay not_run.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… test gap R6-T01

R6-F02 paths / runtime / every write path: the write boundary is an
AuthorisedRoot frozen when the global flags are read — the real path plus the
device/inode identity of the directory behind --workspace — and
resolveWithinRoot given a frozen root never resolves it again: it first proves
that the same directory is still at that path (a symlink or another directory
there is refused: "changed since the command started"), then that the target's
real path lies inside it. The frozen root flows through --save-json, -o
downloads (downloadArtifacts / downloadAssets, sidecar, report-only), make,
mesh prepare-print, the project commands and the task verbs' project
attachment, which freezes the project directory itself before the first
request when no workspace is given and writes through the proven real path.
A workspace (or the alias it was given through) redirected while a request is
in flight is a boundary failure: exit 11, task and accepted journal kept,
single POST, nothing written outside, recovery null. Stable aliases (/var,
symlinked parents, a workspace given through a symlink that stays put) pass.

R6-F01 download --project: before any project lock, snapshot or metadata
write the project is resolved against the frozen boundary; a project (or a
parent of it) replaced by a symlink to an outside tree during the transfer is
a boundary failure — exit 11 / local_io, the completed manifest and assets
kept, project.action = "failed" with the reason, recovery null, nothing
disguised as index_dirty — distinct from a repairable metadata problem, which
keeps the record_project recovery. Records are written through the real path.

R6-T01 tests: E03 asserts the exact method/path sequence for all 20 entries;
E02 binds each line's candidate set to its key. New codex-review-round6:
download × task-json/API × project leaf/parent swapped for an outside symlink
(outside tree byte-identical, exact requests, healthy control); legacy/v1 ×
get/wait/stream/create-async/create-sync × workspace directory swapped or
alias re-pointed (exact requests, journal, outside and original trees
byte-identical, no record command); stable-alias control.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
verification.json, capability-matrix.json and REVIEW_HANDOFF.md bound to code
HEAD e567646 (fix R6-F01/R6-F02/R6-T01): pnpm test 555/555, typecheck,
diff --check on fd94490, 166492b and the tree, poll ×12, round-1 ×8, rounds 2–6
×3, reviewer script copies (round1 0/12, round2 0/8, round3 0/6, round4 0/3
with D03 positive, round5 0/4, round6 0/4 with outside bytes unchanged,
verify-original 20/20, verify-round3-4 8/8, verify-round5-positive 24/24,
material matrix 16/16, round6 material 10/10, project entries 20/20, context
5/5, stream check), tarball smoke 29/29. Live account / Windows / Linux /
slicer / paid checks stay not_run.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…s and bundles in the legacy -o layout

Found during the real-account verification (2026-09-08) and re-verified live.

L01 client/types: the Creative Lab endpoints return finished_at: null (and
may return null for the other not-yet fields) while a task is IN_PROGRESS,
where the v2 endpoints return 0. The task schema accepted only a number with a
default for absence, so creative-lab … get/wait failed with "unexpected task
shape" (error.code server, HTTP 200) on every poll until completion. progress,
preceding_tasks, created_at, started_at, finished_at and expires_at now accept
null and absence alike and read as 0; the v1 view still shows a not-yet
timestamp as null. The live body is the fixture; the test replays it through
the schema and through get/wait.

L02 internal/download + artifacts: the legacy -o downloader named every
model_urls entry model.<key>, so lamp builds landed as model.lamp_stl /
model.base_stl and the keychain OBJ ZIP bundle as model.obj. The legacy
enumerator now asks the product-aware modelAsset mapping (shared with meshy
download) for the file name and format: lamp.stl, base.stl, bundle.zip,
model.obj.zip; slot keys and relink rules are unchanged.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…n bound to 1d9f109

Records the 2026-09-08 live verification run as the account owner: T-104 passed
(API key + OAuth, refresh observed, journal replay/conflict), T-110 passed,
T-111 passed (all Creative Lab products; showcases 403 enterprise-only
recorded), T-112 passed (Bambu Studio), T-109 partial (macOS + Linux
arm64/x64 29/29; Windows not_run). 327 credits consumed. Two live defects
(L01 null timestamps, L02 legacy -o naming) fixed in 1d9f109 and re-verified
live. New docs/skill-parity/live-verification.json holds the sanitised
step-by-step record; verification.json and capability-matrix.json carry the
final runs (558/558), reviewer-script reruns and per-capability live status.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…d release path

Codex round 8 (reviews/cli-s1-1d9f109) accepted the live fixes L01/L02 with
no findings; rounds 7 and 8 are now listed in review_rounds. The owner
authorised the release on 2026-09-08: the branch goes to main through a pull
request, publishing runs through .github/workflows/release.yml, and Windows
x64 stays not_run by their decision. G1-release remains pending until the
publish is verified and recorded.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@AltaMills
AltaMills merged commit 1d7ff01 into main Sep 8, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant