From b6426b476558d794151bab4032a1d4961919da7b Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 1 Aug 2026 14:13:20 +0000 Subject: [PATCH] docs(spec,metadata-protocol): the code is the record for platform `agent` definitions (#4507) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `agent` is the only authorable type with no governed write path — ADR-0063 §2 closes `*.agent.ts` to third parties, so both `allowOrgOverride` and `allowRuntimeCreate` are false and nothing reaches `saveMetaItem`. Its rows are written by the shipping plugin at boot (`AIStudioPlugin.registerMeta` → `metadataService.register()` → `MetadataManager.register` → `DatabaseLoader.save`), which writes `sys_metadata` directly with a fresh checksum and appends no `sys_metadata_history` row. A shipped agent definition that changes between releases therefore leaves no metadata-side change log. That is a deliberate position, and it now sits beside the declaration rather than only in an issue: the two definitions live in version control (`@objectstack/service-ai-studio`, `cloud` repo), so git already holds the full reviewable history, and a second history in `sys_metadata` would be a WORSE record — it would capture only the boots where a given deployment saw the checksum move, so two deployments on one release would carry different "histories" of an identical, code-fixed definition. The note names the two consequences that read as bugs and are not: the `skipped` outcome `os migrate meta --stored` reports for `agent` is correct and permanent for this type, and Studio showing no History tab is the absence of anything to show. `migrateStoredMetadata`'s TSDoc — where the skip reason was what made this look like a gap — now points at it. It also states its own expiry: opening `agent` to tenant authoring removes the git fallback, so opening the type and giving it a real history path are the same piece of work. Comment-only; empty changeset. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01WoZPKPDqJ7WB7z84xk9y3f --- .changeset/agent-code-is-the-record.md | 33 ++++++++++++++++++ packages/metadata-protocol/src/protocol.ts | 8 +++++ .../spec/src/kernel/metadata-plugin.zod.ts | 34 +++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 .changeset/agent-code-is-the-record.md diff --git a/.changeset/agent-code-is-the-record.md b/.changeset/agent-code-is-the-record.md new file mode 100644 index 0000000000..1050e17e10 --- /dev/null +++ b/.changeset/agent-code-is-the-record.md @@ -0,0 +1,33 @@ +--- +--- + +docs(spec,metadata-protocol): record why platform `agent` definitions have no metadata change log (#4507) + +Comment-only — no behaviour changes, nothing to release. + +`agent` is the only authorable metadata type with no governed write path +(`allowOrgOverride` and `allowRuntimeCreate` are both `false` per ADR-0063 §2, +which closes `*.agent.ts` to third parties). Its rows are written by the +shipping plugin at boot — `AIStudioPlugin.registerMeta` → `metadataService.register()` +→ `MetadataManager.register` → `DatabaseLoader.save` — which writes +`sys_metadata` directly with a fresh checksum and appends no +`sys_metadata_history` row. So a shipped agent definition that changes between +releases leaves no metadata-side change log. + +That is accepted rather than overlooked, and the reasoning now sits beside the +declaration instead of in an issue: the two definitions live in version control +(`@objectstack/service-ai-studio` in the `cloud` repo), so git already holds the +full reviewable history. A second history in `sys_metadata` would be a *worse* +record — it would capture only the boots where a given deployment happened to +see the checksum move, so two deployments on the same release would carry +different "histories" of an identical, code-fixed definition. + +Two consequences that read as bugs and are not are named explicitly: the +`skipped` outcome `os migrate meta --stored` reports for `agent` rows is correct +and permanent for this type, and Studio showing no History tab for an agent is +the absence of anything to show. `migrateStoredMetadata`'s TSDoc now points at +the note rather than leaving its skip reason to be read as a to-do. + +The note also states its own expiry: if `agent` is ever opened to tenant +authoring, an author-owned definition has no git to fall back on, so opening the +type and giving it a real history path become the same piece of work. diff --git a/packages/metadata-protocol/src/protocol.ts b/packages/metadata-protocol/src/protocol.ts index c9eed06fd8..cfe9b68b45 100644 --- a/packages/metadata-protocol/src/protocol.ts +++ b/packages/metadata-protocol/src/protocol.ts @@ -6610,6 +6610,14 @@ export class ObjectStackProtocolImplementation implements * raw-engine branch, which records no history and forces `state: * 'active'` — a historyless rewrite that could also promote a draft is * not what this pass promises, so it declines instead. + * + * Today that is exactly one type, `agent`, and its skip is **permanent + * by design, not a to-do** (#4507): ADR-0063 §2 closes `*.agent.ts` to + * third parties, so the only agent definitions in existence are the two + * the platform ships from version control — where git, not + * `sys_metadata_history`, is the change log. See the note beside the + * `agent` entry in `metadata-plugin.zod.ts` before treating this branch + * as a gap to close. * - **Rows that still fail the current schema after conversion.** * `saveMetaItem` rejects them (422) and that rejection is correct: the * body is a genuine contract violation, not chain-owned history. They diff --git a/packages/spec/src/kernel/metadata-plugin.zod.ts b/packages/spec/src/kernel/metadata-plugin.zod.ts index 547424f434..c60cde9699 100644 --- a/packages/spec/src/kernel/metadata-plugin.zod.ts +++ b/packages/spec/src/kernel/metadata-plugin.zod.ts @@ -695,6 +695,40 @@ export const DEFAULT_METADATA_TYPE_REGISTRY: MetadataTypeRegistryEntry[] = [ // allowRuntimeCreate:false (no runtime "create agent") and // allowOrgOverride:false (no per-org agent fork). The runtime catalog // additionally filters out any non-platform agent record (see service-ai). + // + // FOR AGENTS, THE CODE IS THE RECORD — and that is the whole answer to + // "where is this type's change log?" (#4507). Because the two flags above + // are false, `agent` is the one authorable type with NO governed write + // path: `saveMetaItem` would route it down the legacy raw-engine branch, + // and nothing calls it. The rows are written instead by the shipping + // plugin at boot — `AIStudioPlugin.registerMeta` → `metadataService + // .register()` → `MetadataManager.register` → `DatabaseLoader.save` — + // which writes `sys_metadata` directly with a fresh checksum and appends + // NO `sys_metadata_history` row. So an agent definition that changes + // between releases leaves no metadata-side change log, and there is no + // metadata-side rollback. + // + // That is accepted, not overlooked. These definitions live in version + // control (`@objectstack/service-ai-studio`, `cloud` repo: + // `agents/ask-agent.ts`, `agents/metadata-assistant-agent.ts`), so git + // already holds the full, reviewable history of every change. A second + // history in `sys_metadata` would be a WORSE record, not a better one: it + // would capture only the boots where a given deployment happened to see + // the checksum move, so two deployments on the same release would carry + // different "histories" of an identical, code-fixed definition. Do not add + // one to close a perceived gap. + // + // Two consequences that look like bugs and are not: + // - `migrateStoredMetadata` reports `agent` rows `skipped` ("no repository + // write path"). That is CORRECT AND PERMANENT for this type, not a + // to-do — the pass declines rather than performing a historyless + // rewrite that could also promote a draft. + // - Studio surfaces no History tab for an agent. There is nothing to show; + // the answer to "what changed" is the `cloud` commit log. + // + // If `agent` is ever OPENED to tenant authoring, this note stops applying: + // an author-owned definition has no git to fall back on, so opening the + // type and giving it a real history path are the same piece of work. { type: 'agent', label: 'AI Agent', filePatterns: ['**/*.agent.ts', '**/*.agent.yml'], supportsOverlay: false, allowOrgOverride: false, allowRuntimeCreate: false, supportsVersioning: true, executionPinned: true, loadOrder: 90, domain: 'ai' }, { type: 'tool', label: 'AI Tool', filePatterns: ['**/*.tool.ts', '**/*.tool.yml'], supportsOverlay: true, allowOrgOverride: true, allowRuntimeCreate: true, supportsVersioning: false, executionPinned: false, loadOrder: 85, domain: 'ai' }, { type: 'skill', label: 'AI Skill', filePatterns: ['**/*.skill.ts', '**/*.skill.yml'], supportsOverlay: true, allowOrgOverride: true, allowRuntimeCreate: true, supportsVersioning: false, executionPinned: false, loadOrder: 88, domain: 'ai' },