@mindstudio-ai/remy 0.1.294 → 0.1.296

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,4 +2,19 @@
2
2
  trigger: reviseFromAnnotatedImage
3
3
  ---
4
4
 
5
- This is an automated message triggered by the user submitting a screenshot of the app that they have annotated with text notes. Please analyze the provided image and make the requested revisions to the web interface.
5
+ This is an automated message triggered by the user marking up a frozen screenshot of the app to request revisions. You receive two channels that must be read together:
6
+
7
+ **The image**: a viewport capture of the app with the user's annotations drawn on top in magenta (#FF2D8E) with white outlines. Every annotation carries a small numbered badge; that number is the same `index` in the `notes` params below.
8
+
9
+ **The `notes` params**: an array of `{ index, type, note, coords, voice? }` — one entry per annotation, in the same order as the numbered badges. `note` is the user's text verbatim (authoritative — do not re-read it from the image). `coords` are normalized 0–100 percentages of the image (x/y point, x1/y1→x2/y2 endpoints, or x/y/w/h bounds).
10
+
11
+ Annotation types and what they mean:
12
+ - `pin` — "this element here": a dot anchored on the thing the note is about.
13
+ - `region` — a box outlining an area the note applies to.
14
+ - `arrow` — a directional gesture from one place to another, usually "move this from here to there"; x1/y1 is the origin (where the label sits), x2/y2 the destination.
15
+ - `draw` — a freehand loop or stroke circling/indicating something; use its bounds.
16
+ - `measure` — a dimension bracket across a gap or span; the note is prefixed with the measured distance in page pixels (e.g. "96 · tighten this gutter").
17
+ - `text` — a floating comment about the general area it sits in, not anchored to a specific element.
18
+ - `voice` — a spoken note anchored at a point; `note` (and `voice.transcript`) is the transcript. The image shows only the numbered mic marker.
19
+
20
+ Use the image to see exactly what each numbered annotation points at, and the params for the exact intent. Make the requested revisions to the web interface, addressing every note.
package/dist/headless.js CHANGED
@@ -1392,7 +1392,7 @@ async function listRecursive(dir) {
1392
1392
  var presentPublishPlanTool = {
1393
1393
  definition: {
1394
1394
  name: "presentPublishPlan",
1395
- description: "Present a publish changelog to the user for approval \u2014 the consent gate of the release flow, used when the user has asked to publish (the Publish button or an explicit chat request; the `publishing` skill covers the full sequence). Write a clear markdown summary of what changed since the last deploy. The user will see this in a full-screen view and can approve or dismiss. Call this BEFORE committing or pushing.",
1395
+ description: "Present a publish changelog to the user for approval \u2014 the consent gate of the release flow, used when the user has asked to publish (the Publish button or an explicit chat request; the `publishing` skill covers the full sequence). Write a clear markdown summary of what changed since the last deploy. The user reviews this in the editor area and can approve or dismiss. Call this BEFORE committing or pushing.",
1396
1396
  inputSchema: {
1397
1397
  type: "object",
1398
1398
  properties: {
@@ -1527,7 +1527,7 @@ var markBuildCompleteTool = {
1527
1527
  var promptUserTool = {
1528
1528
  definition: {
1529
1529
  name: "promptUser",
1530
- description: 'Ask the user structured questions. Choose type first: "form" for structured intake (5+ questions, takes over screen), "inline" for quick clarifications or confirmations. Blocks until the user responds. Result contains `_dismissed: true` if the user dismisses without answering.',
1530
+ description: 'Ask the user structured questions. Choose type first: "form" for structured intake (5+ questions, opens as a full form in the editor area), "inline" for quick clarifications or confirmations. Blocks until the user responds. Result contains `_dismissed: true` if the user dismisses without answering.',
1531
1531
  inputSchema: {
1532
1532
  type: "object",
1533
1533
  properties: {
@@ -5656,7 +5656,7 @@ var WIREFRAMES_DIR = "src/.wireframes";
5656
5656
  var UPLOAD_TIMEOUT_MS2 = 3e4;
5657
5657
  var definition10 = {
5658
5658
  name: "createWireframe",
5659
- description: "Generate a wireframe from self-contained HTML+CSS you author and write it to disk as a design artifact. This is how a wireframe comes to exist \u2014 the way generateImages is how an image comes to exist \u2014 and the developer builds from the file it creates. The result also hands back the reference line that embeds the wireframe in your response and in specs; paste it wherever the wireframe belongs and it renders as a live preview. Calling again with the same slug revises the wireframe in place, so existing references stay current.",
5659
+ description: "Generate a wireframe from self-contained HTML+CSS you author and write it to disk as a design artifact. This is how a wireframe comes to exist \u2014 the way generateImages is how an image comes to exist \u2014 and the developer builds from the file it creates. The result also hands back the reference line that embeds the wireframe in your response and in specs; paste it wherever the wireframe belongs and it renders as a live preview. Calling again with the same slug revises the wireframe in place, so existing references stay current \u2014 a revision is a call to this tool, never a prose description of changes to an earlier wireframe.",
5660
5660
  inputSchema: {
5661
5661
  type: "object",
5662
5662
  properties: {
@@ -5674,7 +5674,7 @@ var definition10 = {
5674
5674
  },
5675
5675
  html: {
5676
5676
  type: "string",
5677
- description: "The complete HTML document (<html>\u2026</html>), self-contained vanilla HTML/CSS/JS. No frontmatter \u2014 it is added for you."
5677
+ description: "The complete HTML document (<html>\u2026</html>), self-contained vanilla HTML/CSS/JS. Transparent body \u2014 the preview supplies the backdrop; style the component container instead. No frontmatter \u2014 it is added for you."
5678
5678
  }
5679
5679
  },
5680
5680
  required: ["name", "slug", "description", "html"]
package/dist/index.js CHANGED
@@ -872,7 +872,7 @@ var init_presentPublishPlan = __esm({
872
872
  presentPublishPlanTool = {
873
873
  definition: {
874
874
  name: "presentPublishPlan",
875
- description: "Present a publish changelog to the user for approval \u2014 the consent gate of the release flow, used when the user has asked to publish (the Publish button or an explicit chat request; the `publishing` skill covers the full sequence). Write a clear markdown summary of what changed since the last deploy. The user will see this in a full-screen view and can approve or dismiss. Call this BEFORE committing or pushing.",
875
+ description: "Present a publish changelog to the user for approval \u2014 the consent gate of the release flow, used when the user has asked to publish (the Publish button or an explicit chat request; the `publishing` skill covers the full sequence). Write a clear markdown summary of what changed since the last deploy. The user reviews this in the editor area and can approve or dismiss. Call this BEFORE committing or pushing.",
876
876
  inputSchema: {
877
877
  type: "object",
878
878
  properties: {
@@ -1039,7 +1039,7 @@ var init_promptUser = __esm({
1039
1039
  promptUserTool = {
1040
1040
  definition: {
1041
1041
  name: "promptUser",
1042
- description: 'Ask the user structured questions. Choose type first: "form" for structured intake (5+ questions, takes over screen), "inline" for quick clarifications or confirmations. Blocks until the user responds. Result contains `_dismissed: true` if the user dismisses without answering.',
1042
+ description: 'Ask the user structured questions. Choose type first: "form" for structured intake (5+ questions, opens as a full form in the editor area), "inline" for quick clarifications or confirmations. Blocks until the user responds. Result contains `_dismissed: true` if the user dismisses without answering.',
1043
1043
  inputSchema: {
1044
1044
  type: "object",
1045
1045
  properties: {
@@ -6998,7 +6998,7 @@ var init_createWireframe = __esm({
6998
6998
  UPLOAD_TIMEOUT_MS2 = 3e4;
6999
6999
  definition10 = {
7000
7000
  name: "createWireframe",
7001
- description: "Generate a wireframe from self-contained HTML+CSS you author and write it to disk as a design artifact. This is how a wireframe comes to exist \u2014 the way generateImages is how an image comes to exist \u2014 and the developer builds from the file it creates. The result also hands back the reference line that embeds the wireframe in your response and in specs; paste it wherever the wireframe belongs and it renders as a live preview. Calling again with the same slug revises the wireframe in place, so existing references stay current.",
7001
+ description: "Generate a wireframe from self-contained HTML+CSS you author and write it to disk as a design artifact. This is how a wireframe comes to exist \u2014 the way generateImages is how an image comes to exist \u2014 and the developer builds from the file it creates. The result also hands back the reference line that embeds the wireframe in your response and in specs; paste it wherever the wireframe belongs and it renders as a live preview. Calling again with the same slug revises the wireframe in place, so existing references stay current \u2014 a revision is a call to this tool, never a prose description of changes to an earlier wireframe.",
7002
7002
  inputSchema: {
7003
7003
  type: "object",
7004
7004
  properties: {
@@ -7016,7 +7016,7 @@ var init_createWireframe = __esm({
7016
7016
  },
7017
7017
  html: {
7018
7018
  type: "string",
7019
- description: "The complete HTML document (<html>\u2026</html>), self-contained vanilla HTML/CSS/JS. No frontmatter \u2014 it is added for you."
7019
+ description: "The complete HTML document (<html>\u2026</html>), self-contained vanilla HTML/CSS/JS. Transparent body \u2014 the preview supplies the backdrop; style the component container instead. No frontmatter \u2014 it is added for you."
7020
7020
  }
7021
7021
  },
7022
7022
  required: ["name", "slug", "description", "html"]
@@ -153,4 +153,4 @@ Consider the ways in which AI can be incorporated into backend methods to solve
153
153
 
154
154
  ### Task Agents
155
155
 
156
- For multi-step tasks where the model needs to autonomously compose actions (research + scrape + generate, enrichment pipelines, content creation), use `runTask()` instead of chaining actions manually. It runs an agent loop and returns structured JSON. Its tools can include SDK actions as well as your app's own methods, so the agent can read your data to decide what to do next and write results back itself. Load the `taskAgents` skill before writing one — it is the full reference.
156
+ For multi-step tasks where the model needs to autonomously compose actions (research + scrape + generate, enrichment pipelines, content creation), use `runTask()` instead of chaining actions manually. It runs an agent loop and returns structured JSON. Its tools can include SDK actions, your app's own methods, and inline functions defined at the call site, so the agent can read your data to decide what to do next and write results back itself. Load the `taskAgents` skill before writing one — it is the full reference.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: Task Agents
3
- what: A full autonomous agent loop callable from any method. Give it a prompt, a set of tools, and a JSON Schema for the output shape; the platform runs the model until it produces validated output matching that schema — searching, scraping, generating images, retrying approaches that failed, and calling your app's own methods to read and write data as it goes. Tools can be any of the 1000+ SDK actions and your own methods in any combination, which is what makes it part of the app rather than a detached research bot. This is the difference between a feature that saves what the user typed and one that researches, enriches, and creates on their behalf, and it is one of the most powerful things the platform can do. Consider it whenever a feature would be dramatically more compelling if the app could do real work autonomously.
3
+ what: A full autonomous agent loop callable from any method. Give it a prompt, a set of tools, and a JSON Schema for the output shape; the platform runs the model until it produces validated output matching that schema — searching, scraping, generating images, retrying approaches that failed, and calling your app's own methods to read and write data as it goes. Tools can be any of the 1000+ SDK actions, your own methods, and inline functions defined at the call site, in any combination, which is what makes it part of the app rather than a detached research bot. This is the difference between a feature that saves what the user typed and one that researches, enriches, and creates on their behalf, and it is one of the most powerful things the platform can do. Consider it whenever a feature would be dramatically more compelling if the app could do real work autonomously.
4
4
  when: Before writing any `mindstudio.runTask()` call — background enrichment, research-and-generate, anything where the model decides its own next step.
5
5
  ---
6
6
 
@@ -10,7 +10,7 @@ A user types the name of a restaurant into your app, or uploads a photo of a sto
10
10
 
11
11
  `runTask()` makes this possible. It runs a multi-step, tool-use agent loop: give it a prompt, a set of tools, and a JSON Schema for the structured output you want (`outputSchema`). The platform runs the loop (calling the model, executing tool calls, feeding results back) until the model produces JSON conforming to your schema — validated every turn, with automatic repair when it doesn't. `result.output` is typed by inference from the schema: no generic argument, no manual validation. The model decides what to do next based on intermediate results — retrying searches with different terms, working around failed tools, batching independent calls in parallel.
12
12
 
13
- Tools are **SDK actions** (`searchGoogle`, `generateImage`, …) and **your own app's methods** (`{ appMethod: 'save-vendor' }`), in any combination. That second half is what makes a task agent part of your app rather than a detached research bot: it can read your tables to decide what to do next, and write results back itself instead of handing them to you to persist.
13
+ Tools are **SDK actions** (`searchGoogle`, `generateImage`, …), **your own app's methods** (`{ appMethod: 'save-vendor' }`), and **inline functions** (`{ name, description, inputSchema, execute }` — a function defined right in the calling method), in any combination. The latter two are what make a task agent part of your app rather than a detached research bot: it can read your tables to decide what to do next, and write results back itself instead of handing them to you to persist.
14
14
 
15
15
  This is one of the most powerful pieces of the MindStudio SDK, and it can turn an app from amazing into truly magical. Use `askMindStudioSdk` to help construct the right agent for a task — including which model to give it.
16
16
 
@@ -129,6 +129,14 @@ tools: [
129
129
  // One of your app's own methods — note `appMethod`, not `method`
130
130
  { appMethod: 'listVendorsMissingContacts', description: 'Vendors with no email on file. Call this first to decide what needs researching.' },
131
131
  { appMethod: 'updateVendor', description: 'Write researched contact details back. One call per vendor.' },
132
+
133
+ // An inline function — runs right here in your process
134
+ {
135
+ name: 'checkDomainReputation',
136
+ description: 'Look up a domain in our internal blocklist. Call before trusting a scraped site.',
137
+ inputSchema: { type: 'object', properties: { domain: { type: 'string' } }, required: ['domain'] },
138
+ execute: async (input) => BlockedDomains.find(String(input.domain)),
139
+ },
132
140
  ]
133
141
  ```
134
142
 
@@ -151,6 +159,25 @@ Keep them short and task-specific. Say when to reach for it and when not to, sin
151
159
  - Method calls run in parallel with everything else in the turn, so don't expose two methods that would conflict if called simultaneously.
152
160
  - Cost from inside a method (its own model calls) doesn't appear in the task's `usage.totalBillingCost`. It's billed and attributed to that method, just not rolled into the task total.
153
161
 
162
+ ### Inline function tools
163
+
164
+ `{ name, description, inputSchema, execute }` defines a tool right in the calling method — the function executes in your process when the model calls it. Use it for task-private glue that doesn't deserve to be an app method: a lookup against your tables framed exactly for this task, a computation, a check against data the task closed over. If the capability should exist in the app in its own right (invocable, authorized, visible in the manifest), make it a method and expose it with `appMethod` instead.
165
+
166
+ ```typescript
167
+ {
168
+ name: 'checkExisting',
169
+ description: 'Look up whether we already track this vendor. Call before researching one.',
170
+ inputSchema: { type: 'object', properties: { name: { type: 'string' } }, required: ['name'] },
171
+ execute: async (input) => Vendors.findByName(String(input.name)),
172
+ }
173
+ ```
174
+
175
+ - The `description` is required — it is everything the model knows about the tool. `inputSchema` is optional; omitted means the tool takes no arguments.
176
+ - A thrown error is fed back to the model as `{ error: message }` tool output to work around — it never fails the task. Throw informative errors, same as app methods.
177
+ - No `defaults` — the function is your code; close over whatever it needs.
178
+ - Names share the flat tool namespace: 1–64 chars of letters, digits, `_`, `-`, and no collisions with SDK action names.
179
+ - Calling `runTask()` from inside a function tool is not blocked the way it is from a method tool — the depth cap doesn't apply, so unbounded recursion (and its cost) is yours to prevent. Nest deliberately or not at all.
180
+
154
181
  ## Voice & Tone in Prompts
155
182
 
156
183
  When a task agent produces user-facing text, the prompt must state the voice and tone it should write in. Specify the desired voice explicitly, and rule out emojis, em dashes, and other "ai-isms" — the output goes straight to the user, so nothing downstream will catch them.
@@ -161,7 +188,7 @@ When a task agent produces user-facing text, the prompt must state the voice and
161
188
  |-------|----------|---------|-------------|
162
189
  | `prompt` | Yes | — | System prompt defining the agent's behavior |
163
190
  | `input` | Yes | — | Structured input (passed as user message) |
164
- | `tools` | Yes | — | SDK action names and/or `{ appMethod, description }` entries, each with optional `defaults` |
191
+ | `tools` | Yes | — | SDK action names, `{ appMethod, description }` entries (each with optional `defaults`), and/or inline `{ name, description, inputSchema, execute }` function tools |
165
192
  | `outputSchema` | One of these two | — | Plain JSON Schema for the output (`type`/`properties`/`required`/`enum`/`items`; nullable via type arrays, never `nullable: true`; no `oneOf`/`$ref`). Validated every turn with automatic repair; `result.output` typed from the schema. Use this |
166
193
  | `structuredOutputExample` | One of these two | — | Legacy: object or JSON string showing expected output shape, unvalidated. Use realistic example values, not placeholders like `'string'`, and always check `parsedSuccessfully` |
167
194
  | `model` | Yes | — | Model ID (must support tool use). Ask `askMindStudioSdk` for the right one — MindStudio's ids don't match vendor ids, so a plausible-looking guess is usually wrong |
@@ -29,7 +29,7 @@ Process logs are available at .logs/ in NDJSON format (one JSON object per line)
29
29
  ### MindStudio SDK
30
30
  For any work involving AI models, external actions (web scraping, email, SMS), or third-party API/OAuth connections, prefer the `@mindstudio-ai/agent` SDK. It removes the need to research API methods, configure keys and tokens, or require the user to set up developer accounts.
31
31
 
32
- For multi-step tasks with branching logic (research, enrichment, content pipelines), use `runTask()` instead of manually chaining SDK actions. It runs an autonomous agent loop that composes tools, retries on failure, and returns structured JSON. Tools are SDK actions and your own app methods — the agent can read app state to decide what to do next and persist results itself. See the task agents reference for details.
32
+ For multi-step tasks with branching logic (research, enrichment, content pipelines), use `runTask()` instead of manually chaining SDK actions. It runs an autonomous agent loop that composes tools, retries on failure, and returns structured JSON. Tools are SDK actions, your own app methods, and inline functions defined at the call site — the agent can read app state to decide what to do next and persist results itself. See the task agents reference for details.
33
33
 
34
34
  For methods that take more than a few seconds, use `stream()` from `@mindstudio-ai/agent` to push real-time progress to the frontend. Pipe `onLog` from SDK actions through `stream()` so users see what's happening. The frontend calls the method with `stream: true` and gets updates via `onToken`. See the methods reference for the full pattern.
35
35
 
@@ -28,6 +28,8 @@ The user can already see your tool calls, so most of your work is visible withou
28
28
 
29
29
  Skip the rest: narrating what you're about to do, restating what the user asked, explaining tool calls they can already see.
30
30
 
31
+ You and the editor are two sides of one screen: chat on the left, editor area on the right — the live app preview, plans presented for approval, the file browser, the code editor. The user is looking at both. Don't describe the interface or where things sit on screen; refer to actions and let the UI speak for itself. "Approve the plan when you're ready," not "click approve on the plan to your right."
32
+
31
33
  ### User attachments
32
34
  When a user uploads a file (PDF, Word doc, image, etc.), it is automatically saved to `src/.user-uploads/` in the project directory. The message includes the local file path, and for documents with extractable text, a `.txt` sidecar with the extracted content you can read with `readFile`. A document marked "no extracted text — raw file only" has no sidecar: parse the raw file yourself, and if it is genuinely unreadable, tell the user what happened. Pass the file path itself to tools that take an image — `screenshot`, and the design expert's `analyzeImage` / `analyzeDesign` / `editImages` — and they host the file and hand back a URL you can reuse or embed in a spec. If a raw file from `src/` needs to be served by the web interface, copy it to `dist/interfaces/web/public/`. These files persist across the conversation — they survive compaction and session restarts. Do not ask the user to re-upload a document that has already been saved. Voice messages are not saved to disk — their transcripts appear inline in the message.
33
35
 
@@ -12,7 +12,7 @@ Your designer. Consult for any visual decision — choosing a color, picking fon
12
12
 
13
13
  The design expert cannot see your conversation with the user, so include relevant context and requirements in your task. It can, however, see its past conversation with you, as well as the raw spec files, so you don't need to re-summarize everything it already knows. Just describe what's needed now and reference prior work naturally ("the user wants the colors warmer" is enough if the designer already built the palette). It can take screenshots of the app preview on its own (you need to give it paths to different pages if it needs them - it can't navigate by clicking) — just ask it to review what's been built. It has curated font catalogs and design inspiration built in — don't ask it to research generic inspiration or look up "best X apps." Only point it at specific URLs if the user references a particular site, brand, or identity to match.
14
14
 
15
- The designer will return concrete resources: hex values, font names with CSS URLs, image URLs, layout descriptions, as well as specific techniques, CSS properties, animation timings, code snippets, and other values. Even if these don't seem important, it is critical that you note them in spec annotations and rely on them while building - the user cares about design almost above all else, and it is important to be extremely precise in your work. The designer can also return code-fenced typography and color schemes (self-contained HTML and CSS) - write these directly into specs for future reference. Wireframes arrive as file references like `![Feed Post Card](src/.wireframes/feed-post-card.html)`: copy the reference line into specs verbatim (it renders as a visual preview in chat and in the spec), and read the file at that path while building to get the exact markup and CSS the designer specified. When the designer revises a wireframe it overwrites the same path, so existing references stay current.
15
+ The designer will return concrete resources: hex values, font names with CSS URLs, image URLs, layout descriptions, as well as specific techniques, CSS properties, animation timings, code snippets, and other values. Even if these don't seem important, it is critical that you note them in spec annotations and rely on them while building - the user cares about design almost above all else, and it is important to be extremely precise in your work. The designer can also return code-fenced typography and color schemes (self-contained HTML and CSS) - write these directly into specs for future reference. Wireframes arrive as file references like `![Feed Post Card](src/.wireframes/feed-post-card.html)`: copy each reference line verbatim into the relevant spec AND into your reply to the user (it renders as a live visual preview in both places the designer's work is invisible to the user unless you surface it), and always read the file at that path before building the piece it specifies. The designer's prose summary is not the deliverable; the file carries the exact markup and CSS, and building from the summary alone loses the details the designer resolved. When the designer revises a wireframe it overwrites the same path, so existing references stay current.
16
16
 
17
17
  When delegating, describe the design problem — where the asset will be used, what it needs to communicate, what the brand feels like. Do not specify technical details like image formats, pixel dimensions, generation techniques, or workarounds. The design expert makes those decisions.
18
18
 
@@ -66,13 +66,13 @@ When a plan includes multiple screens/API calls, always note this item for the d
66
66
 
67
67
  - **Manual multi-step chains that should be `runTask()`.** If a method chains AI-driven work with branching logic (search, then scrape based on results, then generate based on what was scraped), that's a `runTask()` use case. `runTask()` runs an agent loop that autonomously calls tools and returns structured JSON. The developer writes a prompt and a JSON Schema for the output (`outputSchema`) instead of imperative code. Flag when you see methods with complex sequential/branching chains — especially research, enrichment, or content generation pipelines. Similarly, flag opportunities where the developer might not have realized they could get better and richer data via runTask - it's a really powerful lever for working with data (e.g., user provides some fragment and agent task goes off and enriches it) that the developer might not have remembered when planning their work.
68
68
 
69
- Tools are SDK actions **and the app's own methods** (`{ appMethod: 'save-vendor', description: '...' }`), which widens this considerably. The pattern most worth looking for: work that needs to *read* app state to decide what to do next (fetch rows, loop, research each, update each) hand-rolled as a loop, when the agent could take a read method and a write method and exercise the judgment itself. App methods run as the invoking user with their roles, so authorization is unchanged.
69
+ Tools are SDK actions, **the app's own methods** (`{ appMethod: 'save-vendor', description: '...' }`), and **inline functions** (`{ name, description, inputSchema, execute }` — task-private glue that runs in the method's own process), which widens this considerably. The pattern most worth looking for: work that needs to *read* app state to decide what to do next (fetch rows, loop, research each, update each) hand-rolled as a loop, when the agent could take a read method and a write method and exercise the judgment itself. App methods run as the invoking user with their roles, so authorization is unchanged.
70
70
 
71
71
  Two things NOT to flag. A deterministic sequence that happens to touch several methods — if the order is known up front and no judgment is involved, imperative code is correct and cheaper. And the fire-and-forget background pattern, where a method kicks off `runTask()` and writes the result back in `.then()` with failures landing in `.catch()`: that write-back is doing status management the agent can't do for itself. That one is the recommended pattern, not a smell.
72
72
 
73
73
  - **Task agent tool descriptions missing or recycled.** When a plan exposes app methods to `runTask()`, each entry should carry an inline `description` written for *that* task — when to call it, when not to, what to do with the result. Falling back to the method's own description is allowed but usually too generic, and the description is the main thing determining whether the agent uses the tool correctly. Flag entries with no description, or the same description pasted across different tasks.
74
74
 
75
- - **A method exposed as a task tool that itself calls `runTask()`.** Task agents can't nest — the inner call is rejected at runtime. Flag it and suggest flattening the decomposition.
75
+ - **A method exposed as a task tool that itself calls `runTask()`.** Task agents can't nest through method tools — the inner call is rejected at runtime. Flag it and suggest flattening the decomposition. An inline function tool calling `runTask()` is different: it is NOT blocked by the platform (no depth cap applies), so accidental recursion runs unbounded and burns credits per turn. Flag it unless the nesting is clearly deliberate and bounded.
76
76
 
77
77
  - **MindStudio SDK `runTask()` output used without validation — check which output option the call uses.** With `outputSchema` (the current, preferred form): the SDK validates every turn and throws `MindStudioError` `code === 'task_output_schema_mismatch'` instead of returning garbage, so using `result.output` directly is correct — flag only a missing `.catch()`/`try-catch` where the failure would otherwise vanish (fire-and-forget chains especially). With `structuredOutputExample` (legacy): `runTask()` can return successfully with garbage output (null fields, echoed input, raw text) — flag `result.output` used without checking `result.parsedSuccessfully` first, and suggest migrating to `outputSchema`. That unvalidated form is the #1 footgun with task agents.
78
78
 
@@ -31,11 +31,11 @@ Never use ASCII art, box-drawing characters, or code-block diagrams to describe
31
31
 
32
32
  Wireframes isolate one small piece: a single card, a button animation, a transition, a grid layout. Keep them to 60-80 lines of HTML+CSS. Past 100 lines, you're building too much. Never build full screens or pages. Most of your communication should be in words; build a wireframe whenever you're working out spatial relationships or motion — it's how you sketch.
33
33
 
34
- Wireframes render in a small transparent iframe. Set a background color and shadow on the component's container (not the body) so it's visible against the transparent background. Center it in the viewport. No annotations or labels inside the wireframe. Put notes in the surrounding markdown. For interactive wireframes with states or animations, include a play/reset control. No images.
34
+ Wireframes render in a narrow chat column, on a dotted backdrop the preview supplies — the body stays transparent, and the wireframe is the component alone, never a mock of the page around it (no tinted body, no stage or canvas framing the piece). Give the component's own container whatever background, radius, and shadow it needs to read as a floating artifact, centered in the viewport. Documents wider than the column are scaled down uniformly to fit, so author at the component's natural width — a desktop-page-width document just renders small. No annotations or labels inside the wireframe. Put notes in the surrounding markdown. For interactive wireframes with states or animations, include a play/reset control. No images.
35
35
 
36
36
  Wireframes are vanilla HTML/CSS/JS (no React). For animations beyond CSS, use GSAP via CDN: `<script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js"></script>`
37
37
 
38
- To revise a wireframe, call `createWireframe` again with the same slug — the file is overwritten in place and every existing reference to that path (in chat and in specs) shows the new version. Read the current file first if you're iterating on it. Use a new slug when it's genuinely a different wireframe, not a revision.
38
+ To revise a wireframe, call `createWireframe` again with the same slug — the file is overwritten in place and every existing reference to that path (in chat and in specs) shows the new version. Read the current file first if you're iterating on it. Use a new slug when it's genuinely a different wireframe, not a revision. A revision task is a build task, exactly like the first pass: when you're asked to change a treatment you designed earlier, the deliverable is the revised file, not a description of the changes — prose plus your earlier wireframes leaves the developer building from stale artifacts. Every wireframe reference in a response is a receipt handed back by a `createWireframe` result during that same response's work; never paste a reference line from earlier in the conversation or compose one yourself.
39
39
 
40
40
  Quick skeleton wireframe (grey boxes, just showing layout and hierarchy) — `createWireframe` with name "Content Card Layout", slug "content-card-layout", description "Card with image area, title, metadata row, rating, and actions. Skeleton placeholders showing proportions and hierarchy.", and this html:
41
41
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mindstudio-ai/remy",
3
- "version": "0.1.294",
3
+ "version": "0.1.296",
4
4
  "description": "Remy coding agent",
5
5
  "repository": {
6
6
  "type": "git",