Workspace Automation (xtasks)
Every cargo xtask subcommand, what it does, and when a contributor reaches for it
jackin❯ keeps its workspace automation in a single Rust binary, crates/jackin-xtask/src/main.rs, following the cargo-xtask pattern: all task logic is Rust, subprocesses (docker, git) are driven through std::process::Command, and the project carries no shell task scripts. The cargo alias in .cargo/config.toml makes cargo xtask <command> the direct entrypoint, and the construct-* tasks in mise.toml delegate to the same binary so CI and local runs share one implementation.
This page is the canonical inventory of xtask commands. A PR that adds, removes, or reshapes a subcommand updates this page in the same PR. The declarative image build graph stays in docker-bake.hcl — the xtask invokes it rather than reimplementing it in flag assembly.
Construct image tasks
The construct family (source: crates/jackin-xtask/src/construct.rs) builds and publishes the construct base image. Each has a matching mise task; the role-author-facing build walkthrough lives on Construct image.
| Command | mise task | What it does |
|---|---|---|
cargo xtask construct init-buildx | construct-init-buildx | Create and bootstrap the named Buildx builder. |
cargo xtask construct doctor-buildx | construct-doctor-buildx | Inspect the configured Buildx builder and list available builders. |
cargo xtask construct reset-buildx | construct-reset-buildx | Recreate the configured Buildx builder from scratch — the fix when builds fail with a corrupted builder. |
cargo xtask construct build-local | construct-build-local | Build the construct image for the host platform and load it into the local Docker daemon. |
cargo xtask construct build-platform <amd64|arm64> | construct-build-platform <platform> | Build for one specific platform and load it locally. |
cargo xtask construct push-platform <amd64|arm64> | construct-push-platform <platform> | Push a single-platform image by digest. CI-only for the canonical registry. |
cargo xtask construct assert-version-unpublished | construct-assert-version-unpublished | Fail when the version in docker/construct/versions.env already exists in the registry — the publish-gate guard. |
cargo xtask construct publish-manifest | construct-publish-manifest | Combine per-platform digest pushes into one multi-platform manifest. CI publish step. |
cargo xtask construct inspect | construct-inspect | Print the resolved Bake configuration without building — dry-run inspection. |
Pull request verification helpers
jackin-dev pr sync <PR_NUMBER> (source: crates/jackin-dev/src/main.rs) owns the checkout and isolation setup for local PR verification. It asks GitHub for the PR head, refreshes $HOME/Projects/jackin-project/test/pr-<PR_NUMBER>/jackin, checks out the PR's real head branch while keeping the bundle directory keyed by PR number, trusts and installs mise, builds the local jackin binary, copies live config into $HOME/Projects/jackin-project/test/pr-<PR_NUMBER>/state/config, creates empty runtime state under $HOME/Projects/jackin-project/test/pr-<PR_NUMBER>/state/home, and writes $HOME/Projects/jackin-project/test/pr-<PR_NUMBER>/env.sh. Sync refuses to reset the checkout when it has local changes or local-only commits on the target PR branch; commit, stash, push, or pass --force when intentionally discarding local work.
Source the generated env file before smoke testing the PR. jackin-dev runs as a child process, so it cannot export into the parent shell directly. The env file prepends the checkout's target/debug directory to PATH, sets JACKIN_CONFIG_DIR to the PR bundle's copied config, sets JACKIN_HOME_DIR to the PR bundle's empty state home, and includes JACKIN_CAPSULE_BIN or JACKIN_CONSTRUCT_IMAGE only when the PR diff requires local capsule or construct preparation. Use jackin-dev pr explain <PR_NUMBER> before or after sync to preview those auto-prep decisions and see the changed files that triggered them.
| Command | What it does |
|---|---|
jackin-dev pr sync <PR_NUMBER> | Clone or refresh the PR checkout on the PR's real branch, prepare isolated config/state, build local jackin, auto-build capsule/construct inputs from the diff, and write env.sh. |
jackin-dev pr clean <PR_NUMBER> | Remove the full PR verification bundle. |
jackin-dev pr env <PR_NUMBER> | Print the cd, source, and which jackin commands for entering the bundle. |
jackin-dev pr path <PR_NUMBER> | Print the PR bundle root. |
jackin-dev pr status <PR_NUMBER> | Show local checkout freshness, branch/head SHAs, and env/state existence. |
jackin-dev pr explain <PR_NUMBER> | Fetch the PR diff, preview whether capsule or construct prep would run, and print the changed files/rules behind each decision without cloning or building. |
sync takes optional overrides: --config blank starts from an empty config directory for clean-room verification (default copy mirrors the operator's live config), --test-dir <path> relocates the bundle root, and --repo <owner/name> targets a different repository. explain accepts the same --test-dir and --repo options as the remote-aware PR commands.
cargo xtask pr body --base <ref> assembles a PR body from the diff. It prints a classified change digest (rust / docs / capsule / schema, plus the changed-file list) to stderr, and the body skeleton — .github/PULL_REQUEST_TEMPLATE.md with the verify-locally ### blocks that do not apply to the diff removed — to stdout. The split lets you redirect the body to a file (cargo xtask pr body > body.md) while reading the digest in the terminal. Block selection: Checkout always; Static checks / Rust tests / User smoke on a Rust change; Schema migration smoke on a versioned-schema touch; Docs checks / Documentation on a docs/** change; jackin-capsule smoke on a crates/jackin-capsule/ change. The prose sections stay as template placeholders for the author to fill.
PTY fixture extraction
cargo xtask pty-fixture <capture> <out.bin> (source: crates/jackin-xtask/src/pty_fixture.rs) copies an explicitly captured raw PTY byte stream into a replayable terminal fixture. Set JACKIN_PTY_FIXTURE_CAPTURE=<path> only for the deliberate capture run, then place the resulting fixture under the capsule test fixtures. Telemetry never carries terminal bytes.
The extractor accepts only a raw file created through the explicit JACKIN_PTY_FIXTURE_CAPTURE test gate. Fixtures land under crates/jackin-capsule/tests/fixtures/pty/README.md by convention; the review and wiring flow is documented in TESTING.md. Production telemetry never supplies PTY fixture bytes.
Reach for it when an operator-reported rendering bug needs the agent's exact byte stream as a regression test: one command replaces hand-extracting hex from logs.
Documentation sidebar tasks
The change, research, and roadmap families (source: crates/jackin-xtask/src/docs.rs) scaffold and validate the Fumadocs meta.json sidebars under docs/content/, so contributors never hand-edit the sidebar JSON or leave a new page unreachable. They locate the repo root by walking up for docs/content, so they run from anywhere in the tree.
| Command | What it does |
|---|---|
cargo xtask change new <slug> --group <group> | Scaffold a roadmap item under /roadmap/ with Status, Outcome, Current state, Remaining work, Completion gate, and Related research, then register it in the named product-area group. --title overrides the title-cased default. |
cargo xtask research scaffold <slug> --group <domain> | Scaffold a research dossier under /research/<domain>/<slug>/ with a consistent question, findings, evidence, limitations, reading-order, and related-work format. The reusable brief is created outside published docs at prompts/research/<domain>/<slug>.md. Domains are agents, platform, product, engineering, or context; --title overrides the default. |
cargo xtask research check | Validate research sidebar parity plus the shared page contract: title and concise description frontmatter, canonical state labels, no duplicate body H1, and no published prompt/brief pages. Non-zero exit on any problem. |
cargo xtask roadmap audit | Same validation for the roadmap subtree, including (group) folders and ../<slug> cross-references. Non-zero exit on any problem. |
cargo xtask roadmap retire <slug> | Retire a shipped roadmap item. --plan (default) prints a read-only worklist — page content, inbound links, and the sidebar entry. --apply drops the ../<slug> group entry, deletes the .mdx, runs the audit, and fails if any inbound link still resolves to it. --partial sets **Status**: Partially implemented and keeps the page. |
research check is read-only and deterministic. Roadmap sidebar parity and the machine-checkable research rules listed above are gated in CI by cargo xtask roadmap audit and cargo xtask research check in the docs workflow, so those commands are the local equivalents. Page-type section order and evidence quality remain review requirements.
Schema migration gate
cargo xtask schema-check --base <ref> (source: crates/jackin-xtask/src/schema.rs) enforces the five-artifact rule for versioned schemas described in PRERELEASE.md. It reads each CURRENT_{CONFIG,WORKSPACE,MANIFEST}_VERSION on the working tree and at the base ref; when one is bumped it asserts the new from-<predecessor>/ fixture directory exists (meta.toml / before.toml / after.toml, with the right target_version) and that schema-versions.mdx carries a Timeline entry for the new version. The migration step and the existing-fixture re-bake are already enforced by tests/migration_fixtures.rs, so this gate covers only the two artifacts those tests cannot see. The CI workflow runs it on every Rust change so a partial schema bump fails before merge.
Adding a new xtask
Repo-internal automation belongs in this binary, not in shell scripts or one-off justfile recipes: add a module under crates/jackin-xtask/src/main.rs, register the subcommand in the Command enum, and — when CI or contributors will invoke it routinely — add a delegating mise task. Host-side developer workflows that must be available before a checkout exists belong in jackin-dev instead. Update this page in the same PR.