|
| 1 | +--- |
| 2 | +title: v3.7 External Deltas — for SPEC.CK.NEW reconciliation and operator-dev briefs |
| 3 | +status: external |
| 4 | +ingest: false |
| 5 | +visibility: internal |
| 6 | +revisit: pending |
| 7 | +--- |
| 8 | + |
| 9 | +# v3.7 External Deltas |
| 10 | + |
| 11 | +Tasks **#14, #15, #16, #24** from the v3.7 documentation overhaul. These items are not changes to the published v3.7 spec docs — they are notes and recommendations targeted at: |
| 12 | + |
| 13 | +- the user's external `SPEC.CK.NEW` (#14, #15, #16) |
| 14 | +- the `CK.Operator` codebase (#24) |
| 15 | + |
| 16 | +Each section is self-contained and citation-ready. Paste blocks of "Recommended insertion" text directly into the target document; paste "Code-side fix brief" blocks into a developer ticket. |
| 17 | + |
| 18 | +This file is held outside `docs/v3.7/` and `docs/public/` so it is never served by VitePress, never indexed by `sitemap.xml`, and never referenced by `llms.txt`. |
| 19 | + |
| 20 | +--- |
| 21 | + |
| 22 | +## #14 — `static` kernel type missing from external SPEC.CK.NEW |
| 23 | + |
| 24 | +### v3.7 spec position |
| 25 | + |
| 26 | +`static` is one of five kernel types in the v3.7 normative `qualities.type` enum. It is used by at least one system kernel and described consistently across the spec: |
| 27 | + |
| 28 | +| Citation (v3.7) | Statement | |
| 29 | +|---|---| |
| 30 | +| `docs/v3.7/crd.md:49` | ConceptKernel CRD `spec.type` enum: `["node:hot", "node:cold", "inline", "static", "agent"]` | |
| 31 | +| `docs/v3.7/conformance.md:137` | "One of four deployment profiles: `node:hot` (always-on), `node:cold` (on-demand), `inline` (browser-side), `static` (filer-served, no process)." | |
| 32 | +| `docs/v3.7/bfo-grounding.md:80` | `static` ↔ `ckp:StaticKernel`, "Filer-served web only — No process — gateway serves files — No NATS (read-only web surface)" | |
| 33 | +| `docs/v3.7/auth.md:48` | Kernel Type Authentication Requirements: `static` row, "None / None / No NATS connection" | |
| 34 | +| `docs/v3.7/message-envelope.md:267` | `static` row, "No NATS connection / None / None / None" | |
| 35 | +| `docs/v3.7/taxonomy.md:24` | Declarator archetype example: `CK.Project` is `qualities.type: static` | |
| 36 | +| `docs/v3.7/project.md:14,19` | "CK.Project is a `static` kernel because it holds only declarations; it has no processor that executes actions at runtime." | |
| 37 | +| `docs/public/ontology/v3.7/core.ttl` | `ckp:StaticKernel` is a subClassOf `ckp:Kernel` | |
| 38 | + |
| 39 | +Internal note: `conformance.md:137` says **four** deployment profiles, omitting `agent`. That sentence is itself a v3.7 internal drift bug (the enum has five). It should be fixed independently to: "One of five deployment profiles: `node:hot`, `node:cold`, `inline`, `static`, `agent`." — but it does *include* `static`. |
| 40 | + |
| 41 | +### Discrepancy |
| 42 | + |
| 43 | +External `SPEC.CK.NEW §1.2` and the §7 manifest template list four kernel types (no `static`). v3.7 needs five. |
| 44 | + |
| 45 | +### Recommended insertion into SPEC.CK.NEW |
| 46 | + |
| 47 | +Add a fifth kernel type to the §1.2 enum and the §7 manifest template: |
| 48 | + |
| 49 | +> ```yaml |
| 50 | +> qualities: |
| 51 | +> type: static # filer-served, no process; gateway serves storage/web/ directly |
| 52 | +> ``` |
| 53 | +> |
| 54 | +> A `static` kernel: |
| 55 | +> - has **no** processor pod and **no** NATS connection |
| 56 | +> - is served by the project gateway from its `tool/web/` (or equivalent) DATA-organ path |
| 57 | +> - is the canonical type for **declaration-only** kernels (e.g., CK.Project, which materialises a `.ckproject` manifest but does not execute actions at runtime) |
| 58 | +> - is mapped to `ckp:StaticKernel` in `core.ttl` |
| 59 | +> |
| 60 | +> Conformance: implementations that omit `static` cannot represent declaration-only kernels. CKP requires support for all five types. |
| 61 | +
|
| 62 | +--- |
| 63 | +
|
| 64 | +## #15 — 10-step reconciliation lifecycle: external SPEC missing `deploy.security` and `deploy.graph` |
| 65 | +
|
| 66 | +### v3.7 spec position (canonical 10-step lifecycle) |
| 67 | +
|
| 68 | +`docs/v3.7/reconciliation.md` defines the lifecycle. `docs/v3.7/operator.md:67-76` repeats it as the high-level overview. Both agree on 10 steps in this order: |
| 69 | +
|
| 70 | +| # | Step | Purpose | v3.7 citation | |
| 71 | +|---|---|---|---| |
| 72 | +| 1 | `deploy.namespace` | Create namespace `ck-{subdomain}` | `reconciliation.md:33-37` | |
| 73 | +| 2 | **`deploy.security`** | ServiceAccount + 4 NetworkPolicies (default-deny-all, allow-nats, allow-dns, allow-gateway); `automountServiceAccountToken: false` | `reconciliation.md:39-51` | |
| 74 | +| 3 | `deploy.storage` | PV/PVC per three-loop spec (CK ReadOnlyMany + DATA ReadWriteMany) | `reconciliation.md:53-62` | |
| 75 | +| 4 | `deploy.processors` | ConfigMap (`boot.py`) + Deployment for processor pods | `reconciliation.md:64-68` | |
| 76 | +| 5 | `deploy.web` | Generated `index.html` + web Deployment + Service | `reconciliation.md:70-81` | |
| 77 | +| 6 | `deploy.routing` | HTTPRoute via Gateway API `parentRef` | `reconciliation.md:83-94` | |
| 78 | +| 7 | `deploy.ck_resources` | ConceptKernel CRs per kernel | `reconciliation.md:96-99` | |
| 79 | +| 8 | `deploy.auth` | Keycloak realm reuse / `KeycloakRealmImport` create | `reconciliation.md:~100`, `auth.md` Step-by-Step Execution | |
| 80 | +| 9 | **`deploy.graph`** | RDF materialisation to Jena Fuseki `/ckp` dataset, named graph per project (`urn:ckp:fleet:{hostname}`) | `reconciliation.md:124-148`, `graph.md` | |
| 81 | +| 10 | `deploy.endpoint` | External endpoint verification (HTTP 200) | `reconciliation.md:~150` | |
| 82 | +
|
| 83 | +### Internal v3.7 drift (bonus finding) |
| 84 | +
|
| 85 | +`docs/v3.7/changelog.md:73-86` shows a "Reconciliation Lifecycle (Versioned -- 12 Steps)" that splits storage into `deploy.materialise` + `deploy.storage.ck` + `deploy.storage.tool` + `deploy.storage.data`, and **omits `deploy.security`** entirely from the listing. This is an internal documentation drift bug independent of the external-spec reconciliation: |
| 86 | +
|
| 87 | +- `reconciliation.md` is the canonical lifecycle (10 logical steps) |
| 88 | +- `changelog.md` shows a versioned-implementation breakdown (12 implementation steps for the v3.7 multi-version materialisation feature) |
| 89 | +- The two should cross-reference each other and clarify which is the protocol-level lifecycle vs. which is the implementation breakdown — currently a reader hits both and cannot tell |
| 90 | +
|
| 91 | +Suggest adding to `changelog.md:73` a sentence: "This 12-step breakdown is the implementation expansion of the canonical 10-step lifecycle from [Reconciliation](./reconciliation), with `deploy.materialise` introduced and `deploy.storage` split per organ. The canonical lifecycle remains 10 steps." (Tracked as a candidate Pass-3 follow-up; not part of this externals delta.) |
| 92 | +
|
| 93 | +### Discrepancy with external SPEC |
| 94 | +
|
| 95 | +External `SPEC.CK.NEW §4` defines a 5-check contract. The two steps missing relative to v3.7's 10: |
| 96 | +
|
| 97 | +- **`deploy.security`** — default-deny NetworkPolicies per project namespace |
| 98 | +- **`deploy.graph`** — RDF materialisation to Jena Fuseki at `/ckp` |
| 99 | +
|
| 100 | +### Recommended insertion into SPEC.CK.NEW |
| 101 | +
|
| 102 | +Extend §4 from the 5-check minimum to the v3.7 10-step lifecycle (table above). The two new entries: |
| 103 | +
|
| 104 | +> **`deploy.security`** (between `deploy.namespace` and `deploy.storage`) |
| 105 | +> |
| 106 | +> Per-project Kubernetes namespace isolation via: |
| 107 | +> - `ServiceAccount: ckp-runtime` with `automountServiceAccountToken: false` (kernel pods cannot reach the Kubernetes API) |
| 108 | +> - `NetworkPolicy: ckp-default-deny` denying all ingress and egress |
| 109 | +> - `NetworkPolicy: ckp-allow-nats` permitting egress to NATS service on port 4222 |
| 110 | +> - `NetworkPolicy: ckp-allow-dns` permitting egress to kube-dns |
| 111 | +> - `NetworkPolicy: ckp-allow-gateway` permitting ingress from the gateway namespace on port 80 |
| 112 | +> |
| 113 | +> Rationale: defence in depth. A compromised kernel pod cannot reach services outside the allowed egress list, cannot inspect cluster state via the Kubernetes API, and cannot accept traffic from outside its declared gateway. |
| 114 | +> |
| 115 | +> **`deploy.graph`** (between `deploy.auth` and `deploy.endpoint`) |
| 116 | +> |
| 117 | +> RDF materialisation. After all kernel resources exist, CK.Operator publishes kernel metadata, edges, and instance pointers as RDF triples to a SPARQL endpoint (reference implementation: Jena Fuseki, dataset `/ckp`). Each project's fleet lives in a named graph identified as `urn:ckp:fleet:{hostname}`. Graph materialisation is best-effort: `deploy.endpoint` verification MUST succeed even if the SPARQL endpoint is unreachable. |
| 118 | +> |
| 119 | +> Rationale: the ontological graph is the queryable index of fleet state alongside the Kubernetes API. |
| 120 | +
|
| 121 | +--- |
| 122 | +
|
| 123 | +## #16 — 18-module CK.Lib.Py + 12-module CK.Lib.Js: external SPEC treats as opaque |
| 124 | +
|
| 125 | +### v3.7 spec position (precise enumeration) |
| 126 | +
|
| 127 | +**CK.Lib.Py — 18 modules** (from `docs/v3.7/project.md:144-165`): |
| 128 | +
|
| 129 | +| # | Module | Ontology Class | Purpose | |
| 130 | +|---|---|---|---| |
| 131 | +| 1 | `processor.py` | `ckp:Kernel` | Base class for all kernel processors | |
| 132 | +| 2 | `events.py` | `ckp:Action` | Action handler decorator (`@on`) and typed event emission | |
| 133 | +| 3 | `instance.py` | `ckp:InstanceManifest`, `ckp:SealedInstance` | Instance lifecycle: create, seal, ledger, proof | |
| 134 | +| 4 | `ledger.py` | `ckp:LedgerEntry` | Kernel-wide append-only JSONL action log | |
| 135 | +| 5 | `schema.py` | `ckp:SealedInstance` validation | LinkML `ontology.yaml` loading and validation | |
| 136 | +| 6 | `context.py` | N/A | Three-loop-aware context builder | |
| 137 | +| 7 | `capacity.py` | N/A | Concurrency control via file-based capacity management | |
| 138 | +| 8 | `occurrent.py` | `ckp:Occurrent` (BFO:0000015) | Action substeps with PROV-O proof and hash chains | |
| 139 | +| 9 | `edges.py` | `ckp:Edge`, `ckp:RelationshipType` | Edge subscription materialisation for NATS | |
| 140 | +| 10 | `actions.py` | `ckp:Action`, `rbac.ttl` | Action type resolution, composition, RBAC | |
| 141 | +| 11 | `dispatch.py` | `ckp:EdgeCommunication` | Local inter-kernel action dispatch and FIFO queue | |
| 142 | +| 12 | `serve.py` | `ckp:WebServing`, `ckp:APIServing` | FastAPI HTTP server wrapping `@on` handlers | |
| 143 | +| 13 | `auth.py` | `rbac.ttl` | Keycloak JWT verification + API token fallback | |
| 144 | +| 14 | `urn.py` | CKP URN scheme | URN parser, validator, builder (17 entity types) | |
| 145 | +| 15 | `prov.py` | `prov:Activity` | PROV-O session recording for any kernel | |
| 146 | +| 16 | `execution.py` | `ckp:ProofRecord`, `ckp:ProofCheck` | Multi-step execution proofs with hash chains | |
| 147 | +| 17 | `entities.py` | N/A | In-memory entity store with code-based lookup | |
| 148 | +| 18 | `nats_loop.py` | `ckp:NATSListening` | NATS subscriber loop implementing CK processing cycle | |
| 149 | +
|
| 150 | +**CK.Lib.Js — 12 modules** (from `docs/v3.7/project.md:249-262`): |
| 151 | +
|
| 152 | +| # | Module | Export Path | Ontology Grounding | Purpose | |
| 153 | +|---|---|---|---|---| |
| 154 | +| 1 | `ck-client.js` | `.` / `./client` | `ckp:NATSBrowserClient` | Core NATS WSS client; connection, auth, send, subscribe | |
| 155 | +| 2 | `ck-page.js` | `./page` | `ckp:InlineKernel` | Page harness; auto-detects kernel, renders chrome | |
| 156 | +| 3 | `ck-bus.js` | `./bus` | `ckp:EdgeCommunication` | In-browser event bus for decoupled component communication | |
| 157 | +| 4 | `ck-kernel.js` | `./kernel` | — | Kernel-specific CSS variables and theming | |
| 158 | +| 5 | `ck-registry.js` | `./registry` | `ckp:Project` | Kernel registry for multi-kernel page composition | |
| 159 | +| 6 | `ck-runtime.js` | `./runtime` | — | Client-side runtime utilities | |
| 160 | +| 7 | `ck-materializer.js` | `./materializer` | — | Client-side resource materialisation | |
| 161 | +| 8 | `ck-store.js` | `./store` | — | Client-side state persistence (localStorage + server filer) | |
| 162 | +| 9 | `ck-shapes.js` | `./shapes` | `sh:NodeShape` | SHACL shape rendering and validation UI | |
| 163 | +| 10 | `ck-anim.js` | `./anim` | — | Animation engine for kernel visualisations | |
| 164 | +| 11 | `ck-anim-grammar.js` | (internal) | — | Animation grammar parser | |
| 165 | +| 12 | `ck-sound.js` | `./sound` | — | Web Audio API integration | |
| 166 | +
|
| 167 | +### Discrepancy with external SPEC |
| 168 | +
|
| 169 | +External `SPEC.CK.NEW` treats both `CK.Lib.Py` and `CK.Lib.Js` as opaque — referring to them by name without enumerating modules. This means any divergence in module count or naming between v3.7 and `SPEC.CK.NEW` is silent: an implementer cannot conform to one and validate against the other. |
| 170 | +
|
| 171 | +### Recommended insertion into SPEC.CK.NEW |
| 172 | +
|
| 173 | +Add (or replace) the libraries section with citation-style references back to v3.7: |
| 174 | +
|
| 175 | +> **CK.Lib.Py** — the canonical Python runtime library; npm-equivalent package `conceptkernel` on PyPI. Conformant implementations MUST provide all 18 modules listed in the v3.7 specification, with the ontology class bindings declared per `docs/v3.7/project.md:144-165`. The 18 modules are: `processor`, `events`, `instance`, `ledger`, `schema`, `context`, `capacity`, `occurrent`, `edges`, `actions`, `dispatch`, `serve`, `auth`, `urn`, `prov`, `execution`, `entities`, `nats_loop`. |
| 176 | +> |
| 177 | +> **CK.Lib.Js** — the canonical JavaScript client library; npm package `@conceptkernel/cklib`. Conformant implementations MUST provide all 12 modules listed in the v3.7 specification, with export paths and ontology grounding per `docs/v3.7/project.md:249-262`. The 12 modules are: `ck-client`, `ck-page`, `ck-bus`, `ck-kernel`, `ck-registry`, `ck-runtime`, `ck-materializer`, `ck-store`, `ck-shapes`, `ck-anim`, `ck-anim-grammar`, `ck-sound`. |
| 178 | +
|
| 179 | +### Verification step (do this on the actual code, separate from the spec edit) |
| 180 | +
|
| 181 | +The 18+12 module list above is taken from `project.md`. Before relying on it, verify against the live packages: |
| 182 | +
|
| 183 | +```bash |
| 184 | +# Python (in a checkout that has cklib/) |
| 185 | +python -c "import cklib, pkgutil; print(sorted(m.name for m in pkgutil.iter_modules(cklib.__path__)))" |
| 186 | +
|
| 187 | +# JS (in a checkout with @conceptkernel/cklib installed) |
| 188 | +node -e "console.log(Object.keys(require('@conceptkernel/cklib/package.json').exports))" |
| 189 | +``` |
| 190 | +
|
| 191 | +If the actual exports differ, treat that as a separate bug and reconcile both v3.7 docs and the external spec to the live truth. |
| 192 | +
|
| 193 | +--- |
| 194 | +
|
| 195 | +## #24 — Operator-implementation drift (code briefs, not spec changes) |
| 196 | +
|
| 197 | +These three items are runtime/code bugs in `CK.Operator`. Each violates a clear v3.7 spec contract; the spec is correct, the code disagrees. Hand these as discrete dev tickets. |
| 198 | +
|
| 199 | +### #24.a — RO-FS violation: `action.save()` writes to a ReadOnly organ |
| 200 | +
|
| 201 | +**Reported**: `action.save()` writes proof artefacts to `/ck/CK.Operator/storage/proof/`. `storage/` is also a stale path (renamed `data/` in v3.6); the more important defect is that proofs are landing in the **CK** organ (ReadOnlyMany at runtime) rather than the **DATA** organ (ReadWriteMany). |
| 202 | +
|
| 203 | +**Spec contract violated**: |
| 204 | +
|
| 205 | +| Citation | Statement | |
| 206 | +|---|---| |
| 207 | +| `docs/v3.7/proof.md:256` | "Action proofs MUST be stored in the kernel's `data/proof/` directory as `proof-{action}-{timestamp}.json`." | |
| 208 | +| `docs/v3.7/proof.md:281` | Conformance: "Proofs MUST be stored in `data/proof/` — REQUIRED" | |
| 209 | +| `docs/v3.7/three-loops.md`, `docs/v3.7/isolation.md` | CK organ is ReadOnlyMany at runtime, no exceptions (post-v3.7 retirement of `serving.json`). | |
| 210 | +
|
| 211 | +**Code-side fix brief**: |
| 212 | +
|
| 213 | +> In CK.Operator, change `action.save()` to write to `/ck/CK.Operator/data/proof/proof-{action}-{timestamp}.json` instead of `/ck/CK.Operator/storage/proof/`. The current path is wrong on both axes: |
| 214 | +> - It targets the **CK organ**, which is mounted ReadOnlyMany at runtime (post-v3.7 retirement of `serving.json` there are no write-through exceptions). The current `EROFS` failure is the kernel's defence working correctly. |
| 215 | +> - It uses the legacy `storage/` directory name; v3.7 renamed this to `data/`. |
| 216 | +> |
| 217 | +> The DATA organ is mounted ReadWriteMany; `data/proof/` is the canonical proof location per `docs/v3.7/proof.md:256,281`. After the fix, proofs are sealed instances and inherit the standard sealed-instance immutability contract documented in `docs/v3.7/data-loop.md`. |
| 218 | +
|
| 219 | +### #24.b — Hostname synthesis bug |
| 220 | +
|
| 221 | +**Reported**: a code path ignores `serving.hostname` (or `spec.hostname`) and synthesises a hostname from other fields. |
| 222 | +
|
| 223 | +**Spec contract violated**: |
| 224 | +
|
| 225 | +| Citation | Statement | |
| 226 | +|---|---| |
| 227 | +| `docs/v3.7/project.md` Required Fields table | `domain` (string, REQUIRED), `serving.subdomain` (string, REQUIRED). The `.ckproject` manifest declares serving identity. | |
| 228 | +| `docs/v3.7/operator.md:107` | CKProject CR example shows `spec.hostname: hello.tech.games` as a top-level required field. | |
| 229 | +| `docs/v3.7/crd.md:449` | CKProject CRD conformance: "`spec.hostname`, `spec.storage`, `spec.gateway.parentRef`, and `spec.versions` MUST be present — REQUIRED". | |
| 230 | +| `docs/v3.7/crd.md` CKProject schema | `spec.hostname` is the canonical fully-qualified hostname; `domain` and `serving.subdomain` are derivation sources, optional in the CR but required (in some form) in the manifest. | |
| 231 | +
|
| 232 | +**Code-side fix brief**: |
| 233 | +
|
| 234 | +> `spec.hostname` is the authoritative project hostname per the CKProject CRD schema (`docs/v3.7/crd.md` §CKProject CRD). CK.Operator MUST read it directly and use it for: |
| 235 | +> - DNS / serving subdomain |
| 236 | +> - Filer path prefix (`/ck-data/{hostname}/...`) |
| 237 | +> - Namespace naming (derived: `ck-{serving.subdomain}` where subdomain is the hostname's leftmost label, unless `serving.subdomain` is explicitly set) |
| 238 | +> - All gateway HTTPRoute hostnames |
| 239 | +> |
| 240 | +> If `spec.hostname` is absent, the reconcile MUST fail with a clear error before any resources are created, not silently synthesise a fallback. Synthesising hides operator-config errors and produces hostnames that will conflict with whatever `.ckproject` later declares. |
| 241 | +> |
| 242 | +> Spot-check after the fix: `kubectl get ckp -A -o jsonpath='{range .items[*]}{.metadata.name}{":"}{.spec.hostname}{" → ns="}{.status.namespace}{"\n"}{end}'` should show one-to-one alignment between `.spec.hostname`'s leftmost label and the namespace prefix. |
| 243 | +
|
| 244 | +### #24.c — Dual kopf handlers for the same CR |
| 245 | +
|
| 246 | +**Reported**: two kopf handlers fire on the same `CKProject` CR event. |
| 247 | +
|
| 248 | +**Spec contract violated** (interpretation, since the spec doesn't enumerate handler counts directly): |
| 249 | +
|
| 250 | +| Citation | Statement | |
| 251 | +|---|---| |
| 252 | +| `docs/v3.7/operator.md:212-217` | "Dual Control Plane: kopf + NATS" — two **entry points** (kopf CRD watch and NATS message listener) trigger the **same `reconcile()` function**. The dual entry refers to *transports*, not duplicated handlers on the same transport. | |
| 253 | +| `docs/v3.7/operator.md:33` | `kopf operator watching CKProject CR` is described as a single watcher. | |
| 254 | +| `docs/v3.7/changelog.md:59` | "kopf + NATS dual control plane" — explicitly two entry points triggering one `reconcile()`. | |
| 255 | +
|
| 256 | +The spec does not contemplate two kopf handlers competing for the same CR event, and the dual-control-plane design assumes a single `reconcile()` is the convergence point. Two handlers means non-deterministic ordering, possible double-creation, and split log/proof streams. |
| 257 | +
|
| 258 | +**Code-side fix brief**: |
| 259 | +
|
| 260 | +> Per `docs/v3.7/operator.md:212-217` and `changelog.md:59`, the kopf+NATS dual control plane is two **entry points** converging on a single `reconcile()` function. There should be exactly one kopf handler per CR kind: |
| 261 | +> - `@kopf.on.create('ck.tech.games', 'v1', 'ckprojects')` |
| 262 | +> - `@kopf.on.update('ck.tech.games', 'v1', 'ckprojects')` |
| 263 | +> - `@kopf.on.delete('ck.tech.games', 'v1', 'ckprojects')` |
| 264 | +> |
| 265 | +> All three must call into the same `reconcile()` function (with the action variant — `project.deploy`, `project.update`, `project.teardown` — selected by handler kind). The NATS listener calls the same `reconcile()` for the same actions; there is one convergence point. |
| 266 | +> |
| 267 | +> Audit step: `grep -rnE '@kopf\.on\.|kopf\.handler' <operator-src>` should produce one handler per (kind, verb), not multiple. If there are two `@kopf.on.create('ckprojects')` decorators in the codebase, that is the bug. |
| 268 | +
|
| 269 | +--- |
| 270 | +
|
| 271 | +## How to use this document |
| 272 | +
|
| 273 | +1. Treat each `### Recommended insertion into SPEC.CK.NEW` block (in #14, #15, #16) as paste-ready text for the external spec. |
| 274 | +2. Treat each `**Code-side fix brief**` block (in #24.a/b/c) as a paste-ready dev ticket description. |
| 275 | +3. The internal v3.7 drift noted in #15 (changelog 12-step breakdown without `deploy.security`) is a candidate for a small follow-up Pass on this site, separate from the external work. |
| 276 | +4. Once external reconciliations land in `SPEC.CK.NEW` and operator fixes land in `CK.Operator`, the corresponding tasks (#14, #15, #16, #24) can be closed. |
| 277 | +
|
| 278 | +This file is a working artefact, not a specification. Do not link it from any published CKP page. |
0 commit comments