@agent-native/core 0.203.1-nightly-20261007154213 → 0.203.1

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 (39) hide show
  1. package/dist/agent/default-agent-engine.d.ts +1 -1
  2. package/dist/agent/default-agent-engine.js +1 -1
  3. package/dist/agent/engine-status.d.ts +49 -0
  4. package/dist/agent/engine-status.js +112 -0
  5. package/dist/client/client-status-requests.js +8 -0
  6. package/dist/collab/awareness.d.ts +2 -2
  7. package/dist/collab/routes.d.ts +1 -1
  8. package/dist/jobs/actions/manage-recurring-job.d.ts +1 -1
  9. package/dist/jobs/frontmatter-loss.d.ts +17 -0
  10. package/dist/jobs/frontmatter-loss.js +62 -0
  11. package/dist/jobs/frontmatter.d.ts +7 -0
  12. package/dist/jobs/frontmatter.js +39 -0
  13. package/dist/jobs/tools.js +16 -3
  14. package/dist/localization/default-model-messages.d.ts +11 -0
  15. package/dist/localization/default-model-messages.js +88 -0
  16. package/dist/notifications/routes.d.ts +1 -1
  17. package/dist/observability/routes.d.ts +2 -2
  18. package/dist/org/index.d.ts +1 -1
  19. package/dist/progress/routes.d.ts +1 -1
  20. package/dist/provider-api/actions/custom-provider-registration.d.ts +4 -4
  21. package/dist/provider-api/actions/provider-api.d.ts +8 -8
  22. package/dist/resources/handlers.d.ts +1 -1
  23. package/dist/resources/store.js +40 -2
  24. package/dist/scripts/agent-engines/list-agent-engines.js +8 -5
  25. package/dist/scripts/agent-engines/manage-agent-engine.js +22 -4
  26. package/dist/scripts/agent-engines/set-agent-engine.d.ts +25 -0
  27. package/dist/scripts/agent-engines/set-agent-engine.js +94 -8
  28. package/dist/secrets/routes.d.ts +6 -6
  29. package/dist/server/agent-engine-default-model-route.d.ts +1 -1
  30. package/dist/server/agent-engine-ollama-models-route.d.ts +1 -1
  31. package/dist/server/core-routes-plugin.d.ts +1 -43
  32. package/dist/server/core-routes-plugin.js +15 -92
  33. package/dist/server/email-auth-links.js +98 -2
  34. package/dist/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +26 -39
  35. package/dist/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +16 -1
  36. package/dist/triggers/actions/manage-automation.d.ts +7 -7
  37. package/package.json +4 -4
  38. package/src/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +26 -39
  39. package/src/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +16 -1
@@ -2,13 +2,15 @@ import { createHash } from "node:crypto";
2
2
  import { assertBodySize, defineEventHandler, setResponseStatus, setResponseHeader, getMethod, getHeader, getRequestURL, getRequestIP, readRawBody, getCookie, setCookie, deleteCookie, } from "h3";
3
3
  import { readMultipartFormData } from "h3";
4
4
  import { z } from "zod";
5
+ import { readAgentAppModelDefaultSettings, normalizeAgentAppModelDefaultAppId, } from "../agent/app-model-defaults.js";
5
6
  import { CHATGPT_SUBSCRIPTION_CALLBACK_PATH } from "../agent/chatgpt-subscription-contract.js";
6
7
  import { readDefaultAgentEngineSetting } from "../agent/default-agent-engine.js";
7
- import { DEFAULT_MODEL } from "../agent/default-model.js";
8
+ import { resolveAgentEngineStatus, } from "../agent/engine-status.js";
8
9
  import { registerBuiltinEngines } from "../agent/engine/builtin.js";
9
10
  import { OPENAI_BASE_URL_ENV_VAR, PROVIDER_ENV_META, } from "../agent/engine/provider-env-vars.js";
10
- import { isAgentEngineSettingConfigured, getAgentEngineEntry, detectEngineFromEnv, detectEngineFromUserSecrets, isStoredEngineUsableForRequest, normalizeModelForEngine, } from "../agent/engine/registry.js";
11
+ import { detectEngineFromEnv, detectEngineFromUserSecrets, isStoredEngineUsableForRequest, } from "../agent/engine/registry.js";
11
12
  import { canUpdateAgentLoopSettings, readAgentLoopSettings, resetAgentLoopSettings, validateMaxIterationsInput, writeAgentLoopSettings, } from "../agent/loop-settings.js";
13
+ export { normalizeAgentEngineStatusModel, resolveAgentEngineStatus, } from "../agent/engine-status.js";
12
14
  import { getAppConfig } from "../app-config/index.js";
13
15
  import { getState, putState, compareAndSetState, deleteState, listComposeDrafts, getComposeDraft, putComposeDraft, deleteComposeDraft, deleteAllComposeDrafts, getStateMany, APP_STATE_ANONYMOUS_OWNER_CONTEXT_KEY, } from "../application-state/handlers.js";
14
16
  import { recordOrgAdminAuditEvent } from "../audit/org-admin.js";
@@ -86,7 +88,7 @@ import { createPollEventsHandler, validateSseMaxDurationMs, } from "./poll-event
86
88
  import { createPollHandler } from "./poll.js";
87
89
  import { isHostedRealtimeTransport, realtimeRegistrationUnavailable, } from "./realtime-registration.js";
88
90
  import { createRealtimeTokenHandler, resolveActiveRealtimeChannel, } from "./realtime-token.js";
89
- import { getRequestContext, hasRequestContext, runWithRequestContext, } from "./request-context.js";
91
+ import { getRequestContext, getRequestOrgId, getRequestUserEmail, hasRequestContext, runWithRequestContext, } from "./request-context.js";
90
92
  import { isSameOriginRequest } from "./request-origin.js";
91
93
  import { findUnsupportedScopedKeyNames, saveKeyValuesToScopedSecrets, ScopedKeyStorageError, } from "./scoped-key-storage.js";
92
94
  import { createSpeakHandler } from "./speak.js";
@@ -103,97 +105,18 @@ import { createWorkspaceProviderOAuthHandler } from "./workspace-provider-oauth.
103
105
  export const FRAMEWORK_ROUTE_PREFIX = "/_agent-native";
104
106
  export const FRAMEWORK_EVENTS_ROUTE = `${FRAMEWORK_ROUTE_PREFIX}/events`;
105
107
  export const LEGACY_FRAMEWORK_EVENTS_ROUTE = `${FRAMEWORK_ROUTE_PREFIX}/poll-events`;
106
- export function normalizeAgentEngineStatusModel(entry, model) {
107
- if (!entry)
108
- return model ?? DEFAULT_MODEL;
109
- return normalizeModelForEngine(entry, model ?? entry.defaultModel);
110
- }
111
- /**
112
- * Resolve "does this request have a usable AI provider" for one identity.
113
- *
114
- * Every call site pays for these lookups on a user-visible path (the agent
115
- * composer blocks on the status probe), so the two identity-independent reads
116
- * start together and the expensive `app_secrets` sweep only runs when the
117
- * cheaper sources have not already answered.
118
- */
119
- export async function resolveAgentEngineStatus(deps) {
120
- const lookupEntry = (deps.lookupEntry ?? getAgentEngineEntry);
121
- const [stored, openAiBaseUrlConfigured] = await Promise.all([
122
- deps.readStoredEngine(),
123
- deps.readOpenAiBaseUrlConfigured(),
124
- ]);
125
- if (isAgentEngineSettingConfigured(stored)) {
126
- const engine = stored.engine;
127
- const entry = lookupEntry(engine);
128
- return {
129
- configured: true,
130
- engine,
131
- model: normalizeAgentEngineStatusModel(entry, stored?.model),
132
- source: "settings",
133
- openAiBaseUrlConfigured,
134
- };
135
- }
136
- const configuredEngine = getAppConfig().agent.engine;
137
- const envEntry = configuredEngine ? lookupEntry(configuredEngine) : undefined;
138
- if (envEntry) {
139
- if (await deps.isStoredEngineUsable({ engine: envEntry.name }, envEntry)) {
140
- return {
141
- configured: true,
142
- engine: envEntry.name,
143
- model: envEntry.defaultModel ?? DEFAULT_MODEL,
144
- source: "env",
145
- envVar: "AGENT_ENGINE",
146
- openAiBaseUrlConfigured,
147
- };
148
- }
149
- if (getRequestContext()?.isSyntheticTraffic !== true) {
150
- return { configured: false, openAiBaseUrlConfigured };
151
- }
152
- }
153
- // Stored provider selections win over an existing Builder connection, so
154
- // this is checked before the app_secrets sweep — and the sweep is skipped
155
- // entirely when it answers.
156
- if (stored && typeof stored.engine === "string") {
157
- const entry = lookupEntry(stored.engine);
158
- if (entry && (await deps.isStoredEngineUsable(stored, entry))) {
159
- return {
160
- configured: true,
161
- engine: stored.engine,
162
- model: normalizeAgentEngineStatusModel(entry, stored.model),
163
- source: "env",
164
- envVar: entry.requiredEnvVars[0],
165
- openAiBaseUrlConfigured,
166
- };
167
- }
168
- }
169
- // Per-user app_secrets — a user who connected Builder (or pasted their own
170
- // provider key) may not have any deploy-level env vars set.
171
- const detectedFromUser = await deps.detectFromUserSecrets();
172
- if (detectedFromUser) {
173
- return {
174
- configured: true,
175
- engine: detectedFromUser.name,
176
- model: detectedFromUser.defaultModel ?? DEFAULT_MODEL,
177
- source: "app_secrets",
178
- envVar: detectedFromUser.requiredEnvVars[0],
179
- openAiBaseUrlConfigured,
180
- };
181
- }
182
- const detected = await deps.detectFromEnv();
183
- if (detected) {
184
- return {
185
- configured: true,
186
- engine: detected.name,
187
- model: detected.defaultModel ?? DEFAULT_MODEL,
188
- source: "env",
189
- envVar: detected.requiredEnvVars[0],
190
- openAiBaseUrlConfigured,
191
- };
192
- }
193
- return { configured: false, openAiBaseUrlConfigured };
194
- }
195
108
  function requestAgentEngineStatusDeps() {
196
109
  return {
110
+ readAppDefault: async () => {
111
+ const app = getAppConfig().app;
112
+ const appId = normalizeAgentAppModelDefaultAppId(app.id ?? app.template ?? app.slug);
113
+ if (!appId)
114
+ return null;
115
+ const settings = await readAgentAppModelDefaultSettings({ userEmail: getRequestUserEmail(), orgId: getRequestOrgId() }, appId);
116
+ return settings.engine && settings.model
117
+ ? { engine: settings.engine, model: settings.model }
118
+ : null;
119
+ },
197
120
  readStoredEngine: async () => (await readDefaultAgentEngineSetting()),
198
121
  readOpenAiBaseUrlConfigured: async () => {
199
122
  try {
@@ -1,3 +1,4 @@
1
+ import { randomBytes } from "node:crypto";
1
2
  import { canonicalFrameworkPathname, publicFrameworkPath, } from "./framework-route-prefix.js";
2
3
  export const EMAIL_AUTH_LINK_LANDING_PATH = "/_agent-native/auth/email-link/landing";
3
4
  const BETTER_AUTH_MAGIC_LINK_VERIFY_PATH = "/_agent-native/auth/ba/magic-link/verify";
@@ -108,16 +109,111 @@ function escapeHtml(value) {
108
109
  }
109
110
  });
110
111
  }
112
+ const EMAIL_AUTH_LINK_LANDING_STYLES = `
113
+ *, *::before, *::after { box-sizing: border-box; }
114
+ :root {
115
+ color-scheme: dark;
116
+ --auth-canvas: #0a0a0a; /* guard:allow-raw-color - match the standalone auth palette */
117
+ --auth-card: #141414; /* guard:allow-raw-color - match the standalone auth palette */
118
+ --auth-border: rgba(255, 255, 255, 0.08); /* guard:allow-raw-color - match the standalone auth palette */
119
+ --auth-foreground: #e5e5e5; /* guard:allow-raw-color - match the standalone auth palette */
120
+ --auth-heading: #fff; /* guard:allow-raw-color - match the standalone auth palette */
121
+ --auth-muted: #888; /* guard:allow-raw-color - match the standalone auth palette */
122
+ --auth-primary: #fff; /* guard:allow-raw-color - match the standalone auth palette */
123
+ --auth-primary-foreground: #000; /* guard:allow-raw-color - match the standalone auth palette */
124
+ --auth-primary-hover: #e5e5e5; /* guard:allow-raw-color - match the standalone auth palette */
125
+ --auth-focus: #33c4ff; /* guard:allow-raw-color - match the standalone auth palette */
126
+ }
127
+ body {
128
+ display: flex;
129
+ align-items: center;
130
+ justify-content: center;
131
+ min-height: 100vh;
132
+ min-height: 100svh;
133
+ margin: 0;
134
+ padding: 1rem;
135
+ background: var(--auth-canvas);
136
+ color: var(--auth-foreground);
137
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
138
+ }
139
+ .auth-card {
140
+ width: 100%;
141
+ max-width: 400px;
142
+ padding: 2rem;
143
+ background: var(--auth-card);
144
+ border: 1px solid var(--auth-border);
145
+ border-radius: 12px;
146
+ }
147
+ h1 {
148
+ margin: 0 0 0.25rem;
149
+ color: var(--auth-heading);
150
+ font-size: 1.25rem;
151
+ font-weight: 600;
152
+ line-height: 1.5;
153
+ }
154
+ p {
155
+ margin: 0 0 1.5rem;
156
+ color: var(--auth-muted);
157
+ font-size: 0.8125rem;
158
+ line-height: 1.5;
159
+ }
160
+ form { margin: 0; }
161
+ button {
162
+ width: 100%;
163
+ min-height: 2.75rem;
164
+ padding: 0.625rem 0.75rem;
165
+ background: var(--auth-primary);
166
+ color: var(--auth-primary-foreground);
167
+ border: 0;
168
+ border-radius: 6px;
169
+ font: inherit;
170
+ font-size: 0.875rem;
171
+ font-weight: 500;
172
+ cursor: pointer;
173
+ transition: background-color 120ms ease;
174
+ }
175
+ button:hover { background: var(--auth-primary-hover); }
176
+ button:focus-visible {
177
+ outline: 2px solid var(--auth-focus);
178
+ outline-offset: 2px;
179
+ }
180
+ @media (max-width: 420px) {
181
+ .auth-card { padding: 1.5rem; }
182
+ }
183
+ @media (prefers-reduced-motion: reduce) {
184
+ button { transition: none; }
185
+ }
186
+ `;
111
187
  export function emailAuthLinkLandingPage(actionUrl, fields, copy, locale, direction) {
112
188
  const hiddenInputs = Object.entries(fields)
113
189
  .map(([name, value]) => `<input type="hidden" name="${escapeHtml(name)}" value="${escapeHtml(value)}">`)
114
190
  .join("");
115
- const html = `<!DOCTYPE html><html lang="${escapeHtml(locale)}" dir="${direction}"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>${escapeHtml(copy.title)}</title></head><body><main><h1>${escapeHtml(copy.title)}</h1><p>${escapeHtml(copy.message)}</p><form method="post" action="${escapeHtml(actionUrl)}" autocomplete="off">${hiddenInputs}<button type="submit">${escapeHtml(copy.action)}</button></form></main></body></html>`;
191
+ // A nonce keeps the standalone page styled without allowing arbitrary inline CSS.
192
+ const styleNonce = randomBytes(16).toString("base64");
193
+ const html = `<!doctype html>
194
+ <html lang="${escapeHtml(locale)}" dir="${direction}">
195
+ <head>
196
+ <meta charset="utf-8">
197
+ <meta name="viewport" content="width=device-width, initial-scale=1">
198
+ <title>${escapeHtml(copy.title)}</title>
199
+ <style nonce="${styleNonce}">${EMAIL_AUTH_LINK_LANDING_STYLES}</style>
200
+ </head>
201
+ <body>
202
+ <main class="auth-card">
203
+ <h1>${escapeHtml(copy.title)}</h1>
204
+ <p>${escapeHtml(copy.message)}</p>
205
+ <form method="post" action="${escapeHtml(actionUrl)}" autocomplete="off">
206
+ ${hiddenInputs}
207
+ <button type="submit">${escapeHtml(copy.action)}</button>
208
+ </form>
209
+ </main>
210
+ </body>
211
+ </html>`;
116
212
  return new Response(html, {
117
213
  status: 200,
118
214
  headers: {
119
215
  "cache-control": "no-store",
120
- "content-security-policy": "default-src 'none'; form-action 'self'; base-uri 'none'; frame-ancestors 'none'",
216
+ "content-security-policy": `default-src 'none'; style-src 'nonce-${styleNonce}'; form-action 'self'; base-uri 'none'; frame-ancestors 'none'`,
121
217
  "content-type": "text/html; charset=utf-8",
122
218
  "referrer-policy": "no-referrer",
123
219
  "x-robots-tag": "noindex",
@@ -1,10 +1,10 @@
1
1
  ---
2
2
  name: review-latest-feedback
3
3
  description: >-
4
- Sweep Slack, GitHub, Sentry, Analytics, trackers, and automated diagnostics,
5
- plus app/template, desktop, and package deploy/release/publish lanes. Fix
6
- verified defects, verify recovery targets, and recap. Use for scheduled or
7
- manual sweeps.
4
+ Review Slack, GitHub, CI, Sentry, Analytics, diagnostics, linked trackers,
5
+ and app/template, desktop, and package deploy/release lanes. Answer reporters
6
+ first; fix verified defects, verify delivery, build upvoted features, and
7
+ recap. Use for scheduled or manual sweeps.
8
8
  user-invocable: true
9
9
  scope: dev
10
10
  metadata:
@@ -218,15 +218,9 @@ Phase 2 reapplies these rules after full-thread review.
218
218
  Use `## Slack channels` unless the invocation narrows scope.
219
219
 
220
220
  **Automated diagnostics are feedback.** For Slack, gate before reading.
221
- Before investigating, use only alert and linked issue/PR/run/task metadata to
222
- identify repo/ref/SHA, workflow/service/environment, failure fingerprint, and
223
- active same-failure owner; this is Phase 0's sole pre-claim exception. If
224
- unowned/in scope, claim: Slack `👀`; elsewhere, current-task status row with
225
- source permalink, fingerprint, owner task/worktree, next action. Continue if
226
- this task owns it; else record **Owned elsewhere** (owner/link/action) and
227
- stop. No logs/tests/artifacts before claim. The required Slack claim reaction
228
- is authorized here; other source mutations need exact authorization. Then read
229
- `references/automated-diagnostics.md`.
221
+ Before claiming, use only alert/link metadata. Follow
222
+ [`automated-diagnostics.md`](references/automated-diagnostics.md) for ownership,
223
+ claim, and stop/continue; inspect logs, tests, and artifacts only afterward.
230
224
 
231
225
  **Defects and design feedback.** A clear bug has observable broken behavior: a
232
226
  click or submit does nothing, an action errors, data is lost or reverted, the
@@ -271,13 +265,12 @@ the query also returns ordinary replies and old polls that happen to carry the
271
265
  reaction. Take the ones that name a concrete improvement; skip the rest
272
266
  without comment.
273
267
 
274
- An upvoted item is a **feature or UX change**: it skips only the clear-bug bar,
275
- not `👀`, fix-altitude, verification, or question-budget requirements. The
276
- upvote overrides the bug gate, not ownership; build the smallest endorsed
277
- version and name Sid or Alice in the recap. Add `👀` before investigation or
278
- delegation and read it back. Keep an evidence-limited disposition until Phase
279
- 2's four bars hold; then use **Shipped**, adding `✅` only if it also meets
280
- **Fixed**.
268
+ An upvote endorses a **feature or UX change** and skips only the clear-bug bar;
269
+ it does not change ownership, reaction, verification, or question-budget rules.
270
+ Build the smallest endorsed version, name Sid or Alice, and state requested
271
+ versus actual behavior in the recap. Add `👀` before investigation or
272
+ delegation and read it back. Keep it evidence-limited until Phase 2's four bars
273
+ hold; then use **Shipped**, adding `✅` only if it meets **Fixed**.
281
274
 
282
275
  Don't search `has::eyes:`; use the owner or handoff path above.
283
276
 
@@ -326,13 +319,15 @@ inventing a fix.
326
319
 
327
320
  ### Deployment, release, and publish failures
328
321
 
329
- Scan app/template, desktop build/release, and package-publish lanes on every
330
- sweep, even without a linked report. Include queued/running runs, run-only
331
- failures, and missing/stale artifacts; carry active run IDs and rows across
332
- cursors. Fix verified repo-owned causes; record external/manual causes with the
333
- next owner/action. Use [`deployment-recovery.md`](references/deployment-recovery.md)
334
- for lane-specific recovery and target proof. Green CI or merged source
335
- does not prove delivery.
322
+ Scan app/template, desktop, and package lanes every sweep, even without linked
323
+ feedback. Carry active run IDs, queued/running runs, failures, and missing/stale
324
+ artifacts across cursors. Fix repo causes; record external/manual causes with
325
+ the next owner/action. CI-red deploy rows from [CI triage](references/ci-red-report.md)
326
+ reuse this operational fingerprint. Follow
327
+ [`deployment-recovery.md`](references/deployment-recovery.md) for recovery and
328
+ target proof; keep delivery active until proof passes. A source issue may be
329
+ **Fixed** separately; delivery gaps are never **Quarantined**. Green CI or
330
+ merged source does not prove delivery.
336
331
 
337
332
  ## Phase 2: fix
338
333
 
@@ -363,8 +358,7 @@ slack_search: <2-4 distinctive symptom words> in:<#CHANNEL>
363
358
  ```
364
359
 
365
360
  Search in the reporter's words — `zoom invalid_client`, `logout twice` — not
366
- your diagnosis. People describe one bug differently, so read the hits rather
367
- than trusting the count.
361
+ your diagnosis. Read hits; one bug may have different descriptions.
368
362
 
369
363
  **A repeat report after a Fixed claim is evidence that fix failed.** It is the
370
364
  only falsification signal this workflow gets, and it outranks your belief that
@@ -435,10 +429,9 @@ pre-existing.
435
429
  ### Npx and package reports have a release follow-up
436
430
 
437
431
  Use [`deployment-recovery.md`](references/deployment-recovery.md) for npx
438
- version evidence, registry proof, publication status, and existing-app upgrade
439
- verification. A verified merge may be **Fixed** under the issue-closure rule
440
- above while its delivery row stays open; a local scaffold or beta promise is not
441
- delivery.
432
+ version, registry, publication, and existing-app upgrade proof. A verified merge
433
+ may be **Fixed** while its delivery row stays open; a local scaffold or beta
434
+ promise is not delivery.
442
435
 
443
436
  ### Documentation has a runnable proof obligation
444
437
 
@@ -457,12 +450,6 @@ Never hard-code a rule for the wording of one report. One data point justifies
457
450
  a local regression test or a contained fix; it never justifies a global agent
458
451
  instruction or prompt exception.
459
452
 
460
- ### The bar for saying "Fixed"
461
-
462
- Phase 2 defines the proof bars for **Fixed**, **Shipped**, and
463
- **Live verified**. Upvoted improvements state requested versus actual behavior
464
- and use **Shipped**.
465
-
466
453
  ## Phase 3: reply
467
454
 
468
455
  Thank issue reporters for opening it and Slack reporters for sharing. Give the
@@ -46,10 +46,25 @@ and pass normalized action items to an app's idempotent `import` action.
46
46
 
47
47
  | Tool | Action | Purpose |
48
48
  | ------------- | ---------- | ---------------------------------------------------------- |
49
- | `manage-jobs` | `create` | Create a recurring job (name, cron schedule, instructions) |
49
+ | `manage-jobs` | `create` | Create a recurring job (name, cron schedule, instructions); fails if the name exists |
50
50
  | `manage-jobs` | `list` | List all jobs and their status |
51
51
  | `manage-jobs` | `update` | Update schedule, instructions, or toggle enabled |
52
52
 
53
+ ## Job files an app owns
54
+
55
+ `create` never replaces an existing job file, so a name that collides with an
56
+ app's file (Factory's `factories/<id>/<name>`) is refused instead of reset.
57
+ An app that stores its own settings in a job's frontmatter marks the file with
58
+ `triggerType`, which makes `list`, `update`, and `delete` skip it and sends the
59
+ caller to `manage-automations`. Edit those files only through the owning app's
60
+ actions, and patch fields in place; rebuilding a file from the fields the writer
61
+ knows drops the rest while the job keeps running.
62
+
63
+ Any write to a `jobs/` file that removes a frontmatter field other than run
64
+ bookkeeping is recorded as a `job-fields-dropped` audit event (org admins read
65
+ it with `list-audit-events` and `action: "job-fields-dropped"`). Its input names
66
+ the writer, the dropped fields, and the agent thread and run that made it.
67
+
53
68
  ## UI Surface
54
69
 
55
70
  `/agent#jobs` is the stable compatibility URL for the Agent page's
@@ -13,8 +13,6 @@ declare const _default: import("../../action.js").ActionDefinition<{
13
13
  executionEngine?: string;
14
14
  executionCwd?: string;
15
15
  }, {
16
- deleted?: undefined;
17
- enabled?: undefined;
18
16
  created: boolean;
19
17
  name: string;
20
18
  scope: "organization" | "personal";
@@ -25,31 +23,33 @@ declare const _default: import("../../action.js").ActionDefinition<{
25
23
  reasoningEffort: "auto" | "high" | "low" | "max" | "medium" | "minimal" | "none" | "xhigh";
26
24
  webhookPath: string;
27
25
  nextRun: string;
26
+ deleted?: undefined;
27
+ enabled?: undefined;
28
28
  executionHostId?: undefined;
29
29
  executionEngine?: undefined;
30
30
  executionCwd?: undefined;
31
31
  } | {
32
- scope?: undefined;
33
- enabled?: undefined;
34
- nextRun?: undefined;
35
32
  created?: undefined;
33
+ scope?: undefined;
36
34
  triggerType?: undefined;
37
35
  event?: undefined;
38
36
  deleted: boolean;
39
37
  name: string;
38
+ enabled?: undefined;
40
39
  schedule?: undefined;
41
40
  timezone?: undefined;
42
41
  reasoningEffort?: undefined;
43
42
  executionHostId?: undefined;
44
43
  executionEngine?: undefined;
45
44
  executionCwd?: undefined;
45
+ nextRun?: undefined;
46
46
  webhookPath?: undefined;
47
47
  } | {
48
- scope?: undefined;
49
- deleted?: undefined;
50
48
  created?: undefined;
49
+ scope?: undefined;
51
50
  triggerType?: undefined;
52
51
  event?: undefined;
52
+ deleted?: undefined;
53
53
  name: string;
54
54
  enabled: boolean;
55
55
  schedule: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core",
3
- "version": "0.203.1-nightly-20261007154213",
3
+ "version": "0.203.1",
4
4
  "description": "The agentic application framework for building autonomous agents with intuitive UIs",
5
5
  "homepage": "https://github.com/BuilderIO/agent-native#readme",
6
6
  "bugs": {
@@ -682,8 +682,8 @@
682
682
  "yaml": "^2.9.0",
683
683
  "yjs": "^13.6.33",
684
684
  "zod": "^4.3.6",
685
- "@agent-native/agentkit": "^0.203.1-nightly-20261007154213",
686
- "@agent-native/recap-cli": "^0.5.64"
685
+ "@agent-native/agentkit": "^0.203.1",
686
+ "@agent-native/recap-cli": "^0.5.65"
687
687
  },
688
688
  "devDependencies": {
689
689
  "@ai-sdk/anthropic": "^3.0.71",
@@ -753,7 +753,7 @@
753
753
  "xlsx": "^0.18.5"
754
754
  },
755
755
  "peerDependencies": {
756
- "@agent-native/core-corpus": "0.203.1-nightly-20261007154213",
756
+ "@agent-native/core-corpus": ">=0.196.0",
757
757
  "@ai-sdk/anthropic": ">=3",
758
758
  "@ai-sdk/cohere": ">=3",
759
759
  "@ai-sdk/google": ">=3",
@@ -1,10 +1,10 @@
1
1
  ---
2
2
  name: review-latest-feedback
3
3
  description: >-
4
- Sweep Slack, GitHub, Sentry, Analytics, trackers, and automated diagnostics,
5
- plus app/template, desktop, and package deploy/release/publish lanes. Fix
6
- verified defects, verify recovery targets, and recap. Use for scheduled or
7
- manual sweeps.
4
+ Review Slack, GitHub, CI, Sentry, Analytics, diagnostics, linked trackers,
5
+ and app/template, desktop, and package deploy/release lanes. Answer reporters
6
+ first; fix verified defects, verify delivery, build upvoted features, and
7
+ recap. Use for scheduled or manual sweeps.
8
8
  user-invocable: true
9
9
  scope: dev
10
10
  metadata:
@@ -218,15 +218,9 @@ Phase 2 reapplies these rules after full-thread review.
218
218
  Use `## Slack channels` unless the invocation narrows scope.
219
219
 
220
220
  **Automated diagnostics are feedback.** For Slack, gate before reading.
221
- Before investigating, use only alert and linked issue/PR/run/task metadata to
222
- identify repo/ref/SHA, workflow/service/environment, failure fingerprint, and
223
- active same-failure owner; this is Phase 0's sole pre-claim exception. If
224
- unowned/in scope, claim: Slack `👀`; elsewhere, current-task status row with
225
- source permalink, fingerprint, owner task/worktree, next action. Continue if
226
- this task owns it; else record **Owned elsewhere** (owner/link/action) and
227
- stop. No logs/tests/artifacts before claim. The required Slack claim reaction
228
- is authorized here; other source mutations need exact authorization. Then read
229
- `references/automated-diagnostics.md`.
221
+ Before claiming, use only alert/link metadata. Follow
222
+ [`automated-diagnostics.md`](references/automated-diagnostics.md) for ownership,
223
+ claim, and stop/continue; inspect logs, tests, and artifacts only afterward.
230
224
 
231
225
  **Defects and design feedback.** A clear bug has observable broken behavior: a
232
226
  click or submit does nothing, an action errors, data is lost or reverted, the
@@ -271,13 +265,12 @@ the query also returns ordinary replies and old polls that happen to carry the
271
265
  reaction. Take the ones that name a concrete improvement; skip the rest
272
266
  without comment.
273
267
 
274
- An upvoted item is a **feature or UX change**: it skips only the clear-bug bar,
275
- not `👀`, fix-altitude, verification, or question-budget requirements. The
276
- upvote overrides the bug gate, not ownership; build the smallest endorsed
277
- version and name Sid or Alice in the recap. Add `👀` before investigation or
278
- delegation and read it back. Keep an evidence-limited disposition until Phase
279
- 2's four bars hold; then use **Shipped**, adding `✅` only if it also meets
280
- **Fixed**.
268
+ An upvote endorses a **feature or UX change** and skips only the clear-bug bar;
269
+ it does not change ownership, reaction, verification, or question-budget rules.
270
+ Build the smallest endorsed version, name Sid or Alice, and state requested
271
+ versus actual behavior in the recap. Add `👀` before investigation or
272
+ delegation and read it back. Keep it evidence-limited until Phase 2's four bars
273
+ hold; then use **Shipped**, adding `✅` only if it meets **Fixed**.
281
274
 
282
275
  Don't search `has::eyes:`; use the owner or handoff path above.
283
276
 
@@ -326,13 +319,15 @@ inventing a fix.
326
319
 
327
320
  ### Deployment, release, and publish failures
328
321
 
329
- Scan app/template, desktop build/release, and package-publish lanes on every
330
- sweep, even without a linked report. Include queued/running runs, run-only
331
- failures, and missing/stale artifacts; carry active run IDs and rows across
332
- cursors. Fix verified repo-owned causes; record external/manual causes with the
333
- next owner/action. Use [`deployment-recovery.md`](references/deployment-recovery.md)
334
- for lane-specific recovery and target proof. Green CI or merged source
335
- does not prove delivery.
322
+ Scan app/template, desktop, and package lanes every sweep, even without linked
323
+ feedback. Carry active run IDs, queued/running runs, failures, and missing/stale
324
+ artifacts across cursors. Fix repo causes; record external/manual causes with
325
+ the next owner/action. CI-red deploy rows from [CI triage](references/ci-red-report.md)
326
+ reuse this operational fingerprint. Follow
327
+ [`deployment-recovery.md`](references/deployment-recovery.md) for recovery and
328
+ target proof; keep delivery active until proof passes. A source issue may be
329
+ **Fixed** separately; delivery gaps are never **Quarantined**. Green CI or
330
+ merged source does not prove delivery.
336
331
 
337
332
  ## Phase 2: fix
338
333
 
@@ -363,8 +358,7 @@ slack_search: <2-4 distinctive symptom words> in:<#CHANNEL>
363
358
  ```
364
359
 
365
360
  Search in the reporter's words — `zoom invalid_client`, `logout twice` — not
366
- your diagnosis. People describe one bug differently, so read the hits rather
367
- than trusting the count.
361
+ your diagnosis. Read hits; one bug may have different descriptions.
368
362
 
369
363
  **A repeat report after a Fixed claim is evidence that fix failed.** It is the
370
364
  only falsification signal this workflow gets, and it outranks your belief that
@@ -435,10 +429,9 @@ pre-existing.
435
429
  ### Npx and package reports have a release follow-up
436
430
 
437
431
  Use [`deployment-recovery.md`](references/deployment-recovery.md) for npx
438
- version evidence, registry proof, publication status, and existing-app upgrade
439
- verification. A verified merge may be **Fixed** under the issue-closure rule
440
- above while its delivery row stays open; a local scaffold or beta promise is not
441
- delivery.
432
+ version, registry, publication, and existing-app upgrade proof. A verified merge
433
+ may be **Fixed** while its delivery row stays open; a local scaffold or beta
434
+ promise is not delivery.
442
435
 
443
436
  ### Documentation has a runnable proof obligation
444
437
 
@@ -457,12 +450,6 @@ Never hard-code a rule for the wording of one report. One data point justifies
457
450
  a local regression test or a contained fix; it never justifies a global agent
458
451
  instruction or prompt exception.
459
452
 
460
- ### The bar for saying "Fixed"
461
-
462
- Phase 2 defines the proof bars for **Fixed**, **Shipped**, and
463
- **Live verified**. Upvoted improvements state requested versus actual behavior
464
- and use **Shipped**.
465
-
466
453
  ## Phase 3: reply
467
454
 
468
455
  Thank issue reporters for opening it and Slack reporters for sharing. Give the
@@ -46,10 +46,25 @@ and pass normalized action items to an app's idempotent `import` action.
46
46
 
47
47
  | Tool | Action | Purpose |
48
48
  | ------------- | ---------- | ---------------------------------------------------------- |
49
- | `manage-jobs` | `create` | Create a recurring job (name, cron schedule, instructions) |
49
+ | `manage-jobs` | `create` | Create a recurring job (name, cron schedule, instructions); fails if the name exists |
50
50
  | `manage-jobs` | `list` | List all jobs and their status |
51
51
  | `manage-jobs` | `update` | Update schedule, instructions, or toggle enabled |
52
52
 
53
+ ## Job files an app owns
54
+
55
+ `create` never replaces an existing job file, so a name that collides with an
56
+ app's file (Factory's `factories/<id>/<name>`) is refused instead of reset.
57
+ An app that stores its own settings in a job's frontmatter marks the file with
58
+ `triggerType`, which makes `list`, `update`, and `delete` skip it and sends the
59
+ caller to `manage-automations`. Edit those files only through the owning app's
60
+ actions, and patch fields in place; rebuilding a file from the fields the writer
61
+ knows drops the rest while the job keeps running.
62
+
63
+ Any write to a `jobs/` file that removes a frontmatter field other than run
64
+ bookkeeping is recorded as a `job-fields-dropped` audit event (org admins read
65
+ it with `list-audit-events` and `action: "job-fields-dropped"`). Its input names
66
+ the writer, the dropped fields, and the agent thread and run that made it.
67
+
53
68
  ## UI Surface
54
69
 
55
70
  `/agent#jobs` is the stable compatibility URL for the Agent page's