|
1 | 1 | # ADR-0070: Package-first authoring — every runtime-authored item lives in a writable package (base); no orphans |
2 | 2 |
|
3 | | -**Status**: Proposed (2026-06-24) |
| 3 | +**Status**: Accepted (2026-06-24) — P1–P3 implemented, merged & live-verified (see *Implementation status*); D4–D6 remaining |
4 | 4 | **Deciders**: ObjectStack Protocol Architects |
5 | 5 | **Builds on**: [ADR-0005](./0005-metadata-customization-overlay.md) (`allowOrgOverride` / runtime overlay model; one Zod source per type), [ADR-0048](./0048-cross-package-metadata-collision.md) (one app per package; package id is the addressing unit), [ADR-0033](./0033-ai-assisted-metadata-authoring.md) (AI authors metadata as drafts), [ADR-0067](./0067-commit-history-and-rollback-for-ai-authoring.md) (commit history & rollback for AI authoring) |
6 | 6 | **Consumers**: `@objectstack/objectql` (`protocol.saveMetaItem` write path), `@objectstack/spec` (metadata-type registry), `../objectui` (Studio create flow, package scope selector, `PackagesPage`), `../cloud` (`service-ai-studio` — `create_metadata` / `resolvePackageId` / `apply_blueprint`) |
|
14 | 14 | > |
15 | 15 | > The fixes shipped so far (#2252, #1946) are deliberate **stopgaps**. This ADR replaces them with the proper model. |
16 | 16 |
|
| 17 | +## Implementation status (2026-06-24) — P1–P3 done, live-verified |
| 18 | + |
| 19 | +Built across the three surfaces and verified end-to-end in a real environment via the AI build flow. |
| 20 | + |
| 21 | +- **P1 — Kernel (D1/D2)** — `@objectstack/objectql` ([framework#2285](https://github.com/objectstack-ai/framework/pull/2285)): `isWritablePackage` predicate; a runtime-only create targeting a read-only code/installed package is **rejected** with `writable_package_required` (422) instead of coerced to `null`. |
| 22 | +- **P2 — Studio (D3)** — `../objectui` ([objectui#1970](https://github.com/objectstack-ai/objectui/pull/1970)): a create-flow gate that prompts/redirects to a writable base; `isLocalScope` / `writableBaseOptions` helpers; surfaces `writable_package_required` as an actionable error. |
| 23 | +- **P3 — AI (D3)** — `../cloud` `service-ai-studio` ([cloud#479](https://github.com/objectstack-ai/cloud/pull/479), [cloud#481](https://github.com/objectstack-ai/cloud/pull/481); tests [cloud#480](https://github.com/objectstack-ai/cloud/pull/480)): drops the shared `com.workspace` catch-all and auto-creates an **intentional named** base via `protocol.installPackage` (a real, Studio-visible package); single-writable-base coherence groups an incremental build into one base; an explicit platform/system `packageId` is discarded; empty field props are sanitized. |
| 24 | +- **Live dogfood (real LLM + runtime)**: a one-sentence magic build plus iterative business-user changes (add a related object, add a field) all landed in **one** app base (`app.iojn`), live and editable — no `com.workspace`, no orphans. |
| 25 | +- **Remaining**: **D4** (package-as-lifecycle-unit: delete-cascade / export / duplicate), **D5** (orphan migration + stopgap removal), **D6** (framing). The P1 kernel rejection becomes the runtime backstop once the framework release is consumed by the cloud runtime (today's runtime links the published framework). |
| 26 | + |
17 | 27 | ## TL;DR |
18 | 28 |
|
19 | 29 | 1. **[new] No orphan authored metadata.** Every runtime-*created* metadata item is bound to a **writable package** (`package_id` is a real, writable package id — never `null`, never a code/installed package). The "package-less / `sys_metadata`-scope" state stops being an authoring destination; it remains only as a read-side rehydration detail and a migration source. |
@@ -96,9 +106,9 @@ A metadata-customizable deployment is **single-tenant** (an *environment*; `proj |
96 | 106 |
|
97 | 107 | ## Rollout (tracked separately — see the package-first epic) |
98 | 108 |
|
99 | | -1. Kernel D1/D2 predicate + `writable_package_required` rejection (`@objectstack/objectql`). |
100 | | -2. Studio D3 create-flow + selector default; PackagesPage delete/duplicate (`../objectui`). |
101 | | -3. AI D3 enforcement in `service-ai-studio` (drop fallback, require package, update skills). |
102 | | -4. D4 package-as-unit (delete-cascade, export/duplicate). |
103 | | -5. D5 migration affordance; remove #2252/#1946 stopgaps. |
104 | | -6. Dogfood-gate coverage for each. |
| 109 | +1. ✅ Kernel D1/D2 predicate + `writable_package_required` rejection (`@objectstack/objectql`) — [framework#2285](https://github.com/objectstack-ai/framework/pull/2285). |
| 110 | +2. ✅ Studio D3 create-flow + selector default (`../objectui`) — [objectui#1970](https://github.com/objectstack-ai/objectui/pull/1970). (PackagesPage delete/duplicate moves to D4.) |
| 111 | +3. ✅ AI D3 in `service-ai-studio` (drop fallback, named base, skills) — [cloud#479](https://github.com/objectstack-ai/cloud/pull/479), [cloud#481](https://github.com/objectstack-ai/cloud/pull/481); tests [cloud#480](https://github.com/objectstack-ai/cloud/pull/480). |
| 112 | +4. ⏳ D4 package-as-unit (delete-cascade, export/duplicate). |
| 113 | +5. ⏳ D5 migration affordance; remove #2252/#1946 stopgaps. |
| 114 | +6. ◐ Dogfood-gate coverage — live-verified end-to-end; automated gate pending. |
0 commit comments