@noodleseed/agent-kit 0.14.0 → 0.16.0

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.
Files changed (118) hide show
  1. package/manifest.json +549 -9
  2. package/package.json +1 -1
  3. package/skills/claude-code/SKILL.md +6 -4
  4. package/skills/claude-code/examples/acme-bistro/README.md +51 -0
  5. package/skills/claude-code/examples/acme-bistro/design/UX-Document.md +435 -0
  6. package/skills/claude-code/examples/acme-bistro/design/api-contract.md +161 -0
  7. package/skills/claude-code/examples/acme-bistro/design/wireframe.html +573 -0
  8. package/skills/claude-code/examples/acme-bistro/noodle.json +5 -0
  9. package/skills/claude-code/examples/acme-bistro/package.json +20 -0
  10. package/skills/claude-code/examples/acme-bistro/src/helpers.ts +7 -0
  11. package/skills/claude-code/examples/acme-bistro/src/server.ts +149 -0
  12. package/skills/claude-code/examples/acme-bistro/src/views/menu-cart.tsx +159 -0
  13. package/skills/claude-code/examples/acme-bistro/src/views/widget-style.css +228 -0
  14. package/skills/claude-code/examples/acme-bistro/test/server.test.ts +21 -0
  15. package/skills/claude-code/examples/acme-bistro/vitest.config.ts +7 -0
  16. package/skills/claude-code/examples/acme-discovery/README.md +85 -0
  17. package/skills/claude-code/examples/acme-discovery/design/UX-Document.md +441 -0
  18. package/skills/claude-code/examples/acme-discovery/design/wireframe.html +670 -0
  19. package/skills/claude-code/examples/acme-discovery/noodle.json +5 -0
  20. package/skills/claude-code/examples/acme-discovery/package.json +20 -0
  21. package/skills/claude-code/examples/acme-discovery/src/helpers.ts +7 -0
  22. package/skills/claude-code/examples/acme-discovery/src/server.ts +202 -0
  23. package/skills/claude-code/examples/acme-discovery/src/views/discovery-carousel.tsx +155 -0
  24. package/skills/claude-code/examples/acme-discovery/src/views/widget-style.css +207 -0
  25. package/skills/claude-code/examples/acme-discovery/test/server.test.ts +24 -0
  26. package/skills/claude-code/examples/acme-discovery/vitest.config.ts +7 -0
  27. package/skills/claude-code/examples/acme-tasks/README.md +80 -0
  28. package/skills/claude-code/examples/acme-tasks/design/UX-Document.md +277 -0
  29. package/skills/claude-code/examples/acme-tasks/design/wireframe.html +603 -0
  30. package/skills/claude-code/examples/acme-tasks/noodle.json +5 -0
  31. package/skills/claude-code/examples/acme-tasks/package.json +20 -0
  32. package/skills/claude-code/examples/acme-tasks/src/helpers.ts +6 -0
  33. package/skills/claude-code/examples/acme-tasks/src/server.ts +141 -0
  34. package/skills/claude-code/examples/acme-tasks/src/views/task-list.tsx +177 -0
  35. package/skills/claude-code/examples/acme-tasks/src/views/widget-style.css +227 -0
  36. package/skills/claude-code/examples/acme-tasks/test/server.test.ts +22 -0
  37. package/skills/claude-code/examples/acme-tasks/vitest.config.ts +7 -0
  38. package/skills/claude-code/examples/food-ordering/README.md +82 -0
  39. package/skills/claude-code/examples/food-ordering/noodle.json +5 -0
  40. package/skills/claude-code/examples/food-ordering/package.json +22 -0
  41. package/skills/claude-code/examples/food-ordering/src/helpers.ts +34 -0
  42. package/skills/claude-code/examples/food-ordering/src/server.ts +412 -0
  43. package/skills/claude-code/examples/food-ordering/src/views/capabilities-card.tsx +155 -0
  44. package/skills/claude-code/examples/food-ordering/src/views/ordering-flow.tsx +659 -0
  45. package/skills/claude-code/examples/food-ordering/src/views/widget-style.css +682 -0
  46. package/skills/claude-code/examples/food-ordering/test/server.test.ts +58 -0
  47. package/skills/claude-code/examples/food-ordering/vitest.config.ts +30 -0
  48. package/skills/claude-code/examples/hello/README.md +13 -0
  49. package/skills/claude-code/examples/hello/noodle.json +5 -0
  50. package/skills/claude-code/examples/hello/package.json +16 -0
  51. package/skills/claude-code/examples/hello/src/server.ts +29 -0
  52. package/skills/claude-code/examples/hello/test/server.test.ts +8 -0
  53. package/skills/claude-code/examples/weather/README.md +85 -0
  54. package/skills/claude-code/examples/weather/noodle.json +4 -0
  55. package/skills/claude-code/examples/weather/package.json +16 -0
  56. package/skills/claude-code/examples/weather/src/server.ts +261 -0
  57. package/skills/claude-code/examples/weather/test/server.test.ts +29 -0
  58. package/skills/claude-code/references/connect-an-api.md +63 -1
  59. package/skills/claude-code/references/examples.md +16 -7
  60. package/skills/claude-code/references/troubleshooting.md +2 -0
  61. package/skills/codex/SKILL.md +6 -4
  62. package/skills/codex/examples/acme-bistro/README.md +51 -0
  63. package/skills/codex/examples/acme-bistro/design/UX-Document.md +435 -0
  64. package/skills/codex/examples/acme-bistro/design/api-contract.md +161 -0
  65. package/skills/codex/examples/acme-bistro/design/wireframe.html +573 -0
  66. package/skills/codex/examples/acme-bistro/noodle.json +5 -0
  67. package/skills/codex/examples/acme-bistro/package.json +20 -0
  68. package/skills/codex/examples/acme-bistro/src/helpers.ts +7 -0
  69. package/skills/codex/examples/acme-bistro/src/server.ts +149 -0
  70. package/skills/codex/examples/acme-bistro/src/views/menu-cart.tsx +159 -0
  71. package/skills/codex/examples/acme-bistro/src/views/widget-style.css +228 -0
  72. package/skills/codex/examples/acme-bistro/test/server.test.ts +21 -0
  73. package/skills/codex/examples/acme-bistro/vitest.config.ts +7 -0
  74. package/skills/codex/examples/acme-discovery/README.md +85 -0
  75. package/skills/codex/examples/acme-discovery/design/UX-Document.md +441 -0
  76. package/skills/codex/examples/acme-discovery/design/wireframe.html +670 -0
  77. package/skills/codex/examples/acme-discovery/noodle.json +5 -0
  78. package/skills/codex/examples/acme-discovery/package.json +20 -0
  79. package/skills/codex/examples/acme-discovery/src/helpers.ts +7 -0
  80. package/skills/codex/examples/acme-discovery/src/server.ts +202 -0
  81. package/skills/codex/examples/acme-discovery/src/views/discovery-carousel.tsx +155 -0
  82. package/skills/codex/examples/acme-discovery/src/views/widget-style.css +207 -0
  83. package/skills/codex/examples/acme-discovery/test/server.test.ts +24 -0
  84. package/skills/codex/examples/acme-discovery/vitest.config.ts +7 -0
  85. package/skills/codex/examples/acme-tasks/README.md +80 -0
  86. package/skills/codex/examples/acme-tasks/design/UX-Document.md +277 -0
  87. package/skills/codex/examples/acme-tasks/design/wireframe.html +603 -0
  88. package/skills/codex/examples/acme-tasks/noodle.json +5 -0
  89. package/skills/codex/examples/acme-tasks/package.json +20 -0
  90. package/skills/codex/examples/acme-tasks/src/helpers.ts +6 -0
  91. package/skills/codex/examples/acme-tasks/src/server.ts +141 -0
  92. package/skills/codex/examples/acme-tasks/src/views/task-list.tsx +177 -0
  93. package/skills/codex/examples/acme-tasks/src/views/widget-style.css +227 -0
  94. package/skills/codex/examples/acme-tasks/test/server.test.ts +22 -0
  95. package/skills/codex/examples/acme-tasks/vitest.config.ts +7 -0
  96. package/skills/codex/examples/food-ordering/README.md +82 -0
  97. package/skills/codex/examples/food-ordering/noodle.json +5 -0
  98. package/skills/codex/examples/food-ordering/package.json +22 -0
  99. package/skills/codex/examples/food-ordering/src/helpers.ts +34 -0
  100. package/skills/codex/examples/food-ordering/src/server.ts +412 -0
  101. package/skills/codex/examples/food-ordering/src/views/capabilities-card.tsx +155 -0
  102. package/skills/codex/examples/food-ordering/src/views/ordering-flow.tsx +659 -0
  103. package/skills/codex/examples/food-ordering/src/views/widget-style.css +682 -0
  104. package/skills/codex/examples/food-ordering/test/server.test.ts +58 -0
  105. package/skills/codex/examples/food-ordering/vitest.config.ts +30 -0
  106. package/skills/codex/examples/hello/README.md +13 -0
  107. package/skills/codex/examples/hello/noodle.json +5 -0
  108. package/skills/codex/examples/hello/package.json +16 -0
  109. package/skills/codex/examples/hello/src/server.ts +29 -0
  110. package/skills/codex/examples/hello/test/server.test.ts +8 -0
  111. package/skills/codex/examples/weather/README.md +85 -0
  112. package/skills/codex/examples/weather/noodle.json +4 -0
  113. package/skills/codex/examples/weather/package.json +16 -0
  114. package/skills/codex/examples/weather/src/server.ts +261 -0
  115. package/skills/codex/examples/weather/test/server.test.ts +29 -0
  116. package/skills/codex/references/connect-an-api.md +63 -1
  117. package/skills/codex/references/examples.md +16 -7
  118. package/skills/codex/references/troubleshooting.md +2 -0
@@ -0,0 +1,80 @@
1
+ # Acme Tasks — designed around its top-3 prioritized user flows
2
+
3
+ A Noodle MCP App for **Acme Tasks**, a fictional productivity tool. It is the flagship for
4
+ **designing an app around its prioritized user flows**: a two-way (read + write) experience where the
5
+ top-3 flows — **Capture, Prioritize, Complete** — all happen in chat, each mapped to a tool and surfaced
6
+ in one `TaskList` widget. It shows the "identify and prioritize the flows first, then build" discipline
7
+ the `noodle-seed` skill's `references/experience-design.md` teaches.
8
+
9
+ Capability slots: prioritized multi-flow app design, a two-way (read + write) in-chat pattern, a task-list
10
+ widget with `toolForWidget` helpers, and a worked **design-first** artifact (the flow spec + wireframe
11
+ below). A real deployment would connect the user's account with the end-user auth pattern — see
12
+ [`../customer-auth/README.md`](../customer-auth/README.md); this example seeds a list so the focus stays
13
+ on the flows.
14
+
15
+ ## Design spec (write this before the code)
16
+
17
+ - **What it is** — an in-chat task manager. Unlike a top-of-funnel app, there is **no handoff**: the value
18
+ is doing the work in place (read the list, add, re-prioritize, complete).
19
+ - **Personas** — the quick capturer ("remind me to email the vendor"), the morning triager (re-orders the
20
+ day), the closer (marks things done without leaving chat).
21
+ - **Top-3 prioritized user flows** (the heart of this example — build these, defer the rest)
22
+ 1. **Capture** (`add_task`) — "add: book flights for the offsite, high priority" → task captured.
23
+ 2. **Prioritize** (`list_today` renders the widget; `set_priority` re-orders) — triage today's list.
24
+ 3. **Complete** (`complete_task`) — check a task off; the model can also complete on request.
25
+ - **Tools** — `list_today` (model-visible, renders the widget), `add_task` and `complete_task`
26
+ (model-visible), `set_priority` (widget-only helper hidden from the model).
27
+ - **Widgets + display modes** — `TaskList` as an inline card that expands to fullscreen for a long list.
28
+ No carousel or picture-in-picture — a single list is the right surface.
29
+ - **Grounding** — the seeded list in `src/server.ts` stands in for the user's real list; the app never
30
+ invents a task.
31
+ - **Two users** — tools are atomic and model-fillable ("high priority" → `priority: "high"`), and each
32
+ returns a spoken-ready status so the model can confirm in one turn.
33
+
34
+ ## Wireframe (one screen: the three flows in place)
35
+
36
+ ```html
37
+ <div class="phone"> <!-- in-app: solid frame -->
38
+ <div class="chatgpt-header">ChatGPT · Acme Tasks</div>
39
+ <div class="msg user">what's on my list today?</div>
40
+ <div class="tool-call">list_today { focus: "today" }</div>
41
+ <div class="wcard">
42
+ <div class="wcard-head">TaskList</div> <!-- component name = code + spec -->
43
+ <div class="wcard-body">
44
+ <input placeholder="Add a task…" /> <!-- Flow 1: Capture -->
45
+ <div class="task">◻ Email the vendor about the Q3 quote [high ▾]</div> <!-- Flow 2 -->
46
+ <div class="task">◻ Review the analytics pull request [medium ▾]</div>
47
+ <div class="task done">✓ Book flights for the team offsite [low ▾]</div> <!-- Flow 3 -->
48
+ </div>
49
+ </div>
50
+ </div>
51
+ ```
52
+
53
+ ## Local author loop
54
+
55
+ ```sh
56
+ noodle validate
57
+ noodle test
58
+ noodle dev
59
+ ```
60
+
61
+ In another terminal:
62
+
63
+ ```sh
64
+ noodle tools list
65
+ noodle tools call list_today --args '{"focus":"today"}'
66
+ noodle tools call add_task --args '{"title":"Book flights for the offsite","priority":"high"}'
67
+ noodle tools call complete_task --args '{"task":"review_pr","title":"Review the analytics pull request"}'
68
+ noodle check --target chatgpt
69
+ ```
70
+
71
+ ## Deploy
72
+
73
+ ```sh
74
+ noodle link --org demo --app acme-tasks
75
+ noodle deploy --access owner-only
76
+ noodle open
77
+ ```
78
+
79
+ This example has no connector secrets and does not include tokens, caller-key mechanisms, or
80
+ `.env.noodle` values. All tasks are fictional seed data.
@@ -0,0 +1,277 @@
1
+ # Acme Tasks ChatGPT App — User Flow & Experience Document
2
+
3
+ **Prepared by:** Noodle Seed
4
+ **Scope:** Capture, prioritize, and complete today's tasks entirely inside ChatGPT — a two-way (read + write) task manager. There is no handoff; the value is doing the work in place.
5
+ **Status:** Design specification (v1)
6
+ **Two-way scope & auth stance:** IN-APP (in chat) — read today's list, capture new tasks, re-prioritize, and complete them, each write confirmed in-chat. OFF-APP — nothing transactional; the only boundary crossing is a **one-time scoped account connection** (`customerAuth` end-user OAuth: read + write, connected once). Every scope debate resolves here: if a request is "see, add, re-order, or finish a task," it stays in chat; the account link is the single, revocable off-app moment.
7
+
8
+ > This document is the master spec. The wireframes (`wireframe.html`), the widget code (`src/views/task-list.tsx`), and the server (`src/server.ts`) are all derivable from it. Acme Tasks is a fictional productivity app; all data below is sample content.
9
+
10
+ ---
11
+
12
+ ## Section 0 — The One-Paragraph Thesis
13
+
14
+ A person mid-conversation in ChatGPT says *"remind me to email the vendor about the Q3 quote"* — and today that intent evaporates, because acting on it means leaving the conversation for a separate app. Acme Tasks closes that gap: the moment a task is spoken it is **captured, prioritized, and completed without ever leaving chat**. This is deliberately **not** a top-of-funnel handoff app — there is no cart to check out, no site to open, no "continue in the app." The task manager *is* the conversation. We own the in-chat experience end to end (read the live list, add by natural language, re-prioritize, complete); the user owns their account, connected once through a scoped, revocable link. The strategic kicker: a to-do app is the highest-frequency surface a person touches, and the app that lets them clear their list *in the same window where the work is being discussed* becomes the one they never close. **In-chat completion is the product.**
15
+
16
+ ---
17
+
18
+ ## 1. Acme Tasks Product Overview (Knowledge Base)
19
+
20
+ **What the company is.** Acme Tasks is a personal + small-team task manager: a single prioritized list per user, each task carrying a **title**, a **priority** (`high` / `medium` / `low`), and a **done** state. It is intentionally minimal — no projects, no assignees, no sub-tasks in v1 — so the model can reason about the whole list in one turn.
21
+
22
+ **The data domain the app must know.** The user's *today* list. In this flagship the list is **seeded** so the design can focus on the flows; the three seed items are the canonical fixtures every downstream artifact reuses:
23
+
24
+ | id | title | priority |
25
+ | :--- | :--- | :--- |
26
+ | `email_vendor` | Email the vendor about the Q3 quote | `high` |
27
+ | `review_pr` | Review the analytics pull request | `medium` |
28
+ | `book_offsite` | Book flights for the team offsite | `low` |
29
+
30
+ **The highest-value / highest-risk domain** is the account write. Because the app can *complete* and *re-prioritize* real tasks, every mutation must be legible and confirmed — a silently-checked-off task is the worst possible failure.
31
+
32
+ **What lives after any boundary crossing.** Nothing transactional. Unlike a discovery funnel, Acme Tasks has no off-app destination it hands users to; the only off-app step is the one-time `customerAuth` consent screen (§9). After that, everything is in chat.
33
+
34
+ **Business model / why this matters.** Frequency and retention. A task app is opened many times a day; the version that removes the app-switch tax — "I thought of it, I said it, it's on my list, it's done" — wins the habit. The bottleneck the app removes is **context-switching**, not data entry.
35
+
36
+ ---
37
+
38
+ ## 2. Competitive Landscape — Task Managers on ChatGPT
39
+
40
+ Most task integrations on assistant platforms are **read-only or one-way**: they can list what's due but push the user to a separate app to actually change anything, or they capture a task into a black box with no confirmation. The generic model can *talk about* a to-do list but has no grounded state — it will happily invent tasks that don't exist.
41
+
42
+ **Acme Tasks' unique position** is the *closed two-way loop in one surface*: a grounded read (the real list, never guessed), natural-language writes (capture, re-prioritize, complete), and an in-chat confirmation for every mutation. The differentiator is not the widget — it is that the widget's actions **commit** and the user **sees what changed** without a tab switch.
43
+
44
+ ---
45
+
46
+ ## 3. Target User Personas
47
+
48
+ - **The Quick Capturer** — *"add: book flights for the offsite, low priority."* Thinks of a task mid-conversation and wants it on the list before the thought is gone. Values zero-friction capture.
49
+ - **The Morning Triager** — *"what's on my plate today?"* Opens the day, scans the list, and re-orders priorities before starting. Values a fast, grounded read plus one-tap re-prioritize.
50
+ - **The Closer** — *"mark the vendor email done."* Finishes work and wants the satisfaction of checking it off without leaving the thread. Values instant, confirmed completion.
51
+
52
+ All three are the **same user at different moments of the day** — capture in the morning stand-up, triage before lunch, close out at end of day. The app is designed so one connected session serves all three.
53
+
54
+ ---
55
+
56
+ ## 4. Conversational User Flow
57
+
58
+ ### 4.1 Entry points (natural triggers)
59
+
60
+ - **Capture:** "remind me to…", "add a task…", "put X on my list", "I need to email the vendor."
61
+ - **Prioritize / read:** "what's on my list today?", "what's due?", "show my tasks", "make the PR review high priority."
62
+ - **Complete:** "mark X done", "I finished the vendor email", "check off the offsite booking."
63
+
64
+ ### 4.2 Flow architecture
65
+
66
+ ```
67
+ ┌─────────────────────────────┐
68
+ first run ─────────▶│ Connect Acme Tasks (once) │ §9 · customerAuth, scoped R/W
69
+ └──────────────┬──────────────┘
70
+ │ connection live thereafter
71
+ ┌─────────────────────────────┼─────────────────────────────┐
72
+ ▼ ▼ ▼
73
+ ① CAPTURE ② PRIORITIZE ③ COMPLETE
74
+ add_task list_today → TaskList complete_task
75
+ "add X, high" (render widget) "mark X done"
76
+ │ set_priority (in widget) │
77
+ └──────────────▶ TaskList reflects the change ◀───────────┘
78
+ (grounded read, always current)
79
+ ```
80
+
81
+ `list_today` is the hub — it renders the `TaskList` widget the other two flows write into. Every flow returns a spoken-ready status so the model confirms in one turn.
82
+
83
+ ### 4.3 Detailed conversational scenarios (playscripts)
84
+
85
+ **Scenario A — Capture (The Quick Capturer)**
86
+
87
+ ```
88
+ User: Add "book flights for the team offsite", low priority.
89
+ Tool call: add_task { title: "Book flights for the team offsite", priority: "low" }
90
+ Returns: { status: "Added “Book flights for the team offsite” (low).", title, priority }
91
+ Assistant: Added "Book flights for the team offsite" at low priority. Want to see the full list?
92
+ ```
93
+
94
+ **Scenario B — Prioritize / read + re-order (The Morning Triager)**
95
+
96
+ ```
97
+ User: What's on my plate today?
98
+ Tool call: list_today { focus: "today" } ← renders TaskList widget
99
+ Returns: { status: "Acme Tasks for today: 3 open items, highest priority first.", focus, tasks:[…] }
100
+ Widget: TaskList — Email the vendor (high) · Review the analytics PR (medium) · Book offsite (low)
101
+
102
+ User: Bump the PR review to high.
103
+ Tool call: set_priority { task: "review_pr", priority: "high" } ← widget-only helper
104
+ Returns: { status: "Set review_pr to high priority.", task, priority }
105
+ Widget: TaskList re-orders — Review the analytics PR now sits with the high group.
106
+ ```
107
+
108
+ **Scenario C — Complete (The Closer)**
109
+
110
+ ```
111
+ User: I finished the vendor email — mark it done.
112
+ Tool call: complete_task { task: "email_vendor", title: "Email the vendor about the Q3 quote" }
113
+ Returns: { status: "Completed “Email the vendor about the Q3 quote”.", task }
114
+ Widget: TaskList strikes the row through; open count drops from 3 → 2.
115
+ Assistant: Done — "Email the vendor about the Q3 quote" is checked off. Two left today.
116
+ ```
117
+
118
+ ---
119
+
120
+ ## 5. UI Widget Specifications (Noodle Seed Apps Compliant)
121
+
122
+ ### 5.1 Design system compliance
123
+
124
+ Widgets render inside the host (ChatGPT) via Noodle Seed's `view` component model and **CSS Cascade Layers**, so they inherit the host's light/dark surface and typography rather than shipping an app theme. Compliance rules, all enforceable via `noodle check --target chatgpt`:
125
+
126
+ - **Tokens, not hard-coded chrome.** Text, surface, and border come from host/Noodle Seed semantic tokens. The **brand accent is declared once** in the server `branding` block — `accent: #7C3AED`, `surface: #F5F3FF`, `surfaceDark: #161228`, `radius: lg`, `density: comfortable` — and is restricted to the **primary CTA, the logo/check mark, and the "high" priority emphasis only**. It is never a background wash.
127
+ - **Priority palette (semantic, fixed):** `high` = red `#DC2626`, `medium` = amber `#D97706`, `low` = slate `#6B7280`. These map 1:1 to the `priority` enum so the widget and the model share one vocabulary.
128
+ - **System fonts, outlined monochrome icons, WCAG AA contrast, no nested scroll**, and every mutation shows a confirmable result. The widget exposes a single flat `data-llm` summary line ("N open of M; K completed this session") so the model can narrate state without re-reading the DOM.
129
+
130
+ ### 5.2 Display mode strategy
131
+
132
+ | User intent | Display mode | Why |
133
+ | :--- | :--- | :--- |
134
+ | "What's on my list?" | **Inline card** | The whole list fits; the answer is the list. |
135
+ | Triage a long list | **Fullscreen** (expand) | Density without nested scroll when items exceed the card. |
136
+ | Capture / complete / re-prioritize | **Inline card (in place)** | The write updates the same card; no new surface. |
137
+
138
+ **Deliberately NOT used:** *Carousel* (there is one list, not a set of peers) and *Picture-in-Picture* (nothing runs in the background). Stating the omissions is part of the compliance story.
139
+
140
+ ### 5.3 Widget specifications
141
+
142
+ **★ `TaskList`** — the single widget; the hub all three flows read and write.
143
+ - **Purpose:** show today's prioritized list and let the user capture, re-prioritize, and complete in place.
144
+ - **Content fields:** header (logo, "Acme Tasks", status subtitle, open-count chip); a **capture input** ("Add a task…"); a **task row** per item = complete check + title + priority `<select>`; a footer note ("Two-way in chat: read, capture, re-prioritize, complete").
145
+ - **Actions (≤2 primary):** **Add** (capture) and the per-row **complete check**; re-prioritize is a lightweight inline `<select>`, not a primary CTA.
146
+ - **States:** *default* (seeded list), *captured* (new row appears immediately, then `add_task` records it), *re-prioritized* (row moves priority group), *completed* (row struck through, check filled, count decremented), *all-clear* (empty-state celebration + nudge to capture the next thing).
147
+ - **Grounding flag:** the list only ever shows tasks that exist in state — the app never invents a task.
148
+
149
+ ---
150
+
151
+ ## 6. Tool Definitions (App Backend)
152
+
153
+ All tools are atomic, model-fillable from natural language, and each returns a spoken-ready `status`.
154
+
155
+ **★ `list_today`** *(read-only · renders `TaskList`)*
156
+ - **Input:** `{ focus: string = "today" }`
157
+ - **Output:** `{ status, focus, tasks: [{ id, title, priority, done }] }`
158
+ - **Notes:** `toolWithWidget` — the one tool that opens the widget. Host status copy: invoking "Loading your tasks…", invoked "Tasks ready".
159
+
160
+ **★ `add_task`** *(local write, non-destructive · model-visible)*
161
+ - **Input:** `{ title: string, priority: "high"|"medium"|"low" = "medium" }`
162
+ - **Output:** `{ status, title, priority }`
163
+ - **Notes:** capture from natural language; "high priority" fills `priority: "high"`.
164
+
165
+ **`complete_task`** *(local write, non-destructive · model-visible)*
166
+ - **Input:** `{ task: string (id), title: string = "" }`
167
+ - **Output:** `{ status, task }`
168
+ - **Notes:** model-visible so the user can complete by voice ("mark the vendor email done") without touching the widget.
169
+
170
+ **`set_priority`** *(local write, non-destructive · widget-only)*
171
+ - **Input:** `{ task: string (id), priority: "high"|"medium"|"low" }`
172
+ - **Output:** `{ status, task, priority }`
173
+ - **Notes:** `toolForWidget` — hidden from the model; the `<select>` in `TaskList` is its only caller, keeping the model's tool surface to the three it should reason about.
174
+
175
+ ---
176
+
177
+ ## 7. Conversation Design Principles
178
+
179
+ **Tone.** Brisk, confirming, never chatty. A task app earns trust by getting out of the way; every reply names *what changed* and offers the obvious next move.
180
+
181
+ **Guardrails (non-negotiable):**
182
+ - **Never invent a task.** The list is grounded in `list_today`'s returned state; if the app hasn't read a list, it says so rather than guessing.
183
+ - **Never mutate silently.** Capture, re-prioritize, and complete each return a visible confirmation and update the widget — the user always sees the new state.
184
+ - **Confirm completion explicitly.** "Done — *X* is checked off" plus the remaining count; completion is irreversible-feeling, so it is always narrated.
185
+ - **Priority is the user's, not the model's.** The model may *suggest* a priority when capturing ("this sounds high?") but sets what the user says; it does not silently re-rank the list.
186
+
187
+ **Memory strategy.** Session-scoped: captured tasks and completions persist across turns within the conversation (`added`/`done`/`priority` state layered over the seeded read). A production deployment persists to the connected account (§9).
188
+
189
+ **Multi-turn intelligence.** The model **infers** structured fields from prose ("book flights for the offsite, low" → title + `priority: low`) and **asks** only when a title is genuinely missing. It never asks the user to restate a task it can already see in `TaskList`.
190
+
191
+ ---
192
+
193
+ ## 8. End-to-End User Journey Map
194
+
195
+ | Phase | Time budget | What happens |
196
+ | :--- | :--- | :--- |
197
+ | **First run — Connect** | one-time, ~10s | Scoped `customerAuth` consent (read + write); dismissed forever after (§9). |
198
+ | **Read (grounded)** | first 3–5s | "What's on my plate?" → `list_today` renders `TaskList` with the real list. |
199
+ | **Capture** | ~2s per task | "Add X, high" → row appears instantly, `add_task` records it. |
200
+ | **Prioritize** | ~2s per change | Inline `<select>` or "bump the PR to high" → `set_priority`, list re-orders. |
201
+ | **Complete** | ~2s per task | Check the row or "mark X done" → `complete_task`, struck through, count drops. |
202
+ | **Close-out** | end of day | All-clear empty state; nudge to capture tomorrow's first task. |
203
+
204
+ ---
205
+
206
+ ## 9. Account-Connection / Auth Architecture (Deep Dive)
207
+
208
+ Because Acme Tasks **writes** to the user's tasks, the first interaction is a **scoped, one-time connection** — Noodle Seed's `customerAuth` end-user OAuth pattern (see the `customer-auth` example). This replaces the "handoff" a top-of-funnel app would have: there is no destination to send the user to, only an account to link.
209
+
210
+ **What must be true of the connection:**
211
+ - **Plain-language scope.** The consent card names *read* (your tasks and priorities) and *write* (add, re-prioritize, complete tasks you ask me to) in the user's words — not buried in an OAuth redirect.
212
+ - **Held by the connector, never the model.** The delegated credential is exchanged and stored by the credential broker; it is never surfaced in tool payloads, the widget, logs, or the model's context.
213
+ - **Connected once, revocable anytime.** One connection powers all three flows; the consent card links the revoke path.
214
+ - **The request resumes automatically.** After the user approves, the original ask ("what's on my plate?") continues without re-typing.
215
+
216
+ **Flagship simplification (honest note):** this example ships with a **seeded** `today` list rather than a live account, so the design can stay focused on the three flows. The connect screen is wireframed as step 1 because it is the production pattern; the seed list stands in for the connected account's read. A real deployment swaps the seed for `customerAuth`-brokered account reads/writes — the tool signatures and widget do not change.
217
+
218
+ **Edge cases at the boundary:** connection declined (app degrades to a read-only explanation, no writes attempted); token revoked mid-session (next write returns a re-connect prompt, never a silent failure); scope mismatch (write attempted without write scope → explicit "reconnect to allow changes").
219
+
220
+ ---
221
+
222
+ ## 10. Demo Scope Recommendation
223
+
224
+ **MVP (build these, defer the rest):** the three flows against the seeded list, in one `TaskList` widget — Capture (`add_task`), Prioritize (`list_today` + `set_priority`), Complete (`complete_task`).
225
+
226
+ **2-minute demo script:**
227
+ 1. **0:00** — "What's on my plate today?" → `TaskList` renders the three seed tasks, highest priority first. *(grounded read)*
228
+ 2. **0:25** — "Add 'draft the board update', high priority." → new row appears at the top instantly. *(capture)*
229
+ 3. **0:50** — Open the PR review's priority `<select>`, set **high** → list re-orders. *(prioritize, in-widget)*
230
+ 4. **1:15** — "I finished the vendor email — mark it done." → row strikes through, count 4 → 3. *(complete by voice)*
231
+ 5. **1:40** — Check the last row in the widget → all-clear empty state + "capture tomorrow's first task?" *(close the loop)*
232
+
233
+ ---
234
+
235
+ ## 11. Technical Architecture (High Level)
236
+
237
+ - **Server:** one `server('acme_tasks', …)` in `src/server.ts` (Noodle Seed authoring SDK), four tools, `branding` tokens, per-tool CSP allowlist.
238
+ - **Widget:** `TaskList` (`src/views/task-list.tsx`), a React `view` using `useCallTool` / `useToolInfo` / `useLayout` / `useViewState`; local session state (`added` / `done` / `priority`) layered over the `list_today` read, each change recorded through a tool call.
239
+ - **State:** session-scoped in the flagship (seed list + local overlay). Production: `customerAuth`-brokered reads/writes to the account.
240
+ - **Validation loop:** `noodle validate` → `noodle test` → `noodle dev`; compliance via `noodle check --target chatgpt`.
241
+
242
+ ---
243
+
244
+ ## 12. Success Metrics
245
+
246
+ | Metric | Maps to |
247
+ | :--- | :--- |
248
+ | **Connect completion rate** | % of first-runs that finish the `customerAuth` consent (§9). |
249
+ | **In-chat write rate** | writes (`add_task` + `set_priority` + `complete_task`) per session — the core "work done in chat" signal. |
250
+ | **Capture-to-list latency** | time from utterance to the row appearing in `TaskList` (target < 1s optimistic). |
251
+ | **Completion rate** | % of read sessions that end with at least one `complete_task` — the retention-driving "closed the loop" event. |
252
+ | **Return frequency** | sessions per user per day — the habit metric a task app lives or dies on. |
253
+
254
+ **Attribution:** each tool call carries the connected account identity (server identity + tenant), so writes are traceable to the session without exposing the credential.
255
+
256
+ ---
257
+
258
+ ## 13. Future Enhancements (Post-Launch)
259
+
260
+ - **Live account** via `customerAuth` replacing the seed list (the natural first step out of the flagship).
261
+ - **Due dates & scheduling** ("email the vendor by Friday") once the model can be trusted to parse relative dates.
262
+ - **Bulk triage** ("move everything low to tomorrow") — a batched, previewed, reversible write.
263
+ - **Projects / grouping** beyond a single flat list, once the single-list flows are proven.
264
+ - **Undo** as a first-class in-chat verb for every write.
265
+
266
+ ---
267
+
268
+ ## Appendix — Two-Way Scope Cheat-Sheet
269
+
270
+ | User request | In chat (in-app) | Off-app |
271
+ | :--- | :---: | :---: |
272
+ | "What's on my list?" | ✓ `list_today` → `TaskList` | — |
273
+ | "Add a task…" | ✓ `add_task` | — |
274
+ | "Make X high priority" | ✓ `set_priority` | — |
275
+ | "Mark X done" | ✓ `complete_task` | — |
276
+ | First-run account link | — | ✓ `customerAuth` consent (once, scoped, revocable) |
277
+ | Anything transactional | — | *(none — the app has no transactional off-app step)* |