From 4795ea5ae95600a4d4f67f9f56ff28021d550b47 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 10 Aug 2026 07:36:16 +0000 Subject: [PATCH] docs(adr): repair 8 dead source-tree links in ADR-0004/ADR-0020 and empty the link-gate baseline Fixes #6726 Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01YS2qzDAn3CpWdY7uBX9bFQ --- docs/adr/0004-cloud-multi-kernel.md | 12 +++-- ...0020-state-machine-converge-and-enforce.md | 6 +-- scripts/check-adr-links.mjs | 54 +++---------------- 3 files changed, 18 insertions(+), 54 deletions(-) diff --git a/docs/adr/0004-cloud-multi-kernel.md b/docs/adr/0004-cloud-multi-kernel.md index fd23126710..c8de0cbeeb 100644 --- a/docs/adr/0004-cloud-multi-kernel.md +++ b/docs/adr/0004-cloud-multi-kernel.md @@ -64,8 +64,10 @@ Two deployable applications: ### 2. `KernelManager` + `ProjectKernelFactory` (new in `@objectstack/runtime`) -- **`KernelManager`** ([`packages/runtime/src/kernel-manager.ts`](../../packages/runtime/src/kernel-manager.ts)): LRU+TTL cache of `Map`. Exposes `getOrCreate(projectId)` (concurrent-safe, single-flight per id) and `evict(projectId)` (calls `kernel.shutdown()`). Configurable `maxSize` and `ttlMs`. -- **`DefaultProjectKernelFactory`** ([`packages/runtime/src/project-kernel-factory.ts`](../../packages/runtime/src/project-kernel-factory.ts)): given a `projectId`, reads project + credential + package-install rows from the control-plane driver, clones the base stack config, overrides the `default` datasource mapping to point at the project's driver, instantiates an `AppPlugin` per installed bundle, and calls `kernel.bootstrap()`. +> **Path note (2026-08):** the two paths below are historical and deliberately unlinked — neither file is in this repository any more. `kernel-manager.ts` was moved to `packages/runtime/src/cloud/` on 2026-05-18 (`7dcde27c1`, "decouple runtime from service-cloud"), where `project-kernel-factory.ts` was also superseded by `cloud/artifact-kernel-factory.ts`; the whole `packages/runtime/src/cloud/` tree was then removed by #1600 (`feat(runtime)!: remove multi-tenant runtime; keep single-env + contracts`). Multi-kernel runtime code is no longer maintained here. + +- **`KernelManager`** (`packages/runtime/src/kernel-manager.ts`): LRU+TTL cache of `Map`. Exposes `getOrCreate(projectId)` (concurrent-safe, single-flight per id) and `evict(projectId)` (calls `kernel.shutdown()`). Configurable `maxSize` and `ttlMs`. +- **`DefaultProjectKernelFactory`** (`packages/runtime/src/project-kernel-factory.ts`): given a `projectId`, reads project + credential + package-install rows from the control-plane driver, clones the base stack config, overrides the `default` datasource mapping to point at the project's driver, instantiates an `AppPlugin` per installed bundle, and calls `kernel.bootstrap()`. Both are exported from `@objectstack/runtime`. Self-hosted mode never imports `KernelManager`. @@ -90,8 +92,10 @@ Custom domains and multi-hostname binding (ACME certificates, `sys_domain` table ### 5. Studio surfaces hostname as a first-class field -- Project list ([`apps/studio/src/routes/projects.index.tsx`](../../apps/studio/src/routes/projects.index.tsx)) renders a globe icon + hostname inline with the project card. -- Project detail ([`apps/studio/src/routes/projects.$projectId.index.tsx`](../../apps/studio/src/routes/projects.$projectId.index.tsx)) adds a **Domains** card with inline edit (Enter to save, Escape to cancel, toast on success/conflict). +> **Path note (2026-08):** the two route paths below are historical and deliberately unlinked — Studio is not in this repository any more. `apps/studio/` was collapsed to a single-package metadata browser on 2026-05-22 (`6bacbced2`) and then migrated to the upstream `@object-ui/studio` package on 2026-05-24 (`06ad57f63`); `apps/` here now holds only `docs/`. + +- Project list (`apps/studio/src/routes/projects.index.tsx`) renders a globe icon + hostname inline with the project card. +- Project detail (`apps/studio/src/routes/projects.$projectId.index.tsx`) adds a **Domains** card with inline edit (Enter to save, Escape to cancel, toast on success/conflict). --- diff --git a/docs/adr/0020-state-machine-converge-and-enforce.md b/docs/adr/0020-state-machine-converge-and-enforce.md index 022d8b0f94..475bebe72d 100644 --- a/docs/adr/0020-state-machine-converge-and-enforce.md +++ b/docs/adr/0020-state-machine-converge-and-enforce.md @@ -40,12 +40,12 @@ The design intent is a **runtime guardrail**: declare which `status` transitions **Zero enforcement — verified across `packages/{runtime,objectql,services,core,metadata*,plugins}` and the whole repo:** -- `IWorkflowService` ([`workflow-service.ts:58`](../../packages/spec/src/contracts/workflow-service.ts#L58)) has **no concrete implementation**. +- `IWorkflowService` (`packages/spec/src/contracts/workflow-service.ts:58` — unlinked: the contract file was deleted on 2026-08-01 by #4451 / #4473, which retired the `workflow` service slot outright, closing the follow-up this record left open below) has **no concrete implementation**. - There is **no XState interpreter** anywhere (no `createMachine` / `interpret` / transition engine). - The write-path validator [`validateRecord`](../../packages/objectql/src/validation/record-validator.ts#L198) reads only `objectSchema.fields` and validates **field data types** (string/number/date/…). It **never reads `objectSchema.validations`** at all — so *not one* of the nine validation-rule types (`state_machine`, `cross_field`, `script`, `unique`, `format`, `json_schema`, `async`, `custom`, `conditional`) is enforced by it. - **Nothing reads `object.stateMachines`.** -So the guardrail goal is currently unmet at runtime. The only artefacts that exist are declarations — e.g. [`examples/app-crm/src/workflows/stale-opportunity.workflow.ts:19`](../../examples/app-crm/src/workflows/stale-opportunity.workflow.ts#L19) (`StateMachineConfig`), which additionally **mixes orchestration into the machine** (it carries `email_alert` / `task_creation` actions that no engine executes — that orchestration belongs to a record-triggered Flow per ADR-0019). +So the guardrail goal is currently unmet at runtime. The only artefacts that exist are declarations — e.g. `examples/app-crm/src/workflows/stale-opportunity.workflow.ts:19` (`StateMachineConfig`; unlinked — this file describes the pre-ADR state and was itself removed by this record's own implementation, see the checklist below), which additionally **mixes orchestration into the machine** (it carries `email_alert` / `task_creation` actions that no engine executes — that orchestration belongs to a record-triggered Flow per ADR-0019). #### The prior-state plumbing gap (the real implementation constraint) @@ -135,7 +135,7 @@ The transition declaration stays a flat, recognizable FSM (`field` + `{ from: [t - [~] `spec`: `IWorkflowService` — **kept as a documented follow-up**, not removed (see Implementation notes). - [x] `objectql`: wire the `validations` union into the write path — new [`rule-validator.ts`](../../packages/objectql/src/validation/rule-validator.ts) (`evaluateValidationRules` / `needsPriorRecord` / `legalNextStates`), with the prior record plumbed into [`engine.ts`](../../packages/objectql/src/engine.ts) on single-row update. Enforces `state_machine`, `cross_field`, and `script` together. - [x] `metadata-collection.zod.ts`: dropped the `workflows` collection key + `workflows: 'workflow'` plural mapping ([`metadata-collection.zod.ts`](../../packages/spec/src/shared/metadata-collection.zod.ts)). -- [x] `examples/app-crm`: rewrote `src/workflows/*.workflow.ts` — transition tables already live as the `opp_stage_transitions` `state_machine` rule on the opportunity object; side-effect actions became record-triggered / scheduled Flows ([`high-value-deal.flow.ts`](../../examples/app-crm/src/flows/high-value-deal.flow.ts), [`stale-opportunity.flow.ts`](../../examples/app-crm/src/flows/stale-opportunity.flow.ts)); removed the `workflows` registration from `objectstack.config.ts`. +- [x] `examples/app-crm`: rewrote `src/workflows/*.workflow.ts` — transition tables already live as the `opp_stage_transitions` `state_machine` rule on the opportunity object; side-effect actions became record-triggered / scheduled Flows (`examples/app-crm/src/flows/high-value-deal.flow.ts`, `examples/app-crm/src/flows/stale-opportunity.flow.ts` — unlinked: both flow files were later dropped on 2026-07-05 by `751cf0161`, "refactor(crm): slim back to the loading-pipeline smoke core", which trimmed the CRM example to its loading-pipeline core; the surviving `state_machine` rule is unaffected); removed the `workflows` registration from `objectstack.config.ts`. - [x] `examples/app-showcase`: carries the surviving shape — `state_machine` rules on `Task`, `Project`, `Account`. Predicate conditions corrected to the `record.` CEL scope form so enforcement actually fires. - [x] Tests: [`rule-validator.test.ts`](../../packages/objectql/src/validation/rule-validator.test.ts) (16 cases — allow/reject/no-op transitions, execution-control, predicate fail-open, introspection). Updated `object.test.ts`, `metadata-plugin.test.ts`, `metadata-collection.test.ts`, `overlay-precedence.test.ts` for the retired shapes. diff --git a/scripts/check-adr-links.mjs b/scripts/check-adr-links.mjs index c5b89ad36f..eab3eed2ed 100644 --- a/scripts/check-adr-links.mjs +++ b/scripts/check-adr-links.mjs @@ -139,54 +139,14 @@ const CONVENTION_ILLUSTRATIVE_TARGETS = [ * longer matches a live finding fails as STALE, so a fixed link cannot silently * regress back under cover of its own grandfather clause. * - * All 8 are ADR → source-tree links, not ADR → ADR links: the cross-record - * surface this gate was filed for is clean at the time of writing. Their fix - * is not mechanical — `apps/studio/**` moved to the `cloud` repository and the - * runtime/spec files were deleted outright — so it is tracked separately in - * **#6726** rather than guessed at here. Closing that issue empties this list. + * **The list is EMPTY, and that is the finished state.** The 8 ADR → source-tree + * links it was seeded with (#6592) were repaired under #6726: each target had + * genuinely left this repository, so each link became a plain unlinked path plus + * a short note saying where the code went. The ADR → ADR surface this gate was + * filed for was already clean. An empty baseline means the gate is now a gate + * rather than a grandfather clause — do not re-seed it. */ -const KNOWN_DEAD_TARGETS = [ - { - file: `${ADR_DIR}/0004-cloud-multi-kernel.md`, - target: '../../packages/runtime/src/kernel-manager.ts', - why: 'KernelManager was never a file at this path in this repo; cloud multi-kernel code lives in the cloud repo', - }, - { - file: `${ADR_DIR}/0004-cloud-multi-kernel.md`, - target: '../../packages/runtime/src/project-kernel-factory.ts', - why: 'same move as kernel-manager.ts', - }, - { - file: `${ADR_DIR}/0004-cloud-multi-kernel.md`, - target: '../../apps/studio/src/routes/projects.index.tsx', - why: 'apps/studio/ is not in this repository (apps/ holds only docs/)', - }, - { - file: `${ADR_DIR}/0004-cloud-multi-kernel.md`, - target: '../../apps/studio/src/routes/projects.$projectId.index.tsx', - why: 'apps/studio/ is not in this repository (apps/ holds only docs/)', - }, - { - file: `${ADR_DIR}/0020-state-machine-converge-and-enforce.md`, - target: '../../packages/spec/src/contracts/workflow-service.ts#L58', - why: 'no workflow-service.ts under packages/spec/src/contracts/ any more', - }, - { - file: `${ADR_DIR}/0020-state-machine-converge-and-enforce.md`, - target: '../../examples/app-crm/src/workflows/stale-opportunity.workflow.ts#L19', - why: 'examples/app-crm has no src/workflows/ directory any more', - }, - { - file: `${ADR_DIR}/0020-state-machine-converge-and-enforce.md`, - target: '../../examples/app-crm/src/flows/high-value-deal.flow.ts', - why: 'examples/app-crm/src/flows/ no longer carries this flow file', - }, - { - file: `${ADR_DIR}/0020-state-machine-converge-and-enforce.md`, - target: '../../examples/app-crm/src/flows/stale-opportunity.flow.ts', - why: 'examples/app-crm/src/flows/ no longer carries this flow file', - }, -]; +const KNOWN_DEAD_TARGETS = []; /** * Blank out fenced code blocks, preserving line count so findings keep their