{"owner":"earthtojake","repo":"text-to-cad","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["AGENTS.md"],"skills":{"AGENTS.md":"# AGENTS.md\n\nThis repo is a workbench for CAD-related agent skills. Treat `skills/` as the\nproduct and `models/` as the shared fixture/artifact area.\n\n## Branch And Layout First\n\nBefore changing code, branch from `develop`, not `main`; PRs should target `develop`.\nDo not start development work from `main`. The `develop` branch intentionally uses\nsymlinks across generated runtime and viewer-local package paths. When a path is\nsymlinked, follow the link and edit the source target.\nUse `main` as the production clone/release branch only. `main` is publish-only:\ndo not open PRs to `main` or push it directly.\n\n## Release Workflow\n\nDo not bump the canonical release version in `VERSION` during\nnormal development work. Ship releases only through the single `Release`\nGitHub Actions workflow, which handles the version bump, release PR, publish\ncommit to `main`, `cadgen` PyPI publish, docs deploy, semver tag, and GitHub\nRelease in one run.\n\nWhen asked to publish, make, or ship a release, dispatch `Release` with its\ndefaults: build from `develop` (`base_branch=develop`), publish to `main`\n(`target_branch=main`), and publish the GitHub Release (`publish=true`, not a\ndraft). Never pick the semver bump yourself: if the request does not name\npatch, minor, major, or an exact version, ask which one before dispatching.\nUse `target_branch=build-test` only when the user explicitly asks to test\nCI/CD or build-pipeline changes — never by default and never as part of a\nrequested release, and pair it with `bump=none` so a rehearsal does not consume\na version number. `bump=none` publishes `base_branch` as it stands and is also\nhow you resume a failed publish; it is never a release setting.\n\nThe standalone `Deploy Docs` workflow redeploys the docs site without running a\nrelease. It deploys a source ref (defaulting to `develop`), never `main`: the\npublish tree drops `docs/` and `packages/`, which the docs app builds against.\nThe CAD Viewer is a local-filesystem app with no hosted deployment, but each\nrelease mirrors `viewer/` into the standalone `earthtojake/cad-viewer` repo\nthrough the `Sync CAD Viewer Repo` workflow, which `Release` calls after\npublishing and which can also be dispatched on its own. Both of those read the\nrelease SOURCE commit, because `main` carries only what installs.\n`main` is publish-only; pushing `develop` runs tests but\nnever publishes. See the Releases section in `CONTRIBUTING.md` for the full\nflow, CI/CD-testing and resume options, and local/manual fallbacks.\n\n## Repo Map\n\n- `skills/`: agent skills and their references/scripts.\n- `.claude-plugin/`, `.codex-plugin/`: agent plugin manifests. The repository\n  root is the plugin package; its skills are `skills/` directly.\n- `models/`: sample and durable CAD/robot-description fixtures.\n- `viewer/`: editable CAD Viewer source app.\n- `packages/cadjs`: shared JS CAD/render/runtime code, UI-framework agnostic.\n- `packages/implicitjs`: standalone JS implicit CAD model, shader render,\n  snapshot, mesh sampling, and export runtime.\n- `packages/cadgen`: shared Python STEP/GLB/topology artifact code.\n- `docs/`: documentation site.\n- `tests/`: root-owned test suites for skills, packages, viewer services, and\n  repo-wide policy.\n- `scripts/`: durable repo commands grouped by purpose.\n\n## Repo Rules\n\n- Keep root guidance short. Put domain workflows, CLI details, and validation\n  policy in the relevant `skills/<skill>/SKILL.md` or `references/` file.\n- Keep relevant Markdown docs current when changing behavior, commands, or repo\n  layout, but do not bloat `AGENTS.md`; use it only for durable repo-level\n  rules and pointers.\n- Read `CONTRIBUTING.md` before committing, rebasing, resolving generated-file\n  conflicts, or bumping release versions.\n- Keep the primary local `develop` checkout in symlink layout with\n  `scripts/dev/setup-symlinks.sh`. Do not auto-repair that layout from\n  Codex or Claude Code startup hooks in linked worktrees.\n- Each skill must be self-contained and independent at runtime. A skill must\n  not refer to or import or depend on code from another skill, from `skills/`\n  root, or from repository-root modules. Do not add `skills/`, the repository\n  root, or sibling skill directories to `sys.path`, `PYTHONPATH`, `NODE_PATH`,\n  or similar runtime lookup paths. Shared runtime helpers must live under\n  `packages/` as the source of truth and be vendored/generated from there into\n  each consuming skill runtime; do not keep shared helper modules directly under\n  `skills/`.\n- Edit the source reached by the `develop` symlink layout first, then regenerate\n  explicit derived outputs when a production-output task requires it.\n- Write all test, sample, permanent, and generated CAD/robot-description\n  artifacts under `models/`, including STEP/STP, STL, GLB, DXF, URDF, SRDF,\n  and SDF outputs. Do not create ad hoc artifact directories elsewhere.\n- Reserve `scripts/` for durable repo commands. Do not write temporary,\n  one-off, or local-only helper scripts there; use `tmp/` or `/tmp` instead.\n- Development symlinks mark generated or copied paths. If a file is under a\n  symlinked runtime or viewer package path, edit the symlink target/source path\n  instead of treating the copy as independent.\n- When source changes affect generated runtimes, refresh or check them with the\n  master bundle wrapper, `scripts/bundle/bundle.sh`. Use lower-level bundle\n  scripts only when debugging the wrapper itself.\n- Never let a symlink reach the published tree. Agent installers disagree about\n  symlinks and one loses data silently: the Skills CLI dereferences them, Claude\n  Code preserves them, and Codex `plugin add` drops them with no error, shipping\n  a skill with missing files. `scripts/github-workflows/check-builds.sh` enforces\n  this; do not relax it.\n- `viewer/` must stay self-contained: nothing under it may reference a path,\n  command, or document above it, because it is mirrored verbatim into the\n  standalone `cad-viewer` repo with no rewriting step. Keep repo-level tooling\n  in `scripts/`, not under `viewer/`.\n  `viewer/scripts/selfContained.test.mjs` enforces this.\n- `packages/cadjs` must stay reusable/non-React; app UI and workflow state\n  belong in `viewer/`.\n- `packages/implicitjs` must stay reusable/non-React and independent of\n  `packages/cadjs` (`implicitjs` must never import `cadjs`). The dependency\n  flows one way: `cadjs` depends on `implicitjs` and re-exports its shared\n  render/export APIs under `cadjs/implicit/*`, so consumers (CAD Viewer,\n  snapshot tools) install and import `cadjs` alone rather than depending on\n  `implicitjs` directly or duplicating implicit CAD logic. Shared primitives\n  that both packages need live in `implicitjs` as the single source of truth\n  and are re-exported from `cadjs` (e.g. `cadjs/common/camera.js`).\n- `packages/cadgen` owns reusable Python artifact generation; skills should use\n  bundled package code, not sibling skill imports.\n- Create lightweight shared Python packages under `packages/` when a helper\n  should not inherit heavier package dependencies.\n- Use path-targeted search, validation, and `git status`; avoid broad scans over\n  generated CAD/LFS artifacts unless the task requires them.\n- Treat `VERSION` as the canonical release version. Do not hand-edit duplicate\n  package, plugin, lockfile, or Python `pyproject.toml` versions; release\n  preparation and `scripts/bundle/bundle.sh` stamp them from the canonical\n  version.\n\n## Environments\n\n- Prefer `./.venv/bin/python` for CAD Python work.\n- Keep new branch checkouts and git worktrees lightweight by default. Do not\n  copy `.venv/` or `models/` through `.worktreeinclude`; recreate `.venv/`\n  inside the worktree only when Python dependencies are needed for the workflow.\n- In Codex or Claude Code worktrees, prefer the skill instructions and scripts\n  under the current worktree's `skills/` directory over globally installed\n  skill symlinks from another checkout.\n- If a worktree explicitly needs the development symlink layout, run\n  `scripts/dev/setup-symlinks.sh --check` and then\n  `scripts/dev/setup-symlinks.sh` intentionally in that worktree.\n- Hydrate `models/` only when the user asks for it or when the task targets\n  specific files under `models/`. In a new worktree, make the relevant model\n  paths real before using them, preferring the local Git LFS cache with\n  `git lfs checkout <path>` or `git lfs checkout models`. Download missing LFS\n  objects only when explicitly requested or required after confirming the local\n  cache is missing them.\n- Install dependencies only for the workflow being changed.\n- Do not commit `.venv/`, `node_modules/`, caches, `tmp/`, local credentials, or\n  printer config.\n\n## Checks\n\nRun the smallest path-targeted check that covers the change. Use broad wrappers\nwhen touching shared surfaces or before handoff:\n\n- Code tests: `scripts/test/test.sh`\n  - In GitHub Actions, `test.yml` checks the canonical release version in a\n    separate job so code tests still run when version metadata is wrong; its\n    test job verifies the `develop` symlink layout, checks generated outputs\n    against their sources, bundles temporary production outputs, and runs docs\n    and code tests against that bundle. `main` writes are validated by the\n    `Release` workflow's publish job; GitHub branch settings should block PRs\n    and direct pushes to `main`.\n- Focused test runners: `scripts/test/test-js.sh`,\n  `scripts/test/test-docs.sh`, `scripts/test/test-python.sh`,\n  `scripts/test/test-global.sh`\n- Development symlink layout: `scripts/dev/setup-symlinks.sh --check`\n- Canonical release version: `scripts/release/check-version.sh`\n- Generated runtime freshness: `scripts/bundle/bundle.sh --check`\n- CAD Viewer, `packages/cadjs`, or `packages/implicitjs`:\n  `npm --prefix packages/cadjs test`, `npm --prefix packages/implicitjs test`,\n  `npm --prefix viewer run test`, `npm --prefix viewer run build`\n- Docs site: `npm --prefix docs run check`\n- Targeted Python tests: `./.venv/bin/python -m unittest <changed test paths>`\n\nWhen a task intentionally writes production outputs locally, run\n`scripts/bundle/bundle.sh`, rerun `scripts/bundle/bundle.sh --check`, and restore\nthe development symlink layout afterward if you are continuing on `develop`.\n\n## CAD Viewer\n\nA Viewer URL's PATH is the absolute directory it opens, exactly as in a `file://`\nURL, and `?file=` selects one artifact within it:\n\n```text\nhttp://127.0.0.1:3245/absolute/model/root?file=path/relative/to/that/root\n```\n\nOn Windows the drive is part of that path, after the leading slash and with\nforward slashes: `D:\\project\\models` is `.../3245/D:/project/models`.\n\nThe Viewer is not started against a directory — it opens whatever a URL names, so\none instance serves any folder **under its own served root**. That qualifier\nmatters in a worktree: an instance started from another checkout resolves paths\nagainst ITS root, so an absolute path into a different clone is simply not found\nand the pane reports it as outside this viewer's root. If a Viewer from another\ncheckout already holds the default port, start one for this workspace on a free\nport (`--port <n>`) rather than pointing the running one at your path.\n\nWhen reviewing repo fixtures, use the repo\n`models/` directory as the path and keep permanent or generated\nCAD/robot-description files there so the catalog and artifacts stay in one place.\nAlways use an absolute path: the Viewer runs from an arbitrary working directory,\nso a relative one resolves against the wrong place. Do not stop another Viewer\nunless the user asks.\n\nEditing `viewer/` or `packages/cadjs` source and not seeing the change? Vite's\nserver-side transform cache can outlive both HMR and a hard reload — the browser\nkeeps serving the old module while the file on disk is already correct. Restart\nthe dev server and delete `viewer/node_modules/.vite`.\n\n### Dev by default, prod only for e2e\n\nIterate with the **dev** server — Vite serves the client from source with HMR, so\nyour `viewer/`, `packages/cadjs`, and `packages/implicitjs` edits show up live:\n\n```bash\nnpm --prefix viewer run dev -- --host 127.0.0.1 --port <n>\n# then open http://127.0.0.1:<port><repo>/models?file=<path>\n```\n\nUse the **prod** path only for end-to-end tests against the shipped bundle, or\nwhen explicitly asked to test prod. It serves the built `dist/` via the Python\nbackend (the `cad-viewer` skill's `start` command), so build first:\n\n```bash\nnpm --prefix viewer run build\nnpm --prefix viewer run start -- --host 127.0.0.1 --port <n>\n# then open http://127.0.0.1:<port><repo>/models?file=<path>\n```\n\n### Ports\n\nBoth `dev` and `start` listen on `--port`, defaulting to `3245`. Neither rolls to\nanother port: if the port is taken they exit with an error, so a Viewer is always\non the port you asked for. Pass `--port <n>` to run more than one at a time.\n\nPackaged Viewer runtime and handoff details live in the `cad-viewer` skill.\nTreat packaged Viewer checks as generated-output checks via the master bundle\nwrapper unless you are debugging a lower-level script.\n\n### Starting the Viewer from a lightweight worktree\n\nThe `cad-viewer` skill documents the PRODUCTION runtime and assumes a hydrated\ncheckout. In a lightweight worktree its one-liner fails four times in a row, each\nwith an error that does not name the real cause, because worktrees deliberately\ncarry no `node_modules` and no built bundle:\n\n1. `npm --prefix skills/cad-viewer/scripts/viewer run start` dies with\n   `Cannot find package 'cadjs'`. `skills/cad-viewer/scripts/viewer` is a symlink\n   to `viewer/`, so the \"packaged\" runtime still needs the worktree's modules.\n2. With those linked, the server starts and the CAD API answers but `/` returns\n   404: `start` serves a prebuilt bundle and there is no `viewer/dist` yet. A live\n   backend with no front end looks like a broken link, not a missing build.\n3. `npm --prefix viewer run build` then fails one bare specifier at a time —\n   `implicitjs`, `three`, `meshoptimizer` — each from `packages/cadjs/src/...`.\n4. `meshoptimizer` is not under `packages/cadjs/node_modules` anywhere; the only\n   copy in the repo is `docs/node_modules/meshoptimizer`.\n\nFrom the worktree root, with `<main>` the primary checkout:\n\n```bash\nln -s <main>/viewer/node_modules viewer/node_modules\nmkdir -p packages/cadjs/node_modules\nln -s ../../implicitjs                                packages/cadjs/node_modules/implicitjs\nln -s <main>/packages/cadjs/node_modules/three        packages/cadjs/node_modules/three\nln -s <main>/docs/node_modules/meshoptimizer          packages/cadjs/node_modules/meshoptimizer\nnpm --prefix viewer run build\nnpm --prefix skills/cad-viewer/scripts/viewer run start -- --host 127.0.0.1 --port <n>\n```\n\nUse an explicit free `--port`: a Viewer already running from another checkout\nresolves paths against ITS root, so it will never find a model in this worktree.\n\nTwo behaviours worth knowing before you conclude a model is broken:\n\n- **The catalog scan skips dot-directories.** A buildable entry under `.review/`\n  or any other dotted path resolves by a direct `?dir=` query but never appears\n  in a scan from the project root, and the Viewer reports that the file does not\n  exist. Keep buildable entries out of dotted directories.\n- **Verify a Viewer link by loading the page**, not by curling `/__cad/asset`.\n  That route serves raw files; a generated entry's render package is served by a\n  different route, so probing it returns 404 whether or not anything is wrong.\n\n## Git And LFS\n\nCAD exchange files, generated render/topology assets, and `assets/**` may be\nLFS-tracked. Never disable LFS filters for `git add`, commits, or other\nobject-writing operations. Local hooks live in `.githooks` and\ndelegate build checks through `scripts/git-hooks/pre-commit`.\n"},"files":{"AGENTS.md":"# AGENTS.md\n\nThis repo is a workbench for CAD-related agent skills. Treat `skills/` as the\nproduct and `models/` as the shared fixture/artifact area.\n\n## Branch And Layout First\n\nBefore changing code, branch from `develop`, not `main`; PRs should target `develop`.\nDo not start development work from `main`. The `develop` branch intentionally uses\nsymlinks across generated runtime and viewer-local package paths. When a path is\nsymlinked, follow the link and edit the source target.\nUse `main` as the production clone/release branch only. `main` is publish-only:\ndo not open PRs to `main` or push it directly.\n\n## Release Workflow\n\nDo not bump the canonical release version in `VERSION` during\nnormal development work. Ship releases only through the single `Release`\nGitHub Actions workflow, which handles the version bump, release PR, publish\ncommit to `main`, `cadgen` PyPI publish, docs deploy, semver tag, and GitHub\nRelease in one run.\n\nWhen asked to publish, make, or ship a release, dispatch `Release` with its\ndefaults: build from `develop` (`base_branch=develop`), publish to `main`\n(`target_branch=main`), and publish the GitHub Release (`publish=true`, not a\ndraft). Never pick the semver bump yourself: if the request does not name\npatch, minor, major, or an exact version, ask which one before dispatching.\nUse `target_branch=build-test` only when the user explicitly asks to test\nCI/CD or build-pipeline changes — never by default and never as part of a\nrequested release, and pair it with `bump=none` so a rehearsal does not consume\na version number. `bump=none` publishes `base_branch` as it stands and is also\nhow you resume a failed publish; it is never a release setting.\n\nThe standalone `Deploy Docs` workflow redeploys the docs site without running a\nrelease. It deploys a source ref (defaulting to `develop`), never `main`: the\npublish tree drops `docs/` and `packages/`, which the docs app builds against.\nThe CAD Viewer is a local-filesystem app with no hosted deployment, but each\nrelease mirrors `viewer/` into the standalone `earthtojake/cad-viewer` repo\nthrough the `Sync CAD Viewer Repo` workflow, which `Release` calls after\npublishing and which can also be dispatched on its own. Both of those read the\nrelease SOURCE commit, because `main` carries only what installs.\n`main` is publish-only; pushing `develop` runs tests but\nnever publishes. See the Releases section in `CONTRIBUTING.md` for the full\nflow, CI/CD-testing and resume options, and local/manual fallbacks.\n\n## Repo Map\n\n- `skills/`: agent skills and their references/scripts.\n- `.claude-plugin/`, `.codex-plugin/`: agent plugin manifests. The repository\n  root is the plugin package; its skills are `skills/` directly.\n- `models/`: sample and durable CAD/robot-description fixtures.\n- `viewer/`: editable CAD Viewer source app.\n- `packages/cadjs`: shared JS CAD/render/runtime code, UI-framework agnostic.\n- `packages/implicitjs`: standalone JS implicit CAD model, shader render,\n  snapshot, mesh sampling, and export runtime.\n- `packages/cadgen`: shared Python STEP/GLB/topology artifact code.\n- `docs/`: documentation site.\n- `tests/`: root-owned test suites for skills, packages, viewer services, and\n  repo-wide policy.\n- `scripts/`: durable repo commands grouped by purpose.\n\n## Repo Rules\n\n- Keep root guidance short. Put domain workflows, CLI details, and validation\n  policy in the relevant `skills/<skill>/SKILL.md` or `references/` file.\n- Keep relevant Markdown docs current when changing behavior, commands, or repo\n  layout, but do not bloat `AGENTS.md`; use it only for durable repo-level\n  rules and pointers.\n- Read `CONTRIBUTING.md` before committing, rebasing, resolving generated-file\n  conflicts, or bumping release versions.\n- Keep the primary local `develop` checkout in symlink layout with\n  `scripts/dev/setup-symlinks.sh`. Do not auto-repair that layout from\n  Codex or Claude Code startup hooks in linked worktrees.\n- Each skill must be self-contained and independent at runtime. A skill must\n  not refer to or import or depend on code from another skill, from `skills/`\n  root, or from repository-root modules. Do not add `skills/`, the repository\n  root, or sibling skill directories to `sys.path`, `PYTHONPATH`, `NODE_PATH`,\n  or similar runtime lookup paths. Shared runtime helpers must live under\n  `packages/` as the source of truth and be vendored/generated from there into\n  each consuming skill runtime; do not keep shared helper modules directly under\n  `skills/`.\n- Edit the source reached by the `develop` symlink layout first, then regenerate\n  explicit derived outputs when a production-output task requires it.\n- Write all test, sample, permanent, and generated CAD/robot-description\n  artifacts under `models/`, including STEP/STP, STL, GLB, DXF, URDF, SRDF,\n  and SDF outputs. Do not create ad hoc artifact directories elsewhere.\n- Reserve `scripts/` for durable repo commands. Do not write temporary,\n  one-off, or local-only helper scripts there; use `tmp/` or `/tmp` instead.\n- Development symlinks mark generated or copied paths. If a file is under a\n  symlinked runtime or viewer package path, edit the symlink target/source path\n  instead of treating the copy as independent.\n- When source changes affect generated runtimes, refresh or check them with the\n  master bundle wrapper, `scripts/bundle/bundle.sh`. Use lower-level bundle\n  scripts only when debugging the wrapper itself.\n- Never let a symlink reach the published tree. Agent installers disagree about\n  symlinks and one loses data silently: the Skills CLI dereferences them, Claude\n  Code preserves them, and Codex `plugin add` drops them with no error, shipping\n  a skill with missing files. `scripts/github-workflows/check-builds.sh` enforces\n  this; do not relax it.\n- `viewer/` must stay self-contained: nothing under it may reference a path,\n  command, or document above it, because it is mirrored verbatim into the\n  standalone `cad-viewer` repo with no rewriting step. Keep repo-level tooling\n  in `scripts/`, not under `viewer/`.\n  `viewer/scripts/selfContained.test.mjs` enforces this.\n- `packages/cadjs` must stay reusable/non-React; app UI and workflow state\n  belong in `viewer/`.\n- `packages/implicitjs` must stay reusable/non-React and independent of\n  `packages/cadjs` (`implicitjs` must never import `cadjs`). The dependency\n  flows one way: `cadjs` depends on `implicitjs` and re-exports its shared\n  render/export APIs under `cadjs/implicit/*`, so consumers (CAD Viewer,\n  snapshot tools) install and import `cadjs` alone rather than depending on\n  `implicitjs` directly or duplicating implicit CAD logic. Shared primitives\n  that both packages need live in `implicitjs` as the single source of truth\n  and are re-exported from `cadjs` (e.g. `cadjs/common/camera.js`).\n- `packages/cadgen` owns reusable Python artifact generation; skills should use\n  bundled package code, not sibling skill imports.\n- Create lightweight shared Python packages under `packages/` when a helper\n  should not inherit heavier package dependencies.\n- Use path-targeted search, validation, and `git status`; avoid broad scans over\n  generated CAD/LFS artifacts unless the task requires them.\n- Treat `VERSION` as the canonical release version. Do not hand-edit duplicate\n  package, plugin, lockfile, or Python `pyproject.toml` versions; release\n  preparation and `scripts/bundle/bundle.sh` stamp them from the canonical\n  version.\n\n## Environments\n\n- Prefer `./.venv/bin/python` for CAD Python work.\n- Keep new branch checkouts and git worktrees lightweight by default. Do not\n  copy `.venv/` or `models/` through `.worktreeinclude`; recreate `.venv/`\n  inside the worktree only when Python dependencies are needed for the workflow.\n- In Codex or Claude Code worktrees, prefer the skill instructions and scripts\n  under the current worktree's `skills/` directory over globally installed\n  skill symlinks from another checkout.\n- If a worktree explicitly needs the development symlink layout, run\n  `scripts/dev/setup-symlinks.sh --check` and then\n  `scripts/dev/setup-symlinks.sh` intentionally in that worktree.\n- Hydrate `models/` only when the user asks for it or when the task targets\n  specific files under `models/`. In a new worktree, make the relevant model\n  paths real before using them, preferring the local Git LFS cache with\n  `git lfs checkout <path>` or `git lfs checkout models`. Download missing LFS\n  objects only when explicitly requested or required after confirming the local\n  cache is missing them.\n- Install dependencies only for the workflow being changed.\n- Do not commit `.venv/`, `node_modules/`, caches, `tmp/`, local credentials, or\n  printer config.\n\n## Checks\n\nRun the smallest path-targeted check that covers the change. Use broad wrappers\nwhen touching shared surfaces or before handoff:\n\n- Code tests: `scripts/test/test.sh`\n  - In GitHub Actions, `test.yml` checks the canonical release version in a\n    separate job so code tests still run when version metadata is wrong; its\n    test job verifies the `develop` symlink layout, checks generated outputs\n    against their sources, bundles temporary production outputs, and runs docs\n    and code tests against that bundle. `main` writes are validated by the\n    `Release` workflow's publish job; GitHub branch settings should block PRs\n    and direct pushes to `main`.\n- Focused test runners: `scripts/test/test-js.sh`,\n  `scripts/test/test-docs.sh`, `scripts/test/test-python.sh`,\n  `scripts/test/test-global.sh`\n- Development symlink layout: `scripts/dev/setup-symlinks.sh --check`\n- Canonical release version: `scripts/release/check-version.sh`\n- Generated runtime freshness: `scripts/bundle/bundle.sh --check`\n- CAD Viewer, `packages/cadjs`, or `packages/implicitjs`:\n  `npm --prefix packages/cadjs test`, `npm --prefix packages/implicitjs test`,\n  `npm --prefix viewer run test`, `npm --prefix viewer run build`\n- Docs site: `npm --prefix docs run check`\n- Targeted Python tests: `./.venv/bin/python -m unittest <changed test paths>`\n\nWhen a task intentionally writes production outputs locally, run\n`scripts/bundle/bundle.sh`, rerun `scripts/bundle/bundle.sh --check`, and restore\nthe development symlink layout afterward if you are continuing on `develop`.\n\n## CAD Viewer\n\nA Viewer URL's PATH is the absolute directory it opens, exactly as in a `file://`\nURL, and `?file=` selects one artifact within it:\n\n```text\nhttp://127.0.0.1:3245/absolute/model/root?file=path/relative/to/that/root\n```\n\nOn Windows the drive is part of that path, after the leading slash and with\nforward slashes: `D:\\project\\models` is `.../3245/D:/project/models`.\n\nThe Viewer is not started against a directory — it opens whatever a URL names, so\none instance serves any folder **under its own served root**. That qualifier\nmatters in a worktree: an instance started from another checkout resolves paths\nagainst ITS root, so an absolute path into a different clone is simply not found\nand the pane reports it as outside this viewer's root. If a Viewer from another\ncheckout already holds the default port, start one for this workspace on a free\nport (`--port <n>`) rather than pointing the running one at your path.\n\nWhen reviewing repo fixtures, use the repo\n`models/` directory as the path and keep permanent or generated\nCAD/robot-description files there so the catalog and artifacts stay in one place.\nAlways use an absolute path: the Viewer runs from an arbitrary working directory,\nso a relative one resolves against the wrong place. Do not stop another Viewer\nunless the user asks.\n\nEditing `viewer/` or `packages/cadjs` source and not seeing the change? Vite's\nserver-side transform cache can outlive both HMR and a hard reload — the browser\nkeeps serving the old module while the file on disk is already correct. Restart\nthe dev server and delete `viewer/node_modules/.vite`.\n\n### Dev by default, prod only for e2e\n\nIterate with the **dev** server — Vite serves the client from source with HMR, so\nyour `viewer/`, `packages/cadjs`, and `packages/implicitjs` edits show up live:\n\n```bash\nnpm --prefix viewer run dev -- --host 127.0.0.1 --port <n>\n# then open http://127.0.0.1:<port><repo>/models?file=<path>\n```\n\nUse the **prod** path only for end-to-end tests against the shipped bundle, or\nwhen explicitly asked to test prod. It serves the built `dist/` via the Python\nbackend (the `cad-viewer` skill's `start` command), so build first:\n\n```bash\nnpm --prefix viewer run build\nnpm --prefix viewer run start -- --host 127.0.0.1 --port <n>\n# then open http://127.0.0.1:<port><repo>/models?file=<path>\n```\n\n### Ports\n\nBoth `dev` and `start` listen on `--port`, defaulting to `3245`. Neither rolls to\nanother port: if the port is taken they exit with an error, so a Viewer is always\non the port you asked for. Pass `--port <n>` to run more than one at a time.\n\nPackaged Viewer runtime and handoff details live in the `cad-viewer` skill.\nTreat packaged Viewer checks as generated-output checks via the master bundle\nwrapper unless you are debugging a lower-level script.\n\n### Starting the Viewer from a lightweight worktree\n\nThe `cad-viewer` skill documents the PRODUCTION runtime and assumes a hydrated\ncheckout. In a lightweight worktree its one-liner fails four times in a row, each\nwith an error that does not name the real cause, because worktrees deliberately\ncarry no `node_modules` and no built bundle:\n\n1. `npm --prefix skills/cad-viewer/scripts/viewer run start` dies with\n   `Cannot find package 'cadjs'`. `skills/cad-viewer/scripts/viewer` is a symlink\n   to `viewer/`, so the \"packaged\" runtime still needs the worktree's modules.\n2. With those linked, the server starts and the CAD API answers but `/` returns\n   404: `start` serves a prebuilt bundle and there is no `viewer/dist` yet. A live\n   backend with no front end looks like a broken link, not a missing build.\n3. `npm --prefix viewer run build` then fails one bare specifier at a time —\n   `implicitjs`, `three`, `meshoptimizer` — each from `packages/cadjs/src/...`.\n4. `meshoptimizer` is not under `packages/cadjs/node_modules` anywhere; the only\n   copy in the repo is `docs/node_modules/meshoptimizer`.\n\nFrom the worktree root, with `<main>` the primary checkout:\n\n```bash\nln -s <main>/viewer/node_modules viewer/node_modules\nmkdir -p packages/cadjs/node_modules\nln -s ../../implicitjs                                packages/cadjs/node_modules/implicitjs\nln -s <main>/packages/cadjs/node_modules/three        packages/cadjs/node_modules/three\nln -s <main>/docs/node_modules/meshoptimizer          packages/cadjs/node_modules/meshoptimizer\nnpm --prefix viewer run build\nnpm --prefix skills/cad-viewer/scripts/viewer run start -- --host 127.0.0.1 --port <n>\n```\n\nUse an explicit free `--port`: a Viewer already running from another checkout\nresolves paths against ITS root, so it will never find a model in this worktree.\n\nTwo behaviours worth knowing before you conclude a model is broken:\n\n- **The catalog scan skips dot-directories.** A buildable entry under `.review/`\n  or any other dotted path resolves by a direct `?dir=` query but never appears\n  in a scan from the project root, and the Viewer reports that the file does not\n  exist. Keep buildable entries out of dotted directories.\n- **Verify a Viewer link by loading the page**, not by curling `/__cad/asset`.\n  That route serves raw files; a generated entry's render package is served by a\n  different route, so probing it returns 404 whether or not anything is wrong.\n\n## Git And LFS\n\nCAD exchange files, generated render/topology assets, and `assets/**` may be\nLFS-tracked. Never disable LFS filters for `git add`, commits, or other\nobject-writing operations. Local hooks live in `.githooks` and\ndelegate build checks through `scripts/git-hooks/pre-commit`.\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","title":"AGENTS.md","content":"# AGENTS.md\n\nThis repo is a workbench for CAD-related agent skills. Treat `skills/` as the\nproduct and `models/` as the shared fixture/artifact area.\n\n## Branch And Layout First\n\nBefore changing code, branch from `develop`, not `main`; PRs should target `develop`.\nDo not start development work from `main`. The `develop` branch intentionally uses\nsymlinks across generated runtime and viewer-local package paths. When a path is\nsymlinked, follow the link and edit the source target.\nUse `main` as the production clone/release branch only. `main` is publish-only:\ndo not open PRs to `main` or push it directly.\n\n## Release Workflow\n\nDo not bump the canonical release version in `VERSION` during\nnormal development work. Ship releases only through the single `Release`\nGitHub Actions workflow, which handles the version bump, release PR, publish\ncommit to `main`, `cadgen` PyPI publish, docs deploy, semver tag, and GitHub\nRelease in one run.\n\nWhen asked to publish, make, or ship a release, dispatch `Release` with its\ndefaults: build from `develop` (`base_branch=develop`), publish to `main`\n(`target_branch=main`), and publish the GitHub Release (`publish=true`, not a\ndraft). Never pick the semver bump yourself: if the request does not name\npatch, minor, major, or an exact version, ask which one before dispatching.\nUse `target_branch=build-test` only when the user explicitly asks to test\nCI/CD or build-pipeline changes — never by default and never as part of a\nrequested release, and pair it with `bump=none` so a rehearsal does not consume\na version number. `bump=none` publishes `base_branch` as it stands and is also\nhow you resume a failed publish; it is never a release setting.\n\nThe standalone `Deploy Docs` workflow redeploys the docs site without running a\nrelease. It deploys a source ref (defaulting to `develop`), never `main`: the\npublish tree drops `docs/` and `packages/`, which the docs app builds against.\nThe CAD Viewer is a local-filesystem app with no hosted deployment, but each\nrelease mirrors `viewer/` into the standalone `earthtojake/cad-viewer` repo\nthrough the `Sync CAD Viewer Repo` workflow, which `Release` calls after\npublishing and which can also be dispatched on its own. Both of those read the\nrelease SOURCE commit, because `main` carries only what installs.\n`main` is publish-only; pushing `develop` runs tests but\nnever publishes. See the Releases section in `CONTRIBUTING.md` for the full\nflow, CI/CD-testing and resume options, and local/manual fallbacks.\n\n## Repo Map\n\n- `skills/`: agent skills and their references/scripts.\n- `.claude-plugin/`, `.codex-plugin/`: agent plugin manifests. The repository\n  root is the plugin package; its skills are `skills/` directly.\n- `models/`: sample and durable CAD/robot-description fixtures.\n- `viewer/`: editable CAD Viewer source app.\n- `packages/cadjs`: shared JS CAD/render/runtime code, UI-framework agnostic.\n- `packages/implicitjs`: standalone JS implicit CAD model, shader render,\n  snapshot, mesh sampling, and export runtime.\n- `packages/cadgen`: shared Python STEP/GLB/topology artifact code.\n- `docs/`: documentation site.\n- `tests/`: root-owned test suites for skills, packages, viewer services, and\n  repo-wide policy.\n- `scripts/`: durable repo commands grouped by purpose.\n\n## Repo Rules\n\n- Keep root guidance short. Put domain workflows, CLI details, and validation\n  policy in the relevant `skills/<skill>/SKILL.md` or `references/` file.\n- Keep relevant Markdown docs current when changing behavior, commands, or repo\n  layout, but do not bloat `AGENTS.md`; use it only for durable repo-level\n  rules and pointers.\n- Read `CONTRIBUTING.md` before committing, rebasing, resolving generated-file\n  conflicts, or bumping release versions.\n- Keep the primary local `develop` checkout in symlink layout with\n  `scripts/dev/setup-symlinks.sh`. Do not auto-repair that layout from\n  Codex or Claude Code startup hooks in linked worktrees.\n- Each skill must be self-contained and independent at runtime. A skill must\n  not refer to or import or depend on code from another skill, from `skills/`\n  root, or from repository-root modules. Do not add `skills/`, the repository\n  root, or sibling skill directories to `sys.path`, `PYTHONPATH`, `NODE_PATH`,\n  or similar runtime lookup paths. Shared runtime helpers must live under\n  `packages/` as the source of truth and be vendored/generated from there into\n  each consuming skill runtime; do not keep shared helper modules directly under\n  `skills/`.\n- Edit the source reached by the `develop` symlink layout first, then regenerate\n  explicit derived outputs when a production-output task requires it.\n- Write all test, sample, permanent, and generated CAD/robot-description\n  artifacts under `models/`, including STEP/STP, STL, GLB, DXF, URDF, SRDF,\n  and SDF outputs. Do not create ad hoc artifact directories elsewhere.\n- Reserve `scripts/` for durable repo commands. Do not write temporary,\n  one-off, or local-only helper scripts there; use `tmp/` or `/tmp` instead.\n- Development symlinks mark generated or copied paths. If a file is under a\n  symlinked runtime or viewer package path, edit the symlink target/source path\n  instead of treating the copy as independent.\n- When source changes affect generated runtimes, refresh or check them with the\n  master bundle wrapper, `scripts/bundle/bundle.sh`. Use lower-level bundle\n  scripts only when debugging the wrapper itself.\n- Never let a symlink reach the published tree. Agent installers disagree about\n  symlinks and one loses data silently: the Skills CLI dereferences them, Claude\n  Code preserves them, and Codex `plugin add` drops them with no error, shipping\n  a skill with missing files. `scripts/github-workflows/check-builds.sh` enforces\n  this; do not relax it.\n- `viewer/` must stay self-contained: nothing under it may reference a path,\n  command, or document above it, because it is mirrored verbatim into the\n  standalone `cad-viewer` repo with no rewriting step. Keep repo-level tooling\n  in `scripts/`, not under `viewer/`.\n  `viewer/scripts/selfContained.test.mjs` enforces this.\n- `packages/cadjs` must stay reusable/non-React; app UI and workflow state\n  belong in `viewer/`.\n- `packages/implicitjs` must stay reusable/non-React and independent of\n  `packages/cadjs` (`implicitjs` must never import `cadjs`). The dependency\n  flows one way: `cadjs` depends on `implicitjs` and re-exports its shared\n  render/export APIs under `cadjs/implicit/*`, so consumers (CAD Viewer,\n  snapshot tools) install and import `cadjs` alone rather than depending on\n  `implicitjs` directly or duplicating implicit CAD logic. Shared primitives\n  that both packages need live in `implicitjs` as the single source of truth\n  and are re-exported from `cadjs` (e.g. `cadjs/common/camera.js`).\n- `packages/cadgen` owns reusable Python artifact generation; skills should use\n  bundled package code, not sibling skill imports.\n- Create lightweight shared Python packages under `packages/` when a helper\n  should not inherit heavier package dependencies.\n- Use path-targeted search, validation, and `git status`; avoid broad scans over\n  generated CAD/LFS artifacts unless the task requires them.\n- Treat `VERSION` as the canonical release version. Do not hand-edit duplicate\n  package, plugin, lockfile, or Python `pyproject.toml` versions; release\n  preparation and `scripts/bundle/bundle.sh` stamp them from the canonical\n  version.\n\n## Environments\n\n- Prefer `./.venv/bin/python` for CAD Python work.\n- Keep new branch checkouts and git worktrees lightweight by default. Do not\n  copy `.venv/` or `models/` through `.worktreeinclude`; recreate `.venv/`\n  inside the worktree only when Python dependencies are needed for the workflow.\n- In Codex or Claude Code worktrees, prefer the skill instructions and scripts\n  under the current worktree's `skills/` directory over globally installed\n  skill symlinks from another checkout.\n- If a worktree explicitly needs the development symlink layout, run\n  `scripts/dev/setup-symlinks.sh --check` and then\n  `scripts/dev/setup-symlinks.sh` intentionally in that worktree.\n- Hydrate `models/` only when the user asks for it or when the task targets\n  specific files under `models/`. In a new worktree, make the relevant model\n  paths real before using them, preferring the local Git LFS cache with\n  `git lfs checkout <path>` or `git lfs checkout models`. Download missing LFS\n  objects only when explicitly requested or required after confirming the local\n  cache is missing them.\n- Install dependencies only for the workflow being changed.\n- Do not commit `.venv/`, `node_modules/`, caches, `tmp/`, local credentials, or\n  printer config.\n\n## Checks\n\nRun the smallest path-targeted check that covers the change. Use broad wrappers\nwhen touching shared surfaces or before handoff:\n\n- Code tests: `scripts/test/test.sh`\n  - In GitHub Actions, `test.yml` checks the canonical release version in a\n    separate job so code tests still run when version metadata is wrong; its\n    test job verifies the `develop` symlink layout, checks generated outputs\n    against their sources, bundles temporary production outputs, and runs docs\n    and code tests against that bundle. `main` writes are validated by the\n    `Release` workflow's publish job; GitHub branch settings should block PRs\n    and direct pushes to `main`.\n- Focused test runners: `scripts/test/test-js.sh`,\n  `scripts/test/test-docs.sh`, `scripts/test/test-python.sh`,\n  `scripts/test/test-global.sh`\n- Development symlink layout: `scripts/dev/setup-symlinks.sh --check`\n- Canonical release version: `scripts/release/check-version.sh`\n- Generated runtime freshness: `scripts/bundle/bundle.sh --check`\n- CAD Viewer, `packages/cadjs`, or `packages/implicitjs`:\n  `npm --prefix packages/cadjs test`, `npm --prefix packages/implicitjs test`,\n  `npm --prefix viewer run test`, `npm --prefix viewer run build`\n- Docs site: `npm --prefix docs run check`\n- Targeted Python tests: `./.venv/bin/python -m unittest <changed test paths>`\n\nWhen a task intentionally writes production outputs locally, run\n`scripts/bundle/bundle.sh`, rerun `scripts/bundle/bundle.sh --check`, and restore\nthe development symlink layout afterward if you are continuing on `develop`.\n\n## CAD Viewer\n\nA Viewer URL's PATH is the absolute directory it opens, exactly as in a `file://`\nURL, and `?file=` selects one artifact within it:\n\n```text\nhttp://127.0.0.1:3245/absolute/model/root?file=path/relative/to/that/root\n```\n\nOn Windows the drive is part of that path, after the leading slash and with\nforward slashes: `D:\\project\\models` is `.../3245/D:/project/models`.\n\nThe Viewer is not started against a directory — it opens whatever a URL names, so\none instance serves any folder **under its own served root**. That qualifier\nmatters in a worktree: an instance started from another checkout resolves paths\nagainst ITS root, so an absolute path into a different clone is simply not found\nand the pane reports it as outside this viewer's root. If a Viewer from another\ncheckout already holds the default port, start one for this workspace on a free\nport (`--port <n>`) rather than pointing the running one at your path.\n\nWhen reviewing repo fixtures, use the repo\n`models/` directory as the path and keep permanent or generated\nCAD/robot-description files there so the catalog and artifacts stay in one place.\nAlways use an absolute path: the Viewer runs from an arbitrary working directory,\nso a relative one resolves against the wrong place. Do not stop another Viewer\nunless the user asks.\n\nEditing `viewer/` or `packages/cadjs` source and not seeing the change? Vite's\nserver-side transform cache can outlive both HMR and a hard reload — the browser\nkeeps serving the old module while the file on disk is already correct. Restart\nthe dev server and delete `viewer/node_modules/.vite`.\n\n### Dev by default, prod only for e2e\n\nIterate with the **dev** server — Vite serves the client from source with HMR, so\nyour `viewer/`, `packages/cadjs`, and `packages/implicitjs` edits show up live:\n\n```bash\nnpm --prefix viewer run dev -- --host 127.0.0.1 --port <n>\n# then open http://127.0.0.1:<port><repo>/models?file=<path>\n```\n\nUse the **prod** path only for end-to-end tests against the shipped bundle, or\nwhen explicitly asked to test prod. It serves the built `dist/` via the Python\nbackend (the `cad-viewer` skill's `start` command), so build first:\n\n```bash\nnpm --prefix viewer run build\nnpm --prefix viewer run start -- --host 127.0.0.1 --port <n>\n# then open http://127.0.0.1:<port><repo>/models?file=<path>\n```\n\n### Ports\n\nBoth `dev` and `start` listen on `--port`, defaulting to `3245`. Neither rolls to\nanother port: if the port is taken they exit with an error, so a Viewer is always\non the port you asked for. Pass `--port <n>` to run more than one at a time.\n\nPackaged Viewer runtime and handoff details live in the `cad-viewer` skill.\nTreat packaged Viewer checks as generated-output checks via the master bundle\nwrapper unless you are debugging a lower-level script.\n\n### Starting the Viewer from a lightweight worktree\n\nThe `cad-viewer` skill documents the PRODUCTION runtime and assumes a hydrated\ncheckout. In a lightweight worktree its one-liner fails four times in a row, each\nwith an error that does not name the real cause, because worktrees deliberately\ncarry no `node_modules` and no built bundle:\n\n1. `npm --prefix skills/cad-viewer/scripts/viewer run start` dies with\n   `Cannot find package 'cadjs'`. `skills/cad-viewer/scripts/viewer` is a symlink\n   to `viewer/`, so the \"packaged\" runtime still needs the worktree's modules.\n2. With those linked, the server starts and the CAD API answers but `/` returns\n   404: `start` serves a prebuilt bundle and there is no `viewer/dist` yet. A live\n   backend with no front end looks like a broken link, not a missing build.\n3. `npm --prefix viewer run build` then fails one bare specifier at a time —\n   `implicitjs`, `three`, `meshoptimizer` — each from `packages/cadjs/src/...`.\n4. `meshoptimizer` is not under `packages/cadjs/node_modules` anywhere; the only\n   copy in the repo is `docs/node_modules/meshoptimizer`.\n\nFrom the worktree root, with `<main>` the primary checkout:\n\n```bash\nln -s <main>/viewer/node_modules viewer/node_modules\nmkdir -p packages/cadjs/node_modules\nln -s ../../implicitjs                                packages/cadjs/node_modules/implicitjs\nln -s <main>/packages/cadjs/node_modules/three        packages/cadjs/node_modules/three\nln -s <main>/docs/node_modules/meshoptimizer          packages/cadjs/node_modules/meshoptimizer\nnpm --prefix viewer run build\nnpm --prefix skills/cad-viewer/scripts/viewer run start -- --host 127.0.0.1 --port <n>\n```\n\nUse an explicit free `--port`: a Viewer already running from another checkout\nresolves paths against ITS root, so it will never find a model in this worktree.\n\nTwo behaviours worth knowing before you conclude a model is broken:\n\n- **The catalog scan skips dot-directories.** A buildable entry under `.review/`\n  or any other dotted path resolves by a direct `?dir=` query but never appears\n  in a scan from the project root, and the Viewer reports that the file does not\n  exist. Keep buildable entries out of dotted directories.\n- **Verify a Viewer link by loading the page**, not by curling `/__cad/asset`.\n  That route serves raw files; a generated entry's render package is served by a\n  different route, so probing it returns 404 whether or not anything is wrong.\n\n## Git And LFS\n\nCAD exchange files, generated render/topology assets, and `assets/**` may be\nLFS-tracked. Never disable LFS filters for `git add`, commits, or other\nobject-writing operations. Local hooks live in `.githooks` and\ndelegate build checks through `scripts/git-hooks/pre-commit`.\n","category":"root","tokens":3943}]}