Skip to content

Commit 21bd3dd

Browse files
os-zhuangclaude
andauthored
chore(spec): metadata-liveness P2 follow-through — mark aspirational props experimental + declare renderer-read props (#1878) (#3223)
* chore(spec): mark aspirational props experimental + declare renderer-read props (#1878) Metadata-liveness audit follow-through (umbrella #1878). Resolves the unambiguous framework-spec portions of the open P2 sub-issues. #1893 (aspirational config — prune or mark experimental): add [EXPERIMENTAL — not enforced] markers to properties that parse but have no runtime consumer, so authors are not misled (ADR-0049): - object enable.trash / enable.mru (ledger dead -> experimental) - job retryPolicy / timeout - theme spacing / breakpoints / rtl / density / touchTarget - translation messageFormat:'icu' / cache - webhook authentication (non-HMAC bearer/basic/api-key) - PortalSchema (entire — not registered, no route/renderer) #1891 / #1894 (naming drift + inverse drift — app cluster): declare the props the objectui renderers already read so a strict Schema.parse() holds: - app branding accentColor (ConsoleLayout) - nav item badgeVariant (NavigationRenderer) - nav item `separator` type (AppContent nav divider) - agent knowledge.sources as the canonical key, topics kept as deprecated alias Regenerated reference docs (content/docs/references) to match. All spec gates green: check:liveness, check:docs, check:spec-changes; full spec suite 6763 passing. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LddW4NaQBdf5FTEnBPpnUJ * fix(spec): keep object enable.trash/mru dead, not experimental (CI: author-lint) The author-side liveness lint (lintLivenessProperties, #1966) auto-warns on every `experimental` prop. enable.trash / enable.mru default to `true`, and the lint cannot distinguish an authored `true` from the schema default — so tagging them experimental warned on the default value of every object, tripping the "does NOT warn on a default-on flag left alone (enable.trash)" contract test in Test Core. Revert those two to `dead` (their audit classification) with a ledger note explaining why; drop the [EXPERIMENTAL] marker from their spec .describe(). Their #1893 disposition (prune-or-build) stays tracked in the sub-issue. All other #1893 experimental markers are on ungoverned types the lint never loads, so they are unaffected. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LddW4NaQBdf5FTEnBPpnUJ * docs(spec): mark ToolSchema as a read-only projection, not an execution entry point (#1892) #1892 tool disposition (ADR-0049 line): the ledger already documents that tool metadata is a one-way, write-only projection (no executor loads a metadata-authored tool; the runtime uses a separate AIToolDefinition in cloud service-ai). Surface that on the SPEC itself so an author/AI reading the Zod schema — not just the ledger — knows a hand-authored tool will not run in the open edition. Non-breaking describe-only change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LddW4NaQBdf5FTEnBPpnUJ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 5d62496 commit 21bd3dd

19 files changed

Lines changed: 90 additions & 34 deletions

File tree

content/docs/references/ai/agent.mdx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ const result = AIKnowledge.parse(data);
2929

3030
| Property | Type | Required | Description |
3131
| :--- | :--- | :--- | :--- |
32-
| **topics** | `string[]` || Topics/Tags to recruit knowledge from |
32+
| **sources** | `string[]` | optional | Knowledge sources/tags to recruit RAG context from. Canonical key consumed by the agent renderer (objectui AgentPreview KnowledgeSummary). |
33+
| **topics** | `string[]` | optional | Deprecated alias for `sources` (spec key ≠ consumed key drift, liveness audit #1878/#1891). Prefer `sources`; `topics` is retained for back-compat but the renderer reads `sources`. |
3334
| **indexes** | `string[]` || Vector Store Indexes |
3435

3536

@@ -79,7 +80,7 @@ const result = AIKnowledge.parse(data);
7980
| **surface** | `Enum<'ask' \| 'build'>` || Product surface this agent binds ('ask' \| 'build') — ADR-0063 §1 |
8081
| **skills** | `string[]` | optional | Skill names to attach (Agent→Skill→Tool architecture) |
8182
| **tools** | `{ type: Enum<'action' \| 'flow' \| 'query' \| 'vector_search'>; name: string; description?: string }[]` | optional | Direct tool references (legacy fallback) |
82-
| **knowledge** | `{ topics: string[]; indexes: string[] }` | optional | RAG access |
83+
| **knowledge** | `{ sources?: string[]; topics?: string[]; indexes: string[] }` | optional | RAG access |
8384
| **active** | `boolean` || |
8485
| **access** | `string[]` | optional | Who can chat with this agent |
8586
| **permissions** | `string[]` | optional | Required permission-set capabilities |

content/docs/references/ai/tool.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ const result = Tool.parse(data);
2727

2828
## Tool
2929

30+
AI tool definition. [READ-ONLY PROJECTION — not an execution entry point] Authoring a tool as metadata does NOT make it runnable: this schema has no `implementation`/`handler` field and no framework executor loads a metadata-authored tool. The runtime executes a separately-registered `AIToolDefinition` (cloud `@objectstack/service-ai`); tool metadata is a one-way projection for Studio/discovery. Do not expect a hand-authored tool to run in the open edition (liveness audit #1878/#1892).
31+
3032
### Properties
3133

3234
| Property | Type | Required | Description |

content/docs/references/automation/webhook.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ const result = Webhook.parse(data);
7171
| **body** | `any` | optional | Request body payload (if not using default record data) |
7272
| **payloadFields** | `string[]` | optional | Fields to include. Empty = All |
7373
| **includeSession** | `boolean` || Include user session info |
74-
| **authentication** | `{ type: Enum<'none' \| 'bearer' \| 'basic' \| 'api-key'>; credentials?: Record<string, string> }` | optional | Authentication configuration |
74+
| **authentication** | `{ type: Enum<'none' \| 'bearer' \| 'basic' \| 'api-key'>; credentials?: Record<string, string> }` | optional | Authentication configuration. [EXPERIMENTAL — not enforced] The webhook delivery path only applies HMAC signing via `secret`; bearer/basic/api-key credentials are not attached to outbound requests yet (liveness audit #1878/#1893). |
7575
| **retryPolicy** | `{ maxRetries: integer; backoffStrategy: Enum<'exponential' \| 'linear' \| 'fixed'>; initialDelayMs: integer; maxDelayMs: integer }` | optional | Retry policy configuration |
7676
| **timeoutMs** | `integer` || Request timeout in milliseconds |
7777
| **secret** | `string` | optional | Signing secret for HMAC signature verification |

content/docs/references/integration/connector.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ Synchronization strategy
473473
| **body** | `any` | optional | Request body payload (if not using default record data) |
474474
| **payloadFields** | `string[]` | optional | Fields to include. Empty = All |
475475
| **includeSession** | `boolean` || Include user session info |
476-
| **authentication** | `{ type: Enum<'none' \| 'bearer' \| 'basic' \| 'api-key'>; credentials?: Record<string, string> }` | optional | Authentication configuration |
476+
| **authentication** | `{ type: Enum<'none' \| 'bearer' \| 'basic' \| 'api-key'>; credentials?: Record<string, string> }` | optional | Authentication configuration. [EXPERIMENTAL — not enforced] The webhook delivery path only applies HMAC signing via `secret`; bearer/basic/api-key credentials are not attached to outbound requests yet (liveness audit #1878/#1893). |
477477
| **retryPolicy** | `{ maxRetries: integer; backoffStrategy: Enum<'exponential' \| 'linear' \| 'fixed'>; initialDelayMs: integer; maxDelayMs: integer }` | optional | Retry policy configuration |
478478
| **timeoutMs** | `integer` || Request timeout in milliseconds |
479479
| **secret** | `string` | optional | Signing secret for HMAC signature verification |

content/docs/references/kernel/manifest.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ const result = Manifest.parse(data);
6464
| **data** | `{ object: string; externalId?: string; mode?: Enum<'insert' \| 'update' \| 'upsert' \| 'replace' \| 'ignore'>; env?: Enum<'prod' \| 'dev' \| 'test'>[]; … }[]` | optional | Initial seed data (prefer top-level data field) |
6565
| **capabilities** | `{ implements?: { protocol: object; conformance?: Enum<'full' \| 'partial' \| 'experimental' \| 'deprecated'>; implementedFeatures?: string[]; features?: { name: string; enabled?: boolean; description?: string; sinceVersion?: string; … }[]; … }[]; provides?: { id: string; name: string; description?: string; version: object; … }[]; requires?: { pluginId: string; version: string; optional?: boolean; reason?: string; … }[]; extensionPoints?: { id: string; name: string; description?: string; type: Enum<'action' \| 'hook' \| 'widget' \| 'provider' \| 'transformer' \| 'validator' \| 'decorator'>; … }[]; … }` | optional | Plugin capability declarations for interoperability |
6666
| **extensions** | `Record<string, any>` | optional | Extension points and contributions |
67-
| **navigationContributions** | `{ app: string; group?: string; priority?: integer; items: { id: string; label: string; icon?: string; order?: number; … } \| { id: string; label: string; icon?: string; order?: number; … } \| { id: string; label: string; icon?: string; order?: number; … } \| { id: string; label: string; icon?: string; order?: number; … } \| { id: string; label: string; icon?: string; order?: number; … } \| { id: string; label: string; icon?: string; order?: number; … } \| { id: string; label: string; icon?: string; order?: number; … } \| { id: string; label: string; icon?: string; order?: number; … }[] }[]` | optional | Navigation items this package contributes into apps owned by other packages |
67+
| **navigationContributions** | `{ app: string; group?: string; priority?: integer; items: { id: string; label: string; icon?: string; order?: number; … } \| { id: string; label: string; icon?: string; order?: number; … } \| { id: string; label: string; icon?: string; order?: number; … } \| { id: string; label: string; icon?: string; order?: number; … } \| { id: string; label: string; icon?: string; order?: number; … } \| { id: string; label: string; icon?: string; order?: number; … } \| { id: string; label: string; icon?: string; order?: number; … } \| { type: 'separator'; id?: string; order?: number } \| { id: string; label: string; icon?: string; order?: number; … }[] }[]` | optional | Navigation items this package contributes into apps owned by other packages |
6868
| **loading** | `{ strategy?: Enum<'eager' \| 'lazy' \| 'parallel' \| 'deferred' \| 'on-demand'>; preload?: object; codeSplitting?: object; dynamicImport?: object; … }` | optional | Plugin loading and runtime behavior configuration |
6969
| **engine** | `{ objectstack: string }` | optional | Platform compatibility requirements (legacy; superseded by `engines`) |
7070
| **engines** | `{ platform?: string; protocol?: string }` | optional | Plugin compatibility ranges (ADR-0025 §3.2; supersedes `engine`) |

content/docs/references/system/job.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,8 @@ const result = CronSchedule.parse(data);
6262
| **description** | `string` | optional | Job description / purpose |
6363
| **schedule** | `{ type: 'cron'; expression: string \| { dialect: Enum<'cel' \| 'js' \| 'cron' \| 'template'>; source?: string; ast?: any; meta?: object }; timezone?: string } \| { type: 'interval'; intervalMs: integer } \| { type: 'once'; at: string }` || Job schedule configuration |
6464
| **handler** | `string` || Handler function name (must match a key in `defineStack({ functions })`) |
65-
| **retryPolicy** | `{ maxRetries?: integer; backoffMs?: integer; backoffMultiplier?: number }` | optional | Retry policy configuration |
66-
| **timeout** | `integer` | optional | Timeout in milliseconds |
65+
| **retryPolicy** | `{ maxRetries?: integer; backoffMs?: integer; backoffMultiplier?: number }` | optional | Retry policy configuration. [EXPERIMENTAL — not enforced] The service-job scheduler does not yet read retryPolicy; failed runs are not retried per this config (liveness audit #1878/#1893). |
66+
| **timeout** | `integer` | optional | Timeout in milliseconds. [EXPERIMENTAL — not enforced] The service-job scheduler does not yet enforce a per-run timeout (liveness audit #1878/#1893). |
6767
| **enabled** | `boolean` | optional | Whether the job is enabled |
6868

6969

content/docs/references/system/translation.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,9 +154,9 @@ Internationalization configuration
154154
| **supportedLocales** | `string[]` || Supported BCP-47 locale codes |
155155
| **fallbackLocale** | `string` | optional | Fallback locale code |
156156
| **fileOrganization** | `Enum<'bundled' \| 'per_locale' \| 'per_namespace'>` || File organization strategy |
157-
| **messageFormat** | `Enum<'icu' \| 'simple'>` || Message interpolation format (ICU MessageFormat or simple) |
157+
| **messageFormat** | `Enum<'icu' \| 'simple'>` || Message interpolation format (ICU MessageFormat or simple). [EXPERIMENTAL — 'icu' not enforced] No ICU MessageFormat engine is wired; messageFormat:'icu' is accepted but interpolation falls back to simple substitution (liveness audit #1878/#1893). |
158158
| **lazyLoad** | `boolean` || Load translations on demand |
159-
| **cache** | `boolean` || Cache loaded translations |
159+
| **cache** | `boolean` || Cache loaded translations. [EXPERIMENTAL — not enforced] No runtime consumer reads this cache flag yet (liveness audit #1878/#1893). |
160160

161161

162162
---

0 commit comments

Comments
 (0)