hyperview view --> hyperview
This commit is contained in:
parent
50ac2b7b35
commit
0978302110
@ -60,7 +60,7 @@ npm run example-app
|
||||
|
||||
- `src/node.ts`: Main `RhizomeNode` class orchestrating all components
|
||||
- `src/delta.ts`: Delta data structures and conversion logic
|
||||
- `src/hyperview.ts`: Core hyperview view implementation
|
||||
- `src/hyperview.ts`: Core hyperview implementation
|
||||
- `src/collection-basic.ts`: Basic collection implementation
|
||||
- `src/http/api.ts`: REST API endpoints
|
||||
- `src/pub-sub.ts`: Network communication layer
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Test structure
|
||||
- before test, initialize node and hyperview view
|
||||
- before test, initialize node and hyperview
|
||||
- when test begins, create and ingest a series of deltas
|
||||
- instantiate a resolver, in this case using custom resolver plugins
|
||||
- call the resolver's initializer with the view
|
||||
|
@ -153,11 +153,11 @@ describe('Schema System', () => {
|
||||
expect(schemaRegistry.hasCircularDependencies()).toBe(true);
|
||||
});
|
||||
|
||||
test('should validate hyperview views against schemas', () => {
|
||||
test('should validate hyperviews against schemas', () => {
|
||||
const userSchema = CommonSchemas.User();
|
||||
schemaRegistry.register(userSchema);
|
||||
|
||||
// Create a valid hyperview view
|
||||
// Create a valid hyperview
|
||||
const validView: HyperviewViewOne = {
|
||||
id: 'user123',
|
||||
propertyDeltas: {
|
||||
@ -371,7 +371,7 @@ describe('Schema System', () => {
|
||||
expect(invalidEntities[0].entityId).toBe('user3');
|
||||
});
|
||||
|
||||
test('should apply schema to hyperview views', async () => {
|
||||
test('should apply schema to hyperviews', async () => {
|
||||
const userSchema = CommonSchemas.User();
|
||||
const collection = new TypedCollectionImpl<{
|
||||
name: string;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Tests for hyperview view compose() and decompose() bidirectional conversion
|
||||
* Ensures that deltas can be composed into hyperview views and decomposed back
|
||||
* Tests for hyperview compose() and decompose() bidirectional conversion
|
||||
* Ensures that deltas can be composed into hyperviews and decomposed back
|
||||
* to the original deltas with all pointer relationships preserved.
|
||||
*/
|
||||
|
||||
@ -31,7 +31,7 @@ describe('Hyperview View Compose/Decompose', () => {
|
||||
// Ingest the deltas
|
||||
nameDeltas.forEach(delta => node.hyperview.ingestDelta(delta));
|
||||
|
||||
// Compose hyperview view
|
||||
// Compose hyperview
|
||||
const composed = node.hyperview.compose(['alice']);
|
||||
const aliceView = composed['alice'];
|
||||
|
||||
|
@ -180,7 +180,7 @@ describe('Negation System', () => {
|
||||
});
|
||||
|
||||
describe('Hyperview View Integration', () => {
|
||||
test('should filter negated deltas in hyperview views', () => {
|
||||
test('should filter negated deltas in hyperviews', () => {
|
||||
// Create original delta
|
||||
const originalDelta = createDelta('user1', 'host1')
|
||||
.setProperty('user123', 'name', 'Alice')
|
||||
|
@ -6,7 +6,7 @@ import {createDelta} from '@src/core/delta-builder';
|
||||
describe('Hyperview', () => {
|
||||
const node = new RhizomeNode();
|
||||
|
||||
test('creates a hyperview view of keanu as neo in the matrix', () => {
|
||||
test('creates a hyperview of keanu as neo in the matrix', () => {
|
||||
const delta = createDelta('a', 'h')
|
||||
.addPointer('actor', 'keanu', 'roles')
|
||||
.addPointer('role', 'neo', 'actor')
|
||||
|
@ -39,7 +39,7 @@ class Summarizer extends Lossy<Summary> {
|
||||
|
||||
reducer(acc: Summary, cur: HyperviewViewOne): Summary {
|
||||
this.debug(`Processing view for entity ${cur.id} (referenced as: ${cur.referencedAs?.join(', ')})`);
|
||||
this.debug(`hyperview view:`, JSON.stringify(cur));
|
||||
this.debug(`hyperview:`, JSON.stringify(cur));
|
||||
|
||||
if (cur.referencedAs?.includes("role")) {
|
||||
this.debug(`Found role entity: ${cur.id}`);
|
||||
|
@ -61,7 +61,7 @@ describe('Nested Object Resolution', () => {
|
||||
.buildV1();
|
||||
node.hyperview.ingestDelta(friendshipDelta);
|
||||
|
||||
// Get Alice's hyperview view
|
||||
// Get Alice's hyperview
|
||||
const aliceViews = node.hyperview.compose(['alice']);
|
||||
const aliceView = aliceViews['alice'];
|
||||
|
||||
|
@ -103,7 +103,7 @@ classDiagram
|
||||
- Represents atomic changes in the system
|
||||
- Contains pointers to entities and their properties
|
||||
|
||||
3. **Hyperview**: Manages the hyperview view of data
|
||||
3. **Hyperview**: Manages the hyperview of data
|
||||
- Maintains the complete history of deltas
|
||||
- Provides methods to view and compose entity states
|
||||
|
||||
|
@ -10,7 +10,7 @@ The `CustomResolver` class is the main entry point for the Custom Resolver syste
|
||||
class CustomResolver {
|
||||
/**
|
||||
* Creates a new CustomResolver instance
|
||||
* @param view The hyperview view to resolve
|
||||
* @param view The hyperview to resolve
|
||||
* @param config Plugin configuration
|
||||
*/
|
||||
constructor(
|
||||
@ -48,7 +48,7 @@ class CustomResolver {
|
||||
Creates a new instance of the CustomResolver.
|
||||
|
||||
**Parameters:**
|
||||
- `view: HyperviewView` - The hyperview view containing the data to resolve
|
||||
- `view: HyperviewView` - The hyperview containing the data to resolve
|
||||
- `config: ResolverConfig` - Configuration object mapping property IDs to their resolver plugins
|
||||
|
||||
**Example:**
|
||||
@ -148,7 +148,7 @@ The resolver may throw the following errors:
|
||||
import { CustomResolver, LastWriteWinsPlugin } from './resolver';
|
||||
import { HyperviewView } from '../hyperview-view';
|
||||
|
||||
// Create a hyperview view with some data
|
||||
// Create a hyperview with some data
|
||||
const view = new HyperviewView();
|
||||
// ... add data to the view ...
|
||||
|
||||
|
@ -26,7 +26,7 @@ import { CustomResolver } from '../src/views/resolvers/custom-resolvers';
|
||||
import { LastWriteWinsPlugin } from '../src/views/resolvers/custom-resolvers/plugins';
|
||||
import { Hyperview } from '../src/views/hyperview';
|
||||
|
||||
// Create a hyperview view
|
||||
// Create a hyperview
|
||||
const hyperview = new Hyperview();
|
||||
|
||||
// Create a resolver with a last-write-wins strategy
|
||||
@ -34,7 +34,7 @@ const resolver = new CustomResolver(hyperview, {
|
||||
myProperty: new LastWriteWinsPlugin()
|
||||
});
|
||||
|
||||
// Process updates through the hyperview view
|
||||
// Process updates through the hyperview
|
||||
// hyperview.applyDelta(delta);
|
||||
|
||||
// Get resolved values for specific entities
|
||||
|
@ -18,7 +18,7 @@ type User = {
|
||||
(async () => {
|
||||
const rhizomeNode = new RhizomeNode();
|
||||
|
||||
// Enable API to read hyperview view
|
||||
// Enable API to read hyperview
|
||||
rhizomeNode.httpServer.httpApi.serveHyperview();
|
||||
|
||||
const users = new BasicCollection("user");
|
||||
|
@ -17,7 +17,7 @@ Phase 4 recognizes that in Rhizome, **deltas ARE relationships**. Instead of add
|
||||
- **All tests passing**: 21/21 suites, 183/183 tests (100%)
|
||||
- **Delta system**: Fully functional with pointers expressing relationships
|
||||
- **Negation system**: Can invalidate deltas (and thus relationships)
|
||||
- **Query system**: Basic traversal of hyperview views
|
||||
- **Query system**: Basic traversal of hyperviews
|
||||
- **Schema system**: Can describe entity structures
|
||||
- **Resolver system**: Application-level interpretation of deltas
|
||||
|
||||
|
@ -19,7 +19,7 @@ The rhizome-node implementation demonstrates strong alignment with core spec con
|
||||
- **Tests**: Good coverage of basic transformation, filtering by creator/host
|
||||
|
||||
3. **Lossy Views**
|
||||
- **Spec**: Compression of hyperview views using resolution strategies
|
||||
- **Spec**: Compression of hyperviews using resolution strategies
|
||||
- **Implementation**: Initializer/reducer/resolver pattern provides flexibility
|
||||
- **Tests**: Domain-specific example (Role/Actor/Film) demonstrates concept
|
||||
|
||||
|
14
spec.md
14
spec.md
@ -8,11 +8,11 @@
|
||||
* a `primitive` is a literal string, number or boolean value whose meaning is not tied up in its being a reference to a larger whole.
|
||||
* An `object` is a composite object whose entire existence is encoded as the set of deltas that reference it. An object is identified by a unique `reference`, and every delta that includes that `reference` is asserting a claim about some property of that object.
|
||||
* A `negation` is a specific kind of delta that includes a pointer with the name `negates`, a `target` reference to another delta, and a `context` called `negated_by`.
|
||||
* a `schema` represents a template by which an `object` can be compiled into a `hyperview view`. A schema specifies which properties of that object are included, and it specifies schemas for the objects references by the deltas within those properties. A schema must terminate in primitive schemas to avoid an infinite regress.
|
||||
* For instance, a `hyperview view` "User" of a user may include references to friends. If those friends are in turn encoded as instances of the "User" schema then all of *their* friends would be fully encoded, etc.
|
||||
* a `schema` represents a template by which an `object` can be compiled into a `hyperview`. A schema specifies which properties of that object are included, and it specifies schemas for the objects references by the deltas within those properties. A schema must terminate in primitive schemas to avoid an infinite regress.
|
||||
* For instance, a `hyperview` "User" of a user may include references to friends. If those friends are in turn encoded as instances of the "User" schema then all of *their* friends would be fully encoded, etc.
|
||||
* This could lead to circular references and arbitrarily deep nesting, which runs into the problem of "returning the entire graph". So our schema should specify, for instance, that the "friends" field apply the "Summary" schema to referenced users rather than the "User" schema, where the "Summary" schema simply resolves to username and photo.
|
||||
* A `hyperview view` is a representation of an `object` that includes a full inventory of all of the deltas that compose that object. So for instance, a hyperview view of the object representing the user "Alice" might include `alice.name`, which contains an array of all deltas with a pointer whose `target` is the ID of Alice and whose context is `name`. Such deltas would likely include a second pointer with the name `name` and the target a primitive string "Alice", for instance.
|
||||
* A `hyperview view` may also include nested delta/object layering. Consider `alice.friends`, which would include all deltas asserting friendship between Alice and some other person. Each such delta would reference a different friend object. In a hyperview view, these references would be expanded to contain hyperview views of those friends. Schemas, as defined above, would be applied to constrain tree depth and avoid infinite regress.
|
||||
* A `view view` is a compression of a `hyperview view` that removes delta information and flattens the structure into a standard domain object, typically in JSON. So instead of `alice.name` resolving to a list of deltas that assert the object's name it might simply resolve to `"alice"`.
|
||||
* Note that in a hyperview view any property of an object necessarily resolves to a set of deltas, even if it's an empty set, because we cannot anticipate how many deltas exist that assert values on that context.
|
||||
* In collapsing a hyperview view into a view view we may specify `resolution strategies` on each field of the schema. A resolution strategy takes as input the set of all deltas targeting that context and returns as output the value in the view view. So if we have 15 deltas asserting the value for an object's name, our resolution strategy may simply say "return the target of the `name` pointer associated with the most recent delta", or it may say "return an array of names". If the value is numeric it may say "take the max" or "take the min" or "take the average".
|
||||
* A `hyperview` is a representation of an `object` that includes a full inventory of all of the deltas that compose that object. So for instance, a hyperview of the object representing the user "Alice" might include `alice.name`, which contains an array of all deltas with a pointer whose `target` is the ID of Alice and whose context is `name`. Such deltas would likely include a second pointer with the name `name` and the target a primitive string "Alice", for instance.
|
||||
* A `hyperview` may also include nested delta/object layering. Consider `alice.friends`, which would include all deltas asserting friendship between Alice and some other person. Each such delta would reference a different friend object. In a hyperview, these references would be expanded to contain hyperviews of those friends. Schemas, as defined above, would be applied to constrain tree depth and avoid infinite regress.
|
||||
* A `view view` is a compression of a `hyperview` that removes delta information and flattens the structure into a standard domain object, typically in JSON. So instead of `alice.name` resolving to a list of deltas that assert the object's name it might simply resolve to `"alice"`.
|
||||
* Note that in a hyperview any property of an object necessarily resolves to a set of deltas, even if it's an empty set, because we cannot anticipate how many deltas exist that assert values on that context.
|
||||
* In collapsing a hyperview into a view view we may specify `resolution strategies` on each field of the schema. A resolution strategy takes as input the set of all deltas targeting that context and returns as output the value in the view view. So if we have 15 deltas asserting the value for an object's name, our resolution strategy may simply say "return the target of the `name` pointer associated with the most recent delta", or it may say "return an array of names". If the value is numeric it may say "take the max" or "take the min" or "take the average".
|
@ -71,7 +71,7 @@ export class TypedCollectionImpl<T extends Record<string, unknown>>
|
||||
|
||||
// Validate an entity against the schema
|
||||
validate(entity: T): SchemaValidationResult {
|
||||
// Convert entity to a mock hyperview view for validation
|
||||
// Convert entity to a mock hyperview for validation
|
||||
const mockHyperviewView: HyperviewViewOne = {
|
||||
id: 'validation-mock',
|
||||
referencedAs: [],
|
||||
@ -88,7 +88,7 @@ export class TypedCollectionImpl<T extends Record<string, unknown>>
|
||||
return this.schemaRegistry.validate('validation-mock', this.schema.id, mockHyperviewView);
|
||||
}
|
||||
|
||||
// Apply schema to a hyperview view
|
||||
// Apply schema to a hyperview
|
||||
apply(view: HyperviewViewOne): SchemaAppliedView {
|
||||
return this.schemaRegistry.applySchema(view, this.schema.id, this.applicationOptions);
|
||||
}
|
||||
@ -202,7 +202,7 @@ export class TypedCollectionImpl<T extends Record<string, unknown>>
|
||||
}
|
||||
const hyperviewView = this.rhizomeNode.hyperview.compose(this.getIds());
|
||||
if (!hyperviewView) {
|
||||
debug(`No hyperview view found`)
|
||||
debug(`No hyperview found`)
|
||||
return [];
|
||||
}
|
||||
debug(`getValidEntities, hyperviewView: ${JSON.stringify(hyperviewView, null, 2)}`)
|
||||
|
@ -148,7 +148,7 @@ export class HttpApi {
|
||||
});
|
||||
});
|
||||
|
||||
// Get a hyperview view of a single domain entity
|
||||
// Get a hyperview of a single domain entity
|
||||
this.router.get('/hyperview/:id', (req: express.Request, res: express.Response) => {
|
||||
const {params: {id}} = req;
|
||||
const v = this.rhizomeNode.hyperview.compose([id]);
|
||||
|
@ -91,9 +91,9 @@ export class RhizomeNode {
|
||||
}: { syncOnStart?: boolean } = {}): Promise<void> {
|
||||
debug(`[${this.config.peerId}]`, 'Starting node (waiting for ready)...');
|
||||
|
||||
// Connect our hyperview view to the delta stream
|
||||
// Connect our hyperview to the delta stream
|
||||
this.deltaStream.subscribeDeltas(async (delta) => {
|
||||
// Ingest into hyperview view
|
||||
// Ingest into hyperview
|
||||
this.hyperview.ingestDelta(delta);
|
||||
|
||||
// Also store in persistent storage
|
||||
@ -150,11 +150,11 @@ export class RhizomeNode {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync existing hyperview view data to persistent storage
|
||||
* Sync existing hyperview data to persistent storage
|
||||
* Useful for migrating from memory-only to persistent storage
|
||||
*/
|
||||
async syncToStorage(): Promise<void> {
|
||||
debug(`[${this.config.peerId}]`, 'Syncing hyperview view to storage');
|
||||
debug(`[${this.config.peerId}]`, 'Syncing hyperview to storage');
|
||||
|
||||
const allDeltas = this.deltaStream.deltasAccepted;
|
||||
let synced = 0;
|
||||
|
@ -96,9 +96,9 @@ export class QueryEngine {
|
||||
const candidateEntityIds = this.discoverEntitiesBySchema(schemaId);
|
||||
debug(`Found ${candidateEntityIds.length} candidate entities for schema ${schemaId}`);
|
||||
|
||||
// 2. Compose hyperview views for all candidates
|
||||
// 2. Compose hyperviews for all candidates
|
||||
const allViews = this.hyperview.compose(candidateEntityIds, options.deltaFilter);
|
||||
debug(`Composed ${Object.keys(allViews).length} hyperview views`);
|
||||
debug(`Composed ${Object.keys(allViews).length} hyperviews`);
|
||||
|
||||
// 3. Apply JSON Logic filter if provided
|
||||
let filteredViews: HyperviewViewMany = allViews;
|
||||
@ -195,8 +195,8 @@ export class QueryEngine {
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply JSON Logic filter to hyperview views
|
||||
* This requires converting each hyperview view to a queryable object
|
||||
* Apply JSON Logic filter to hyperviews
|
||||
* This requires converting each hyperview to a queryable object
|
||||
*/
|
||||
private applyJsonLogicFilter(
|
||||
views: HyperviewViewMany,
|
||||
@ -215,7 +215,7 @@ export class QueryEngine {
|
||||
|
||||
for (const [entityId, view] of Object.entries(views)) {
|
||||
try {
|
||||
// Convert hyperview view to queryable object using schema
|
||||
// Convert hyperview to queryable object using schema
|
||||
const queryableObject = this.hyperviewViewToQueryableObject(view, schema);
|
||||
|
||||
// Apply JSON Logic filter
|
||||
@ -246,7 +246,7 @@ export class QueryEngine {
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a hyperview view to a queryable object based on schema
|
||||
* Convert a hyperview to a queryable object based on schema
|
||||
* Uses simple resolution strategies for now
|
||||
*/
|
||||
private hyperviewViewToQueryableObject(view: HyperviewViewOne, schema: ObjectSchema): Record<string, unknown> {
|
||||
@ -255,7 +255,7 @@ export class QueryEngine {
|
||||
_referencedAs: view.referencedAs
|
||||
};
|
||||
|
||||
// Convert each schema property from hyperview view deltas
|
||||
// Convert each schema property from hyperview deltas
|
||||
for (const [propertyId, propertySchema] of Object.entries(schema.properties)) {
|
||||
const deltas = view.propertyDeltas[propertyId] || [];
|
||||
|
||||
|
@ -480,7 +480,7 @@ export class DefaultSchemaRegistry implements SchemaRegistry {
|
||||
const referenceIds = this.extractReferenceIdsFromDelta(delta, parentEntityId);
|
||||
for (const referenceId of referenceIds) {
|
||||
try {
|
||||
// Get the referenced entity's hyperview view
|
||||
// Get the referenced entity's hyperview
|
||||
const referencedViews = hyperviewView.compose([referenceId]);
|
||||
const referencedView = referencedViews[referenceId];
|
||||
|
||||
|
@ -76,7 +76,7 @@ export interface SchemaApplicationOptions {
|
||||
strictValidation?: boolean;
|
||||
}
|
||||
|
||||
// Applied schema result - a hyperview view filtered through a schema
|
||||
// Applied schema result - a hyperview filtered through a schema
|
||||
export interface SchemaAppliedView {
|
||||
id: DomainEntityID;
|
||||
schemaId: SchemaID;
|
||||
|
@ -1,5 +1,5 @@
|
||||
// We have the hyperview transformation of the delta stream.
|
||||
// We want to enable transformations from the hyperview view,
|
||||
// We want to enable transformations from the hyperview,
|
||||
// into various possible "view" views that combine or exclude some information.
|
||||
|
||||
import Debug from 'debug';
|
||||
@ -49,7 +49,7 @@ export abstract class Lossy<Accumulator, Result = Accumulator> {
|
||||
const hyperviewPartial = this.hyperview.compose([entityId], combinedFilter);
|
||||
|
||||
if (!hyperviewPartial) {
|
||||
// This should not happen; this should only be called after the hyperview view has been updated
|
||||
// This should not happen; this should only be called after the hyperview has been updated
|
||||
console.error(`Hyperview view for entity ${entityId} not found`);
|
||||
return;
|
||||
}
|
||||
|
8
todo.md
8
todo.md
@ -12,7 +12,7 @@ This document tracks work needed to achieve full specification compliance, organ
|
||||
- [x] Add validation for pointer consistency
|
||||
|
||||
### 1.2 Complete Transaction Support ✅ (mostly)
|
||||
- [x] Implement transaction-based filtering in hyperview views
|
||||
- [x] Implement transaction-based filtering in hyperviews
|
||||
- [x] Add transaction grouping in delta streams
|
||||
- [x] Test atomic transaction operations
|
||||
- [ ] Add transaction rollback capabilities (deferred - not critical for spec parity)
|
||||
@ -29,7 +29,7 @@ This document tracks work needed to achieve full specification compliance, organ
|
||||
### 2.1 Negation Deltas ✅
|
||||
- [x] Implement negation delta type with "negates" pointer
|
||||
- [x] Add "negated_by" context handling
|
||||
- [x] Update hyperview view to handle negations
|
||||
- [x] Update hyperview to handle negations
|
||||
- [x] Update view resolvers to respect negations
|
||||
- [x] Add comprehensive negation tests
|
||||
|
||||
@ -50,7 +50,7 @@ This document tracks work needed to achieve full specification compliance, organ
|
||||
|
||||
### 3.1 Query Engine Foundation ✅
|
||||
- [x] Implement JSON Logic parser (using json-logic-js)
|
||||
- [x] Create query planner for hyperview views
|
||||
- [x] Create query planner for hyperviews
|
||||
- [x] Add query execution engine (QueryEngine class)
|
||||
- [x] Implement schema-driven entity discovery
|
||||
- [x] Enable the skipped query tests
|
||||
@ -91,7 +91,7 @@ This document tracks work needed to achieve full specification compliance, organ
|
||||
|
||||
### 4.4 Schema-as-Deltas (Meta-Schema System)
|
||||
- [ ] Define schema entities that are stored as deltas in the system
|
||||
- [ ] Implement schema queries that return schema instances from hyperview views
|
||||
- [ ] Implement schema queries that return schema instances from hyperviews
|
||||
- [ ] Create schema evolution through delta mutations
|
||||
- [ ] Add temporal schema queries (schema time-travel)
|
||||
- [ ] Build schema conflict resolution for competing schema definitions
|
||||
|
Loading…
x
Reference in New Issue
Block a user