create-devstack-app: rebuild around a minimal, survives-into-production template#27
create-devstack-app: rebuild around a minimal, survives-into-production template#27hayes-mysten wants to merge 6 commits into
Conversation
…on template
Replace the 44-file demo-panel gallery (and the app-local plugin framework +
compose-down machinery that existed to serve it) with two small verbatim
templates — `app` (React dapp) and `ts` (headless) — plus ONE rendered file,
devstack.config.ts, generated from the service selection. Every scaffolded
file is meant to be edited and kept, never deleted; rich demos live in
examples/ instead.
Scaffolder: @clack/prompts CLI (Ink/React dropped), --template app|ts,
walrus/seal multiselect (one factory line + SDK dep each; DeepBook dropped —
devstack no longer auto-synthesizes it, README points at
examples/deepbook-trader), --yes default flips to no services. Generated apps
carry no DEVSTACK_APP tokens and no pinned stackName (both inferred from
package.json#name). Templates carry @mysten/signers: dev-wallet's /adapters
entry eagerly requires its optional peer, which only resolves transitively
inside the monorepo — without it the vite dev-wallet virtual module dies at
eval and the wallet silently never registers.
devstack: align the build-integrations discovery ladder with the CLI — the
default stack name now package-infers from the nearest package.json (explicit
> $DEVSTACK_STACK > package name > 'main'), so `pnpm test` finds a bare app's
live stack instead of failing with VitestManifestNotFoundError for 'main'.
Threaded through discover/vitest/playwright/vite call sites; also breaks a
latent two-module import cycle (TDZ) between resolve-discovery-env and
inference-network.
CI: new workflow scaffolds app×{minimal,all} + ts×minimal, installs against
packed workspace tarballs, and runs each app's typecheck (devstack apply +
tsc); devstack-e2e gains a boot smoke that runs `devstack up` on a scaffolded
app and executes its vitest spec against the live stack. The old template was
workspace-excluded and never CI-verified.
Verified locally end-to-end for both templates: scaffold → install →
typecheck → pnpm dev → browser counter create/increment via the dev wallet →
pnpm test green against the live stack, plus the stack-down friendly-error
path (the long-lived router answers dead routes with 404, so the probe now
treats router error statuses as "stack down").
Supersedes the unreleased demo-panels/picker changeset (folded into the new
one).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
commit: |
Published 2026-06-11, it fails `pnpm audit --prod --audit-level high` on every branch including main. The vulnerable path (fumadocs-mdx > esbuild 0.27.4) only matters under Deno's loader; here esbuild runs under Node. The real fix is double-blocked: fumadocs-mdx pins esbuild ^0.27.2 and the patched 0.28.1 is younger than the repo's 2-day minimumReleaseAge gate. Dated revisit note in the comment. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The boot wait polled .devstack/stacks/main/manifest.json, but a bare app's stack is named after the package (stacks/smoke-boot/) via package.json inference — the stack booted in ~3.5min and the step then timed out for 16. Wait on the `codegen.emitted` log line instead: name-blind, and it lands after the manifest flush, guaranteeing src/generated/ is fresh for the assert + pnpm test steps. Also stop uploading the whole .devstack/ tree on failure — package cache keys contain `::`, which upload-artifact rejects; keep just the manifests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
@clud-bot review |
…-tag composition New stack option passed through to @mysten/codegen's generateFromPackageSummary. Off (default), structs whose type parameters are all phantom render as plain consts with the phantoms erased from the BCS name — unusable as concrete type tags. On, they render as factories whose phantom parameters are REQUIRED BcsType arguments, and the returned class's .name is the fully-qualified, type-level-tracked tag — so tags compose by nesting (`Receipt(Vault(USDC)).name`) instead of being spelled by hand. Threaded as a static per-stack option: substrate options → resolveProductionCodegenOptions → layerMystenMoveCodegen(options) factory → generateFromPackageSummary. Default unchanged. Docs: new "Phantom type parameters and type tags" section in devstack/features/codegen.mdx covering the setting and showing type arguments in both forms — hand-written strings (nested tags included) and composed generated BCS classes via .name. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Review: APPROVE ✅
Reviewed via deep multi-lens analysis (correctness, concurrency, security, docs) with the repo on disk. Installed deps, built @mysten-incubation/devstack, and ran the touched suites.
Tests: create-devstack-app 30/30 pass. PR-touched devstack build-integration suites (discover, vitest/env, vitest/setup, vitest/stack-context, playwright/stack-context) 85/85 pass. The only failures were environmental (missing dist before build, missing sui/docker toolchain) — no PR regressions.
Key claims verified:
- Import-cycle break (TDZ):
inference-network.tsimports nothing back fromresolve-discovery-env.ts— one-way diamond, no TDZ under any import order. - Stack-name ladder: the
cwdrung is threaded intoresolveDiscoveryEnvat every manifest-locating call site (discover.ts,vite/index.ts,vitest/stack-context.ts,playwright/stack-context.ts), so discovery agrees withdevstack upon the package-inferred stack.cold-start-url.tsdeliberately omits the package rung andglobal-setup.tsomitscwd— both intentional and tested. - render-config.ts: all 8
{app,ts} × {∅,walrus,seal,walrus+seal}combinations emit declaration-ordered symbols with exactly-matching imports — no dead/missing imports, no undeclared references. - Security:
NAME_REgates the name before any spawn; allspawn/spawnSyncuse arg arrays with noshell:true; only closed enums reach the rendered config — no injection path.
Findings (minor only)
examples/README.md(~L37-42): the "Adding An Example" section still points to the deletedpackages/create-devstack-app/template/dir and describes removed features (core/walrus/seal/deepbook panels, the e2e spec,DEVSTACK_APPtoken rewriting). Not in the diff and nothing breaks, but it now misleads anyone following it — worth updating to the new two-template / inferred-identity design.src/bin.ts— flag-value parsing can swallow a following flag token; pre-existing, not a regression (inline note left).
No critical or major issues. The substrate inference-ladder fix, the cycle break, the CLI rewrite, and the rendered-config logic are all correct and well-covered.
| } | ||
| } else if (arg !== undefined && arg.startsWith('--plugins=')) { | ||
| pluginsFlag = arg.slice('--plugins='.length); | ||
| return argv[i]; |
There was a problem hiding this comment.
Minor (not a regression): valueOf lets a value-taking flag swallow a following flag token — --target-dir --yes my-app sets targetDir = '--yes'. This is standard getopt behavior and identical to the pre-PR implementation, so nothing breaks for normal invocations. A argv[i]?.startsWith('--') guard would harden it if you care.
…ct + scaffolder Split the conflated `chain` concept into three precise ones across devstack + dev-wallet: `network` (the network name), `chainId` (the genesis-transaction digest, unique per spun-up network), and the wallet-standard `sui:<network>` chain name (derived only at the dev-wallet boundary — `sui:` never appears in devstack internals). Deletes NETWORK_ALIASES, drops the `local` shorthand, canonicalizes the codegen active-network key (`local` → `localnet`), and fixes a latent deepbook DEEP-funding gate that compared a genesis digest against the `'sui:testnet'` literal. BREAKING: invalidates on-disk local state keyed by the old `sui:local` brand — run `devstack wipe`. - devstack vite plugin: `optimizeDeps.include` + Lit `resolve.dedupe` fixes the injected dev wallet's `Illegal constructor` / unusable-reconnect failure. - dev-wallet: injected wallet bundles a WebCryptoSignerAdapter so users can create their own (IndexedDB-persisted) accounts; the inject + DevWalletConfig API take `network` instead of `chain`; exposes a single localnet network. - dashboard: `print-schema` now formats via prettier (schema.graphql is byte-stable, no more generated-vs-formatted flutter); GraphQL surfaces `chainId` (sui) / `network` (deepbook). - create-devstack-app: templates approve native build scripts via both `pnpm.onlyBuiltDependencies` (pnpm 10) and `allowBuilds` (pnpm 11) — fixes stock pnpm-11 `ERR_PNPM_IGNORED_BUILDS` on `pnpm install` / `pnpm dev`. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bumps the dapp-kit / vite / typescript toolchain (catalog -> dapp-kit-core 1.6, dapp-kit-react 2.x, vite 8) and resolves the fallout: - Wallet connect: dapp-kit 1.6 rewrote auto-connect into a two-phase "reconnecting" state machine, which broke the dev wallet's localStorage-seeding hack. The dev wallet no longer pre-connects or seeds dApp Kit storage; a page loads disconnected and autoConnect only restores a genuine prior session. A new DEV-only devstack `/dapp-kit` entry (registerDAppKitForTesting) publishes the `connectAs` slot, which drives a real connection through dApp Kit's public connectWallet/switchAccount (resolving accounts by label). The dev wallet auto-approves standard:connect only under autoApprove (the headless-e2e signal). - deepbook-trader: read networkEndpoints.chainId (codegen emits chainId, not chain) so the app renders instead of crashing on shortId(undefined). - dev-wallet demo: add src/vite-env.d.ts (fixes TS2882 on the CSS side-effect import under the upgraded TypeScript). - Docs: document the new /dapp-kit export (README + CHANGELOG) + changeset. Green: lint, typecheck, 1915 unit tests, devstack package e2e (19/19, incl. the snapshot-restore matrix and per-app cold-boot suites), and all four example Playwright e2e suites. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Summary
pnpm create @mysten-incubation/devstack-appcurrently scaffolds 44 files / ~2,000 lines, most of which a real app deletes on day one: four demo panels, per-service helper libs, a demovaultMove package, Playwright specs, and an app-local plugin framework (src/devstack/contribution.ts+ two generated barrels) that exists only so the scaffolder can compose by deleting files. This PR rebuilds the tool around one rule: every generated file survives into a real app — it gets edited, never deleted.templates/app(React dapp: vite + dapp-kit + dev wallet, ~19 files) andtemplates/ts(headless, ~10 files). OnecounterMove package, one screen/module driving it through the generated bindings, one vitest spec that runs against the live stack. Demos live inexamples/.devstack.config.tsis generated from the service selection as straight-linedefineDevstack({ members }), exactly like the documented API. No barrels, no contribution framework.examples/deepbook-traderinstead.DEVSTACK_APP=script tokens and no pinnedstackName(both inferred frompackage.json#name); the only package.json mutations are name, service-dep pruning, and SDK version injection.--template app|ts,--services walrus,seal,--all,--minimal,--yes(default flipped to no services),--target-dir,--no-install,--no-git, plus a non-fatal Docker preflight.PLUGIN_MANIFEST,compose.ts, dangling-import scanner, Ink picker) is deleted. Net −2,641 lines.devstack collateral fix
The end-to-end smoke surfaced a real substrate bug: the CLI resolves the stack name as flag > env > package.json name >
'main', but the build-integrations discovery ladder skipped the package-inference rung — sopnpm testin a bare app looked forstacks/main/while the supervisor wrotestacks/<name>/(VitestManifestNotFoundError). The shared ladder now package-infers (opt-incwdrung, threaded through discover/vitest/playwright/vite call sites), and a latent two-module import cycle (TDZ hazard) betweenresolve-discovery-envandinference-networkis broken. Separate changeset, patch bump.Two more standalone-consumer bugs fixed in the templates:
@mysten/signersadded as a dep (dev-wallet's/adaptersentry eagerly requires its optional peer; inside the monorepo it resolves transitively, outside it the dev-wallet virtual module dies at eval and the wallet silently never registers), and the test liveness probe treats router 404/5xx as "stack down" (the long-lived router answers routed hostnames even when the stack is dead).CI
New
create-devstack-app.ymlscaffoldsapp×{minimal,all}+ts×minimal, installs against packed workspace tarballs (same mechanism assmoke:pack-consumer), and runs each app'spnpm typecheck(=devstack apply+ tsc).devstack-e2e.ymlgains a boot smoke: scaffold →devstack up→ assert bindings → run the app's vitest spec live → teardown. The old template was workspace-excluded and never CI-verified.Verification (local, Docker)
Both templates, full path: scaffold → install (tarball overrides) →
pnpm typecheck(boots chain, publishes counter, generatessrc/generated/, tsc green) →pnpm dev→ browser walkthrough on the routed origin: dev wallet auto-connects, counter created and incremented 0→1 on-chain →pnpm testgreen against the live stack → stack-down run shows the friendly "start the stack withpnpm dev" error. Repo-wideturbo lint/build/test+ oxlint green.Notes for review
dev.<name>.<name>.localhostdoubled hostnames; cold-start conventional URLs still assume stack'main';sui-rpc/rpcendpoint-name aliasing gap;devstackVitestTestConfig({testSetup})is a silent no-op.🤖 Generated with Claude Code
AI Assistance Notice