# Block manifest

Every supported manifest and port field for SDK 0.1.0.

## Package envelope
Recipe packages contain `manifest`, `recipe`, and `tests`. JavaScript packages contain `manifest`, `code`, and `tests`. Unknown envelope and manifest fields are rejected.

## Manifest example
```json
{
  "schemaVersion": 1,
  "license": "MIT",
  "provenance": {
    "notice": "MIT License\n\nCopyright (c) 2026 StillMade SDK contributors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and \nassociated documentation files (the \"Software\"), to deal in the Software without restriction, including \nwithout limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell \ncopies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the \nfollowing conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial \nportions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT \nLIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO \nEVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER \nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE \nUSE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  "sdkVersion": "0.1.0",
  "id": "example.word-count",
  "version": "1.0.0",
  "name": "Word count",
  "description": "Counts words and returns trimmed text using isolated JavaScript.",
  "kind": "task",
  "runtime": "javascript",
  "inputs": {
    "text": {
      "type": "text",
      "semantic": "plain_text",
      "required": true,
      "description": "Text whose surrounding whitespace should be removed."
    }
  },
  "outputs": {
    "text": {
      "type": "text",
      "semantic": "plain_text",
      "description": "The trimmed source text."
    },
    "words": {
      "type": "integer",
      "semantic": "word_count",
      "description": "The number of whitespace-separated words."
    }
  },
  "permissions": {
    "project": [],
    "network": [],
    "filesystem": [],
    "secrets": []
  },
  "ui": [
    {
      "control": "text",
      "port": "text"
    }
  ]
}
```

## Required fields
| Field | Contract |
| --- | --- |
| schemaVersion | Integer 1 |
| sdkVersion | Exact stable version 0.1.0, caret, tilde, or comparator intersection satisfied by this host |
| id | Lowercase namespace.name; sm. is reserved |
| version | Three-part SemVer, such as 1.0.0 |
| name | 1–120 characters |
| description | 1–1000 characters describing behavior |
| kind | task, workspace, editor-extension, or composite |
| runtime | recipe, javascript, reviewed capability, or reviewed comfyui adapter |
| inputs / outputs | Named port objects; at most 64 in each direction |
| permissions | Explicit supported permission families |

## SDK compatibility
The runtime remains SDK `0.1.0`; exact declarations remain valid. A Block may also declare a bounded stable range such as `^0.1.0`, `~0.1.0`, or `>=0.1.0 <0.2.0`. `sdkCompatibility(declared)` reports `supported`, `unsupported` or `invalid` against that actual runtime version. `validateManifest` enforces the same result. A supported range never bypasses permissions, runtime availability, source admission or fixtures.

Supported grammar is an exact stable three-part version, caret, tilde, or up to four space-separated comparator intersections (`=`, `>`, `>=`, `<`, `<=`). Numeric components are bounded to 999999. Tags, prereleases, wildcards, alternatives and hyphen ranges are unsupported. Major-zero caret rules apply: `^0.1.0` excludes `0.2.0`; `^0.0.3` excludes `0.0.4`. A declaration is preserved verbatim in its package identity; changing it requires a new immutable release. Do not widen it merely to silence an incompatibility.

This is compatibility checking, not automatic code adaptation or a promise of future SDK support. Explicit reviewed Step-state migration routes are documented separately; changing an SDK range never runs a migration or changes project pins.

## Port fields
| Field | Meaning |
| --- | --- |
| type | A supported type, optionally followed by [] |
| required | Defaults to required; set false for omission |
| default | Used when no value is supplied; must match the type |
| min / max | Inclusive numeric bounds |
| primary | At most one true per direction |
| role | Lowercase semantic identifier such as source_image |
| context | A supported input-only context field with matching type and permission |
| description | Help text explaining the port |

## Optional metadata
`ui` binds controls to inputs. `license` records source licensing. `provenance` records remix or adaptation origin. `summary` records the source-linked description. `category` groups related capabilities. `entry` is descriptive metadata; execution uses the packed source.

## Platform compatibility
Block cards and listing pages show Phone, Browser, and Desktop SVG indicators.
Phone means a phone browser; Browser means a desktop web browser; Desktop means
the downloaded StillMade app. Add optional `manifest.platforms` to declare all
three environments. Each entry has `supported` (boolean) and an optional `reason`
(up to 240 characters); unsupported environments require a reason. At least one
environment must be supported. For example, a Block with a desktop-only interface:

```json
{
  "platforms": {
    "phone": {"supported": false, "reason": "This interface requires the StillMade desktop app."},
    "browser": {"supported": false, "reason": "This interface requires the StillMade desktop app."},
    "desktop": {"supported": true}
  }
}
```

A declaration is a request to support a platform, **not verification**. An
unsupported declaration keeps that platform unavailable. `supported:true` or an
omitted declaration never lights an icon on its own. Runtime portability does not
prove usable UI. Unknown, stale, or missing checks display **Not verified**.

StillMade's server-owned import and release review runs `testPlatforms` against
the actual working preview, using the same isolated runtime and UI frame as the
app. Reports are stored with the existing import/release report and bound to the
exact source digest. Package-supplied reports are rejected. Changing code, UI,
fixtures, or compatibility metadata invalidates the previous source report.
Built-in audits also track the production UI source fingerprint.

The current `mobile-ui-1` gate checks 320 × 720, 390 × 844, 768 × 1024,
844 × 390 phone landscape, and 1280 × 800 desktop containers in Light, Dark,
and White. It uses the real embedded Block/Project Type host and custom sandbox,
then checks the main touch task, empty/populated/loading/error/success states,
long labels, enlarged text, and continuity through resize, rotation and panel
toggles. Ordinary touch controls target 44 × 44 CSS pixels. Fields require
accessible labels; draggable actions require a visible tap or menu alternative.
Intentional canvas/timeline panning remains distinct from page-wide overflow.
See [Mobile-compatible Block UI](/docs/build/mobile-ui) for authoring patterns.

For a custom interface with multiple buttons, put
`data-stillmade-action="run"` on the button that runs the included sample through
`StillMade.run`. The test clicks that control inside the disposable sandbox;
no generation provider, account API, or device permission can be invoked there.
A single-button interface can use its sole button. Interfaces requiring more
complex interaction remain unverified until their host adapter covers it.

The SDK exports `testPlatforms`, `measurePlatformLayout`,
`assessPlatformCapture`, and `checkedPlatformTargets`. A trusted browser adapter
renders the real interface, calls `measurePlatformLayout` in every frame, tries
its interaction, and returns frames plus interaction, embedding, state, and
continuity evidence. Use the checker in
an external test harness as follows:

```js
const fixtures = await testPackage(pkg);
const devices = await testPlatforms(pkg, {
  runtimePassed: fixtures.passed,
  probe: trustedBrowserAdapter,
});
```

`admitPackage` accepts the same adapter as `platformProbe` and includes
`platformChecks` in its result. Without a browser adapter it reports unverified
platforms; CLI `validate --mobile` exposes the exact required profile but remains
pending until a trusted embedded browser run, and code-only fixture tests never claim device support.
In StillMade, use **Run mobile UI profile** in import review to inspect the
server's result. Import confirmation repeats the server-owned checks.

Cloud-side checks cover Phone and Browser. They do not masquerade as an Electron
check: Desktop stays unverified without an actual desktop-runner report. The
built-in audit runner tests the Electron renderer separately. Browser emulation
is not a physical iOS-device test, and macOS Electron does not certify a Windows
installer or native recording capability. Cloud/ComfyUI operations still require
their normal configured connection; checks never make a paid sample call.

Project Types combine enabled, version-pinned Blocks. An unavailable dependency
makes that platform unavailable; an unverified dependency keeps it unverified.
These indicators do not grant filesystem, process, system recording, or other
native permissions. Unsupported native APIs still fail admission/runtime checks.

## UI schema
Use an array of `{control, port}` objects. Controls are `text`, `number`, `slider`, `checkbox`, and `asset`. Every control binds to a declared input. The host renders these fallback controls in StillMade’s style. A separate package-level `view` may supply a [sandboxed custom interface](/docs/build/custom-interface); it never loads into the parent app DOM.

## Permissions
Supported families are `project`, `network`, `filesystem`, `secrets`, and `capabilities`. Network, filesystem, and secrets arrays must be empty. A capability runtime declares exactly one supported operation: `text.generate`, `audio.speech`, `audio.transcribe`, `audio.music`, `audio.sfx`, `image.generate`, `video.generate`, `image.describe`, `media.analyze`, `web.fetch`, `web.research`, `timeline.propose`, `workspace.propose`, `connection.execute`; reviewed ComfyUI declares `comfyui.execute`. These permissions do not grant JavaScript or a custom interface direct host access. Supported context read permissions are listed in [project context](/docs/build/context).
