refactor(artifacts)!: establish the shared Kind contract (FACT-61) - #535
Conversation
…1297) Refactors Artifact Kind definitions into one shared, validated contract: every Kind declares its category, readable title path and positive integer schema generation. Existing framework and product consumers migrate together; old metadata no longer silently controls validation, rendering, context selection or status transitions. Tracks [FACT-61](https://makaio.atlassian.net/browse/FACT-61), under [FACT-58](https://makaio.atlassian.net/browse/FACT-58). Consumer PR: [Factory #929](https://github.com/computeruniverse/ai-factory/pull/929). ## Contract and migration - Require `category`, `titlePath`, numeric `schemaVersion`, description and a data schema. Validate data-relative paths and the declared relation, uniqueness and evidence constraints structurally. - Preserve live-only hooks. New declarative constraints do not introduce a lifecycle or cross-Artifact uniqueness engine. - Remove Kind `scopeSchema`, `observationSchema`, `discriminator`, `conflictPolicy`, `status`, `lifecycle`, `projection` and `defaultContext`. Explicit caller context selectors and custom view builders remain available. - Carry integer generations through registration, revisions, workflow bindings, hooks, MCP and product persistence. Existing TEXT storage uses an explicit strict codec; historical opaque/SemVer values are not guessed or rewritten. - Allow a caller-assigned create identity. Existing primary-key/CAS mechanisms reject collisions without overwrite or duplicate creation events. This preserves retry identity independently of semantic uniqueness. ## Deliberate scope and temporary losses This is a pre-production contract cut, not a replacement of every retired capability. Generic Kind-driven field/summary rendering, surface permission/affordance routing, implicit related-context injection, derived Kind-status events/readiness and automatic natural-key conflict handling are retired. Explicit custom rendering, caller-selected context and existing Workpiece paths remain. Unsupported legacy activation must fail visibly. Reusable Kind views and their shared extensible vocabulary remain a later slice. Semantic uniqueness execution is tracked in [FACT-103](https://makaio.atlassian.net/browse/FACT-103). Configurable Confluence representations are [FACT-65](https://makaio.atlassian.net/browse/FACT-65); the entire existing World Plan is Legacy, with a possible separate Epic recorded in [FACT-104](https://makaio.atlassian.net/browse/FACT-104). ## Implementation decisions to review - Lifecycle tokens in declaration validation are implementation choices for this cut, not a claim that every name was explicitly agreed: Knowledge `valid/retired`, Commitment `proposed/decided/fulfilled/revoked`, Interaction `open/resolved/closed-without-resolution`; Records reject lifecycle-conditioned declarations. - No migration engine or historical-content conversion is introduced. Incompatible old generations fail visibly. - Technical scope/identity boundaries remain distinct from semantic relations. Category is generic Core vocabulary; no product Kind names are added to the shared engine. - Caller-assigned identity addresses technical replay; it neither implements `uniqueness` nor decides whether semantic duplicates should merge. - Authoring fails visibly for closed-object intersections and Zod tuples whose current serialization cannot preserve their live constraints. This cut does not introduce a schema-normalization engine; ordinary object/union Kinds remain supported. Standard hand-authored JSON Schemas are validated according to their declared dialect and constraints. ## Review hardening - Preserve canonical cross-field validation at inline Factory configuration intake and reject retired GitHub field inference/derived modes before provisioning. - Inspect shared and referenced union constraints according to the declared schema dialect. Unsupported dialects are rejected at registration rather than failing every write later. Path inspection checks declared locations/types; it does not prove global schema satisfiability. The original complete schema still validates every write. - Skip blank generated extraction entries without abandoning later valid observations; give attachment Artifacts a readable producer-owned label when supplied names are blank. - Use a stable UUID operation identity for the first review-orchestration snapshot. Concurrent creators recompute through the existing CAS loop; historical identities remain intact. Report-local finding replay remains separate from semantic cross-report consolidation. - Repair a verified process-cleanup classification race exposed by validation: TERM/escalation/final cleanup/probe `EPERM` may proceed to bounded quiescence verification, but never grants success by itself. Safe release still requires an absent group or positively observed zombie-only members; live or unverifiable groups fail closed. No timeout or TERM/escalation policy is relaxed. Additional confirmed review corrections: - Reject asynchronous schemas at registration and compiled async validators before invocation; named anchors are explicitly unsupported in this cut. Zod 4 already enforces safe integer generations, now covered by a boundary regression. - Index primitive leaves within explicitly declared searchable object containers without indexing their keys or undeclared siblings. - Observe status only when an explicit workflow binding supplies request-only `statusPath`. Persisted post-hook values determine existing status events; the status hook sees the latest revision after earlier hooks. No Kind status inference returns. - Terminally supersede stale legacy GitHub projection commands using exact-slot revision/checksum checks. Retain provider identity and uncertain-create evidence, allow safe explicit preparation, and preserve matching prepared-command recovery. Migration 0005 changes only the recovery index; no table rewrite or new routing engine. ## Scoped review decision For this PR only, the maintainer requires fixing all valid findings when a review round contains a merge blocker. A round containing only non-blocking findings is recorded for a prompt post-merge follow-up, without another implementation commit here. The late Codex round was initially deferred, then the final same-head CI added a blocker. Under the mixed-round rule, its valid corrections are included together; [FACT-61 comment 10484](https://makaio.atlassian.net/browse/FACT-61?focusedCommentId=10484) records that disposition. The earlier attached patch remains a draft historical snapshot, not the final implementation. - Registration uses an explicit fragment-only schema-reference profile. External/document-relative references and missing/non-schema fragment targets fail early, including unrelated optional properties. Owned non-string `$ref` values fail; example/default/constant/enum data is untouched. Boolean and recursive schema targets remain supported. Absolute self-contained `$id` forms, percent-encoded URI fragments and paths through intermediate arrays are outside this cut's profile even where AJV could support them; no new schema resolver is introduced. - The retained blueprint materializer forwards its configured status position as a data-relative pointer. Existing actual-value comparison suppresses unchanged status events, including relation-only changes. No Kind status inference returns. - Workflow creation requires explicit initial data. A binding without a create expression remains valid when an existing Artifact reference is supplied or resolved; invalid creation no longer synthesizes `{}`. ## Validation and delivery Current head: `75b9d673e0e077fda670da14a76bd2995731b84a`. full `yarn validate` passed **11,016 files**. The complete supported `MAKAIO_TEST_PLAN=bounded yarn test` plan passed on **Node 22.22.2 / Bun 1.4.2** with **30,438 Vitest tests, 68 skipped, plus 25 Bun tests** (330.1 seconds). Every project and the execution-sensitive lanes are included. Independent reviews of the schema reference, workflow binding and explicit status corrections are clean. CodeRabbit reviewed all eight changed files, including both new regression files, with zero findings. The CI test matrix now pins Bun **1.4.2**, matching the runtime used by the successful same-head distribution build. The existing child-process deadlines, full declaration backend and runtime assertions are unchanged. The complete [CI run 34267280415](https://github.com/makaio-ai/makaio/actions/runs/34267280415) passed on this exact head, including both installed-consumer proofs. The previous failure was: [run 34262513930](https://github.com/makaio-ai/makaio/actions/runs/34262513930) hit both installed-consumer builds' own 270-second deadlines under Bun 1.3.14. The earlier aggregate setup correction remains necessary: deadlines are derived from the existing sequential child limits (recovery 630 seconds plus five seconds hook headroom; local Git 510 plus five). Runtime evidence has distinct limits. The official [Bun #33102](oven-sh/bun#33102) symlink/repeated-build fixture fails on 1.3.14 and passes on 1.4.2 locally, but our distribution build uses tsdown rather than direct `Bun.build`. The successful standalone job also installs fresh dependencies without a copied lockfile, unlike the locked full-workspace fixture. Therefore neither observation alone establishes the cause of the CI timing gap. A local negative control on Node 24.12.0 / Bun 1.4.2 produced 26 framework-platform/adapter failures involving spawn `EBADF` and worker startup, with 30,412 tests passing. Keeping Bun and the source tree unchanged, the complete Node 22 run passed. Both results are retained in FACT-61 and shared with FACT-102; no claim is made that the local Darwin failure and Linux CI timeout share one cause. The framework archive from `75b9d673e0e077fda670da14a76bd2995731b84a` has SHA256 `5607a7836600842a7c4aa627b9db670b3f908e12c45ef583d8e6483b5e446849`. The private-facade archive has SHA256 `617a685f19dcc920409d94043531011d50a6da76b2a8ef46f065d99dd908169f`; all 249 files were verified byte-for-byte and 43 private-package tests passed. These are local integration archives, not npm publications. These archives include the current schema-reference and workflow-binding corrections. Independent verification matched all 678 framework files and 249 private files against the installed/vendored copies. Factory #929 passed its complete local canon against those archives: static validation (2,800 files), 4,685 Bun tests, 7,802 Vitest tests (seven skipped), TypeScript, build and real PostgreSQL/server/CLI/MCP/dashboard/auth E2E. Its clean-install CI remains blocked by the committed old published framework until actual publication and pin update. Delivery requires a new `@makaio/framework` publication after upstream merge/sync and a refreshed private `@makaio/cyberport-factory` bundle. No new `@makaio/storage-pg` release is needed: its implementation is unchanged and shared helpers are external framework imports. No deployment, merge, publication or database reset is included. The exact-head CI and final 20-minute review observation are complete: no new actionable feedback arrived. The upstream PR is ready for maintainer merge; the Factory consumer still requires the ensuing framework publication and pin update. Synced-from: makaio-ai/makaio@7d2c1842365e5ca1419eaa97152394308421c0ab
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b503c180af
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| return combined ? fieldSchemas(root, combined, parts, required, refs) : undefined; | ||
| } | ||
| if (parts.length === 0) return [node]; | ||
| if (node.type !== 'object') return undefined; |
There was a problem hiding this comment.
Accept implicit root-object JSON Schemas
Treat the root artifact data envelope as an object when inspecting paths. A valid hand-authored schema such as { properties: { title: { type: 'string' } }, required: ['title'] } omits the optional type keyword, but artifact data is already constrained to an object by ArtifactRevisionSchema; this unconditional check therefore rejects registrations whose title is correctly required for every possible artifact payload.
Useful? React with 👍 / 👎.
| schemaVersion: ArtifactSchemaVersionSchema, | ||
| category: ArtifactCategorySchema, | ||
| dataSchema: JsonObjectContractSchema, | ||
| titlePath: ArtifactDataPathSchema, |
There was a problem hiding this comment.
Update the public artifact authoring documentation
Update the user-facing examples with this contract change. docs/creating-extensions.md:425-511 still instructs users to pass string schema versions and the removed conflictPolicy, projection, and defaultContext APIs, while docs/creating-workflows.md:137-142 and 411-416 still use schemaVersion: '1'; copying these examples now produces type errors or registration failures against the newly required numeric version, category, and title path.
Useful? React with 👍 / 👎.
Refactors Artifact Kind definitions into one shared, validated contract: every Kind declares its category, readable title path and positive integer schema generation. Existing framework and product consumers migrate together; old metadata no longer silently controls validation, rendering, context selection or status transitions.
Tracks FACT-61, under FACT-58. Consumer PR: Factory makaio-ai/makaio#929.
Contract and migration
category,titlePath, numericschemaVersion, description and a data schema. Validate data-relative paths and the declared relation, uniqueness and evidence constraints structurally.scopeSchema,observationSchema,discriminator,conflictPolicy,status,lifecycle,projectionanddefaultContext. Explicit caller context selectors and custom view builders remain available.Deliberate scope and temporary losses
This is a pre-production contract cut, not a replacement of every retired capability. Generic Kind-driven field/summary rendering, surface permission/affordance routing, implicit related-context injection, derived Kind-status events/readiness and automatic natural-key conflict handling are retired. Explicit custom rendering, caller-selected context and existing Workpiece paths remain. Unsupported legacy activation must fail visibly.
Reusable Kind views and their shared extensible vocabulary remain a later slice. Semantic uniqueness execution is tracked in FACT-103. Configurable Confluence representations are FACT-65; the entire existing World Plan is Legacy, with a possible separate Epic recorded in FACT-104.
Implementation decisions to review
Lifecycle tokens in declaration validation are implementation choices for this cut, not a claim that every name was explicitly agreed: Knowledge
valid/retired, Commitmentproposed/decided/fulfilled/revoked, Interactionopen/resolved/closed-without-resolution; Records reject lifecycle-conditioned declarations.No migration engine or historical-content conversion is introduced. Incompatible old generations fail visibly.
Technical scope/identity boundaries remain distinct from semantic relations. Category is generic Core vocabulary; no product Kind names are added to the shared engine.
Caller-assigned identity addresses technical replay; it neither implements
uniquenessnor decides whether semantic duplicates should merge.Authoring fails visibly for closed-object intersections and Zod tuples whose current serialization cannot preserve their live constraints. This cut does not introduce a schema-normalization engine; ordinary object/union Kinds remain supported. Standard hand-authored JSON Schemas are validated according to their declared dialect and constraints.
Review hardening
EPERMmay proceed to bounded quiescence verification, but never grants success by itself. Safe release still requires an absent group or positively observed zombie-only members; live or unverifiable groups fail closed. No timeout or TERM/escalation policy is relaxed.Additional confirmed review corrections:
statusPath. Persisted post-hook values determine existing status events; the status hook sees the latest revision after earlier hooks. No Kind status inference returns.Scoped review decision
For this PR only, the maintainer requires fixing all valid findings when a review round contains a merge blocker. A round containing only non-blocking findings is recorded for a prompt post-merge follow-up, without another implementation commit here.
The late Codex round was initially deferred, then the final same-head CI added a blocker. Under the mixed-round rule, its valid corrections are included together; FACT-61 comment 10484 records that disposition. The earlier attached patch remains a draft historical snapshot, not the final implementation.
$refvalues fail; example/default/constant/enum data is untouched. Boolean and recursive schema targets remain supported. Absolute self-contained$idforms, percent-encoded URI fragments and paths through intermediate arrays are outside this cut's profile even where AJV could support them; no new schema resolver is introduced.{}.Validation and delivery
Current head:
75b9d673e0e077fda670da14a76bd2995731b84a. fullyarn validatepassed 11,016 files. The complete supportedMAKAIO_TEST_PLAN=bounded yarn testplan passed on Node 22.22.2 / Bun 1.4.2 with 30,438 Vitest tests, 68 skipped, plus 25 Bun tests (330.1 seconds). Every project and the execution-sensitive lanes are included. Independent reviews of the schema reference, workflow binding and explicit status corrections are clean. CodeRabbit reviewed all eight changed files, including both new regression files, with zero findings.The CI test matrix now pins Bun 1.4.2, matching the runtime used by the successful same-head distribution build. The existing child-process deadlines, full declaration backend and runtime assertions are unchanged. The complete CI run 34267280415 passed on this exact head, including both installed-consumer proofs. The previous failure was: run 34262513930 hit both installed-consumer builds' own 270-second deadlines under Bun 1.3.14. The earlier aggregate setup correction remains necessary: deadlines are derived from the existing sequential child limits (recovery 630 seconds plus five seconds hook headroom; local Git 510 plus five).
Runtime evidence has distinct limits. The official Bun makaio-ai/makaio#33102 symlink/repeated-build fixture fails on 1.3.14 and passes on 1.4.2 locally, but our distribution build uses tsdown rather than direct
Bun.build. The successful standalone job also installs fresh dependencies without a copied lockfile, unlike the locked full-workspace fixture. Therefore neither observation alone establishes the cause of the CI timing gap.A local negative control on Node 24.12.0 / Bun 1.4.2 produced 26 framework-platform/adapter failures involving spawn
EBADFand worker startup, with 30,412 tests passing. Keeping Bun and the source tree unchanged, the complete Node 22 run passed. Both results are retained in FACT-61 and shared with FACT-102; no claim is made that the local Darwin failure and Linux CI timeout share one cause.The framework archive from
75b9d673e0e077fda670da14a76bd2995731b84ahas SHA2565607a7836600842a7c4aa627b9db670b3f908e12c45ef583d8e6483b5e446849. The private-facade archive has SHA256617a685f19dcc920409d94043531011d50a6da76b2a8ef46f065d99dd908169f; all 249 files were verified byte-for-byte and 43 private-package tests passed. These are local integration archives, not npm publications. These archives include the current schema-reference and workflow-binding corrections. Independent verification matched all 678 framework files and 249 private files against the installed/vendored copies.Factory makaio-ai/makaio#929 passed its complete local canon against those archives: static validation (2,800 files), 4,685 Bun tests, 7,802 Vitest tests (seven skipped), TypeScript, build and real PostgreSQL/server/CLI/MCP/dashboard/auth E2E. Its clean-install CI remains blocked by the committed old published framework until actual publication and pin update.
Delivery requires a new
@makaio/frameworkpublication after upstream merge/sync and a refreshed private@makaio/cyberport-factorybundle. No new@makaio/storage-pgrelease is needed: its implementation is unchanged and shared helpers are external framework imports. No deployment, merge, publication or database reset is included. The exact-head CI remains green. Delayed Codex feedback reopened review after the initial 20-minute observation; the maintainer extended final observation to 40 minutes, now running on this unchanged head. The three valid non-blocking items below are explicitly assigned to the prompt post-merge follow-up. The Factory consumer still requires the ensuing framework publication and pin update.Delayed review: non-blocking follow-up
FACT-61 comment 10524 assigns all three independently verified findings to the first upstream follow-up promptly after merge, under the maintainer's scoped rule. No current-release blocker was found.
Synced-from: makaio-ai/makaio@7d2c1842365e5ca1419eaa97152394308421c0ab