MotiaDev/motia/main 4.2M tokens More Tools
```
├── .cargo/
   ├── config.toml (100 tokens)
├── .config/
   ├── nextest.toml
├── .cursor/
   ├── rules/
      ├── docs.mdc (400 tokens)
   ├── skills/
      ├── doc_explanation.md (300 tokens)
      ├── doc_howto.md (200 tokens)
      ├── doc_reference.md (200 tokens)
      ├── doc_tutorial.md (400 tokens)
      ├── doc_workflow.md (800 tokens)
├── .githooks/
   ├── pre-commit (100 tokens)
├── .github/
   ├── assets/
      ├── iii-intro-preview.gif
      ├── workers-add.gif
      ├── zero-integration.png
   ├── pull_request_template.md
   ├── scripts/
      ├── build_engine_publish_payload.py (1700 tokens)
      ├── build_skills_payload.py (1100 tokens)
      ├── bump_manifests.py (1400 tokens)
      ├── calculate_release_version.py (2.4k tokens)
      ├── collect_engine_worker_interface.py (1400 tokens)
      ├── discover_engine_worker_skills.py (700 tokens)
      ├── license-agreement-check.mjs (2.2k tokens)
      ├── license-agreement-check.test.mjs (1000 tokens)
      ├── pin_docs.py (2.1k tokens)
      ├── test_bump_manifests.py (2.3k tokens)
      ├── test_calculate_release_version.py (7.5k tokens)
      ├── test_collect_engine_worker_interface.py (500 tokens)
      ├── test_pin_docs.py (3.2k tokens)
      ├── validate_release_worker_matrix.py (600 tokens)
   ├── workflows/
      ├── WORKFLOWS.md (3.4k tokens)
      ├── _go.yml (1200 tokens)
      ├── _homebrew.yml (2.1k tokens)
      ├── _npm.yml (700 tokens)
      ├── _publish-engine-workers.yml (1900 tokens)
      ├── _publish-worker-skills.yml (500 tokens)
      ├── _py.yml (600 tokens)
      ├── _rust-binary.yml (2.4k tokens)
      ├── _rust-cargo.yml (600 tokens)
      ├── alpha-release.yml (3.3k tokens)
      ├── bench-release.yml (600 tokens)
      ├── checklist-checker.yml (500 tokens)
      ├── ci.yml (6k tokens)
      ├── cloudfront-functions-test.yml (100 tokens)
      ├── create-tag.yml (2.7k tokens)
      ├── deploy-website.yml (1500 tokens)
      ├── docker-engine.yml (1700 tokens)
      ├── generate-api-docs.yml (800 tokens)
      ├── install-sh.yml (500 tokens)
      ├── license-check.yml (100 tokens)
      ├── publish-worker-skills.yml (100 tokens)
      ├── release-iii.yml (6.9k tokens)
      ├── skill-check-recheck.yml (200 tokens)
      ├── skill-check.yml (200 tokens)
      ├── smoke.yml (700 tokens)
      ├── test-scripts.yml (200 tokens)
      ├── tf-apply.yml (500 tokens)
      ├── tf-plan.yml (500 tokens)
├── .gitignore (200 tokens)
├── .prettierignore (omitted)
├── .prettierrc
├── .skill-check.yaml (100 tokens)
├── AGENTS.md (1200 tokens)
├── CONTRIBUTING.md (1900 tokens)
├── Cargo.lock (omitted)
├── Cargo.toml (300 tokens)
├── LICENSE.spdx (200 tokens)
├── Makefile (1600 tokens)
├── README.md (2.1k tokens)
├── biome.json (1100 tokens)
├── blog/
   ├── .gitignore
   ├── .nvmrc
   ├── README.md (400 tokens)
   ├── astro.config.mjs (100 tokens)
   ├── package.json (100 tokens)
   ├── src/
      ├── assets/
         ├── blog/
            ├── add-a-worker/
               ├── banner.png
               ├── orchestrator-network.png
               ├── orders-worker-chain.png
            ├── building-agents-for-real-world/
               ├── banner.png
            ├── how-to-build-your-own-agent-harness/
               ├── cover.png
            ├── loop-engineering-is-just-software-engineering/
               ├── banner.png
               ├── harness-traces-console.png
               ├── harness-turn-waterfall.png
               ├── loop-engineering-meme.png
               ├── provider-configuration.png
            ├── the-harness-is-the-backend/
               ├── point-to-point-vs-shared-runtime.png
            ├── the-substrate-is-installable/
               ├── banner.png
            ├── why-agent-sandboxes-are-converging-on-libkrun-not-firecracker/
               ├── banner.png
      ├── components/
         ├── AnalyticsHead.astro (400 tokens)
         ├── CookieBanner.astro (700 tokens)
         ├── Footer.astro (300 tokens)
         ├── FormattedDate.astro
         ├── Logo.astro (100 tokens)
         ├── ThemeInit.astro (300 tokens)
         ├── ThemeToggle.astro (700 tokens)
      ├── content.config.ts (100 tokens)
      ├── content/
         ├── blog/
            ├── add-a-worker.md (2.3k tokens)
            ├── building-agents-for-real-world.md (2.8k tokens)
            ├── how-to-build-your-own-agent-harness.md (4.7k tokens)
            ├── loop-engineering-is-just-software-engineering.md (2.7k tokens)
            ├── the-harness-is-the-backend.md (3.8k tokens)
            ├── the-substrate-is-installable.md (3.3k tokens)
            ├── why-agent-sandboxes-are-converging-on-libkrun-not-firecracker.md (4.5k tokens)
      ├── layouts/
         ├── BaseLayout.astro (400 tokens)
         ├── BlogPost.astro (200 tokens)
      ├── pages/
         ├── [...slug].astro (100 tokens)
         ├── index.astro (200 tokens)
         ├── rss.xml.ts (200 tokens)
      ├── styles/
         ├── global.css (1900 tokens)
   ├── tests/
      ├── build.test.ts (900 tokens)
   ├── tsconfig.json
├── console/
   ├── .gitignore (200 tokens)
   ├── LICENSE (2.2k tokens)
   ├── README.md (700 tokens)
   ├── install.sh (4.5k tokens)
   ├── lefthook.yml
   ├── package.json (200 tokens)
   ├── packages/
      ├── console-frontend/
         ├── DESIGN.md (1200 tokens)
         ├── README.md (1100 tokens)
         ├── biome.json (300 tokens)
         ├── index.html (300 tokens)
         ├── package.json (400 tokens)
         ├── postcss.config.mjs
         ├── public/
            ├── favicon/
               ├── android-chrome-192x192.png
               ├── android-chrome-512x512.png
               ├── apple-touch-icon.png
               ├── favicon-16x16.png
               ├── favicon-32x32.png
               ├── favicon.ico
               ├── site.webmanifest (100 tokens)
            ├── file.svg (100 tokens)
            ├── globe.svg (200 tokens)
            ├── iii-black1.1.svg (100 tokens)
            ├── iii-white1.1.svg (200 tokens)
            ├── next.svg (300 tokens)
            ├── vercel.svg
            ├── window.svg (100 tokens)
         ├── src/
            ├── api/
               ├── alerts/
                  ├── alerts.ts (300 tokens)
                  ├── sampling.ts (300 tokens)
               ├── config-provider.tsx (500 tokens)
               ├── config.ts (200 tokens)
               ├── events/
                  ├── functions.ts (800 tokens)
                  ├── invocation.ts (700 tokens)
               ├── flows/
                  ├── flows.ts (2.4k tokens)
                  ├── types.ts (300 tokens)
               ├── index.ts (700 tokens)
               ├── observability/
                  ├── logs.ts (800 tokens)
                  ├── metrics.ts (800 tokens)
                  ├── traces.ts (700 tokens)
               ├── queries.ts (1300 tokens)
               ├── queues/
                  ├── index.ts
                  ├── queues.ts (600 tokens)
               ├── state/
                  ├── state.ts (500 tokens)
                  ├── streams.ts (300 tokens)
               ├── system/
                  ├── adapters.ts (100 tokens)
                  ├── status.ts (500 tokens)
                  ├── workers.test.ts (300 tokens)
                  ├── workers.ts (400 tokens)
               ├── types/
                  ├── shared.ts (400 tokens)
               ├── utils.ts (400 tokens)
               ├── websocket.ts (1100 tokens)
            ├── components/
               ├── command-palette.tsx (1200 tokens)
               ├── filters/
                  ├── TimeRangeFilter.tsx (2.5k tokens)
               ├── flow/
                  ├── base-edge.tsx (300 tokens)
                  ├── flow-page.tsx (1400 tokens)
                  ├── flow-selector.tsx (400 tokens)
                  ├── flow-view.tsx (600 tokens)
                  ├── node-organizer.tsx (500 tokens)
                  ├── nodes/
                     ├── api-node.tsx (200 tokens)
                     ├── base-handle.tsx (200 tokens)
                     ├── base-node.tsx (400 tokens)
                     ├── cron-node.tsx (200 tokens)
                     ├── event-node.tsx (100 tokens)
                     ├── node-header.tsx (600 tokens)
                     ├── noop-node.tsx (100 tokens)
                     ├── queue-node.tsx (200 tokens)
                     ├── state-node.tsx (100 tokens)
                     ├── trigger-icon.tsx (100 tokens)
                     ├── trigger-list.tsx (300 tokens)
                  ├── use-flow-state.ts (900 tokens)
               ├── keyboard-shortcut-overlay.tsx (300 tokens)
               ├── layout/
                  ├── Sidebar.tsx (2.5k tokens)
               ├── queues/
                  ├── QueueDlqTab.test.ts (500 tokens)
                  ├── QueueDlqTab.tsx (3.5k tokens)
                  ├── QueueOverviewTab.tsx (1100 tokens)
                  ├── dlq-error.ts (500 tokens)
               ├── traces/
                  ├── AttributesFilter.tsx (1100 tokens)
                  ├── FlameGraph.tsx (4.7k tokens)
                  ├── FlowView.tsx (3.1k tokens)
                  ├── ServiceBreakdown.tsx (1000 tokens)
                  ├── SpanBaggageTab.tsx (600 tokens)
                  ├── SpanErrorsTab.tsx (1100 tokens)
                  ├── SpanInfoTab.tsx (1300 tokens)
                  ├── SpanLinksTab.tsx (400 tokens)
                  ├── SpanLogsTab.tsx (700 tokens)
                  ├── SpanOtelLogsTab.tsx (2.1k tokens)
                  ├── SpanPanel.tsx (2.2k tokens)
                  ├── SpanTagsTab.tsx (1600 tokens)
                  ├── TraceFilters.tsx (5.6k tokens)
                  ├── TraceHeader.tsx (1500 tokens)
                  ├── TraceMap.tsx (2.5k tokens)
                  ├── ViewSwitcher.tsx (300 tokens)
                  ├── WaterfallChart.tsx (3.3k tokens)
                  ├── WorkflowChain.tsx (700 tokens)
               ├── ui/
                  ├── button.tsx (300 tokens)
                  ├── card.tsx (1300 tokens)
                  ├── command.tsx (1000 tokens)
                  ├── dialog.tsx (800 tokens)
                  ├── empty-state.tsx (300 tokens)
                  ├── error-boundary.tsx (200 tokens)
                  ├── json-viewer.tsx (1100 tokens)
                  ├── page-header.tsx (200 tokens)
                  ├── pagination.tsx (700 tokens)
                  ├── search-bar.tsx (200 tokens)
                  ├── skeleton.tsx (100 tokens)
                  ├── tabs.tsx (400 tokens)
                  ├── tooltip.tsx (300 tokens)
            ├── hooks/
               ├── useKeyboard.ts (500 tokens)
               ├── useResizablePanels.ts (900 tokens)
               ├── useResizableSplitPane.ts (600 tokens)
               ├── useTheme.ts (300 tokens)
               ├── useTraceData.ts (700 tokens)
               ├── useTraceFilters.ts (1600 tokens)
            ├── lib/
               ├── otel-utils.ts (300 tokens)
               ├── timeRangeUtils.ts (200 tokens)
               ├── traceColors.ts (300 tokens)
               ├── traceGroups.test.ts (800 tokens)
               ├── traceGroups.ts (500 tokens)
               ├── traceTransform.ts (1800 tokens)
               ├── traceUtils.ts (500 tokens)
               ├── utils.ts
            ├── main.tsx (300 tokens)
            ├── routeTree.gen.ts (1600 tokens)
            ├── routes/
               ├── __root.tsx (600 tokens)
               ├── config.tsx (7.7k tokens)
               ├── dead-letter.tsx
               ├── flow.tsx
               ├── functions.tsx (4.2k tokens)
               ├── index.tsx (4.4k tokens)
               ├── logs.tsx (8.4k tokens)
               ├── queues.tsx (3.2k tokens)
               ├── states.tsx (7.2k tokens)
               ├── streams.tsx (7.6k tokens)
               ├── traces.tsx (4.4k tokens)
               ├── triggers.tsx (11k tokens)
               ├── workers.tsx (5k tokens)
            ├── styles/
               ├── globals.css (1000 tokens)
            ├── vite-env.d.ts (omitted)
         ├── tsconfig.json (100 tokens)
         ├── tsconfig.node.json
         ├── vite.config.ts (300 tokens)
         ├── vitest.config.ts (100 tokens)
      ├── console-rust/
         ├── Cargo.lock (omitted)
         ├── Cargo.toml (200 tokens)
         ├── build.rs (1000 tokens)
         ├── src/
            ├── bridge/
               ├── error.rs (200 tokens)
               ├── functions.rs (10.2k tokens)
               ├── mod.rs
               ├── triggers.rs (1000 tokens)
            ├── lib.rs
            ├── main.rs (1300 tokens)
            ├── proxy/
               ├── http.rs (800 tokens)
               ├── mod.rs
               ├── ws.rs (800 tokens)
            ├── server.rs (1600 tokens)
         ├── tests/
            ├── proxy_test.rs (1100 tokens)
├── contributors.md (100 tokens)
├── crates/
   ├── iii-clap-docs/
      ├── Cargo.toml (100 tokens)
      ├── src/
         ├── lib.rs (6.7k tokens)
   ├── iii-filesystem/
      ├── Cargo.toml (100 tokens)
      ├── build.rs (500 tokens)
      ├── src/
         ├── backends/
            ├── mod.rs
            ├── passthroughfs/
               ├── builder.rs (1400 tokens)
               ├── create_ops.rs (1300 tokens)
               ├── dir_ops.rs (2.4k tokens)
               ├── file_ops.rs (1300 tokens)
               ├── inode.rs (4.7k tokens)
               ├── metadata.rs (1300 tokens)
               ├── mod.rs (5.2k tokens)
               ├── remove_ops.rs (1300 tokens)
               ├── special.rs (600 tokens)
            ├── shared/
               ├── handle_table.rs (100 tokens)
               ├── init_binary.rs (1200 tokens)
               ├── inode_table.rs (1500 tokens)
               ├── mod.rs (100 tokens)
               ├── name_validation.rs (400 tokens)
               ├── platform.rs (5.2k tokens)
         ├── init.rs (200 tokens)
         ├── lib.rs (100 tokens)
      ├── tests/
         ├── filesystem_integration.rs (3.9k tokens)
   ├── iii-init/
      ├── Cargo.toml (300 tokens)
      ├── src/
         ├── child_exits.rs (1100 tokens)
         ├── error.rs (300 tokens)
         ├── fs_handler.rs (600 tokens)
         ├── fs_handler/
            ├── ops.rs (6.5k tokens)
            ├── streaming.rs (2.3k tokens)
            ├── tests.rs (7.6k tokens)
         ├── lib.rs (300 tokens)
         ├── main.rs (400 tokens)
         ├── mount.rs (3k tokens)
         ├── network.rs (2.3k tokens)
         ├── parse.rs (900 tokens)
         ├── rlimit.rs (500 tokens)
         ├── root_pivot.rs (6.3k tokens)
         ├── shell_dispatcher.rs (12.9k tokens)
         ├── supervisor.rs (3.5k tokens)
      ├── tests/
         ├── init_integration.rs (1100 tokens)
   ├── iii-network/
      ├── Cargo.toml (100 tokens)
      ├── src/
         ├── backend.rs (1300 tokens)
         ├── config.rs (100 tokens)
         ├── conn.rs (2.6k tokens)
         ├── device.rs (1700 tokens)
         ├── dns.rs (1600 tokens)
         ├── lib.rs (200 tokens)
         ├── network.rs (1100 tokens)
         ├── proxy.rs (1100 tokens)
         ├── shared.rs (700 tokens)
         ├── stack.rs (4.1k tokens)
         ├── udp_relay.rs (3.5k tokens)
         ├── wake_pipe.rs (800 tokens)
      ├── tests/
         ├── network_integration.rs (2.2k tokens)
   ├── iii-shell-client/
      ├── Cargo.toml (200 tokens)
      ├── src/
         ├── lib.rs (10.2k tokens)
      ├── tests/
         ├── fake_fs_relay.rs (4.1k tokens)
         ├── fake_relay.rs (4.1k tokens)
   ├── iii-shell-proto/
      ├── Cargo.toml (100 tokens)
      ├── src/
         ├── lib.rs (7.4k tokens)
   ├── iii-supervisor/
      ├── Cargo.toml (200 tokens)
      ├── src/
         ├── child.rs (6k tokens)
         ├── control.rs (2.2k tokens)
         ├── lib.rs (100 tokens)
         ├── protocol.rs (1200 tokens)
         ├── shell_protocol.rs (100 tokens)
      ├── tests/
         ├── socketpair_integration.rs (1200 tokens)
   ├── iii-worker/
      ├── Cargo.toml (700 tokens)
      ├── build.rs (300 tokens)
      ├── examples/
         ├── dump_worker_env.rs (200 tokens)
         ├── gen-golden.rs (300 tokens)
      ├── images/
         ├── node/
            ├── Dockerfile (100 tokens)
            ├── README.md (300 tokens)
         ├── python/
            ├── Dockerfile (200 tokens)
            ├── README.md (300 tokens)
      ├── src/
         ├── cli/
            ├── app.rs (4.2k tokens)
            ├── binary_download.rs (4.7k tokens)
            ├── builtin_defaults.rs (2.4k tokens)
            ├── bundle_download.rs (16.2k tokens)
            ├── config_file.rs (13.3k tokens)
            ├── download.rs (5.1k tokens)
            ├── erofs/
               ├── builder.rs (2.8k tokens)
               ├── crc32c.rs (300 tokens)
               ├── format.rs (700 tokens)
               ├── mod.rs (400 tokens)
               ├── reader.rs (7.3k tokens)
               ├── tree.rs (6.9k tokens)
               ├── writer.rs (9.1k tokens)
            ├── firmware/
               ├── constants.rs (1200 tokens)
               ├── download.rs (2.4k tokens)
               ├── libkrunfw_bytes.rs (100 tokens)
               ├── mod.rs (200 tokens)
               ├── resolve.rs (1600 tokens)
               ├── symlinks.rs (500 tokens)
            ├── gen_docs.rs (300 tokens)
            ├── host_shim.rs (10.2k tokens)
            ├── init.rs (3.9k tokens)
            ├── lifecycle.rs (800 tokens)
            ├── local_worker.rs (16.6k tokens)
            ├── lockfile.rs (7.9k tokens)
            ├── managed.rs (51.9k tokens)
            ├── mod.rs (200 tokens)
            ├── oci_ref.rs (700 tokens)
            ├── overlay.rs (1500 tokens)
            ├── pidfile.rs (2.2k tokens)
            ├── project.rs (10.7k tokens)
            ├── registry.rs (7.4k tokens)
            ├── rootfs.rs (500 tokens)
            ├── rootfs_cache.rs (1600 tokens)
            ├── sandbox.rs (5k tokens)
            ├── sandbox_daemon.rs (300 tokens)
            ├── shell_client.rs (7.1k tokens)
            ├── shell_relay.rs (11.8k tokens)
            ├── source_watcher.rs (10.1k tokens)
            ├── spinner.rs (1100 tokens)
            ├── status.rs (15.5k tokens)
            ├── stderr_sink.rs (300 tokens)
            ├── supervisor_ctl.rs (3.5k tokens)
            ├── sync.rs (3.4k tokens)
            ├── test_support.rs (400 tokens)
            ├── upper.rs (2.4k tokens)
            ├── vm_boot.rs (11.4k tokens)
            ├── worker_manager/
               ├── adapter.rs (200 tokens)
               ├── libkrun.rs (8.3k tokens)
               ├── mod.rs (100 tokens)
               ├── oci.rs (12k tokens)
               ├── platform.rs (700 tokens)
               ├── state.rs (1000 tokens)
            ├── worker_manager_daemon.rs (8.7k tokens)
            ├── worker_manifest.rs (8.7k tokens)
            ├── worker_manifest_deps.rs (1100 tokens)
            ├── worker_trigger.rs (5.4k tokens)
         ├── core/
            ├── add.rs (2.2k tokens)
            ├── clear.rs (700 tokens)
            ├── error.rs (4k tokens)
            ├── events.rs (600 tokens)
            ├── host.rs (1000 tokens)
            ├── list.rs (600 tokens)
            ├── logs.rs (3k tokens)
            ├── mod.rs (200 tokens)
            ├── project.rs (1600 tokens)
            ├── remove.rs (1000 tokens)
            ├── start.rs (900 tokens)
            ├── stop.rs (900 tokens)
            ├── types.rs (3.6k tokens)
            ├── update.rs (800 tokens)
         ├── daemon_exit.rs (6.2k tokens)
         ├── lib.rs (200 tokens)
         ├── main.rs (5.4k tokens)
         ├── sandbox_daemon/
            ├── README.md (4.4k tokens)
            ├── adapters.rs (6.7k tokens)
            ├── auto_install.rs (500 tokens)
            ├── catalog.rs (2.3k tokens)
            ├── config.rs (1800 tokens)
            ├── create.rs (2.3k tokens)
            ├── errors.rs (5.7k tokens)
            ├── events.rs (300 tokens)
            ├── exec.rs (3.8k tokens)
            ├── fs/
               ├── adapter.rs (2.5k tokens)
               ├── chmod.rs (1400 tokens)
               ├── grep.rs (1700 tokens)
               ├── ls.rs (1200 tokens)
               ├── mkdir.rs (1300 tokens)
               ├── mod.rs (300 tokens)
               ├── mv.rs (1300 tokens)
               ├── read.rs (2.7k tokens)
               ├── rm.rs (1200 tokens)
               ├── sed.rs (2k tokens)
               ├── stat.rs (1400 tokens)
               ├── write.rs (4.4k tokens)
            ├── iii.worker.yaml (100 tokens)
            ├── list.rs (700 tokens)
            ├── mod.rs (3.7k tokens)
            ├── overlay.rs (500 tokens)
            ├── reaper.rs (600 tokens)
            ├── registry.rs (1300 tokens)
            ├── run.rs (3k tokens)
            ├── skills/
               ├── SKILL.md (1400 tokens)
            ├── stop.rs (1200 tokens)
      ├── tests/
         ├── README.md (800 tokens)
         ├── binary_worker_integration.rs (3.1k tokens)
         ├── bundle_worker_integration.rs (11.8k tokens)
         ├── common/
            ├── assertions.rs (200 tokens)
            ├── fixtures.rs (600 tokens)
            ├── isolation.rs (300 tokens)
            ├── mod.rs (100 tokens)
            ├── sandbox_fakes.rs (2k tokens)
         ├── common_fixtures_integration.rs (700 tokens)
         ├── config_clear_integration.rs (500 tokens)
         ├── config_crossplatform_integration.rs (1200 tokens)
         ├── config_crud_integration.rs (2k tokens)
         ├── config_force_integration.rs (700 tokens)
         ├── config_managed_integration.rs (4.8k tokens)
         ├── config_path_type_integration.rs (1000 tokens)
         ├── daemon_orphan_exit_integration.rs (4.4k tokens)
         ├── engine_death_cascade_integration.rs (5.9k tokens)
         ├── fake_sandbox_relay.rs (1900 tokens)
         ├── firmware_integration.rs (2.6k tokens)
         ├── fixtures/
            ├── sandbox_error_codes.json (700 tokens)
            ├── templates/
               ├── default-gitignore
               ├── template.yaml (100 tokens)
               ├── worker-bare/
                  ├── Cargo.toml
                  ├── iii.worker.js.yaml
                  ├── iii.worker.py.yaml
                  ├── iii.worker.rust.yaml
                  ├── iii.worker.ts.yaml
                  ├── package.js.json
                  ├── package.ts.json (100 tokens)
                  ├── pyproject.toml
                  ├── src/
                     ├── index.js (100 tokens)
                     ├── index.ts (100 tokens)
                     ├── main.py (100 tokens)
                     ├── main.rs (200 tokens)
                  ├── template.yaml (300 tokens)
                  ├── tsconfig.json
         ├── local_add_dependencies_integration.rs (1600 tokens)
         ├── local_add_manifest_validation_integration.rs (1700 tokens)
         ├── local_worker_integration.rs (6.3k tokens)
         ├── oci_gate_smoke.rs (100 tokens)
         ├── oci_worker_integration.rs (3.7k tokens)
         ├── project_detection_integration.rs (2.4k tokens)
         ├── sandbox_docs_anchor_stability.rs (600 tokens)
         ├── sandbox_error_codes_integration.rs (1500 tokens)
         ├── sandbox_fs_decode_error_wire.rs (500 tokens)
         ├── sandbox_fs_integration.rs (7.9k tokens)
         ├── sandbox_fs_read_buffer_boundary.rs (1300 tokens)
         ├── sandbox_integration_e2e.rs (1000 tokens)
         ├── sandbox_lifecycle_integration.rs (3.7k tokens)
         ├── sandbox_workflow_integration.rs (1300 tokens)
         ├── sync_drift_adversarial.rs (2.9k tokens)
         ├── vm_args_integration.rs (4.3k tokens)
         ├── vm_gate_smoke.rs (100 tokens)
         ├── vm_integration.rs (3.2k tokens)
         ├── vm_lifecycle_integration.rs (1100 tokens)
         ├── worker_init_e2e.rs (2.6k tokens)
         ├── worker_integration.rs (3.5k tokens)
         ├── worker_list_discovery_integration.rs (4k tokens)
         ├── worker_manager_integration.rs (2.3k tokens)
         ├── worker_trigger_integration.rs (6.8k tokens)
      ├── vendor/
         ├── .gitignore
         ├── regen-golden.sh (400 tokens)
         ├── test-regen-golden.sh (300 tokens)
         ├── upper-golden.iiu.gz
   ├── motia-tools/
      ├── Cargo.toml (100 tokens)
      ├── src/
         ├── main.rs (800 tokens)
   ├── scaffolder-core/
      ├── Cargo.toml (200 tokens)
      ├── src/
         ├── cli.rs (1100 tokens)
         ├── iii.rs (400 tokens)
         ├── lib.rs (200 tokens)
         ├── product.rs (300 tokens)
         ├── runtime/
            ├── check.rs (1200 tokens)
            ├── mod.rs (100 tokens)
            ├── tool.rs (1400 tokens)
         ├── telemetry.rs (5.2k tokens)
         ├── templates/
            ├── copier.rs (1700 tokens)
            ├── fetcher.rs (2.3k tokens)
            ├── manifest.rs (1800 tokens)
            ├── mod.rs (100 tokens)
            ├── version.rs (1500 tokens)
         ├── tui/
            ├── mod.rs
            ├── prompts.rs (4.2k tokens)
      ├── tests/
         ├── cli_helpers.rs (400 tokens)
         ├── fetcher.rs (1700 tokens)
├── docs/
   ├── .gitignore
   ├── .mintignore
   ├── .prettierrc (100 tokens)
   ├── 0-10-0/
      ├── advanced/
         ├── adapters.mdx (1000 tokens)
         ├── architecture.mdx (1700 tokens)
         ├── custom-modules.mdx (4.5k tokens)
         ├── deployment.mdx (1800 tokens)
         ├── protocol.mdx (800 tokens)
         ├── telemetry.mdx (2.2k tokens)
      ├── api-reference/
         ├── disable-telemetry.mdx (200 tokens)
         ├── sdk-node.mdx (5.5k tokens)
         ├── sdk-python.mdx (5.2k tokens)
         ├── sdk-rust.mdx (5.2k tokens)
      ├── console/
         ├── index.mdx (3.6k tokens)
      ├── examples/
         ├── conditions.mdx (2.2k tokens)
         ├── cron.mdx (2k tokens)
         ├── hello-world.mdx (2k tokens)
         ├── multi-trigger.mdx (2.6k tokens)
         ├── observability.mdx (2.9k tokens)
         ├── state-management.mdx (2.7k tokens)
         ├── todo-app.mdx (3.4k tokens)
      ├── how-to/
         ├── configure-engine.mdx (5.3k tokens)
         ├── create-custom-trigger-type.mdx (1800 tokens)
         ├── create-ephemeral-worker.mdx (1100 tokens)
         ├── dead-letter-queues.mdx (1100 tokens)
         ├── define-request-response-formats.mdx (1400 tokens)
         ├── expose-http-endpoint.mdx (800 tokens)
         ├── manage-state.mdx (2000 tokens)
         ├── react-to-state-changes.mdx (1000 tokens)
         ├── schedule-cron-task.mdx (700 tokens)
         ├── stream-realtime-data.mdx (1600 tokens)
         ├── trigger-actions.mdx (7.1k tokens)
         ├── trigger-functions-from-cli.mdx (1300 tokens)
         ├── use-channels.mdx (4.7k tokens)
         ├── use-functions-and-triggers.mdx (6.4k tokens)
         ├── use-queues.mdx (7.1k tokens)
         ├── use-trigger-conditions.mdx (800 tokens)
      ├── index.mdx (700 tokens)
      ├── modules/
         ├── index.mdx (500 tokens)
         ├── module-bridge.mdx (800 tokens)
         ├── module-cron.mdx (1100 tokens)
         ├── module-exec.mdx (400 tokens)
         ├── module-http.mdx (1700 tokens)
         ├── module-observability.mdx (4.2k tokens)
         ├── module-pubsub.mdx (1700 tokens)
         ├── module-queue.mdx (2.3k tokens)
         ├── module-state.mdx (3.2k tokens)
         ├── module-stream.mdx (4.6k tokens)
      ├── primitives-and-concepts/
         ├── discovery.mdx (600 tokens)
         ├── functions-triggers-workers.mdx (500 tokens)
      ├── quickstart.mdx (500 tokens)
      ├── tutorials/
         ├── index.mdx
   ├── 0-11-0/
      ├── advanced/
         ├── adapters.mdx (800 tokens)
         ├── architecture.mdx (1700 tokens)
         ├── custom-modules.mdx (4.5k tokens)
         ├── deployment.mdx (1700 tokens)
         ├── protocol.mdx (800 tokens)
         ├── telemetry.mdx (2.2k tokens)
      ├── api-reference/
         ├── disable-telemetry.mdx (200 tokens)
         ├── sandbox.mdx (12.2k tokens)
         ├── sdk-browser.mdx (3.3k tokens)
         ├── sdk-node.mdx (5.3k tokens)
         ├── sdk-python.mdx (4.6k tokens)
         ├── sdk-rust.mdx (4.4k tokens)
      ├── architecture/
         ├── channels.mdx (4.8k tokens)
         ├── engine.mdx (1400 tokens)
         ├── external-workers.mdx (1200 tokens)
         ├── index.mdx (500 tokens)
         ├── queues.mdx (2.7k tokens)
         ├── trigger-types.mdx (8.2k tokens)
         ├── workers.mdx (800 tokens)
      ├── assets/
         ├── console-config-overview.png
         ├── console-functions-invoke.png
         ├── console-logs-detail.png
         ├── console-queues-overview.png
         ├── console-states-detail.png
         ├── console-traces-flame-graph.png
         ├── console-traces-flow.png
         ├── console-traces-map.png
         ├── console-traces-waterfall.png
         ├── console-triggers-http-test.png
         ├── console-workers-detail.png
         ├── console-workers-list.png
         ├── context7.json
         ├── todo-app.png
      ├── console/
         ├── index.mdx (4.3k tokens)
      ├── examples/
         ├── conditions.mdx (2.2k tokens)
         ├── cron.mdx (2.1k tokens)
         ├── hello-world.mdx (2000 tokens)
         ├── multi-trigger.mdx (2.7k tokens)
         ├── observability.mdx (3k tokens)
         ├── state-management.mdx (2.9k tokens)
         ├── todo-app.mdx (2.6k tokens)
      ├── how-to/
         ├── configure-engine.mdx (5.2k tokens)
         ├── create-custom-trigger-type.mdx (1800 tokens)
         ├── create-ephemeral-worker.mdx (1100 tokens)
         ├── dead-letter-queues.mdx (1100 tokens)
         ├── define-request-response-formats.mdx (1400 tokens)
         ├── developing-sandbox-workers.mdx (1900 tokens)
         ├── expose-http-endpoint.mdx (800 tokens)
         ├── manage-state.mdx (2.8k tokens)
         ├── managing-container-workers.mdx (1900 tokens)
         ├── observability-and-logs.mdx (2.5k tokens)
         ├── react-to-state-changes.mdx (900 tokens)
         ├── reproduce-worker-installs.mdx (900 tokens)
         ├── schedule-cron-task.mdx (700 tokens)
         ├── stream-realtime-data.mdx (2.3k tokens)
         ├── trigger-actions.mdx (6.9k tokens)
         ├── trigger-functions-from-cli.mdx (1300 tokens)
         ├── use-channels.mdx (4.6k tokens)
         ├── use-console.mdx (1200 tokens)
         ├── use-functions-and-triggers.mdx (6.5k tokens)
         ├── use-http-middleware.mdx (1400 tokens)
         ├── use-iii-in-the-browser.mdx (1400 tokens)
         ├── use-named-queues.mdx (5.2k tokens)
         ├── use-topic-queues.mdx (3k tokens)
         ├── use-trigger-conditions.mdx (800 tokens)
         ├── worker-rbac.mdx (4.6k tokens)
      ├── images/
         ├── architecture-dark.png
         ├── architecture-light.png
         ├── console/
            ├── config-overview-dark.png
            ├── config-overview-light.png
            ├── config-overview.png
            ├── console-logs.png
            ├── dashboard-dark.png
            ├── dashboard-light.png
            ├── dashboard.png
            ├── flow-view-dark.png
            ├── flow-view-light.png
            ├── flow-view.png
            ├── functions-dark.png
            ├── functions-invoke-dark.png
            ├── functions-invoke-light.png
            ├── functions-invoke.png
            ├── functions-light.png
            ├── functions.png
            ├── logs-dark.png
            ├── logs-detail-dark.png
            ├── logs-detail-light.png
            ├── logs-detail.png
            ├── logs-light.png
            ├── logs-list-dark.png
            ├── logs-list-light.png
            ├── logs-list.png
            ├── logs.png
            ├── states-dark.png
            ├── states-detail-dark.png
            ├── states-detail-light.png
            ├── states-detail.png
            ├── states-light.png
            ├── states.png
            ├── streams-dark.png
            ├── streams-detail-dark.png
            ├── streams-detail-light.png
            ├── streams-detail.png
            ├── streams-light.png
            ├── streams.png
            ├── traces-dark.png
            ├── traces-detail-dark.png
            ├── traces-detail-light.png
            ├── traces-detail.png
            ├── traces-light.png
            ├── traces-waterfall-dark.png
            ├── traces-waterfall-light.png
            ├── traces-waterfall.png
            ├── traces.png
            ├── triggers-dark.png
            ├── triggers-detail-dark.png
            ├── triggers-detail-light.png
            ├── triggers-detail.png
            ├── triggers-light.png
            ├── triggers.png
         ├── favicon/
            ├── apple-touch-icon.png
            ├── favicon-96x96.png
            ├── favicon.ico
            ├── favicon.svg (3.6k tokens)
            ├── site.webmanifest (100 tokens)
            ├── web-app-manifest-192x192.png
            ├── web-app-manifest-512x512.png
         ├── icons/
            ├── iii-black.svg (100 tokens)
            ├── iii-white.svg (200 tokens)
         ├── lsp.mp4
      ├── index.mdx (800 tokens)
      ├── install.mdx (400 tokens)
      ├── primitives-and-concepts/
         ├── discovery.mdx (700 tokens)
         ├── functions-triggers-workers.mdx (500 tokens)
      ├── quickstart.mdx (1900 tokens)
      ├── scripts/
         ├── generate-api-docs.mts (700 tokens)
         ├── parsers/
            ├── __tests__/
               ├── parse-griffe.test.mts (7.2k tokens)
               ├── parse-rustdoc.test.mts (8.7k tokens)
            ├── parse-griffe.mts (2.1k tokens)
            ├── parse-rustdoc.mts (4k tokens)
            ├── parse-typedoc.mts (1800 tokens)
         ├── renderers/
            ├── __tests__/
               ├── components.test.mts (700 tokens)
               ├── render-mdx.test.mts (700 tokens)
            ├── components.mts (700 tokens)
            ├── render-mdx.mts (900 tokens)
         ├── types.mts (200 tokens)
      ├── tutorials/
         ├── index.mdx
      ├── workers/
         ├── iii-bridge.mdx (800 tokens)
         ├── iii-cron.mdx (1200 tokens)
         ├── iii-exec.mdx (400 tokens)
         ├── iii-http.mdx (1800 tokens)
         ├── iii-observability.mdx (4.2k tokens)
         ├── iii-pubsub.mdx (1700 tokens)
         ├── iii-queue.mdx (3.4k tokens)
         ├── iii-state.mdx (4.7k tokens)
         ├── iii-stream.mdx (5.9k tokens)
         ├── iii-worker-manager.mdx (3.3k tokens)
         ├── index.mdx (400 tokens)
         ├── managed-worker-lockfile.mdx (1000 tokens)
         ├── worker-management-triggers.mdx (1600 tokens)
   ├── 0-12-0/
      ├── assets/
         ├── favicon.svg (3.6k tokens)
         ├── iii-black.svg (100 tokens)
         ├── iii-white.svg (200 tokens)
      ├── creating-workers/
         ├── functions.mdx (1300 tokens)
         ├── functions.mdx.skill.md (1300 tokens)
         ├── triggers.mdx (1400 tokens)
         ├── triggers.mdx.skill.md (1400 tokens)
         ├── workers-registry.mdx (300 tokens)
         ├── workers-registry.mdx.skill.md (400 tokens)
         ├── workers.mdx (1100 tokens)
         ├── workers.mdx.skill.md (1100 tokens)
      ├── how-to/
         ├── build-a-realtime-todo-app.mdx (300 tokens)
         ├── build-a-realtime-todo-app.mdx.skill.md (300 tokens)
      ├── index.mdx (1000 tokens)
      ├── index.mdx.skill.md (1000 tokens)
      ├── install.mdx (600 tokens)
      ├── install.mdx.skill.md (600 tokens)
      ├── patterns/
         ├── adapter-pattern.mdx (200 tokens)
         ├── adapter-pattern.mdx.skill.md (200 tokens)
         ├── reactive-state-pattern.mdx (300 tokens)
         ├── reactive-state-pattern.mdx.skill.md (300 tokens)
      ├── quickstart.mdx (1400 tokens)
      ├── quickstart.mdx.skill.md (1400 tokens)
      ├── sdk-reference/
         ├── browser-sdk.mdx (900 tokens)
         ├── browser-sdk.mdx.skill.md (900 tokens)
         ├── engine-sdk.mdx (2.2k tokens)
         ├── engine-sdk.mdx.skill.md (2.2k tokens)
         ├── node-sdk.mdx (1100 tokens)
         ├── node-sdk.mdx.skill.md (1100 tokens)
         ├── python-sdk.mdx (1200 tokens)
         ├── python-sdk.mdx.skill.md (1200 tokens)
         ├── rust-sdk.mdx (1100 tokens)
         ├── rust-sdk.mdx.skill.md (1100 tokens)
      ├── tutorials/
         ├── build-an-agent/
            ├── define-tools.mdx
            ├── define-tools.mdx.skill.md
            ├── memory-and-state.mdx
            ├── memory-and-state.mdx.skill.md
            ├── orchestration-loop.mdx
            ├── orchestration-loop.mdx.skill.md
            ├── overview.mdx (100 tokens)
            ├── overview.mdx.skill.md (100 tokens)
         ├── incremental-adoption/
            ├── migrate-persistence.mdx
            ├── migrate-persistence.mdx.skill.md
            ├── offload-to-queue.mdx
            ├── offload-to-queue.mdx.skill.md
            ├── overview.mdx (400 tokens)
            ├── overview.mdx.skill.md (400 tokens)
            ├── wrap-existing-api.mdx
            ├── wrap-existing-api.mdx.skill.md
         ├── reactive-crud/
            ├── crud-endpoints.mdx
            ├── crud-endpoints.mdx.skill.md
            ├── model-and-store.mdx
            ├── model-and-store.mdx.skill.md
            ├── overview.mdx (100 tokens)
            ├── overview.mdx.skill.md (200 tokens)
            ├── realtime-subscriptions.mdx
            ├── realtime-subscriptions.mdx.skill.md
      ├── understanding-iii/
         ├── channels.mdx (600 tokens)
         ├── channels.mdx.skill.md (700 tokens)
         ├── engine.mdx (600 tokens)
         ├── engine.mdx.skill.md (600 tokens)
         ├── functions.mdx (500 tokens)
         ├── functions.mdx.skill.md (500 tokens)
         ├── index.mdx (1500 tokens)
         ├── index.mdx.skill.md (1500 tokens)
         ├── triggers.mdx (900 tokens)
         ├── triggers.mdx.skill.md (900 tokens)
         ├── workers.mdx (300 tokens)
         ├── workers.mdx.skill.md (300 tokens)
      ├── using-iii/
         ├── channels.mdx (1100 tokens)
         ├── channels.mdx.skill.md (1100 tokens)
         ├── cli.mdx (600 tokens)
         ├── cli.mdx.skill.md (600 tokens)
         ├── console.mdx (1500 tokens)
         ├── console.mdx.skill.md (1500 tokens)
         ├── deployment.mdx (700 tokens)
         ├── deployment.mdx.skill.md (700 tokens)
         ├── engine.mdx (500 tokens)
         ├── engine.mdx.skill.md (500 tokens)
         ├── functions.mdx (600 tokens)
         ├── functions.mdx.skill.md (600 tokens)
         ├── triggers.mdx (1200 tokens)
         ├── triggers.mdx.skill.md (1200 tokens)
         ├── workers-registry.mdx (300 tokens)
         ├── workers-registry.mdx.skill.md (300 tokens)
         ├── workers.mdx (1400 tokens)
         ├── workers.mdx.skill.md (1300 tokens)
   ├── 0-13-0/
      ├── assets/
         ├── favicon.svg (3.6k tokens)
         ├── iii-black.svg (100 tokens)
         ├── iii-white.svg (200 tokens)
      ├── creating-workers/
         ├── functions.mdx (1300 tokens)
         ├── functions.mdx.skill.md (1300 tokens)
         ├── triggers.mdx (1400 tokens)
         ├── triggers.mdx.skill.md (1400 tokens)
         ├── workers-registry.mdx (1200 tokens)
         ├── workers-registry.mdx.skill.md (1200 tokens)
         ├── workers.mdx (1100 tokens)
         ├── workers.mdx.skill.md (1100 tokens)
      ├── how-to/
         ├── build-a-realtime-todo-app.mdx (300 tokens)
         ├── build-a-realtime-todo-app.mdx.skill.md (300 tokens)
      ├── index.mdx (1000 tokens)
      ├── index.mdx.skill.md (1000 tokens)
      ├── install.mdx (600 tokens)
      ├── install.mdx.skill.md (600 tokens)
      ├── patterns/
         ├── adapter-pattern.mdx (200 tokens)
         ├── adapter-pattern.mdx.skill.md (200 tokens)
         ├── reactive-state-pattern.mdx (300 tokens)
         ├── reactive-state-pattern.mdx.skill.md (300 tokens)
      ├── quickstart.mdx (1400 tokens)
      ├── quickstart.mdx.skill.md (1400 tokens)
      ├── sdk-reference/
         ├── browser-sdk.mdx (900 tokens)
         ├── browser-sdk.mdx.skill.md (900 tokens)
         ├── engine-sdk.mdx (2.2k tokens)
         ├── engine-sdk.mdx.skill.md (2.2k tokens)
         ├── node-sdk.mdx (1100 tokens)
         ├── node-sdk.mdx.skill.md (1100 tokens)
         ├── python-sdk.mdx (1200 tokens)
         ├── python-sdk.mdx.skill.md (1200 tokens)
         ├── rust-sdk.mdx (1100 tokens)
         ├── rust-sdk.mdx.skill.md (1100 tokens)
      ├── tutorials/
         ├── build-an-agent/
            ├── define-tools.mdx
            ├── define-tools.mdx.skill.md
            ├── memory-and-state.mdx
            ├── memory-and-state.mdx.skill.md
            ├── orchestration-loop.mdx
            ├── orchestration-loop.mdx.skill.md
            ├── overview.mdx (100 tokens)
            ├── overview.mdx.skill.md (100 tokens)
         ├── incremental-adoption/
            ├── migrate-persistence.mdx
            ├── migrate-persistence.mdx.skill.md
            ├── offload-to-queue.mdx
            ├── offload-to-queue.mdx.skill.md
            ├── overview.mdx (400 tokens)
            ├── overview.mdx.skill.md (400 tokens)
            ├── wrap-existing-api.mdx
            ├── wrap-existing-api.mdx.skill.md
         ├── reactive-crud/
            ├── crud-endpoints.mdx
            ├── crud-endpoints.mdx.skill.md
            ├── model-and-store.mdx
            ├── model-and-store.mdx.skill.md
            ├── overview.mdx (100 tokens)
            ├── overview.mdx.skill.md (200 tokens)
            ├── realtime-subscriptions.mdx
            ├── realtime-subscriptions.mdx.skill.md
      ├── understanding-iii/
         ├── channels.mdx (600 tokens)
         ├── channels.mdx.skill.md (700 tokens)
         ├── engine.mdx (600 tokens)
         ├── engine.mdx.skill.md (600 tokens)
         ├── functions.mdx (500 tokens)
         ├── functions.mdx.skill.md (500 tokens)
         ├── index.mdx (1500 tokens)
         ├── index.mdx.skill.md (1500 tokens)
         ├── triggers.mdx (1200 tokens)
         ├── triggers.mdx.skill.md (1200 tokens)
         ├── workers.mdx (300 tokens)
         ├── workers.mdx.skill.md (300 tokens)
      ├── using-iii/
         ├── channels.mdx (1100 tokens)
         ├── channels.mdx.skill.md (1100 tokens)
         ├── cli.mdx (600 tokens)
         ├── cli.mdx.skill.md (600 tokens)
         ├── console.mdx (1500 tokens)
         ├── console.mdx.skill.md (1500 tokens)
         ├── deployment.mdx (700 tokens)
         ├── deployment.mdx.skill.md (700 tokens)
         ├── engine.mdx (500 tokens)
         ├── engine.mdx.skill.md (500 tokens)
         ├── functions.mdx (600 tokens)
         ├── functions.mdx.skill.md (600 tokens)
         ├── triggers.mdx (1200 tokens)
         ├── triggers.mdx.skill.md (1200 tokens)
         ├── workers-registry.mdx (300 tokens)
         ├── workers-registry.mdx.skill.md (300 tokens)
         ├── workers.mdx (1400 tokens)
         ├── workers.mdx.skill.md (1300 tokens)
   ├── 0-16-0/
      ├── assets/
         ├── favicon.svg (3.6k tokens)
         ├── iii-black.svg (100 tokens)
         ├── iii-white.svg (200 tokens)
      ├── creating-workers/
         ├── channels.mdx (2.1k tokens)
         ├── channels.mdx.skill.md (2.1k tokens)
         ├── functions.mdx (2.5k tokens)
         ├── functions.mdx.skill.md (2.5k tokens)
         ├── index.mdx (300 tokens)
         ├── index.mdx.skill.md (300 tokens)
         ├── triggers.mdx (3.7k tokens)
         ├── triggers.mdx.skill.md (3.7k tokens)
         ├── workers-registry.mdx (1200 tokens)
         ├── workers-registry.mdx.skill.md (1200 tokens)
         ├── workers.mdx (3.5k tokens)
         ├── workers.mdx.skill.md (3.5k tokens)
      ├── how-to/
         ├── build-a-realtime-todo-app.mdx (300 tokens)
         ├── build-a-realtime-todo-app.mdx.skill.md (300 tokens)
         ├── schedule-cron-task.mdx (100 tokens)
         ├── schedule-cron-task.mdx.skill.md (100 tokens)
         ├── use-trigger-conditions.mdx (100 tokens)
         ├── use-trigger-conditions.mdx.skill.md (100 tokens)
      ├── index.mdx (900 tokens)
      ├── index.mdx.skill.md (900 tokens)
      ├── install.mdx (500 tokens)
      ├── install.mdx.skill.md (500 tokens)
      ├── patterns/
         ├── adapter-pattern.mdx (200 tokens)
         ├── adapter-pattern.mdx.skill.md (200 tokens)
         ├── reactive-state-pattern.mdx (300 tokens)
         ├── reactive-state-pattern.mdx.skill.md (300 tokens)
      ├── quickstart.mdx (1400 tokens)
      ├── quickstart.mdx.skill.md (1400 tokens)
      ├── sdk-reference/
         ├── browser-sdk.mdx (900 tokens)
         ├── browser-sdk.mdx.skill.md (900 tokens)
         ├── engine-sdk.mdx (2.2k tokens)
         ├── engine-sdk.mdx.skill.md (2.2k tokens)
         ├── node-sdk.mdx (1100 tokens)
         ├── node-sdk.mdx.skill.md (1100 tokens)
         ├── python-sdk.mdx (1200 tokens)
         ├── python-sdk.mdx.skill.md (1200 tokens)
         ├── rust-sdk.mdx (1200 tokens)
         ├── rust-sdk.mdx.skill.md (1200 tokens)
      ├── tutorials/
         ├── build-an-agent/
            ├── define-tools.mdx
            ├── define-tools.mdx.skill.md
            ├── memory-and-state.mdx
            ├── memory-and-state.mdx.skill.md
            ├── orchestration-loop.mdx
            ├── orchestration-loop.mdx.skill.md
            ├── overview.mdx (100 tokens)
            ├── overview.mdx.skill.md (100 tokens)
         ├── incremental-adoption/
            ├── migrate-persistence.mdx
            ├── migrate-persistence.mdx.skill.md
            ├── offload-to-queue.mdx
            ├── offload-to-queue.mdx.skill.md
            ├── overview.mdx (400 tokens)
            ├── overview.mdx.skill.md (400 tokens)
            ├── wrap-existing-api.mdx
            ├── wrap-existing-api.mdx.skill.md
         ├── reactive-crud/
            ├── crud-endpoints.mdx
            ├── crud-endpoints.mdx.skill.md
            ├── model-and-store.mdx
            ├── model-and-store.mdx.skill.md
            ├── overview.mdx (100 tokens)
            ├── overview.mdx.skill.md (200 tokens)
            ├── realtime-subscriptions.mdx
            ├── realtime-subscriptions.mdx.skill.md
      ├── understanding-iii/
         ├── channels.mdx (500 tokens)
         ├── channels.mdx.skill.md (500 tokens)
         ├── engine.mdx (600 tokens)
         ├── engine.mdx.skill.md (600 tokens)
         ├── index.mdx (2.9k tokens)
         ├── index.mdx.skill.md (2.9k tokens)
      ├── using-iii/
         ├── cli.mdx (600 tokens)
         ├── cli.mdx.skill.md (600 tokens)
         ├── console.mdx (1500 tokens)
         ├── console.mdx.skill.md (1500 tokens)
         ├── deployment.mdx (700 tokens)
         ├── deployment.mdx.skill.md (700 tokens)
         ├── engine.mdx (600 tokens)
         ├── engine.mdx.skill.md (600 tokens)
         ├── functions.mdx (1400 tokens)
         ├── functions.mdx.skill.md (1400 tokens)
         ├── triggers.mdx (2.3k tokens)
         ├── triggers.mdx.skill.md (2.3k tokens)
         ├── workers-registry.mdx (300 tokens)
         ├── workers-registry.mdx.skill.md (300 tokens)
         ├── workers.mdx (1500 tokens)
         ├── workers.mdx.skill.md (1400 tokens)
   ├── 0-17-0/
      ├── assets/
         ├── favicon.svg (3.6k tokens)
         ├── iii-black.svg (100 tokens)
         ├── iii-white.svg (200 tokens)
      ├── creating-workers/
         ├── channels.mdx (2000 tokens)
         ├── channels.mdx.skill.md (2000 tokens)
         ├── functions.mdx (2.5k tokens)
         ├── functions.mdx.skill.md (2.5k tokens)
         ├── index.mdx (300 tokens)
         ├── index.mdx.skill.md (300 tokens)
         ├── triggers.mdx (3.7k tokens)
         ├── triggers.mdx.skill.md (3.7k tokens)
         ├── workers-registry.mdx (1200 tokens)
         ├── workers-registry.mdx.skill.md (1200 tokens)
         ├── workers.mdx (3.5k tokens)
         ├── workers.mdx.skill.md (3.5k tokens)
      ├── how-to/
         ├── build-a-realtime-todo-app.mdx (300 tokens)
         ├── build-a-realtime-todo-app.mdx.skill.md (300 tokens)
         ├── schedule-cron-task.mdx (100 tokens)
         ├── schedule-cron-task.mdx.skill.md (100 tokens)
         ├── use-trigger-conditions.mdx (100 tokens)
         ├── use-trigger-conditions.mdx.skill.md (100 tokens)
      ├── index.mdx (900 tokens)
      ├── index.mdx.skill.md (900 tokens)
      ├── install.mdx (500 tokens)
      ├── install.mdx.skill.md (500 tokens)
      ├── patterns/
         ├── adapter-pattern.mdx (200 tokens)
         ├── adapter-pattern.mdx.skill.md (200 tokens)
         ├── reactive-state-pattern.mdx (300 tokens)
         ├── reactive-state-pattern.mdx.skill.md (300 tokens)
      ├── quickstart.mdx (1400 tokens)
      ├── quickstart.mdx.skill.md (1400 tokens)
      ├── sdk-reference/
         ├── browser-sdk.mdx (900 tokens)
         ├── browser-sdk.mdx.skill.md (900 tokens)
         ├── engine-sdk.mdx (2.2k tokens)
         ├── engine-sdk.mdx.skill.md (2.2k tokens)
         ├── node-sdk.mdx (1100 tokens)
         ├── node-sdk.mdx.skill.md (1100 tokens)
         ├── python-sdk.mdx (1200 tokens)
         ├── python-sdk.mdx.skill.md (1200 tokens)
         ├── rust-sdk.mdx (1100 tokens)
         ├── rust-sdk.mdx.skill.md (1100 tokens)
      ├── tutorials/
         ├── build-an-agent/
            ├── define-tools.mdx
            ├── define-tools.mdx.skill.md
            ├── memory-and-state.mdx
            ├── memory-and-state.mdx.skill.md
            ├── orchestration-loop.mdx
            ├── orchestration-loop.mdx.skill.md
            ├── overview.mdx (100 tokens)
            ├── overview.mdx.skill.md (100 tokens)
         ├── incremental-adoption/
            ├── migrate-persistence.mdx
            ├── migrate-persistence.mdx.skill.md
            ├── offload-to-queue.mdx
            ├── offload-to-queue.mdx.skill.md
            ├── overview.mdx (400 tokens)
            ├── overview.mdx.skill.md (400 tokens)
            ├── wrap-existing-api.mdx
            ├── wrap-existing-api.mdx.skill.md
         ├── reactive-crud/
            ├── crud-endpoints.mdx
            ├── crud-endpoints.mdx.skill.md
            ├── model-and-store.mdx
            ├── model-and-store.mdx.skill.md
            ├── overview.mdx (100 tokens)
            ├── overview.mdx.skill.md (200 tokens)
            ├── realtime-subscriptions.mdx
            ├── realtime-subscriptions.mdx.skill.md
      ├── understanding-iii/
         ├── channels.mdx (500 tokens)
         ├── channels.mdx.skill.md (500 tokens)
         ├── engine.mdx (600 tokens)
         ├── engine.mdx.skill.md (600 tokens)
         ├── index.mdx (2.9k tokens)
         ├── index.mdx.skill.md (2.9k tokens)
      ├── using-iii/
         ├── cli.mdx (600 tokens)
         ├── cli.mdx.skill.md (600 tokens)
         ├── console.mdx (1500 tokens)
         ├── console.mdx.skill.md (1500 tokens)
         ├── deployment.mdx (700 tokens)
         ├── deployment.mdx.skill.md (700 tokens)
         ├── engine.mdx (600 tokens)
         ├── engine.mdx.skill.md (600 tokens)
         ├── functions.mdx (1400 tokens)
         ├── functions.mdx.skill.md (1400 tokens)
         ├── triggers.mdx (2.3k tokens)
         ├── triggers.mdx.skill.md (2.3k tokens)
         ├── workers-registry.mdx (300 tokens)
         ├── workers-registry.mdx.skill.md (300 tokens)
         ├── workers.mdx (1500 tokens)
         ├── workers.mdx.skill.md (1400 tokens)
   ├── 0-18-0/
      ├── assets/
         ├── favicon.svg (3.6k tokens)
         ├── iii-black.svg (100 tokens)
         ├── iii-white.svg (200 tokens)
      ├── creating-workers/
         ├── channels.mdx (2000 tokens)
         ├── channels.mdx.skill.md (2000 tokens)
         ├── functions.mdx (2.5k tokens)
         ├── functions.mdx.skill.md (2.5k tokens)
         ├── index.mdx (300 tokens)
         ├── index.mdx.skill.md (300 tokens)
         ├── triggers.mdx (3.7k tokens)
         ├── triggers.mdx.skill.md (3.7k tokens)
         ├── workers-registry.mdx (1200 tokens)
         ├── workers-registry.mdx.skill.md (1200 tokens)
         ├── workers.mdx (3.5k tokens)
         ├── workers.mdx.skill.md (3.5k tokens)
      ├── how-to/
         ├── build-a-realtime-todo-app.mdx (300 tokens)
         ├── build-a-realtime-todo-app.mdx.skill.md (300 tokens)
         ├── schedule-cron-task.mdx (100 tokens)
         ├── schedule-cron-task.mdx.skill.md (100 tokens)
         ├── use-trigger-conditions.mdx (100 tokens)
         ├── use-trigger-conditions.mdx.skill.md (100 tokens)
      ├── index.mdx (1000 tokens)
      ├── index.mdx.skill.md (1000 tokens)
      ├── install.mdx (500 tokens)
      ├── install.mdx.skill.md (500 tokens)
      ├── patterns/
         ├── adapter-pattern.mdx (200 tokens)
         ├── adapter-pattern.mdx.skill.md (200 tokens)
         ├── reactive-state-pattern.mdx (300 tokens)
         ├── reactive-state-pattern.mdx.skill.md (300 tokens)
      ├── quickstart.mdx (1500 tokens)
      ├── quickstart.mdx.skill.md (1500 tokens)
      ├── sdk-reference/
         ├── browser-sdk.mdx (900 tokens)
         ├── browser-sdk.mdx.skill.md (900 tokens)
         ├── engine-sdk.mdx (2.2k tokens)
         ├── engine-sdk.mdx.skill.md (2.2k tokens)
         ├── node-sdk.mdx (1100 tokens)
         ├── node-sdk.mdx.skill.md (1100 tokens)
         ├── python-sdk.mdx (1200 tokens)
         ├── python-sdk.mdx.skill.md (1200 tokens)
         ├── rust-sdk.mdx (1100 tokens)
         ├── rust-sdk.mdx.skill.md (1100 tokens)
      ├── tutorials/
         ├── build-an-agent/
            ├── define-tools.mdx
            ├── define-tools.mdx.skill.md
            ├── memory-and-state.mdx
            ├── memory-and-state.mdx.skill.md
            ├── orchestration-loop.mdx
            ├── orchestration-loop.mdx.skill.md
            ├── overview.mdx (100 tokens)
            ├── overview.mdx.skill.md (100 tokens)
         ├── incremental-adoption/
            ├── migrate-persistence.mdx
            ├── migrate-persistence.mdx.skill.md
            ├── offload-to-queue.mdx
            ├── offload-to-queue.mdx.skill.md
            ├── overview.mdx (400 tokens)
            ├── overview.mdx.skill.md (400 tokens)
            ├── wrap-existing-api.mdx
            ├── wrap-existing-api.mdx.skill.md
         ├── linkly/
            ├── channels.mdx (800 tokens)
            ├── channels.mdx.skill.md (800 tokens)
            ├── console-traces.png
            ├── durable-execution.mdx (2.2k tokens)
            ├── durable-execution.mdx.skill.md (2.2k tokens)
            ├── foundations.mdx (2.5k tokens)
            ├── foundations.mdx.skill.md (2.5k tokens)
            ├── frontend.mdx (2.2k tokens)
            ├── frontend.mdx.skill.md (2.1k tokens)
            ├── observability.mdx (1400 tokens)
            ├── observability.mdx.skill.md (1400 tokens)
            ├── overview.mdx (400 tokens)
            ├── overview.mdx.skill.md (400 tokens)
            ├── persistence.mdx (1500 tokens)
            ├── persistence.mdx.skill.md (1500 tokens)
            ├── streaming.mdx (800 tokens)
            ├── streaming.mdx.skill.md (800 tokens)
         ├── reactive-crud/
            ├── crud-endpoints.mdx
            ├── crud-endpoints.mdx.skill.md
            ├── model-and-store.mdx
            ├── model-and-store.mdx.skill.md
            ├── overview.mdx (100 tokens)
            ├── overview.mdx.skill.md (200 tokens)
            ├── realtime-subscriptions.mdx
            ├── realtime-subscriptions.mdx.skill.md
      ├── understanding-iii/
         ├── channels.mdx (500 tokens)
         ├── channels.mdx.skill.md (500 tokens)
         ├── engine.mdx (600 tokens)
         ├── engine.mdx.skill.md (600 tokens)
         ├── index.mdx (2.9k tokens)
         ├── index.mdx.skill.md (2.9k tokens)
      ├── using-iii/
         ├── cli.mdx (600 tokens)
         ├── cli.mdx.skill.md (600 tokens)
         ├── console.mdx (1500 tokens)
         ├── console.mdx.skill.md (1500 tokens)
         ├── deployment.mdx (700 tokens)
         ├── deployment.mdx.skill.md (700 tokens)
         ├── engine.mdx (600 tokens)
         ├── engine.mdx.skill.md (600 tokens)
         ├── functions.mdx (1400 tokens)
         ├── functions.mdx.skill.md (1400 tokens)
         ├── triggers.mdx (2.3k tokens)
         ├── triggers.mdx.skill.md (2.3k tokens)
         ├── workers-registry.mdx (300 tokens)
         ├── workers-registry.mdx.skill.md (300 tokens)
         ├── workers.mdx (1500 tokens)
         ├── workers.mdx.skill.md (1400 tokens)
   ├── 0-19-0/
      ├── assets/
         ├── favicon.svg (3.6k tokens)
         ├── iii-black.svg (100 tokens)
         ├── iii-white.svg (200 tokens)
      ├── cli-reference/
         ├── index.mdx (5.1k tokens)
         ├── index.mdx.skill.md (5.1k tokens)
      ├── creating-workers/
         ├── channels.mdx (2000 tokens)
         ├── channels.mdx.skill.md (2000 tokens)
         ├── functions.mdx (2.5k tokens)
         ├── functions.mdx.skill.md (2.5k tokens)
         ├── index.mdx (300 tokens)
         ├── index.mdx.skill.md (300 tokens)
         ├── triggers.mdx (3.7k tokens)
         ├── triggers.mdx.skill.md (3.7k tokens)
         ├── worker-manifest.mdx (900 tokens)
         ├── worker-manifest.mdx.skill.md (900 tokens)
         ├── workers-registry.mdx (1200 tokens)
         ├── workers-registry.mdx.skill.md (1200 tokens)
         ├── workers.mdx (3.6k tokens)
         ├── workers.mdx.skill.md (3.6k tokens)
      ├── how-to/
         ├── build-a-realtime-todo-app.mdx (300 tokens)
         ├── build-a-realtime-todo-app.mdx.skill.md (300 tokens)
         ├── schedule-cron-task.mdx (100 tokens)
         ├── schedule-cron-task.mdx.skill.md (100 tokens)
         ├── use-trigger-conditions.mdx (100 tokens)
         ├── use-trigger-conditions.mdx.skill.md (100 tokens)
      ├── index.mdx (1000 tokens)
      ├── index.mdx.skill.md (1000 tokens)
      ├── install.mdx (500 tokens)
      ├── install.mdx.skill.md (500 tokens)
      ├── patterns/
         ├── adapter-pattern.mdx (200 tokens)
         ├── adapter-pattern.mdx.skill.md (200 tokens)
         ├── reactive-state-pattern.mdx (300 tokens)
         ├── reactive-state-pattern.mdx.skill.md (300 tokens)
      ├── quickstart.mdx (1500 tokens)
      ├── quickstart.mdx.skill.md (1500 tokens)
      ├── sdk-reference/
         ├── browser-sdk.mdx (900 tokens)
         ├── browser-sdk.mdx.skill.md (900 tokens)
         ├── engine-sdk.mdx (2.2k tokens)
         ├── engine-sdk.mdx.skill.md (2.2k tokens)
         ├── node-sdk.mdx (1200 tokens)
         ├── node-sdk.mdx.skill.md (1200 tokens)
         ├── python-sdk.mdx (1200 tokens)
         ├── python-sdk.mdx.skill.md (1200 tokens)
         ├── rust-sdk.mdx (1200 tokens)
         ├── rust-sdk.mdx.skill.md (1200 tokens)
      ├── troubleshooting.mdx (200 tokens)
      ├── troubleshooting.mdx.skill.md (200 tokens)
      ├── tutorials/
         ├── build-an-agent/
            ├── define-tools.mdx
            ├── define-tools.mdx.skill.md
            ├── memory-and-state.mdx
            ├── memory-and-state.mdx.skill.md
            ├── orchestration-loop.mdx
            ├── orchestration-loop.mdx.skill.md
            ├── overview.mdx (100 tokens)
            ├── overview.mdx.skill.md (100 tokens)
         ├── incremental-adoption/
            ├── migrate-persistence.mdx
            ├── migrate-persistence.mdx.skill.md
            ├── offload-to-queue.mdx
            ├── offload-to-queue.mdx.skill.md
            ├── overview.mdx (400 tokens)
            ├── overview.mdx.skill.md (400 tokens)
            ├── wrap-existing-api.mdx
            ├── wrap-existing-api.mdx.skill.md
         ├── linkly/
            ├── channels.mdx (800 tokens)
            ├── channels.mdx.skill.md (800 tokens)
            ├── console-traces.png
            ├── durable-execution.mdx (2.2k tokens)
            ├── durable-execution.mdx.skill.md (2.2k tokens)
            ├── foundations.mdx (2.5k tokens)
            ├── foundations.mdx.skill.md (2.5k tokens)
            ├── frontend.mdx (2.2k tokens)
            ├── frontend.mdx.skill.md (2.2k tokens)
            ├── observability.mdx (1200 tokens)
            ├── observability.mdx.skill.md (1200 tokens)
            ├── overview.mdx (400 tokens)
            ├── overview.mdx.skill.md (400 tokens)
            ├── persistence.mdx (1600 tokens)
            ├── persistence.mdx.skill.md (1600 tokens)
            ├── streaming.mdx (900 tokens)
            ├── streaming.mdx.skill.md (900 tokens)
         ├── reactive-crud/
            ├── crud-endpoints.mdx
            ├── crud-endpoints.mdx.skill.md
            ├── model-and-store.mdx
            ├── model-and-store.mdx.skill.md
            ├── overview.mdx (100 tokens)
            ├── overview.mdx.skill.md (200 tokens)
            ├── realtime-subscriptions.mdx
            ├── realtime-subscriptions.mdx.skill.md
      ├── understanding-iii/
         ├── channels.mdx (500 tokens)
         ├── channels.mdx.skill.md (500 tokens)
         ├── engine.mdx (600 tokens)
         ├── engine.mdx.skill.md (600 tokens)
         ├── index.mdx (2.9k tokens)
         ├── index.mdx.skill.md (2.9k tokens)
      ├── using-iii/
         ├── cli.mdx (600 tokens)
         ├── cli.mdx.skill.md (600 tokens)
         ├── console.mdx (1500 tokens)
         ├── console.mdx.skill.md (1500 tokens)
         ├── deployment.mdx (700 tokens)
         ├── deployment.mdx.skill.md (700 tokens)
         ├── engine.mdx (600 tokens)
         ├── engine.mdx.skill.md (600 tokens)
         ├── functions.mdx (1900 tokens)
         ├── functions.mdx.skill.md (1900 tokens)
         ├── triggers.mdx (1700 tokens)
         ├── triggers.mdx.skill.md (1700 tokens)
         ├── workers-registry.mdx (300 tokens)
         ├── workers-registry.mdx.skill.md (300 tokens)
         ├── workers.mdx (1800 tokens)
         ├── workers.mdx.skill.md (1700 tokens)
   ├── 0-20-0/
      ├── api-reference/
         ├── helpers-node.mdx (7.4k tokens)
         ├── helpers-node.mdx.skill.md (7.4k tokens)
         ├── helpers-python.mdx (5.4k tokens)
         ├── helpers-python.mdx.skill.md (5.4k tokens)
         ├── helpers-rust.mdx (4.9k tokens)
         ├── helpers-rust.mdx.skill.md (4.9k tokens)
         ├── sdk-browser.mdx (7.6k tokens)
         ├── sdk-browser.mdx.skill.md (7.6k tokens)
         ├── sdk-node.mdx (5.4k tokens)
         ├── sdk-node.mdx.skill.md (5.5k tokens)
         ├── sdk-python.mdx (4.4k tokens)
         ├── sdk-python.mdx.skill.md (4.4k tokens)
         ├── sdk-rust.mdx (5.6k tokens)
         ├── sdk-rust.mdx.skill.md (5.6k tokens)
      ├── assets/
         ├── favicon.svg (3.6k tokens)
         ├── iii-black.svg (100 tokens)
         ├── iii-white.svg (200 tokens)
      ├── cli-reference/
         ├── index.mdx (5.1k tokens)
         ├── index.mdx.skill.md (5.1k tokens)
      ├── creating-workers/
         ├── channels.mdx (2000 tokens)
         ├── channels.mdx.skill.md (2000 tokens)
         ├── functions.mdx (2.8k tokens)
         ├── functions.mdx.skill.md (2.8k tokens)
         ├── http.mdx (800 tokens)
         ├── http.mdx.skill.md (800 tokens)
         ├── index.mdx (500 tokens)
         ├── index.mdx.skill.md (500 tokens)
         ├── observability.mdx (1100 tokens)
         ├── observability.mdx.skill.md (1100 tokens)
         ├── queues.mdx (1500 tokens)
         ├── queues.mdx.skill.md (1500 tokens)
         ├── sandboxes.mdx (900 tokens)
         ├── sandboxes.mdx.skill.md (900 tokens)
         ├── triggers.mdx (3.7k tokens)
         ├── triggers.mdx.skill.md (3.7k tokens)
         ├── worker-manager.mdx (2.4k tokens)
         ├── worker-manager.mdx.skill.md (2.4k tokens)
         ├── worker-manifest.mdx (1000 tokens)
         ├── worker-manifest.mdx.skill.md (1000 tokens)
         ├── workers-registry.mdx (1200 tokens)
         ├── workers-registry.mdx.skill.md (1200 tokens)
         ├── workers.mdx (3.8k tokens)
         ├── workers.mdx.skill.md (3.8k tokens)
      ├── how-to/
         ├── build-a-realtime-todo-app.mdx (300 tokens)
         ├── build-a-realtime-todo-app.mdx.skill.md (300 tokens)
         ├── schedule-cron-task.mdx (100 tokens)
         ├── schedule-cron-task.mdx.skill.md (100 tokens)
         ├── use-trigger-conditions.mdx (100 tokens)
         ├── use-trigger-conditions.mdx.skill.md (100 tokens)
      ├── index.mdx (1000 tokens)
      ├── install.mdx (500 tokens)
      ├── patterns/
         ├── adapter-pattern.mdx (200 tokens)
         ├── adapter-pattern.mdx.skill.md (200 tokens)
         ├── reactive-state-pattern.mdx (300 tokens)
         ├── reactive-state-pattern.mdx.skill.md (300 tokens)
      ├── quickstart.mdx (1500 tokens)
      ├── scripts/
         ├── compare-exports.mts (3.4k tokens)
         ├── generate-api-docs.mts (800 tokens)
         ├── parsers/
            ├── parse-griffe.mts (3k tokens)
            ├── parse-rustdoc.mts (4.1k tokens)
            ├── parse-typedoc.mts (3.1k tokens)
         ├── renderers/
            ├── components.mts (700 tokens)
            ├── render-mdx.mts (1600 tokens)
         ├── types.mts (500 tokens)
      ├── sdk-reference/
         ├── engine-sdk.mdx (2.2k tokens)
         ├── engine-sdk.mdx.skill.md (2.2k tokens)
      ├── troubleshooting.mdx (200 tokens)
      ├── tutorials/
         ├── build-an-agent/
            ├── define-tools.mdx
            ├── define-tools.mdx.skill.md
            ├── memory-and-state.mdx
            ├── memory-and-state.mdx.skill.md
            ├── orchestration-loop.mdx
            ├── orchestration-loop.mdx.skill.md
            ├── overview.mdx (100 tokens)
            ├── overview.mdx.skill.md (100 tokens)
         ├── incremental-adoption/
            ├── migrate-persistence.mdx
            ├── migrate-persistence.mdx.skill.md
            ├── offload-to-queue.mdx
            ├── offload-to-queue.mdx.skill.md
            ├── overview.mdx (400 tokens)
            ├── overview.mdx.skill.md (400 tokens)
            ├── wrap-existing-api.mdx
            ├── wrap-existing-api.mdx.skill.md
         ├── linkly/
            ├── channels.mdx (900 tokens)
            ├── channels.mdx.skill.md (800 tokens)
            ├── console-traces.png
            ├── durable-execution.mdx (2.3k tokens)
            ├── durable-execution.mdx.skill.md (2.3k tokens)
            ├── foundations.mdx (2.6k tokens)
            ├── foundations.mdx.skill.md (2.6k tokens)
            ├── frontend.mdx (2.3k tokens)
            ├── frontend.mdx.skill.md (2.3k tokens)
            ├── observability.mdx (1300 tokens)
            ├── observability.mdx.skill.md (1300 tokens)
            ├── overview.mdx (400 tokens)
            ├── overview.mdx.skill.md (400 tokens)
            ├── persistence.mdx (1700 tokens)
            ├── persistence.mdx.skill.md (1600 tokens)
            ├── streaming.mdx (900 tokens)
            ├── streaming.mdx.skill.md (900 tokens)
         ├── reactive-crud/
            ├── crud-endpoints.mdx
            ├── crud-endpoints.mdx.skill.md
            ├── model-and-store.mdx
            ├── model-and-store.mdx.skill.md
            ├── overview.mdx (100 tokens)
            ├── overview.mdx.skill.md (200 tokens)
            ├── realtime-subscriptions.mdx
            ├── realtime-subscriptions.mdx.skill.md
      ├── understanding-iii/
         ├── channels.mdx (500 tokens)
         ├── channels.mdx.skill.md (500 tokens)
         ├── engine.mdx (600 tokens)
         ├── engine.mdx.skill.md (600 tokens)
         ├── index.mdx (2.9k tokens)
         ├── index.mdx.skill.md (2.9k tokens)
      ├── upgrading/
         ├── from-0-19-x.mdx (2.2k tokens)
         ├── from-0-19-x.mdx.skill.md (2.2k tokens)
      ├── using-iii/
         ├── cli.mdx (500 tokens)
         ├── cli.mdx.skill.md (500 tokens)
         ├── console.mdx (1500 tokens)
         ├── console.mdx.skill.md (1500 tokens)
         ├── deployment.mdx (700 tokens)
         ├── deployment.mdx.skill.md (700 tokens)
         ├── engine.mdx (600 tokens)
         ├── engine.mdx.skill.md (600 tokens)
         ├── functions.mdx (1900 tokens)
         ├── functions.mdx.skill.md (1900 tokens)
         ├── triggers.mdx (1700 tokens)
         ├── triggers.mdx.skill.md (1700 tokens)
         ├── workers-registry.mdx (300 tokens)
         ├── workers-registry.mdx.skill.md (300 tokens)
         ├── workers.mdx (2k tokens)
         ├── workers.mdx.skill.md (1900 tokens)
   ├── LICENSE (2.2k tokens)
   ├── README.md (200 tokens)
   ├── README.md.skill.md (200 tokens)
   ├── RELEASING.md (700 tokens)
   ├── api-reference/
      ├── helpers-node.mdx (7.4k tokens)
      ├── helpers-node.mdx.skill.md (7.4k tokens)
      ├── helpers-python.mdx (5.3k tokens)
      ├── helpers-python.mdx.skill.md (5.3k tokens)
      ├── helpers-rust.mdx (4.9k tokens)
      ├── helpers-rust.mdx.skill.md (4.9k tokens)
      ├── sdk-browser.mdx (7.6k tokens)
      ├── sdk-browser.mdx.skill.md (7.6k tokens)
      ├── sdk-node.mdx (5.6k tokens)
      ├── sdk-node.mdx.skill.md (5.6k tokens)
      ├── sdk-python.mdx (4.4k tokens)
      ├── sdk-python.mdx.skill.md (4.4k tokens)
      ├── sdk-rust.mdx (5.9k tokens)
      ├── sdk-rust.mdx.skill.md (5.9k tokens)
   ├── assets/
      ├── favicon.svg (3.6k tokens)
      ├── iii-black.svg (100 tokens)
      ├── iii-white.svg (200 tokens)
   ├── changelog/
      ├── 0-11-0/
         ├── everything-is-a-worker.mdx (2.1k tokens)
         ├── migrated-examples.mdx (900 tokens)
         ├── migrating-from-motia-js.mdx (3.6k tokens)
         ├── migrating-from-motia-py.mdx (4k tokens)
      ├── 0-16-0/
         ├── align-rust-register-function-with-signature.mdx (1500 tokens)
      ├── 0-20-0/
         ├── cross-language-parity.mdx (600 tokens)
         ├── extract-helpers-lib.mdx (700 tokens)
         ├── observability-into-helpers.mdx (500 tokens)
         ├── organize-sdk-imports.mdx (600 tokens)
         ├── submodule-clean-break.mdx (500 tokens)
      ├── index.mdx (16k tokens)
   ├── cli-reference/
      ├── index.mdx (5.1k tokens)
      ├── index.mdx.skill.md (5.1k tokens)
   ├── creating-workers/
      ├── channels.mdx (2000 tokens)
      ├── channels.mdx.skill.md (2000 tokens)
      ├── functions.mdx (3.1k tokens)
      ├── functions.mdx.skill.md (3.1k tokens)
      ├── http.mdx (900 tokens)
      ├── http.mdx.skill.md (900 tokens)
      ├── index.mdx (500 tokens)
      ├── index.mdx.skill.md (500 tokens)
      ├── observability.mdx (1100 tokens)
      ├── observability.mdx.skill.md (1100 tokens)
      ├── queues.mdx (3k tokens)
      ├── queues.mdx.skill.md (3k tokens)
      ├── sandboxes.mdx (900 tokens)
      ├── sandboxes.mdx.skill.md (900 tokens)
      ├── triggers.mdx (3.7k tokens)
      ├── triggers.mdx.skill.md (3.7k tokens)
      ├── worker-manager.mdx (2.5k tokens)
      ├── worker-manager.mdx.skill.md (2.5k tokens)
      ├── worker-manifest.mdx (1100 tokens)
      ├── worker-manifest.mdx.skill.md (1100 tokens)
      ├── workers-registry.mdx (1200 tokens)
      ├── workers-registry.mdx.skill.md (1200 tokens)
      ├── workers.mdx (3.9k tokens)
      ├── workers.mdx.skill.md (3.9k tokens)
   ├── custom.css (1900 tokens)
   ├── docs.json (7.8k tokens)
   ├── how-to/
      ├── build-a-realtime-todo-app.mdx (300 tokens)
      ├── build-a-realtime-todo-app.mdx.skill.md (300 tokens)
      ├── schedule-cron-task.mdx (100 tokens)
      ├── schedule-cron-task.mdx.skill.md (100 tokens)
      ├── use-trigger-conditions.mdx (100 tokens)
      ├── use-trigger-conditions.mdx.skill.md (100 tokens)
   ├── index.mdx (1000 tokens)
   ├── index.mdx.skill.md (1000 tokens)
   ├── install.mdx (500 tokens)
   ├── install.mdx.skill.md (500 tokens)
   ├── navbar-counters.js (500 tokens)
   ├── next/
      ├── api-reference/
         ├── helpers-node.mdx (7.4k tokens)
         ├── helpers-node.mdx.skill.md (7.4k tokens)
         ├── helpers-python.mdx (5.3k tokens)
         ├── helpers-python.mdx.skill.md (5.3k tokens)
         ├── helpers-rust.mdx (4.9k tokens)
         ├── helpers-rust.mdx.skill.md (4.9k tokens)
         ├── sdk-browser.mdx (7.6k tokens)
         ├── sdk-browser.mdx.skill.md (7.6k tokens)
         ├── sdk-node.mdx (5.6k tokens)
         ├── sdk-node.mdx.skill.md (5.6k tokens)
         ├── sdk-python.mdx (4.4k tokens)
         ├── sdk-python.mdx.skill.md (4.4k tokens)
         ├── sdk-rust.mdx (5.9k tokens)
         ├── sdk-rust.mdx.skill.md (5.9k tokens)
      ├── assets/
         ├── favicon.svg (3.6k tokens)
         ├── iii-black.svg (100 tokens)
         ├── iii-white.svg (200 tokens)
      ├── cli-reference/
         ├── index.mdx (5.1k tokens)
         ├── index.mdx.skill.md (5.1k tokens)
      ├── creating-workers/
         ├── channels.mdx (2000 tokens)
         ├── channels.mdx.skill.md (2000 tokens)
         ├── functions.mdx (3.1k tokens)
         ├── functions.mdx.skill.md (3.1k tokens)
         ├── http.mdx (900 tokens)
         ├── http.mdx.skill.md (900 tokens)
         ├── index.mdx (500 tokens)
         ├── index.mdx.skill.md (500 tokens)
         ├── observability.mdx (1100 tokens)
         ├── observability.mdx.skill.md (1100 tokens)
         ├── queues.mdx (3k tokens)
         ├── queues.mdx.skill.md (3k tokens)
         ├── sandboxes.mdx (900 tokens)
         ├── sandboxes.mdx.skill.md (900 tokens)
         ├── triggers.mdx (3.7k tokens)
         ├── triggers.mdx.skill.md (3.7k tokens)
         ├── worker-manager.mdx (2.5k tokens)
         ├── worker-manager.mdx.skill.md (2.5k tokens)
         ├── worker-manifest.mdx (1100 tokens)
         ├── worker-manifest.mdx.skill.md (1100 tokens)
         ├── workers-registry.mdx (1200 tokens)
         ├── workers-registry.mdx.skill.md (1200 tokens)
         ├── workers.mdx (3.9k tokens)
         ├── workers.mdx.skill.md (3.9k tokens)
      ├── how-to/
         ├── build-a-realtime-todo-app.mdx (300 tokens)
         ├── build-a-realtime-todo-app.mdx.skill.md (300 tokens)
         ├── schedule-cron-task.mdx (100 tokens)
         ├── schedule-cron-task.mdx.skill.md (100 tokens)
         ├── use-trigger-conditions.mdx (100 tokens)
         ├── use-trigger-conditions.mdx.skill.md (100 tokens)
      ├── index.mdx (1000 tokens)
      ├── index.mdx.skill.md (1000 tokens)
      ├── install.mdx (500 tokens)
      ├── install.mdx.skill.md (500 tokens)
      ├── patterns/
         ├── adapter-pattern.mdx (200 tokens)
         ├── adapter-pattern.mdx.skill.md (200 tokens)
         ├── reactive-state-pattern.mdx (300 tokens)
         ├── reactive-state-pattern.mdx.skill.md (300 tokens)
      ├── quickstart.mdx (1500 tokens)
      ├── quickstart.mdx.skill.md (1500 tokens)
      ├── scripts/
         ├── compare-exports.mts (3.4k tokens)
         ├── generate-api-docs.mts (800 tokens)
         ├── parsers/
            ├── parse-griffe.mts (3k tokens)
            ├── parse-rustdoc.mts (4.3k tokens)
            ├── parse-typedoc.mts (3.1k tokens)
         ├── renderers/
            ├── components.mts (700 tokens)
            ├── render-mdx.mts (1600 tokens)
         ├── types.mts (500 tokens)
      ├── sdk-reference/
         ├── engine-sdk.mdx (2.3k tokens)
         ├── engine-sdk.mdx.skill.md (2.3k tokens)
      ├── troubleshooting.mdx (200 tokens)
      ├── troubleshooting.mdx.skill.md (200 tokens)
      ├── tutorials/
         ├── build-an-agent/
            ├── define-tools.mdx
            ├── define-tools.mdx.skill.md
            ├── memory-and-state.mdx
            ├── memory-and-state.mdx.skill.md
            ├── orchestration-loop.mdx
            ├── orchestration-loop.mdx.skill.md
            ├── overview.mdx (100 tokens)
            ├── overview.mdx.skill.md (100 tokens)
         ├── incremental-adoption/
            ├── migrate-persistence.mdx
            ├── migrate-persistence.mdx.skill.md
            ├── offload-to-queue.mdx
            ├── offload-to-queue.mdx.skill.md
            ├── overview.mdx (400 tokens)
            ├── overview.mdx.skill.md (400 tokens)
            ├── wrap-existing-api.mdx
            ├── wrap-existing-api.mdx.skill.md
         ├── linkly/
            ├── channels.mdx (900 tokens)
            ├── channels.mdx.skill.md (800 tokens)
            ├── console-traces.png
            ├── durable-execution.mdx (2.4k tokens)
            ├── durable-execution.mdx.skill.md (2.4k tokens)
            ├── foundations.mdx (2.6k tokens)
            ├── foundations.mdx.skill.md (2.6k tokens)
            ├── frontend.mdx (2.3k tokens)
            ├── frontend.mdx.skill.md (2.3k tokens)
            ├── observability.mdx (1300 tokens)
            ├── observability.mdx.skill.md (1300 tokens)
            ├── overview.mdx (400 tokens)
            ├── overview.mdx.skill.md (400 tokens)
            ├── persistence.mdx (1700 tokens)
            ├── persistence.mdx.skill.md (1700 tokens)
            ├── streaming.mdx (900 tokens)
            ├── streaming.mdx.skill.md (900 tokens)
         ├── reactive-crud/
            ├── crud-endpoints.mdx
            ├── crud-endpoints.mdx.skill.md
            ├── model-and-store.mdx
            ├── model-and-store.mdx.skill.md
            ├── overview.mdx (100 tokens)
            ├── overview.mdx.skill.md (200 tokens)
            ├── realtime-subscriptions.mdx
            ├── realtime-subscriptions.mdx.skill.md
      ├── understanding-iii/
         ├── channels.mdx (500 tokens)
         ├── channels.mdx.skill.md (500 tokens)
         ├── engine.mdx (700 tokens)
         ├── engine.mdx.skill.md (700 tokens)
         ├── index.mdx (2.9k tokens)
         ├── index.mdx.skill.md (2.9k tokens)
      ├── upgrading/
         ├── from-0-19-x.mdx (2.2k tokens)
         ├── from-0-19-x.mdx.skill.md (2.2k tokens)
      ├── using-iii/
         ├── cli.mdx (500 tokens)
         ├── cli.mdx.skill.md (500 tokens)
         ├── configuration.mdx (1400 tokens)
         ├── configuration.mdx.skill.md (1400 tokens)
         ├── console.mdx (1500 tokens)
         ├── console.mdx.skill.md (1500 tokens)
         ├── deployment.mdx (700 tokens)
         ├── deployment.mdx.skill.md (700 tokens)
         ├── engine.mdx (700 tokens)
         ├── engine.mdx.skill.md (700 tokens)
         ├── functions.mdx (2000 tokens)
         ├── functions.mdx.skill.md (2000 tokens)
         ├── triggers.mdx (1800 tokens)
         ├── triggers.mdx.skill.md (1900 tokens)
         ├── workers-registry.mdx (300 tokens)
         ├── workers-registry.mdx.skill.md (300 tokens)
         ├── workers.mdx (2.1k tokens)
         ├── workers.mdx.skill.md (2000 tokens)
   ├── package.json
   ├── patterns/
      ├── adapter-pattern.mdx (200 tokens)
      ├── adapter-pattern.mdx.skill.md (200 tokens)
      ├── reactive-state-pattern.mdx (300 tokens)
      ├── reactive-state-pattern.mdx.skill.md (300 tokens)
   ├── quickstart.mdx (1500 tokens)
   ├── quickstart.mdx.skill.md (1500 tokens)
   ├── scripts/
      ├── compare-exports.mts (3.4k tokens)
      ├── generate-api-docs.mts (800 tokens)
      ├── parsers/
         ├── parse-griffe.mts (3k tokens)
         ├── parse-rustdoc.mts (4.3k tokens)
         ├── parse-typedoc.mts (3.1k tokens)
      ├── renderers/
         ├── components.mts (700 tokens)
         ├── render-mdx.mts (1600 tokens)
      ├── types.mts (500 tokens)
   ├── sdk-reference/
      ├── engine-sdk.mdx (2.3k tokens)
      ├── engine-sdk.mdx.skill.md (2.3k tokens)
   ├── troubleshooting.mdx (200 tokens)
   ├── troubleshooting.mdx.skill.md (200 tokens)
   ├── tutorials/
      ├── build-an-agent/
         ├── define-tools.mdx
         ├── define-tools.mdx.skill.md
         ├── memory-and-state.mdx
         ├── memory-and-state.mdx.skill.md
         ├── orchestration-loop.mdx
         ├── orchestration-loop.mdx.skill.md
         ├── overview.mdx (100 tokens)
         ├── overview.mdx.skill.md (100 tokens)
      ├── incremental-adoption/
         ├── migrate-persistence.mdx
         ├── migrate-persistence.mdx.skill.md
         ├── offload-to-queue.mdx
         ├── offload-to-queue.mdx.skill.md
         ├── overview.mdx (400 tokens)
         ├── overview.mdx.skill.md (400 tokens)
         ├── wrap-existing-api.mdx
         ├── wrap-existing-api.mdx.skill.md
      ├── linkly/
         ├── channels.mdx (900 tokens)
         ├── channels.mdx.skill.md (800 tokens)
         ├── console-traces.png
         ├── durable-execution.mdx (2.4k tokens)
         ├── durable-execution.mdx.skill.md (2.4k tokens)
         ├── foundations.mdx (2.6k tokens)
         ├── foundations.mdx.skill.md (2.6k tokens)
         ├── frontend.mdx (2.3k tokens)
         ├── frontend.mdx.skill.md (2.3k tokens)
         ├── observability.mdx (1300 tokens)
         ├── observability.mdx.skill.md (1300 tokens)
         ├── overview.mdx (400 tokens)
         ├── overview.mdx.skill.md (400 tokens)
         ├── persistence.mdx (1700 tokens)
         ├── persistence.mdx.skill.md (1700 tokens)
         ├── streaming.mdx (900 tokens)
         ├── streaming.mdx.skill.md (900 tokens)
      ├── reactive-crud/
         ├── crud-endpoints.mdx
         ├── crud-endpoints.mdx.skill.md
         ├── model-and-store.mdx
         ├── model-and-store.mdx.skill.md
         ├── overview.mdx (100 tokens)
         ├── overview.mdx.skill.md (200 tokens)
         ├── realtime-subscriptions.mdx
         ├── realtime-subscriptions.mdx.skill.md
   ├── understanding-iii/
      ├── channels.mdx (500 tokens)
      ├── channels.mdx.skill.md (500 tokens)
      ├── engine.mdx (700 tokens)
      ├── engine.mdx.skill.md (700 tokens)
      ├── index.mdx (2.9k tokens)
      ├── index.mdx.skill.md (2.9k tokens)
   ├── upgrading/
      ├── from-0-19-x.mdx (2.2k tokens)
      ├── from-0-19-x.mdx.skill.md (2.2k tokens)
   ├── using-iii/
      ├── cli.mdx (500 tokens)
      ├── cli.mdx.skill.md (500 tokens)
      ├── configuration.mdx (1400 tokens)
      ├── configuration.mdx.skill.md (1400 tokens)
      ├── console.mdx (1500 tokens)
      ├── console.mdx.skill.md (1500 tokens)
      ├── deployment.mdx (700 tokens)
      ├── deployment.mdx.skill.md (700 tokens)
      ├── engine.mdx (700 tokens)
      ├── engine.mdx.skill.md (700 tokens)
      ├── functions.mdx (2000 tokens)
      ├── functions.mdx.skill.md (2000 tokens)
      ├── triggers.mdx (1800 tokens)
      ├── triggers.mdx.skill.md (1900 tokens)
      ├── workers-registry.mdx (300 tokens)
      ├── workers-registry.mdx.skill.md (300 tokens)
      ├── workers.mdx (2.1k tokens)
      ├── workers.mdx.skill.md (2000 tokens)
├── engine/
   ├── .dockerignore
   ├── .gitignore
   ├── .pre-commit-config.yaml (100 tokens)
   ├── CONTRIBUTING.md (1500 tokens)
   ├── Caddyfile
   ├── Cargo.toml (1000 tokens)
   ├── Dockerfile (300 tokens)
   ├── Dockerfile.debug (200 tokens)
   ├── LICENSE (800 tokens)
   ├── Makefile
   ├── NOTICE
   ├── PATENTS (100 tokens)
   ├── README.md (1000 tokens)
   ├── benches/
      ├── common/
         ├── mod.rs (500 tokens)
      ├── concurrent_invocation_bench.rs (500 tokens)
      ├── control_plane_churn_bench.rs (1100 tokens)
      ├── core_runtime_bench.rs (300 tokens)
      ├── http_blackbox/
         ├── mod.rs (1900 tokens)
      ├── http_concurrency_loopback_bench.rs (400 tokens)
      ├── http_many_routes_loopback_bench.rs (200 tokens)
      ├── http_single_route_loopback_bench.rs (200 tokens)
      ├── invoke_function_payload_sizes_bench.rs (300 tokens)
      ├── kv_store_bench.rs (1500 tokens)
      ├── protocol_serde_bench.rs (900 tokens)
      ├── pubsub_fanout_bench.rs (600 tokens)
      ├── queue_enqueue_bench.rs (700 tokens)
      ├── startup_bench.rs (200 tokens)
      ├── state_adapter_bench.rs (800 tokens)
      ├── trigger_fanout_bench.rs (900 tokens)
      ├── worker_cleanup_bench.rs (2.4k tokens)
      ├── worker_invocation_tracking_bench.rs (800 tokens)
      ├── ws_roundtrip_bench.rs (2.4k tokens)
   ├── build.rs
   ├── build.sh (100 tokens)
   ├── config-remote-kv.yaml (100 tokens)
   ├── config.prod.yaml
   ├── config.yaml (1700 tokens)
   ├── docker-compose.prod.yml (100 tokens)
   ├── docker-compose.yml (300 tokens)
   ├── examples/
      ├── custom_queue_adapter.rs (2.4k tokens)
      ├── python/
         ├── echo_invoker.py (400 tokens)
   ├── firmware/
      ├── libkrunfw-darwin-aarch64.dylib
      ├── libkrunfw-linux-aarch64.so
      ├── libkrunfw-linux-x86_64.so
   ├── function-macros/
      ├── Cargo.lock (omitted)
      ├── Cargo.toml
      ├── src/
         ├── lib.rs (3.7k tokens)
   ├── header.txt (100 tokens)
   ├── iii.lock (omitted)
   ├── install.sh (5.9k tokens)
   ├── licenserc.toml
   ├── local-worker-dev.md (1300 tokens)
   ├── packaging/
      ├── aur/
         ├── .SRCINFO.template (100 tokens)
         ├── PKGBUILD.template (200 tokens)
      ├── chocolatey/
         ├── iii.nuspec.template (300 tokens)
         ├── tools/
            ├── chocolateyinstall.ps1.template (100 tokens)
      ├── rpm/
         ├── iii-fedora.spec.template (200 tokens)
         ├── iii-rhel.spec.template (200 tokens)
   ├── src/
      ├── builtins/
         ├── kv.rs (10.6k tokens)
         ├── mod.rs (100 tokens)
         ├── pubsub_lite.rs (1300 tokens)
         ├── queue.rs (21k tokens)
         ├── queue_kv.rs (6.3k tokens)
      ├── cli/
         ├── advisory.rs (1500 tokens)
         ├── download.rs (1600 tokens)
         ├── error.rs (700 tokens)
         ├── exec.rs (700 tokens)
         ├── gen_docs.rs (700 tokens)
         ├── github.rs (1700 tokens)
         ├── mod.rs (1700 tokens)
         ├── platform.rs (1900 tokens)
         ├── project/
            ├── mod.rs (3.6k tokens)
         ├── registry.rs (1600 tokens)
         ├── state.rs (1700 tokens)
         ├── telemetry.rs (2.4k tokens)
         ├── update.rs (4.8k tokens)
      ├── cli_trigger/
         ├── exec.rs (500 tokens)
         ├── help.rs (2.6k tokens)
         ├── mod.rs (1000 tokens)
         ├── payload.rs (1000 tokens)
      ├── condition.rs (900 tokens)
      ├── config/
         ├── mod.rs (1000 tokens)
      ├── engine/
         ├── mod.rs (36.7k tokens)
      ├── function.rs (3k tokens)
      ├── invocation/
         ├── auth.rs (2.4k tokens)
         ├── http_function.rs (700 tokens)
         ├── http_invoker.rs (6.1k tokens)
         ├── method.rs (500 tokens)
         ├── mod.rs (4.2k tokens)
         ├── signature.rs (300 tokens)
         ├── url_validator.rs (3.1k tokens)
      ├── lib.rs (300 tokens)
      ├── logging.rs (12.9k tokens)
      ├── main.rs (6.5k tokens)
      ├── protocol.rs (3.1k tokens)
      ├── services.rs (2.7k tokens)
      ├── telemetry.rs (1000 tokens)
      ├── trigger.rs (7.1k tokens)
      ├── trigger_formats.rs (2.5k tokens)
      ├── update_ops.rs (10.5k tokens)
      ├── worker_connections/
         ├── mod.rs (3.8k tokens)
         ├── traits.rs (2.5k tokens)
      ├── workers/
         ├── bridge_client/
            ├── README.md (600 tokens)
            ├── iii.worker.yaml
            ├── mod.rs (4.1k tokens)
            ├── skills/
               ├── SKILL.md (700 tokens)
         ├── config.rs (17.2k tokens)
         ├── config_rewrite.rs (2.2k tokens)
         ├── configuration/
            ├── README.md (2.1k tokens)
            ├── adapters/
               ├── bridge.rs (2.5k tokens)
               ├── fs.rs (6.4k tokens)
               ├── mod.rs (600 tokens)
            ├── config.rs (400 tokens)
            ├── configuration.rs (8.3k tokens)
            ├── iii.worker.yaml
            ├── mod.rs (100 tokens)
            ├── registry.rs (100 tokens)
            ├── skills/
               ├── SKILL.md (1100 tokens)
            ├── store.rs (4.9k tokens)
            ├── structs.rs (1300 tokens)
            ├── trigger.rs (3.8k tokens)
         ├── cron/
            ├── README.md (1200 tokens)
            ├── adapters/
               ├── kv_adapter.rs (1100 tokens)
               ├── mod.rs (100 tokens)
               ├── redis_adapter.rs (900 tokens)
            ├── config.rs (2.7k tokens)
            ├── configuration.rs (3.1k tokens)
            ├── cron.rs (7.9k tokens)
            ├── iii.worker.yaml
            ├── mod.rs (100 tokens)
            ├── registry.rs (100 tokens)
            ├── skills/
               ├── SKILL.md (800 tokens)
            ├── structs.rs (6.4k tokens)
         ├── engine_fn/
            ├── README.md (1500 tokens)
            ├── iii.worker.yaml
            ├── mod.rs (28.1k tokens)
            ├── skills/
               ├── SKILL.md (3.2k tokens)
         ├── external.rs (7.9k tokens)
         ├── http_functions/
            ├── config.rs (500 tokens)
            ├── mod.rs (3.4k tokens)
         ├── observability/
            ├── README.md (4.5k tokens)
            ├── config.rs (5.5k tokens)
            ├── configuration.rs (3.1k tokens)
            ├── iii.worker.yaml
            ├── logs_layer.rs (3.8k tokens)
            ├── metrics.rs (29k tokens)
            ├── mod.rs (60.4k tokens)
            ├── otel.rs (57.5k tokens)
            ├── otlp_exporter.rs (2.9k tokens)
            ├── sampler.rs (3.5k tokens)
            ├── skills/
               ├── SKILL.md (1200 tokens)
         ├── pubsub/
            ├── README.md (900 tokens)
            ├── adapters/
               ├── local_adapter.rs (1400 tokens)
               ├── memory_adapter.rs (300 tokens)
               ├── mod.rs (100 tokens)
               ├── redis_adapter.rs (1600 tokens)
            ├── config.rs (2.1k tokens)
            ├── configuration.rs (2.9k tokens)
            ├── iii.worker.yaml
            ├── mod.rs (200 tokens)
            ├── pubsub.rs (7.3k tokens)
            ├── registry.rs (100 tokens)
            ├── skills/
               ├── SKILL.md (700 tokens)
         ├── queue/
            ├── README.md (1200 tokens)
            ├── adapters/
               ├── bridge.rs (3.7k tokens)
               ├── builtin/
                  ├── adapter.rs (12.2k tokens)
                  ├── mod.rs (100 tokens)
               ├── memory_adapter.rs (300 tokens)
               ├── mod.rs (100 tokens)
               ├── rabbitmq/
                  ├── adapter.rs (9k tokens)
                  ├── consumer.rs (400 tokens)
                  ├── mod.rs (100 tokens)
                  ├── naming.rs (800 tokens)
                  ├── publisher.rs (1100 tokens)
                  ├── retry.rs (500 tokens)
                  ├── topology.rs (1600 tokens)
                  ├── types.rs (1200 tokens)
                  ├── worker.rs (2000 tokens)
               ├── redis_adapter.rs (3.2k tokens)
            ├── config.rs (6.2k tokens)
            ├── configuration.rs (3.1k tokens)
            ├── message.rs (500 tokens)
            ├── mod.rs (1000 tokens)
            ├── queue.rs (25k tokens)
            ├── registry.rs (100 tokens)
            ├── skills/
               ├── SKILL.md (900 tokens)
            ├── subscriber_config.rs (1200 tokens)
         ├── redis.rs (4.3k tokens)
         ├── registry.rs (1100 tokens)
         ├── registry_worker.rs (9.5k tokens)
         ├── reload.rs (2.9k tokens)
         ├── rest_api/
            ├── README.md (1600 tokens)
            ├── api_core.rs (13.6k tokens)
            ├── config.rs (3k tokens)
            ├── configuration.rs (3k tokens)
            ├── hot_router.rs (1000 tokens)
            ├── iii.worker.yaml (100 tokens)
            ├── mod.rs (100 tokens)
            ├── skills/
               ├── SKILL.md (1200 tokens)
            ├── types.rs (3.2k tokens)
            ├── views.rs (20.2k tokens)
         ├── secure_temp.rs (900 tokens)
         ├── shell/
            ├── README.md (400 tokens)
            ├── config.rs (300 tokens)
            ├── exec.rs (4.4k tokens)
            ├── glob_exec.rs (1000 tokens)
            ├── iii.worker.yaml
            ├── mod.rs (100 tokens)
            ├── skills/
               ├── SKILL.md (600 tokens)
            ├── worker.rs (600 tokens)
         ├── state/
            ├── README.md (1400 tokens)
            ├── adapters/
               ├── bridge.rs (1300 tokens)
               ├── kv_store.rs (1500 tokens)
               ├── mod.rs (300 tokens)
               ├── redis_adapter.rs (3.1k tokens)
            ├── config.rs (3.1k tokens)
            ├── configuration.rs (4.9k tokens)
            ├── iii.worker.yaml (100 tokens)
            ├── mod.rs (100 tokens)
            ├── registry.rs (100 tokens)
            ├── skills/
               ├── SKILL.md (800 tokens)
            ├── state.rs (13.7k tokens)
            ├── structs.rs (1100 tokens)
            ├── trigger.rs (1400 tokens)
         ├── stream/
            ├── README.md (1600 tokens)
            ├── adapters/
               ├── bridge.rs (2.1k tokens)
               ├── kv_store.rs (2.1k tokens)
               ├── mod.rs (500 tokens)
               ├── redis_adapter.rs (3.5k tokens)
            ├── config.rs (3.4k tokens)
            ├── configuration.rs (3k tokens)
            ├── connection.rs (7.1k tokens)
            ├── iii.worker.yaml (100 tokens)
            ├── mod.rs (200 tokens)
            ├── registry.rs (100 tokens)
            ├── skills/
               ├── SKILL.md (1000 tokens)
            ├── socket.rs (4.2k tokens)
            ├── stream.rs (21.1k tokens)
            ├── structs.rs (2.1k tokens)
            ├── trigger.rs (3.4k tokens)
            ├── utils.rs (600 tokens)
         ├── telemetry/
            ├── README.md (100 tokens)
            ├── amplitude.rs (5.1k tokens)
            ├── collector.rs (4.6k tokens)
            ├── environment.rs (5.7k tokens)
            ├── mod.rs (19.6k tokens)
         ├── traits.rs (5.5k tokens)
         ├── worker/
            ├── README.md (2.7k tokens)
            ├── channels.rs (3.3k tokens)
            ├── iii.worker.yaml
            ├── mod.rs (1600 tokens)
            ├── rbac_config.rs (4.2k tokens)
            ├── rbac_session.rs (900 tokens)
            ├── skills/
               ├── SKILL.md (2000 tokens)
            ├── ws_handler.rs (3k tokens)
   ├── tests/
      ├── builtin_functions_e2e.rs (2.4k tokens)
      ├── cli_args.rs (400 tokens)
      ├── cli_integration.rs (2.7k tokens)
      ├── common/
         ├── http_helpers.rs (600 tokens)
         ├── mod.rs
         ├── queue_helpers.rs (2.7k tokens)
         ├── rabbitmq_helpers.rs (1000 tokens)
      ├── config_reload_e2e.rs (3.8k tokens)
      ├── configuration_e2e.rs (2.2k tokens)
      ├── cron_configuration_e2e.rs (3.6k tokens)
      ├── dlq_redrive_e2e.rs (4.5k tokens)
      ├── external_known_sandbox.rs (500 tokens)
      ├── fixtures/
         ├── argv_probe.sh (100 tokens)
         ├── templates/
            ├── bare/
               ├── template.yaml (200 tokens)
            ├── default-gitignore (1500 tokens)
            ├── default-iii-config.yaml (100 tokens)
            ├── docker/
               ├── Dockerfile (100 tokens)
               ├── docker-compose.yml (200 tokens)
               ├── template.yaml (100 tokens)
            ├── template.yaml (400 tokens)
      ├── http_configuration_e2e.rs (4.7k tokens)
      ├── http_e2e_error_handling.rs (1200 tokens)
      ├── http_e2e_security.rs (900 tokens)
      ├── http_middleware_e2e.rs (3.4k tokens)
      ├── install_sh_integration.sh (1000 tokens)
      ├── install_sh_unit.bats (1300 tokens)
      ├── invocation_extensibility.rs (1800 tokens)
      ├── invocation_integration.rs (400 tokens)
      ├── observability_configuration_e2e.rs (6k tokens)
      ├── otel_ws_no_worker_registration_test.rs (1100 tokens)
      ├── project_init_e2e.rs (2.9k tokens)
      ├── pubsub_configuration_e2e.rs (3.5k tokens)
      ├── queue_configuration_e2e.rs (4.2k tokens)
      ├── queue_e2e_concurrency_resilience.rs (2.4k tokens)
      ├── queue_e2e_failure_retry.rs (2.4k tokens)
      ├── queue_e2e_fanout.rs (3.1k tokens)
      ├── queue_e2e_happy_path.rs (1200 tokens)
      ├── queue_integration.rs (3.3k tokens)
      ├── rabbitmq_queue_integration.rs (11.3k tokens)
      ├── rbac_infrastructure_e2e.rs (2.3k tokens)
      ├── reload_diff_unit.rs (1300 tokens)
      ├── reload_manager_unit.rs (1900 tokens)
      ├── reload_scope_unit.rs (1900 tokens)
      ├── serverless_http.rs (200 tokens)
      ├── state_configuration_e2e.rs (2.2k tokens)
      ├── state_stream_update_e2e.rs (4.2k tokens)
      ├── state_stream_update_redis_e2e.rs (1200 tokens)
      ├── stream_configuration_e2e.rs (4.8k tokens)
      ├── vm_platform_e2e.rs (1300 tokens)
      ├── worker_init_dispatch_e2e.rs (300 tokens)
      ├── worker_trigger_e2e.rs (4.3k tokens)
├── infra/
   ├── terraform/
      ├── .gitignore (100 tokens)
      ├── _bootstrap/
         ├── .terraform.lock.hcl (300 tokens)
         ├── README.md (700 tokens)
         ├── main.tf (400 tokens)
         ├── versions.tf
      ├── website/
         ├── .terraform.lock.hcl (300 tokens)
         ├── acm.tf (200 tokens)
         ├── cloudfront.tf (1600 tokens)
         ├── cloudfront_functions/
            ├── redirects.js (1600 tokens)
            ├── redirects.test.js (4.4k tokens)
         ├── iam_github_oidc.tf (1100 tokens)
         ├── main.tf (100 tokens)
         ├── observability.tf (300 tokens)
         ├── outputs.tf (400 tokens)
         ├── route53.tf (500 tokens)
         ├── s3.tf (300 tokens)
         ├── variables.tf (600 tokens)
         ├── versions.tf
├── package.json (300 tokens)
├── pnpm-lock.yaml (omitted)
├── pnpm-workspace.yaml
├── scripts/
   ├── generate-api-docs.sh (300 tokens)
   ├── generate-cli-docs.sh (400 tokens)
   ├── start-iii.sh (200 tokens)
   ├── stop-iii.sh
├── sdk/
   ├── .gitignore
   ├── .pre-commit-config.yaml (300 tokens)
   ├── LICENSE (2.2k tokens)
   ├── README.md (1500 tokens)
   ├── biome.json (200 tokens)
   ├── fixtures/
      ├── config-bridge-backend.yaml (100 tokens)
      ├── config-bridge.yaml (100 tokens)
      ├── config-test.yaml (500 tokens)
   ├── packages/
      ├── go/
         ├── iii-example/
            ├── README.md (200 tokens)
            ├── go.mod (200 tokens)
            ├── go.sum (400 tokens)
            ├── main.go (900 tokens)
         ├── iii/
            ├── LICENSE (2.2k tokens)
            ├── README.md (2.1k tokens)
            ├── channels.go (2.3k tokens)
            ├── channels_test.go (1600 tokens)
            ├── client.go (6.2k tokens)
            ├── client_reply_test.go (800 tokens)
            ├── client_test.go (6.2k tokens)
            ├── constants.go (800 tokens)
            ├── doc.go (500 tokens)
            ├── errors.go (500 tokens)
            ├── errors_test.go (600 tokens)
            ├── example_test.go (700 tokens)
            ├── go.mod (100 tokens)
            ├── go.sum (400 tokens)
            ├── metadata.go (300 tokens)
            ├── metadata_test.go (300 tokens)
            ├── mockengine_test.go (2.6k tokens)
            ├── otel.go (300 tokens)
            ├── protocol.go (3.5k tokens)
            ├── protocol_test.go (1900 tokens)
            ├── schema.go (800 tokens)
            ├── schema_test.go (1400 tokens)
            ├── tests/
               ├── api_triggers_test.go (1100 tokens)
               ├── bridge_test.go (600 tokens)
               ├── common_test.go (700 tokens)
               ├── data_channels_test.go (600 tokens)
               ├── errors_test.go (400 tokens)
               ├── queue_test.go (400 tokens)
               ├── registration_dedup_test.go (300 tokens)
               ├── trigger_registration_error_test.go (500 tokens)
               ├── worker_metadata_test.go (500 tokens)
            ├── triggers.go (500 tokens)
      ├── node/
         ├── .prettierrc
         ├── helpers/
            ├── README.md
            ├── package.json (500 tokens)
            ├── src/
               ├── http/
                  ├── index.ts (1000 tokens)
               ├── observability/
                  ├── http-instrumentation.test.ts (100 tokens)
                  ├── http-instrumentation.ts (700 tokens)
                  ├── index.ts (300 tokens)
                  ├── internal.ts (100 tokens)
                  ├── logger.test.ts (100 tokens)
                  ├── logger.ts (1100 tokens)
                  ├── otel-worker-gauges.ts (900 tokens)
                  ├── telemetry-system/
                     ├── baggage-span-processor.ts (300 tokens)
                     ├── connection.ts (1700 tokens)
                     ├── context.test.ts (100 tokens)
                     ├── context.ts (700 tokens)
                     ├── exporters.ts
                     ├── fetch-instrumentation.ts (1200 tokens)
                     ├── index.ts (2.4k tokens)
                     ├── log-exporter.ts (700 tokens)
                     ├── metrics-exporter.ts (800 tokens)
                     ├── payload.ts (600 tokens)
                     ├── span-exporter.test.ts (500 tokens)
                     ├── span-exporter.ts (800 tokens)
                     ├── span-ops.ts (200 tokens)
                     ├── types.ts (900 tokens)
                     ├── utils.test.ts (400 tokens)
                     ├── utils.ts (300 tokens)
                  ├── types.ts (200 tokens)
                  ├── utils.ts (100 tokens)
                  ├── worker-metrics.ts (1000 tokens)
               ├── queue/
                  ├── index.ts
               ├── stream/
                  ├── index.ts (2.1k tokens)
               ├── worker-connection-manager/
                  ├── index.ts (1000 tokens)
            ├── tsconfig.json (100 tokens)
            ├── tsdown.config.ts (100 tokens)
            ├── typedoc.json (100 tokens)
            ├── vitest.config.ts
         ├── iii-browser/
            ├── .npmignore
            ├── README.md (900 tokens)
            ├── package.json (300 tokens)
            ├── src/
               ├── channels.ts (1500 tokens)
               ├── helpers.ts (300 tokens)
               ├── iii-constants.ts (400 tokens)
               ├── iii-types.ts (2.1k tokens)
               ├── iii.ts (5.3k tokens)
               ├── index.ts (200 tokens)
               ├── state.ts (700 tokens)
               ├── stream.ts (2000 tokens)
               ├── triggers.ts (200 tokens)
               ├── types.ts (2.1k tokens)
               ├── utils.ts (500 tokens)
            ├── tests/
               ├── bridge.test.ts (1500 tokens)
               ├── channels.test.ts (1000 tokens)
               ├── connection.test.ts (500 tokens)
               ├── exports.test.ts (600 tokens)
               ├── helpers.test.ts (300 tokens)
               ├── integration/
                  ├── bridge.test.ts (900 tokens)
                  ├── channels.test.ts (1200 tokens)
                  ├── functions-available-trigger.test.ts (500 tokens)
                  ├── setup.ts
                  ├── trigger-type-lifecycle.test.ts (900 tokens)
                  ├── trigger-types.test.ts (800 tokens)
                  ├── triggers.test.ts (600 tokens)
                  ├── utils.ts (200 tokens)
               ├── mock-websocket.ts (1500 tokens)
               ├── setup.ts
               ├── trigger-types.test.ts (1000 tokens)
               ├── triggers.test.ts (800 tokens)
            ├── tsconfig.json (100 tokens)
            ├── tsdown.config.ts (100 tokens)
            ├── typedoc.json
            ├── vitest.config.ts (100 tokens)
            ├── vitest.integration.config.ts (100 tokens)
         ├── iii-example/
            ├── config.yaml (400 tokens)
            ├── docker-compose.yaml (300 tokens)
            ├── otel-collector-config.yaml (300 tokens)
            ├── package.json (100 tokens)
            ├── src/
               ├── hooks.ts (200 tokens)
               ├── http-example.ts (300 tokens)
               ├── iii-zod-example.ts (100 tokens)
               ├── iii.ts (100 tokens)
               ├── index.ts (800 tokens)
               ├── middleware-example.ts (600 tokens)
               ├── queue-basic.ts (600 tokens)
               ├── queue-bulk-email.ts (300 tokens)
               ├── queue-dlq.ts (400 tokens)
               ├── queue-ecommerce.ts (500 tokens)
               ├── queue-financial.ts (600 tokens)
               ├── state.ts (200 tokens)
               ├── stream.ts (500 tokens)
               ├── trigger-types.ts (1000 tokens)
               ├── types.ts
            ├── stress-dlq.sh (400 tokens)
            ├── test-queues.sh (600 tokens)
         ├── iii/
            ├── .npmignore
            ├── README.md (600 tokens)
            ├── local.yml
            ├── package.json (500 tokens)
            ├── src/
               ├── channel.ts
               ├── channels.ts (1800 tokens)
               ├── engine.ts
               ├── errors.ts (400 tokens)
               ├── helpers.ts (300 tokens)
               ├── iii-constants.ts (400 tokens)
               ├── iii-types.ts (1300 tokens)
               ├── iii.ts (7.6k tokens)
               ├── index.ts (100 tokens)
               ├── internal.ts
               ├── protocol.ts (100 tokens)
               ├── runtime.ts
               ├── state.ts (700 tokens)
               ├── stream.ts (200 tokens)
               ├── trigger.ts
               ├── triggers.ts (200 tokens)
               ├── types.ts (2.3k tokens)
               ├── utils.ts (600 tokens)
            ├── tests/
               ├── api-triggers.test.ts (3.5k tokens)
               ├── baggage-span-processor.test.ts (700 tokens)
               ├── bridge-state.test.ts (800 tokens)
               ├── bridge-stream.test.ts (1000 tokens)
               ├── bridge-utils.ts (200 tokens)
               ├── bridge.test.ts (600 tokens)
               ├── channel-close-delay.test.ts (1500 tokens)
               ├── channel-writer-readiness.test.ts (1700 tokens)
               ├── data-channels.test.ts (1500 tokens)
               ├── errors.test.ts (600 tokens)
               ├── exports.test.ts (400 tokens)
               ├── fetch-instrumentation.test.ts (3.9k tokens)
               ├── healthcheck.test.ts (300 tokens)
               ├── helpers.test.ts (200 tokens)
               ├── http-external-functions.test.ts (2.4k tokens)
               ├── invoke-metadata.test.ts (1500 tokens)
               ├── logger-runtime.test.ts (500 tokens)
               ├── logger.test.ts (500 tokens)
               ├── middleware.test.ts (1100 tokens)
               ├── otel-defaults.test.ts (1700 tokens)
               ├── otel-exception.test.ts (600 tokens)
               ├── otel-worker-gauges.test.ts (700 tokens)
               ├── payload.test.ts (1100 tokens)
               ├── pubsub.test.ts (600 tokens)
               ├── rbac-workers.test.ts (3.4k tokens)
               ├── register-worker-metadata.test.ts (900 tokens)
               ├── service-triggers.test.ts (1900 tokens)
               ├── setup.ts (100 tokens)
               ├── span-ops.test.ts (800 tokens)
               ├── state.test.ts (1700 tokens)
               ├── stream.test.ts (2.9k tokens)
               ├── trigger-action.test.ts (100 tokens)
               ├── trigger-registration-error.test.ts (500 tokens)
               ├── trigger-type-lifecycle.test.ts (900 tokens)
               ├── utils.ts (400 tokens)
               ├── worker-metrics.test.ts (600 tokens)
            ├── tsconfig.json (100 tokens)
            ├── tsdown.config.ts (100 tokens)
            ├── typedoc.json (100 tokens)
            ├── vitest.config.ts (200 tokens)
         ├── observability/
            ├── README.md (100 tokens)
            ├── package.json (200 tokens)
            ├── src/
               ├── index.ts
               ├── internal.ts
            ├── tsconfig.json (100 tokens)
            ├── tsdown.config.ts (100 tokens)
         ├── package.json
      ├── python/
         ├── .gitignore (200 tokens)
         ├── helpers/
            ├── README.md
            ├── pyproject.toml (300 tokens)
            ├── src/
               ├── iii_helpers/
                  ├── __init__.py
                  ├── http/
                     ├── __init__.py (1000 tokens)
                  ├── observability/
                     ├── __init__.py (300 tokens)
                     ├── baggage_span_processor.py (300 tokens)
                     ├── http_instrumentation.py (800 tokens)
                     ├── logger.py (1300 tokens)
                     ├── payload.py (500 tokens)
                     ├── reconnection.py (200 tokens)
                     ├── span_ops.py (200 tokens)
                     ├── telemetry.py (4.2k tokens)
                     ├── telemetry_exporters.py (3.6k tokens)
                     ├── telemetry_types.py (400 tokens)
                  ├── py.typed
                  ├── queue/
                     ├── __init__.py (100 tokens)
                  ├── stream/
                     ├── __init__.py (1900 tokens)
                  ├── worker_connection_manager/
                     ├── __init__.py (1700 tokens)
            ├── tests/
               ├── __init__.py
               ├── test_observability_http_instrumentation.py (200 tokens)
               ├── test_observability_telemetry.py (100 tokens)
            ├── uv.lock (omitted)
         ├── iii-example/
            ├── config.yaml (300 tokens)
            ├── docker-compose.yaml (200 tokens)
            ├── otel-collector-config.yaml (200 tokens)
            ├── pyproject.toml (100 tokens)
            ├── src/
               ├── __init__.py
               ├── hooks.py (400 tokens)
               ├── iii_function_example.py (100 tokens)
               ├── main.py (1400 tokens)
               ├── models.py
               ├── state.py (200 tokens)
               ├── stream.py (700 tokens)
               ├── trigger_types.py (1300 tokens)
            ├── uv.lock (omitted)
         ├── iii/
            ├── README.md (700 tokens)
            ├── pyproject.toml (300 tokens)
            ├── src/
               ├── iii/
                  ├── __init__.py (200 tokens)
                  ├── channel.py
                  ├── channels.py (1600 tokens)
                  ├── engine.py
                  ├── errors.py (500 tokens)
                  ├── format_utils.py (900 tokens)
                  ├── helpers.py (600 tokens)
                  ├── iii.py (11.1k tokens)
                  ├── iii_constants.py (700 tokens)
                  ├── iii_types.py (2.4k tokens)
                  ├── internal.py
                  ├── otel_worker_gauges.py (1000 tokens)
                  ├── protocol.py (100 tokens)
                  ├── runtime.py
                  ├── state.py (500 tokens)
                  ├── stream.py (300 tokens)
                  ├── trigger.py
                  ├── triggers.py (700 tokens)
                  ├── types.py (1300 tokens)
                  ├── utils.py (100 tokens)
                  ├── worker_metrics.py (1100 tokens)
            ├── tests/
               ├── conftest.py (100 tokens)
               ├── test_api_triggers.py (4.2k tokens)
               ├── test_async_api.py (300 tokens)
               ├── test_baggage_span_processor.py (800 tokens)
               ├── test_bridge.py (700 tokens)
               ├── test_channel_close_delay.py (600 tokens)
               ├── test_channel_submodule.py (100 tokens)
               ├── test_context_propagation.py (700 tokens)
               ├── test_data_channels.py (1300 tokens)
               ├── test_engine_constants.py (200 tokens)
               ├── test_errors.py (1300 tokens)
               ├── test_format_utils.py (1900 tokens)
               ├── test_healthcheck.py (500 tokens)
               ├── test_helpers.py (1200 tokens)
               ├── test_hold_process.py (500 tokens)
               ├── test_http_external_functions_integration.py (3.8k tokens)
               ├── test_iii_registration_dedup.py (1100 tokens)
               ├── test_init_api.py (400 tokens)
               ├── test_invocation_exception.py (700 tokens)
               ├── test_invocation_metadata.py (1800 tokens)
               ├── test_logger_function_ids.py (200 tokens)
               ├── test_logger_otel.py (800 tokens)
               ├── test_middleware.py (1400 tokens)
               ├── test_payload.py (1100 tokens)
               ├── test_pubsub.py (600 tokens)
               ├── test_rbac_workers.py (3.6k tokens)
               ├── test_register_function_args.py (2.8k tokens)
               ├── test_runtime_submodule.py (100 tokens)
               ├── test_span_ops.py (700 tokens)
               ├── test_state.py (2000 tokens)
               ├── test_stream_models.py (1000 tokens)
               ├── test_stream_types.py (100 tokens)
               ├── test_streams.py (2.4k tokens)
               ├── test_streams_runtime_annotations.py
               ├── test_sync_api.py (1200 tokens)
               ├── test_telemetry.py (1600 tokens)
               ├── test_telemetry_exporters.py (1600 tokens)
               ├── test_telemetry_types.py (300 tokens)
               ├── test_trace_helpers.py (100 tokens)
               ├── test_trigger_action.py (100 tokens)
               ├── test_trigger_metadata.py (200 tokens)
               ├── test_trigger_registration_error.py (400 tokens)
               ├── test_trigger_submodule.py (200 tokens)
               ├── test_trigger_type_lifecycle.py (1000 tokens)
               ├── test_utils.py (300 tokens)
               ├── test_worker_metadata.py (800 tokens)
               ├── test_worker_metrics.py (1000 tokens)
            ├── uv.lock (omitted)
         ├── observability/
            ├── README.md
            ├── pyproject.toml (200 tokens)
            ├── src/
               ├── iii_observability/
                  ├── __init__.py (100 tokens)
                  ├── py.typed
            ├── uv.lock (omitted)
      ├── rust/
         ├── helpers/
            ├── Cargo.toml (300 tokens)
            ├── README.md
            ├── src/
               ├── http.rs (500 tokens)
               ├── lib.rs
               ├── observability/
                  ├── logger.rs (1500 tokens)
                  ├── mod.rs (200 tokens)
                  ├── telemetry/
                     ├── baggage_span_processor.rs (1300 tokens)
                     ├── connection.rs (2.2k tokens)
                     ├── context.rs (2k tokens)
                     ├── http_instrumentation.rs (1600 tokens)
                     ├── json_serializer.rs (900 tokens)
                     ├── live_span_processor.rs (1900 tokens)
                     ├── log_exporter.rs (1100 tokens)
                     ├── metrics_exporter.rs (2.2k tokens)
                     ├── mod.rs (5.3k tokens)
                     ├── otel_worker_gauges.rs (600 tokens)
                     ├── payload.rs (1500 tokens)
                     ├── span_exporter.rs (1400 tokens)
                     ├── span_ops.rs (400 tokens)
                     ├── types.rs (1200 tokens)
                     ├── worker_metrics.rs (700 tokens)
               ├── queue.rs (100 tokens)
               ├── stream.rs (4.8k tokens)
               ├── worker_connection_manager.rs (1500 tokens)
            ├── tests/
               ├── observability_context_test.rs
               ├── observability_init_test.rs (100 tokens)
               ├── observability_logger_test.rs
               ├── observability_payload_test.rs (100 tokens)
               ├── observability_types_test.rs (100 tokens)
         ├── iii-example/
            ├── Cargo.lock (omitted)
            ├── Cargo.toml (100 tokens)
            ├── src/
               ├── cron_trigger_example.rs (1000 tokens)
               ├── custom_trigger_example.rs (1100 tokens)
               ├── http_example.rs (800 tokens)
               ├── logger_example.rs (200 tokens)
               ├── main.rs (2.1k tokens)
               ├── trigger_type_example.rs (900 tokens)
         ├── iii/
            ├── .gitignore
            ├── Cargo.lock (omitted)
            ├── Cargo.toml (300 tokens)
            ├── README.md (1200 tokens)
            ├── src/
               ├── builtin_triggers.rs (2.3k tokens)
               ├── channels.rs (2.5k tokens)
               ├── engine.rs (500 tokens)
               ├── error.rs (700 tokens)
               ├── helpers.rs (800 tokens)
               ├── iii.rs (20.2k tokens)
               ├── lib.rs (2.5k tokens)
               ├── protocol.rs (2.4k tokens)
               ├── stream_provider.rs (200 tokens)
               ├── structs.rs (200 tokens)
               ├── triggers.rs (400 tokens)
               ├── types.rs (500 tokens)
            ├── tests/
               ├── api_triggers.rs (7.7k tokens)
               ├── bridge.rs (1000 tokens)
               ├── common/
                  ├── mock_engine.rs (1600 tokens)
                  ├── mod.rs (200 tokens)
               ├── data_channels.rs (2.8k tokens)
               ├── error_wire.rs (800 tokens)
               ├── healthcheck.rs (600 tokens)
               ├── helpers_module.rs (100 tokens)
               ├── hold_process.rs (200 tokens)
               ├── http_external_functions.rs (2.8k tokens)
               ├── init_api.rs (200 tokens)
               ├── middleware.rs (1400 tokens)
               ├── payload_capture.rs (1500 tokens)
               ├── pubsub.rs (1000 tokens)
               ├── rbac_workers.rs (6.2k tokens)
               ├── registration_dedup.rs (1700 tokens)
               ├── span_ops_api.rs (1200 tokens)
               ├── state.rs (2.5k tokens)
               ├── stream.rs (2.1k tokens)
               ├── stream_provider_trait.rs (200 tokens)
               ├── trigger_action.rs (200 tokens)
               ├── trigger_type_lifecycle.rs (1600 tokens)
         ├── observability/
            ├── Cargo.toml (100 tokens)
            ├── README.md
            ├── src/
               ├── lib.rs (100 tokens)
   ├── test-assets/
      ├── handbook.pdf
├── skills/
   ├── .gitignore
   ├── LICENSE (2.2k tokens)
   ├── README.md (500 tokens)
   ├── SKILLS.md (300 tokens)
   ├── iii-architecture-patterns/
      ├── SKILL.md (1300 tokens)
   ├── iii-core-primitives/
      ├── SKILL.md (1900 tokens)
   ├── iii-engine-config/
      ├── SKILL.md (1900 tokens)
   ├── iii-error-handling/
      ├── SKILL.md (1000 tokens)
   ├── iii-getting-started/
      ├── SKILL.md (1400 tokens)
   ├── iii-sdk-reference/
      ├── SKILL.md (1100 tokens)
   ├── presentation/
      ├── README.md (600 tokens)
      ├── SKILL.md (3.1k tokens)
      ├── base/
         ├── .gitignore
         ├── COMPONENTS.md (3.1k tokens)
         ├── README.md (1100 tokens)
         ├── _viewer/
            ├── index.html (200 tokens)
            ├── src/
               ├── ViewerApp.tsx (700 tokens)
               ├── main.tsx (100 tokens)
         ├── build.mjs (1600 tokens)
         ├── index.html (200 tokens)
         ├── package.json (200 tokens)
         ├── scripts/
            ├── manifest.mjs (2000 tokens)
         ├── src/
            ├── components/
               ├── Footer.tsx (300 tokens)
               ├── PageShell.tsx (400 tokens)
               ├── PlayerControls.tsx (300 tokens)
               ├── Section.tsx (400 tokens)
               ├── SpecSheet.tsx (500 tokens)
               ├── TopNav.tsx (700 tokens)
               ├── diagrams/
                  ├── CliPlayground.tsx (1100 tokens)
                  ├── DurabilityTimeline.tsx (1300 tokens)
                  ├── EventFanOut.tsx (1300 tokens)
                  ├── FanOut.tsx (1800 tokens)
                  ├── Funnel.tsx (1900 tokens)
                  ├── SequencePlayer.tsx (1500 tokens)
                  ├── SpawnTree.tsx (2k tokens)
                  ├── StepReveal.tsx (1300 tokens)
                  ├── SystemMap.tsx (2.8k tokens)
               ├── schematic/
                  ├── Button.tsx (300 tokens)
                  ├── Caret.tsx (100 tokens)
                  ├── Cell.tsx (100 tokens)
                  ├── CodeBlock.tsx (300 tokens)
                  ├── FnChip.tsx (200 tokens)
                  ├── ModeToggle.tsx (200 tokens)
                  ├── Prompt.tsx (100 tokens)
                  ├── Sheet.tsx (100 tokens)
                  ├── StatusDot.tsx (100 tokens)
                  ├── StatusPanel.tsx (300 tokens)
                  ├── Terminal.tsx (300 tokens)
                  ├── Wordmark.tsx (100 tokens)
                  ├── WorkerCard.tsx (300 tokens)
            ├── content/
               ├── highlight.tsx (1800 tokens)
               ├── markdown.tsx (1900 tokens)
               ├── mermaid.tsx (700 tokens)
            ├── gallery/
               ├── App.tsx (500 tokens)
               ├── Gallery.tsx (600 tokens)
               ├── PresentationCard.tsx (500 tokens)
               ├── SiteFooter.tsx (100 tokens)
               ├── SiteHeader.tsx (200 tokens)
               ├── main.tsx
               ├── site.ts (200 tokens)
            ├── hooks/
               ├── useHashRoute.ts (300 tokens)
               ├── useStepper.ts (400 tokens)
               ├── useTheme.ts (100 tokens)
            ├── index.css (1000 tokens)
            ├── lib/
               ├── deck-types.ts (200 tokens)
               ├── utils.ts
            ├── pages/
               ├── SpecPage.tsx (700 tokens)
            ├── vite-env.d.ts (omitted)
         ├── tsconfig.app.json (100 tokens)
         ├── tsconfig.json
         ├── tsconfig.node.json (100 tokens)
         ├── vite.config.ts (200 tokens)
      ├── reference/
         ├── archetypes.md (2.2k tokens)
         ├── component-standards.md (900 tokens)
         ├── design-system.md (1000 tokens)
         ├── hosting.md (1200 tokens)
         ├── narrative-framework.md (800 tokens)
         ├── quality-bar.md (700 tokens)
      ├── template/
         ├── README.md (100 tokens)
         ├── index.html (200 tokens)
         ├── src/
            ├── App.tsx (400 tokens)
            ├── content/
               ├── deck.ts (200 tokens)
               ├── example.ts (2.2k tokens)
            ├── diagrams/
               ├── .gitkeep
            ├── main.tsx
            ├── pages/
               ├── ExamplePage.tsx (300 tokens)
            ├── sections/
               ├── Hero.tsx (900 tokens)
               ├── PayoffSection.tsx (500 tokens)
               ├── SystemMapSection.tsx (1000 tokens)
            ├── spec-docs.ts (100 tokens)
├── tech-specs/
   ├── 2026-06-08-agentic/
      ├── README.md (5.5k tokens)
      ├── approval-gate.md (8.2k tokens)
      ├── context-manager.md (3k tokens)
      ├── harness.md (12k tokens)
      ├── llm-router.md (8.2k tokens)
      ├── session-manager.md (4.2k tokens)
   ├── 2026-06-22-rbac-proxy-worker/
      ├── README.md (2.3k tokens)
      ├── engine-overrides.md (2.9k tokens)
      ├── protocol-interception.md (3.1k tokens)
      ├── rbac-proxy.md (3.2k tokens)
      ├── rbac.md (5k tokens)
   ├── 2026-06-29-codegen/
      ├── README.md (2.1k tokens)
      ├── configuration.md (2000 tokens)
      ├── discovery-and-types.md (2k tokens)
      ├── emitters.md (2k tokens)
      ├── worker-and-cli.md (1800 tokens)
   ├── README.md (100 tokens)
   ├── engine-register-trigger-metadata.md (4.8k tokens)
├── turbo.json (100 tokens)
├── website/
   ├── .gitignore
   ├── README.md (400 tokens)
   ├── favicon.svg (100 tokens)
   ├── fonts/
      ├── ChivoMono-Italic-VariableFont_wght.ttf
      ├── ChivoMono-VariableFont_wght.ttf
   ├── index.html (85.1k tokens)
   ├── manifesto.html (6.4k tokens)
   ├── og-image.png
   ├── og-image.xcf
   ├── package.json (100 tokens)
   ├── posthog-consent.js (700 tokens)
   ├── presentations/
      ├── .gitignore
      ├── 2026-06-08-agentic/
         ├── index.html (200 tokens)
         ├── src/
            ├── App.tsx (500 tokens)
            ├── content/
               ├── deck.ts (200 tokens)
               ├── durability.ts (900 tokens)
               ├── fanout.ts (100 tokens)
               ├── spawn.ts (700 tokens)
               ├── workers.ts (2.1k tokens)
            ├── diagrams/
               ├── SystemMap.tsx (4k tokens)
            ├── main.tsx
            ├── pages/
               ├── ConsolePage.tsx (1300 tokens)
               ├── LoopsPage.tsx (1400 tokens)
               ├── TelegramPage.tsx (1700 tokens)
               ├── UseCaseShell.tsx (400 tokens)
            ├── sections/
               ├── DurableSection.tsx (700 tokens)
               ├── GovernanceSection.tsx (2.1k tokens)
               ├── Hero.tsx (1000 tokens)
               ├── OnboardingSection.tsx (1400 tokens)
               ├── ReactiveSection.tsx (900 tokens)
               ├── SolvesSection.tsx (900 tokens)
               ├── SpawnSection.tsx (800 tokens)
               ├── SubstrateSection.tsx (1700 tokens)
               ├── SystemMapSection.tsx (1300 tokens)
               ├── TurnSection.tsx (1300 tokens)
               ├── UseCasesSection.tsx (600 tokens)
            ├── spec-docs.ts (100 tokens)
      ├── 2026-06-22-rbac-proxy-worker/
         ├── index.html (200 tokens)
         ├── src/
            ├── App.tsx (500 tokens)
            ├── content/
               ├── access.ts (1000 tokens)
               ├── architecture.ts (1700 tokens)
               ├── coexistence.ts (200 tokens)
               ├── deck.ts (300 tokens)
               ├── flow.ts (1300 tokens)
               ├── hero.ts (200 tokens)
               ├── payoff.ts (300 tokens)
               ├── rbac.ts (800 tokens)
               ├── why.ts (500 tokens)
            ├── main.tsx
            ├── pages/
               ├── EngineOverridesPage.tsx (1100 tokens)
               ├── RbacContractPage.tsx (1500 tokens)
            ├── sections/
               ├── AccessSection.tsx (1200 tokens)
               ├── CoexistenceSection.tsx (800 tokens)
               ├── FailClosedSection.tsx (1000 tokens)
               ├── Hero.tsx (900 tokens)
               ├── LifecycleSection.tsx (500 tokens)
               ├── MapSection.tsx (1000 tokens)
               ├── OverridesSection.tsx (800 tokens)
               ├── PayoffSection.tsx (500 tokens)
               ├── WhySection.tsx (600 tokens)
            ├── spec-docs.ts (100 tokens)
      ├── 2026-06-29-codegen/
         ├── index.html (200 tokens)
         ├── src/
            ├── App.tsx (500 tokens)
            ├── content/
               ├── cli.ts (200 tokens)
               ├── deck.ts (200 tokens)
               ├── harness.ts (400 tokens)
               ├── hero.ts (200 tokens)
               ├── map.ts (1000 tokens)
               ├── payoff.ts (300 tokens)
               ├── select.ts (300 tokens)
               ├── sequence.ts (400 tokens)
               ├── why.ts (200 tokens)
            ├── main.tsx
            ├── pages/
               ├── HarnessConsumerPage.tsx (1000 tokens)
            ├── sections/
               ├── HarnessSection.tsx (400 tokens)
               ├── Hero.tsx (1000 tokens)
               ├── LanguagesSection.tsx (1100 tokens)
               ├── PayoffSection.tsx (500 tokens)
               ├── RunItSection.tsx (200 tokens)
               ├── SelectSection.tsx (600 tokens)
               ├── SourceOfTruthSection.tsx (300 tokens)
               ├── SystemMapSection.tsx (1000 tokens)
               ├── WhySection.tsx (300 tokens)
            ├── spec-docs.ts (100 tokens)
      ├── COMPONENTS.md (3.1k tokens)
      ├── README.md (1100 tokens)
      ├── _viewer/
         ├── index.html (200 tokens)
         ├── src/
            ├── ViewerApp.tsx (700 tokens)
            ├── main.tsx (100 tokens)
      ├── build.mjs (1600 tokens)
      ├── index.html (200 tokens)
      ├── package.json (100 tokens)
      ├── scripts/
         ├── manifest.mjs (2000 tokens)
      ├── src/
         ├── components/
            ├── Footer.tsx (300 tokens)
            ├── PageShell.tsx (400 tokens)
            ├── PlayerControls.tsx (300 tokens)
            ├── Section.tsx (400 tokens)
            ├── SpecSheet.tsx (500 tokens)
            ├── TopNav.tsx (700 tokens)
            ├── diagrams/
               ├── CliPlayground.tsx (1100 tokens)
               ├── DurabilityTimeline.tsx (1300 tokens)
               ├── EventFanOut.tsx (1300 tokens)
               ├── FanOut.tsx (1800 tokens)
               ├── Funnel.tsx (1900 tokens)
               ├── SequencePlayer.tsx (1500 tokens)
               ├── SpawnTree.tsx (2k tokens)
               ├── StepReveal.tsx (1300 tokens)
               ├── SystemMap.tsx (2.8k tokens)
            ├── schematic/
               ├── Button.tsx (300 tokens)
               ├── Caret.tsx (100 tokens)
               ├── Cell.tsx (100 tokens)
               ├── CodeBlock.tsx (300 tokens)
               ├── FnChip.tsx (200 tokens)
               ├── ModeToggle.tsx (200 tokens)
               ├── Prompt.tsx (100 tokens)
               ├── Sheet.tsx (100 tokens)
               ├── StatusDot.tsx (100 tokens)
               ├── StatusPanel.tsx (300 tokens)
               ├── Terminal.tsx (300 tokens)
               ├── Wordmark.tsx (100 tokens)
               ├── WorkerCard.tsx (300 tokens)
         ├── content/
            ├── highlight.tsx (1800 tokens)
            ├── markdown.tsx (1900 tokens)
            ├── mermaid.tsx (700 tokens)
         ├── gallery/
            ├── App.tsx (500 tokens)
            ├── Gallery.tsx (600 tokens)
            ├── PresentationCard.tsx (500 tokens)
            ├── SiteFooter.tsx (100 tokens)
            ├── SiteHeader.tsx (200 tokens)
            ├── main.tsx
            ├── site.ts (200 tokens)
         ├── hooks/
            ├── useHashRoute.ts (300 tokens)
            ├── useStepper.ts (400 tokens)
            ├── useTheme.ts (100 tokens)
         ├── index.css (1000 tokens)
         ├── lib/
            ├── deck-types.ts (200 tokens)
            ├── utils.ts
         ├── pages/
            ├── SpecPage.tsx (700 tokens)
         ├── vite-env.d.ts (omitted)
      ├── tsconfig.app.json (100 tokens)
      ├── tsconfig.json
      ├── tsconfig.node.json (100 tokens)
      ├── vite.config.ts (200 tokens)
   ├── privacy-policy.html (5.9k tokens)
   ├── robots.txt (200 tokens)
   ├── scripts/
      ├── agents-appendix.md (1500 tokens)
      ├── ai-overview.ts (2000 tokens)
      ├── blog-posts.test.ts (500 tokens)
      ├── blog-posts.ts (400 tokens)
      ├── generate-llms-agents.test.ts (500 tokens)
      ├── generate-llms-agents.ts (1500 tokens)
      ├── generate-sitemap.ts (700 tokens)
      ├── routes-kvs.test.ts (400 tokens)
      ├── routes-kvs.ts (600 tokens)
      ├── routes.ts (300 tokens)
      ├── tech-specs.test.ts (500 tokens)
      ├── tech-specs.ts (500 tokens)
   ├── sitemap.xml (600 tokens)
```


## /.cargo/config.toml

```toml path="/.cargo/config.toml" 
# Linker configuration for init binary musl cross-compilation.
# rust-lld is bundled with the Rust toolchain -- no system packages needed.
# D-01 specified musl-tools/aarch64-linux-gnu-gcc, but rust-lld achieves
# the same static musl linking with zero external deps (see RESEARCH.md).

[target.x86_64-unknown-linux-musl]
linker = "rust-lld"

[target.aarch64-unknown-linux-musl]
linker = "rust-lld"

```

## /.config/nextest.toml

```toml path="/.config/nextest.toml" 
[profile.ci]
fail-fast = false

[profile.ci.junit]
path = "junit.xml"

```

## /.cursor/rules/docs.mdc

```mdc path="/.cursor/rules/docs.mdc" 
---
description: Documentation agent using Divio system for docs/ directory
globs: docs/**/*.mdx, docs/**/*.md
alwaysApply: false
---

# Documentation Agent Capabilities

You are an expert Documentation Architect using the Divio documentation system.
Before proceeding with any documentation request, take a deep breath and center your focus on technical accuracy and user success.

## Core Directives

1. **Analyze First**: When a user requests documentation, first categorize the request into one of the four Divio quadrants:
   - **Tutorials**: Learning-oriented (File: `.cursor/skills/doc_tutorial.md`)
   - **How-to Guides**: Problem-oriented (File: `.cursor/skills/doc_howto.md`)
   - **Reference**: Information-oriented (File: `.cursor/skills/doc_reference.md`)
   - **Explanation**: Understanding-oriented (File: `.cursor/skills/doc_explanation.md`)

   Use the two axes to resolve ambiguous categorization:
   - **Axis 1 — Practical vs. Theoretical**: Tutorials and How-to Guides are practical (the user is doing something). Reference and Explanation are theoretical (the user is reading to understand).
   - **Axis 2 — Studying vs. Working**: Tutorials and Explanation are for when the user is learning or studying. How-to Guides and Reference are for when the user is actively working and needs an answer fast.

   When a request is ambiguous, use these axes to reason toward a quadrant before asking the user to confirm. For example: if the user wants to "understand why X works this way," that is theoretical + studying = **Explanation**. If they want to "do X in their specific environment," that is practical + working = **How-to Guide**.

2. **Predict & Suggest**:
   - Inspect the current file structure.
   - Suggest the optimal file path for the new doc.
   - If the request is ambiguous, ask the user to confirm the category.

3. **Load Skill**: Once the category and location are confirmed (or if the intent is obvious), strictly adhere to the guidelines in the corresponding `.cursor/skills/` file AND the global workflow rules in `.cursor/skills/doc_workflow.md`.

4. **Reference**:
   - Always read `.cursor/skills/doc_workflow.md` for rules regarding Tone, Component Usage (Callouts), and Chunked Execution.

```

## /.cursor/skills/doc_explanation.md

---
name: doc_explanation
description: Writing guide for Explanation documentation — understanding-oriented content that provides context, background, and the reasoning behind design decisions. Use when the reader wants to understand why something works the way it does, not how to use it.
---

# Skill: Writing Explanation (Understanding-Oriented)

**Goal**: Clarify and illuminate specific topics.

## content_rules

- **Context Provider**: Discuss the background, the "why," and the bigger picture.
- **Discursive**: Allow for connections between differing concepts.
- **No Code**: Avoid code blocks unless used for high-level architectural illustration.
- **Permanence**: Write content that changes slowly. Focus on design decisions.
- **Justification**: Explain why the software works the way it does.

## structure

Explanation is the most loosely structured quadrant. It is discursive and essay-like — do not impose a rigid sequence. The following is a suggested flow, not a template to fill in:

- **Topic**: Name the concept being discussed and why it warrants explanation.
- **Background**: Provide contextual or historical information that helps the reader place this concept.
- **Details**: Explore the mechanics, philosophy, or trade-offs in depth. Allow for digressions and connections between ideas.
- **Related**: Link outward to specific Reference or How-to docs. Do not inline their content — cross-reference instead.

Adjust as needed: some explanations need no background; others need no "related" section. The measure of a good explanation is whether the reader comes away understanding _why_, not whether it followed a specific structure.


## /.cursor/skills/doc_howto.md

---
name: doc_howto
description: Writing guide for How-to Guide documentation — task-oriented content for users who already know the basics and need to accomplish a specific, well-defined goal. Use when the reader knows what they want to do but not how to do it.
---

# Skill: Writing How-to Guides (Problem-Oriented)

**Goal**: Show the user how to solve a specific problem they already have.

## content_rules

- **Problem Focus**: Start with the specific problem or real-world use case.
- **Assumed Competence**: Assume the user knows the basics. Do not explain "what" things are, only "how" to use them.
- **Flexibility**: Unlike tutorials, acknowledge that the user might be adapting this to their own setup.
- **External Links**: If a concept requires explanation, link to an _Explanation_ document.

## structure

1. **Goal**: "How to [Task Name]"
2. **Context**: A single sentence on when this is useful.
3. **Steps**: A series of steps to achieve the goal. Steps can be less granular than tutorials.
4. **Result**: What the final state looks like.


## /.cursor/skills/doc_reference.md

---
name: doc_reference
description: Writing guide for Reference documentation — information-oriented content that accurately and completely describes the technical machinery of the software. Use when the reader needs to look something up, not learn or accomplish a task.
---

# Skill: Writing Technical Reference (Information-Oriented)

**Goal**: Describe the machinery accurately.

## content_rules

- **Map of Territory**: Function strictly as a map. Describe classes, functions, API endpoints, commands, or configurations.
- **Austerity**: Be dry, accurate, and concise. Avoid examples unless necessary for syntax clarity.
- **Completeness**: Strive for 100% technical accuracy. Ask the user for context if it is missing.
- **One-to-One**: Ensure the structure of the documentation mirrors the structure of the code/software.
- **No Instruction**: Do not tell the user "how" to use the feature. Link to a _How-to_ guide for that.

## structure

- **Lists and Tables**: Prioritize structured data formats over paragraphs.
- **Signature/Type**: Clearly state inputs, outputs, types, and defaults.
- **Description**: Technical description of functionality.


## /.cursor/skills/doc_tutorial.md

---
name: doc_tutorial
description: Writing guide for Tutorial documentation — learning-oriented content that teaches users a skill through hands-on, concrete, step-by-step practice. Use when the goal is for the reader to acquire a new skill by doing, not just reading.
---

# Skill: Writing Tutorials (Learning-Oriented)

**Goal**: Allow the user to acquire a skill by doing.

## content_rules

- **Learning Experience**: Focus entirely on the learning experience of the user.
- **Concrete Steps**: Provide exact, ordered steps.
- **Immediate Results**: Ensure the user sees results immediately after actions.
- **Repetition**: Repeat actions only if necessary for muscle memory; otherwise, reference previous steps.
- **No Alternatives**: Provide exactly one way to do the task. Avoid "or you could do this."
- **Concrete Examples**: Use specific filenames, variable names, and code blocks. Avoid abstract concepts.
- **Resist Abstraction**: The temptation to generalize is strong — resist it. Tutorials proceed strictly from the concrete to the particular. Never introduce edge cases, advanced options, or generalizations mid-tutorial. Those belong in Explanation or Reference docs. Naming the failure mode: if you catch yourself writing "or, more generally..." — stop.
- **Robustness**: Every step must be tested and verifiable before publishing. A tutorial that breaks partway through is worse than no tutorial — it abandons the beginner at the worst moment. Tutorials must be actively maintained as the underlying software changes.

## structure

1. **Introduction**: "In this tutorial, you will learn how to..."
2. **Prerequisites**: Briefly list what is strictly needed.
3. **Steps**: Numbered sequence of actions.
4. **Conclusion**: "You have successfully..."


## /.cursor/skills/doc_workflow.md

---
name: doc_workflow
description: Global workflow and style rules that apply to all documentation types. Always load this file alongside the quadrant-specific skill file. Contains tone guidance, component usage, chunked execution protocol, and structural integrity rules.
---

# Global Documentation Workflow & Style

Apply these rules to ALL documentation tasks.

## 1. Tone and Focus

- **Your Knowledge**: Always make sure you have the relevant context, if you're writing technical documentation but do not have it (ex. code base access, libraries, sdks, diagrams) then always ask the user for it first.
- **Educational Focus**: _(Tutorials, How-to Guides, Reference only)_ Maintain a tone that is strictly factual, goal-oriented, and solution-focused. Explanation docs are exempt — they use a discursive, conceptual tone instead (see `doc_explanation.md`).
- **Technical Purity**: _(Tutorials, How-to Guides, Reference only)_ Describe features and implementation details solely. Focus on "how it works" and "how to use it." Explanation docs focus on "why it works this way" and are not bound by this rule.
- **Positive Framing**: Structure instructions to guide the user toward the correct path.
- **Contextual Awareness**: Assume the user is intelligent but lacks the specific context of this feature, design pattern, or other knowledge.

## 2. Component Usage

- **Cross-Referencing**: When referencing concepts explained elsewhere, utilize `<Callout>` components to link to existing documentation rather than restating the information.
- **Fumadocs Standard**: Use the default Fumadocs syntax for callouts. Adapt to other frameworks only if the project structure explicitly demands it.
  - Example: `<Callout type="info">See [Concept Name](./path) for details.</Callout>`
  - Types: `info`, `warn`, `error`, `tip`.

## 3. Execution Protocol (Chunked)

- **Phase 1: Plan**: Outline the file structure and section headers. Pause for confirmation.
- **Phase 2: Execution**: Write content in cohesive chunks (e.g., one complete section or logical step).
- **Phase 3: Review**: Stop after each cohesive chunk.
  - Ask the user: "Review this section. Shall I proceed to [Next Section]?"
  - If the user makes changes relevant to upcoming changes in the plan then take those changes into account.
  - If the user makes changes to the current change then verify their change and prompt them if clarification is needed.
  - If the user makes changes relevant to past changes then outline and suggest making necessary additional revisions to the user.
- **Phase 4: Commit**: Upon completing a logical set of changes (e.g., a full file or a major edit), suggest a Git commit message.
  - Format: `scope: concise description of change`

## 4. Quadrant Integrity (Anti-Contamination)

Each quadrant must stay pure. Documentation naturally drifts — resist it.

- **If you find yourself explaining *why* something works inside a How-to Guide** → stop. Extract it to an Explanation doc and link to it instead.
- **If you find yourself listing all available options inside a Tutorial** → stop. That content belongs in Reference. Link to it.
- **If you find yourself writing step-by-step instructions inside an Explanation doc** → stop. Link to the relevant How-to Guide.
- **If your Reference entry starts coaching the user on what to do** → remove it. Link to a How-to Guide.

Cross-referencing is correct. Embedding foreign content is contamination. When in doubt, link — don't inline.

## 5. Structural Integrity

- **Cohesion**: Ensure every sentence serves the specific goal of the document type (Tutorial vs. Reference).
- **Location**: Always prefer existing file structure over prompting the user to restructure. Avoid any restructuring that would impact SEO. Place files in directories that match their intent (e.g., `/tutorials`, `/how-to`, `/reference`, `/explanation`). Suggest moving files if they are misplaced.


## /.githooks/pre-commit

```githooks/pre-commit path="/.githooks/pre-commit" 
#!/usr/bin/env bash
# Pre-commit hook: block commits that would fail CI's format check.
# Install with: make install-hooks
set -euo pipefail

staged_rs=$(git diff --cached --name-only --diff-filter=ACM -- '*.rs' || true)

if [ -n "$staged_rs" ]; then
  if ! command -v cargo >/dev/null 2>&1; then
    echo "[pre-commit] cargo not found; skipping rustfmt check" >&2
  else
    if ! cargo fmt --all -- --check >/dev/null 2>&1; then
      echo "[pre-commit] rustfmt would reformat files — CI will fail." >&2
      echo "             Run 'make fix-fmt' (or 'cargo fmt --all'), re-stage, and commit again." >&2
      exit 1
    fi
  fi
fi

```

## /.github/assets/iii-intro-preview.gif

Binary file available at https://raw.githubusercontent.com/MotiaDev/motia/refs/heads/main/.github/assets/iii-intro-preview.gif

## /.github/assets/workers-add.gif

Binary file available at https://raw.githubusercontent.com/MotiaDev/motia/refs/heads/main/.github/assets/workers-add.gif

## /.github/assets/zero-integration.png

Binary file available at https://raw.githubusercontent.com/MotiaDev/motia/refs/heads/main/.github/assets/zero-integration.png

## /.github/pull_request_template.md

## What

<!-- Brief description of the change -->

## Why

<!-- Motivation or context -->

## Notes

<!-- Anything reviewers should know (breaking changes, migration steps, etc.) -->


## /.github/scripts/build_engine_publish_payload.py

```py path="/.github/scripts/build_engine_publish_payload.py" 
#!/usr/bin/env python3
import argparse
import json
import pathlib
import sys
import tomllib
from typing import Any


def normalize_dependencies(raw_deps: Any) -> list[dict[str, Any]]:
    if raw_deps in (None, ""):
        return []
    if isinstance(raw_deps, dict):
        return [{"name": name, "version": version} for name, version in raw_deps.items()]
    if isinstance(raw_deps, list):
        return raw_deps
    raise ValueError(f"`dependencies` must be a map or list, got {type(raw_deps).__name__}")


def derive_registry_function_name(function_id: str, metadata: dict[str, Any] | None) -> str:
    metadata = metadata or {}
    for key in ("registry_name", "name"):
        value = metadata.get(key)
        if isinstance(value, str) and value.strip():
            return value.strip()
    return function_id


def _extract_array(payload: dict[str, Any], key: str) -> list[dict[str, Any]]:
    value = payload.get(key, [])
    if value is None:
        return []
    if not isinstance(value, list):
        raise ValueError(f"`{key}` must be an array")
    return value


def _read_yaml(path: pathlib.Path) -> Any:
    import yaml
    return yaml.safe_load(path.read_text(encoding="utf-8"))


def _schema_or_empty(value: Any) -> dict[str, Any]:
    if value is None:
        return {}
    if isinstance(value, dict):
        return value
    raise ValueError("function schema fields must be objects or null")


def _metadata_or_empty(value: Any) -> dict[str, Any]:
    return value if isinstance(value, dict) else {}


def _string_or_empty(value: Any) -> str:
    return value if isinstance(value, str) else ""


def _normalize_registry_trigger_type(trigger_type: dict[str, Any]) -> dict[str, Any]:
    # Field renames vs the pre-rework engine: `trigger_request_format` is now
    # `configuration_schema`; `call_request_format` is now `request_schema`.
    return {
        "name": _string_or_empty(trigger_type.get("id")),
        "description": _string_or_empty(trigger_type.get("description")),
        "invocation_schema": _schema_or_empty(trigger_type.get("configuration_schema")),
        "return_schema": _schema_or_empty(trigger_type.get("request_schema")),
        "metadata": {},
    }


def normalize_worker_interface(
    *,
    worker_name: str,
    worker_info: dict[str, Any],
    function_details: list[dict[str, Any]],
    trigger_type_details: list[dict[str, Any]],
    baseline_trigger_type_ids: list[str] | None = None,
) -> dict[str, list[dict[str, Any]]]:
    """Normalize the engine's enriched worker surface into the registry shape.

    The shape change vs the pre-rework engine:

    - `engine::workers::list` no longer carries per-worker `functions[]`; the
      detail envelope from `engine::workers::info` is the source of truth.
    - `engine::functions::list` is lean (no schemas / metadata); the caller
      must fetch `engine::functions::info` per function for `request_schema`,
      `response_schema`, `metadata`.
    - `engine::trigger-types::list` was retired in favor of
      `engine::triggers::list` (types) + `engine::triggers::info` (schemas).

    Args:
        worker_name: Sanity check that the info envelope is the right worker.
        worker_info: Response from `engine::workers::info { name }`.
        function_details: List of `engine::functions::info` responses, one
            per function id reported by `worker_info`.
        trigger_type_details: List of `engine::triggers::info` responses,
            one per trigger type reported by `worker_info`.
        baseline_trigger_type_ids: Trigger type ids present in the engine
            BEFORE the target worker was reloaded — used to subtract
            mandatory-worker types (e.g. iii-observability's `log`).
    """
    worker = worker_info.get("worker") or {}
    if not isinstance(worker, dict):
        raise ValueError("worker_info `worker` must be an object")
    actual_name = worker.get("name") or worker.get("id")
    if actual_name != worker_name:
        raise ValueError(
            f"worker_info envelope is for {actual_name!r}, expected {worker_name!r}"
        )

    functions = []
    for details in function_details:
        if not isinstance(details, dict):
            continue
        function_id = details.get("function_id")
        if not isinstance(function_id, str):
            continue
        metadata = details.get("metadata") or {}
        functions.append(
            {
                "name": derive_registry_function_name(function_id, metadata),
                "description": _string_or_empty(details.get("description")),
                "request_schema": _schema_or_empty(details.get("request_schema")),
                "response_schema": _schema_or_empty(details.get("response_schema")),
                "metadata": _metadata_or_empty(metadata),
            }
        )

    baseline_ids = set(baseline_trigger_type_ids or [])

    triggers = []
    for trigger_type in trigger_type_details:
        if not isinstance(trigger_type, dict):
            continue
        tt_id = trigger_type.get("id")
        if not isinstance(tt_id, str) or tt_id.startswith("engine::"):
            continue
        if tt_id in baseline_ids:
            continue
        triggers.append(_normalize_registry_trigger_type(trigger_type))
    return {"functions": functions, "triggers": triggers}


def build_payload(
    *,
    repo_root: pathlib.Path,
    worker: str,
    worker_dir: pathlib.Path,
    expected_version: str,
    registry_tag: str,
    repo_url: str,
    interface: dict[str, Any],
) -> dict[str, Any]:
    engine_manifest = repo_root / "engine" / "Cargo.toml"
    if not engine_manifest.exists():
        raise ValueError(f"{engine_manifest} not found")
    try:
        engine_version = tomllib.loads(engine_manifest.read_text(encoding="utf-8"))["package"]["version"]
    except KeyError as exc:
        raise ValueError(f"{engine_manifest}: missing [package].version ({exc})") from exc
    if expected_version and expected_version != engine_version:
        raise ValueError(
            f"engine worker version mismatch: input is {expected_version}, engine/Cargo.toml is {engine_version}"
        )

    manifest_path = repo_root / worker_dir / "iii.worker.yaml"
    if not manifest_path.exists():
        raise ValueError(f"{manifest_path} not found")
    meta = _read_yaml(manifest_path) or {}
    if meta.get("type") != "engine":
        raise ValueError(
            f"{worker}: iii.worker.yaml type must be 'engine' (got {meta.get('type')!r})"
        )

    readme_path = repo_root / worker_dir / "README.md"
    readme = readme_path.read_text(encoding="utf-8") if readme_path.exists() else ""

    manifest_name = meta.get("name")
    worker_name = (
        manifest_name.strip()
        if isinstance(manifest_name, str) and manifest_name.strip()
        else worker
    )

    return {
        "worker_name": worker_name,
        "version": engine_version,
        "tag": registry_tag or "latest",
        "type": "engine",
        "readme": readme,
        "repo": repo_url,
        "description": meta.get("description", ""),
        "dependencies": normalize_dependencies(meta.get("dependencies")),
        "config": meta.get("config") or {},
        "functions": interface.get("functions") or [],
        "triggers": interface.get("triggers") or [],
    }


def main() -> int:
    parser = argparse.ArgumentParser()
    parser.add_argument("--worker", required=True)
    parser.add_argument("--worker-dir", required=True)
    parser.add_argument("--expected-version", default="")
    parser.add_argument("--registry-tag", default="latest")
    parser.add_argument("--repo-url", required=True)
    parser.add_argument("--interface-json", required=True)
    parser.add_argument("--repo-root", default=".")
    parser.add_argument("--out", default="payload.json")
    args = parser.parse_args()

    interface = json.loads(pathlib.Path(args.interface_json).read_text(encoding="utf-8"))
    payload = build_payload(
        repo_root=pathlib.Path(args.repo_root),
        worker=args.worker,
        worker_dir=pathlib.Path(args.worker_dir),
        expected_version=args.expected_version,
        registry_tag=args.registry_tag,
        repo_url=args.repo_url,
        interface=interface,
    )
    pathlib.Path(args.out).write_text(json.dumps(payload, indent=2) + "\n", encoding="utf-8")
    print(json.dumps({k: v for k, v in payload.items() if k != "readme"}, indent=2))
    return 0


if __name__ == "__main__":
    sys.exit(main())

```

## /.github/scripts/build_skills_payload.py

```py path="/.github/scripts/build_skills_payload.py" 
#!/usr/bin/env python3
"""Build the POST /w/<slug>/skills payload from a worker directory.

Walks the worker's top-of-tree skill doc plus ``<worker>/skills/**/*.md`` and
produces the JSON body expected by the workers-registry endpoint.  Skill paths
map to payload keys as:

    <worker>/skills/SKILL.md      -> "index.md"   (preferred top-of-tree)
    <worker>/skills/index.md      -> "index.md"   (legacy)
    <worker>/skill.md             -> "index.md"   (legacy)
    <worker>/skills/<rel>.md      -> "skills/<rel>.md"

When more than one top-of-tree candidate is present the highest-precedence one
wins (``skills/SKILL.md`` > ``skills/index.md`` > ``skill.md``) and a GitHub
Actions warning is emitted.

If no non-empty markdown is found the script writes ``skip=true`` to
``$GITHUB_OUTPUT`` (so the calling workflow can gate the POST step off) and
exits cleanly; the API rejects payloads that omit both ``skills`` and
``prompts``, and ``skills: {}`` would be a destructive "clear all" call which is
wrong on a fresh publish.
"""
import argparse
import json
import os
import pathlib
import re
import sys


KEY_RE = re.compile(r"^[a-z0-9][a-z0-9._/\-]*\.md{{contextString}}quot;, re.IGNORECASE)


def collect_skills(worker_root: pathlib.Path) -> dict[str, str]:
    """Return a ``{payload-key: markdown-body}`` map for one worker directory.

    The top-of-tree resolution order is ``skills/SKILL.md`` then
    ``skills/index.md`` then ``skill.md``; whichever wins is published under the
    ``index.md`` payload key.  If more than one is present a GitHub Actions
    warning is emitted and the highest-precedence file wins.  Empty bodies are
    skipped silently so blank placeholder files don't end up in the registry.
    """
    skills: dict[str, str] = {}

    leaves_dir = worker_root / "skills"
    skill_md = leaves_dir / "SKILL.md"
    skills_index = leaves_dir / "index.md"
    intro = worker_root / "skill.md"

    # Preferred new convention is skills/SKILL.md; the skills/index.md and
    # skill.md forms are legacy. Whichever wins maps to the "index.md" key.
    top_candidates = [c for c in (skill_md, skills_index, intro) if c.is_file()]
    if top_candidates:
        top = top_candidates[0]
        body = top.read_text(encoding="utf-8")
        if body.strip():
            skills["index.md"] = body
        if len(top_candidates) > 1:
            present = ", ".join(
                c.relative_to(worker_root).as_posix() for c in top_candidates
            )
            print(
                f"::warning::{worker_root.name}: multiple top-of-tree skill "
                f"files present ({present}); using "
                f"{top.relative_to(worker_root).as_posix()} as the top-of-tree."
            )

    if leaves_dir.is_dir():
        for path in sorted(leaves_dir.rglob("*.md")):
            if path in (skill_md, skills_index):
                continue
            rel = path.relative_to(worker_root).as_posix()
            if not KEY_RE.match(rel):
                raise ValueError(
                    f"skill path rejected by server regex: {rel} "
                    "(must match /^[a-z0-9][a-z0-9._/\\-]*\\.md$/i)"
                )
            body = path.read_text(encoding="utf-8")
            if not body.strip():
                continue
            skills[rel] = body

    return skills


def _signal_skip(worker: str) -> None:
    gha_out = os.environ.get("GITHUB_OUTPUT")
    if gha_out:
        with open(gha_out, "a", encoding="utf-8") as f:
            f.write("skip=true\n")
    print(f"::notice::no skills found for {worker}; skipping POST /w/.../skills")


def main() -> int:
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "--worker-dir",
        help="Path to worker source directory relative to repo root "
        "(e.g. engine/src/workers/state).",
    )
    parser.add_argument(
        "--worker",
        help="(deprecated) Same as --worker-dir.",
    )
    parser.add_argument(
        "--version",
        required=True,
        help="Worker version tag or semver to attach this snapshot to (e.g. latest, next, 1.2.3).",
    )
    parser.add_argument("--out", default="skills-payload.json")
    parser.add_argument(
        "--repo-root",
        default=".",
        help="Repo root containing the worker folder (default: cwd).",
    )
    args = parser.parse_args()

    worker_dir = args.worker_dir or args.worker
    if not worker_dir:
        parser.error("one of --worker-dir or --worker is required")

    worker_root = pathlib.Path(args.repo_root) / worker_dir
    if not worker_root.is_dir():
        print(f"::error::worker directory not found: {worker_root}", file=sys.stderr)
        return 1

    try:
        skills = collect_skills(worker_root)
    except ValueError as exc:
        print(f"::error::{exc}", file=sys.stderr)
        return 1

    out_path = pathlib.Path(args.out)
    if not skills:
        out_path.write_text("{}\n", encoding="utf-8")
        _signal_skip(worker_dir)
        return 0

    payload = {"version": args.version, "skills": skills}
    out_path.write_text(json.dumps(payload, indent=2) + "\n", encoding="utf-8")
    print(f"::notice::collected {len(skills)} skill file(s) for {worker_dir}")
    return 0


if __name__ == "__main__":
    sys.exit(main())

```

## /.github/scripts/bump_manifests.py

```py path="/.github/scripts/bump_manifests.py" 
#!/usr/bin/env python3
"""Rewrite every release-bumped manifest in lockstep.

Pure functions live at module top so they can be unit-tested. The CLI at
the bottom drives the rewrites the create-tag workflow used to perform
inline with sed/jq.
"""
from __future__ import annotations

import re


_CARGO_PACKAGE_VERSION_RE = re.compile(r'^version = "[^"]*"', re.MULTILINE)


def bump_cargo_package_version(text: str, new_version: str) -> str:
    """Replace the first top-level ``version = "..."`` line in a Cargo manifest."""
    m = _CARGO_PACKAGE_VERSION_RE.search(text)
    if m is None:
        raise ValueError("no top-level version line in Cargo manifest")
    start, end = m.span()
    return f'{text[:start]}version = "{new_version}"{text[end:]}'


def bump_cargo_workspace_dep_version(text: str, dep_name: str, new_version: str) -> str:
    """Replace the ``version = "..."`` value inside a ``dep_name = { ... }`` line.

    Matches a single workspace-dependency entry whose key is exactly
    ``dep_name`` and rewrites the embedded ``version`` field. Other fields
    on the line (``path``, ``features``, ...) are preserved.
    """
    line_re = re.compile(
        rf'^(?P<lead>{re.escape(dep_name)}\s*=\s*\{{[^}}\n]*?version\s*=\s*")[^"]*(?P<tail>"[^}}\n]*\}})',
        re.MULTILINE,
    )
    m = line_re.search(text)
    if m is None:
        raise ValueError(f"no workspace dependency entry for {dep_name!r}")
    return f'{text[:m.start()]}{m.group("lead")}{new_version}{m.group("tail")}{text[m.end():]}'


_JSON_TOP_VERSION_RE = re.compile(r'^(\s*)"version"(\s*):(\s*)"[^"]*"', re.MULTILINE)


def bump_json_top_level_version(text: str, new_version: str) -> str:
    """Replace the first top-level ``"version": "..."`` line in a JSON file.

    Operates textually to preserve formatting. The npm/iii workflow uses
    ``jq`` today; we replace it with this so the workflow has a single
    invocation point and the behaviour is unit-tested.
    """
    m = _JSON_TOP_VERSION_RE.search(text)
    if m is None:
        raise ValueError("no top-level version key in JSON manifest")
    indent, sp1, sp2 = m.group(1), m.group(2), m.group(3)
    replacement = f'{indent}"version"{sp1}:{sp2}"{new_version}"'
    return f'{text[:m.start()]}{replacement}{text[m.end():]}'


def bump_pep440_dep_pin(text: str, dep_name: str, new_pep440: str) -> str:
    """Replace ``"<dep_name>==<old>"`` with ``"<dep_name>==<new_pep440>"``.

    Replaces a pinned PEP 440 dependency version in a pyproject.toml
    ``dependencies = [...]`` array.
    """
    line_re = re.compile(rf'"{re.escape(dep_name)}==[^"]*"')
    m = line_re.search(text)
    if m is None:
        raise ValueError(f"no pinned dependency entry for {dep_name!r}")
    return f'{text[:m.start()]}"{dep_name}=={new_pep440}"{text[m.end():]}'


_GO_SDK_VERSION_RE = re.compile(r'const sdkVersion = "[^"]*"')


def bump_go_const_version(text: str, new_version: str) -> str:
    """Replace the ``const sdkVersion = "..."`` line in the Go SDK client.

    Go modules are versioned by their git tag, but the const is reported in
    worker metadata, so it must stay in lockstep with the other SDKs. Uses
    the raw semver string (not the PEP 440 form).
    """
    m = _GO_SDK_VERSION_RE.search(text)
    if m is None:
        raise ValueError("no sdkVersion const in Go client")
    return f'{text[:m.start()]}const sdkVersion = "{new_version}"{text[m.end():]}'


from pathlib import Path


_CARGO_PACKAGE_FILES = (
    "engine/Cargo.toml",
    "sdk/packages/rust/iii/Cargo.toml",
    "sdk/packages/rust/observability/Cargo.toml",
    "sdk/packages/rust/helpers/Cargo.toml",
    "console/packages/console-rust/Cargo.toml",
)
_JSON_PACKAGE_FILES = (
    "sdk/packages/node/iii/package.json",
    "sdk/packages/node/iii-browser/package.json",
    "sdk/packages/node/observability/package.json",
    "sdk/packages/node/helpers/package.json",
)


def rewrite_all(root: Path, new_version: str, new_py_version: str) -> None:
    """Rewrite every release manifest under ``root`` in lockstep."""
    # Cargo package versions
    for rel in _CARGO_PACKAGE_FILES:
        path = root / rel
        path.write_text(bump_cargo_package_version(path.read_text(), new_version))

    # Workspace root: bump the workspace.package version and the internal
    # workspace-dep version pins. The pins are plain "X.Y.Z" requirements, so
    # they must move to the prerelease too — otherwise `cargo` can't match the
    # prerelease candidate (e.g. ^0.19.4 won't accept 0.19.4-alpha.1).
    workspace_path = root / "Cargo.toml"
    body = bump_cargo_package_version(workspace_path.read_text(), new_version)
    body = bump_cargo_workspace_dep_version(body, "iii-observability", new_version)
    body = bump_cargo_workspace_dep_version(body, "iii-helpers", new_version)
    workspace_path.write_text(body)

    # JSON package versions
    for rel in _JSON_PACKAGE_FILES:
        path = root / rel
        path.write_text(bump_json_top_level_version(path.read_text(), new_version))

    # Python iii: top-level version + internal pins (== requirements must
    # move to the prerelease alongside the packages they point at).
    # Note: iii-observability is no longer a direct dep of Python iii (replaced
    # by iii-helpers after the observability-into-helpers refactor).
    py_iii = root / "sdk/packages/python/iii/pyproject.toml"
    body = bump_cargo_package_version(py_iii.read_text(), new_py_version)
    body = bump_pep440_dep_pin(body, "iii-helpers", new_py_version)
    py_iii.write_text(body)

    # Python observability: top-level version + iii-helpers dep pin (shim must
    # depend on the same version of iii-helpers being released alongside it).
    py_obs = root / "sdk/packages/python/observability/pyproject.toml"
    body = bump_cargo_package_version(py_obs.read_text(), new_py_version)
    body = bump_pep440_dep_pin(body, "iii-helpers", new_py_version)
    py_obs.write_text(body)

    # Go SDK: keep the reported sdkVersion const in lockstep. The module
    # itself is versioned by its git tag; this only updates the metadata
    # const, using the raw semver (not the PEP 440) version.
    go_client = root / "sdk/packages/go/iii/client.go"
    go_client.write_text(bump_go_const_version(go_client.read_text(), new_version))

    # Python helpers: top-level version only
    py_helpers = root / "sdk/packages/python/helpers/pyproject.toml"
    py_helpers.write_text(bump_cargo_package_version(py_helpers.read_text(), new_py_version))


import argparse
import sys


def main(argv: list[str] | None = None) -> int:
    parser = argparse.ArgumentParser()
    parser.add_argument("--root", required=True, type=Path)
    parser.add_argument("--version", required=True)
    parser.add_argument("--python-version", required=True)
    args = parser.parse_args(argv)

    rewrite_all(root=args.root, new_version=args.version, new_py_version=args.python_version)
    print(f"Bumped manifests to {args.version} (python: {args.python_version})")
    return 0


if __name__ == "__main__":
    sys.exit(main())

```

## /.github/scripts/calculate_release_version.py

```py path="/.github/scripts/calculate_release_version.py" 
#!/usr/bin/env python3
"""Compute the next release version for the create-tag workflow.

Pure functions live at module top so they can be unit-tested. The CLI at
the bottom reads inputs from environment variables / git and emits the
GitHub Actions outputs the workflow needs.
"""
from __future__ import annotations

import argparse
import os
import re
import subprocess
import sys
from dataclasses import dataclass

PRERELEASE_LABELS = ("alpha", "beta", "rc", "next")
BUMP_RANK = {"patch": 1, "minor": 2, "major": 3}

PRERELEASE_RE = re.compile(r"^(\d+\.\d+\.\d+)-([a-z]+)\.(\d+){{contextString}}quot;)
BASE_RE = re.compile(r"^(\d+)\.(\d+)\.(\d+){{contextString}}quot;)


@dataclass(frozen=True)
class Version:
    major: int
    minor: int
    patch: int
    prerelease_label: str | None = None
    prerelease_num: int | None = None

    @property
    def base(self) -> str:
        return f"{self.major}.{self.minor}.{self.patch}"

    def __str__(self) -> str:
        if self.prerelease_label is not None:
            return f"{self.base}-{self.prerelease_label}.{self.prerelease_num}"
        return self.base


def parse_version(s: str) -> Version:
    m = PRERELEASE_RE.match(s)
    if m:
        base, label, num = m.group(1), m.group(2), int(m.group(3))
        bm = BASE_RE.match(base)
        assert bm is not None
        return Version(int(bm.group(1)), int(bm.group(2)), int(bm.group(3)), label, num)
    bm = BASE_RE.match(s)
    if bm:
        return Version(int(bm.group(1)), int(bm.group(2)), int(bm.group(3)))
    raise ValueError(f"unrecognized version string: {s!r}")


def bump_base(base: str, bump_type: str) -> str:
    m = BASE_RE.match(base)
    if not m:
        raise ValueError(f"not a base version: {base!r}")
    major, minor, patch = int(m.group(1)), int(m.group(2)), int(m.group(3))
    if bump_type == "major":
        return f"{major + 1}.0.0"
    if bump_type == "minor":
        return f"{major}.{minor + 1}.0"
    if bump_type == "patch":
        return f"{major}.{minor}.{patch + 1}"
    raise ValueError(f"unknown bump_type: {bump_type!r}")


def detect_current_level(current_base: str, latest_stable: str | None) -> str | None:
    """Classify how `current_base` relates to the last stable release.

    Returns "major" / "minor" / "patch" depending on which component grew,
    or None when we can't tell (no stable yet, or current is older).
    """
    if latest_stable is None:
        return None
    cur = parse_version(current_base)
    stable = parse_version(latest_stable)
    if cur.major > stable.major:
        return "major"
    if cur.major == stable.major and cur.minor > stable.minor:
        return "minor"
    if cur.major == stable.major and cur.minor == stable.minor and cur.patch > stable.patch:
        return "patch"
    return None


def next_prerelease_counter(
    new_base: str,
    prerelease: str,
    existing_tags: list[str],
    tag_prefix: str,
) -> int:
    """Find the next prerelease counter by scanning existing tags."""
    pattern = re.compile(
        rf"^{re.escape(tag_prefix)}/v{re.escape(new_base)}-{re.escape(prerelease)}\.(\d+){{contextString}}quot;
    )
    nums = [int(m.group(1)) for t in existing_tags if (m := pattern.match(t))]
    return max(nums) + 1 if nums else 1


def next_dry_run_counter(base: str, existing_tags: list[str], tag_prefix: str) -> int:
    pattern = re.compile(rf"^{re.escape(tag_prefix)}/v{re.escape(base)}-dry-run\.(\d+){{contextString}}quot;)
    nums = [int(m.group(1)) for t in existing_tags if (m := pattern.match(t))]
    return max(nums) + 1 if nums else 1


def highest_inflight_prerelease_base(
    existing_tags: list[str],
    tag_prefix: str,
    latest_stable: str | None,
) -> str | None:
    """Highest prerelease base, under ``tag_prefix``, strictly above the latest stable.

    Drives the ``bump="none"`` path: it lets a release iterate an in-flight
    prerelease train (e.g. ``0.19.5-next.1`` -> ``0.19.5-next.2``) without
    advancing the base. Any prerelease channel counts toward the base
    detection, so ``next`` and ``rc`` of the same upcoming release share it.

    Returns ``None`` when no prerelease tag sits above ``latest_stable`` — the
    alpha-from-stable case, where every prerelease anchors on the current
    stable — so callers fall back to anchoring on the stable release itself.
    """
    pattern = re.compile(rf"^{re.escape(tag_prefix)}/v(\d+\.\d+\.\d+)-[a-z]+\.\d+{{contextString}}quot;)
    floor = parse_version(latest_stable) if latest_stable else None
    best: Version | None = None
    for t in existing_tags:
        if not (m := pattern.match(t)):
            continue
        base = parse_version(m.group(1))
        key = (base.major, base.minor, base.patch)
        if floor is not None and key <= (floor.major, floor.minor, floor.patch):
            continue
        if best is None or key > (best.major, best.minor, best.patch):
            best = base
    return best.base if best else None


def calculate_version(
    current: str,
    bump_type: str,
    prerelease: str,
    latest_stable: str | None,
    existing_tags: list[str],
    tag_prefix: str,
) -> str:
    """Decide the next version, accounting for the current prerelease train.

    Rules:
      - `none` never advances the base: it iterates the prerelease
        counter on the in-flight train (the highest prerelease base above
        the latest stable), or on the latest stable when no such train
        exists (alpha-from-stable). Requires a prerelease label.
      - Promoting a prerelease to stable (prerelease == "none" and current
        has a prerelease label) keeps the base as-is.
      - `patch` always increments the patch component of the current
        base, starting a fresh prerelease counter. Patch never iterates
        an existing train.
      - `minor` / `major` in the same prerelease channel are
        level-aware: if the current base already represents a bump at
        the same or higher level (relative to the latest stable), keep
        the base and iterate the counter; if the request escalates
        beyond the current level, restart from the latest stable.
      - Otherwise apply the requested bump to the current base.
    """
    cur = parse_version(current)

    if bump_type == "none":
        # Iterate-only mode: never advances the base, only the prerelease
        # counter. Two scenarios resolve to the same operation:
        #   - Continue an in-flight train (create-tag): if a prerelease tag
        #     sits above the latest stable, anchor on its base so repeated
        #     `none` releases iterate 0.19.5-next.1 -> .2 -> .3 instead of
        #     re-bumping the base. To START a train, use patch/minor/major.
        #   - Alpha-from-stable: when no prerelease train exists above the
        #     latest stable, anchor on the stable release (fall back to the
        #     current base when there is no stable yet).
        if prerelease not in PRERELEASE_LABELS:
            raise ValueError(
                f"bump_type 'none' requires a prerelease label, got {prerelease!r}"
            )
        inflight = highest_inflight_prerelease_base(existing_tags, tag_prefix, latest_stable)
        new_base = inflight or latest_stable or cur.base
        counter = next_prerelease_counter(new_base, prerelease, existing_tags, tag_prefix)
        return f"{new_base}-{prerelease}.{counter}"

    if bump_type not in BUMP_RANK:
        raise ValueError(f"unknown bump_type: {bump_type!r}")
    if prerelease != "none" and prerelease not in PRERELEASE_LABELS:
        raise ValueError(f"unknown prerelease: {prerelease!r}")

    if prerelease == "none" and cur.prerelease_label is not None:
        # Promote prerelease to stable.
        return cur.base

    same_channel = (
        prerelease != "none"
        and cur.prerelease_label == prerelease
    )
    if same_channel and bump_type != "patch":
        current_level = detect_current_level(cur.base, latest_stable)
        if current_level is not None and BUMP_RANK[bump_type] <= BUMP_RANK[current_level]:
            new_base = cur.base
        else:
            # No stable to anchor against, or the requested bump
            # escalates past the current train: restart from the
            # latest stable when available, else bump the current base.
            anchor = latest_stable if (latest_stable and current_level is not None) else cur.base
            new_base = bump_base(anchor, bump_type)
    else:
        new_base = bump_base(cur.base, bump_type)

    if prerelease == "none":
        return new_base
    counter = next_prerelease_counter(new_base, prerelease, existing_tags, tag_prefix)
    return f"{new_base}-{prerelease}.{counter}"


def to_pep440(version: str) -> str:
    m = PRERELEASE_RE.match(version)
    if not m:
        return version
    base, label, num = m.group(1), m.group(2), m.group(3)
    mapping = {"rc": f"rc{num}", "alpha": f"a{num}", "beta": f"b{num}", "next": f".dev{num}"}
    suffix = mapping.get(label)
    if suffix is None:
        return version
    return f"{base}{suffix}"


def latest_stable_from_tags(tags: list[str], tag_prefix: str) -> str | None:
    """Pick the highest stable (non-prerelease, non-dry-run) tag."""
    pattern = re.compile(rf"^{re.escape(tag_prefix)}/v(\d+\.\d+\.\d+){{contextString}}quot;)
    stables = []
    for t in tags:
        if (m := pattern.match(t)):
            stables.append(parse_version(m.group(1)))
    if not stables:
        return None
    stables.sort(key=lambda v: (v.major, v.minor, v.patch))
    return stables[-1].base


# ---------- CLI ----------


def _read_cargo_version(path: str) -> str:
    with open(path, encoding="utf-8") as f:
        for line in f:
            if line.startswith("version = "):
                return line.split('"')[1]
    raise RuntimeError(f"no version in {path}")


def _git_tags() -> list[str]:
    out = subprocess.run(
        ["git", "tag", "-l"], capture_output=True, text=True, check=True
    )
    return [t for t in out.stdout.splitlines() if t]


def _emit(name: str, value: str) -> None:
    gho = os.environ.get("GITHUB_OUTPUT")
    if gho:
        with open(gho, "a", encoding="utf-8") as f:
            f.write(f"{name}={value}\n")
    print(f"{name}={value}")


def main(argv: list[str] | None = None) -> int:
    parser = argparse.ArgumentParser()
    parser.add_argument("--target", required=True)
    parser.add_argument("--bump", required=True, choices=list(BUMP_RANK) + ["none"])
    parser.add_argument("--prerelease", required=True)
    parser.add_argument(
        "--counter-tag-prefix",
        default=None,
        help=(
            "Tag prefix used when scanning for the prerelease counter "
            "(default: --target). Lets alpha releases accumulate under a "
            "separate namespace, e.g. iii-alpha, without colliding with the "
            "official iii/v* tags."
        ),
    )
    parser.add_argument("--dry-run", action="store_true")
    parser.add_argument("--current-version-file", required=True)
    args = parser.parse_args(argv)

    current = _read_cargo_version(args.current_version_file)
    tags = _git_tags()
    stable_prefix = args.target
    counter_prefix = args.counter_tag_prefix or args.target
    latest_stable = latest_stable_from_tags(tags, stable_prefix)

    new_ver = calculate_version(
        current=current,
        bump_type=args.bump,
        prerelease=args.prerelease,
        latest_stable=latest_stable,
        existing_tags=tags,
        tag_prefix=counter_prefix,
    )

    if args.dry_run:
        base_ver = new_ver.split("-", 1)[0]
        counter = next_dry_run_counter(base_ver, tags, counter_prefix)
        new_ver = f"{base_ver}-dry-run.{counter}"

    py_ver = to_pep440(new_ver)
    is_prerelease = args.prerelease != "none"
    npm_tag = args.prerelease if is_prerelease else "latest"

    _emit("version", new_ver)
    _emit("python_version", py_ver)
    _emit("tag", f"{counter_prefix}/v{new_ver}")
    _emit("current", current)
    _emit("is_prerelease", "true" if is_prerelease else "false")
    _emit("npm_tag", npm_tag)
    print(f"::notice::{counter_prefix}: {current} -> {new_ver} (python: {py_ver})", file=sys.stderr)
    return 0


if __name__ == "__main__":
    sys.exit(main())

```

## /.github/scripts/collect_engine_worker_interface.py

```py path="/.github/scripts/collect_engine_worker_interface.py" 
#!/usr/bin/env python3
import argparse
import json
import pathlib
import subprocess
import sys
import time

from build_engine_publish_payload import normalize_worker_interface


def count_worker_matches(workers_json: dict[str, object], worker_name: str) -> int:
    workers = workers_json.get("workers", [])
    if not isinstance(workers, list):
        return 0
    return sum(
        1
        for worker in workers
        if isinstance(worker, dict)
        and (worker.get("name") == worker_name or worker.get("id") == worker_name)
    )


def run_iii(function_path: str, payload: dict[str, object]) -> dict[str, object]:
    completed = subprocess.run(
        [
            "iii",
            "trigger",
            function_path,
            "--json",
            json.dumps(payload),
        ],
        check=True,
        text=True,
        capture_output=True,
        timeout=60,
    )
    return json.loads(completed.stdout)


def wait_for_worker(worker_name: str, wait_seconds: int) -> dict[str, object]:
    # `engine::workers::list` is lean post-rework (no per-worker `functions[]`),
    # but we only need it to confirm the worker is reachable. The function
    # surface is fetched via `engine::workers::info` below.
    deadline = time.monotonic() + wait_seconds
    workers_json = run_iii("engine::workers::list", {})
    while count_worker_matches(workers_json, worker_name) != 1 and time.monotonic() < deadline:
        time.sleep(2)
        workers_json = run_iii("engine::workers::list", {})
    return workers_json


def collect_worker_info(worker_name: str) -> dict[str, object]:
    # The detailed info envelope is the source of truth for a worker's surface
    # in the new engine_fn world. The `worker` field mirrors a workers::list
    # row; `functions`, `trigger_types`, and `registered_triggers` arrays are
    # appended.
    return run_iii("engine::workers::info", {"name": worker_name})


# `engine::functions::info` accepts at most 32 ids per `function_ids` batch.
FUNCTIONS_INFO_BATCH_MAX = 32


def collect_function_details(function_ids: list[str]) -> list[dict[str, object]]:
    # `engine::functions::list` is lean post-rework — schemas live behind
    # `engine::functions::info`. Its `function_ids` batch mode fetches up
    # to 32 details per round-trip; a per-item `error` marker ("forbidden"
    # / "not_found") fails the collection, matching the old per-id loop.
    details: list[dict[str, object]] = []
    for start in range(0, len(function_ids), FUNCTIONS_INFO_BATCH_MAX):
        chunk = function_ids[start : start + FUNCTIONS_INFO_BATCH_MAX]
        try:
            response = run_iii("engine::functions::info", {"function_ids": chunk})
        except (subprocess.CalledProcessError, subprocess.TimeoutExpired, json.JSONDecodeError) as exc:
            raise RuntimeError(
                f"could not collect function info for batch {chunk!r}: {exc}"
            ) from exc
        entries = response.get("functions")
        if not isinstance(entries, list):
            raise RuntimeError(
                f"functions::info batch response missing `functions` array: {response!r}"
            )
        for entry in entries:
            if not isinstance(entry, dict):
                raise RuntimeError(
                    f"functions::info batch entry is not an object: {entry!r}"
                )
            if entry.get("error"):
                raise RuntimeError(
                    f"could not collect function info for "
                    f"{entry.get('function_id')!r}: {entry['error']}"
                )
            details.append(entry)
    return details


def collect_trigger_type_details(trigger_type_ids: list[str]) -> list[dict[str, object]]:
    # Same shape concern as functions: `engine::triggers::list` is lean, so
    # we fetch per-type schemas via `engine::triggers::info`. Trigger types
    # are the primary content for infrastructure workers (iii-http, iii-cron,
    # iii-bridge, ...) — failing closed if any lookup errors out is
    # intentional to avoid masking the real surface of the worker.
    details: list[dict[str, object]] = []
    for tt_id in trigger_type_ids:
        try:
            details.append(run_iii("engine::triggers::info", {"id": tt_id}))
        except (subprocess.CalledProcessError, subprocess.TimeoutExpired, json.JSONDecodeError) as exc:
            raise RuntimeError(
                f"could not collect trigger type info for {tt_id!r}: {exc}"
            ) from exc
    return details


def collect_baseline_trigger_type_ids(baseline_path: pathlib.Path) -> list[str]:
    # The baseline snapshot is captured BEFORE the target worker is reloaded
    # into the engine, so it contains the always-on (`mandatory`) trigger
    # types. We use the lean `triggers::list` shape here — only ids are
    # needed for diffing.
    if not baseline_path.exists():
        return []
    raw = json.loads(baseline_path.read_text(encoding="utf-8"))
    triggers = raw.get("triggers") or raw.get("trigger_types") or []
    return [t.get("id") for t in triggers if isinstance(t, dict) and isinstance(t.get("id"), str)]


def main() -> int:
    parser = argparse.ArgumentParser()
    parser.add_argument("--worker", required=True)
    parser.add_argument("--out", default="worker-interface.json")
    parser.add_argument("--wait-seconds", type=int, default=0)
    parser.add_argument("--trigger-types-baseline", default="")
    args = parser.parse_args()

    baseline_ids: list[str] = []
    if args.trigger_types_baseline:
        baseline_ids = collect_baseline_trigger_type_ids(
            pathlib.Path(args.trigger_types_baseline)
        )

    wait_for_worker(args.worker, args.wait_seconds)
    worker_info = collect_worker_info(args.worker)

    functions = worker_info.get("functions") or []
    if not isinstance(functions, list):
        raise ValueError("workers::info `functions` must be an array")
    function_ids = [
        f.get("function_id")
        for f in functions
        if isinstance(f, dict) and isinstance(f.get("function_id"), str)
    ]

    trigger_types = worker_info.get("trigger_types") or []
    if not isinstance(trigger_types, list):
        raise ValueError("workers::info `trigger_types` must be an array")
    trigger_type_ids = [
        t.get("id")
        for t in trigger_types
        if isinstance(t, dict) and isinstance(t.get("id"), str)
    ]

    function_details = collect_function_details(function_ids)
    trigger_type_details = collect_trigger_type_details(trigger_type_ids)

    interface = normalize_worker_interface(
        worker_name=args.worker,
        worker_info=worker_info,
        function_details=function_details,
        trigger_type_details=trigger_type_details,
        baseline_trigger_type_ids=baseline_ids,
    )
    pathlib.Path(args.out).write_text(json.dumps(interface, indent=2) + "\n", encoding="utf-8")
    print(json.dumps(interface, indent=2))
    return 0


if __name__ == "__main__":
    sys.exit(main())

```

## /.github/scripts/discover_engine_worker_skills.py

```py path="/.github/scripts/discover_engine_worker_skills.py" 
#!/usr/bin/env python3
"""Discover workers with publishable skill bundles.

Scans the repo for ``iii.worker.yaml`` manifests that sit next to a non-empty
``skills/`` tree (``skills/SKILL.md`` or the legacy ``skills/index.md`` /
``skill.md``) and emits a GitHub Actions matrix JSON with ``worker_dir`` (path
relative to repo root) and ``slug`` (registry name from the manifest). Workers
whose skills tree has no non-empty markdown are omitted.
"""
from __future__ import annotations

import argparse
import json
import os
import pathlib
import sys

sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent))
from build_skills_payload import collect_skills  # noqa: E402

_SKIP_DIR_NAMES = frozenset(
    {
        ".git",
        "node_modules",
        "target",
        ".turbo",
        "dist",
        "build",
    }
)


def _read_slug(manifest_path: pathlib.Path) -> str:
    try:
        import yaml
    except ImportError as exc:
        raise RuntimeError("pyyaml is required: pip install pyyaml") from exc

    data = yaml.safe_load(manifest_path.read_text(encoding="utf-8")) or {}
    name = data.get("name")
    if not isinstance(name, str) or not name.strip():
        raise ValueError(f"{manifest_path}: missing or empty `name` field")
    return name.strip()


def _iter_worker_manifests(repo_root: pathlib.Path):
    for path in sorted(repo_root.rglob("iii.worker.yaml")):
        if any(part in _SKIP_DIR_NAMES for part in path.relative_to(repo_root).parts):
            continue
        yield path


def discover(repo_root: pathlib.Path) -> list[dict[str, str]]:
    entries: list[dict[str, str]] = []
    seen_dirs: set[str] = set()

    for manifest in _iter_worker_manifests(repo_root):
        worker_dir = manifest.parent
        worker_key = worker_dir.relative_to(repo_root).as_posix()
        if worker_key in seen_dirs:
            continue

        skills_dir = worker_dir / "skills"
        intro = worker_dir / "skill.md"
        if not skills_dir.is_dir() and not intro.is_file():
            continue

        try:
            slug = _read_slug(manifest)
            skills = collect_skills(worker_dir)
        except ValueError as exc:
            print(f"::error::{exc}", file=sys.stderr)
            raise

        if not skills:
            print(
                f"::notice::{worker_key}: "
                "no non-empty skill markdown; skipping"
            )
            continue

        seen_dirs.add(worker_key)
        entries.append(
            {
                "worker_dir": worker_key,
                "slug": slug,
            }
        )

    return sorted(entries, key=lambda entry: entry["worker_dir"])


def main() -> int:
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "--repo-root",
        default=".",
        help="Repository root (default: cwd).",
    )
    parser.add_argument(
        "--out",
        default="-",
        help="Write matrix JSON here, or '-' for stdout (default).",
    )
    args = parser.parse_args()

    repo_root = pathlib.Path(args.repo_root).resolve()
    matrix = {"include": discover(repo_root)}
    text = json.dumps(matrix)

    if args.out == "-":
        print(text)
    else:
        pathlib.Path(args.out).write_text(text + "\n", encoding="utf-8")

    gha_out = os.environ.get("GITHUB_OUTPUT")
    if gha_out:
        with open(gha_out, "a", encoding="utf-8") as f:
            f.write(f"matrix={text}\n")
            f.write(f"has_workers={'true' if matrix['include'] else 'false'}\n")

    print(
        f"::notice::discovered {len(matrix['include'])} worker(s) with publishable skills"
    )
    return 0


if __name__ == "__main__":
    sys.exit(main())

```

## /.github/scripts/license-agreement-check.mjs

```mjs path="/.github/scripts/license-agreement-check.mjs" 
import { readFile } from "node:fs/promises";
import { pathToFileURL } from "node:url";

export const CHECKBOX_TEXT =
  "I license my contributions to this repository under Apache 2.0, and I have all necessary rights over the code I am contributing.";
export const STATUS_CONTEXT = "license-agreement";

// The workflow posts as whatever identity mints its token: github-actions[bot]
// under GITHUB_TOKEN, or <app-slug>[bot] under a GitHub App installation token.
// Match any bot login so the sticky comment is recognized and updated in place
// regardless of which identity is in use.
function isBotLogin(login = "") {
  return login.endsWith("[bot]");
}

export function hasCheckedCheckbox(prBody = "") {
  const escaped = CHECKBOX_TEXT.replace(/[.*+?^${}()|[\]\\]/g, "\\{{contextString}}amp;");
  return new RegExp(`^- \\[x\\] ${escaped}\\s*$`, "im").test(prBody);
}

export function isInContributorsFile(username, content = "") {
  return content
    .split("\n")
    .some((line) => line.trim() === `- @${username}` || line.trim().startsWith(`- @${username} `));
}

export function evaluateAgreement({ prBody = "", inContributorsFile = false } = {}) {
  const checkboxChecked = hasCheckedCheckbox(prBody);
  const acknowledged = inContributorsFile || checkboxChecked;

  return { acknowledged, checkboxChecked, inContributorsFile };
}

export function buildCommitMessage(prAuthor) {
  return `docs: add @${prAuthor} to contributors.md\n\n@${prAuthor} agrees to license contributions to iii under Apache 2.0.`;
}

export function buildPendingComment(prAuthor) {
  return [
    "## License agreement required",
    "",
    `@${prAuthor}, to contribute to this repository please confirm that you license your changes under Apache 2.0 and that you have all necessary rights over the code you are contributing.`,
    "",
    "Your agreement also signifies that you have read and agree to CONTRIBUTING.md located in the root of this repository",
    "",
    "Copy the following into your PR description and check the box:",
    "",
    "\`\`\`markdown",
    `- [ ] ${CHECKBOX_TEXT}`,
    "\`\`\`",
    "",
    "When you check the box, this workflow will automatically add you to contributors.md with the following commit:",
    "",
    "\`\`\`",
    buildCommitMessage(prAuthor),
    "\`\`\`",
    "",
    "Once added, all future PRs from your account will pass this check automatically.",
    "",
    "Alternatively you can add your github username as a new line to the end of `contributors.md` in the repository root.",
  ].join("\n");
}

export function buildSatisfiedComment(prAuthor) {
  return [
    "## License agreement recorded",
    "",
    `@${prAuthor}, your agreement has been recorded and you have been added to contributors.md. All future PRs from your account will pass this check automatically.`,
  ].join("\n");
}

export function findStickyComment(comments = []) {
  return comments.find(
    (comment) =>
      isBotLogin(comment.user?.login ?? "") &&
      (comment.body?.includes("## License agreement required") ||
        comment.body?.includes("## License agreement recorded")),
  );
}

function getRequiredEnv(name) {
  const value = process.env[name];

  if (!value) {
    throw new Error(`${name} is required`);
  }

  return value;
}

function getRepoParts() {
  const repository = getRequiredEnv("GITHUB_REPOSITORY");
  const [owner, repo] = repository.split("/");

  if (!owner || !repo) {
    throw new Error(`Invalid GITHUB_REPOSITORY: ${repository}`);
  }

  return { owner, repo, repository };
}

async function githubRequest(path, options = {}) {
  const token = getRequiredEnv("GITHUB_TOKEN");
  const response = await fetch(`https://api.github.com${path}`, {
    ...options,
    headers: {
      accept: "application/vnd.github+json",
      authorization: `Bearer ${token}`,
      "content-type": "application/json",
      "x-github-api-version": "2022-11-28",
      ...options.headers,
    },
  });

  if (!response.ok) {
    const message = await response.text();
    const error = new Error(`GitHub API request failed: ${response.status} ${path} ${message}`);
    error.status = response.status;
    throw error;
  }

  if (response.status === 204) {
    return null;
  }

  return response.json();
}

async function listIssueComments({ owner, repo, issueNumber }) {
  const comments = [];

  for (let page = 1; ; page += 1) {
    const batch = await githubRequest(
      `/repos/${owner}/${repo}/issues/${issueNumber}/comments?per_page=100&page=${page}`,
    );
    comments.push(...batch);

    if (batch.length < 100) {
      return comments;
    }
  }
}

async function upsertStickyComment({ owner, repo, issueNumber, comments, body }) {
  const stickyComment = findStickyComment(comments);

  if (stickyComment) {
    await githubRequest(`/repos/${owner}/${repo}/issues/comments/${stickyComment.id}`, {
      method: "PATCH",
      body: JSON.stringify({ body }),
    });
    return;
  }

  await githubRequest(`/repos/${owner}/${repo}/issues/${issueNumber}/comments`, {
    method: "POST",
    body: JSON.stringify({ body }),
  });
}

async function createCommitStatus({ owner, repo, sha, state, description }) {
  const serverUrl = process.env.GITHUB_SERVER_URL || "https://github.com";
  const repository = getRequiredEnv("GITHUB_REPOSITORY");
  const runId = getRequiredEnv("GITHUB_RUN_ID");

  await githubRequest(`/repos/${owner}/${repo}/statuses/${sha}`, {
    method: "POST",
    body: JSON.stringify({
      context: STATUS_CONTEXT,
      description,
      state,
      target_url: `${serverUrl}/${repository}/actions/runs/${runId}`,
    }),
  });
}

async function fetchContributorsFile({ owner, repo }) {
  try {
    const result = await githubRequest(`/repos/${owner}/${repo}/contents/contributors.md`);
    const content = Buffer.from(result.content, "base64").toString("utf8");
    return { content, sha: result.sha };
  } catch (error) {
    if (error.status === 404) {
      return { content: "", sha: null };
    }
    throw error;
  }
}

async function addToContributorsFile({ owner, repo, username, content, sha }) {
  if (isInContributorsFile(username, content)) {
    return;
  }

  const newContent = content.trimEnd() + `\n- @${username}\n`;
  const encodedContent = Buffer.from(newContent).toString("base64");

  const body = {
    message: buildCommitMessage(username),
    content: encodedContent,
    committer: {
      name: "github-actions[bot]",
      email: "41898282+github-actions[bot]@users.noreply.github.com",
    },
  };

  if (sha) {
    body.sha = sha;
  }

  try {
    await githubRequest(`/repos/${owner}/${repo}/contents/contributors.md`, {
      method: "PUT",
      body: JSON.stringify(body),
    });
  } catch (error) {
    if (error.status === 409) {
      const { content: freshContent, sha: freshSha } = await fetchContributorsFile({ owner, repo });
      if (!isInContributorsFile(username, freshContent)) {
        const retryContent = freshContent.trimEnd() + `\n- @${username}\n`;
        body.content = Buffer.from(retryContent).toString("base64");
        body.sha = freshSha;
        await githubRequest(`/repos/${owner}/${repo}/contents/contributors.md`, {
          method: "PUT",
          body: JSON.stringify(body),
        });
      }
    } else {
      throw error;
    }
  }
}

// Whether `username` belongs to the `org`. Uses an authenticated call so it sees
// private (concealed) members too, which the event payload's `author_association`
// does not. Requires the token's App to have organization `Members: read`.
// Returns false when the repo owner is a user account rather than an org.
async function isOrgMember({ org, username }) {
  try {
    await githubRequest(`/orgs/${org}/members/${encodeURIComponent(username)}`);
    return true;
  } catch (error) {
    if (error.status === 404 || error.status === 302) {
      return false;
    }
    throw error;
  }
}

async function getPullRequestForEvent({ event, owner, repo }) {
  if (event.pull_request) {
    return {
      issueNumber: event.pull_request.number,
      pullRequest: event.pull_request,
    };
  }

  if (!event.issue?.pull_request) {
    return null;
  }

  return {
    issueNumber: event.issue.number,
    pullRequest: await githubRequest(`/repos/${owner}/${repo}/pulls/${event.issue.number}`),
  };
}

export async function run() {
  const event = JSON.parse(await readFile(getRequiredEnv("GITHUB_EVENT_PATH"), "utf8"));
  const { owner, repo } = getRepoParts();
  const prContext = await getPullRequestForEvent({ event, owner, repo });

  if (!prContext) {
    console.log("No pull request found for this event; skipping license agreement check.");
    return;
  }

  const { issueNumber, pullRequest } = prContext;
  const prAuthor = pullRequest.user.login;
  const headSha = pullRequest.head.sha;
  const prBody = pullRequest.body || "";

  if (await isOrgMember({ org: owner, username: prAuthor })) {
    await createCommitStatus({
      owner,
      repo,
      sha: headSha,
      state: "success",
      description: "Org member; license agreement not required.",
    });
    console.log(`${prAuthor} is a member of ${owner}; license agreement skipped.`);
    return;
  }

  const { content: contributorsContent, sha: contributorsSha } = await fetchContributorsFile({
    owner,
    repo,
  });
  const inContributorsFile = isInContributorsFile(prAuthor, contributorsContent);

  if (inContributorsFile) {
    await createCommitStatus({
      owner,
      repo,
      sha: headSha,
      state: "success",
      description: "Contributor agreement on file.",
    });
    console.log(`${prAuthor} is already in contributors.md; license agreement satisfied.`);
    return;
  }

  if (hasCheckedCheckbox(prBody)) {
    await addToContributorsFile({
      owner,
      repo,
      username: prAuthor,
      content: contributorsContent,
      sha: contributorsSha,
    });

    const comments = await listIssueComments({ owner, repo, issueNumber });
    await upsertStickyComment({
      owner,
      repo,
      issueNumber,
      comments,
      body: buildSatisfiedComment(prAuthor),
    });
    await createCommitStatus({
      owner,
      repo,
      sha: headSha,
      state: "success",
      description: "License agreement recorded.",
    });
    console.log(`License agreement recorded for ${prAuthor}; added to contributors.md.`);
    return;
  }

  const comments = await listIssueComments({ owner, repo, issueNumber });
  await upsertStickyComment({
    owner,
    repo,
    issueNumber,
    comments,
    body: buildPendingComment(prAuthor),
  });
  await createCommitStatus({
    owner,
    repo,
    sha: headSha,
    state: "failure",
    description: "License agreement acknowledgement required.",
  });
  console.error(
    `::error::License agreement required. ${prAuthor} must check the agreement box in the PR description.`,
  );
  process.exitCode = 1;
}

if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
  run().catch((error) => {
    console.error(error);
    process.exitCode = 1;
  });
}

```

## /.github/scripts/license-agreement-check.test.mjs

```mjs path="/.github/scripts/license-agreement-check.test.mjs" 
import assert from 'node:assert/strict';
import test from 'node:test';

import {
  CHECKBOX_TEXT,
  buildCommitMessage,
  buildPendingComment,
  buildSatisfiedComment,
  evaluateAgreement,
  findStickyComment,
  hasCheckedCheckbox,
  isInContributorsFile,
} from './license-agreement-check.mjs';

// ── hasCheckedCheckbox ────────────────────────────────────────────────────────

test('detects a checked checkbox in the PR body', () => {
  assert.equal(hasCheckedCheckbox(`- [x] ${CHECKBOX_TEXT}`), true);
});

test('detects a checked checkbox regardless of case', () => {
  assert.equal(hasCheckedCheckbox(`- [X] ${CHECKBOX_TEXT}`), true);
});

test('does not treat an unchecked checkbox as checked', () => {
  assert.equal(hasCheckedCheckbox(`- [ ] ${CHECKBOX_TEXT}`), false);
});

test('returns false when the PR body is empty', () => {
  assert.equal(hasCheckedCheckbox(''), false);
});

// ── isInContributorsFile ──────────────────────────────────────────────────────

test('finds a username that appears as a list entry', () => {
  const content = '# Contributors\n\n- @alice\n- @bob\n';
  assert.equal(isInContributorsFile('alice', content), true);
  assert.equal(isInContributorsFile('bob', content), true);
});

test('does not match a partial username', () => {
  const content = '# Contributors\n\n- @alice-bot\n';
  assert.equal(isInContributorsFile('alice', content), false);
});

test('returns false when the file is empty', () => {
  assert.equal(isInContributorsFile('alice', ''), false);
});

test('returns false when the username is not present', () => {
  assert.equal(isInContributorsFile('carol', '# Contributors\n\n- @alice\n'), false);
});

// ── evaluateAgreement ─────────────────────────────────────────────────────────

test('passes contributors already in contributors.md', () => {
  const result = evaluateAgreement({ prBody: '', inContributorsFile: true });

  assert.deepEqual(result, {
    acknowledged: true,
    checkboxChecked: false,
    inContributorsFile: true,
  });
});

test('passes contributors who have checked the checkbox', () => {
  const result = evaluateAgreement({ prBody: `- [x] ${CHECKBOX_TEXT}`, inContributorsFile: false });

  assert.deepEqual(result, {
    acknowledged: true,
    checkboxChecked: true,
    inContributorsFile: false,
  });
});

test('fails contributors without acknowledgement', () => {
  const result = evaluateAgreement({ prBody: '', inContributorsFile: false });

  assert.deepEqual(result, {
    acknowledged: false,
    checkboxChecked: false,
    inContributorsFile: false,
  });
});

// ── findStickyComment ─────────────────────────────────────────────────────────

test('finds the pending comment when authored by the workflow bot', () => {
  const comments = [
    { body: '## License agreement required', user: { login: 'external-user' } },
    { body: '## License agreement required', user: { login: 'github-actions[bot]' }, id: 123 },
  ];

  assert.deepEqual(findStickyComment(comments), comments[1]);
});

test('recognizes the sticky comment under a GitHub App bot login', () => {
  const comments = [
    { body: '## License agreement required', user: { login: 'iii-cla[bot]' }, id: 789 },
  ];

  assert.deepEqual(findStickyComment(comments), comments[0]);
});

test('finds the satisfied comment when authored by the workflow bot', () => {
  const comments = [
    { body: '## License agreement recorded', user: { login: 'github-actions[bot]' }, id: 456 },
  ];

  assert.deepEqual(findStickyComment(comments), comments[0]);
});

test('returns undefined when no bot comment exists', () => {
  const comments = [
    { body: '## License agreement required', user: { login: 'external-user' } },
  ];

  assert.equal(findStickyComment(comments), undefined);
});

// ── buildCommitMessage ────────────────────────────────────────────────────────

test('buildCommitMessage includes the username', () => {
  const msg = buildCommitMessage('alice');
  assert.ok(msg.includes('@alice'));
  assert.ok(msg.startsWith('docs:'));
});

// ── buildPendingComment ───────────────────────────────────────────────────────

test('buildPendingComment includes the checkbox text as a copyable code sample', () => {
  const comment = buildPendingComment('alice');
  assert.ok(comment.includes('@alice'));
  assert.ok(comment.includes('docs: add @alice to contributors.md'));
  assert.ok(comment.includes('\`\`\`markdown'));
  assert.ok(comment.includes(`- [ ] ${CHECKBOX_TEXT}`));
});

// ── buildSatisfiedComment ─────────────────────────────────────────────────────

test('buildSatisfiedComment includes the username and contributors.md reference', () => {
  const comment = buildSatisfiedComment('alice');
  assert.ok(comment.includes('@alice'));
  assert.ok(comment.includes('contributors.md'));
});

```

## /.github/scripts/pin_docs.py

```py path="/.github/scripts/pin_docs.py" 
#!/usr/bin/env python3
"""Rotate Mintlify docs versions during the create-tag release flow.

On a stable minor/major release: archive the old Latest (root) into a
MAJOR-MINOR-0/ folder, promote the fixed docs/next/ folder into the root as
the new Latest (labeled with the tag version), and relabel the Next block to
the following minor.

Two subcommands:
* ``validate`` — gate a stable release on the Next docs being ready (a Next
  block exists and docs/next/ is non-empty). Runs even on dry runs.
* ``rotate`` — update docs from docs/next/. Dispatches on the version: a
  minor/major does a full rotation (archive + promote + bump Next); a patch
  refreshes the current Latest in place (no archive, no Next bump).

Pure functions live at module top so they can be unit-tested. The CLI at the
bottom is invoked from .github/workflows/create-tag.yml.
"""
from __future__ import annotations

import argparse
import copy
import json
import re
import shutil
import sys
from pathlib import Path

NEXT_TAG = "Next"
LATEST_TAG = "Latest"
NEXT_DIR = "next"  # fixed folder name holding the Next docs

_VERSION_RE = re.compile(r"^(\d+)\.(\d+)\.(\d+)")


def parse_version(version: str) -> tuple[int, int, int]:
    """Return (major, minor, patch); any prerelease/dry-run suffix is ignored."""
    m = _VERSION_RE.match(version)
    if not m:
        raise ValueError(f"unrecognized version string: {version!r}")
    return int(m.group(1)), int(m.group(2)), int(m.group(3))


def minor_label(major: int, minor: int) -> str:
    return f"{major}.{minor}.x"


def dir_prefix(major: int, minor: int) -> str:
    return f"{major}-{minor}-0"


def next_minor(version: str) -> tuple[int, int]:
    """Return (major, minor+1) for the version — the new Next after a release."""
    major, minor, _ = parse_version(version)
    return major, minor + 1


def _map_page_strings(node, fn, in_pages=False):
    if isinstance(node, str):
        return fn(node) if in_pages else node
    if isinstance(node, list):
        return [_map_page_strings(item, fn, in_pages) for item in node]
    if isinstance(node, dict):
        return {k: _map_page_strings(v, fn, k == "pages") for k, v in node.items()}
    return node


def _is_shared_page(path: str) -> bool:
    return path.split("/", 1)[0] in SHARED_ROOTS


def add_prefix(tabs: list, prefix: str) -> list:
    """Deep-copy ``tabs`` and prefix every page string with ``prefix/``, except
    shared-root pages (e.g. changelog), which always stay at the root."""
    return _map_page_strings(
        copy.deepcopy(tabs),
        lambda s: s if _is_shared_page(s) else f"{prefix}/{s}",
    )


def strip_prefix(tabs: list, prefix: str) -> list:
    """Deep-copy ``tabs`` and remove a leading ``prefix/`` from page strings."""
    head = f"{prefix}/"
    return _map_page_strings(
        copy.deepcopy(tabs),
        lambda s: s[len(head):] if s.startswith(head) else s,
    )


def find_index_by_tag(versions: list[dict], tag: str) -> int:
    for i, block in enumerate(versions):
        if block.get("tag") == tag:
            return i
    raise ValueError(f"no version block tagged {tag!r} in docs.json")


_MINOR_RE = re.compile(r"^(\d+)\.(\d+)")


def _version_sort_key(block: dict) -> tuple[int, int]:
    m = _MINOR_RE.match(block.get("version", ""))
    return (int(m.group(1)), int(m.group(2))) if m else (-1, -1)


def sort_versions(versions: list[dict]) -> list[dict]:
    """Order: Next first, then Latest, then archived newest-first (Mintlify
    renders the dropdown in array order)."""
    nxt = [b for b in versions if b.get("tag") == NEXT_TAG]
    latest = [b for b in versions if b.get("tag") == LATEST_TAG]
    rest = [b for b in versions if b.get("tag") not in (NEXT_TAG, LATEST_TAG)]
    rest.sort(key=_version_sort_key, reverse=True)
    return nxt + latest + rest


_VERSION_DIR_RE = re.compile(r"^\d+-\d+-\d+{{contextString}}quot;)

# Content shared across all versions: kept at the docs root, never copied into a
# version folder and never version-prefixed in docs.json (every version's tab
# points at the single root copy).
SHARED_ROOTS = {"changelog"}

_EXCLUDED_NAMES = {
    "docs.json", "package.json", "package-lock.json", "node_modules",
    "custom.css", "navbar-counters.js", ".gitignore", ".mintignore",
    ".prettierrc", "README.md", "RELEASING.md", "LICENSE", NEXT_DIR,
}


def is_excluded(name: str) -> bool:
    """True if a top-level docs entry is not movable content (infra, sidecars,
    version folders, the fixed next/ folder, or shared root content)."""
    return (
        name in _EXCLUDED_NAMES
        or name in SHARED_ROOTS
        or name.endswith(".skill.md")
        or bool(_VERSION_DIR_RE.match(name))
    )


def _content_entries(docs_dir: Path):
    return [e for e in sorted(docs_dir.iterdir()) if not is_excluded(e.name)]


def _copy_entry(src: Path, dst: Path) -> None:
    if src.is_dir():
        shutil.copytree(src, dst)
    else:
        shutil.copy2(src, dst)


def copy_root_to_dir(docs_dir: Path, prefix: str) -> None:
    """Copy root content (excluding infra/version/next) into ``docs_dir/prefix``,
    overwriting it."""
    target = docs_dir / prefix
    if target.exists():
        shutil.rmtree(target)
    target.mkdir(parents=True)
    for entry in _content_entries(docs_dir):
        _copy_entry(entry, target / entry.name)


def replace_root_with_dir(docs_dir: Path, prefix: str) -> None:
    """Replace root content with the content of ``docs_dir/prefix`` (infra,
    version dirs, and the next/ folder are left in place). The source folder is
    not removed."""
    source = docs_dir / prefix
    for entry in _content_entries(docs_dir):
        if entry.is_dir():
            shutil.rmtree(entry)
        else:
            entry.unlink()
    for entry in sorted(source.iterdir()):
        _copy_entry(entry, docs_dir / entry.name)


def _load(docs_dir: Path) -> dict:
    return json.loads((docs_dir / "docs.json").read_text(encoding="utf-8"))


def _save(docs_dir: Path, doc: dict) -> None:
    (docs_dir / "docs.json").write_text(
        json.dumps(doc, indent=2, ensure_ascii=False) + "\n", encoding="utf-8"
    )


def validate(docs_dir: Path) -> int:
    """Exit 0 if the Next docs are ready; 1 (with error) otherwise.

    Ready = a Next block exists in docs.json AND docs/next/ is non-empty. The
    release version is irrelevant — rotation always pulls whatever is in next/.
    """
    try:
        versions = _load(docs_dir)["navigation"]["versions"]
        find_index_by_tag(versions, NEXT_TAG)
    except (FileNotFoundError, ValueError) as exc:
        print(f"::error::Cannot validate Next docs: {exc}")
        return 1

    folder = docs_dir / NEXT_DIR
    if not folder.is_dir() or not any(folder.iterdir()):
        print(
            f"::error::Missing Next docs at {folder}. "
            f"Prepare docs/{NEXT_DIR}/ before tagging."
        )
        return 1

    print("pin_docs: Next docs ready")
    return 0


def rotate(docs_dir: Path, version: str) -> None:
    """Archive the old Latest, promote docs/next/ into root as the new Latest
    (labeled with the tag version), and relabel the Next block to minor+1.

    Assumes ``validate`` already passed.
    """
    major, minor, patch = parse_version(version)
    # A patch release does not rotate — it only refreshes the current Latest
    # from docs/next/ in place (no archive, no Next bump, no version changes).
    if patch > 0:
        sync_patch(docs_dir)
        return
    rel_label = minor_label(major, minor)        # tag version label, e.g. 0.17.x
    nmaj, nmin = next_minor(version)
    nxt_label = minor_label(nmaj, nmin)          # e.g. 0.18.x

    doc = _load(docs_dir)
    versions = doc["navigation"]["versions"]
    next_block = versions[find_index_by_tag(versions, NEXT_TAG)]
    latest_block = versions[find_index_by_tag(versions, LATEST_TAG)]

    # Idempotency guard: if the current Latest is already this version, the
    # rotation has already happened for it — re-running would duplicate the
    # block and re-copy folders. No-op.
    if latest_block["version"] == rel_label:
        print(f"pin_docs: already rotated to {rel_label}, skipping")
        return

    old_major, old_minor, _ = parse_version(latest_block["version"].replace("x", "0"))
    old_prefix = dir_prefix(old_major, old_minor)  # e.g. 0-16-0

    # --- filesystem (order matters) ---
    # In-content links are version-relative, so they survive the move untouched.
    copy_root_to_dir(docs_dir, old_prefix)          # archive old Latest -> folder
    replace_root_with_dir(docs_dir, NEXT_DIR)       # promote next/ -> root (next/ kept)

    # --- docs.json ---
    # old Latest -> archived (root paths -> old_prefix), drop tag/default
    latest_block["tabs"] = add_prefix(latest_block["tabs"], old_prefix)
    latest_block.pop("tag", None)
    latest_block.pop("default", None)
    # new Latest block from the Next tabs (next/ -> root), labeled with the tag
    new_latest = {
        "version": rel_label,
        "tag": LATEST_TAG,
        "default": True,
        "tabs": strip_prefix(next_block["tabs"], NEXT_DIR),
    }
    # Next block keeps its next/ paths; only its label advances to minor+1
    next_block["version"] = nxt_label

    versions.append(new_latest)
    doc["navigation"]["versions"] = sort_versions(versions)
    _save(docs_dir, doc)
    print(f"pin_docs: rotated — Latest={rel_label}, Next={nxt_label}, archived {latest_block['version']}")


def sync_patch(docs_dir: Path) -> None:
    """Patch release: refresh the Latest (root) docs from docs/next/ in place.

    Unlike ``rotate`` there is no version ceremony — the old Latest is not
    archived, the Next block is not bumped, and no version blocks in docs.json
    change. Only the root content is replaced (in-content links are relative, so
    they survive the move untouched).
    """
    replace_root_with_dir(docs_dir, NEXT_DIR)
    print("pin_docs: patched Latest from docs/next/ (no rotation)")


def main(argv: list[str] | None = None) -> int:
    parser = argparse.ArgumentParser()
    sub = parser.add_subparsers(dest="command", required=True)

    p_validate = sub.add_parser("validate")
    p_validate.add_argument("--docs-dir", required=True, type=Path)

    p_rotate = sub.add_parser("rotate")
    p_rotate.add_argument("--docs-dir", required=True, type=Path)
    p_rotate.add_argument("--version", required=True)

    args = parser.parse_args(argv)
    if args.command == "validate":
        return validate(args.docs_dir)
    rotate(args.docs_dir, args.version)
    return 0


if __name__ == "__main__":
    sys.exit(main())

```

## /.github/scripts/test_bump_manifests.py

```py path="/.github/scripts/test_bump_manifests.py" 
"""Unit tests for bump_manifests.py.

Run with: python -m pytest .github/scripts/test_bump_manifests.py -v
"""
from __future__ import annotations

import subprocess
import sys
import textwrap
from pathlib import Path

import pytest

from bump_manifests import bump_cargo_package_version
from bump_manifests import bump_cargo_workspace_dep_version
from bump_manifests import bump_go_const_version
from bump_manifests import bump_json_top_level_version
from bump_manifests import bump_pep440_dep_pin
from bump_manifests import rewrite_all


class TestBumpCargoPackageVersion:
    def test_replaces_first_version_only(self):
        src = textwrap.dedent(
            """\
            [package]
            name = "iii-observability"
            version = "0.13.0-next.1"
            edition = "2024"

            [dependencies]
            other = { version = "1.2.3" }
            """
        )
        out = bump_cargo_package_version(src, "0.16.0-next.2")
        assert 'version = "0.16.0-next.2"' in out
        assert 'other = { version = "1.2.3" }' in out
        # First match anchored on line start only — no other top-level
        # version line should change.
        assert out.count('version = "0.16.0-next.2"') == 1

    def test_raises_when_no_version(self):
        src = '[package]\nname = "foo"\n'
        with pytest.raises(ValueError, match="no top-level version"):
            bump_cargo_package_version(src, "0.16.0-next.2")


class TestBumpCargoWorkspaceDepVersion:
    def test_replaces_version_pin(self):
        src = (
            "[workspace.dependencies]\n"
            'iii-observability = { path = "sdk/packages/rust/observability", version = "0.13.0-next.1" }\n'
            'tokio = { version = "1", features = ["macros"] }\n'
        )
        out = bump_cargo_workspace_dep_version(src, "iii-observability", "0.16.0-next.2")
        assert (
            'iii-observability = { path = "sdk/packages/rust/observability", version = "0.16.0-next.2" }'
            in out
        )
        assert 'tokio = { version = "1", features = ["macros"] }' in out

    def test_raises_when_dep_missing(self):
        src = '[workspace.dependencies]\ntokio = { version = "1" }\n'
        with pytest.raises(ValueError, match="iii-observability"):
            bump_cargo_workspace_dep_version(src, "iii-observability", "0.16.0-next.2")


class TestBumpJsonTopLevelVersion:
    def test_replaces_first_version(self):
        src = (
            '{\n'
            '  "name": "iii-sdk",\n'
            '  "version": "0.13.0-next.1",\n'
            '  "dependencies": {\n'
            '    "@iii-dev/observability": "workspace:*"\n'
            '  }\n'
            '}\n'
        )
        out = bump_json_top_level_version(src, "0.16.0-next.2")
        assert '"version": "0.16.0-next.2"' in out
        assert '"@iii-dev/observability": "workspace:*"' in out

    def test_raises_when_no_top_level_version(self):
        src = '{ "name": "x" }\n'
        with pytest.raises(ValueError, match="no top-level version"):
            bump_json_top_level_version(src, "1.0.0")


class TestBumpPep440DepPin:
    def test_replaces_pin(self):
        src = (
            'dependencies = [\n'
            '    "websockets>=12.0",\n'
            '    "iii-observability==0.13.0.dev1",\n'
            ']\n'
        )
        out = bump_pep440_dep_pin(src, "iii-observability", "0.16.0.dev2")
        assert '"iii-observability==0.16.0.dev2"' in out
        assert '"websockets>=12.0"' in out

    def test_raises_when_dep_missing(self):
        src = 'dependencies = [\n    "websockets>=12.0",\n]\n'
        with pytest.raises(ValueError, match="iii-observability"):
            bump_pep440_dep_pin(src, "iii-observability", "0.16.0.dev2")


class TestBumpGoConstVersion:
    def test_replaces_const(self):
        src = (
            "// sdkVersion is reported in the worker metadata.\n"
            'const sdkVersion = "0.1.0"\n'
        )
        out = bump_go_const_version(src, "0.19.2-alpha.1")
        assert 'const sdkVersion = "0.19.2-alpha.1"' in out
        assert '"0.1.0"' not in out

    def test_raises_when_missing(self):
        with pytest.raises(ValueError, match="sdkVersion"):
            bump_go_const_version("package iii\n", "0.19.2-alpha.1")


def _write(p: Path, body: str) -> None:
    p.parent.mkdir(parents=True, exist_ok=True)
    p.write_text(body)


def test_rewrite_all_updates_every_target_file(tmp_path: Path):
    root = tmp_path

    _write(root / "Cargo.toml", (
        '[workspace.package]\n'
        'version = "0.15.0-next.1"\n\n'
        '[workspace.dependencies]\n'
        'iii-observability = { path = "sdk/packages/rust/observability", version = "0.13.0-next.1" }\n'
        'iii-helpers = { path = "sdk/packages/rust/helpers", version = "0.13.0-next.1" }\n'
    ))
    _write(root / "engine" / "Cargo.toml", '[package]\nname = "iii"\nversion = "0.15.0-next.1"\n')
    _write(root / "sdk/packages/rust/iii/Cargo.toml", '[package]\nname = "iii-sdk"\nversion = "0.15.0-next.1"\n')
    _write(root / "sdk/packages/rust/observability/Cargo.toml", '[package]\nname = "iii-observability"\nversion = "0.13.0-next.1"\n')
    _write(root / "sdk/packages/rust/helpers/Cargo.toml", '[package]\nname = "iii-helpers"\nversion = "0.13.0-next.1"\n')
    _write(root / "sdk/packages/node/iii/package.json", '{\n  "name": "iii-sdk",\n  "version": "0.15.0-next.1"\n}\n')
    _write(root / "sdk/packages/node/iii-browser/package.json", '{\n  "name": "iii-browser",\n  "version": "0.15.0-next.1"\n}\n')
    _write(root / "sdk/packages/node/observability/package.json", '{\n  "name": "@iii-dev/observability",\n  "version": "0.13.0-next.1"\n}\n')
    _write(root / "sdk/packages/node/helpers/package.json", '{\n  "name": "@iii-dev/helpers",\n  "version": "0.13.0-next.1"\n}\n')
    # Python iii: iii-observability is no longer a direct dep (removed in
    # observability-into-helpers refactor); only iii-helpers is pinned.
    _write(root / "sdk/packages/python/iii/pyproject.toml", (
        '[project]\nname = "iii-sdk"\nversion = "0.15.0.dev1"\n'
        'dependencies = [\n    "iii-helpers==0.13.0.dev1",\n]\n'
    ))
    _write(root / "sdk/packages/python/observability/pyproject.toml", (
        '[project]\nname = "iii-observability"\nversion = "0.13.0.dev1"\n'
        'dependencies = [\n    "iii-helpers==0.13.0.dev1",\n]\n\n'
        '[tool.uv.sources]\niii-helpers = { path = "../helpers", editable = true }\n'
    ))
    _write(root / "sdk/packages/python/helpers/pyproject.toml", '[project]\nname = "iii-helpers"\nversion = "0.13.0.dev1"\n')
    _write(root / "console/packages/console-rust/Cargo.toml", '[package]\nname = "console-rust"\nversion = "0.15.0-next.1"\n')
    _write(root / "sdk/packages/go/iii/client.go", 'package iii\n\nconst sdkVersion = "0.1.0"\n')

    rewrite_all(root=root, new_version="0.16.0-next.2", new_py_version="0.16.0.dev2")

    assert 'version = "0.16.0-next.2"' in (root / "Cargo.toml").read_text()
    assert 'iii-observability = { path = "sdk/packages/rust/observability", version = "0.16.0-next.2" }' in (root / "Cargo.toml").read_text()
    assert 'iii-helpers = { path = "sdk/packages/rust/helpers", version = "0.16.0-next.2" }' in (root / "Cargo.toml").read_text()
    assert 'version = "0.16.0-next.2"' in (root / "engine" / "Cargo.toml").read_text()
    assert 'version = "0.16.0-next.2"' in (root / "sdk/packages/rust/iii/Cargo.toml").read_text()
    assert 'version = "0.16.0-next.2"' in (root / "sdk/packages/rust/observability/Cargo.toml").read_text()
    assert 'version = "0.16.0-next.2"' in (root / "sdk/packages/rust/helpers/Cargo.toml").read_text()
    assert '"version": "0.16.0-next.2"' in (root / "sdk/packages/node/iii/package.json").read_text()
    assert '"version": "0.16.0-next.2"' in (root / "sdk/packages/node/iii-browser/package.json").read_text()
    assert '"version": "0.16.0-next.2"' in (root / "sdk/packages/node/observability/package.json").read_text()
    assert '"version": "0.16.0-next.2"' in (root / "sdk/packages/node/helpers/package.json").read_text()
    py_iii = (root / "sdk/packages/python/iii/pyproject.toml").read_text()
    assert 'version = "0.16.0.dev2"' in py_iii
    assert '"iii-helpers==0.16.0.dev2"' in py_iii
    # iii-observability is published as a shim but is no longer a dep of iii-sdk
    assert '"iii-observability==' not in py_iii
    py_obs = (root / "sdk/packages/python/observability/pyproject.toml").read_text()
    assert 'version = "0.16.0.dev2"' in py_obs
    # The shim's iii-helpers dep pin must be bumped to the new release version.
    assert '"iii-helpers==0.16.0.dev2"' in py_obs
    assert '"iii-helpers==0.13.0.dev1"' not in py_obs
    assert 'version = "0.16.0.dev2"' in (root / "sdk/packages/python/helpers/pyproject.toml").read_text()
    assert 'version = "0.16.0-next.2"' in (root / "console/packages/console-rust/Cargo.toml").read_text()
    assert 'const sdkVersion = "0.16.0-next.2"' in (root / "sdk/packages/go/iii/client.go").read_text()


def test_cli_invokes_rewrite_all(tmp_path: Path):
    root = tmp_path
    _write(root / "Cargo.toml", (
        '[workspace.package]\n'
        'version = "0.15.0-next.1"\n\n'
        '[workspace.dependencies]\n'
        'iii-observability = { path = "sdk/packages/rust/observability", version = "0.13.0-next.1" }\n'
        'iii-helpers = { path = "sdk/packages/rust/helpers", version = "0.13.0-next.1" }\n'
    ))
    _write(root / "engine" / "Cargo.toml", 'version = "0.15.0-next.1"\n')
    _write(root / "sdk/packages/rust/iii/Cargo.toml", 'version = "0.15.0-next.1"\n')
    _write(root / "sdk/packages/rust/observability/Cargo.toml", 'version = "0.13.0-next.1"\n')
    _write(root / "sdk/packages/rust/helpers/Cargo.toml", 'version = "0.13.0-next.1"\n')
    _write(root / "sdk/packages/node/iii/package.json", '{\n  "version": "0.15.0-next.1"\n}\n')
    _write(root / "sdk/packages/node/iii-browser/package.json", '{\n  "version": "0.15.0-next.1"\n}\n')
    _write(root / "sdk/packages/node/observability/package.json", '{\n  "version": "0.13.0-next.1"\n}\n')
    _write(root / "sdk/packages/node/helpers/package.json", '{\n  "version": "0.13.0-next.1"\n}\n')
    # Python iii: only iii-helpers is pinned (iii-observability removed in
    # observability-into-helpers refactor).
    _write(root / "sdk/packages/python/iii/pyproject.toml", (
        'version = "0.15.0.dev1"\n'
        'dependencies = [\n    "iii-helpers==0.13.0.dev1",\n]\n'
    ))
    _write(root / "sdk/packages/python/observability/pyproject.toml", (
        'version = "0.13.0.dev1"\n'
        'dependencies = [\n    "iii-helpers==0.13.0.dev1",\n]\n\n'
        '[tool.uv.sources]\niii-helpers = { path = "../helpers", editable = true }\n'
    ))
    _write(root / "sdk/packages/python/helpers/pyproject.toml", 'version = "0.13.0.dev1"\n')
    _write(root / "console/packages/console-rust/Cargo.toml", 'version = "0.15.0-next.1"\n')
    _write(root / "sdk/packages/go/iii/client.go", 'package iii\n\nconst sdkVersion = "0.1.0"\n')

    script = Path(__file__).parent / "bump_manifests.py"
    result = subprocess.run(
        [sys.executable, str(script), "--root", str(root),
         "--version", "0.16.0-next.2", "--python-version", "0.16.0.dev2"],
        check=True, capture_output=True, text=True,
    )
    assert "0.16.0-next.2" in result.stdout

    assert 'version = "0.16.0-next.2"' in (root / "Cargo.toml").read_text()
    assert 'iii-helpers==0.16.0.dev2' in (root / "sdk/packages/python/iii/pyproject.toml").read_text()
    assert 'iii-helpers==0.16.0.dev2' in (root / "sdk/packages/python/observability/pyproject.toml").read_text()

```

## /.github/scripts/test_calculate_release_version.py

```py path="/.github/scripts/test_calculate_release_version.py" 
"""Unit tests for calculate_release_version.py.

Run with: python -m pytest .github/scripts/test_calculate_release_version.py -v
"""
from __future__ import annotations

import pytest

from calculate_release_version import (
    bump_base,
    calculate_version,
    detect_current_level,
    highest_inflight_prerelease_base,
    latest_stable_from_tags,
    next_dry_run_counter,
    next_prerelease_counter,
    parse_version,
    to_pep440,
)


# ---------- parse_version ----------


class TestParseVersion:
    def test_stable(self):
        v = parse_version("1.2.3")
        assert (v.major, v.minor, v.patch) == (1, 2, 3)
        assert v.prerelease_label is None
        assert v.prerelease_num is None

    def test_prerelease(self):
        v = parse_version("0.12.0-next.5")
        assert (v.major, v.minor, v.patch) == (0, 12, 0)
        assert v.prerelease_label == "next"
        assert v.prerelease_num == 5

    @pytest.mark.parametrize("label", ["alpha", "beta", "rc", "next"])
    def test_all_prerelease_labels(self, label):
        v = parse_version(f"1.2.3-{label}.7")
        assert v.prerelease_label == label
        assert v.prerelease_num == 7

    def test_invalid(self):
        with pytest.raises(ValueError):
            parse_version("not-a-version")


# ---------- bump_base ----------


class TestBumpBase:
    @pytest.mark.parametrize(
        "base,bump,expected",
        [
            ("0.11.7", "patch", "0.11.8"),
            ("0.11.7", "minor", "0.12.0"),
            ("0.11.7", "major", "1.0.0"),
            ("1.2.3", "minor", "1.3.0"),
            ("0.0.0", "patch", "0.0.1"),
        ],
    )
    def test_bump(self, base, bump, expected):
        assert bump_base(base, bump) == expected

    def test_unknown_bump(self):
        with pytest.raises(ValueError):
            bump_base("1.0.0", "bogus")


# ---------- detect_current_level ----------


class TestDetectCurrentLevel:
    @pytest.mark.parametrize(
        "current,stable,expected",
        [
            ("0.11.7", "0.11.6", "patch"),
            ("0.12.0", "0.11.6", "minor"),
            ("1.0.0", "0.11.6", "major"),
            ("0.11.6", "0.11.6", None),  # equal — no bump implied
            ("0.10.0", "0.11.6", None),  # current older
        ],
    )
    def test_levels(self, current, stable, expected):
        assert detect_current_level(current, stable) == expected

    def test_no_stable(self):
        assert detect_current_level("0.1.0", None) is None


# ---------- next_prerelease_counter ----------


class TestPrereleaseCounter:
    def test_empty(self):
        assert next_prerelease_counter("0.12.0", "next", [], "iii") == 1

    def test_existing(self):
        tags = ["iii/v0.12.0-next.1", "iii/v0.12.0-next.2", "iii/v0.12.0-next.3"]
        assert next_prerelease_counter("0.12.0", "next", tags, "iii") == 4

    def test_different_base_ignored(self):
        tags = ["iii/v0.11.0-next.1", "iii/v0.13.0-next.5"]
        assert next_prerelease_counter("0.12.0", "next", tags, "iii") == 1

    def test_different_label_ignored(self):
        tags = ["iii/v0.12.0-rc.1", "iii/v0.12.0-alpha.3"]
        assert next_prerelease_counter("0.12.0", "next", tags, "iii") == 1

    def test_different_prefix_ignored(self):
        tags = ["other/v0.12.0-next.5"]
        assert next_prerelease_counter("0.12.0", "next", tags, "iii") == 1

    def test_picks_max_not_count(self):
        tags = ["iii/v0.12.0-next.1", "iii/v0.12.0-next.7"]
        assert next_prerelease_counter("0.12.0", "next", tags, "iii") == 8


# ---------- next_dry_run_counter ----------


class TestDryRunCounter:
    def test_empty(self):
        assert next_dry_run_counter("0.12.0", [], "iii") == 1

    def test_existing(self):
        tags = ["iii/v0.12.0-dry-run.1", "iii/v0.12.0-dry-run.4"]
        assert next_dry_run_counter("0.12.0", tags, "iii") == 5


# ---------- highest_inflight_prerelease_base ----------


class TestHighestInflightPrereleaseBase:
    def test_none_when_empty(self):
        assert highest_inflight_prerelease_base([], "iii", "0.19.4") is None

    def test_picks_base_above_stable(self):
        tags = ["iii/v0.19.4", "iii/v0.19.5-next.1"]
        assert highest_inflight_prerelease_base(tags, "iii", "0.19.4") == "0.19.5"

    def test_ignores_base_at_or_below_stable(self):
        tags = ["iii/v0.19.4-alpha.1", "iii/v0.19.3-next.9"]
        assert highest_inflight_prerelease_base(tags, "iii", "0.19.4") is None

    def test_picks_highest_across_trains(self):
        tags = ["iii/v0.19.5-next.1", "iii/v0.20.0-rc.1"]
        assert highest_inflight_prerelease_base(tags, "iii", "0.19.4") == "0.20.0"

    def test_prefix_scoped(self):
        tags = ["other/v0.30.0-next.1", "iii/v0.19.5-next.1"]
        assert highest_inflight_prerelease_base(tags, "iii", "0.19.4") == "0.19.5"

    def test_no_stable_floor_accepts_any_prerelease(self):
        tags = ["iii/v0.5.0-next.1"]
        assert highest_inflight_prerelease_base(tags, "iii", None) == "0.5.0"

    def test_numeric_not_lexical_base_compare(self):
        tags = ["iii/v0.19.5-next.1", "iii/v0.19.10-next.1"]
        assert highest_inflight_prerelease_base(tags, "iii", "0.19.4") == "0.19.10"


# ---------- latest_stable_from_tags ----------


class TestLatestStable:
    def test_picks_highest(self):
        tags = [
            "iii/v0.11.5",
            "iii/v0.11.6",
            "iii/v0.11.6-next.3",  # prerelease ignored
            "iii/v0.10.0",
        ]
        assert latest_stable_from_tags(tags, "iii") == "0.11.6"

    def test_no_stable(self):
        tags = ["iii/v0.12.0-next.1", "iii/v0.12.0-next.2"]
        assert latest_stable_from_tags(tags, "iii") is None

    def test_empty(self):
        assert latest_stable_from_tags([], "iii") is None

    def test_different_prefix_ignored(self):
        tags = ["other/v9.9.9", "iii/v0.1.0"]
        assert latest_stable_from_tags(tags, "iii") == "0.1.0"


# ---------- calculate_version ----------


class TestCalculateVersion:
    """All the version-bump scenarios.

    The naming convention is: starting_state__bump_prerelease__expected.
    """

    # -- Stable starting point --

    def test_stable_patch_stable(self):
        assert calculate_version("0.11.6", "patch", "none", "0.11.6", [], "iii") == "0.11.7"

    def test_stable_minor_stable(self):
        assert calculate_version("0.11.6", "minor", "none", "0.11.6", [], "iii") == "0.12.0"

    def test_stable_major_stable(self):
        assert calculate_version("0.11.6", "major", "none", "0.11.6", [], "iii") == "1.0.0"

    def test_stable_patch_next(self):
        assert calculate_version("0.11.6", "patch", "next", "0.11.6", [], "iii") == "0.11.7-next.1"

    def test_stable_minor_next(self):
        assert calculate_version("0.11.6", "minor", "next", "0.11.6", [], "iii") == "0.12.0-next.1"

    def test_stable_major_rc(self):
        assert calculate_version("0.11.6", "major", "rc", "0.11.6", [], "iii") == "1.0.0-rc.1"

    # -- Patch always advances the patch component --

    def test_patch_always_bumps_patch_component(self):
        """patch is never an iteration: it always advances the patch component."""
        assert (
            calculate_version("0.11.7-next.2", "patch", "next", "0.11.6", [], "iii")
            == "0.11.8-next.1"
        )

    def test_patch_from_minor_prerelease_bumps_patch_component(self):
        """Even mid-minor-train, patch advances to a new patch base."""
        tags = ["iii/v0.12.0-next.1", "iii/v0.12.0-next.2"]
        assert (
            calculate_version("0.12.0-next.2", "patch", "next", "0.11.6", tags, "iii")
            == "0.12.1-next.1"
        )

    def test_patch_stable_to_next(self):
        assert (
            calculate_version("0.11.6", "patch", "next", "0.11.6", [], "iii")
            == "0.11.7-next.1"
        )

    # -- Patch prerelease train + non-patch bumps --

    def test_patch_prerelease_minor_next_escalates(self):
        """The bug from the original report: minor must escalate, not continue counter."""
        assert (
            calculate_version("0.11.7-next.2", "minor", "next", "0.11.6", [], "iii")
            == "0.12.0-next.1"
        )

    def test_patch_prerelease_major_next_escalates(self):
        assert (
            calculate_version("0.11.7-next.2", "major", "next", "0.11.6", [], "iii")
            == "1.0.0-next.1"
        )

    # -- Minor prerelease train (the second bug the user reported) --

    def test_minor_prerelease_minor_next_continues_train(self):
        """After escalating to 0.12.0-next.1, subsequent minor+next must iterate, not bump again."""
        tags = ["iii/v0.12.0-next.1"]
        assert (
            calculate_version("0.12.0-next.1", "minor", "next", "0.11.6", tags, "iii")
            == "0.12.0-next.2"
        )

    def test_minor_prerelease_major_next_escalates(self):
        assert (
            calculate_version("0.12.0-next.1", "major", "next", "0.11.6", [], "iii")
            == "1.0.0-next.1"
        )

    # -- Major prerelease train --

    def test_major_prerelease_major_next_continues_train(self):
        tags = ["iii/v1.0.0-next.1", "iii/v1.0.0-next.2"]
        assert (
            calculate_version("1.0.0-next.2", "major", "next", "0.11.6", tags, "iii")
            == "1.0.0-next.3"
        )

    def test_major_prerelease_minor_next_continues_train(self):
        tags = ["iii/v1.0.0-next.1"]
        assert (
            calculate_version("1.0.0-next.1", "minor", "next", "0.11.6", tags, "iii")
            == "1.0.0-next.2"
        )

    # -- Promotion to stable --

    def test_promote_prerelease_to_stable_drops_suffix(self):
        assert calculate_version("0.12.0-next.5", "patch", "none", "0.11.6", [], "iii") == "0.12.0"

    def test_promote_with_minor_bump_still_uses_base(self):
        """Once a prerelease train decided the base, promotion uses it as-is."""
        assert calculate_version("0.12.0-next.5", "minor", "none", "0.11.6", [], "iii") == "0.12.0"

    # -- Channel switching --

    def test_next_to_rc_starts_fresh_counter(self):
        tags = ["iii/v0.12.0-next.3"]
        assert (
            calculate_version("0.12.0-next.3", "minor", "rc", "0.11.6", tags, "iii")
            == "0.13.0-rc.1"
        )

    # -- No prior stable tag (bootstrap) --

    def test_no_stable_minor_bumps_from_current(self):
        """Without a stable anchor, minor must still apply to the current base."""
        tags = ["iii/v0.1.0-next.1"]
        assert (
            calculate_version("0.1.0-next.1", "minor", "next", None, tags, "iii")
            == "0.2.0-next.1"
        )

    def test_no_stable_stable_starts_from_current(self):
        assert calculate_version("0.0.1", "minor", "next", None, [], "iii") == "0.1.0-next.1"

    def test_no_stable_patch_bumps_from_current(self):
        tags = ["iii/v0.1.0-next.1"]
        assert (
            calculate_version("0.1.0-next.1", "patch", "next", None, tags, "iii")
            == "0.1.1-next.1"
        )

    # -- Counter resumes from existing max --

    def test_counter_uses_max_existing(self):
        tags = [
            "iii/v0.12.0-next.1",
            "iii/v0.12.0-next.7",
            "iii/v0.12.0-next.3",
        ]
        assert (
            calculate_version("0.12.0-next.7", "minor", "next", "0.11.6", tags, "iii")
            == "0.12.0-next.8"
        )

    # -- Invalid inputs --

    def test_unknown_bump(self):
        with pytest.raises(ValueError):
            calculate_version("0.1.0", "bogus", "none", "0.1.0", [], "iii")

    def test_unknown_prerelease(self):
        with pytest.raises(ValueError):
            calculate_version("0.1.0", "patch", "weird", "0.1.0", [], "iii")


# ---------- to_pep440 ----------


class TestAdversarial:
    """Edge cases designed to break the algorithm."""

    # -- Counter-bump ordering --

    def test_counter_uses_numeric_max_not_lex(self):
        """Lex sort would put next.10 before next.2; integer comparison must win."""
        tags = [
            "iii/v0.12.0-next.1",
            "iii/v0.12.0-next.2",
            "iii/v0.12.0-next.10",
        ]
        assert (
            calculate_version("0.12.0-next.10", "minor", "next", "0.11.6", tags, "iii")
            == "0.12.0-next.11"
        )

    def test_counter_picks_max_with_huge_gaps(self):
        tags = ["iii/v0.12.0-next.1", "iii/v0.12.0-next.999"]
        assert (
            calculate_version("0.12.0-next.999", "minor", "next", "0.11.6", tags, "iii")
            == "0.12.0-next.1000"
        )

    # -- Tag prefix isolation --

    def test_other_prefix_tags_do_not_pollute_counter(self):
        tags = [
            "console/v0.12.0-next.50",
            "other/v0.12.0-next.99",
            "iii/v0.12.0-next.1",
        ]
        assert (
            calculate_version("0.12.0-next.1", "minor", "next", "0.11.6", tags, "iii")
            == "0.12.0-next.2"
        )

    def test_substring_prefix_does_not_match(self):
        """`iii` must not match `iiii/...` or `iii-extra/...`."""
        tags = ["iiii/v0.12.0-next.50", "iii-extra/v0.12.0-next.30"]
        assert (
            calculate_version("0.12.0-next.1", "minor", "next", "0.11.6", tags, "iii")
            == "0.12.0-next.1"
        )

    def test_latest_stable_ignores_substring_prefix(self):
        tags = ["iiii/v9.9.9", "iii-extra/v8.8.8", "iii/v0.5.0"]
        assert latest_stable_from_tags(tags, "iii") == "0.5.0"

    def test_tag_prefix_with_regex_special_chars(self):
        """Prefix containing `.` must be literal, not regex wildcard."""
        tags = ["myXtarget/v0.12.0-next.50", "my.target/v0.12.0-next.1"]
        assert (
            calculate_version("0.12.0-next.1", "minor", "next", "0.11.6", tags, "my.target")
            == "0.12.0-next.2"
        )

    # -- Cross-channel counter isolation --

    def test_other_channels_do_not_affect_next_counter(self):
        tags = [
            "iii/v0.12.0-rc.5",
            "iii/v0.12.0-alpha.7",
            "iii/v0.12.0-beta.3",
            "iii/v0.12.0-next.1",
        ]
        assert (
            calculate_version("0.12.0-next.1", "minor", "next", "0.11.6", tags, "iii")
            == "0.12.0-next.2"
        )

    def test_switching_channel_starts_fresh(self):
        tags = ["iii/v0.12.0-next.5"]
        assert (
            calculate_version("0.12.0-next.5", "minor", "rc", "0.11.6", tags, "iii")
            == "0.13.0-rc.1"
        )

    def test_patch_on_rc_train_advances_patch_component(self):
        tags = ["iii/v0.12.0-rc.1", "iii/v0.12.0-rc.2"]
        assert (
            calculate_version("0.12.0-rc.2", "patch", "rc", "0.11.6", tags, "iii")
            == "0.12.1-rc.1"
        )

    # -- Promotion semantics --

    def test_promote_with_major_bump_still_keeps_base(self):
        """Once a prerelease decided the base, promotion uses it regardless of bump type."""
        assert (
            calculate_version("0.12.0-next.5", "major", "none", "0.11.6", [], "iii")
            == "0.12.0"
        )

    def test_promote_from_rc_to_stable(self):
        assert (
            calculate_version("0.12.0-rc.7", "patch", "none", "0.11.6", [], "iii")
            == "0.12.0"
        )

    def test_stable_to_stable_does_not_trigger_promotion(self):
        """Promotion branch is gated on current having a prerelease label."""
        assert (
            calculate_version("0.12.0", "patch", "none", "0.12.0", [], "iii")
            == "0.12.1"
        )

    # -- Latest_stable equal to or ahead of current --

    def test_current_equals_stable_no_level_detected(self):
        """If current and stable are equal, the prerelease is degenerate; bump anyway."""
        tags = ["iii/v0.12.0", "iii/v0.12.0-next.1"]
        # detect_current_level returns None (cur == stable), so we apply bump to current base.
        assert (
            calculate_version("0.12.0-next.1", "minor", "next", "0.12.0", tags, "iii")
            == "0.13.0-next.1"
        )

    def test_current_older_than_stable_treated_as_no_level(self):
        """Pathological: cargo says 0.10.0-next.1 but stable has moved to 0.11.6."""
        assert (
            calculate_version("0.10.0-next.1", "minor", "next", "0.11.6", [], "iii")
            == "0.11.0-next.1"
        )

    # -- Zero-component edge cases --

    def test_zero_base_patch(self):
        assert calculate_version("0.0.0", "patch", "next", None, [], "iii") == "0.0.1-next.1"

    def test_zero_base_major(self):
        assert calculate_version("0.0.0", "major", "next", None, [], "iii") == "1.0.0-next.1"

    def test_large_numbers(self):
        assert (
            calculate_version("999.999.999", "patch", "next", "999.999.998", [], "iii")
            == "999.999.1000-next.1"
        )

    # -- Sequential walk: each result feeds the next call --

    def test_full_release_sequence(self):
        """The whole release cycle the user described, in order."""
        tags = ["iii/v0.11.6"]
        stable = "0.11.6"

        def step(current, bump, pre):
            result = calculate_version(current, bump, pre, stable, tags, "iii")
            tags.append(f"iii/v{result}")
            return result

        assert step("0.11.6", "patch", "next") == "0.11.7-next.1"
        assert step("0.11.7-next.1", "patch", "next") == "0.11.8-next.1"  # patch always advances
        assert step("0.11.8-next.1", "minor", "next") == "0.12.0-next.1"  # escalate
        assert step("0.12.0-next.1", "minor", "next") == "0.12.0-next.2"  # iterate
        assert step("0.12.0-next.2", "minor", "next") == "0.12.0-next.3"  # iterate
        assert step("0.12.0-next.3", "patch", "none") == "0.12.0"          # promote

    def test_rc_iteration_sequence(self):
        tags = ["iii/v0.11.6"]
        stable = "0.11.6"

        def step(current, bump, pre):
            result = calculate_version(current, bump, pre, stable, tags, "iii")
            tags.append(f"iii/v{result}")
            return result

        assert step("0.11.6", "minor", "rc") == "0.12.0-rc.1"
        assert step("0.12.0-rc.1", "minor", "rc") == "0.12.0-rc.2"
        assert step("0.12.0-rc.2", "major", "rc") == "1.0.0-rc.1"
        assert step("1.0.0-rc.1", "major", "rc") == "1.0.0-rc.2"
        assert step("1.0.0-rc.2", "patch", "none") == "1.0.0"

    # -- Malformed tag handling in counter scan --

    def test_malformed_tags_ignored(self):
        tags = [
            "iii/v0.12.0-next.1",
            "iii/not-a-version",
            "iii/v0.12.0-next.abc",
            "garbage",
            "iii/v0.12.0-next.",
        ]
        assert (
            calculate_version("0.12.0-next.1", "minor", "next", "0.11.6", tags, "iii")
            == "0.12.0-next.2"
        )

    # -- Mixed major+minor latest_stable behavior --

    def test_minor_jump_after_major_release(self):
        """After releasing 1.0.0, subsequent minor+next prereleases."""
        tags = ["iii/v1.0.0"]
        assert (
            calculate_version("1.0.0", "minor", "next", "1.0.0", tags, "iii")
            == "1.1.0-next.1"
        )
        tags.append("iii/v1.1.0-next.1")
        assert (
            calculate_version("1.1.0-next.1", "minor", "next", "1.0.0", tags, "iii")
            == "1.1.0-next.2"
        )

    # -- Counter starts past 1 if existing tags found at new base --

    def test_existing_tags_at_target_base_continue_counter(self):
        """If we escalate to a base that already has prereleases, resume the counter."""
        tags = [
            "iii/v0.11.6",
            "iii/v0.12.0-next.1",  # someone else already started this train
            "iii/v0.12.0-next.2",
        ]
        assert (
            calculate_version("0.11.7-next.5", "minor", "next", "0.11.6", tags, "iii")
            == "0.12.0-next.3"
        )

    # -- Patch + same channel with existing patch-base tags --

    def test_patch_resumes_counter_at_new_patch_base(self):
        """patch advances the patch component, but if tags already exist at that base, resume."""
        tags = [
            "iii/v0.11.6",
            "iii/v0.11.7-next.1",
        ]
        assert (
            calculate_version("0.11.6", "patch", "next", "0.11.6", tags, "iii")
            == "0.11.7-next.2"
        )


class TestToPep440:
    @pytest.mark.parametrize(
        "version,expected",
        [
            ("0.12.0", "0.12.0"),
            ("0.12.0-rc.1", "0.12.0rc1"),
            ("0.12.0-alpha.3", "0.12.0a3"),
            ("0.12.0-beta.2", "0.12.0b2"),
            ("0.12.0-next.5", "0.12.0.dev5"),
        ],
    )
    def test_conversion(self, version, expected):
        assert to_pep440(version) == expected

    def test_unknown_label_passes_through(self):
        # Dry-run tags aren't valid PEP 440 prereleases; we just leave them.
        assert to_pep440("0.12.0-dry-run.1") == "0.12.0-dry-run.1"

    def test_unknown_label_matching_regex_passes_through(self):
        # `dev` is [a-z]+ so it matches PRERELEASE_RE but isn't in the channel
        # mapping. Must passthrough untouched rather than producing garbage.
        assert to_pep440("1.2.3-dev.4") == "1.2.3-dev.4"
        assert to_pep440("1.2.3-foo.4") == "1.2.3-foo.4"


# ---------- Adversarial (post-merge hardening) ----------
#
# These tests document behavior we discovered while attacking the algorithm
# after the initial port. They lock in current behavior — including a few
# documented footguns — so future refactors don't silently drift.


class TestPromotionFootguns:
    """Promotion to `none` always returns the current base, regardless of bump.

    This is intentional ("drop the prerelease suffix, keep the base") but is a
    sharp edge: a user on `0.15.0-next.5` who runs `patch + none` expecting
    `0.15.1` will get `0.15.0`. Documented here so the surprise is visible.
    """

    def test_promote_ignores_patch_bump(self):
        assert (
            calculate_version("0.15.0-next.5", "patch", "none", "0.14.0", ["iii/v0.14.0"], "iii")
            == "0.15.0"
        )

    def test_promote_ignores_minor_bump(self):
        assert (
            calculate_version("0.15.0-next.5", "minor", "none", "0.14.0", ["iii/v0.14.0"], "iii")
            == "0.15.0"
        )

    def test_promote_ignores_major_bump(self):
        assert (
            calculate_version("0.15.0-next.5", "major", "none", "0.14.0", ["iii/v0.14.0"], "iii")
            == "0.15.0"
        )

    def test_stable_to_stable_does_not_promote(self):
        # No prerelease label on current → promotion branch skipped → real bump.
        assert (
            calculate_version("0.15.0", "patch", "none", "0.15.0", ["iii/v0.15.0"], "iii")
            == "0.15.1"
        )


class TestCurrentBehindLatestStable:
    """If engine/Cargo.toml falls behind the latest stable tag (manual
    downgrade, bad merge), the algorithm anchors from the *current* base
    rather than `latest_stable`. That can produce a tag that overlaps an
    earlier train. Locked in here so we notice if the behavior changes.
    """

    def test_minor_below_stable_anchors_from_current(self):
        assert (
            calculate_version(
                "0.12.0-next.5", "minor", "next", "0.15.0", ["iii/v0.15.0"], "iii"
            )
            == "0.13.0-next.1"
        )

    def test_major_jump_when_current_minor_below_stable_major(self):
        # Current's major < stable's major → detect_current_level returns None
        # → falls into the "no level" branch → bumps the current base.
        assert (
            calculate_version(
                "0.5.0-next.1", "minor", "next", "1.2.0", ["iii/v1.2.0"], "iii"
            )
            == "0.6.0-next.1"
        )

    def test_current_equals_stable_no_level_minor(self):
        # cur == stable → detect_current_level None → bump current base.
        assert (
            calculate_version("0.13.0", "minor", "next", "0.13.0", ["iii/v0.13.0"], "iii")
            == "0.14.0-next.1"
        )


class TestChannelSwitchPicksUpExistingCounter:
    """Switching channels (e.g. rc → next) uses the next_prerelease_counter
    scan on the target base, which resumes from any existing tags. This is
    intentional (avoids clobbering published prereleases) but can surprise
    someone who expects `.1` after a fresh switch.
    """

    def test_switch_resumes_counter_from_existing_target_tag(self):
        tags = ["iii/v0.16.0-next.3", "iii/v0.13.0"]
        # rc.2 → minor + next bumps base to 0.16.0; existing 0.16.0-next.3
        # forces counter to 4 rather than 1.
        assert (
            calculate_version("0.15.0-rc.2", "minor", "next", "0.13.0", tags, "iii")
            == "0.16.0-next.4"
        )

    def test_switch_starts_at_1_when_no_existing_on_target_base(self):
        tags = ["iii/v0.13.0", "iii/v0.15.0-rc.2"]
        assert (
            calculate_version("0.15.0-rc.2", "minor", "next", "0.13.0", tags, "iii")
            == "0.16.0-next.1"
        )


class TestSameChannelStaysIsolatedFromOtherChannels:
    """A `next` release must not be polluted by `rc` (or alpha/beta) tags."""

    def test_next_ignores_rc_tags_at_same_base(self):
        tags = [
            "iii/v0.15.0-rc.5",
            "iii/v0.15.0-rc.6",
            "iii/v0.15.0-rc.7",
            "iii/v0.15.0-next.1",
        ]
        assert (
            calculate_version("0.15.0-next.1", "minor", "next", "0.13.0", tags, "iii")
            == "0.15.0-next.2"
        )

    def test_rc_ignores_next_tags_at_same_base(self):
        tags = [
            "iii/v0.15.0-next.5",
            "iii/v0.15.0-next.6",
            "iii/v0.15.0-rc.1",
        ]
        assert (
            calculate_version("0.15.0-rc.1", "minor", "rc", "0.13.0", tags, "iii")
            == "0.15.0-rc.2"
        )


class TestCounterAtZero:
    """A `.next.0` tag in the wild shouldn't break counter math."""

    def test_zero_counter_increments(self):
        tags = ["iii/v0.15.0-next.0"]
        assert (
            calculate_version("0.15.0-next.0", "minor", "next", "0.13.0", tags, "iii")
            == "0.15.0-next.1"
        )


class TestNoLatestStable:
    """First-ever release: no stable tag yet, current is the seed prerelease."""

    def test_same_channel_minor_bumps_current_when_no_stable(self):
        assert (
            calculate_version("0.5.0-next.5", "minor", "next", None, ["iii/v0.5.0-next.5"], "iii")
            == "0.6.0-next.1"
        )

    def test_same_channel_patch_advances_patch_when_no_stable(self):
        assert (
            calculate_version("0.5.0-next.5", "patch", "next", None, [], "iii")
            == "0.5.1-next.1"
        )


class TestEscalationRestartsFromStable:
    """When the requested bump escalates beyond the current train's level,
    we restart from the latest stable rather than the current base.
    """

    def test_major_from_minor_train_anchors_at_stable(self):
        # current 0.20.0-next.1, stable 0.13.0 → current_level=minor, request=major
        # → escalate → anchor=latest_stable=0.13.0 → bump major → 1.0.0
        assert (
            calculate_version(
                "0.20.0-next.1", "major", "next", "0.13.0", ["iii/v0.13.0"], "iii"
            )
            == "1.0.0-next.1"
        )

    def test_minor_from_patch_train_anchors_at_stable(self):
        # current 0.13.5-next.1 (patch train above stable 0.13.0), request minor
        # → escalate → anchor=0.13.0 → bump minor → 0.14.0
        assert (
            calculate_version(
                "0.13.5-next.1", "minor", "next", "0.13.0", ["iii/v0.13.0"], "iii"
            )
            == "0.14.0-next.1"
        )


class TestCargoVersionParsing:
    """`_read_cargo_version` returns the FIRST line that starts with
    `version = `. A Cargo.toml whose first such line is in a dependency
    table (rather than `[package]`) would yield the wrong version. Locked
    in so we catch any regression in the parser.
    """

    def test_picks_first_line_starting_with_version(self, tmp_path):
        from calculate_release_version import _read_cargo_version

        p = tmp_path / "Cargo.toml"
        p.write_text('[package]\nname = "iii"\nversion = "1.2.3"\n')
        assert _read_cargo_version(str(p)) == "1.2.3"

    def test_indented_version_lines_are_skipped(self, tmp_path):
        # `startswith("version = ")` requires column-0, so indented version
        # lines inside dependency tables are correctly ignored.
        from calculate_release_version import _read_cargo_version

        p = tmp_path / "Cargo.toml"
        p.write_text(
            '[dependencies.foo]\n    version = "9.9.9"\n[package]\nversion = "1.2.3"\n'
        )
        assert _read_cargo_version(str(p)) == "1.2.3"

    def test_missing_version_raises(self, tmp_path):
        from calculate_release_version import _read_cargo_version

        p = tmp_path / "Cargo.toml"
        p.write_text("[package]\nname = \"iii\"\n")
        with pytest.raises(RuntimeError):
            _read_cargo_version(str(p))


class TestCalculateRejectsBadInputs:
    def test_unknown_bump_type_raises(self):
        with pytest.raises(ValueError):
            calculate_version("0.13.0", "bogus", "next", "0.13.0", [], "iii")

    def test_unknown_prerelease_raises(self):
        with pytest.raises(ValueError):
            calculate_version("0.13.0", "minor", "bogus", "0.13.0", [], "iii")

    def test_empty_prerelease_string_raises(self):
        with pytest.raises(ValueError):
            calculate_version("0.13.0", "minor", "", "0.13.0", [], "iii")

    def test_uppercase_prerelease_raises(self):
        # Only lowercase channel labels are accepted; CLI should normalize
        # upstream if it ever supports anything else.
        with pytest.raises(ValueError):
            calculate_version("0.13.0", "minor", "NEXT", "0.13.0", [], "iii")

    def test_unparseable_current_raises(self):
        with pytest.raises(ValueError):
            calculate_version("not-a-version", "minor", "next", "0.13.0", [], "iii")


class TestDryRunInteraction:
    """`--dry-run` is applied after `calculate_version`. It splits on the
    first `-` of whatever calculate produced and tacks on a dry-run counter.
    Verify the boundary cases.
    """

    def test_dry_run_counter_on_stable_base(self):
        from calculate_release_version import next_dry_run_counter

        tags = ["iii/v0.16.0-dry-run.1", "iii/v0.16.0-dry-run.5"]
        assert next_dry_run_counter("0.16.0", tags, "iii") == 6

    def test_dry_run_counter_starts_at_1_when_none(self):
        from calculate_release_version import next_dry_run_counter

        assert next_dry_run_counter("0.16.0", [], "iii") == 1

    def test_dry_run_ignores_other_prefixes(self):
        from calculate_release_version import next_dry_run_counter

        tags = ["other/v0.16.0-dry-run.99", "iii/v0.16.0-dry-run.1"]
        assert next_dry_run_counter("0.16.0", tags, "iii") == 2


class TestLargeCounterMath:
    def test_counter_well_above_int32(self):
        # Python ints are unbounded; ensure huge counters work.
        tags = [f"iii/v0.15.0-next.{2**40}"]
        assert (
            calculate_version("0.15.0-next.1", "minor", "next", "0.13.0", tags, "iii")
            == f"0.15.0-next.{2**40 + 1}"
        )


class TestTagPatternRejectsImpostors:
    """Bogus or malformed entries in the tag list must not affect counters."""

    def test_partial_match_does_not_count(self):
        tags = [
            "iii/v0.15.0-next.1abc",  # trailing garbage — must be rejected
            "iii/v0.15.0-next.",  # missing number
            "iii/v0.15.0-next",  # missing dot+number
            "iii/v0.15.0-NEXT.5",  # uppercase channel
            "iii/v0.15.0-next.1",  # only this one should count
        ]
        assert (
            calculate_version("0.15.0-next.1", "minor", "next", "0.13.0", tags, "iii")
            == "0.15.0-next.2"
        )

    def test_blank_lines_in_tag_list(self):
        # `_git_tags` filters blanks but `next_prerelease_counter` should be
        # robust regardless of upstream filtering.
        tags = ["", "iii/v0.15.0-next.3", ""]
        assert (
            calculate_version("0.15.0-next.1", "minor", "next", "0.13.0", tags, "iii")
            == "0.15.0-next.4"
        )


# ---------- calculate_version: bump="none" (alpha anchor) ----------


class TestCalculateVersionBumpNone:
    def test_anchors_on_latest_stable_keeps_base(self):
        # Manifest is ahead (0.19.3-next.1) but the alpha anchors on the
        # latest stable (0.19.2) and never touches the official version.
        v = calculate_version(
            current="0.19.3-next.1",
            bump_type="none",
            prerelease="alpha",
            latest_stable="0.19.2",
            existing_tags=[],
            tag_prefix="iii-alpha",
        )
        assert v == "0.19.2-alpha.1"

    def test_counter_accumulates_under_its_own_prefix(self):
        v = calculate_version(
            current="0.19.3-next.1",
            bump_type="none",
            prerelease="alpha",
            latest_stable="0.19.2",
            existing_tags=[
                "iii-alpha/v0.19.2-alpha.1",
                "iii-alpha/v0.19.2-alpha.2",
                "iii/v0.19.2",  # official stable — different prefix, ignored
            ],
            tag_prefix="iii-alpha",
        )
        assert v == "0.19.2-alpha.3"

    def test_falls_back_to_current_base_without_stable(self):
        v = calculate_version(
            current="0.19.3-next.1",
            bump_type="none",
            prerelease="alpha",
            latest_stable=None,
            existing_tags=[],
            tag_prefix="iii-alpha",
        )
        assert v == "0.19.3-alpha.1"

    def test_requires_a_prerelease_label(self):
        with pytest.raises(ValueError, match="requires a prerelease"):
            calculate_version(
                current="0.19.3-next.1",
                bump_type="none",
                prerelease="none",
                latest_stable="0.19.2",
                existing_tags=[],
                tag_prefix="iii-alpha",
            )

    # -- create-tag: none continues an in-flight train (the fix) --

    def test_none_iterates_inflight_next_train(self):
        # 0.19.5-next.1 already exists above stable 0.19.4 → none iterates it
        # instead of re-bumping to 0.19.6 (the original release bug).
        v = calculate_version(
            current="0.19.5-next.1",
            bump_type="none",
            prerelease="next",
            latest_stable="0.19.4",
            existing_tags=["iii/v0.19.4", "iii/v0.19.5-next.1"],
            tag_prefix="iii",
        )
        assert v == "0.19.5-next.2"

    def test_none_picks_highest_inflight_base(self):
        v = calculate_version(
            current="0.20.0-next.1",
            bump_type="none",
            prerelease="next",
            latest_stable="0.19.4",
            existing_tags=[
                "iii/v0.19.4",
                "iii/v0.19.5-next.1",
                "iii/v0.20.0-next.1",
            ],
            tag_prefix="iii",
        )
        assert v == "0.20.0-next.2"

    def test_none_shares_base_across_channels(self):
        # A next train set the base; switching to rc via none keeps the base.
        v = calculate_version(
            current="0.19.5-next.2",
            bump_type="none",
            prerelease="rc",
            latest_stable="0.19.4",
            existing_tags=["iii/v0.19.4", "iii/v0.19.5-next.1", "iii/v0.19.5-next.2"],
            tag_prefix="iii",
        )
        assert v == "0.19.5-rc.1"

    def test_none_ignores_train_at_or_below_stable(self):
        # alpha case: every prerelease sits at the current stable, so none
        # anchors on the stable rather than treating it as in-flight.
        v = calculate_version(
            current="0.19.4-alpha.2",
            bump_type="none",
            prerelease="alpha",
            latest_stable="0.19.4",
            existing_tags=[
                "iii-alpha/v0.19.4-alpha.1",
                "iii-alpha/v0.19.4-alpha.2",
            ],
            tag_prefix="iii-alpha",
        )
        assert v == "0.19.4-alpha.3"

    def test_none_inflight_scan_is_prefix_scoped(self):
        # An in-flight iii/ next train must not leak into an iii-alpha run.
        v = calculate_version(
            current="0.19.5-next.1",
            bump_type="none",
            prerelease="alpha",
            latest_stable="0.19.4",
            existing_tags=["iii/v0.19.4", "iii/v0.19.5-next.1"],
            tag_prefix="iii-alpha",
        )
        assert v == "0.19.4-alpha.1"

    def test_full_release_sequence_with_none_iteration(self):
        """The exact flow the user wants: patch starts the train, none iterates,
        promotion lands the intended patch (0.19.5, not 0.19.6)."""
        tags = ["iii/v0.19.4"]
        stable = "0.19.4"

        def step(current, bump, pre):
            result = calculate_version(current, bump, pre, stable, tags, "iii")
            tags.append(f"iii/v{result}")
            return result

        assert step("0.19.4", "patch", "next") == "0.19.5-next.1"  # start train
        assert step("0.19.5-next.1", "none", "next") == "0.19.5-next.2"  # iterate
        assert step("0.19.5-next.2", "none", "next") == "0.19.5-next.3"  # iterate
        assert step("0.19.5-next.3", "patch", "none") == "0.19.5"  # promote

```

## /.github/scripts/test_collect_engine_worker_interface.py

```py path="/.github/scripts/test_collect_engine_worker_interface.py" 
"""Unit tests for collect_engine_worker_interface.py.

Run with: python -m pytest .github/scripts/test_collect_engine_worker_interface.py -v
"""
from __future__ import annotations

import pytest

import collect_engine_worker_interface as collect


def _fake_run_iii(calls: list[dict[str, object]]):
    def fake(function_path: str, payload: dict[str, object]) -> dict[str, object]:
        assert function_path == "engine::functions::info"
        calls.append(payload)
        ids = payload["function_ids"]
        return {"functions": [{"function_id": fn_id} for fn_id in ids]}

    return fake


def test_collects_details_in_one_batch(monkeypatch: pytest.MonkeyPatch) -> None:
    calls: list[dict[str, object]] = []
    monkeypatch.setattr(collect, "run_iii", _fake_run_iii(calls))

    details = collect.collect_function_details(["a", "b", "c"])

    assert calls == [{"function_ids": ["a", "b", "c"]}]
    assert [d["function_id"] for d in details] == ["a", "b", "c"]


def test_chunks_batches_at_engine_limit(monkeypatch: pytest.MonkeyPatch) -> None:
    calls: list[dict[str, object]] = []
    monkeypatch.setattr(collect, "run_iii", _fake_run_iii(calls))
    ids = [f"fn-{i}" for i in range(collect.FUNCTIONS_INFO_BATCH_MAX + 1)]

    details = collect.collect_function_details(ids)

    assert len(calls) == 2
    assert calls[0]["function_ids"] == ids[: collect.FUNCTIONS_INFO_BATCH_MAX]
    assert calls[1]["function_ids"] == ids[collect.FUNCTIONS_INFO_BATCH_MAX :]
    assert [d["function_id"] for d in details] == ids


def test_no_ids_makes_no_calls(monkeypatch: pytest.MonkeyPatch) -> None:
    calls: list[dict[str, object]] = []
    monkeypatch.setattr(collect, "run_iii", _fake_run_iii(calls))

    assert collect.collect_function_details([]) == []
    assert calls == []


def test_per_item_error_marker_fails_collection(monkeypatch: pytest.MonkeyPatch) -> None:
    def fake(function_path: str, payload: dict[str, object]) -> dict[str, object]:
        return {
            "functions": [
                {"function_id": "a"},
                {"function_id": "b", "error": "not_found"},
            ]
        }

    monkeypatch.setattr(collect, "run_iii", fake)

    with pytest.raises(RuntimeError, match="'b': not_found"):
        collect.collect_function_details(["a", "b"])


def test_malformed_envelope_fails_collection(monkeypatch: pytest.MonkeyPatch) -> None:
    monkeypatch.setattr(collect, "run_iii", lambda *_: {"function_id": "a"})

    with pytest.raises(RuntimeError, match="missing `functions` array"):
        collect.collect_function_details(["a"])

```

## /.github/scripts/test_pin_docs.py

```py path="/.github/scripts/test_pin_docs.py" 
"""Unit tests for pin_docs.py.

Run with: python -m pytest .github/scripts/test_pin_docs.py -v
"""
from __future__ import annotations

import json
from pathlib import Path

import pytest

from pin_docs import add_prefix
from pin_docs import copy_root_to_dir
from pin_docs import dir_prefix
from pin_docs import find_index_by_tag
from pin_docs import is_excluded
from pin_docs import minor_label
from pin_docs import next_minor
from pin_docs import parse_version
from pin_docs import replace_root_with_dir
from pin_docs import rotate
from pin_docs import sort_versions
from pin_docs import strip_prefix
from pin_docs import sync_patch
from pin_docs import validate


class TestParseVersion:
    def test_stable(self):
        assert parse_version("0.17.0") == (0, 17, 0)

    def test_prerelease_suffix_ignored(self):
        assert parse_version("1.0.0-next.5") == (1, 0, 0)

    def test_dry_run_suffix_ignored(self):
        assert parse_version("0.17.0-dry-run.2") == (0, 17, 0)

    def test_rejects_garbage(self):
        with pytest.raises(ValueError):
            parse_version("nope")


class TestLabelPrefix:
    def test_minor_label(self):
        assert minor_label(0, 17) == "0.17.x"
        assert minor_label(1, 0) == "1.0.x"

    def test_dir_prefix(self):
        assert dir_prefix(0, 17) == "0-17-0"
        assert dir_prefix(1, 0) == "1-0-0"

    def test_next_minor(self):
        assert next_minor("0.17.0") == (0, 18)
        assert next_minor("1.0.0") == (1, 1)
        assert next_minor("0.17.0-next.1") == (0, 18)


def _tabs(*pages):
    return [{"tab": "Docs", "groups": [
        {"group": "G", "pages": list(pages)},
        {"group": "Nested", "pages": [{"group": "Sub", "pages": ["how-to/a"]}]},
    ]}]


class TestAddStripPrefix:
    def test_add_prefix(self):
        out = add_prefix(_tabs("index", "install"), "next")
        assert out[0]["groups"][0]["pages"] == ["next/index", "next/install"]
        assert out[0]["groups"][1]["pages"][0]["pages"] == ["next/how-to/a"]

    def test_strip_prefix(self):
        prefixed = add_prefix(_tabs("index"), "next")
        out = strip_prefix(prefixed, "next")
        assert out[0]["groups"][0]["pages"] == ["index"]
        assert out[0]["groups"][1]["pages"][0]["pages"] == ["how-to/a"]

    def test_add_does_not_mutate_input(self):
        tabs = _tabs("index")
        add_prefix(tabs, "next")
        assert tabs[0]["groups"][0]["pages"] == ["index"]

    def test_strip_only_removes_matching(self):
        out = strip_prefix(_tabs("index"), "next")
        assert out[0]["groups"][0]["pages"] == ["index"]

    def test_add_prefix_keeps_shared_changelog_at_root(self):
        tabs = [{"tab": "D", "groups": [{"group": "G", "pages": [
            "using-iii/workers", "changelog/index", "changelog/0-11-0/x",
        ]}]}]
        out = add_prefix(tabs, "0-16-0")
        assert out[0]["groups"][0]["pages"] == [
            "0-16-0/using-iii/workers", "changelog/index", "changelog/0-11-0/x",
        ]


class TestFindIndexByTag:
    def test_finds(self):
        versions = [{"tag": "Latest"}, {"tag": "Next"}, {}]
        assert find_index_by_tag(versions, "Next") == 1
        assert find_index_by_tag(versions, "Latest") == 0

    def test_raises_when_absent(self):
        with pytest.raises(ValueError):
            find_index_by_tag([{"tag": "Latest"}], "Next")


class TestSortVersions:
    def test_order(self):
        versions = [
            {"version": "0.12.x"},
            {"version": "0.16.x", "tag": "Latest", "default": True},
            {"version": "0.10.x"},
            {"version": "0.17.x", "tag": "Next"},
        ]
        out = sort_versions(versions)
        assert [v["version"] for v in out] == ["0.17.x", "0.16.x", "0.12.x", "0.10.x"]
        assert out[0]["tag"] == "Next"
        assert out[1]["tag"] == "Latest"

    def test_double_digit_numeric(self):
        out = sort_versions([{"version": "0.2.x"}, {"version": "0.10.x"}])
        assert [v["version"] for v in out] == ["0.10.x", "0.2.x"]


class TestIsExcluded:
    @pytest.mark.parametrize("name", [
        "docs.json", "package.json", "node_modules", "custom.css",
        "navbar-counters.js", ".gitignore", ".mintignore", ".prettierrc",
        "README.md", "0-11-0", "1-0-0", "index.mdx.skill.md", "next", "changelog",
    ])
    def test_excluded(self, name):
        assert is_excluded(name) is True

    @pytest.mark.parametrize("name", [
        "index.mdx", "using-iii", "assets", "images",
    ])
    def test_included(self, name):
        assert is_excluded(name) is False


def _make_root(tmp_path: Path) -> Path:
    docs = tmp_path / "docs"
    docs.mkdir()
    (docs / "index.mdx").write_text("# Home latest")
    (docs / "index.mdx.skill.md").write_text("sidecar")
    (docs / "docs.json").write_text("{}")
    (docs / ".gitignore").write_text("node_modules/")
    (docs / "using-iii").mkdir()
    (docs / "using-iii" / "workers.mdx").write_text("# Workers")
    return docs


class TestCopyRootToDir:
    def test_copies_content_excludes_infra(self, tmp_path):
        docs = _make_root(tmp_path)
        copy_root_to_dir(docs, "0-16-0")
        pinned = docs / "0-16-0"
        assert (pinned / "index.mdx").read_text() == "# Home latest"
        assert (pinned / "using-iii" / "workers.mdx").exists()
        assert not (pinned / "docs.json").exists()
        assert not (pinned / ".gitignore").exists()
        assert not (pinned / "index.mdx.skill.md").exists()

    def test_does_not_copy_next_folder(self, tmp_path):
        docs = _make_root(tmp_path)
        (docs / "next").mkdir()
        (docs / "next" / "index.mdx").write_text("# Next")
        copy_root_to_dir(docs, "0-16-0")
        assert not (docs / "0-16-0" / "next").exists()

    def test_overwrites_existing(self, tmp_path):
        docs = _make_root(tmp_path)
        (docs / "0-16-0").mkdir()
        (docs / "0-16-0" / "stale.mdx").write_text("old")
        copy_root_to_dir(docs, "0-16-0")
        assert not (docs / "0-16-0" / "stale.mdx").exists()


class TestReplaceRootWithDir:
    def test_replaces_content_keeps_infra_and_next(self, tmp_path):
        docs = _make_root(tmp_path)
        nxt = docs / "next"
        nxt.mkdir()
        (nxt / "index.mdx").write_text("# Home next")
        (nxt / "newpage.mdx").write_text("# New")
        replace_root_with_dir(docs, "next")
        assert (docs / "index.mdx").read_text() == "# Home next"
        assert (docs / "newpage.mdx").exists()
        assert not (docs / "using-iii").exists()
        assert (docs / "docs.json").exists()
        assert (docs / ".gitignore").exists()
        assert (docs / "next" / "index.mdx").exists()


def _write_docs(docs: Path, versions):
    (docs / "docs.json").write_text(json.dumps({"navigation": {"versions": versions}}, indent=2))


def _ready_docs(tmp_path: Path) -> Path:
    """root = Latest 0.16.x; docs/next/ = Next (label 0.17.x)."""
    docs = tmp_path / "docs"
    docs.mkdir()
    (docs / "index.mdx").write_text("# Latest 0.16")
    nxt = docs / "next"
    nxt.mkdir()
    (nxt / "index.mdx").write_text("# Next")
    _write_docs(docs, [
        {"version": "0.16.x", "tag": "Latest", "default": True,
         "tabs": [{"tab": "D", "groups": [{"group": "G", "pages": ["index"]}]}]},
        {"version": "0.17.x", "tag": "Next",
         "tabs": [{"tab": "D", "groups": [{"group": "G", "pages": ["next/index"]}]}]},
    ])
    return docs


class TestValidate:
    def test_ok_when_next_block_and_folder_present(self, tmp_path):
        assert validate(_ready_docs(tmp_path)) == 0

    def test_fails_when_folder_missing(self, tmp_path):
        docs = _ready_docs(tmp_path)
        import shutil as _sh
        _sh.rmtree(docs / "next")
        assert validate(docs) == 1

    def test_fails_when_folder_empty(self, tmp_path):
        docs = _ready_docs(tmp_path)
        import shutil as _sh
        _sh.rmtree(docs / "next")
        (docs / "next").mkdir()
        assert validate(docs) == 1

    def test_fails_when_no_next_block(self, tmp_path):
        docs = tmp_path / "docs"
        docs.mkdir()
        (docs / "next").mkdir()
        (docs / "next" / "index.mdx").write_text("x")
        _write_docs(docs, [{"version": "0.16.x", "tag": "Latest"}])
        assert validate(docs) == 1


def _read_versions(docs: Path):
    return json.loads((docs / "docs.json").read_text())["navigation"]["versions"]


class TestRotate:
    def test_rotation_0_17_0(self, tmp_path):
        docs = _ready_docs(tmp_path)  # root=Latest 0.16.x; next/=Next 0.17.x
        rotate(docs, "0.17.0")

        assert (docs / "0-16-0" / "index.mdx").read_text() == "# Latest 0.16"
        assert (docs / "index.mdx").read_text() == "# Next"
        assert (docs / "next" / "index.mdx").read_text() == "# Next"

        versions = _read_versions(docs)
        by_tag = {v.get("tag"): v for v in versions}
        assert by_tag["Latest"]["version"] == "0.17.x"
        assert by_tag["Latest"]["tabs"][0]["groups"][0]["pages"] == ["index"]
        assert by_tag["Next"]["version"] == "0.18.x"
        assert by_tag["Next"]["tabs"][0]["groups"][0]["pages"] == ["next/index"]
        archived = [v for v in versions if v.get("tag") not in ("Latest", "Next")]
        old = [v for v in archived if v["version"] == "0.16.x"][0]
        assert old["tabs"][0]["groups"][0]["pages"] == ["0-16-0/index"]

        assert versions[0]["tag"] == "Next"
        assert versions[1]["tag"] == "Latest"
        assert sum(1 for v in versions if v.get("default")) == 1

    def test_changelog_stays_shared_at_root(self, tmp_path):
        docs = tmp_path / "docs"
        docs.mkdir()
        (docs / "index.mdx").write_text("# Latest 0.16")
        (docs / "changelog").mkdir()
        (docs / "changelog" / "index.mdx").write_text("# changelog")
        nxt = docs / "next"
        nxt.mkdir()
        (nxt / "index.mdx").write_text("# Next")
        _write_docs(docs, [
            {"version": "0.16.x", "tag": "Latest", "default": True,
             "tabs": [{"tab": "D", "groups": [{"group": "G", "pages": ["index"]}]},
                      {"tab": "Changelog", "groups": [{"group": "C", "pages": ["changelog/index"]}]}]},
            {"version": "0.17.x", "tag": "Next",
             "tabs": [{"tab": "D", "groups": [{"group": "G", "pages": ["next/index"]}]},
                      {"tab": "Changelog", "groups": [{"group": "C", "pages": ["changelog/index"]}]}]},
        ])
        rotate(docs, "0.17.0")
        # Changelog folder never copied into the archive.
        assert not (docs / "0-16-0" / "changelog").exists()
        # Shared changelog still at the root.
        assert (docs / "changelog" / "index.mdx").exists()
        # Every block's changelog tab points at the root changelog.
        for block in _read_versions(docs):
            cl = [t for t in block["tabs"] if t.get("tab") == "Changelog"][0]
            assert cl["groups"][0]["pages"] == ["changelog/index"]

    def test_patch_version_delegates_to_sync(self, tmp_path):
        docs = _ready_docs(tmp_path)  # root=Latest 0.16.x; next/=Next 0.17.x
        before = (docs / "docs.json").read_text()
        rotate(docs, "0.16.1")  # patch -> sync, not rotation
        # No archive folder, docs.json version blocks unchanged.
        assert not (docs / "0-16-0").exists()
        assert (docs / "docs.json").read_text() == before
        # Root content refreshed from next/.
        assert (docs / "index.mdx").read_text() == "# Next"

    def test_rerun_same_version_is_idempotent(self, tmp_path):
        docs = _ready_docs(tmp_path)
        rotate(docs, "0.17.0")
        after_first = (docs / "docs.json").read_text()
        rotate(docs, "0.17.0")  # re-run must be a no-op
        assert (docs / "docs.json").read_text() == after_first
        versions = _read_versions(docs)
        assert sum(1 for v in versions if v["version"] == "0.17.x") == 1
        assert sum(1 for v in versions if v.get("tag") == "Latest") == 1

    def test_major_release_uses_tag_and_minor_plus_one(self, tmp_path):
        docs = tmp_path / "docs"
        docs.mkdir()
        (docs / "index.mdx").write_text("# Latest 0.17")
        nxt = docs / "next"
        nxt.mkdir()
        (nxt / "index.mdx").write_text("# Next 0.18")
        _write_docs(docs, [
            {"version": "0.17.x", "tag": "Latest", "default": True,
             "tabs": [{"tab": "D", "groups": [{"group": "G", "pages": ["index"]}]}]},
            {"version": "0.18.x", "tag": "Next",
             "tabs": [{"tab": "D", "groups": [{"group": "G", "pages": ["next/index"]}]}]},
        ])
        rotate(docs, "1.0.0")
        assert (docs / "0-17-0" / "index.mdx").exists()
        assert (docs / "index.mdx").read_text() == "# Next 0.18"
        by_tag = {v.get("tag"): v for v in _read_versions(docs)}
        assert by_tag["Latest"]["version"] == "1.0.x"
        assert by_tag["Next"]["version"] == "1.1.x"
        assert by_tag["Next"]["tabs"][0]["groups"][0]["pages"] == ["next/index"]

    def test_relative_links_survive_move(self, tmp_path):
        # In-content links are version-relative, so rotation moves files verbatim
        # without rewriting them; cross-version/shared absolute links are untouched.
        docs = tmp_path / "docs"
        docs.mkdir()
        (docs / "using-iii").mkdir()
        (docs / "using-iii" / "workers.mdx").write_text("# root workers")
        (docs / "index.mdx").write_text(
            "See [workers](./using-iii/workers) and [cl](/changelog/x)."
        )
        nxt = docs / "next"
        (nxt / "using-iii").mkdir(parents=True)
        (nxt / "using-iii" / "workers.mdx").write_text("# next workers")
        (nxt / "index.mdx").write_text(
            "See [workers](./using-iii/workers) and [old](/0-11-0/gone)."
        )
        _write_docs(docs, [
            {"version": "0.16.x", "tag": "Latest", "default": True,
             "tabs": [{"tab": "D", "groups": [{"group": "G",
                "pages": ["index", "using-iii/workers"]}]}]},
            {"version": "0.17.x", "tag": "Next",
             "tabs": [{"tab": "D", "groups": [{"group": "G",
                "pages": ["next/index", "next/using-iii/workers"]}]}]},
        ])
        rotate(docs, "0.17.0")

        # Archived old Latest: relative link intact, shared absolute untouched.
        archived = (docs / "0-16-0" / "index.mdx").read_text()
        assert "](./using-iii/workers)" in archived
        assert "(/changelog/x)" in archived
        # Promoted Latest (root): next content moved verbatim (relative survives).
        root_index = (docs / "index.mdx").read_text()
        assert "](./using-iii/workers)" in root_index
        assert "(/0-11-0/gone)" in root_index


class TestSyncPatch:
    def test_refreshes_latest_without_rotation(self, tmp_path):
        docs = tmp_path / "docs"
        docs.mkdir()
        (docs / "index.mdx").write_text("# old latest")
        nxt = docs / "next"
        (nxt / "using-iii").mkdir(parents=True)
        (nxt / "using-iii" / "workers.mdx").write_text("# w")
        (nxt / "index.mdx").write_text("# next [w](./using-iii/workers)")
        _write_docs(docs, [
            {"version": "0.17.x", "tag": "Latest", "default": True,
             "tabs": [{"tab": "D", "groups": [{"group": "G", "pages": ["index"]}]}]},
            {"version": "0.18.x", "tag": "Next",
             "tabs": [{"tab": "D", "groups": [{"group": "G",
                "pages": ["next/index", "next/using-iii/workers"]}]}]},
        ])
        before = (docs / "docs.json").read_text()
        sync_patch(docs)

        # Root refreshed from next/ verbatim (relative link survives the move).
        root_index = (docs / "index.mdx").read_text()
        assert "# old latest" not in root_index
        assert "](./using-iii/workers)" in root_index
        # Next folder untouched.
        assert "](./using-iii/workers)" in (docs / "next" / "index.mdx").read_text()
        # No archive folder, and docs.json version blocks unchanged.
        assert not (docs / "0-17-0").exists()
        assert (docs / "docs.json").read_text() == before

```

## /.github/scripts/validate_release_worker_matrix.py

```py path="/.github/scripts/validate_release_worker_matrix.py" 
#!/usr/bin/env python3
"""Validate release-iii publish-builtin-workers matrix against worker manifests.

Checks that every matrix entry points at an engine worker manifest and that
registry slugs (manifest ``name``) stay aligned with what skill discovery emits.
Matrix ``worker`` values must remain the engine config / runtime names used by
``_publish-engine-workers.yml`` when reloading config.yaml.
"""
from __future__ import annotations

import argparse
import pathlib
import re
import sys

import yaml

sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent))
from discover_engine_worker_skills import discover  # noqa: E402

_MATRIX_BLOCK_RE = re.compile(
    r"publish-builtin-workers:.*?matrix:\s*\n\s*include:(.*?)(?:\n\s{4}\w|\n\s{2}\w|\Z)",
    re.DOTALL,
)
_MATRIX_ENTRY_RE = re.compile(
    r"- worker: (?P<worker>.+)\n\s+worker_dir: (?P<worker_dir>.+)"
)


def _load_matrix(repo_root: pathlib.Path) -> list[dict[str, str]]:
    workflow = (repo_root / ".github/workflows/release-iii.yml").read_text(encoding="utf-8")
    block = _MATRIX_BLOCK_RE.search(workflow)
    if not block:
        raise ValueError("could not find publish-builtin-workers matrix in release-iii.yml")
    return [
        {"worker": m.group("worker").strip(), "worker_dir": m.group("worker_dir").strip()}
        for m in _MATRIX_ENTRY_RE.finditer(block.group(1))
    ]


def validate(repo_root: pathlib.Path) -> list[str]:
    errors: list[str] = []
    matrix = _load_matrix(repo_root)
    discovered = {entry["worker_dir"]: entry["slug"] for entry in discover(repo_root)}

    for entry in matrix:
        worker = entry["worker"]
        worker_dir = entry["worker_dir"]
        manifest_path = repo_root / worker_dir / "iii.worker.yaml"
        if not manifest_path.is_file():
            errors.append(f"{worker_dir}: missing iii.worker.yaml for matrix worker {worker!r}")
            continue

        meta = yaml.safe_load(manifest_path.read_text(encoding="utf-8")) or {}
        if meta.get("type") != "engine":
            errors.append(
                f"{manifest_path}: type must be 'engine' (got {meta.get('type')!r})"
            )

        registry_name = meta.get("name")
        if not isinstance(registry_name, str) or not registry_name.strip():
            errors.append(f"{manifest_path}: missing or empty name field")
            continue

        registry_name = registry_name.strip()
        if worker_dir in discovered and discovered[worker_dir] != registry_name:
            errors.append(
                f"{worker_dir}: discover slug {discovered[worker_dir]!r} != "
                f"manifest name {registry_name!r}"
            )

    return errors


def main() -> int:
    parser = argparse.ArgumentParser()
    parser.add_argument("--repo-root", default=".", help="Repository root (default: cwd).")
    args = parser.parse_args()

    repo_root = pathlib.Path(args.repo_root).resolve()
    errors = validate(repo_root)
    if errors:
        for err in errors:
            print(f"::error::{err}", file=sys.stderr)
        return 1

    print("::notice::release worker matrix validation passed")
    return 0


if __name__ == "__main__":
    sys.exit(main())

```

## /.github/workflows/WORKFLOWS.md

# CI/CD Workflows

## Overview

The workflows are organized into two categories:

- **Top-level workflows** — triggered by events (push, PR, tag, manual dispatch)
- **Reusable workflows** — prefixed with `_`, called by top-level workflows via `workflow_call`

```text
                ┌──────────────┐
                │  create-tag  │  (manual dispatch)
                └──────┬───────┘
                       │ creates git tag
                       ▼
        ┌──────────────────────────────┐
        │      Tag push triggers       │
        ├──────────────────────────────┤
        │  iii/v*                      │
        ▼                              │
   release-iii                         │
        │                              │
        │   ┌──────────────────┐       │
        │   │  _npm.yml        │       │
        │   │  _py.yml         │       │
        │   │  _rust-cargo.yml │       │
        │   │  _rust-binary.yml│       │
        │   │  _homebrew.yml   │       │
        │   └──────────────────┘       │
        │     (reusable workflows)     │
        └──────────────────────────────┘

   ci.yml ◄── push to main / PRs
   docker-engine.yml ◄── called by release-iii / manual
   license-check.yml ◄── push to main / PRs
   checklist-checker.yml ◄── PR license agreement / comments

   alpha-release ◄── manual dispatch from a feature branch
        │  bumps + tags iii-alpha/v* (isolated; never touches main)
        ▼
        ├─► sdk-node (pnpm) / _py / _rust-cargo / _go   (SDK packages)
        ├─► _rust-binary.yml + init-build job            (engine/worker/init binaries → iii-alpha prerelease)
        └─► _publish-engine-workers / -skills            (builtin workers → `alpha` registry tag)
```

---

## Top-Level Workflows

### `ci.yml` — Continuous Integration

**Triggers:** push to `main`, pull requests to `main`, manual dispatch

Runs the full test suite across the monorepo. Cancels in-progress runs for PRs.

| Job | Depends On | What it does |
|-----|-----------|--------------|
| `changes` | — | Detects changed paths (engine/crates/Cargo) for scoping downstream jobs |
| `engine-build` | — | Builds debug `iii` with all features, uploads `iii-binary` artifact (critical path) |
| `engine-test` | — | Tests `iii-worker`, `iii-filesystem`, `iii-network`, `iii-init`, and `iii --all-features` |
| `engine-coverage` | `changes` | `cargo llvm-cov` on `iii --all-features`. PRs: only when engine paths change. Push/dispatch: always |
| `engine-benches` | — | `cargo bench --benches --no-run` to verify benches compile |
| `engine-fmt` | — | `cargo fmt --all -- --check` |
| `engine-build-matrix` | — | Cross-platform build validation (macOS, Windows, Linux, musl) |
| `sdk-node-ci` | `engine-build` | Type check, build, start engine, run SDK tests |
| `sdk-python-ci` | `engine-build` | Lint (ruff), type check (mypy), start engine, run pytest. Matrix: Python 3.10/3.11/3.12 |
| `sdk-rust-ci` | `engine-build` | Fmt, clippy, start engine, run cargo tests |
| `sdk-go-ci` | `engine-build` | gofmt, vet, race unit tests, start engine, run `-tags integration` tests |
| `console-ci` | — | Lint + build frontend (Node 22), build console Rust binary |

All SDK tests download the engine binary artifact and start a live engine instance before running.

---

### `create-tag.yml` — Version Bump & Tag Creation

**Triggers:** manual dispatch only

Entry point for all releases. Provides a form with:

| Input | Options |
|-------|---------|
| `target` | `iii` |
| `bump` | `patch`, `minor`, `major` |
| `prerelease` | `none`, `alpha`, `beta`, `rc`, `next` |
| `dry_run` | boolean |

**What it does:**

1. Validates it's running on `main` and all required manifest files exist
2. Reads the current version from the canonical manifest
3. Calculates the next version (handles semver bump + prerelease labels + dry-run suffixes)
4. **Stable releases only** — validates docs are ready (`pin_docs.py validate`): `docs/docs.json` must have a `Next` block and the `docs/next/` folder must be non-empty (stable releases pull their docs from `docs/next/`). If not, the workflow posts a Slack alert and aborts **before** bumping or tagging. Runs even on dry runs.
5. Converts to PEP 440 format for Python packages (e.g., `1.0.0-alpha.1` becomes `1.0.0a1`)
6. Updates all manifest files in lockstep (Cargo.toml, package.json, pyproject.toml)
7. Updates docs from `docs/next/` on stable releases (`pin_docs.py rotate`, which dispatches on the version):
   - **minor/major** — rotates: archives the old Latest into `docs/OLD-MINOR-0/` (its `Latest` block becomes archived), promotes `docs/next/` into the root as a new `Latest` block labeled with the **tag version** (the official version comes from the tag and can be anything), relabels the `Next` block to `MINOR + 1` (reusing the `docs/next/` folder), and reorders the dropdown (Next, Latest, archived newest-first — Mintlify's own ordering does not work).
   - **patch** — syncs in place: replaces the root content with `docs/next/`. No archive, no `Next` bump, no version-block changes — it just refreshes the current Latest's docs.
   - **all prereleases** (`alpha`/`beta`/`rc`/`next`) leave docs untouched.
   - In-content links are version-relative, so files move verbatim; only `docs.json` nav paths carry the version prefix.
8. Commits the version bump (including any docs changes), creates an annotated tag, and pushes both
9. Posts a Slack notification

> **Docs layout:** `Latest` lives at the docs root (unprefixed paths); `Next` lives in the fixed `docs/next/` folder; archived versions live in `docs/MAJOR-MINOR-0/` folders. `docs/changelog/` is shared by all versions — it stays at the root, is never copied into a version folder, and every version's Changelog tab points at it. Rotation assumes this shape already exists (a `Latest` root block + a `Next` block pointing at `docs/next/`).

The tag push then triggers the corresponding release workflow.

**Tag format:** `{target}/v{version}` (e.g., `iii/v1.2.3`)

---

### `alpha-release.yml` — Isolated Per-Branch Alpha

**Triggers:** manual dispatch only — run from a feature branch via "Use workflow from: `<branch>`"

Publishes an alpha prerelease of every SDK (npm, pypi, crates, go), the engine binaries, and the builtin workers **from any feature branch, without touching `main`**. Built for testing a branch end-to-end before merging.

| Input | Options |
|-------|---------|
| `dry_run` | boolean (build + validate, no upload; still pushes the alpha tag) |

**What it does:**

1. Refuses to run on `main` (use `create-tag.yml` for official releases)
2. Calculates the version with `calculate_release_version.py --bump none --counter-tag-prefix iii-alpha`: anchors on the latest stable `iii/v*` tag and appends an accumulating `-alpha.N` suffix (`0.19.2-alpha.1`, `.2`, `.3` …). The official version is never advanced.
3. Bumps all manifests in lockstep (Cargo.toml, package.json, pyproject.toml, **Go `sdkVersion` const**) into an **ephemeral commit**
4. Pushes **only** the `iii-alpha/v{version}` tag — never a branch, never `main`
5. Publishes, all checking out that tag:
   - **SDK packages** — an inline `sdk-node` job (single `pnpm -r publish` over the three node packages) plus `_py.yml`, `_rust-cargo.yml`, `_go.yml`
   - **Engine binaries** — `iii` and `iii-worker` via `_rust-binary.yml`, and `iii-init` via an inline `init-build` job; all attached to a GitHub **prerelease** on the `iii-alpha/v*` tag
   - **Builtin workers + skills** — `_publish-engine-workers.yml` / `_publish-worker-skills.yml` published to the workers registry under a dedicated **`alpha`** tag (never `next`/`latest`)

**Isolation:** the `iii-alpha/v*` namespace does not match `release-iii.yml`'s `iii/v*` trigger, so the official pipeline never fires. Engine binaries land on a separate prerelease (own tag namespace); workers use the dedicated `alpha` registry tag — neither collides with the official `iii/v*` releases or the `next`/`latest` channels. **Console, docker and homebrew are intentionally excluded.**

**Engine install:** because the binaries live under `iii-alpha/v*`, install them with the `III_RELEASE_TAG` override on `install.sh`, e.g. `III_RELEASE_TAG=iii-alpha/v0.19.2-alpha.1 curl -fsSL https://iii.dev/install.sh | sh`. The worker-publish job uses the same override to pin the engine CLI.

**Tag format:** `iii-alpha/v{version}` (e.g., `iii-alpha/v0.19.2-alpha.1`)

---

### `release-iii.yml` — iii Release Pipeline

**Triggers:** tag push matching `iii/v*`

Orchestrates the full iii release across all package registries and distribution channels.

```text
setup (parse tag metadata, Slack notification)
  │
  ├─► create-iii-release (GitHub Release with auto-generated notes)
  │     │
  │     ├─► engine-release ──────► _rust-binary.yml (9 platform targets)
  │     │     │
  │     │     ├─► docker ────────► docker-engine.yml (pre-built binaries, no compilation)
  │     │     │
  │     │     └─► homebrew-engine ► _homebrew.yml (stable only)
  │     │
  │     ├─► console-frontend ───► Build React frontend for embedding
  │     │     │
  │     │     └─► console-release ► _rust-binary.yml (with embedded frontend)
  │     │           │
  │     │           └─► homebrew-console ► _homebrew.yml (stable only)
  │     │
  │     ├─► sdk-npm ─────────────► _npm.yml
  │     ├─► sdk-py ──────────────► _py.yml
  │     ├─► sdk-rust ────────────► _rust-cargo.yml
  │     └─► sdk-go ──────────────► _go.yml (pushes subdir-scoped module tag)
  │
  ├─► publish-builtin-workers ► _publish-engine-workers.yml
  └─► publish-worker-skills ► _publish-worker-skills.yml
  │
  ├─► trigger-validations (dispatch downstream smoke/quickstart on success)
  │
  └─► notify-complete (aggregated Slack status)
```

**Downstream validations:** once every publish job succeeds (non-dry-run), `trigger-validations` dispatches `init-smoke.yml` in `iii-hq/templates` and `quickstart-validate.yml` in `iii-hq/quickstart-validator`, passing `channel=next` for a prerelease or `channel=main` for a stable release. Both repos report results to their own Slack threads. Requires the `III_CI_APP` GitHub App installed on both repos with `actions: write`.

**Setup job** parses the tag to determine:
- `version` — stripped prefix (e.g., `iii/v1.2.3` becomes `1.2.3`)
- `is_prerelease` — true if version contains a prerelease label
- `npm_tag` — dist-tag for npm (`latest`, `alpha`, `beta`, `rc`, `dry-run`)
- `dry_run` — true if version ends with `-dry-run.N`

**Concurrency:** only one iii release runs at a time per repository.

**Skipped on dry run:** GitHub Release creation, Homebrew publish, downstream validations.

---

### `docker-engine.yml` — Docker Image Build & Publish

**Triggers:** called by `release-iii.yml` after engine binaries are built, or manual dispatch with a release tag

Downloads pre-built binaries from the GitHub Release (no Rust compilation) and packages them into a minimal distroless Docker image.

| Job | Runner | What it does |
|-----|--------|--------------|
| `setup` | `ubuntu-latest` | Parse version from release tag |
| `build` (amd64) | `ubuntu-latest` | Download pre-built binary, build + push image |
| `build` (arm64) | `ubuntu-24.04-arm` | Download pre-built binary, build + push image (native ARM runner) |
| `publish` | `ubuntu-latest` | Create multi-platform manifest, Trivy security scan, push to GHCR + DockerHub |

**Registries:** GHCR (`ghcr.io`) and DockerHub (`iiidev/iii`)

**Security:** Trivy vulnerability scanning (CRITICAL + HIGH), distroless nonroot runtime.

---

### `license-check.yml` — License Header Check

**Triggers:** push to `main`, pull requests to `main`

Uses [hawkeye](https://github.com/korandoru/hawkeye) to verify license headers across source files, configured via `engine/licenserc.toml`.

### `checklist-checker.yml` — License Agreement Check

**Triggers:** `pull_request_target` for pull request changes, `issue_comment` for PR comments

Requires external contributors to acknowledge the Apache 2.0 contributor license agreement before merge. Contributors can satisfy the gate by checking the license box in the PR description or by replying with the exact acknowledgement phrase posted by the bot. iii team members with `write`, `maintain`, or `admin` repository permission are skipped.

The workflow posts a sticky PR comment and publishes the `license-agreement` commit status on the PR head SHA. Branch protection should require the `license-agreement` status context.

---

## Reusable Workflows

All reusable workflows support `dry_run` mode and Slack thread notifications.

### `_npm.yml` — NPM Publish

Publishes a Node.js package to the npm registry.

| Input | Purpose |
|-------|---------|
| `package_path` | Directory containing the package to publish |
| `npm_tag` | dist-tag (`latest`, `alpha`, `beta`, `rc`) |
| `build_filter` | pnpm filter for building the package |
| `pre_build_filter` | pnpm filter for building dependencies first (optional) |

Uses `pnpm publish` with `--no-git-checks` and `--access public`.

### `_py.yml` — PyPI Publish

Publishes a Python package to PyPI.

Builds with `python -m build`, validates with `twine check` on dry run, publishes via `pypa/gh-action-pypi-publish`.

### `_rust-cargo.yml` — Cargo Publish

Publishes a Rust crate to crates.io via `cargo publish`.

### `_go.yml` — Go Module Publish

"Publishes" a Go module by pushing a subdirectory-scoped git tag (`sdk/packages/go/iii/vX.Y.Z`) — Go has no registry, so `go get` resolves the module from the repo via the Go proxy. No token required. Dry run runs `go build/vet/test` and `go mod verify` without tagging.

### `_rust-binary.yml` — Rust Binary Release

Cross-compiles a Rust binary for 9 platform targets and uploads them to a GitHub Release.

**Targets:**

| Platform | Runner |
|----------|--------|
| `x86_64-apple-darwin` | `macos-latest` |
| `aarch64-apple-darwin` | `macos-latest` |
| `x86_64-pc-windows-msvc` | `windows-latest` |
| `i686-pc-windows-msvc` | `windows-latest` |
| `aarch64-pc-windows-msvc` | `windows-latest` |
| `x86_64-unknown-linux-gnu` | `ubuntu-22.04` |
| `x86_64-unknown-linux-musl` | `ubuntu-latest` |
| `aarch64-unknown-linux-gnu` | `ubuntu-22.04` |
| `armv7-unknown-linux-gnueabihf` | `ubuntu-22.04` |

Supports downloading a pre-built artifact (used by console to embed the frontend build).

Uses `taiki-e/upload-rust-binary-action` for building and uploading.

### `_homebrew.yml` — Homebrew Formula Publish

Generates and publishes a Homebrew formula to the `iii-hq/homebrew-tap` repository.

1. Downloads release tarballs from GitHub Releases
2. Calculates SHA256 checksums
3. Generates a Ruby formula file with platform-specific URLs
4. Tests the formula locally (`brew audit`, `brew install`, version check)
5. Commits and pushes to the tap repository

Only runs for stable (non-prerelease) versions.

### `_publish-engine-workers.yml` — Publish Builtin Engine Worker

Collects a worker's live interface from a running III engine and POSTs to `POST /publish`. Called by `release-iii.yml` for each builtin engine worker.

### `_publish-worker-skills.yml` — Publish Worker Skills

Discovers worker directories with an `iii.worker.yaml` manifest and a non-empty `skills/` tree (repo-wide, including e.g. `crates/iii-worker/src/sandbox_daemon`), builds payloads via `build_skills_payload.py`, and POSTs to `POST /w/{slug}/skills`. Called by `release-iii.yml` (after builtin worker publish) and by the manual `publish-worker-skills.yml` workflow.

| Input | Purpose |
|-------|---------|
| `registry_tag` | Version tag on the registry (`latest`, `next`) |
| `api_url` | Workers registry base URL |

---

### `publish-worker-skills.yml` — Manual Skills Publish

**Triggers:** `workflow_dispatch` only

Publishes skill markdown for all workers with an `iii.worker.yaml` manifest and a non-empty `skills/` tree. Choose `registry_tag` (`latest` or `next`) at dispatch time.

---

## Secrets

| Secret | Used by |
|--------|---------|
| `III_CI_APP_ID` / `III_CI_APP_PRIVATE_KEY` | GitHub App token for pushing tags, creating releases, updating homebrew-tap |
| `NPM_TOKEN` | npm registry authentication |
| `PYPI_API_TOKEN` | PyPI publishing |
| `CARGO_REGISTRY_TOKEN` | crates.io publishing |
| `DOCKERHUB_USERNAME` / `DOCKERHUB_PASSWORD` | DockerHub publishing |
| `SLACK_BOT_TOKEN` / `SLACK_CHANNEL_ID` | Slack release notifications |
| `SLACK_WEBHOOK_URL` | Slack Docker notifications |
| `WORKERS_REGISTRY_API_KEY` | Workers registry publish (`_publish-engine-workers`, `_publish-worker-skills`) |

---

## Release Flow (End to End)

1. Developer triggers `create-tag` workflow manually, selecting target/bump/prerelease
2. Workflow bumps versions across all manifests, commits, and pushes a tag
3. Tag push triggers the `release-iii` workflow
4. Release workflow fans out to reusable workflows in parallel
5. Each reusable workflow posts progress to a Slack thread
6. Final job aggregates results and updates the parent Slack message with overall status


## /.github/workflows/_go.yml

```yml path="/.github/workflows/_go.yml" 
name: Go Module Publish

# Publishing a Go module is not an upload: there is no registry. A module is "published"
# by pushing a git tag, after which `go get <module>@<version>` resolves it straight from
# the repo via proxy.golang.org. So unlike _npm.yml / _rust-cargo.yml there is no token —
# the only side effect is the tag push, and dry-run runs the full validation without it.
#
# Tag shape (the one hard constraint): the module lives in a subdirectory, so Go requires
# its tag to be PREFIXED with the module path relative to the repo root, i.e.
# `sdk/packages/go/iii/vX.Y.Z`. The repo's release tag `iii/vX.Y.Z` does NOT make a
# subdirectory module resolvable (`go get …@vX.Y.Z` would fail). This job therefore pushes
# its own subdir-scoped tag in lockstep with the engine release (issue iii-hq/iii#1719).

on:
  workflow_call:
    inputs:
      package_path:
        description: 'Path to the Go module (e.g., sdk/packages/go/iii)'
        required: true
        type: string
      module_path:
        description: 'Go module import path (e.g., github.com/iii-hq/iii/sdk/packages/go/iii)'
        required: true
        type: string
      version:
        description: 'Semantic version without the v prefix (e.g., 0.1.0)'
        required: true
        type: string
      ref:
        description: 'Git ref to checkout (default: the triggering ref)'
        required: false
        type: string
        default: ''
      dry_run:
        description: 'Build and validate without pushing the tag'
        required: false
        type: boolean
        default: false
      slack_thread_ts:
        description: 'Slack parent message timestamp for thread replies (optional)'
        required: false
        type: string
        default: ''
      slack_label:
        description: 'Label for this step in Slack notifications (optional)'
        required: false
        type: string
        default: ''
    secrets:
      SLACK_BOT_TOKEN:
        required: false
      SLACK_CHANNEL_ID:
        required: false

jobs:
  publish:
    name: Publish Go module
    runs-on: ubuntu-latest
    permissions:
      contents: write # to push the version tag
    steps:
      - name: Notify Slack — in progress
        if: inputs.slack_thread_ts != ''
        id: slack
        continue-on-error: true
        uses: slackapi/slack-github-action@v2.0.0
        with:
          method: chat.postMessage
          token: ${{ secrets.SLACK_BOT_TOKEN }}
          payload: |
            channel: ${{ secrets.SLACK_CHANNEL_ID }}
            thread_ts: "${{ inputs.slack_thread_ts }}"
            text: ":large_yellow_circle: ${{ inputs.slack_label }}${{ inputs.dry_run == true && ' (dry run)' || '' }} — in progress"

      - uses: actions/checkout@v4
        with:
          fetch-depth: 0 # full history so we can tag
          ref: ${{ inputs.ref }}
          # Don't leave the write-scoped token in git config: the caller
          # controls `ref` and we run go build/test before pushing. Auth is
          # supplied only to the tag-push step below.
          persist-credentials: false

      - uses: actions/setup-go@v5
        with:
          go-version: '1.24'
          cache-dependency-path: ${{ inputs.package_path }}/go.sum

      # Validation — runs in BOTH dry-run and real release.
      - name: Build, vet, test, verify
        working-directory: ${{ inputs.package_path }}
        run: |
          go build ./...
          go vet ./...
          go test ./...
          go mod verify

      # The only side effect — skipped on dry-run. Subdir-scoped tag (see header note).
      - name: Push subdirectory-scoped module tag
        if: ${{ inputs.dry_run == false }}
        env:
          TAG: ${{ inputs.package_path }}/v${{ inputs.version }}
          GH_TOKEN: ${{ github.token }}
        run: |
          if git rev-parse -q --verify "refs/tags/$TAG" >/dev/null; then
            echo "Tag $TAG already exists, nothing to push."
          else
            git tag "$TAG"
            # Auth scoped to this push only (checkout used persist-credentials: false).
            git push "https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" "$TAG"
          fi

      - name: Verify the proxy resolves the published version
        if: ${{ inputs.dry_run == false }}
        env:
          GOPROXY: proxy.golang.org
          GOFLAGS: -mod=mod
          MODULE_PATH: ${{ inputs.module_path }}
          VERSION: ${{ inputs.version }}
        # Pass inputs through quoted env vars rather than interpolating them into the
        # command, and validate the version shape, so a malformed input can't be abused by
        # the shell. The proxy is eventually-consistent right after a tag push, so retry a
        # few times before failing.
        run: |
          if ! printf '%s' "$VERSION" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+([-+][0-9A-Za-z.-]+)?{{contextString}}#39;; then
            echo "Refusing to resolve: invalid version '$VERSION'" >&2
            exit 1
          fi
          for attempt in 1 2 3 4 5; do
            if go list -m "${MODULE_PATH}@v${VERSION}"; then
              exit 0
            fi
            echo "proxy not ready (attempt $attempt), retrying in 10s..." >&2
            sleep 10
          done
          echo "proxy did not resolve ${MODULE_PATH}@v${VERSION} after retries" >&2
          exit 1

      - name: Notify Slack — result
        if: always() && steps.slack.outputs.ts != ''
        continue-on-error: true
        uses: slackapi/slack-github-action@v2.0.0
        with:
          method: chat.update
          token: ${{ secrets.SLACK_BOT_TOKEN }}
          payload: |
            channel: ${{ secrets.SLACK_CHANNEL_ID }}
            ts: "${{ steps.slack.outputs.ts }}"
            text: "${{ job.status == 'success' && ':large_green_circle:' || ':red_circle:' }} ${{ inputs.slack_label }}${{ inputs.dry_run == true && ' (dry run)' || '' }} — ${{ job.status }}"

```

## /.github/workflows/_homebrew.yml

```yml path="/.github/workflows/_homebrew.yml" 
name: Homebrew Publish

on:
  workflow_call:
    inputs:
      bin_name:
        description: 'Binary name (e.g., iii, iii-console)'
        required: true
        type: string
      formula_class:
        description: 'Ruby class name for the formula (e.g., Iii, IiiConsole)'
        required: true
        type: string
      formula_path:
        description: 'Path inside homebrew-tap repo (e.g., Formula/iii.rb)'
        required: true
        type: string
      description:
        description: 'Formula description'
        required: true
        type: string
      homepage:
        description: 'Homepage URL for the formula'
        required: true
        type: string
      release_repo:
        description: 'GitHub repo hosting the release assets (e.g., iii-hq/iii)'
        required: true
        type: string
      release_tag:
        description: 'GitHub release tag for downloading assets (e.g., iii/v1.0.0)'
        required: true
        type: string
      version:
        description: 'Version number without v prefix (e.g., 1.0.0)'
        required: true
        type: string
      include_linux:
        description: 'Whether to include Linux targets in the formula'
        required: false
        type: boolean
        default: false
      dry_run:
        description: 'Run in dry-run mode (skip actual publish)'
        required: false
        type: boolean
        default: false
      slack_thread_ts:
        description: 'Slack parent message timestamp for thread replies (optional)'
        required: false
        type: string
        default: ''
      slack_label:
        description: 'Label for this step in Slack notifications (optional)'
        required: false
        type: string
        default: ''
    secrets:
      III_CI_APP_ID:
        required: true
      III_CI_APP_PRIVATE_KEY:
        required: true
      SLACK_BOT_TOKEN:
        required: false
      SLACK_CHANNEL_ID:
        required: false

env:
  TAP_REPO: iii-hq/homebrew-tap

jobs:
  publish-homebrew:
    name: Update Homebrew Formula
    runs-on: macos-latest
    permissions:
      contents: read
    steps:
      - name: Notify Slack — in progress
        if: inputs.slack_thread_ts != ''
        id: slack
        continue-on-error: true
        uses: slackapi/slack-github-action@v2.0.0
        with:
          method: chat.postMessage
          token: ${{ secrets.SLACK_BOT_TOKEN }}
          payload: |
            channel: ${{ secrets.SLACK_CHANNEL_ID }}
            thread_ts: "${{ inputs.slack_thread_ts }}"
            text: ":large_yellow_circle: ${{ inputs.slack_label }}${{ inputs.dry_run == true && ' (dry run)' || '' }} — in progress"

      - name: Validate version format
        env:
          VERSION: ${{ inputs.version }}
        run: |
          if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
            echo "::error::Invalid version format. Expected: X.Y.Z (got $VERSION)"
            exit 1
          fi
          echo "Version validated: $VERSION"

      - name: Generate token
        id: generate_token
        uses: actions/create-github-app-token@v2
        with:
          app-id: ${{ secrets.III_CI_APP_ID }}
          private-key: ${{ secrets.III_CI_APP_PRIVATE_KEY }}
          owner: iii-hq
          repositories: homebrew-tap
          permission-contents: write

      - name: Checkout tap repository
        uses: actions/checkout@v4
        with:
          repository: ${{ env.TAP_REPO }}
          token: ${{ steps.generate_token.outputs.token }}
          path: homebrew-tap

      - name: Download release assets
        env:
          RELEASE_REPO: ${{ inputs.release_repo }}
          RELEASE_TAG: ${{ inputs.release_tag }}
          BIN_NAME: ${{ inputs.bin_name }}
          INCLUDE_LINUX: ${{ inputs.include_linux }}
        run: |
          BASE_URL="https://github.com/${RELEASE_REPO}/releases/download/${RELEASE_TAG}"

          curl -L --fail -o "${BIN_NAME}-x86_64-apple-darwin.tar.gz" \
            "${BASE_URL}/${BIN_NAME}-x86_64-apple-darwin.tar.gz"
          curl -L --fail -o "${BIN_NAME}-aarch64-apple-darwin.tar.gz" \
            "${BASE_URL}/${BIN_NAME}-aarch64-apple-darwin.tar.gz"

          REQUIRED_FILES="${BIN_NAME}-x86_64-apple-darwin.tar.gz ${BIN_NAME}-aarch64-apple-darwin.tar.gz"

          if [[ "$INCLUDE_LINUX" == "true" ]]; then
            curl -L --fail -o "${BIN_NAME}-x86_64-unknown-linux-gnu.tar.gz" \
              "${BASE_URL}/${BIN_NAME}-x86_64-unknown-linux-gnu.tar.gz"
            curl -L --fail -o "${BIN_NAME}-aarch64-unknown-linux-gnu.tar.gz" \
              "${BASE_URL}/${BIN_NAME}-aarch64-unknown-linux-gnu.tar.gz"
            REQUIRED_FILES="$REQUIRED_FILES ${BIN_NAME}-x86_64-unknown-linux-gnu.tar.gz ${BIN_NAME}-aarch64-unknown-linux-gnu.tar.gz"
          fi

          for file in $REQUIRED_FILES; do
            if [ ! -s "$file" ]; then
              echo "::error::$file is missing or empty"
              exit 1
            fi
          done
          ls -lh *.tar.gz

      - name: Calculate SHA256 checksums
        id: checksums
        env:
          BIN_NAME: ${{ inputs.bin_name }}
          INCLUDE_LINUX: ${{ inputs.include_linux }}
        run: |
          MACOS_X86_SHA=$(shasum -a 256 "${BIN_NAME}-x86_64-apple-darwin.tar.gz" | awk '{print $1}')
          MACOS_ARM_SHA=$(shasum -a 256 "${BIN_NAME}-aarch64-apple-darwin.tar.gz" | awk '{print $1}')
          echo "macos_x86_64_sha256=${MACOS_X86_SHA}" >> "$GITHUB_OUTPUT"
          echo "macos_aarch64_sha256=${MACOS_ARM_SHA}" >> "$GITHUB_OUTPUT"

          if [[ "$INCLUDE_LINUX" == "true" ]]; then
            LINUX_X86_SHA=$(shasum -a 256 "${BIN_NAME}-x86_64-unknown-linux-gnu.tar.gz" | awk '{print $1}')
            LINUX_ARM_SHA=$(shasum -a 256 "${BIN_NAME}-aarch64-unknown-linux-gnu.tar.gz" | awk '{print $1}')
            echo "linux_x86_64_sha256=${LINUX_X86_SHA}" >> "$GITHUB_OUTPUT"
            echo "linux_aarch64_sha256=${LINUX_ARM_SHA}" >> "$GITHUB_OUTPUT"
          fi

      - name: Generate formula
        env:
          BIN_NAME: ${{ inputs.bin_name }}
          FORMULA_CLASS: ${{ inputs.formula_class }}
          FORMULA_FILE: ${{ inputs.formula_path }}
          DESCRIPTION: ${{ inputs.description }}
          HOMEPAGE: ${{ inputs.homepage }}
          VERSION: ${{ inputs.version }}
          RELEASE_REPO: ${{ inputs.release_repo }}
          RELEASE_TAG: ${{ inputs.release_tag }}
          INCLUDE_LINUX: ${{ inputs.include_linux }}
          MACOS_X86_SHA: ${{ steps.checksums.outputs.macos_x86_64_sha256 }}
          MACOS_ARM_SHA: ${{ steps.checksums.outputs.macos_aarch64_sha256 }}
          LINUX_X86_SHA: ${{ steps.checksums.outputs.linux_x86_64_sha256 }}
          LINUX_ARM_SHA: ${{ steps.checksums.outputs.linux_aarch64_sha256 }}
        run: |
          cd homebrew-tap
          mkdir -p "$(dirname "$FORMULA_FILE")"

          BASE_URL="https://github.com/${RELEASE_REPO}/releases/download/${RELEASE_TAG}"

          {
            echo "class ${FORMULA_CLASS} < Formula"
            echo "  desc \"${DESCRIPTION}\""
            echo "  homepage \"${HOMEPAGE}\""
            echo "  version \"${VERSION}\""
            echo "  license \"Apache-2.0\""
            echo ""
            echo "  on_macos do"
            echo "    if Hardware::CPU.arm?"
            echo "      url \"${BASE_URL}/${BIN_NAME}-aarch64-apple-darwin.tar.gz\""
            echo "      sha256 \"${MACOS_ARM_SHA}\""
            echo "    else"
            echo "      url \"${BASE_URL}/${BIN_NAME}-x86_64-apple-darwin.tar.gz\""
            echo "      sha256 \"${MACOS_X86_SHA}\""
            echo "    end"
            echo "  end"

            if [[ "$INCLUDE_LINUX" == "true" ]]; then
              echo ""
              echo "  on_linux do"
              echo "    if Hardware::CPU.arm?"
              echo "      url \"${BASE_URL}/${BIN_NAME}-aarch64-unknown-linux-gnu.tar.gz\""
              echo "      sha256 \"${LINUX_ARM_SHA}\""
              echo "    else"
              echo "      url \"${BASE_URL}/${BIN_NAME}-x86_64-unknown-linux-gnu.tar.gz\""
              echo "      sha256 \"${LINUX_X86_SHA}\""
              echo "    end"
              echo "  end"
            fi

            echo ""
            echo "  def install"
            echo "    bin.install \"${BIN_NAME}\""
            echo "  end"
            echo ""
            echo "  test do"
            echo "    assert_match version.to_s, shell_output(\"\#{bin}/${BIN_NAME} --version\")"
            echo "  end"
            echo "end"
          } > "$FORMULA_FILE"

          echo "Formula generated:"
          cat "$FORMULA_FILE"

      - name: Test formula locally
        env:
          BIN_NAME: ${{ inputs.bin_name }}
          FORMULA_FILE: ${{ inputs.formula_path }}
        run: |
          brew tap iii-hq/tap
          cp "$GITHUB_WORKSPACE/homebrew-tap/${FORMULA_FILE}" \
            "$(brew --repo iii-hq/tap)/${FORMULA_FILE}"
          brew audit --new "iii-hq/tap/${BIN_NAME}" || true
          brew install "iii-hq/tap/${BIN_NAME}"
          "${BIN_NAME}" --version
          brew uninstall "${BIN_NAME}"
          brew untap iii-hq/tap

      - name: Commit and push changes
        if: inputs.dry_run != true
        env:
          BIN_NAME: ${{ inputs.bin_name }}
          VERSION: ${{ inputs.version }}
          FORMULA_FILE: ${{ inputs.formula_path }}
        run: |
          cd homebrew-tap

          git config user.name "iii-ci[bot]"
          git config user.email "iii-ci[bot]@users.noreply.github.com"

          git add "$FORMULA_FILE"
          git commit -m "chore: update ${BIN_NAME} to v${VERSION}

          Automated update from release workflow."

          git push origin main

          echo "Formula published to homebrew-tap!"

      - name: Dry-run summary
        if: inputs.dry_run == true
        env:
          BIN_NAME: ${{ inputs.bin_name }}
          VERSION: ${{ inputs.version }}
        run: |
          echo "DRY RUN MODE - No changes pushed"
          echo ""
          echo "Formula validated successfully for ${BIN_NAME} v${VERSION}"
          echo "Set dry_run=false to publish for real."

      - name: Notify Slack — result
        if: always() && steps.slack.outputs.ts != ''
        continue-on-error: true
        uses: slackapi/slack-github-action@v2.0.0
        with:
          method: chat.update
          token: ${{ secrets.SLACK_BOT_TOKEN }}
          payload: |
            channel: ${{ secrets.SLACK_CHANNEL_ID }}
            ts: "${{ steps.slack.outputs.ts }}"
            text: "${{ job.status == 'success' && ':large_green_circle:' || ':red_circle:' }} ${{ inputs.slack_label }}${{ inputs.dry_run == true && ' (dry run)' || '' }} — ${{ job.status }}"

```

## /.github/workflows/_npm.yml

```yml path="/.github/workflows/_npm.yml" 
name: NPM Publish

on:
  workflow_call:
    inputs:
      package_path:
        description: 'Package directory to publish (e.g., sdk/packages/node/iii)'
        required: true
        type: string
      npm_tag:
        description: 'NPM dist-tag (latest, alpha, beta, rc)'
        required: true
        type: string
      build_filter:
        description: 'pnpm filter for building the package (e.g., iii-sdk)'
        required: true
        type: string
      ref:
        description: 'Git ref to checkout (default: the triggering ref)'
        required: false
        type: string
        default: ''
      pre_build_filter:
        description: 'pnpm filter for building dependencies first (optional)'
        required: false
        type: string
        default: ''
      dry_run:
        description: 'Build and validate without publishing'
        required: false
        type: boolean
        default: false
      slack_thread_ts:
        description: 'Slack parent message timestamp for thread replies (optional)'
        required: false
        type: string
        default: ''
      slack_label:
        description: 'Label for this step in Slack notifications (optional)'
        required: false
        type: string
        default: ''
    secrets:
      NPM_TOKEN:
        required: true
      SLACK_BOT_TOKEN:
        required: false
      SLACK_CHANNEL_ID:
        required: false

jobs:
  publish:
    name: Publish to NPM
    runs-on: ubuntu-latest
    permissions:
      contents: read
      id-token: write
    steps:
      - name: Notify Slack — in progress
        if: inputs.slack_thread_ts != ''
        id: slack
        continue-on-error: true
        uses: slackapi/slack-github-action@v2.0.0
        with:
          method: chat.postMessage
          token: ${{ secrets.SLACK_BOT_TOKEN }}
          payload: |
            channel: ${{ secrets.SLACK_CHANNEL_ID }}
            thread_ts: "${{ inputs.slack_thread_ts }}"
            text: ":large_yellow_circle: ${{ inputs.slack_label }}${{ inputs.dry_run == true && ' (dry run)' || '' }} — in progress"

      - uses: actions/checkout@v4
        with:
          ref: ${{ inputs.ref }}

      - uses: pnpm/action-setup@v4
        with:
          run_install: false

      - uses: actions/setup-node@v4
        with:
          node-version: '22'
          cache: 'pnpm'

      - name: Install dependencies
        run: pnpm install --frozen-lockfile

      - name: Build dependencies
        if: inputs.pre_build_filter != ''
        run: pnpm --filter "${{ inputs.pre_build_filter }}" build

      - name: Build package
        run: pnpm --filter "${{ inputs.build_filter }}" build

      - name: Setup NPM authentication
        env:
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
        run: echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" >> .npmrc

      - name: Publish to NPM
        working-directory: ${{ inputs.package_path }}
        run: pnpm publish --no-git-checks --tag "${{ inputs.npm_tag }}" --access public ${{ inputs.dry_run == true && '--dry-run' || '' }}
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

      - name: Notify Slack — result
        if: always() && steps.slack.outputs.ts != ''
        continue-on-error: true
        uses: slackapi/slack-github-action@v2.0.0
        with:
          method: chat.update
          token: ${{ secrets.SLACK_BOT_TOKEN }}
          payload: |
            channel: ${{ secrets.SLACK_CHANNEL_ID }}
            ts: "${{ steps.slack.outputs.ts }}"
            text: "${{ job.status == 'success' && ':large_green_circle:' || ':red_circle:' }} ${{ inputs.slack_label }}${{ inputs.dry_run == true && ' (dry run)' || '' }} — ${{ job.status }}"

```

## /.github/workflows/_publish-engine-workers.yml

```yml path="/.github/workflows/_publish-engine-workers.yml" 
name: Publish engine worker to registry

on:
  workflow_call:
    inputs:
      worker:
        description: 'Worker name (e.g. iii-http)'
        required: true
        type: string
      worker_dir:
        description: 'Path to the worker source directory containing iii.worker.yaml'
        required: true
        type: string
      version:
        description: 'Expected iii engine semver version'
        required: false
        type: string
        default: ''
      release_tag:
        description: 'Exact release tag to install the engine from (e.g. iii-alpha/v0.19.2-alpha.1). When set, the CLI is pinned to this tag via III_RELEASE_TAG instead of the iii/v<version> default. Used by the isolated alpha flow.'
        required: false
        type: string
        default: ''
      ref:
        description: 'Git ref to checkout (default: the triggering ref). The payload builder asserts engine/Cargo.toml matches the published version, so this must point at the version-bumped commit.'
        required: false
        type: string
        default: ''
      registry_tag:
        description: 'Registry tag (latest, next, ...)'
        required: false
        type: string
        default: latest
      api_url:
        description: 'Workers registry base URL'
        required: false
        type: string
        default: 'https://api.workers.iii.dev'
    secrets:
      WORKERS_REGISTRY_API_KEY:
        description: 'API key for the workers registry'
        required: false

jobs:
  publish:
    name: POST /publish (${{ inputs.worker }})
    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ inputs.ref }}

      - uses: actions/setup-python@v5
        with:
          python-version: '3.12'

      - name: Install pyyaml
        run: pip install --quiet pyyaml

      # Pin the iii CLI to the version we are publishing. Without this the
      # install script picks "latest stable", which can be older than the
      # tag being released and may lack features that the publish step
      # depends on (for example `engine::workers::list` exposing engine
      # internal workers landed in PR #1585). The install script also
      # bundles `iii-worker`, which iii-sandbox needs at runtime.
      - name: Install iii CLI
        env:
          VERSION_INPUT: ${{ inputs.version }}
          RELEASE_TAG_INPUT: ${{ inputs.release_tag }}
          # install.sh queries the GitHub releases API; unauthenticated calls
          # share a 60/hr per-IP limit that hosted runners routinely exhaust.
          GITHUB_TOKEN: ${{ github.token }}
        run: |
          set -euo pipefail
          curl -fsSL https://install.iii.dev/iii/main/install.sh -o /tmp/install-iii.sh
          if [[ -n "$RELEASE_TAG_INPUT" ]]; then
            # Isolated alpha: install the exact tag from its own namespace
            # (e.g. iii-alpha/v0.19.2-alpha.1), which the iii/v<version>
            # default cannot resolve.
            III_RELEASE_TAG="$RELEASE_TAG_INPUT" sh /tmp/install-iii.sh
          else
            expected="$VERSION_INPUT"
            if [[ -z "$expected" && "${GITHUB_REF_NAME:-}" == iii/v* ]]; then
              expected="${GITHUB_REF_NAME#iii/v}"
            fi
            install_args=()
            if [[ "$expected" == *-* ]]; then
              install_args+=("--next")
            fi
            VERSION="$expected" sh /tmp/install-iii.sh "${install_args[@]}"
          fi
          {
            echo "$HOME/.local/bin"
            echo "$HOME/.iii/bin"
          } >> "$GITHUB_PATH"
          export PATH="$HOME/.local/bin:$HOME/.iii/bin:$PATH"
          iii --version

      # Boot the engine with no workers so we can snapshot the trigger
      # types registered by `mandatory` workers (e.g. iii-observability's
      # `log` trigger type). The collect step diffs those out so the target
      # worker's payload only carries the types it actually contributes.
      - name: Start III engine
        run: |
          set -euo pipefail
          printf 'workers: []\n' > config.yaml
          iii --config config.yaml --no-update-check > iii-engine.log 2>&1 &
          echo "$!" > iii-engine.pid

          for _ in {1..60}; do
            if ! kill -0 "$(cat iii-engine.pid)" 2>/dev/null; then
              echo "::error::iii engine exited before becoming ready"
              cat iii-engine.log
              exit 1
            fi
            if iii trigger 'engine::workers::list' --json '{}' >/tmp/iii-workers.json 2>/tmp/iii-trigger.err; then
              cat /tmp/iii-workers.json
              exit 0
            fi
            sleep 1
          done

          echo "::error::iii engine did not become ready"
          cat /tmp/iii-trigger.err || true
          cat iii-engine.log || true
          exit 1

      - name: Snapshot engine trigger types baseline
        run: |
          set -euo pipefail
          # `engine::trigger-types::list` was retired in the engine_fn rework.
          # `engine::triggers::list` now returns trigger TYPES (templates).
          iii trigger \
            'engine::triggers::list' \
            --json '{"include_internal": false}' \
            > trigger-types-baseline.json
          cat trigger-types-baseline.json

      # Reload the engine with the target worker by overwriting config.yaml.
      # The engine watches config.yaml and reloads on change, so the target
      # worker registers without restarting.
      - name: Reload engine with target worker (${{ inputs.worker }})
        env:
          WORKER: ${{ inputs.worker }}
          WORKER_DIR: ${{ inputs.worker_dir }}
        run: |
          set -euo pipefail
          python3 - <<'PY'
          import os, pathlib, yaml
          worker = os.environ["WORKER"]
          worker_dir = pathlib.Path(os.environ["WORKER_DIR"])
          manifest = worker_dir / "iii.worker.yaml"
          meta = yaml.safe_load(manifest.read_text(encoding="utf-8")) or {}
          entry = {"name": worker}
          if meta.get("config") is not None:
              entry["config"] = meta["config"]
          config = {"workers": [entry]}
          pathlib.Path("config.yaml").write_text(yaml.dump(config, sort_keys=False), encoding="utf-8")
          PY
          cat config.yaml

      - name: Collect worker interface
        env:
          WORKER: ${{ inputs.worker }}
        run: |
          python3 .github/scripts/collect_engine_worker_interface.py \
            --worker "$WORKER" \
            --out worker-interface.json \
            --wait-seconds 120 \
            --trigger-types-baseline trigger-types-baseline.json

      - name: Build payload
        id: payload
        env:
          WORKER: ${{ inputs.worker }}
          WORKER_DIR: ${{ inputs.worker_dir }}
          VERSION: ${{ inputs.version }}
          REGISTRY_TAG: ${{ inputs.registry_tag }}
          REPO_URL: ${{ format('https://github.com/{0}', github.repository) }}
        run: |
          set -euo pipefail
          expected="$VERSION"
          if [[ -z "$expected" && "${GITHUB_REF_NAME:-}" == iii/v* ]]; then
            expected="${GITHUB_REF_NAME#iii/v}"
          fi
          python3 .github/scripts/build_engine_publish_payload.py \
            --worker "$WORKER" \
            --worker-dir "$WORKER_DIR" \
            --expected-version "$expected" \
            --registry-tag "$REGISTRY_TAG" \
            --repo-url "$REPO_URL" \
            --interface-json worker-interface.json \
            --out payload.json
          version=$(python3 -c 'import json; print(json.load(open("payload.json"))["version"])')
          echo "version=$version" >> "$GITHUB_OUTPUT"

      - name: POST /publish
        env:
          API_URL: ${{ inputs.api_url }}
          API_KEY: ${{ secrets.WORKERS_REGISTRY_API_KEY }}
          WORKER: ${{ inputs.worker }}
          PUBLISHED_VERSION: ${{ steps.payload.outputs.version }}
        run: |
          if [[ -z "$API_KEY" ]]; then
            echo "::error::WORKERS_REGISTRY_API_KEY secret is not set"
            exit 1
          fi
          http=$(curl -sS -o response.json -w '%{http_code}' \
            -H "X-API-Key: $API_KEY" \
            -H "Content-Type: application/json" \
            -X POST "$API_URL/publish" \
            --data-binary @payload.json)
          echo "HTTP $http"
          cat response.json
          if [[ "$http" != "200" && "$http" != "409" ]]; then
            echo "::error::publish failed with HTTP $http"
            exit 1
          fi
          if [[ "$http" == "409" ]]; then
            echo "::notice::${WORKER} v${PUBLISHED_VERSION} already published (409) — skipping"
          fi

      - name: Dump III logs
        if: failure()
        run: |
          echo "::group::iii engine log"
          # Full log instead of tail: iii-sandbox spawns iii-worker as a
          # subprocess whose stderr is forwarded into this file, and the
          # interesting output is at the start (initial spawn) — a tail
          # would only show the post-mortem reconnect loop.
          cat iii-engine.log || true
          echo "::endgroup::"

      - name: Stop III engine
        if: always()
        run: |
          if [[ -f iii-engine.pid ]]; then
            kill "$(cat iii-engine.pid)" 2>/dev/null || true
          fi

```

## /.github/workflows/_publish-worker-skills.yml

```yml path="/.github/workflows/_publish-worker-skills.yml" 
name: Publish worker skills to registry

on:
  workflow_call:
    inputs:
      registry_tag:
        description: 'Registry version tag (latest, next, ...)'
        required: false
        type: string
        default: latest
      api_url:
        description: 'Workers registry base URL'
        required: false
        type: string
        default: 'https://api.workers.iii.dev'
    secrets:
      WORKERS_REGISTRY_API_KEY:
        description: 'API key for the workers registry'
        required: false

jobs:
  discover:
    name: Discover workers with skills
    runs-on: ubuntu-latest
    outputs:
      matrix: ${{ steps.discover.outputs.matrix }}
      has_workers: ${{ steps.discover.outputs.has_workers }}
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-python@v5
        with:
          python-version: '3.12'

      - name: Install pyyaml
        run: pip install --quiet pyyaml

      - name: Discover worker skill bundles
        id: discover
        run: |
          python3 .github/scripts/discover_engine_worker_skills.py --repo-root .

  publish:
    name: POST /w/${{ matrix.slug }}/skills
    needs: discover
    if: needs.discover.outputs.has_workers == 'true'
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix: ${{ fromJson(needs.discover.outputs.matrix) }}
    steps:
      - uses: actions/checkout@v4

      - name: Build skills payload (${{ matrix.slug }})
        id: payload
        env:
          REGISTRY_TAG: ${{ inputs.registry_tag }}
        run: |
          set -euo pipefail
          python3 .github/scripts/build_skills_payload.py \
            --worker-dir "${{ matrix.worker_dir }}" \
            --version "$REGISTRY_TAG" \
            --out skills-payload.json

      - name: POST /w/${{ matrix.slug }}/skills
        if: steps.payload.outputs.skip != 'true'
        env:
          API_URL: ${{ inputs.api_url }}
          API_KEY: ${{ secrets.WORKERS_REGISTRY_API_KEY }}
          SLUG: ${{ matrix.slug }}
        run: |
          set -euo pipefail
          if [[ -z "$API_KEY" ]]; then
            echo "::error::WORKERS_REGISTRY_API_KEY secret is not set"
            exit 1
          fi
          http=$(curl -sS -o response.json -w '%{http_code}' \
            -H "X-API-Key: $API_KEY" \
            -H "Content-Type: application/json" \
            -X POST "$API_URL/w/$SLUG/skills" \
            --data-binary @skills-payload.json)
          echo "HTTP $http"
          cat response.json
          if [[ "$http" != "200" ]]; then
            echo "::error::publish skills failed for $SLUG with HTTP $http"
            exit 1
          fi
          echo "::notice::published skills for $SLUG (version tag in payload)"

```

## /.github/workflows/_py.yml

```yml path="/.github/workflows/_py.yml" 
name: PyPI Publish

on:
  workflow_call:
    inputs:
      package_path:
        description: 'Package directory (e.g., sdk/packages/python/iii)'
        required: true
        type: string
      ref:
        description: 'Git ref to checkout (default: the triggering ref)'
        required: false
        type: string
        default: ''
      dry_run:
        description: 'Build and validate without publishing'
        required: false
        type: boolean
        default: false
      slack_thread_ts:
        description: 'Slack parent message timestamp for thread replies (optional)'
        required: false
        type: string
        default: ''
      slack_label:
        description: 'Label for this step in Slack notifications (optional)'
        required: false
        type: string
        default: ''
    secrets:
      PYPI_API_TOKEN:
        required: true
      SLACK_BOT_TOKEN:
        required: false
      SLACK_CHANNEL_ID:
        required: false

jobs:
  publish:
    name: Publish to PyPI
    runs-on: ubuntu-latest
    permissions:
      contents: read
      id-token: write
    steps:
      - name: Notify Slack — in progress
        if: inputs.slack_thread_ts != ''
        id: slack
        continue-on-error: true
        uses: slackapi/slack-github-action@v2.0.0
        with:
          method: chat.postMessage
          token: ${{ secrets.SLACK_BOT_TOKEN }}
          payload: |
            channel: ${{ secrets.SLACK_CHANNEL_ID }}
            thread_ts: "${{ inputs.slack_thread_ts }}"
            text: ":large_yellow_circle: ${{ inputs.slack_label }}${{ inputs.dry_run == true && ' (dry run)' || '' }} — in progress"

      - uses: actions/checkout@v4
        with:
          ref: ${{ inputs.ref }}

      - uses: actions/setup-python@v5
        with:
          python-version: '3.12'

      - name: Install build tools
        run: pip install build twine

      - name: Build package
        working-directory: ${{ inputs.package_path }}
        run: python -m build

      - name: Validate package
        if: inputs.dry_run == true
        run: twine check ${{ inputs.package_path }}/dist/*

      - name: Publish to PyPI
        if: inputs.dry_run != true
        uses: pypa/gh-action-pypi-publish@release/v1
        with:
          packages-dir: ${{ inputs.package_path }}/dist/
          password: ${{ secrets.PYPI_API_TOKEN }}

      - name: Notify Slack — result
        if: always() && steps.slack.outputs.ts != ''
        continue-on-error: true
        uses: slackapi/slack-github-action@v2.0.0
        with:
          method: chat.update
          token: ${{ secrets.SLACK_BOT_TOKEN }}
          payload: |
            channel: ${{ secrets.SLACK_CHANNEL_ID }}
            ts: "${{ steps.slack.outputs.ts }}"
            text: "${{ job.status == 'success' && ':large_green_circle:' || ':red_circle:' }} ${{ inputs.slack_label }}${{ inputs.dry_run == true && ' (dry run)' || '' }} — ${{ job.status }}"

```

## /.github/workflows/_rust-binary.yml

```yml path="/.github/workflows/_rust-binary.yml" 
name: Rust Binary Release

on:
  workflow_call:
    inputs:
      bin_name:
        description: 'Binary name (e.g., iii, iii-console)'
        required: true
        type: string
      manifest_path:
        description: 'Path to Cargo.toml (e.g., engine/Cargo.toml)'
        required: true
        type: string
      tag_name:
        description: 'Git tag for the GitHub Release (e.g., iii/v1.0.0)'
        required: true
        type: string
      tag_prefix:
        description: 'Tag prefix used to filter stable tags for release-note diff (e.g., "iii/" or "motia/"). Leave empty to skip previous-stable lookup and fall back to GitHub default.'
        required: false
        type: string
        default: ''
      is_prerelease:
        description: 'Mark as pre-release'
        required: false
        type: boolean
        default: false
      skip_create_release:
        description: 'Skip GH release creation (assumes release already exists for the tag)'
        required: false
        type: boolean
        default: false
      artifact_name:
        description: 'Pre-built artifact to download before building (optional)'
        required: false
        type: string
        default: ''
      artifact_dest:
        description: 'Destination path for the downloaded artifact (optional)'
        required: false
        type: string
        default: ''
      features:
        description: 'Cargo features to enable (e.g., iii-filesystem/embed-init)'
        required: false
        type: string
        default: ''
      init_artifacts:
        description: 'Download iii-init cross-compiled artifacts for embedding'
        required: false
        type: boolean
        default: false
      dry_run:
        description: 'Build binaries without uploading or creating releases'
        required: false
        type: boolean
        default: false
      slack_thread_ts:
        description: 'Slack parent message timestamp for thread replies (optional)'
        required: false
        type: string
        default: ''
      targets:
        description: 'JSON array of target triples to build. When provided, only matching targets from the default matrix are built. Leave empty for full 9-target matrix.'
        required: false
        type: string
        default: ''
      slack_label:
        description: 'Label for this step in Slack notifications (optional)'
        required: false
        type: string
        default: ''
      system_deps:
        description: 'Space-separated list of additional apt packages to install on Linux (e.g., libcap-ng-dev)'
        required: false
        type: string
        default: ''
    secrets:
      III_CI_APP_ID:
        required: true
      III_CI_APP_PRIVATE_KEY:
        required: true
      SLACK_BOT_TOKEN:
        required: false
      SLACK_CHANNEL_ID:
        required: false

env:
  CARGO_TERM_COLOR: always
  CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
  CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_LINKER: arm-linux-gnueabihf-gcc
  CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_PKG_CONFIG_ALLOW_CROSS: '1'
  PKG_CONFIG_SYSROOT_DIR_aarch64_unknown_linux_gnu: /usr/aarch64-linux-gnu
  PKG_CONFIG_PATH_aarch64_unknown_linux_gnu: /usr/lib/aarch64-linux-gnu/pkgconfig
  CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUSTFLAGS: '-C link-arg=-L/usr/lib/aarch64-linux-gnu'

jobs:
  prepare-matrix:
    name: Prepare Build Matrix
    runs-on: ubuntu-latest
    outputs:
      matrix: ${{ steps.set-matrix.outputs.matrix }}
    steps:
      - name: Compute build matrix
        id: set-matrix
        env:
          TARGETS_INPUT: ${{ inputs.targets }}
        run: |
          # Default 9-target matrix
          DEFAULT='{"include":[{"target":"x86_64-apple-darwin","os":"macos-latest"},{"target":"aarch64-apple-darwin","os":"macos-latest"},{"target":"x86_64-pc-windows-msvc","os":"windows-latest"},{"target":"i686-pc-windows-msvc","os":"windows-latest"},{"target":"aarch64-pc-windows-msvc","os":"windows-latest"},{"target":"x86_64-unknown-linux-gnu","os":"ubuntu-22.04"},{"target":"x86_64-unknown-linux-musl","os":"ubuntu-latest"},{"target":"aarch64-unknown-linux-gnu","os":"ubuntu-22.04"},{"target":"armv7-unknown-linux-gnueabihf","os":"ubuntu-22.04"}]}'

          if [ -z "$TARGETS_INPUT" ]; then
            echo "matrix=$DEFAULT" >> "$GITHUB_OUTPUT"
            echo "Using default 9-target matrix"
          else
            # Filter default matrix to only include targets in the provided JSON array
            FILTERED=$(echo "$DEFAULT" | jq -c --argjson targets "$TARGETS_INPUT" '
              .include |= [ .[] | select(.target as $t | $targets | index($t)) ]
            ')
            echo "matrix=$FILTERED" >> "$GITHUB_OUTPUT"
            echo "Filtered matrix to targets: $TARGETS_INPUT"
          fi

  pre-build:
    name: Pre-build
    runs-on: ubuntu-latest
    permissions:
      contents: write
    outputs:
      slack_ts: ${{ steps.slack.outputs.ts }}
    steps:
      - name: Notify Slack — in progress
        if: inputs.slack_thread_ts != ''
        id: slack
        continue-on-error: true
        uses: slackapi/slack-github-action@v2.0.0
        with:
          method: chat.postMessage
          token: ${{ secrets.SLACK_BOT_TOKEN }}
          payload: |
            channel: ${{ secrets.SLACK_CHANNEL_ID }}
            thread_ts: "${{ inputs.slack_thread_ts }}"
            text: ":large_yellow_circle: ${{ inputs.slack_label }}${{ inputs.dry_run == true && ' (dry run)' || '' }} — in progress"

      - name: Generate token
        if: inputs.skip_create_release != true && inputs.dry_run != true
        id: generate_token
        uses: actions/create-github-app-token@v2
        with:
          app-id: ${{ secrets.III_CI_APP_ID }}
          private-key: ${{ secrets.III_CI_APP_PRIVATE_KEY }}

      - uses: actions/checkout@v4
        if: inputs.skip_create_release != true && inputs.dry_run != true
        with:
          token: ${{ steps.generate_token.outputs.token }}
          fetch-tags: true

      - name: Compute previous stable tag
        id: prev
        if: inputs.skip_create_release != true && inputs.dry_run != true && inputs.tag_prefix != ''
        env:
          TAG_PREFIX: ${{ inputs.tag_prefix }}
          CURRENT_TAG: ${{ inputs.tag_name }}
        run: |
          PREFIX="${TAG_PREFIX}v"
          PREV_STABLE=$(git tag --list "${PREFIX}*" --sort=-v:refname \
            | grep -E "^${PREFIX}[0-9]+\.[0-9]+\.[0-9]+\{{contextString}}quot; \
            | grep -v "^${CURRENT_TAG}\{{contextString}}quot; \
            | head -n 1 || true)
          echo "previous_tag=${PREV_STABLE}" >> "$GITHUB_OUTPUT"
          echo "::notice::Previous stable tag for release notes: ${PREV_STABLE:-<none, GitHub default>}"

      - name: Create GitHub Release
        if: inputs.skip_create_release != true && inputs.dry_run != true
        uses: softprops/action-gh-release@v2
        with:
          token: ${{ steps.generate_token.outputs.token }}
          tag_name: ${{ inputs.tag_name }}
          name: ${{ inputs.bin_name }} ${{ inputs.tag_name }}
          draft: false
          prerelease: ${{ inputs.is_prerelease }}
          generate_release_notes: true
          previous_tag: ${{ steps.prev.outputs.previous_tag }}

  build:
    name: Build ${{ matrix.target }}
    needs: [prepare-matrix, pre-build]
    runs-on: ${{ matrix.os }}
    permissions:
      contents: write
    env:
      SKIP_FRONTEND_BUILD: ${{ inputs.artifact_name != '' && '1' || '' }}
    strategy:
      fail-fast: false
      matrix: ${{ fromJson(needs.prepare-matrix.outputs.matrix) }}

    steps:
      - name: Generate token
        id: generate_token
        uses: actions/create-github-app-token@v2
        with:
          app-id: ${{ secrets.III_CI_APP_ID }}
          private-key: ${{ secrets.III_CI_APP_PRIVATE_KEY }}

      - uses: actions/checkout@v4
        with:
          token: ${{ steps.generate_token.outputs.token }}

      - name: Download pre-built artifact
        if: inputs.artifact_name != ''
        uses: actions/download-artifact@v4
        with:
          name: ${{ inputs.artifact_name }}
          path: ${{ inputs.artifact_dest }}

      - name: Download iii-init (x86_64-musl)
        if: inputs.init_artifacts == true
        uses: actions/download-artifact@v4
        with:
          name: iii-init-x86_64-unknown-linux-musl
          path: target/x86_64-unknown-linux-musl/release/

      - name: Download iii-init (aarch64-musl)
        if: inputs.init_artifacts == true
        uses: actions/download-artifact@v4
        with:
          name: iii-init-aarch64-unknown-linux-musl
          path: target/aarch64-unknown-linux-musl/release/

      - name: Install additional system dependencies
        if: runner.os == 'Linux' && inputs.system_deps != ''
        env:
          BUILD_TARGET: ${{ matrix.target }}
        run: |
          sudo apt-get update
          case "$BUILD_TARGET" in
            aarch64-unknown-linux-gnu)
              sudo dpkg --add-architecture arm64
              sudo sed -i 's/^deb /deb [arch=amd64] /' /etc/apt/sources.list
              echo "deb [arch=arm64] http://ports.ubuntu.com/ $(lsb_release -cs) main restricted universe" | sudo tee /etc/apt/sources.list.d/arm64.list
              echo "deb [arch=arm64] http://ports.ubuntu.com/ $(lsb_release -cs)-updates main restricted universe" | sudo tee -a /etc/apt/sources.list.d/arm64.list
              sudo apt-get update
              for pkg in ${{ inputs.system_deps }}; do
                sudo apt-get install -y "${pkg}:arm64"
              done
              ;;
            *)
              sudo apt-get install -y ${{ inputs.system_deps }}
              ;;
          esac

      - name: Install cross-compilation tools
        if: runner.os == 'Linux'
        env:
          BUILD_TARGET: ${{ matrix.target }}
        run: |
          sudo apt-get update
          case "$BUILD_TARGET" in
            x86_64-unknown-linux-musl)
              sudo apt-get install -y musl-tools
              ;;
            aarch64-unknown-linux-gnu)
              sudo apt-get install -y gcc-aarch64-linux-gnu libc6-dev-arm64-cross
              ;;
            armv7-unknown-linux-gnueabihf)
              sudo apt-get install -y gcc-arm-linux-gnueabihf libc6-dev-armhf-cross
              ;;
          esac

      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target }}

      - name: Cache cargo registry & build
        uses: Swatinem/rust-cache@v2
        with:
          key: ${{ inputs.bin_name }}-${{ matrix.target }}

      - name: Build and upload binary
        uses: taiki-e/upload-rust-binary-action@v1
        with:
          bin: ${{ inputs.bin_name }}
          target: ${{ matrix.target }}
          features: ${{ inputs.features }}
          ref: refs/tags/${{ inputs.tag_name }}
          tar: unix
          zip: windows
          checksum: sha256
          manifest-path: ${{ inputs.manifest_path }}
          token: ${{ steps.generate_token.outputs.token }}
          dry-run: ${{ inputs.dry_run }}

  notify-result:
    name: Notify Result
    needs: [pre-build, build]
    if: always() && needs.pre-build.outputs.slack_ts != ''
    runs-on: ubuntu-latest
    steps:
      - name: Update thread message
        continue-on-error: true
        uses: slackapi/slack-github-action@v2.0.0
        with:
          method: chat.update
          token: ${{ secrets.SLACK_BOT_TOKEN }}
          payload: |
            channel: ${{ secrets.SLACK_CHANNEL_ID }}
            ts: "${{ needs.pre-build.outputs.slack_ts }}"
            text: "${{ needs.build.result == 'success' && ':large_green_circle:' || ':red_circle:' }} ${{ inputs.slack_label }}${{ inputs.dry_run == true && ' (dry run)' || '' }} — ${{ needs.build.result }}"

```

## /.github/workflows/_rust-cargo.yml

```yml path="/.github/workflows/_rust-cargo.yml" 
name: Rust Cargo Publish

on:
  workflow_call:
    inputs:
      package_path:
        description: 'Path to the crate directory (e.g., sdk/packages/rust/iii)'
        required: true
        type: string
      ref:
        description: 'Git ref to checkout (default: the triggering ref)'
        required: false
        type: string
        default: ''
      dry_run:
        description: 'Build and validate without publishing'
        required: false
        type: boolean
        default: false
      slack_thread_ts:
        description: 'Slack parent message timestamp for thread replies (optional)'
        required: false
        type: string
        default: ''
      slack_label:
        description: 'Label for this step in Slack notifications (optional)'
        required: false
        type: string
        default: ''
    secrets:
      CARGO_REGISTRY_TOKEN:
        required: true
      SLACK_BOT_TOKEN:
        required: false
      SLACK_CHANNEL_ID:
        required: false

env:
  CARGO_TERM_COLOR: always

jobs:
  publish:
    name: Publish to crates.io
    runs-on: ubuntu-latest
    # cargo publish authenticates to crates.io via CARGO_REGISTRY_TOKEN, not
    # git. Drop the inherited write scope so a verify-build can't reuse the
    # token (matches _npm.yml / _py.yml).
    permissions:
      contents: read
    steps:
      - name: Notify Slack — in progress
        if: inputs.slack_thread_ts != ''
        id: slack
        continue-on-error: true
        uses: slackapi/slack-github-action@v2.0.0
        with:
          method: chat.postMessage
          token: ${{ secrets.SLACK_BOT_TOKEN }}
          payload: |
            channel: ${{ secrets.SLACK_CHANNEL_ID }}
            thread_ts: "${{ inputs.slack_thread_ts }}"
            text: ":large_yellow_circle: ${{ inputs.slack_label }}${{ inputs.dry_run == true && ' (dry run)' || '' }} — in progress"

      - uses: actions/checkout@v4
        with:
          ref: ${{ inputs.ref }}
          # cargo publish doesn't push to git; don't leave the token in config.
          persist-credentials: false

      - uses: dtolnay/rust-toolchain@stable

      - uses: Swatinem/rust-cache@v2

      - name: Publish to crates.io
        working-directory: ${{ inputs.package_path }}
        run: cargo publish ${{ inputs.dry_run == true && '--dry-run' || '' }}
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}

      - name: Notify Slack — result
        if: always() && steps.slack.outputs.ts != ''
        continue-on-error: true
        uses: slackapi/slack-github-action@v2.0.0
        with:
          method: chat.update
          token: ${{ secrets.SLACK_BOT_TOKEN }}
          payload: |
            channel: ${{ secrets.SLACK_CHANNEL_ID }}
            ts: "${{ steps.slack.outputs.ts }}"
            text: "${{ job.status == 'success' && ':large_green_circle:' || ':red_circle:' }} ${{ inputs.slack_label }}${{ inputs.dry_run == true && ' (dry run)' || '' }} — ${{ job.status }}"

```

## /.github/workflows/alpha-release.yml

```yml path="/.github/workflows/alpha-release.yml" 
name: Alpha Release

# Publishes an isolated alpha prerelease of every SDK + engine-internal lib
# from ANY feature branch, without touching main. The version anchors on the
# latest stable tag and appends an accumulating -alpha.N suffix
# (0.19.2-alpha.1, .2, .3 ...).
#
# Publishes:
#   * SDK packages — npm + pypi + crates + go.
#   * Engine binaries — iii / iii-worker / iii-init, attached to a GitHub
#     prerelease on the iii-alpha/v* tag.
#   * Builtin workers + skills — to the workers registry under a dedicated
#     `alpha` tag (never next/latest).
#   Console, docker and homebrew are intentionally excluded.
#
# Isolation guarantees:
#   * Tags live under the iii-alpha/v* namespace, so release-iii.yml
#     (trigger iii/v*) never fires.
#   * No commit or push to main or to the feature branch — the version bump
#     lives only in an ephemeral commit that the alpha tag points at.
#   * Engine binaries land on their own prerelease and workers use the
#     dedicated `alpha` registry tag, so nothing collides with the official
#     iii/v* releases or the next/latest channels.
#
# Run from: Actions -> Alpha Release -> "Use workflow from: <feature-branch>".
# Note: dry_run still creates the iii-alpha tag (publishers need it to check
# out the bumped commit) and increments the counter; it just skips uploads.

on:
  workflow_dispatch:
    inputs:
      dry_run:
        description: 'Build and validate without publishing (still pushes the iii-alpha tag)'
        required: false
        type: boolean
        default: false

permissions:
  contents: write # prepare tag push, go tag, GitHub prerelease + binary uploads
  id-token: write # OIDC / npm + pypi provenance (sdk-node, _py.yml)

jobs:
  prepare:
    name: Bump & tag alpha
    runs-on: ubuntu-latest
    timeout-minutes: 10
    outputs:
      tag: ${{ steps.versions.outputs.tag }}
      version: ${{ steps.versions.outputs.version }}
      python_version: ${{ steps.versions.outputs.python_version }}
      npm_tag: ${{ steps.versions.outputs.npm_tag }}
      dry_run: ${{ inputs.dry_run }}
    steps:
      - name: Checkout selected branch
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
          # Default GITHUB_TOKEN (contents: write) is persisted in git config
          # and reused by the tag push below. No app token needed: we only
          # push a tag in the fresh iii-alpha/* namespace, never a branch.

      - name: Refuse to run on main
        run: |
          BRANCH=$(git rev-parse --abbrev-ref HEAD)
          if [[ "$BRANCH" == "main" ]]; then
            echo "::error::alpha-release is for feature branches; use create-tag for main releases"
            exit 1
          fi
          echo "Alpha release from branch: $BRANCH"

      - name: Calculate alpha version
        id: versions
        run: |
          python3 .github/scripts/calculate_release_version.py \
            --target iii \
            --bump none \
            --prerelease alpha \
            --counter-tag-prefix iii-alpha \
            --current-version-file engine/Cargo.toml

      - uses: dtolnay/rust-toolchain@stable

      - name: Configure git identity
        run: |
          git config user.name "iii-ci[bot]"
          git config user.email "iii-ci[bot]@users.noreply.github.com"

      - name: Bump all manifests in lockstep
        env:
          VERSION: ${{ steps.versions.outputs.version }}
          PY_VERSION: ${{ steps.versions.outputs.python_version }}
        run: |
          python3 .github/scripts/bump_manifests.py \
            --root . \
            --version "$VERSION" \
            --python-version "$PY_VERSION"

      - name: Sync Cargo.lock
        run: cargo update --workspace

      - name: Commit bump (ephemeral) and push the alpha tag only
        env:
          TAG: ${{ steps.versions.outputs.tag }}
        run: |
          git add -A
          git commit -m "chore(alpha): $TAG [skip ci]"
          git tag -a "$TAG" -m "Alpha release $TAG"
          # Push ONLY the tag. The branch (and main) are never modified on
          # the remote — the bump commit is reachable solely via this tag.
          git push origin "$TAG"
          echo "Pushed alpha tag: $TAG"

  sdk-node:
    name: SDK Node (npm)
    needs: prepare
    if: ${{ !failure() && !cancelled() }}
    runs-on: ubuntu-latest
    permissions:
      contents: read
      id-token: write
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ needs.prepare.outputs.tag }}

      - uses: pnpm/action-setup@v4
        with:
          run_install: false

      - uses: actions/setup-node@v4
        with:
          node-version: '22'
          cache: 'pnpm'

      - name: Install dependencies
        run: pnpm install --frozen-lockfile

      - name: Build node SDK packages
        run: >-
          pnpm
          --filter "@iii-dev/observability"
          --filter "@iii-dev/helpers"
          --filter iii-sdk
          --filter iii-browser-sdk
          build

      - name: Setup NPM authentication
        env:
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
        run: echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" >> .npmrc

      # Recursive publish: pnpm resolves topological order (observability
      # before iii / iii-browser) and rewrites `workspace:*` deps to the
      # concrete alpha version automatically — no manual ordering needed.
      - name: Publish node SDK packages
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
        run: >-
          pnpm
          --filter "@iii-dev/observability"
          --filter "@iii-dev/helpers"
          --filter iii-sdk
          --filter iii-browser-sdk
          -r publish
          --no-git-checks
          --tag "${{ needs.prepare.outputs.npm_tag }}"
          --access public
          ${{ needs.prepare.outputs.dry_run == 'true' && '--dry-run' || '' }}

  observability-py:
    name: Observability Python (pypi)
    # The shim pins iii-helpers at the release version; publish helpers first so
    # PyPI can resolve the dependency.
    needs: [prepare, helpers-py]
    if: ${{ !failure() && !cancelled() }}
    uses: ./.github/workflows/_py.yml
    with:
      package_path: sdk/packages/python/observability
      ref: ${{ needs.prepare.outputs.tag }}
      dry_run: ${{ needs.prepare.outputs.dry_run == 'true' }}
    secrets:
      PYPI_API_TOKEN: ${{ secrets.PYPI_API_TOKEN }}

  helpers-py:
    name: Helpers Python (pypi)
    needs: prepare
    if: ${{ !failure() && !cancelled() }}
    uses: ./.github/workflows/_py.yml
    with:
      package_path: sdk/packages/python/helpers
      ref: ${{ needs.prepare.outputs.tag }}
      dry_run: ${{ needs.prepare.outputs.dry_run == 'true' }}
    secrets:
      PYPI_API_TOKEN: ${{ secrets.PYPI_API_TOKEN }}

  sdk-py:
    name: SDK Python (pypi)
    # iii depends on iii-observability and iii-helpers; publish them first
    # so the package is installable from PyPI.
    needs: [prepare, observability-py, helpers-py]
    if: ${{ !failure() && !cancelled() }}
    uses: ./.github/workflows/_py.yml
    with:
      package_path: sdk/packages/python/iii
      ref: ${{ needs.prepare.outputs.tag }}
      dry_run: ${{ needs.prepare.outputs.dry_run == 'true' }}
    secrets:
      PYPI_API_TOKEN: ${{ secrets.PYPI_API_TOKEN }}

  observability-rust:
    name: Observability Rust (cargo)
    # The shim depends on iii-helpers; cargo publish resolves it from crates.io,
    # so helpers must be published first.
    needs: [prepare, helpers-rust]
    if: ${{ !failure() && !cancelled() }}
    uses: ./.github/workflows/_rust-cargo.yml
    with:
      package_path: sdk/packages/rust/observability
      ref: ${{ needs.prepare.outputs.tag }}
      dry_run: ${{ needs.prepare.outputs.dry_run == 'true' }}
    secrets:
      CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}

  helpers-rust:
    name: Helpers Rust (cargo)
    needs: prepare
    if: ${{ !failure() && !cancelled() }}
    uses: ./.github/workflows/_rust-cargo.yml
    with:
      package_path: sdk/packages/rust/helpers
      ref: ${{ needs.prepare.outputs.tag }}
      dry_run: ${{ needs.prepare.outputs.dry_run == 'true' }}
    secrets:
      CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}

  sdk-rust:
    name: SDK Rust (cargo)
    # iii-sdk depends on both iii-observability and iii-helpers; cargo
    # publish resolves those from crates.io, so both must be published first.
    needs: [prepare, observability-rust, helpers-rust]
    if: ${{ !failure() && !cancelled() }}
    uses: ./.github/workflows/_rust-cargo.yml
    with:
      package_path: sdk/packages/rust/iii
      ref: ${{ needs.prepare.outputs.tag }}
      dry_run: ${{ needs.prepare.outputs.dry_run == 'true' }}
    secrets:
      CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}

  sdk-go:
    name: SDK Go (module)
    needs: prepare
    if: ${{ !failure() && !cancelled() }}
    uses: ./.github/workflows/_go.yml
    with:
      package_path: sdk/packages/go/iii
      module_path: github.com/iii-hq/iii/sdk/packages/go/iii
      version: ${{ needs.prepare.outputs.version }}
      ref: ${{ needs.prepare.outputs.tag }}
      dry_run: ${{ needs.prepare.outputs.dry_run == 'true' }}

  # ──────────────────────────────────────────────────────────────
  # Engine pipeline (isolated): binaries -> GitHub prerelease on the
  # iii-alpha/v* tag, builtin workers -> dedicated `alpha` registry tag.
  # Nothing here touches the official iii/v* releases or the next/latest
  # worker channels. Console, docker and homebrew are intentionally out.
  # ──────────────────────────────────────────────────────────────

  create-alpha-release:
    name: Create alpha GitHub prerelease
    needs: prepare
    if: ${{ !failure() && !cancelled() && needs.prepare.outputs.dry_run != 'true' }}
    runs-on: ubuntu-latest
    permissions:
      contents: write
    steps:
      # The tag was already pushed by `prepare`; this attaches a prerelease
      # to it. Uses the default GITHUB_TOKEN (contents: write).
      - name: Create GitHub prerelease
        uses: softprops/action-gh-release@v2
        with:
          tag_name: ${{ needs.prepare.outputs.tag }}
          name: iii ${{ needs.prepare.outputs.version }} (alpha)
          draft: false
          prerelease: true
          generate_release_notes: false

  init-build:
    name: Build iii-init (${{ matrix.target }})
    needs: [prepare, create-alpha-release]
    if: ${{ !failure() && !cancelled() }}
    runs-on: ubuntu-latest
    permissions:
      contents: write
    strategy:
      fail-fast: false
      matrix:
        include:
          - target: x86_64-unknown-linux-musl
            publish_aliases: 'x86_64-unknown-linux-gnu x86_64-apple-darwin'
          - target: aarch64-unknown-linux-musl
            publish_aliases: 'aarch64-unknown-linux-gnu aarch64-apple-darwin'
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ needs.prepare.outputs.tag }}
          # Build runs checked-out code; uploads go through softprops (token
          # via env), so the write token never needs to sit in git config.
          persist-credentials: false

      - name: Install cross-compilation tools
        run: |
          sudo apt-get update
          sudo apt-get install -y musl-tools

      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target }}

      - uses: Swatinem/rust-cache@v2
        with:
          key: iii-init-${{ matrix.target }}

      - name: Build iii-init
        run: cargo build -p iii-init --target ${{ matrix.target }} --release

      - name: Upload init binary as workflow artifact
        uses: actions/upload-artifact@v4
        with:
          name: iii-init-${{ matrix.target }}
          path: target/${{ matrix.target }}/release/iii-init
          retention-days: 1

      - name: Package and upload to release
        if: needs.prepare.outputs.dry_run != 'true'
        run: |
          cd target/${{ matrix.target }}/release
          tar czf iii-init-${{ matrix.target }}.tar.gz iii-init
          sha256sum iii-init-${{ matrix.target }}.tar.gz | awk '{print $1}' > iii-init-${{ matrix.target }}.sha256
          for alias in ${{ matrix.publish_aliases }}; do
            cp iii-init-${{ matrix.target }}.tar.gz "iii-init-${alias}.tar.gz"
            sha256sum "iii-init-${alias}.tar.gz" | awk '{print $1}' > "iii-init-${alias}.sha256"
          done

      - name: Upload release assets
        if: needs.prepare.outputs.dry_run != 'true'
        uses: softprops/action-gh-release@v2
        with:
          tag_name: ${{ needs.prepare.outputs.tag }}
          files: target/${{ matrix.target }}/release/iii-init-*.tar.gz,target/${{ matrix.target }}/release/iii-init-*.sha256

  engine-release:
    name: Engine Binary (alpha)
    needs: [prepare, create-alpha-release]
    if: ${{ !failure() && !cancelled() }}
    uses: ./.github/workflows/_rust-binary.yml
    with:
      bin_name: iii
      manifest_path: engine/Cargo.toml
      tag_name: ${{ needs.prepare.outputs.tag }}
      tag_prefix: iii-alpha/
      is_prerelease: true
      skip_create_release: true
      dry_run: ${{ needs.prepare.outputs.dry_run == 'true' }}
    secrets:
      III_CI_APP_ID: ${{ secrets.III_CI_APP_ID }}
      III_CI_APP_PRIVATE_KEY: ${{ secrets.III_CI_APP_PRIVATE_KEY }}

  worker-release:
    name: Worker Binary (alpha)
    needs: [prepare, create-alpha-release, init-build]
    if: ${{ !failure() && !cancelled() }}
    uses: ./.github/workflows/_rust-binary.yml
    with:
      bin_name: iii-worker
      manifest_path: crates/iii-worker/Cargo.toml
      tag_name: ${{ needs.prepare.outputs.tag }}
      tag_prefix: iii-alpha/
      is_prerelease: true
      skip_create_release: true
      dry_run: ${{ needs.prepare.outputs.dry_run == 'true' }}
      features: embed-init,embed-libkrunfw
      init_artifacts: true
      targets: '["aarch64-apple-darwin","x86_64-unknown-linux-gnu","aarch64-unknown-linux-gnu"]'
      system_deps: libcap-ng-dev
    secrets:
      III_CI_APP_ID: ${{ secrets.III_CI_APP_ID }}
      III_CI_APP_PRIVATE_KEY: ${{ secrets.III_CI_APP_PRIVATE_KEY }}

  publish-builtin-workers:
    name: Publish builtin workers (alpha)
    needs: [prepare, create-alpha-release, engine-release, worker-release]
    if: ${{ !failure() && !cancelled() && needs.prepare.outputs.dry_run != 'true' }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - { worker: iii-worker-manager, worker_dir: engine/src/workers/worker }
          - { worker: iii-http, worker_dir: engine/src/workers/rest_api }
          - { worker: iii-stream, worker_dir: engine/src/workers/stream }
          - { worker: iii-state, worker_dir: engine/src/workers/state }
          - { worker: iii-pubsub, worker_dir: engine/src/workers/pubsub }
          - { worker: iii-cron, worker_dir: engine/src/workers/cron }
          - { worker: iii-observability, worker_dir: engine/src/workers/observability }
          - { worker: iii-exec, worker_dir: engine/src/workers/shell }
          - { worker: iii-bridge, worker_dir: engine/src/workers/bridge_client }
          - { worker: configuration, worker_dir: engine/src/workers/configuration }
          - { worker: iii-sandbox, worker_dir: crates/iii-worker/src/sandbox_daemon }
          - { worker: iii-engine-functions, worker_dir: engine/src/workers/engine_fn }
    uses: ./.github/workflows/_publish-engine-workers.yml
    with:
      worker: ${{ matrix.worker }}
      worker_dir: ${{ matrix.worker_dir }}
      version: ${{ needs.prepare.outputs.version }}
      release_tag: ${{ needs.prepare.outputs.tag }}
      # Checkout the version-bumped commit: build_engine_publish_payload.py
      # asserts engine/Cargo.toml matches the published version.
      ref: ${{ needs.prepare.outputs.tag }}
      registry_tag: alpha
    secrets:
      WORKERS_REGISTRY_API_KEY: ${{ secrets.WORKERS_REGISTRY_API_KEY }}

  publish-worker-skills:
    name: Publish worker skills (alpha)
    needs: [prepare, publish-builtin-workers]
    if: ${{ !failure() && !cancelled() && needs.prepare.outputs.dry_run != 'true' }}
    uses: ./.github/workflows/_publish-worker-skills.yml
    with:
      registry_tag: alpha
    secrets:
      WORKERS_REGISTRY_API_KEY: ${{ secrets.WORKERS_REGISTRY_API_KEY }}

```

## /.github/workflows/bench-release.yml

```yml path="/.github/workflows/bench-release.yml" 
name: Benchmark Release

on:
  push:
    tags:
      - 'iii/v*'
  workflow_dispatch:

permissions:
  contents: write

concurrency:
  group: bench-release-${{ github.repository }}

env:
  CARGO_TERM_COLOR: always
  III_TELEMETRY_ENABLED: "false"

jobs:
  benchmark:
    name: Run Benchmarks
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: dtolnay/rust-toolchain@stable

      - uses: Swatinem/rust-cache@v2
        with:
          cache-on-failure: true

      - name: Run benchmarks
        run: cargo bench -p iii --bench '*' -- --output-format bencher 2>&1 | tee bench-output.txt

      - name: Extract version from tag
        id: meta
        run: |
          if [[ "$GITHUB_REF_NAME" == iii/v* ]]; then
            VERSION="${GITHUB_REF_NAME#iii/v}"
          else
            VERSION="manual-$(date +%Y%m%d-%H%M%S)"
          fi
          echo "version=$VERSION" >> "$GITHUB_OUTPUT"

      - name: Store benchmark result
        uses: benchmark-action/github-action-benchmark@v1
        with:
          name: iii Engine Benchmarks
          tool: 'cargo'
          output-file-path: bench-output.txt
          gh-pages-branch: gh-pages
          benchmark-data-dir-path: dev/bench
          github-token: ${{ secrets.GITHUB_TOKEN }}
          auto-push: true
          alert-threshold: '120%'
          comment-on-alert: true
          summary-always: true
          alert-comment-cc-users: '@iii-hq/engine'

      - name: Upload raw criterion data
        uses: actions/upload-artifact@v4
        with:
          name: criterion-data-${{ steps.meta.outputs.version }}
          path: target/criterion/
          retention-days: 90

      - name: Generate benchmark summary
        if: always()
        id: summary
        run: |
          VERSION="${{ steps.meta.outputs.version }}"
          BENCH_COUNT=$(grep -c "^test " bench-output.txt 2>/dev/null || echo "0")
          if [[ "${{ job.status }}" == "success" ]]; then
            STATUS_ICON=":large_green_circle:"
          else
            STATUS_ICON=":red_circle:"
          fi
          PAGES_URL="https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/dev/bench/"
          WORKFLOW_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"

          {
            echo "body<<EOFSLACK"
            printf '%s %s\n%s\n%s' \
              "${STATUS_ICON}" "*Benchmark Results* — iii v${VERSION}" \
              "${BENCH_COUNT} benchmarks collected" \
              "<${PAGES_URL}|View historical charts> | <${WORKFLOW_URL}|View workflow>"
            echo ""
            echo "EOFSLACK"
          } >> "$GITHUB_OUTPUT"

      - name: Post to Slack
        if: always()
        continue-on-error: true
        uses: slackapi/slack-github-action@v2.0.0
        with:
          method: chat.postMessage
          token: ${{ secrets.SLACK_BOT_TOKEN }}
          payload: |
            channel: ${{ secrets.SLACK_CHANNEL_ID }}
            text: "Benchmark results for iii v${{ steps.meta.outputs.version }}"
            blocks:
              - type: "section"
                text:
                  type: "mrkdwn"
                  text: "${{ steps.summary.outputs.body }}"

```

## /.github/workflows/checklist-checker.yml

```yml path="/.github/workflows/checklist-checker.yml" 
name: License Agreement Check

on:
  pull_request_target:
    types: [opened, edited, synchronize, reopened, ready_for_review]

permissions:
  contents: read

concurrency:
  group: license-agreement-${{ github.event.pull_request.number }}
  # Let an in-flight run finish so it can post its final commit status. With
  # `cancel-in-progress: true` a synchronize event would cancel the prior run
  # mid-flight, leaving a CANCELLED check on the PR rollup even for team-member
  # PRs that the script would otherwise mark `success`.
  cancel-in-progress: false

jobs:
  license-agreement:
    # Skip bot-authored PRs. Org membership is NOT gated here: the event payload's
    # author_association conceals private org members, so membership is checked
    # authoritatively in the script using the App token (which can see them).
    if: |
      github.actor != 'github-actions[bot]' &&
      github.event.pull_request.user.type != 'Bot'
    runs-on: ubuntu-latest
    # SECURITY: this is a `pull_request_target` job, so it runs in the base repo
    # context with access to secrets (APP_PRIVATE_KEY). It is safe ONLY because it
    # checks out the base branch and runs our own trusted script against the PR as
    # data. NEVER check out the PR head or execute fork-provided code (npm install,
    # build, PR-supplied actions) in this job, doing so would expose the secret to
    # untrusted contributors. Run untrusted PR code in a separate `pull_request` job.
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.event.repository.default_branch }}
          persist-credentials: false

      - uses: actions/setup-node@v4
        with:
          node-version: '22'

      # Mint a short-lived installation token. Unlike GITHUB_TOKEN, an App
      # installation token can write to the base repo on fork PRs, which is the
      # only kind of PR this workflow ever processes.
      - uses: actions/create-github-app-token@v2
        id: app-token
        with:
          app-id: ${{ secrets.III_CI_APP_ID }}
          private-key: ${{ secrets.III_CI_APP_PRIVATE_KEY }}

      - name: Check license agreement
        env:
          GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}
        run: node .github/scripts/license-agreement-check.mjs

```

## /.github/workflows/cloudfront-functions-test.yml

```yml path="/.github/workflows/cloudfront-functions-test.yml" 
name: CloudFront Functions Tests

on:
  pull_request:
    paths:
      - 'infra/terraform/website/cloudfront_functions/**'
      - '.github/workflows/cloudfront-functions-test.yml'
  push:
    branches: [main]
    paths:
      - 'infra/terraform/website/cloudfront_functions/**'

jobs:
  test:
    name: node --test
    runs-on: ubuntu-latest
    timeout-minutes: 3

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: '22'

      - name: Run CloudFront Function unit tests
        run: node --test infra/terraform/website/cloudfront_functions/redirects.test.js

```

## /.github/workflows/license-check.yml

```yml path="/.github/workflows/license-check.yml" 
name: License Header Check

on:
  push:
    branches: [main]
    paths-ignore:
      - 'docs/**'
      - 'skills/**'
      - 'website/**'
      - 'blog/**'
      - '**/*.md'
      - '**/*.mdx'
      - '.cursor/**'
  pull_request:
    branches: [main]
    paths-ignore:
      - 'docs/**'
      - 'skills/**'
      - 'website/**'
      - 'blog/**'
      - '**/*.md'
      - '**/*.mdx'
      - '.cursor/**'

jobs:
  check-license-headers:
    name: Check License Headers
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Check license headers
        uses: korandoru/hawkeye@v6
        with:
          config: engine/licenserc.toml

```

## /.github/workflows/publish-worker-skills.yml

```yml path="/.github/workflows/publish-worker-skills.yml" 
name: Publish worker skills

on:
  workflow_dispatch:
    inputs:
      registry_tag:
        description: 'Registry version tag to attach skills to'
        required: true
        type: choice
        options:
          - latest
          - next
        default: latest

jobs:
  publish:
    uses: ./.github/workflows/_publish-worker-skills.yml
    with:
      registry_tag: ${{ inputs.registry_tag }}
    secrets: inherit

```

## /.github/workflows/skill-check.yml

```yml path="/.github/workflows/skill-check.yml" 
name: Skill check

on:
  pull_request:
    paths:
      - "docs/next/**/*.md"
      - "docs/next/**/*.mdx"
      - ".skill-check.yaml"
      - ".github/workflows/skill-check.yml"
  push:
    branches: [main]
    paths:
      - "docs/next/**/*.md"
      - "docs/next/**/*.mdx"
      - ".skill-check.yaml"
      - ".github/workflows/skill-check.yml"

permissions:
  contents: read # report-only; the action no longer commits back
  pull-requests: write # for the sticky PR comment
  actions: write # for the persistent AI skip-cache (v0.3+)

jobs:
  verify:
    name: Verify docs skills
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v5

      - name: Run iii-skill-check
        uses: iii-hq/skills-and-validation@v0.4
        with:
          write: false
          scope: pr-diff
          anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }}

```

## /.prettierrc

```prettierrc path="/.prettierrc" 
{
  "proseWrap": "always",
  "printWidth": 100
}

```

## /blog/.nvmrc

```nvmrc path="/blog/.nvmrc" 
22

```


The content has been capped at 50000 tokens. The user could consider applying other filters to refine the result. The better and more specific the context, the better the LLM can follow instructions. If the context seems verbose, the user can refine the filter using uithub. Thank you for using https://uithub.com - Perfect LLM context for any GitHub repo.
Copied!