feat(component)!: declared data extraction with typed cells and topology validation - #165
Merged
Merged
Conversation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…Data Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…art cell reset Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Migrate the extraction-and-guards example, custom-resource example, and e2e multi-resource test off the legacy WithDataExtractor closure API onto concepts.NewData cells with ExtractInto and WithDataGuard. Nothing outside pkg/ still uses the legacy API. BuildComponent now returns the shared cell alongside the component so tests can seed it before golden-file previews, since a mutation calling Require() never sees an extracted value when Preview() renders without a cluster. main.go prints Component.DataTopology() before reconciling. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
BREAKING CHANGE: free-form data extractors are removed. Declare writes with ExtractInto and reads with WithDataGuard or WithOptionalData instead. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The suspension path applies each managed resource through applyResources, which never ran declared data extractions. A suspended component whose consumer mutation calls Data.Require() therefore failed to reconcile: the producer's cell was cleared at the start of Reconcile and never refilled, so the component could never reach Suspended. applyResources now runs each resource's declared extractions immediately after a successful apply, in registration order, matching the reconcile path. Cells produced by read-only resources (not fetched while suspended) or by resources deleted on suspend stay absent, so readers of those must use Get rather than Require when the component can be suspended. The GoDoc on applyResources and Reconcile, and the suspension section of the component guide, now say so. Also addressed from the same review: - validateDataTopology used a plain nil comparison, which missed a typed-nil cell such as (*concepts.Data[string])(nil) held in a DataCell interface and then panicked in Name(). It now uses a reflective check mirroring isNilResource, so both forms surface as the intended build error. - Reconcile's numbered GoDoc steps did not mention the declared-cell reset the code performs first; it is now stated before step 1. - Data.Set's GoDoc called every manual call unsupported while the component guide documents seeding a cell in a test before a cluster-free preview. The one supported manual use is now named. - The data-validation section of the component guide did not mention that a resource behind a disabled GatedBy gate moves to the delete set at registration, so a cell it alone produced fails Build with the no-earlier-producer error. - Added a runtime test for the documented last-producer-wins behavior of repeated ExtractInto calls into one cell. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR replaces closure/pointer-based intra-component data sharing with a first-class “declared data” model: typed, presence-aware data cells with explicit producers (extractions) and consumers (guards/optional reads), validated at component build time and introspectable via a topology API.
Changes:
- Introduces
concepts.Data[T]cells plusDataProducer/DataConsumer/DataInspectorfor declared data flow and topology introspection. - Replaces
WithDataExtractorwithExtractInto(...), and adds declared read APIs (WithDataGuard,WithOptionalData) across the generic layer and many primitives. - Hardens reconciliation/suspension behavior by resetting declared cells per reconcile and running per-resource extractions during suspension applies; updates examples, docs, and tests accordingly.
Reviewed changes
Copilot reviewed 145 out of 145 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| pkg/primitives/unstructured/workload/resource.go | Forwards produced/consumed data topology from the generic base resource. |
| pkg/primitives/unstructured/workload/builder.go | Replaces extractor API with data guard/optional reads and ExtractInto. |
| pkg/primitives/unstructured/workload/builder_test.go | Adds tests for declared extraction and read declarations/guard reasons. |
| pkg/primitives/unstructured/task/resource.go | Adds DataProducer/DataConsumer forwarding for topology support. |
| pkg/primitives/unstructured/task/builder.go | Adds WithDataGuard/WithOptionalData and package-level ExtractInto. |
| pkg/primitives/unstructured/task/builder_test.go | Tests declared extraction plus guard/optional declarations. |
| pkg/primitives/unstructured/static/resource.go | Adds DataProducer/DataConsumer forwarding for topology support. |
| pkg/primitives/unstructured/static/builder.go | Adds WithDataGuard/WithOptionalData and package-level ExtractInto. |
| pkg/primitives/unstructured/static/builder_test.go | Tests declared extraction plus guard/optional declarations. |
| pkg/primitives/unstructured/integration/resource.go | Adds DataProducer/DataConsumer forwarding for topology support. |
| pkg/primitives/unstructured/integration/builder.go | Adds WithDataGuard/WithOptionalData and package-level ExtractInto. |
| pkg/primitives/unstructured/integration/builder_test.go | Tests declared extraction plus guard/optional declarations. |
| pkg/primitives/statefulset/resource.go | Adds ProducedData/ConsumedData to satisfy topology interfaces. |
| pkg/primitives/statefulset/resource_test.go | Removes legacy extractor-focused tests in favor of declared model elsewhere. |
| pkg/primitives/statefulset/builder.go | Replaces extractor API with guard/optional and ExtractInto. |
| pkg/primitives/statefulset/builder_test.go | Adds tests for declared extraction and declared reads. |
| pkg/primitives/serviceaccount/resource.go | Adds ProducedData/ConsumedData to satisfy topology interfaces. |
| pkg/primitives/serviceaccount/resource_test.go | Removes legacy ExtractData tests tied to the old extractor API. |
| pkg/primitives/serviceaccount/builder.go | Replaces extractor API with guard/optional and ExtractInto. |
| pkg/primitives/serviceaccount/builder_test.go | Adds tests for declared extraction and declared reads. |
| pkg/primitives/service/resource.go | Adds ProducedData/ConsumedData to satisfy topology interfaces. |
| pkg/primitives/service/resource_test.go | Removes legacy ExtractData tests tied to the old extractor API. |
| pkg/primitives/service/builder.go | Replaces extractor API with guard/optional and ExtractInto. |
| pkg/primitives/secret/resource.go | Adds ProducedData/ConsumedData to satisfy topology interfaces. |
| pkg/primitives/secret/resource_test.go | Removes legacy ExtractData tests tied to the old extractor API. |
| pkg/primitives/secret/observation_test.go | Migrates read-only observation→extraction test to declared extraction + cell. |
| pkg/primitives/secret/builder.go | Replaces extractor API with guard/optional and ExtractInto. |
| pkg/primitives/rolebinding/resource.go | Adds ProducedData/ConsumedData to satisfy topology interfaces. |
| pkg/primitives/rolebinding/resource_test.go | Removes legacy ExtractData tests tied to the old extractor API. |
| pkg/primitives/rolebinding/builder.go | Replaces extractor API with guard/optional and ExtractInto. |
| pkg/primitives/role/resource.go | Adds ProducedData/ConsumedData to satisfy topology interfaces. |
| pkg/primitives/role/resource_test.go | Removes legacy ExtractData tests tied to the old extractor API. |
| pkg/primitives/role/builder.go | Replaces extractor API with guard/optional and ExtractInto. |
| pkg/primitives/role/builder_test.go | Adds tests for declared extraction and declared reads. |
| pkg/primitives/replicaset/resource.go | Adds ProducedData/ConsumedData to satisfy topology interfaces. |
| pkg/primitives/replicaset/resource_test.go | Removes legacy ExtractData tests tied to the old extractor API. |
| pkg/primitives/replicaset/builder.go | Replaces extractor API with guard/optional and ExtractInto. |
| pkg/primitives/replicaset/builder_test.go | Adds tests for declared extraction and declared reads. |
| pkg/primitives/pvc/resource.go | Adds ProducedData/ConsumedData to satisfy topology interfaces. |
| pkg/primitives/pvc/resource_test.go | Removes legacy ExtractData tests tied to the old extractor API. |
| pkg/primitives/pvc/builder.go | Replaces extractor API with guard/optional and ExtractInto. |
| pkg/primitives/pv/resource.go | Adds ProducedData/ConsumedData to satisfy topology interfaces. |
| pkg/primitives/pv/resource_test.go | Removes legacy ExtractData tests tied to the old extractor API. |
| pkg/primitives/pv/builder.go | Replaces extractor API with guard/optional and ExtractInto. |
| pkg/primitives/pv/builder_test.go | Adds tests for declared extraction and declared reads. |
| pkg/primitives/pod/resource.go | Adds ProducedData/ConsumedData to satisfy topology interfaces. |
| pkg/primitives/pod/resource_test.go | Removes legacy ExtractData tests tied to the old extractor API. |
| pkg/primitives/pod/builder.go | Replaces extractor API with guard/optional and ExtractInto. |
| pkg/primitives/pod/builder_test.go | Adds tests for declared extraction and declared reads. |
| pkg/primitives/pdb/resource.go | Adds ProducedData/ConsumedData to satisfy topology interfaces. |
| pkg/primitives/pdb/resource_test.go | Removes legacy ExtractData tests tied to the old extractor API. |
| pkg/primitives/pdb/builder.go | Replaces extractor API with guard/optional and ExtractInto. |
| pkg/primitives/networkpolicy/resource.go | Adds ProducedData/ConsumedData to satisfy topology interfaces. |
| pkg/primitives/networkpolicy/resource_test.go | Removes legacy ExtractData tests tied to the old extractor API. |
| pkg/primitives/networkpolicy/builder.go | Replaces extractor API with guard/optional and ExtractInto. |
| pkg/primitives/job/resource.go | Adds ProducedData/ConsumedData to satisfy topology interfaces. |
| pkg/primitives/job/resource_test.go | Removes legacy ExtractData tests tied to the old extractor API. |
| pkg/primitives/job/builder.go | Replaces extractor API with guard/optional and ExtractInto. |
| pkg/primitives/job/builder_test.go | Adds tests for declared extraction and declared reads. |
| pkg/primitives/ingress/resource.go | Adds ProducedData/ConsumedData to satisfy topology interfaces. |
| pkg/primitives/ingress/resource_test.go | Removes legacy ExtractData tests tied to the old extractor API. |
| pkg/primitives/ingress/builder.go | Replaces extractor API with guard/optional and ExtractInto. |
| pkg/primitives/ingress/builder_test.go | Adds tests for declared extraction and declared reads. |
| pkg/primitives/hpa/resource.go | Adds ProducedData/ConsumedData to satisfy topology interfaces. |
| pkg/primitives/hpa/builder.go | Replaces extractor API with guard/optional and ExtractInto. |
| pkg/primitives/hpa/builder_test.go | Adds tests for declared extraction and declared reads. |
| pkg/primitives/deployment/resource.go | Adds ProducedData/ConsumedData to satisfy topology interfaces. |
| pkg/primitives/deployment/resource_test.go | Removes legacy ExtractData tests tied to the old extractor API. |
| pkg/primitives/deployment/builder.go | Replaces extractor API with guard/optional and ExtractInto. |
| pkg/primitives/deployment/builder_test.go | Adds tests for declared extraction and declared reads. |
| pkg/primitives/daemonset/resource.go | Adds ProducedData/ConsumedData to satisfy topology interfaces. |
| pkg/primitives/daemonset/resource_test.go | Removes legacy ExtractData tests tied to the old extractor API. |
| pkg/primitives/daemonset/builder.go | Replaces extractor API with guard/optional and ExtractInto. |
| pkg/primitives/daemonset/builder_test.go | Adds tests for declared extraction and declared reads. |
| pkg/primitives/cronjob/resource.go | Adds ProducedData/ConsumedData to satisfy topology interfaces. |
| pkg/primitives/cronjob/resource_test.go | Removes legacy ExtractData tests tied to the old extractor API. |
| pkg/primitives/cronjob/builder.go | Replaces extractor API with guard/optional and ExtractInto. |
| pkg/primitives/cronjob/builder_test.go | Adds tests for declared extraction and declared reads. |
| pkg/primitives/configmap/resource.go | Adds ProducedData/ConsumedData to satisfy topology interfaces. |
| pkg/primitives/configmap/resource_test.go | Removes legacy ExtractData tests tied to the old extractor API. |
| pkg/primitives/configmap/builder.go | Replaces extractor API with guard/optional and ExtractInto. |
| pkg/primitives/clusterrolebinding/resource.go | Adds ProducedData/ConsumedData to satisfy topology interfaces. |
| pkg/primitives/clusterrolebinding/builder.go | Replaces extractor API with guard/optional and ExtractInto. |
| pkg/primitives/clusterrole/resource.go | Adds ProducedData/ConsumedData to satisfy topology interfaces. |
| pkg/primitives/clusterrole/resource_test.go | Removes legacy ExtractData tests tied to the old extractor API. |
| pkg/primitives/clusterrole/builder.go | Replaces extractor API with guard/optional and ExtractInto. |
| pkg/primitives/clusterrole/builder_test.go | Adds tests for declared extraction and declared reads. |
| pkg/generic/resource_static_test.go | Updates generic resource tests to use declared extractions + cells. |
| pkg/generic/data.go | Adds the generic declared-extraction data model (DataExtraction, ExtractInto, WrapExtraction). |
| pkg/generic/callback_helpers.go | Removes now-obsolete WrapExtractor. |
| pkg/generic/builder_workload.go | Replaces WithDataExtractor with data guard/optional declarations for workloads. |
| pkg/generic/builder_task.go | Replaces WithDataExtractor with data guard/optional declarations for tasks. |
| pkg/generic/builder_static.go | Replaces WithDataExtractor with data guard/optional declarations for static resources. |
| pkg/generic/builder_static_test.go | Removes tests that only validated the old extractor registration. |
| pkg/generic/builder_integration.go | Replaces WithDataExtractor with data guard/optional declarations for integration resources. |
| pkg/generic/builder_base.go | Adds base-level validation for declared extractions and declared reads. |
| pkg/component/resource_options.go | Updates read-only absence semantics docs to reflect declared extraction. |
| pkg/component/create.go | Runs per-resource declared extraction during apply loop (notably used in suspension). |
| pkg/component/concepts/extractable.go | Re-documents DataExtractable as the runtime hook for declared extraction. |
| pkg/component/concepts/data.go | Introduces typed, presence-aware Data[T] cells and ErrDataNotExtracted. |
| pkg/component/concepts/data_test.go | Adds unit tests for cell presence/value semantics and errors. |
| pkg/component/concepts/data_inspector.go | Adds topology interfaces/types for data producers/consumers/edges. |
| pkg/component/component.go | Clears declared cells at reconcile start; documents suspension/extraction behavior. |
| pkg/component/builder.go | Adds build-time data topology validation and persists declared cells into the built component. |
| examples/extraction-and-guards/resources/testdata/secret.yaml | Updates golden output to include seeded/required db-host entry. |
| examples/extraction-and-guards/resources/secret.go | Migrates example Secret to data guard + Require()-consuming mutation. |
| examples/extraction-and-guards/resources/secret_test.go | Seeds cell to support cluster-free previews with Require() logic. |
| examples/extraction-and-guards/resources/configmap.go | Migrates example ConfigMap to declared extraction into a shared cell. |
| examples/extraction-and-guards/resources/configmap_test.go | Updates factory wiring to use a shared data cell in tests. |
| examples/extraction-and-guards/README.md | Rewrites example documentation around cells, declared extraction, and topology. |
| examples/extraction-and-guards/main.go | Prints declared data topology and updates narrative to declared extraction model. |
| examples/extraction-and-guards/app/testdata/component.yaml | Updates component golden output to reflect seeded db-host propagation. |
| examples/extraction-and-guards/app/controller.go | Returns shared cell from assembly for preview seeding and topology assertions. |
| examples/extraction-and-guards/app/component_test.go | Adds topology assertion and seeds cell for golden preview correctness. |
| examples/custom-resource/resources/certificate.go | Migrates unstructured example to declared extraction into a cell. |
| examples/custom-resource/README.md | Updates docs to refer to declared extraction rather than WithDataExtractor. |
| e2e/component/multi_resource_test.go | Migrates E2E test from shared-variable extraction to declared cell flow. |
| docs/primitives/unstructured.md | Updates unstructured primitive docs to use declared extraction and cells. |
| docs/primitives/serviceaccount.md | Updates ServiceAccount docs to use ExtractInto and cells. |
| docs/primitives/service.md | Updates Service docs to use ExtractInto and cells (including guidance). |
| docs/primitives/rolebinding.md | Updates RoleBinding docs to use ExtractInto and cells. |
| docs/primitives/role.md | Updates Role docs to use ExtractInto and cells. |
| docs/primitives/pvc.md | Updates PVC docs to use ExtractInto and cells (including guidance). |
| docs/primitives/pdb.md | Updates PDB docs to use ExtractInto and cells (including guidance). |
| docs/primitives/networkpolicy.md | Updates NetworkPolicy docs to use ExtractInto and cells. |
| docs/primitives/ingress.md | Updates Ingress docs to refer to ExtractInto for post-sync reads. |
| docs/primitives/clusterrolebinding.md | Updates ClusterRoleBinding docs to use ExtractInto and cells. |
| docs/primitives/clusterrole.md | Updates ClusterRole docs to use ExtractInto and cells. |
| docs/primitives.md | Updates primitives overview and examples to reflect declared data cells. |
extractResourceData already wraps failures with the resource identity, so the call sites in reconcileResources and applyResources produced the same message twice. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 145 out of 145 changed files in this pull request and generated no new comments.
Suppressed comments (3)
pkg/component/concepts/extractable.go:15
- The ExtractData method comment still describes the pre-cells behavior (“store the extracted data in its own fields or shared state”). With declared extractions/cells, this is misleading: ExtractData is an internal hook that runs declared extractions which write into data cells.
pkg/generic/builder_base.go:91 - WithDataGuard appends consumptions without deduplicating. If the same cell is declared multiple times (or first as optional and later as guarded), GuardStatus/DataTopology can end up with duplicated/contradictory entries and noisy reasons like
waiting for data "x", "x". Consider deduplicating by cell identity and upgrading optional→guarded when re-declared.
pkg/generic/builder_base.go:106 - WithOptionalData also appends consumptions without deduplicating. Declaring the same cell multiple times can lead to duplicated topology entries and (if later guarded) confusing mixed optional/guarded listings. Skipping cells that are already declared (either optional or guarded) keeps reasons/introspection deterministic.
The interface type comment was rewritten for declared extractions, but the method comment still described the old fields-or-shared-state contract. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
sourcehawk
added a commit
that referenced
this pull request
Aug 2, 2026
Update the distilled skill guidance, reviewer agent checklist, and docs command index for the declared data API merged in #165: concepts.Data cells, ExtractInto, WithDataGuard, WithOptionalData, build-time topology validation, DataTopology introspection, reconcile-start cell reset, and the suspension and preview caveats. Regenerate skill references via make sync-plugin. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
sourcehawk
added a commit
that referenced
this pull request
Aug 2, 2026
…#164) * feat(plugin): add ocf plugin and marketplace manifests Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(plugin): sync framework docs into skill references via make sync-plugin Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(plugin): building-components skill Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(component): state deletion ordering and required builder inputs Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(plugin): using-primitives skill Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(plugin): remove em dashes from using-primitives skill Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(plugin): custom-resource-wrappers skill Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(plugin): scope unstructured primitive claim to the wrapper reference Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(plugin): structuring-operators skill Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(plugin): testing-operators skill Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(plugin): drop unbacked integration-helpers claim from testing-operators description Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(plugin): /ocf:docs documentation lookup command Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(plugin): /ocf:new-component scaffolding command Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(plugin): /ocf:new-wrapper custom resource wrapper command Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(plugin): guidelines reviewer agent and /ocf:review command Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci: validate Claude plugin and check reference sync drift Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: maintainer rules and install instructions for the ocf Claude plugin Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci: fail plugin sync check on untracked reference drift Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(plugin): add marketplace description and drop stray checklist anchor Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci(plugin): pin nodejs via asdf in the plugin validation job The plugin job installed Claude Code with the runner's default Node toolchain while the sibling lint job pins nodejs from .tool-versions, so the job was exposed to CI-only failures when the ubuntu-latest default drifts. Install nodejs through asdf as the lint job does. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * feat(plugin): reconcile skills with declared data extraction API Update the distilled skill guidance, reviewer agent checklist, and docs command index for the declared data API merged in #165: concepts.Data cells, ExtractInto, WithDataGuard, WithOptionalData, build-time topology validation, DataTopology introspection, reconcile-start cell reset, and the suspension and preview caveats. Regenerate skill references via make sync-plugin. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
sourcehawk
added a commit
that referenced
this pull request
Aug 2, 2026
…ds (#168) PR #165 added ExtractInto to every primitive package but documented it in only 11 of the 22 per-kind pages. Add a Data Extraction section to the remaining kinds, matching the structure used by the pages updated in #165: the kind-specific ExtractInto signature with a realistic extraction target, and the WithDataGuard / WithOptionalData read declarations on the builder. Every snippet was compile checked against the primitive packages. Regenerated the plugin skill references with make sync-plugin. Claude-Session: https://claude.ai/code/session_01PhRYyAS9tcQcg6iZXMoVfd Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Intra-component data flow previously relied on closure variables: an extractor wrote to a captured pointer and a hand-written guard on a later resource tested it for emptiness. The framework could not see the dependency, zero values were ambiguous, and a registration reordering could silently block a component forever. This PR gives extracted data the same first-class treatment mutations already have: named, typed, presence-aware cells with declared writes and reads, validated at build time and exposed read-only for tests.
Breaking change:
WithDataExtractor(on the generic layer and all 25 primitive builders) andgeneric.WrapExtractorare removed outright, not deprecated. Migration: declare writes withExtractInto(builder, cell, fn)and reads withWithDataGuard(cell)orWithOptionalData(cell); read values withcell.Get()orcell.Require().Changes
concepts.Data[T]: a named cell withGet/Require/Set/Clearand a presence flag, so "not extracted yet" and "extracted as zero value" are distinct.Requirereturns an error wrappingconcepts.ErrDataNotExtracted; there is deliberately no panicking accessor.ExtractIntoon every primitive package (plusgeneric.ExtractIntoandgeneric.WrapExtractionfor custom wrapper authors). The framework stores the value and flips presence right after the resource is applied or fetched.WithDataGuardblocks the resource until every listed cell is set, with a framework-generated reason (waiting for data "db-host") that cannot drift from the dependency;WithOptionalDatadeclares a non-blocking read that stays visible to validation and introspection.component.Builder.Build()rejects a read with no producer registered strictly earlier and rejects two distinct cells sharing a name. Multiple producers are allowed; the last registered one wins.Requiredata can still suspend.Component.DataTopology()(concepts.DataInspector) returns one edge per cell with producers, guarded readers, and optional readers, mirroringconcepts.MutationInspector.examples/extraction-and-guardsrewritten as the showcase for the new API, including a topology assertion and the cell-seeding pattern for cluster-free golden previews;docs/guidelines.md,docs/component.md,docs/custom-resource.md, and the primitives docs rewritten around cells.Challenges
A mutation that calls
cell.Require()cannot render in a cluster-freePreview()because extraction never ran there. The example resolves this by having the assembly function return the cell so tests seed it before golden assertions;docs/component.mddocuments the pattern. Suspension had the same shape of problem (content mutations run while cells are empty), solved by running declared extractions per resource inside the suspension apply loop; cells produced by read-only or delete-on-suspend resources stay absent while suspended, and the docs say so.Related
make sync-pluginmachinery live only on that branch, so the spec'd plugin reference re-sync is a no-op here; the plugin skill references get refreshed when feat(plugin): ship the ocf Claude Code plugin for framework consumers #164 rebases onto this change.Testing
make allpasses (fmt, golangci-lint, prettier, full envtest-backed unit suite, example tests, example builds), andmake run-examplesexercises the rewritten example end to end including the printed topology. New coverage includes cell semantics, declared write and read mechanics on the generic layer and every primitive, all build-time validation rules, the reconcile-start reset observed at extraction time, generated guard reasons surfacing on the owner condition, last-producer-wins, topology edge ordering, and a suspension spec proving aRequire-consuming component reaches Suspended. The e2e suite was migrated to the new API and compiles clean; it was not run live because no kind cluster was available in this environment.🤖 Generated with Claude Code