`nexyron.feature_register`
Generic Description
nexyron.feature_register registers or replaces one feature definition.
CALL nexyron.procedures()
YIELD name, description, parameters, output_columns
WHERE name = 'nexyron.feature_register'
RETURN name, description, parameters, output_columns
Abstraction-platform registry procedures create, list, read, and inspect named contracts such as abstractions, features, datasets, snapshots, models, policies, interventions, scenarios, and split policies.
Consumer-Level Explanation
This procedure is part of the abstraction catalog contract layer. Use it when you want to define a named feature calculation that other runtime procedures can execute for abstraction subjects.
Parameters
name: Feature name Required.abstraction: Owning abstraction name. Required.description: Optional human-readable feature intent.query: Required stored single-subject Cypher. It must returnsubject_idandvalue.output_type: Optional value type. UseNUMBER,TEXT, orBOOLEAN.feature_role: Optional ML role for the feature. Usepredictorfor ordinary input features,targetfor the supervised outcome or label to predict, andclustering_inputfor future unsupervised segmentation inputs. Defaults topredictor.cascade_refresh: When true, immediately refresh dependent materialized snapshots and datasets after replacing this feature Optional.
Output Columns
nameabstractionsubject_typeentity_labelgrainoutput_typeas_of_moderefresh_modelookback_msmaterializedversionstatusdependenciestagsqueryfeature_roledescription
Example Contract Prerequisite
The executable Cypher blocks on this page query nexyron.procedures() so they work in an empty database and stay synchronized with the live procedure registry. A direct CALL nexyron.feature_register(...) requires the named abstraction contracts, artifacts, features, snapshots, datasets, models, or policies referenced by that call to exist first; otherwise the runtime correctly fails with an unknown-contract error rather than inventing state.
Conceptual Explanation
The important thing about nexyron.feature_register is that a feature query is now best modeled as a single-subject runtime contract. The owning abstraction defines the full virtual subject set. The feature query accepts one subject from that set through $subject_id, computes one parameter or statistic for that subject, and returns subject_id and value.
Observed-data feature contracts are generated by the post-ingest Rust abstraction generator. Knowledge extraction can add abstraction knowledge, but it does not author observed-data feature contracts.
Feature definitions also carry an ML role. Most features are predictor inputs. A target feature is the supervised outcome or label that downstream model training should predict for the owning abstraction. Generated target features must be target-shaped: BOOLEAN where possible, otherwise a NUMBER constrained to a 0..1 probability, propensity, or bounded score. Nexyron keeps at most one target feature per abstraction: registering a new target for the same abstraction demotes the previous target back to predictor. clustering_input is reserved for later unsupervised segmentation workflows and does not have the one-per-abstraction target rule.
Post-ingest feature generation records target evidence and prevents later predictor and clustering parameters from reusing the same source property, temporal stream, object index_path, relationship evidence, or aggregation/statistical family used by the target. This prevents target leakage while still allowing the Rust generator to build a broad feature surface from the ingested dataset.
The abstraction builder dry run and health check use that same contract. Nexyron samples up to ten subjects from the owning abstraction source query, substitutes each sampled subject into $subject_id, executes the resulting runtime calculation, and validates the returned subject_id and value columns. That means dry run failures should usually be fixed in the abstraction source query or in the feature's single-subject calculation, not by widening the feature into a full-dataset scan.
Abstraction Builder also validates Cypher variable scope before executing sampled feature rows. WITH narrows the available variables, so a feature query that carries only subject_id forward and later returns avg(m.score) AS value is invalid because m is no longer in scope. Keep the node or relationship variable in every intervening WITH until its property is consumed, or aggregate/project the property before dropping the variable.
Weak value warnings are confirmed by deterministic dry-run diagnostics. If a feature query uses a relative current-time window, such as currenttimestamp() - 2592000000, validation can use the latest available temporal data for the relevant tag/category as context so historical datasets are not mistaken for empty live-current windows.
When a feature is registered manually or by the post-ingest Rust generator, it should compute a real value from direct properties, related nodes, relationship properties, containment paths, temporal histories and rollups, document-style fields, object index_paths, or existing abstraction/relation contracts. A contract that only returns $subject_id and null AS value is not a valid substitute.
Temporal streams are now mandatory planning evidence when they are reachable from the selected abstraction or from contained/member items. If a field is available both as a current node or edge property and as a temporal stream, the post-ingest deterministic generator keeps the temporal stream-derived surface and does not register static direct-property .current features. Stream-derived contracts should compute from nexyron.temporal_history, nexyron.temporal_rollup, declared object index_paths, event-time predicates, or ordered temporal sequences rather than shortcutting back to the current field. The Rust-side planner adds deterministic temporal parameters for eligible numeric streams, including latest plus 30-day and 90-day sum, min, max, avg, stddev_samp, trend, and cadence/inter-event-average metrics. Boolean streams get latest plus 30-day and 90-day counts. Text streams get latest only. For object-valued temporal streams, each declared index_path is exposed according to its inferred type under the same numeric, boolean, or text rules.
Persisted feature contracts should normally stay ASOF-free. Snapshot, materialize, and backfill execution can run the same stored query under an injected point-in-time context when an at timestamp is supplied. Under that context, direct access to a declared temporal property returns the latest scalar or object value at or before the ASOF timestamp, while nexyron.temporal_history and nexyron.temporal_rollup still return rows or buckets capped to that timestamp.
Relationship-backed abstractions must also plan graph-statistical and algorithmic feature families when the schema supports them. Useful examples include connected counts, ratios, rates, neighbor aggregates, relationship density, path or flow measures, community or cluster membership and size, community density, centrality, bridge-style scores, and cross-abstraction aggregates. The Rust-side planner adds basic connected-count features for selected abstraction relations and matching schema connections, after filtering out anything that overlaps the target footprint. These graph features are additions to scalar node, edge, and stream features; they should not replace direct stored values.
The removed Abstraction Builder LLM feature planner is not a production generation path. Persisted observed-data feature contracts should come from post-ingest Rust abstraction generation or explicit manual registry edits, and persisted feature queries must be complete runtime contracts without sample-only LIMIT clauses.
For stage and society features, containment is derived inside the feature query. When a stage feature needs actors, the query should bind the stage from $subject_id and match the schema-grounded actor relationship from that stage. When a society feature needs stages or actors, the query should bind the society from $subject_id, match contained stages, and then match actors through those stages. Runtime-injected containment-list placeholders are not part of the feature contract.
Containment lookup is source-bounded during dry run. Relation contracts must therefore expose source_id as an explicit alias expression that can be filtered before the query runs. A relation query that can only be checked by materializing all source-target pairs is rejected during Abstraction Builder validation rather than being allowed to time out later.
More Detailed Explanation
In practical queries, start by deciding the row grain you want after the call: one row per node, one row per path, one row per registry object, one row per artifact, or one row per summary. Then keep that grain explicit with YIELD and named projections. That is the difference between a useful planner-facing example and a vague call that downstream tooling cannot safely compose. For contract-driven abstraction procedures, the executable examples on these pages intentionally inspect procedure metadata unless the required named artifacts are created in the same example.
Advanced Example
CALL nexyron.procedures()
YIELD name, parameters, output_columns
WHERE name = 'nexyron.feature_register'
RETURN name,
[p IN parameters | p.name] AS parameter_names,
output_columns
ORDER BY name
Real Use Cases
- Register reusable member-retention contracts once, then let snapshots, datasets, models, and policies reference those names instead of duplicating raw Cypher in every workflow.
- Keep admin and product teams aligned around one shared abstraction contract for members, households, facilities, interventions, and churn labels during quarterly retraining cycles.
Real Limitations And Tradeoffs
- This surface is contract-driven. If the registered feature, snapshot, dataset, model, or policy definition is weak, the procedure will faithfully execute that weak contract rather than silently repairing it.
- A target feature is a registry annotation, not a model by itself. It tells supervised ML workflows which feature represents the label to predict; snapshots and datasets still need to include the feature names they use.
- Catalog procedures define or expose metadata. They do not by themselves build data, score models, or apply interventions.
- Generated feature contracts must use
$subject_idas the only runtime input and derive any related scope through Cypher patterns from that subject instead of scanning the full abstraction set. - Health checks sample abstraction subjects rather than proving every possible subject-feature value. They are meant to catch invalid contracts, missing columns, null-only calculations, subject mismatches, and obvious degenerate values before snapshot materialization.
- Feature generation is expected to produce intent-relevant business signals, not arbitrary schema transforms. Identifier mechanics such as id length, string length, or element-id length are rejected unless the user explicitly asks for text-quality or identifier-hygiene features.
- Feature values must be statistically or behaviorally meaningful model signals. Raw identity outputs such as the member itself,
subject_id,node_id,element_id, UUIDs, identifiers, or raw contact fields are rejected because they identify the row rather than measuring behavior, state, risk, context, containment, or another useful signal. - Name, date-of-birth, and birthdate fields are allowed feature candidates when they are schema-grounded and useful for the selected analysis. Categorical business names such as
package_name,plan_name,campaign_name,target_label,node_title,display_category,postcode, orpostal_regionremain valid when they identify the selected offer, plan, category, label, title, business state, or geographic bucket. - Raw contact details such as email addresses, phone numbers, and street addresses are rejected for the same reason. Contact-channel permission and preference fields are different: scalar values such as
email_opt_in,text_notifications, or opt-out status can be valid feature signals when they return consent, notification, or preference state rather than the raw contact value. - Automatic observed-data feature generation is owned by the post-ingest Rust abstraction generator. It uses schema evidence, temporal declarations, object
index_paths, and existing abstraction/relation contracts from the completed ingest. ASOFbelongs to execution context, not ordinary persisted feature text. Add explicitASOFonly for ad hoc point-in-time Cypher outside the registry; feature snapshots and backfills inject the point-in-time context around stored contracts.- Removing a feature is an explicit registry mutation through
nexyron.feature_delete, not an implicit result of a later ingest or registry edit omitting it. - Feature names are registry identifiers, not display labels. They should be safe field-like names such as
visit_count_30d,churn_risk_score, ormember.days_since_last_visit, because selector-style usage depends on names that can appear after a dot, such asactor(Member:<subject_id>).visit_count_30d. Names with spaces, colons, angle brackets, parentheses, slashes, punctuation, or title-style display text are invalid. - Relationship-derived feature scope is only as good as the schema-grounded path in the feature query and the owning abstraction's subject identity. If the stage-to-actor or society-to-stage path is missing or too broad, dry run and materialization will either fail or faithfully compute the wrong scope.
- Dry-run health checks report invalid source, relation, or feature diagnostics. They do not invoke the removed LLM repair path.