# Universal requirement resolver

How StillMade fills Block inputs from upstream outputs, project context and user answers.

# Universal requirement resolver

The public SDK exports `createUniversalResolver()`, the same implementation used
by the Project Type composer, runtime input resolution and native explanations.
The older `block-platform/universal-resolver.js` import reexports this engine.

### Interactive JavaScript user requests

The Node SDK host may explicitly provide `runPackageAsync(..., {requestFromUser})`.
An isolated Block can return `StillMade.requestFromUser('name')` for a missing,
optional, non-context input whose contract allows user answers. Check
`StillMade.resolveRequirement('name').resolved` first. The SDK resumes the code
from its beginning with the validated answer in `input.name`; this is a
cooperative return, not a Promise or an in-sandbox host callback. Avoid emitting
outputs before returning the request. Other inputs remain unchanged.

Both worker boundaries validate the exact declared question and answer. Questions
cannot collect credentials, overwrite existing values, widen permissions, or call
providers. At most 20 questions are allowed. The Node worker pauses its cumulative
five-second execution allowance while waiting, with a five-minute answer deadline;
the guest's cumulative CPU and memory limits remain in force. Cancellation ends the
run. Successful results include `userAnswers` for the host to persist alongside
execution provenance. Hosts without the callback fail closed.

The application browser runner enables this bridge for individual non-batch
JavaScript Step runs. It rechecks project identity, edit access, source admission,
and the captured input snapshot around each question. Reviewed answers become
semantic user values and contribute to the accepted run's input digest and output
dependencies. Other browser callers must explicitly supply both a question handler
and a current-project guard; otherwise interactive requests remain unavailable.
Browser execution pauses its cumulative worker allowance during a bounded question
wait, without expanding the guest CPU allowance. Batch
questions, automatic in-run Chat, and shared credit accounting remain unfinished.

Interactive connected local runs now also forward user requests for JavaScript
Steps with stop-on-error, bounded retry, or approval-before-retry policies, including connected media batches. The workflow
runner independently validates each question, captures the reviewed answer, and
requires the executor to return exactly those answers. The accepted input digest
includes them, and retained results restore/revalidate optional answers without
opening dialogs or rerunning completed Steps. Connected job deadlines still apply;
fallback/recovery policies and unattended runs do not enable these questions.
Retries receive previously reviewed answers as existing inputs instead of asking
again. Each attempt may return only answers newly reviewed during that attempt;
the workflow retains the aggregate and binds it to the successful result. Late
replies from an ended attempt cannot change the retained answer set.

Connected batch questions name the current source asset and version. Answers are
scoped to that target's run and do not silently carry into the next target. Resume
validation binds them to the full source snapshot as well as the package, workflow,
and effective inputs. Standalone single-Step batch previews also enable questions.
Each preview keeps its own reviewed answers and input fingerprint. Using a result
rechecks source, settings and answers, then registers the selected answers and
outputs as the adopted single-Step result. Previews alone do not overwrite saved
answers or advance saved Block memory.

Structured collections use a one-element schema array, such as
`schema: [{word: 'string', start: 'number', end: 'number'}]` on an `object[]`
contract. That schema describes every item, not a tuple or a fixed-length value.
It also works inside object fields. Validation and connection compatibility check
each item's required fields; plain `object[]` cannot promise those fields.
The input dialog collects structured list items using their declared fields.

Built-in connection adapters also support ordered lists when both endpoints are
scalar types with list variants. Each list adapter pins the scalar adapter version,
converts at most 100 items, checks each item, and requires all context grants before
conversion. A failed item rejects the entire conversion; no partial list is emitted.
List-to-scalar flattening, implicit Block fan-out, and nested lists are not inferred.
For example, `text[]` with meaning `narration_script` can supply `script[]` with the
same meaning through `list-text-to-script-v1` version 1. These are local data
conversions, not separately billed provider calls or general workflow batches.

```js
import {createUniversalResolver,input} from './packages/block-sdk/index.js';

const requirement=input({
  key:'company',type:'object',semantic:'company_profile',required:true,
  description:'Company information',schema:{name:'string'},sources:['project']
});
const resolver=createUniversalResolver();
const options={values:[{
  id:'company-profile',revision:1,type:'object',semantic:'company_profile',
  value:{name:'Morning Bakery'},source:{kind:'project'},permissions:[]
}]};
const explanation=resolver.inspect(requirement,options);
const resolved=await resolver.resolve(requirement,options);
```

`inspect` and `explain` return the selected source, reason and candidates.
`listCandidates` returns priority-ordered alternatives. `resolve` checks actual
values and returns source/dependency metadata. A required unresolved input stays
unresolved; a pending callback can return one clarification question.

Pass an explicit semantic registry and versioned adapter registry when needed.
The host may supply `canDerive`, `requestFromChat` and `requestFromUser` callbacks.
No callback is provided automatically. Permission and freshness filtering applies
to context passed to those callbacks; source/schema validation still applies to
their results. Use stable record IDs and revisions for executable values. Plan
mode can inspect declarations that do not yet contain a value; `resolve` always
requires materialized values or an answer callback.

Callbacks receive isolated copies. Final resolution rechecks dependency freshness
after waiting for an answer and rejects expired sources or missing revisions.
The host must still detect edits to the underlying project while resolving; a
copied context snapshot does not subscribe to storage changes.

This is a trusted-host/authoring library, not a new guest API or permission grant.
It does not fetch project data, mutate projects, run Blocks, approve purchases,
authorize credentials, or enforce a provider spending budget. Hosts must retain
their existing scoped storage, sandbox, approval, cancellation and shared-budget
boundaries around integrations. Do not register arbitrary creator code as a host
callback. Download assembly includes this module, but generated download artifacts
must be rebuilt separately.
# Custom meanings and connection checks

Pass the same explicit `semantics` registry to the universal resolver and to
`compatible`, `connectionCompatibility`, `validateConnectionAdapter` and
`adaptConnectionValue`. The optional argument is `{semantics}`; adapter calls
retain their existing permission, context and exact-version pin options.
Inheritance widens only meaning compatibility, never physical types, schemas,
permissions or adapter versions. Without a registry, only the standard semantic
relationships apply. No process-global registry is mutated by these calls.

The application composition helpers accept the same scoped registry for audits,
automatic connection selection, explicit source selection and recommendation
checks. Store reusable definitions in `manifest.semantics`:

```js
semantics: [{
  name: 'creator.example.spoken_copy',
  description: 'Words to read aloud.',
  parents: ['narration_script']
}]
```

Each Block may declare up to 64 namespaced meanings, eight parents per meaning
and 500 description characters. Definitions cannot override unnamespaced standard
meanings. Duplicate names within a Block, cycles, and conflicting parent sets
across selected versions are rejected. Matching definitions may be shared.
The source and release digest includes these declarations; changing a published
definition requires a new release, not editing an immutable version.

`semanticRegistryForManifests(manifests)` reconstructs a scoped registry from
saved contracts. Composer audits and local workflow execution load these package
definitions automatically. Connected execution captures their exact snapshot in
the execution-plan digest. Explicit injected registries are still ephemeral;
only package declarations survive save/reopen. Guest access to arbitrary project
context, generated adapter execution and automatic metered Chat derivation are
separate integrations, not permissions granted by declaring a meaning.

## Direct structured answers

The application's reviewed-answer dialogs collect required schema fields with
typed controls, leaving optional fields unasked and preserving existing optional
answers during edits. Unstructured objects offer named details with text,
number, yes/no, nested-detail, list and empty-value choices. Object and JSON
lists support adding, editing and removing items without requiring JSON syntax.
Primitive schemas on JSON inputs choose the corresponding typed question.

These dialogs serve the existing lazy user resolver, shared-default editor and
connected preview samples. They capture the contract and previous answer before
waiting, validate the final value and return nothing on cancellation. Collection
is bounded to 20 recursive questions, 60 menu choices, 20 detailed list items or
object fields, and the existing 8,000-character scalar/simple-list limits. Larger
answers still need the appropriate settings editor. Source permissions and
credential restrictions remain enforced by the calling resolver; these controls
do not create new runtime authority or automatically invoke Chat.

Single-Step and connected-run missing-answer collection use the same universal
resolver for allowed defaults and user callbacks. A permitted default is selected
before asking; it is not recorded as a user answer. Retained reviewed answers
remain explicit replay inputs. Contract, supplied-input and retained-answer
snapshots are captured before waiting, and callbacks cannot claim dependencies on
unavailable context. Existing host scope checks still reject edits to the real
project during collection. This does not enable automatic paid Chat calls.

## Versioned document conversions

The shared connection registry includes `csv-file-to-table@1`,
`text-to-script@1` and `script-to-text@1`. Visual/native composition, explicit
connection pins and semantic context resolution use the same descriptors.

CSV files must be single inline `.csv` files declared with the `csv` meaning;
the result has the `table` meaning and `{columns, rows}` schema. Archives,
remote media and malformed CSV are rejected. The existing CSV limits and
string-preserving parser apply; cell contents are never executed.

Script conversions preserve semantic compatibility and exact words. Wrapping
adds only `{schemaVersion: 1, text}`; unwrapping requires readable `text` and
does not carry other script metadata into the text output. Neither conversion
turns research notes into narration or invents additional required fields.
Candidate checks validate actual values when present. Version pins, source
policy, inherited permissions and provenance remain enforced. These are
deterministic built-ins, not arbitrary multi-hop or creator-code adapters.

## Conditional SDK Steps

Existing Step conditions support `greater-than`, `at-least`, `less-than` and
`at-most` in addition to presence and equality comparisons. Numeric thresholds
must be finite numbers; missing values, strings and booleans do not satisfy a
numeric comparison. Safe field paths and existing default handling still apply.
The builder and native `set_condition` control share `setProjectTypeCondition`;
use `null` to remove a condition. Native Step inspection includes its condition.

These conditions retain the existing false-case behavior: pass the primary input
unchanged to a single compatible output. They do not create general branches,
invent outputs, enable hosted-workspace conditions or grant execution approval.

Reviewed Chat suggestions share `canSuggestRequirement` eligibility across the
application and server. Supported information includes scalar text/numbers/
booleans, script documents, objects, JSON and their supported lists. Host-bound
context, credential-sensitive inputs and inputs excluding Chat remain ineligible.
The server captures the notes and requirement before waiting and validates the
returned value before issuing matching provenance. This remains a reviewed
suggestion, not automatic workflow dispatch or a budget authorization.

## Saved-project source updates

Project Type connections use the Block's declared input and output contracts,
including Blocks a creator adds later. A reviewed source change updates that
project's binding and marks affected results stale; it does not run a Block.
An explicit affected-Step update can then reuse a current saved upstream value.
The runner pins that value before dispatch and records its producer placement,
output port and run ID in the receiving run's captured input identities. The
pin is checked again during execution, so a changed upstream result requires a
fresh review. Text and structured input contents are not copied into this
identity record; inspect the authorized value separately when needed.

## Recommendation execution evidence

The hosted completion signal uses server-owned, terminal production capability
runs for an exact public release digest over 30 days. It excludes creator
self-use, suspended accounts, revoked releases, previews, cancellation and
unresolved remote work. At least five terminal runs from three users are needed;
each user contributes at most 20 recent runs per release. A smoothed completion
adjustment between minus two and plus two points supplements, but cannot replace, capability coverage
and connection validation. Creator-supplied quality numbers are not used.

This signal measures terminal execution completion, not generated-content
quality, local execution reliability or resistance to coordinated account abuse.
Missing evidence contributes no adjustment and does not mean failure. A measured
completion rate below one half lowers ranking rather than earning a bonus; a
rate of one half is neutral. The response
reports signal availability and the number of measured releases. Cost, latency
and creator reputation remain unmeasured ranking signals.

Visual recommendation Details explains these limits and measured-Block coverage.
Native recommendation inspection includes the same signal availability and
warnings, alongside per-proposal score explanations.

## Guest workspace patch proposals

JavaScript Blocks can call
`StillMade.patchProject(outputKey, {field, title, after})` to emit a reviewed
workspace-edit proposal. Declare a `workspace-edit` output, a matching context
input, and both `context.<field>.read` and `workspace.<field>.propose` permissions.
The helper obtains `before` from the original host-supplied context snapshot,
not the guest's mutable input. It returns no value and uses the ordinary output
collector: emit each output once and do not also return an output object.

This method does **not** apply an edit, save a project, grant permissions or call
the host from the sandbox. Final outputs pass the existing workspace-edit and
permission validators; the host's review and stale-document checks still decide
whether a proposal can be applied. Only existing workspace-edit fields are
supported, not arbitrary project fields or credentials. Guest Chat/user request
bridges and broader project mutation remain separate unfinished integrations.

## Bounded adapter paths

### Creator-owned conversion Blocks

When two admitted Blocks declare incompatible inputs and outputs, the Project
Type builder can search saved Blocks for a real intermediate Step. **Find
converter Blocks** inspects each candidate's versioned ports and source policy;
it does not run the candidate or infer that its result is correct. Choosing one
embeds the exact package version and creates two ordinary typed connections.
The connected runner executes the intermediate Block through its declared
runtime and validates its output before the receiver runs. Saved-project Flow
can search converter packages already embedded in that Project Type and review
the migration before adding an instance. This route preserves each Block's own
implementation and does not install a creator's transform in the trusted host.

The on-demand search discovers paths of up to three intermediate Blocks with
bounded exploration. Longer routes can still be composed as ordinary Steps.
New Marketplace package search from an existing project and full native/hosted
acceptance are still required for general interoperability. A source preview in
the search is never presented as a converter's unrun output.

Trusted resolver callers can opt into `maxAdapterHops: 2` or `3`. The default
remains one for compatibility with existing saved connection pins. Registries
expose `findPaths(source, requirement, options)` and
`applyPath([{id, version}, ...], source, requirement, options)`. Search uses
contract compatibility without executing transforms, examines at most 512
edges and returns at most 16 paths. `inspect` reports `searchTruncated` when
those limits prevent an exhaustive search.

Execution preflights the complete chain's permissions and contracts, validates
each intermediate result, preserves the original source's freshness and returns
provenance containing every conversion pin plus the original source revision.
These are trusted registered adapters, not creator-code execution authority.
Saving and executing chain pins in the visual/native application is not yet
integrated; existing connection paths remain unchanged.
