diff --git a/README.md b/README.md
index a2bf31f..9544388 100644
--- a/README.md
+++ b/README.md
@@ -297,7 +297,7 @@ the CLI fallback, then continue the same workflow check with `--ran-suggest`.
## Public truth
-v0.4.30 · 36 MCP tools + 5 prompts · 214 diagnostic codes · 1350 tests · 58 live packages · 34 bundled templates
+v0.4.30 · 36 MCP tools + 5 prompts · 214 diagnostic codes · 1362 tests · 58 live packages · 39 bundled templates
Public proof is generated from `../public-truth/public-truth.json` via `npm --prefix .. run truth:sync`.
diff --git a/ROADMAP.md b/ROADMAP.md
index b2955cd..1a687e6 100644
--- a/ROADMAP.md
+++ b/ROADMAP.md
@@ -1,11 +1,13 @@
# Axint Roadmap
-_Last updated: May 2026 · Current release: [v0.4.28](https://github.com/agenticempire/axint/releases/tag/v0.4.28)_
+_Last updated: June 2026 · Current release: [v0.4.30](https://github.com/agenticempire/axint/releases/tag/v0.4.30)_
Axint is the Apple-native execution layer for AI coding agents. The open-source package gives agents a smaller contract for Apple surfaces, emits ordinary Swift, validates Apple-specific rules, writes Fix Packets, and coordinates proof loops across CLI, MCP, Xcode, Registry, and Cloud-facing workflows.
The thesis is simple: agents can write code, but Apple-native software needs proof. Axint turns agent output into validated, repairable, inspectable Apple work.
+Current compiler snapshot: v0.4.30 · 36 MCP tools + 5 prompts · 39 templates · 214 diagnostic codes · 1362 tests.
+
---
## Shipped Now
@@ -22,8 +24,8 @@ The thesis is simple: agents can write code, but Apple-native software needs pro
- TypeScript, Python, JSON schema mode, and preview `.axint` inputs compile into Apple-native Swift.
- Supported surfaces include App Intents, SwiftUI views, WidgetKit widgets, app scaffolds, plist fragments, entitlements, and Apple metadata.
-- The validator covers 204 diagnostic codes across compiler, intent, view, widget, app, Swift build, SwiftUI, accessibility, concurrency, and Live Activity rules.
-- The suite currently tracks 1319 tests across TypeScript and Python paths.
+- The validator covers 214 diagnostic codes across compiler, intent, view, widget, app, Swift build, SwiftUI, accessibility, concurrency, and Live Activity rules.
+- The suite currently tracks 1362 tests across TypeScript and Python paths.
### Agent distribution
@@ -35,7 +37,7 @@ The thesis is simple: agents can write code, but Apple-native software needs pro
### First-use and templates
- `create-axint-app` / `axint create` generates the Apple Day Agent starter: multiple App Intent contracts, generated Swift, plist and entitlement fragments, agent prompts, proof artifacts, and an interactive local proof preview.
-- 26 bundled templates and 58 live Registry packages give agents reusable starting points instead of asking them to hallucinate every Apple surface from scratch.
+- 39 bundled templates and 58 live Registry packages give agents reusable starting points instead of asking them to hallucinate every Apple surface from scratch.
### Privacy-safe learning and adoption proof
diff --git a/extensions/README.md b/extensions/README.md
index baa962b..18525f1 100644
--- a/extensions/README.md
+++ b/extensions/README.md
@@ -12,7 +12,7 @@ Pre-built integrations for every major AI coding tool. Each directory contains t
| **Cursor** | Copy `cursor/mcp.json` → `.cursor/mcp.json` or search in Settings → Tools → MCP |
| **Windsurf** | Copy `windsurf/mcp_config.json` → `~/.codeium/windsurf/mcp_config.json` |
| **Codex** | Copy `codex/mcp.json` into your Codex MCP config |
-| **Xcode** | Add SPM dependency (see `xcode/README.md`) |
+| **Xcode** | Use the Xcode 27 agent plugin or add the SPM dependency (see `xcode/README.md`) |
| **JetBrains** | Settings → Tools → AI Assistant → MCP Servers (see `jetbrains/README.md`) |
| **Zed** | Add to `~/.config/zed/settings.json` (see `zed/README.md`) |
| **Neovim** | Configure your MCP plugin (see `neovim/README.md`) |
diff --git a/extensions/xcode/README.md b/extensions/xcode/README.md
index 4d92ea4..fd2817f 100644
--- a/extensions/xcode/README.md
+++ b/extensions/xcode/README.md
@@ -1,6 +1,6 @@
# Axint for Xcode
-Axint integrates with Xcode in four ways: as an MCP server for agentic coding, as an SPM build plugin for compile-time generation, as a [native Source Editor Extension](./source-editor-extension) for in-editor quickfixes, and via the `axint xcode setup` command for one-step configuration.
+Axint integrates with Xcode in five ways: as an Xcode 27 agent plugin, as an MCP server for agentic coding, as an SPM build plugin for compile-time generation, as a [native Source Editor Extension](./source-editor-extension) for in-editor quickfixes, and via the `axint xcode setup` command for one-step configuration.
## Quick Setup (recommended)
@@ -27,6 +27,26 @@ What MCP servers are available?
You should see both `xcode-tools` and `axint`.
+## Xcode 27 Agent Plugin
+
+Xcode 27 can load agent plugins that bundle skills, MCP servers, and tool metadata. Axint ships a public plugin package at [`agent-plugin/plugin.json`](./agent-plugin/plugin.json) so Xcode agents can discover the Axint MCP server with branded tool names and an Apple Intelligence proof skill.
+
+The plugin points Xcode at the npm package:
+
+```json
+{
+ "mcpServers": {
+ "axint": {
+ "type": "stdio",
+ "command": "npx",
+ "args": ["-y", "-p", "@axint/compiler", "axint-mcp"]
+ }
+ }
+}
+```
+
+Use the bundled `apple-intelligence-proof` skill when building App Intents schemas, Foundation Models features, previews, localization flows, or any Xcode 27 Apple Intelligence surface. It requires `axint.swift.validate`, `axint.cloud.check`, AppIntentsTesting proof for schema-backed App Intents, and focused Xcode build/test evidence before the agent can call a feature demo-ready.
+
## MCP for Xcode Agentic Coding
Xcode 26.3+ supports agentic coding with external agents via MCP. Axint adds specialized Apple-native feature generation on top of Xcode's built-in workspace/build/test tools.
diff --git a/extensions/xcode/agent-plugin/icon.svg b/extensions/xcode/agent-plugin/icon.svg
new file mode 100644
index 0000000..70d3343
--- /dev/null
+++ b/extensions/xcode/agent-plugin/icon.svg
@@ -0,0 +1,4 @@
+
diff --git a/extensions/xcode/agent-plugin/plugin.json b/extensions/xcode/agent-plugin/plugin.json
new file mode 100644
index 0000000..18c8035
--- /dev/null
+++ b/extensions/xcode/agent-plugin/plugin.json
@@ -0,0 +1,37 @@
+{
+ "name": "Axint",
+ "description": "Apple Intelligence proof layer for Xcode agents: compile, validate, repair, and prove App Intents, Foundation Models, previews, localization, and Xcode build loops.",
+ "version": "0.4.30",
+ "homepage": "https://axint.ai",
+ "repository": "https://github.com/agenticempire/axint",
+ "license": "Apache-2.0",
+ "mcpServers": {
+ "axint": {
+ "type": "stdio",
+ "command": "npx",
+ "args": ["-y", "-p", "@axint/compiler", "axint-mcp"],
+ "tools": ["*"],
+ "_meta": {
+ "ideToolIconPath": "./icon.svg",
+ "ideToolIconRendersAsTemplate": true,
+ "ideToolTitles": {
+ "axint.status": "Axint Status",
+ "axint.suggest": "Apple Feature Plan",
+ "axint.feature": "Generate Apple Feature",
+ "axint.swift.validate": "Swift Validator",
+ "axint.cloud.check": "Apple Readiness Check",
+ "axint.repair": "Apple Repair Plan",
+ "axint.run": "Build Proof Loop",
+ "axint.xcode.guard": "Axint Guard",
+ "axint.xcode.write": "Guarded Swift Write"
+ }
+ }
+ }
+ },
+ "skills": [
+ {
+ "name": "apple-intelligence-proof",
+ "path": "./skills/apple-intelligence-proof.md"
+ }
+ ]
+}
diff --git a/extensions/xcode/agent-plugin/skills/apple-intelligence-proof.md b/extensions/xcode/agent-plugin/skills/apple-intelligence-proof.md
new file mode 100644
index 0000000..7bfa5ab
--- /dev/null
+++ b/extensions/xcode/agent-plugin/skills/apple-intelligence-proof.md
@@ -0,0 +1,19 @@
+# Apple Intelligence Proof
+
+Use Axint before and after every Apple Intelligence or App Intents edit in Xcode.
+
+## Required Loop
+
+1. Start with `axint.status`, then `axint.session.start` for the project.
+2. For new App Intents, entities, enums, Foundation Models, previews, or localization flows, call `axint.suggest` or `axint.feature` before writing code.
+3. After edits, run `axint.swift.validate` on changed Swift files.
+4. Run `axint.cloud.check` with Xcode 27 build/test evidence.
+5. For schema-backed App Intents, attach AppIntentsTesting proof for Siri, Shortcuts, and Spotlight pathways.
+6. Before claiming the task is fixed, run `axint.run` or focused `xcodebuild` proof and summarize the exact command output.
+
+## Guardrails
+
+- Do not call generated Apple Intelligence code demo-ready from static checks alone.
+- Do not invent App Schema, Foundation Models, or AppIntentsTesting APIs.
+- If Xcode 27 beta is installed outside the selected developer directory, set `DEVELOPER_DIR` before build/test proof.
+- Keep source, prompts, and user content out of public reports unless the user explicitly opts in.
diff --git a/metrics.json b/metrics.json
index 710b031..6883d88 100644
--- a/metrics.json
+++ b/metrics.json
@@ -47,7 +47,7 @@
"axint.create-widget",
"axint.create-intent"
],
- "bundledTemplates": 34,
+ "bundledTemplates": 39,
"diagnostics": 214,
"xcodeFixRules": 33,
"xcodeFixRuleCodes": [
@@ -86,7 +86,7 @@
"AX748"
],
"tests": {
- "typescript": 1236,
+ "typescript": 1248,
"python": 114
},
"registryPackages": 58,
diff --git a/src/cloud/check.ts b/src/cloud/check.ts
index 984e762..4dec9fa 100644
--- a/src/cloud/check.ts
+++ b/src/cloud/check.ts
@@ -496,6 +496,18 @@ export function runCloudCheck(input: CloudCheckInput): CloudCheckReport {
: []),
]
) satisfies CloudCheckReport["checks"];
+ const wwdc26Diagnostics = diagnostics.filter((diagnostic) =>
+ diagnostic.code.startsWith("AXCLOUD-WWDC26-")
+ );
+ if (wwdc26Diagnostics.length > 0) {
+ checks.push({
+ label: "Xcode 27 readiness",
+ state: wwdc26Diagnostics.some((diagnostic) => diagnostic.severity === "error")
+ ? "fail"
+ : "warn",
+ detail: `${wwdc26Diagnostics.length} WWDC26 proof requirement${wwdc26Diagnostics.length === 1 ? "" : "s"} need evidence before this is demo-ready.`,
+ });
+ }
if (projectContext) {
checks.push({
label: "Project context pack",
@@ -1204,6 +1216,29 @@ function diagnosticsFromWwdc26Readiness(
): Diagnostic[] {
const diagnostics: Diagnostic[] = [];
const lower = source.toLowerCase();
+ const touchesEvaluationProof =
+ /\b[A-Za-z_][A-Za-z0-9_]*Evaluations\b/.test(source) ||
+ /\b(static\s+let\s+scenarios|static\s+let\s+criteria|Evaluation\s+suite)\b/i.test(
+ source
+ );
+ const touchesPreviewSnapshotProof =
+ /\bPreview Snapshot proof matrix\b/i.test(source) ||
+ /\bpreviewProof\b/.test(source) ||
+ /\bXcode Preview Snapshot proof\b/i.test(source);
+ const touchesVisualIntelligence =
+ /\b(VisualIntelligence|VisionKit|visual-intelligence|visual intelligence)\b/i.test(
+ source
+ );
+ const touchesImagePlayground =
+ /\b(ImagePlayground|Image Playground|generated image)\b/i.test(source);
+ const touchesStringCatalog =
+ /\b(StringCatalog|String Catalog|Localizable\.xcstrings|\.xcstrings|generated translations?)\b/i.test(
+ source
+ );
+ const touchesResizableIosLayout =
+ /\bSwiftUI\b/.test(source) &&
+ /\bView\b/.test(source) &&
+ /\.frame\s*\([^)]*\b(width|height)\s*:\s*\d{3,}/.test(source);
const touchesAppleIntelligence =
/@App(Intent|Entity|Enum)\(schema:/.test(source) ||
/\b(AppSchema|SyncableEntity|OwnershipProvidingEntity|IndexedEntityQuery|IntentValueQuery|FoundationModels|LanguageModelSession|SystemLanguageModel|PrivateCloudComputeLanguageModel|GenerationSchema|ToolCallingMode)\b/.test(
@@ -1212,10 +1247,56 @@ function diagnosticsFromWwdc26Readiness(
/@(?:Generable|UnionValue)\b/.test(source) ||
/\b(LongRunningIntent|ProgressReportingIntent|SnippetIntent|ShowsSnippetIntent|ShowsSnippetView|ResultsCollection|IntentItemCollection|AppUnionValue|AppUnionValueCasesProviding)\b/.test(
source
- );
+ ) ||
+ touchesEvaluationProof ||
+ touchesPreviewSnapshotProof ||
+ touchesVisualIntelligence ||
+ touchesImagePlayground ||
+ touchesStringCatalog ||
+ touchesResizableIosLayout;
if (!touchesAppleIntelligence) return diagnostics;
+ const touchesAppIntentSystemPath =
+ /@App(Intent|Entity|Enum)\(schema:/.test(source) ||
+ /\b(AppSchema|AssistantSchemaIntent|AssistantIntent|IndexedEntity|IndexedEntityQuery|AppShortcutsProvider)\b/.test(
+ source
+ );
+
+ if (
+ touchesAppIntentSystemPath &&
+ !/\b(xcode\s*27|ios\s*27|ipados\s*27|macos\s*27|visionos\s*27|sdk\s*27)\b/.test(
+ evidenceText
+ )
+ ) {
+ diagnostics.push({
+ code: "AXCLOUD-WWDC26-XCODE27-PROOF",
+ severity: "warning",
+ file,
+ message:
+ "WWDC26 App Intents and Apple Intelligence surfaces need Xcode 27 / SDK 27 proof before they are demo-ready.",
+ suggestion:
+ "Attach Xcode 27 build/test evidence, or rerun the proof loop with DEVELOPER_DIR pointing at the Xcode 27 beta.",
+ });
+ }
+
+ if (
+ /@App(Intent|Entity|Enum)\(schema:/.test(source) &&
+ !/\b(appintentstesting|app\s*intents\s*testing|siri|shortcuts|spotlight)\b/.test(
+ evidenceText
+ )
+ ) {
+ diagnostics.push({
+ code: "AXCLOUD-WWDC26-APPINTENTS-TESTING",
+ severity: "warning",
+ file,
+ message:
+ "Schema-backed App Intents need AppIntentsTesting proof through the same Siri, Shortcuts, and Spotlight pathways people will use.",
+ suggestion:
+ "Add an AppIntentsTesting test for the intent/entity/enum adoption, then attach the passing Xcode 27 test log to Cloud Check.",
+ });
+ }
+
if (
/@AppEntity\(schema:/.test(source) &&
!/\bSyncableEntity\b/.test(source) &&
@@ -1279,6 +1360,108 @@ function diagnosticsFromWwdc26Readiness(
});
}
+ if (
+ touchesEvaluationProof &&
+ !/\b(evaluation|evaluations|scenario|criteria|pass|passed|xcode\s*27|test succeeded|0 failures)\b/.test(
+ evidenceText
+ )
+ ) {
+ diagnostics.push({
+ code: "AXCLOUD-WWDC26-EVALUATION-PROOF",
+ severity: "warning",
+ file,
+ message:
+ "Evaluation suites need attached scenario evidence before model-backed behavior is demo-ready.",
+ suggestion:
+ "Attach the passing evaluation run, Xcode 27 test log, or scenario/criteria proof that covers the generated suite.",
+ });
+ }
+
+ if (
+ touchesPreviewSnapshotProof &&
+ !/\b(preview snapshot|snapshot|baseline|variant|accessibility|xcode\s*27|test succeeded|0 failures)\b/.test(
+ evidenceText
+ )
+ ) {
+ diagnostics.push({
+ code: "AXCLOUD-WWDC26-PREVIEW-SNAPSHOT-PROOF",
+ severity: "warning",
+ file,
+ message:
+ "Preview Snapshot proof matrices need attached rendered snapshot evidence before release.",
+ suggestion:
+ "Attach the Xcode 27 Preview Snapshot run or baseline artifact for each declared variant, including accessibility-size variants when listed.",
+ });
+ }
+
+ if (
+ touchesVisualIntelligence &&
+ !/\b(visual intelligence|visionkit|screenshot|camera|object|image understanding|xcode\s*27|test succeeded|0 failures)\b/.test(
+ evidenceText
+ )
+ ) {
+ diagnostics.push({
+ code: "AXCLOUD-WWDC26-VISUAL-INTELLIGENCE-PROOF",
+ severity: "warning",
+ file,
+ message:
+ "Visual Intelligence routes need screenshot/object-understanding proof before they are demo-ready.",
+ suggestion:
+ "Attach the Xcode 27 run, screenshot fixture, or VisionKit/Visual Intelligence evidence showing the detected object maps to the intended app action.",
+ });
+ }
+
+ if (
+ touchesImagePlayground &&
+ !/\b(image playground|generated image|image generation|style|safety|private cloud compute|pcc|xcode\s*27|test succeeded|0 failures)\b/.test(
+ evidenceText
+ )
+ ) {
+ diagnostics.push({
+ code: "AXCLOUD-WWDC26-IMAGE-PLAYGROUND-PROOF",
+ severity: "warning",
+ file,
+ message:
+ "Image Playground flows need generated-image proof before they are safe to present as working.",
+ suggestion:
+ "Attach the generated image artifact or Xcode 27 run evidence, including prompt/style notes and any safety or Private Cloud Compute constraints.",
+ });
+ }
+
+ if (
+ touchesStringCatalog &&
+ !/\b(string catalog|xcstrings|localization|localized|locale|translation|xliff|xcode\s*27|test succeeded|0 failures)\b/.test(
+ evidenceText
+ )
+ ) {
+ diagnostics.push({
+ code: "AXCLOUD-WWDC26-STRING-CATALOG-PROOF",
+ severity: "warning",
+ file,
+ message: "String Catalog workflows need localization proof before release.",
+ suggestion:
+ "Attach the updated .xcstrings output, locale coverage, or Xcode 27 localization/export evidence for the generated strings.",
+ });
+ }
+
+ if (
+ touchesResizableIosLayout &&
+ !/\b(resizable|size class|compact|regular|dynamic type|accessibility|preview snapshot|baseline|xcode\s*27|test succeeded|0 failures)\b/.test(
+ evidenceText
+ )
+ ) {
+ diagnostics.push({
+ code: "AXCLOUD-WWDC26-RESIZABLE-IOS-LAYOUT",
+ severity: "warning",
+ file,
+ line: findLine(source, ".frame"),
+ message:
+ "SwiftUI layouts with fixed large frame dimensions need resizable iOS proof.",
+ suggestion:
+ "Replace fixed device-sized frames with adaptive layout, or attach Preview Snapshot evidence across compact/regular, landscape, and accessibility-size variants.",
+ });
+ }
+
if (
/\bLongRunningIntent\b/.test(source) &&
!/\b(performBackgroundTask|LongRunningTaskOptions)\b/.test(
diff --git a/src/core/generator.ts b/src/core/generator.ts
index 4695f31..fd39c75 100644
--- a/src/core/generator.ts
+++ b/src/core/generator.ts
@@ -20,6 +20,8 @@ import type {
IRType,
IREntity,
IRParameterSummary,
+ IREvaluationConfig,
+ IRPreviewProofConfig,
} from "./types.js";
import { irTypeToSwift } from "./types.js";
@@ -38,6 +40,10 @@ export function escapeSwiftString(s: string): string {
.replace(/\t/g, "\\t");
}
+function quotedSwiftString(value: string): string {
+ return `"${escapeSwiftString(value)}"`;
+}
+
/**
* Escape a string for safe interpolation into XML (Info.plist or
* .entitlements). Plist XML uses the same rules as general XML.
@@ -75,6 +81,9 @@ export function generateSwift(intent: IRIntent): string {
if (intentUsesCoreTransferable(safeIntent)) {
lines.push(`import CoreTransferable`);
}
+ if (safeIntent.model) {
+ lines.push(`import FoundationModels`);
+ }
lines.push(`import Foundation`);
lines.push(``);
@@ -93,6 +102,11 @@ export function generateSwift(intent: IRIntent): string {
lines.push(``);
}
+ if (safeIntent.model) {
+ lines.push(generateFoundationModelSupport(safeIntent));
+ lines.push(``);
+ }
+
// Struct declaration
if (safeIntent.schema) {
lines.push(`@AppIntent(schema: ${safeIntent.schema})`);
@@ -166,6 +180,16 @@ export function generateSwift(intent: IRIntent): string {
lines.push(`}`);
lines.push(``);
+ if (safeIntent.evaluation) {
+ lines.push(generateEvaluationSupport(safeIntent.evaluation));
+ lines.push(``);
+ }
+
+ if (safeIntent.previewProof) {
+ lines.push(generatePreviewProofSupport(safeIntent.previewProof));
+ lines.push(``);
+ }
+
return lines.join("\n");
}
@@ -364,6 +388,121 @@ function generateDynamicOptionsProvider(providerName: string, valueType: IRType)
return lines.join("\n");
}
+function generateFoundationModelSupport(intent: IRIntent): string {
+ const model = intent.model!;
+ const sessionName = model.sessionName || `${intent.name}ModelSession`;
+ const lines: string[] = [];
+
+ if (model.generable) {
+ lines.push(`@Generable`);
+ lines.push(`struct ${model.generable.name}: Generable {`);
+ for (const [name, type] of Object.entries(model.generable.fields)) {
+ lines.push(` var ${name}: ${type}`);
+ }
+ lines.push(`}`);
+ lines.push(``);
+ }
+
+ for (const tool of model.tools ?? []) {
+ const argumentsType = tool.argumentsType || `${tool.name}Arguments`;
+ const outputType = tool.outputType || "String";
+ lines.push(`struct ${tool.name}: Tool {`);
+ lines.push(` let name = "${escapeSwiftString(tool.name)}"`);
+ lines.push(` let description = "${escapeSwiftString(tool.description)}"`);
+ lines.push(``);
+ lines.push(` @Generable`);
+ lines.push(` struct Arguments: Generable {`);
+ lines.push(
+ ` // TODO: Replace with fields from ${escapeSwiftString(argumentsType)}.`
+ );
+ lines.push(` var query: String`);
+ lines.push(` }`);
+ lines.push(``);
+ lines.push(` func call(arguments: Arguments) async throws -> ${outputType} {`);
+ lines.push(` // TODO: Implement ${escapeSwiftString(tool.name)} safely.`);
+ lines.push(` ${defaultFoundationModelToolReturn(outputType)}`);
+ lines.push(` }`);
+ lines.push(`}`);
+ lines.push(``);
+ }
+
+ lines.push(`enum ${sessionName}Factory {`);
+ lines.push(` static func make() -> LanguageModelSession {`);
+ if (model.instructions) {
+ lines.push(
+ ` let instructions = Instructions("${escapeSwiftString(model.instructions)}")`
+ );
+ } else {
+ lines.push(` let instructions = Instructions("")`);
+ }
+ if (model.dynamicProfile) {
+ lines.push(` // Dynamic Profile: ${escapeSwiftString(model.dynamicProfile)}`);
+ }
+ if (model.guardrails?.length) {
+ lines.push(
+ ` // Guardrails: ${model.guardrails.map(escapeSwiftString).join(", ")}`
+ );
+ }
+ lines.push(
+ ` // Provider: ${escapeSwiftString(model.provider)}${model.useCase ? ` · Use case: ${escapeSwiftString(model.useCase)}` : ""}`
+ );
+ if (model.prompt) {
+ lines.push(` // Prompt seed: ${escapeSwiftString(model.prompt)}`);
+ }
+ lines.push(` return LanguageModelSession(instructions: instructions)`);
+ lines.push(` }`);
+ lines.push(`}`);
+
+ return lines.join("\n");
+}
+
+function defaultFoundationModelToolReturn(outputType: string): string {
+ if (outputType === "String") return `return ""`;
+ if (outputType === "Int") return `return 0`;
+ if (outputType === "Bool") return `return false`;
+ if (/^\[[A-Za-z_][A-Za-z0-9_]*\]$/.test(outputType)) return `return []`;
+ return `throw CancellationError()`;
+}
+
+function generateEvaluationSupport(evaluation: IREvaluationConfig): string {
+ const lines: string[] = [];
+ lines.push(`enum ${evaluation.suite} {`);
+ lines.push(` // Evaluations framework proof contract.`);
+ lines.push(
+ ` static let scenarios: [String] = [${evaluation.scenarios.map(quotedSwiftString).join(", ")}]`
+ );
+ lines.push(
+ ` static let criteria: [String] = [${evaluation.criteria.map(quotedSwiftString).join(", ")}]`
+ );
+ lines.push(
+ ` // AppIntentsTesting: pair these scenarios with Siri, Shortcuts, and Spotlight pathway tests.`
+ );
+ lines.push(`}`);
+ return lines.join("\n");
+}
+
+function generatePreviewProofSupport(previewProof: IRPreviewProofConfig): string {
+ const lines: string[] = [];
+ lines.push(`// Preview Snapshot proof matrix for ${previewProof.view}.`);
+ lines.push(
+ `// Variants: ${previewProof.variants.length ? previewProof.variants.map(escapeSwiftString).join(", ") : "default"}`
+ );
+ if (previewProof.widgetTimeline) {
+ lines.push(
+ `// Widget timeline states must be rendered in Xcode Preview Snapshot proof.`
+ );
+ }
+ if (previewProof.liveActivityStates?.length) {
+ lines.push(
+ `// Live Activity states: ${previewProof.liveActivityStates.map(escapeSwiftString).join(", ")}`
+ );
+ }
+ lines.push(
+ `// AppIntentsTesting and preview evidence should be attached before release.`
+ );
+ return lines.join("\n");
+}
+
// ─── Info.plist Fragment Generator ───────────────────────────────────
/**
diff --git a/src/core/index.ts b/src/core/index.ts
index 1836051..0fe2762 100644
--- a/src/core/index.ts
+++ b/src/core/index.ts
@@ -96,6 +96,12 @@ export type {
AppSchemaDomain,
AppIntentConformance,
EntityOwnership,
+ FoundationModelProvider,
+ FoundationModelGenerableDefinition,
+ FoundationModelToolDefinition,
+ FoundationModelDefinition,
+ EvaluationDefinition,
+ PreviewProofDefinition,
EntityDefinition,
EntityDisplay,
ViewDefinition,
diff --git a/src/core/parser.ts b/src/core/parser.ts
index a97bdc1..8a92a09 100644
--- a/src/core/parser.ts
+++ b/src/core/parser.ts
@@ -24,6 +24,12 @@ import type {
IRAppSchemaDomain,
IRIntentConformance,
IREntityOwnership,
+ IRFoundationModelConfig,
+ IRFoundationModelProvider,
+ IRFoundationModelTool,
+ IRFoundationModelGenerable,
+ IREvaluationConfig,
+ IRPreviewProofConfig,
} from "./types.js";
import { PARAM_TYPES, LEGACY_PARAM_ALIASES, isPrimitiveType } from "./types.js";
import {
@@ -39,6 +45,12 @@ import {
findAllCallExpressions,
} from "./parser-utils.js";
+const FOUNDATION_MODEL_PROVIDERS = new Set([
+ "apple-on-device",
+ "private-cloud-compute",
+ "custom-language-model",
+]);
+
function resolveEntityProperties(type: IRType, entities: IREntity[]): void {
if (type.kind === "entity") {
const match = entities.find((e) => e.name === type.entityName);
@@ -172,6 +184,13 @@ export function parseIntentSource(
const conformsTo = readStringArray(props.get("conformsTo"));
const supportedModes = readStringLiteral(props.get("supportedModes"));
const allowedExecutionTargets = readStringLiteral(props.get("allowedExecutionTargets"));
+ const model = parseFoundationModelConfig(props.get("model"), filePath, sourceFile);
+ const evaluation = parseEvaluationConfig(props.get("evaluation"), filePath, sourceFile);
+ const previewProof = parsePreviewProofConfig(
+ props.get("previewProof"),
+ filePath,
+ sourceFile
+ );
return {
name,
@@ -194,6 +213,9 @@ export function parseIntentSource(
conformsTo: conformsTo.length > 0 ? (conformsTo as IRIntentConformance[]) : undefined,
supportedModes: supportedModes || undefined,
allowedExecutionTargets: allowedExecutionTargets || undefined,
+ model,
+ evaluation,
+ previewProof,
};
}
@@ -472,6 +494,196 @@ function parseParameterSummaryDefinition(
);
}
+function parseFoundationModelConfig(
+ node: ts.Node | undefined,
+ filePath: string,
+ sourceFile: ts.SourceFile
+): IRFoundationModelConfig | undefined {
+ if (!node) return undefined;
+ if (!ts.isObjectLiteralExpression(node)) {
+ throw new ParserError(
+ "AX031",
+ "model must be an object literal",
+ filePath,
+ posOf(sourceFile, node),
+ 'Use model: { provider: "apple-on-device", instructions: "..." }.'
+ );
+ }
+
+ const props = propertyMap(node);
+ const provider = readStringLiteral(props.get("provider"));
+ if (!provider) {
+ throw new ParserError(
+ "AX032",
+ "model.provider is required",
+ filePath,
+ posOf(sourceFile, node),
+ 'Add provider: "apple-on-device", "private-cloud-compute", or "custom-language-model".'
+ );
+ }
+ if (!FOUNDATION_MODEL_PROVIDERS.has(provider)) {
+ throw new ParserError(
+ "AX042",
+ `Invalid model.provider: "${provider}"`,
+ filePath,
+ posOf(sourceFile, props.get("provider") ?? node),
+ 'Use provider: "apple-on-device", "private-cloud-compute", or "custom-language-model".'
+ );
+ }
+
+ return {
+ sessionName: readStringLiteral(props.get("sessionName")) || undefined,
+ provider: provider as IRFoundationModelProvider,
+ useCase: readStringLiteral(props.get("useCase")) || undefined,
+ instructions: readStringLiteral(props.get("instructions")) || undefined,
+ prompt: readStringLiteral(props.get("prompt")) || undefined,
+ dynamicProfile: readStringLiteral(props.get("dynamicProfile")) || undefined,
+ guardrails: readStringArray(props.get("guardrails")),
+ generable: parseFoundationModelGenerable(
+ props.get("generable"),
+ filePath,
+ sourceFile
+ ),
+ tools: parseFoundationModelTools(props.get("tools"), filePath, sourceFile),
+ };
+}
+
+function parseFoundationModelGenerable(
+ node: ts.Node | undefined,
+ filePath: string,
+ sourceFile: ts.SourceFile
+): IRFoundationModelGenerable | undefined {
+ if (!node) return undefined;
+ if (!ts.isObjectLiteralExpression(node)) {
+ throw new ParserError(
+ "AX033",
+ "model.generable must be an object literal",
+ filePath,
+ posOf(sourceFile, node)
+ );
+ }
+ const props = propertyMap(node);
+ const name = readStringLiteral(props.get("name"));
+ if (!name) {
+ throw new ParserError(
+ "AX034",
+ "model.generable.name is required",
+ filePath,
+ posOf(sourceFile, node)
+ );
+ }
+ return {
+ name,
+ fields: readStringRecord(props.get("fields")),
+ };
+}
+
+function parseFoundationModelTools(
+ node: ts.Node | undefined,
+ filePath: string,
+ sourceFile: ts.SourceFile
+): IRFoundationModelTool[] {
+ if (!node) return [];
+ if (!ts.isArrayLiteralExpression(node)) {
+ throw new ParserError(
+ "AX035",
+ "model.tools must be an array",
+ filePath,
+ posOf(sourceFile, node)
+ );
+ }
+ return node.elements.map((element) => {
+ if (!ts.isObjectLiteralExpression(element)) {
+ throw new ParserError(
+ "AX036",
+ "model.tools entries must be object literals",
+ filePath,
+ posOf(sourceFile, element)
+ );
+ }
+ const props = propertyMap(element);
+ const name = readStringLiteral(props.get("name"));
+ const description = readStringLiteral(props.get("description"));
+ if (!name || !description) {
+ throw new ParserError(
+ "AX037",
+ "model.tools entries require name and description",
+ filePath,
+ posOf(sourceFile, element)
+ );
+ }
+ return {
+ name,
+ description,
+ argumentsType: readStringLiteral(props.get("argumentsType")) || undefined,
+ outputType: readStringLiteral(props.get("outputType")) || undefined,
+ };
+ });
+}
+
+function parseEvaluationConfig(
+ node: ts.Node | undefined,
+ filePath: string,
+ sourceFile: ts.SourceFile
+): IREvaluationConfig | undefined {
+ if (!node) return undefined;
+ if (!ts.isObjectLiteralExpression(node)) {
+ throw new ParserError(
+ "AX038",
+ "evaluation must be an object literal",
+ filePath,
+ posOf(sourceFile, node)
+ );
+ }
+ const props = propertyMap(node);
+ const suite = readStringLiteral(props.get("suite"));
+ if (!suite) {
+ throw new ParserError(
+ "AX039",
+ "evaluation.suite is required",
+ filePath,
+ posOf(sourceFile, node)
+ );
+ }
+ return {
+ suite,
+ scenarios: readStringArray(props.get("scenarios")),
+ criteria: readStringArray(props.get("criteria")),
+ };
+}
+
+function parsePreviewProofConfig(
+ node: ts.Node | undefined,
+ filePath: string,
+ sourceFile: ts.SourceFile
+): IRPreviewProofConfig | undefined {
+ if (!node) return undefined;
+ if (!ts.isObjectLiteralExpression(node)) {
+ throw new ParserError(
+ "AX040",
+ "previewProof must be an object literal",
+ filePath,
+ posOf(sourceFile, node)
+ );
+ }
+ const props = propertyMap(node);
+ const view = readStringLiteral(props.get("view"));
+ if (!view) {
+ throw new ParserError(
+ "AX041",
+ "previewProof.view is required",
+ filePath,
+ posOf(sourceFile, node)
+ );
+ }
+ return {
+ view,
+ variants: readStringArray(props.get("variants")),
+ widgetTimeline: readBooleanLiteral(props.get("widgetTimeline")),
+ liveActivityStates: readStringArray(props.get("liveActivityStates")),
+ };
+}
+
// ─── Parameter Extraction ────────────────────────────────────────────
function extractParameters(
diff --git a/src/core/types.ts b/src/core/types.ts
index cf9f946..b7039c1 100644
--- a/src/core/types.ts
+++ b/src/core/types.ts
@@ -96,6 +96,48 @@ export type IRIntentConformance =
export type IREntityOwnership = "unknown" | "shared" | "public";
+export type IRFoundationModelProvider =
+ | "apple-on-device"
+ | "private-cloud-compute"
+ | "custom-language-model";
+
+export interface IRFoundationModelGenerable {
+ name: string;
+ fields: Record;
+}
+
+export interface IRFoundationModelTool {
+ name: string;
+ description: string;
+ argumentsType?: string;
+ outputType?: string;
+}
+
+export interface IRFoundationModelConfig {
+ sessionName?: string;
+ provider: IRFoundationModelProvider;
+ useCase?: string;
+ instructions?: string;
+ prompt?: string;
+ dynamicProfile?: string;
+ guardrails?: string[];
+ generable?: IRFoundationModelGenerable;
+ tools?: IRFoundationModelTool[];
+}
+
+export interface IREvaluationConfig {
+ suite: string;
+ scenarios: string[];
+ criteria: string[];
+}
+
+export interface IRPreviewProofConfig {
+ view: string;
+ variants: string[];
+ widgetTimeline?: boolean;
+ liveActivityStates?: string[];
+}
+
/**
* An App Entity definition for complex, domain-specific data types.
* Entities can be queried and used as parameter types in intents.
@@ -237,6 +279,12 @@ export interface IRIntent {
supportedModes?: string;
/** Swift expression for `allowedExecutionTargets`, e.g. `.main`. */
allowedExecutionTargets?: string;
+ /** Foundation Models generation contract for Apple Intelligence intents. */
+ model?: IRFoundationModelConfig;
+ /** Evaluation suite metadata that should accompany model-backed output. */
+ evaluation?: IREvaluationConfig;
+ /** Preview snapshot matrix required to prove generated UI variants. */
+ previewProof?: IRPreviewProofConfig;
}
// ─── Widget IR Types ────────────────────────────────────────────────────────
diff --git a/src/mcp/manifest.ts b/src/mcp/manifest.ts
index 777c140..588bcdd 100644
--- a/src/mcp/manifest.ts
+++ b/src/mcp/manifest.ts
@@ -2206,7 +2206,7 @@ export const TOOL_MANIFEST = [
{
name: "axint.templates.list",
description:
- "List all 26 bundled reference templates in the Axint SDK. Returns " +
+ "List all 39 bundled reference templates in the Axint SDK. Returns " +
"a JSON array of { id, name, description } objects — one per template. " +
"Templates cover messaging, productivity, health, finance, commerce, " +
"media, navigation, smart-home, and entity/query patterns. No input " +
diff --git a/src/sdk/index.ts b/src/sdk/index.ts
index d959d65..fdf96aa 100644
--- a/src/sdk/index.ts
+++ b/src/sdk/index.ts
@@ -83,6 +83,48 @@ export type AppIntentConformance =
export type EntityOwnership = "unknown" | "shared" | "public";
+export type FoundationModelProvider =
+ | "apple-on-device"
+ | "private-cloud-compute"
+ | "custom-language-model";
+
+export interface FoundationModelGenerableDefinition {
+ name: string;
+ fields: Record;
+}
+
+export interface FoundationModelToolDefinition {
+ name: string;
+ description: string;
+ argumentsType?: string;
+ outputType?: string;
+}
+
+export interface FoundationModelDefinition {
+ sessionName?: string;
+ provider: FoundationModelProvider;
+ useCase?: string;
+ instructions?: string;
+ prompt?: string;
+ dynamicProfile?: string;
+ guardrails?: string[];
+ generable?: FoundationModelGenerableDefinition;
+ tools?: FoundationModelToolDefinition[];
+}
+
+export interface EvaluationDefinition {
+ suite: string;
+ scenarios: string[];
+ criteria: string[];
+}
+
+export interface PreviewProofDefinition {
+ view: string;
+ variants: string[];
+ widgetTimeline?: boolean;
+ liveActivityStates?: string[];
+}
+
/** Configuration for a single parameter. */
export interface ParamConfig {
/** Display name for this parameter (auto-generated from field name if omitted). */
@@ -297,6 +339,12 @@ export interface IntentDefinition<
supportedModes?: string;
/** Swift expression emitted as `static var allowedExecutionTargets`. */
allowedExecutionTargets?: string;
+ /** Foundation Models session/tool/guided-generation contract. */
+ model?: FoundationModelDefinition;
+ /** Evaluation suite that proves model behavior across scenarios. */
+ evaluation?: EvaluationDefinition;
+ /** Preview Snapshot proof matrix for generated UI variants. */
+ previewProof?: PreviewProofDefinition;
}
/**
diff --git a/src/templates/index.ts b/src/templates/index.ts
index a01ef3b..7070144 100644
--- a/src/templates/index.ts
+++ b/src/templates/index.ts
@@ -1086,6 +1086,174 @@ export default defineIntent({
`,
};
+const appIntentsTestingHarness: IntentTemplate = {
+ id: "appintents-testing-harness",
+ name: "appintents-testing-harness",
+ title: "AppIntentsTesting Harness",
+ domain: "apple-intelligence",
+ category: "testing",
+ description:
+ "Scaffold a schema-backed intent with an evaluation contract for Siri, Shortcuts, and Spotlight proof.",
+ source: `import { defineIntent, param } from "@axint/compiler";
+
+export default defineIntent({
+ name: "VerifyReminderIntentPath",
+ title: "Verify Reminder Intent Path",
+ description: "Exercises a schema-backed App Intent through user-facing system paths.",
+ schemaDomain: "reminders",
+ schema: "AppSchema.RemindersIntent.createReminder",
+ params: {
+ title: param.string("Reminder title"),
+ dueDate: param.date("Due date", { required: false }),
+ },
+ evaluation: {
+ suite: "ReminderIntentPathEvaluations",
+ scenarios: ["siri-request", "shortcuts-run", "spotlight-suggestion"],
+ criteria: ["intent resolves", "parameters bind", "result is visible"],
+ },
+ perform: async ({ title }) => {
+ // Swift proof hint:
+ // Add AppIntentsTesting coverage for Siri, Shortcuts, and Spotlight before release.
+ return { title };
+ },
+});
+`,
+};
+
+const visualIntelligenceRouter: IntentTemplate = {
+ id: "visual-intelligence-router",
+ name: "visual-intelligence-router",
+ title: "Visual Intelligence Router",
+ domain: "apple-intelligence",
+ category: "visual-intelligence",
+ description:
+ "Scaffold an intent that maps a visual result into app search or object-specific actions.",
+ source: `import { defineIntent, param } from "@axint/compiler";
+
+export default defineIntent({
+ name: "RouteVisualResult",
+ title: "Route Visual Result",
+ description: "Routes a Visual Intelligence result into the right app workflow.",
+ schemaDomain: "visual-intelligence",
+ params: {
+ objectLabel: param.string("Detected object label"),
+ sourceContext: param.string("Screenshot, camera, or scene context", {
+ required: false,
+ }),
+ },
+ previewProof: {
+ view: "VisualResultRouteView",
+ variants: ["light", "dark", "landscape"],
+ },
+ perform: async ({ objectLabel }) => {
+ // Swift proof hint:
+ // Attach screenshot fixtures and Xcode 27 evidence that detected objects map correctly.
+ return { routedObject: objectLabel };
+ },
+});
+`,
+};
+
+const imagePlaygroundIntent: IntentTemplate = {
+ id: "image-playground-intent",
+ name: "image-playground-intent",
+ title: "Image Playground Intent",
+ domain: "apple-intelligence",
+ category: "image-playground",
+ description:
+ "Scaffold an intent for generating an image artifact with style, safety, and proof metadata.",
+ source: `import { defineIntent, param } from "@axint/compiler";
+
+export default defineIntent({
+ name: "GenerateCampaignImage",
+ title: "Generate Campaign Image",
+ description: "Creates a generated image with an Image Playground handoff.",
+ schemaDomain: "assistant",
+ params: {
+ prompt: param.string("Image prompt"),
+ style: param.string("Requested visual style", { required: false }),
+ audience: param.string("Audience or campaign context", { required: false }),
+ },
+ evaluation: {
+ suite: "CampaignImageEvaluations",
+ scenarios: ["safe-prompt", "style-match", "empty-context"],
+ criteria: ["artifact returned", "style respected", "safety constraints held"],
+ },
+ perform: async ({ prompt }) => {
+ // Swift proof hint:
+ // Attach generated-image evidence before calling this demo-ready.
+ return { prompt, artifact: "Replace with generated image handle" };
+ },
+});
+`,
+};
+
+const stringCatalogLocalizer: IntentTemplate = {
+ id: "string-catalog-localizer",
+ name: "string-catalog-localizer",
+ title: "String Catalog Localizer",
+ domain: "productivity",
+ category: "localization",
+ description:
+ "Scaffold a workflow for generating and proving String Catalog localization updates.",
+ source: `import { defineIntent, param } from "@axint/compiler";
+
+export default defineIntent({
+ name: "LocalizeStringCatalog",
+ title: "Localize String Catalog",
+ description: "Updates Localizable.xcstrings with reviewed generated translations.",
+ domain: "localization",
+ conformsTo: ["LongRunningIntent", "ProgressReportingIntent"],
+ supportedModes: "[.foreground, .background]",
+ params: {
+ catalogPath: param.string("Path to Localizable.xcstrings"),
+ locale: param.string("Target locale identifier"),
+ reviewMode: param.string("Review mode, such as draft or approved", {
+ default: "draft",
+ }),
+ },
+ perform: async ({ catalogPath, locale }) => {
+ // Swift proof hint:
+ // Attach the updated .xcstrings artifact and locale coverage evidence.
+ return { catalogPath, locale };
+ },
+});
+`,
+};
+
+const resizableLayoutProof: IntentTemplate = {
+ id: "resizable-layout-proof",
+ name: "resizable-layout-proof",
+ title: "Resizable Layout Proof",
+ domain: "developer-tools",
+ category: "preview-proof",
+ description:
+ "Scaffold a proof intent that tracks adaptive SwiftUI layout snapshots across iOS sizes.",
+ source: `import { defineIntent, param } from "@axint/compiler";
+
+export default defineIntent({
+ name: "VerifyResizableLayout",
+ title: "Verify Resizable Layout",
+ description: "Records Preview Snapshot proof for adaptive iOS SwiftUI layouts.",
+ domain: "developer-tools",
+ params: {
+ viewName: param.string("SwiftUI view name"),
+ targetSize: param.string("Target size class or preview variant"),
+ dynamicType: param.string("Dynamic Type size", { required: false }),
+ },
+ previewProof: {
+ view: "ResizableLayoutPreview",
+ variants: ["compact", "regular", "landscape", "accessibilityExtraLarge"],
+ },
+ perform: async ({ viewName, targetSize }) => {
+ // Swift proof hint:
+ // Attach Preview Snapshot baselines instead of relying on fixed device-sized frames.
+ return { viewName, targetSize };
+ },
+});
+`,
+};
+
// ─── Registry ────────────────────────────────────────────────────────
export const TEMPLATES: IntentTemplate[] = [
@@ -1123,6 +1291,11 @@ export const TEMPLATES: IntentTemplate[] = [
systemShortcutBridge,
entityCollectionSearch,
unionValueRouter,
+ appIntentsTestingHarness,
+ visualIntelligenceRouter,
+ imagePlaygroundIntent,
+ stringCatalogLocalizer,
+ resizableLayoutProof,
];
/** @deprecated Use TEMPLATES. Kept for v0.1.x import compatibility. */
diff --git a/tests/cloud/check.test.ts b/tests/cloud/check.test.ts
index 3174c80..51114d1 100644
--- a/tests/cloud/check.test.ts
+++ b/tests/cloud/check.test.ts
@@ -122,6 +122,60 @@ struct SendMessageIntent: AppIntent {
expect(report.status).toBe("needs_review");
});
+ it("asks schema-backed App Intents for Xcode 27 and AppIntentsTesting proof", () => {
+ const report = runCloudCheck({
+ fileName: "CreateReminderIntent.swift",
+ source: `
+import AppIntents
+
+@AppIntent(schema: AppSchema.RemindersIntent.createReminder)
+struct CreateReminderIntent: AppIntent {
+ static var title: LocalizedStringResource = "Create Reminder"
+ static var description: IntentDescription = "Create a reminder"
+ func perform() async throws -> some IntentResult { .result() }
+}
+`,
+ });
+
+ const codes = report.diagnostics.map((d) => d.code);
+ expect(codes).toContain("AXCLOUD-WWDC26-XCODE27-PROOF");
+ expect(codes).toContain("AXCLOUD-WWDC26-APPINTENTS-TESTING");
+ expect(report.checks).toContainEqual(
+ expect.objectContaining({
+ label: "Xcode 27 readiness",
+ state: "warn",
+ })
+ );
+ expect(report.status).toBe("needs_review");
+ });
+
+ it("accepts Xcode 27 AppIntentsTesting evidence for schema-backed intents", () => {
+ const report = runCloudCheck({
+ fileName: "CreateReminderIntent.swift",
+ source: `
+import AppIntents
+
+@AppIntent(schema: AppSchema.RemindersIntent.createReminder)
+struct CreateReminderIntent: AppIntent {
+ static var title: LocalizedStringResource = "Create Reminder"
+ static var description: IntentDescription = "Create a reminder"
+ func perform() async throws -> some IntentResult { .result() }
+}
+`,
+ xcodeBuildLog: [
+ "Xcode 27.0",
+ "AppIntentsTesting passed CreateReminderIntent through Siri, Shortcuts, and Spotlight pathways.",
+ "** TEST SUCCEEDED **",
+ "Executed 1 test, with 0 failures",
+ ].join("\n"),
+ });
+
+ const codes = report.diagnostics.map((d) => d.code);
+ expect(codes).not.toContain("AXCLOUD-WWDC26-XCODE27-PROOF");
+ expect(codes).not.toContain("AXCLOUD-WWDC26-APPINTENTS-TESTING");
+ expect(report.status).toBe("pass");
+ });
+
it("asks Foundation Models code for model-version proof", () => {
const report = runCloudCheck({
fileName: "ModelSummary.swift",
@@ -144,6 +198,128 @@ struct SummarizeIntent: AppIntent {
expect(report.status).toBe("needs_review");
});
+ it("asks evaluation suites for scenario proof", () => {
+ const report = runCloudCheck({
+ fileName: "MessageSummaryEvaluations.swift",
+ source: `
+import AppIntents
+
+enum MessageSummaryEvaluations {
+ static let scenarios: [String] = ["short-thread", "long-thread"]
+ static let criteria: [String] = ["preserves sender intent"]
+}
+`,
+ });
+
+ expect(report.diagnostics.map((d) => d.code)).toContain(
+ "AXCLOUD-WWDC26-EVALUATION-PROOF"
+ );
+ expect(report.status).toBe("needs_review");
+ });
+
+ it("asks preview snapshot matrices for attached snapshot proof", () => {
+ const report = runCloudCheck({
+ fileName: "MessageSummaryPreviewProof.swift",
+ source: `
+import SwiftUI
+
+// Preview Snapshot proof matrix for MessageSummaryView.
+// Variants: light, dark, landscape, accessibilityExtraLarge
+struct MessageSummaryView: View {
+ var body: some View { Text("Summary") }
+}
+`,
+ });
+
+ expect(report.diagnostics.map((d) => d.code)).toContain(
+ "AXCLOUD-WWDC26-PREVIEW-SNAPSHOT-PROOF"
+ );
+ expect(report.status).toBe("needs_review");
+ });
+
+ it("asks Visual Intelligence routers for screenshot/object proof", () => {
+ const report = runCloudCheck({
+ fileName: "VisualIntelligenceRouter.swift",
+ source: `
+import AppIntents
+import VisionKit
+
+struct VisualIntelligenceRouterIntent: AppIntent {
+ static var title: LocalizedStringResource = "Route Visual Result"
+ static var description: IntentDescription = "Routes a Visual Intelligence result into app search."
+ func perform() async throws -> some IntentResult { .result() }
+}
+`,
+ });
+
+ expect(report.diagnostics.map((d) => d.code)).toContain(
+ "AXCLOUD-WWDC26-VISUAL-INTELLIGENCE-PROOF"
+ );
+ expect(report.status).toBe("needs_review");
+ });
+
+ it("asks Image Playground flows for generated-image proof", () => {
+ const report = runCloudCheck({
+ fileName: "ImagePlaygroundIntent.swift",
+ source: `
+import AppIntents
+import ImagePlayground
+
+struct GenerateCampaignImageIntent: AppIntent {
+ static var title: LocalizedStringResource = "Generate Campaign Image"
+ static var description: IntentDescription = "Creates a generated image in Image Playground."
+ func perform() async throws -> some IntentResult { .result() }
+}
+`,
+ });
+
+ expect(report.diagnostics.map((d) => d.code)).toContain(
+ "AXCLOUD-WWDC26-IMAGE-PLAYGROUND-PROOF"
+ );
+ expect(report.status).toBe("needs_review");
+ });
+
+ it("asks String Catalog workflows for localization proof", () => {
+ const report = runCloudCheck({
+ fileName: "StringCatalogLocalizer.swift",
+ source: `
+import AppIntents
+
+struct LocalizeStringCatalogIntent: AppIntent {
+ static var title: LocalizedStringResource = "Localize String Catalog"
+ static var description: IntentDescription = "Updates Localizable.xcstrings with generated translations."
+ func perform() async throws -> some IntentResult { .result() }
+}
+`,
+ });
+
+ expect(report.diagnostics.map((d) => d.code)).toContain(
+ "AXCLOUD-WWDC26-STRING-CATALOG-PROOF"
+ );
+ expect(report.status).toBe("needs_review");
+ });
+
+ it("asks fixed-size SwiftUI layouts for resizable iOS proof", () => {
+ const report = runCloudCheck({
+ fileName: "CampaignDashboardView.swift",
+ source: `
+import SwiftUI
+
+struct CampaignDashboardView: View {
+ var body: some View {
+ Text("Campaign")
+ .frame(width: 393, height: 852)
+ }
+}
+`,
+ });
+
+ expect(report.diagnostics.map((d) => d.code)).toContain(
+ "AXCLOUD-WWDC26-RESIZABLE-IOS-LAYOUT"
+ );
+ expect(report.status).toBe("needs_review");
+ });
+
it("asks long-running progress intents for background and progress proof", () => {
const report = runCloudCheck({
fileName: "ResearchBriefIntent.swift",
diff --git a/tests/core/compiler.test.ts b/tests/core/compiler.test.ts
index 3daab3d..f78181e 100644
--- a/tests/core/compiler.test.ts
+++ b/tests/core/compiler.test.ts
@@ -248,4 +248,75 @@ export default defineIntent({
expect(result.output?.swiftCode).toContain("var messages: [Message]");
expect(result.output?.swiftCode).toContain("var tags: [String]?");
});
+
+ it("emits Foundation Models, Evaluations, and preview proof support", () => {
+ const source = `
+import { defineIntent, param } from "@axint/sdk";
+
+export default defineIntent({
+ name: "SummarizeWithModel",
+ title: "Summarize With Model",
+ description: "Summarizes selected text with Apple Intelligence proof.",
+ schemaDomain: "assistant",
+ schema: "AppSchema.AssistantIntent.summarize",
+ params: {
+ sourceText: param.string("Text to summarize"),
+ },
+ model: {
+ sessionName: "MessageSummarySession",
+ provider: "apple-on-device",
+ useCase: "summarization",
+ instructions: "Summarize the input for a busy reader.",
+ prompt: "Summarize the selected text.",
+ dynamicProfile: "MessageSummaryProfile",
+ guardrails: ["sensitive-content", "locale-aware"],
+ generable: {
+ name: "MessageSummary",
+ fields: {
+ summary: "String",
+ actionItems: "[String]",
+ },
+ },
+ tools: [
+ {
+ name: "MessageSearchTool",
+ description: "Searches local messages for cited context.",
+ argumentsType: "MessageSearchArguments",
+ outputType: "[Message]",
+ },
+ ],
+ },
+ evaluation: {
+ suite: "MessageSummaryEvaluations",
+ scenarios: ["short-thread", "long-thread"],
+ criteria: ["preserves sender intent", "returns action items"],
+ },
+ previewProof: {
+ view: "MessageSummaryView",
+ variants: ["light", "dark", "landscape", "accessibilityExtraLarge"],
+ widgetTimeline: true,
+ liveActivityStates: ["queued", "complete"],
+ },
+ perform: async ({ sourceText }) => {
+ return { summary: sourceText };
+ },
+});
+`;
+ const result = compileSource(source, "model-proof.ts");
+
+ expect(result.success).toBe(true);
+ expect(result.output?.ir.model?.provider).toBe("apple-on-device");
+ expect(result.output?.ir.evaluation?.suite).toBe("MessageSummaryEvaluations");
+ expect(result.output?.ir.previewProof?.view).toBe("MessageSummaryView");
+ expect(result.output?.swiftCode).toContain("import FoundationModels");
+ expect(result.output?.swiftCode).toContain("@Generable");
+ expect(result.output?.swiftCode).toContain("struct MessageSummary: Generable");
+ expect(result.output?.swiftCode).toContain("struct MessageSearchTool: Tool");
+ expect(result.output?.swiftCode).toContain("enum MessageSummarySessionFactory");
+ expect(result.output?.swiftCode).toContain("LanguageModelSession");
+ expect(result.output?.swiftCode).toContain("Dynamic Profile: MessageSummaryProfile");
+ expect(result.output?.swiftCode).toContain("enum MessageSummaryEvaluations");
+ expect(result.output?.swiftCode).toContain("AppIntentsTesting");
+ expect(result.output?.swiftCode).toContain("Preview Snapshot proof matrix");
+ });
});
diff --git a/tests/core/parser.test.ts b/tests/core/parser.test.ts
index 2f041b2..f75bb06 100644
--- a/tests/core/parser.test.ts
+++ b/tests/core/parser.test.ts
@@ -107,6 +107,24 @@ defineIntent({
expect(() => parseIntentSource(source, "badtype.ts")).toThrow(ParserError);
});
+ it("throws ParserError for unsupported Foundation Model providers", () => {
+ const source = `
+defineIntent({
+ name: "ModelIntent",
+ title: "Model Intent",
+ description: "Uses a model",
+ params: {},
+ model: {
+ provider: "unsupported-provider",
+ },
+ perform: async () => {},
+});
+`;
+ expect(() => parseIntentSource(source, "bad-model-provider.ts")).toThrow(
+ /model.provider/
+ );
+ });
+
it("ParserError formats correctly", () => {
const err = new ParserError(
"AX001",
diff --git a/tests/extensions/xcode-agent-plugin.test.ts b/tests/extensions/xcode-agent-plugin.test.ts
new file mode 100644
index 0000000..5ea764a
--- /dev/null
+++ b/tests/extensions/xcode-agent-plugin.test.ts
@@ -0,0 +1,43 @@
+import { readFileSync } from "node:fs";
+import { join } from "node:path";
+import { describe, expect, it } from "vitest";
+
+const ROOT = process.cwd();
+
+describe("Xcode agent plugin package", () => {
+ it("declares Axint as an Xcode 27 agent plugin with MCP tools and skills", () => {
+ const manifestPath = join(ROOT, "extensions", "xcode", "agent-plugin", "plugin.json");
+ const manifest = JSON.parse(readFileSync(manifestPath, "utf-8")) as {
+ name: string;
+ version: string;
+ mcpServers?: Record<
+ string,
+ {
+ type: string;
+ command?: string;
+ args?: string[];
+ _meta?: {
+ ideToolIconPath?: string;
+ ideToolTitles?: Record;
+ };
+ }
+ >;
+ skills?: Array<{ name: string; path: string }>;
+ };
+
+ expect(manifest.name).toBe("Axint");
+ expect(manifest.version).toBe("0.4.30");
+ expect(manifest.mcpServers?.axint).toMatchObject({
+ type: "stdio",
+ command: "npx",
+ args: ["-y", "-p", "@axint/compiler", "axint-mcp"],
+ });
+ expect(manifest.mcpServers?.axint?._meta?.ideToolTitles).toMatchObject({
+ "axint.cloud.check": "Apple Readiness Check",
+ "axint.xcode.guard": "Axint Guard",
+ });
+ expect(manifest.skills?.map((skill) => skill.name)).toContain(
+ "apple-intelligence-proof"
+ );
+ });
+});
diff --git a/tests/templates/index.test.ts b/tests/templates/index.test.ts
index 1c17f56..3b21a4e 100644
--- a/tests/templates/index.test.ts
+++ b/tests/templates/index.test.ts
@@ -5,6 +5,7 @@ import {
templates,
TEMPLATES,
} from "../../src/templates/index.js";
+import { compileSource } from "../../src/core/compiler.js";
describe("templates registry", () => {
it("TEMPLATES contains the bundled reference set", () => {
@@ -51,4 +52,23 @@ describe("templates registry", () => {
expect(msgs.length).toBeGreaterThan(0);
expect(msgs.every((t) => t.category === "messaging")).toBe(true);
});
+
+ it("ships WWDC26 proof templates that compile", () => {
+ const ids = [
+ "appintents-testing-harness",
+ "visual-intelligence-router",
+ "image-playground-intent",
+ "string-catalog-localizer",
+ "resizable-layout-proof",
+ ];
+
+ for (const id of ids) {
+ const template = getTemplate(id);
+ expect(template, id).toBeDefined();
+
+ const result = compileSource(template!.source, `${id}.ts`);
+ expect(result.success, id).toBe(true);
+ expect(result.output?.swiftCode, id).toContain("struct");
+ }
+ });
});