# History Schema — Composable History Primitive # KNO Schema Version: 0.5.1 # # Defines the composable building block for entity version history. # Aligns with: kno-foundational-principles.md § History Architecture # ============================================================================= # SCHEMA DECLARATION (RFC-007) # ============================================================================= $schema: kno@0.0.9 # ============================================================================= # IDENTITY # ============================================================================= id: 01KGK3V73KF7SKEGF4NTX20KV9 slug: history-schema type: spec version: 0.3.0 # ============================================================================= # STANDARD TIER # ============================================================================= title: "History Schema" purpose: "Define the composable building block for entity version history" # ============================================================================= # RICH TIER — Relationships (Edge Maximization) # ============================================================================= provenance: origin: id: 01KGK3V73KF7SKEGF4NTX20KV9 timestamp: "2026-02-04T01:47:56Z" tool: manual-migration taxonomy: topics: - history - versioning - temporal - provenance - schema-composition keywords: - history - version - created - modified - changelog - temporal - audit relationships: depends_on: - xri: "kno://specs/kno-spec" reason: "Defines the kno@0.0.9 schema this conforms to" related_to: - xri: "kno://specs/identity-schema" reason: "Sibling composable primitive" - xri: "kno://specs/quality-schema" reason: "Sibling composable primitive" - xri: "kno://concepts/provenance" reason: "Distinct but related concern" enables: - xri: "kno://specs/document-schema" reason: "Base type that composes this" - xri: "kno://specs/spec-schema" reason: "Domain schema with version tracking" - xri: "kno://specs/rfc-schema" reason: "Domain schema with revision history" - xri: "kno://services/vcs-backend" reason: "Defines the pluggable contract for VCS backend implementations" implements: - xri: "kno://principles/P9" reason: "Temporal/Historical principle" - xri: "kno://principles/VCS-Mandatory-Rule" reason: "Defines VCS recording requirement enforced via depth_policy" quality: completeness: 0.85 last_reviewed: "2026-02-18" review_status: draft reviewed_by: "claude" # ============================================================================= # HISTORY (P9 Temporal — self-referential!) # ============================================================================= _history: version: 4 created: "2026-01-06T12:00:00Z" created_by: "claude" modified: "2026-02-21T00:00:00Z" modified_by: "claude" # ============================================================================= # SPECIFICATION CONTENT # ============================================================================= spec: status: Draft description: | History is a **composable primitive** — a building block that provides version tracking fields for any .kno entity. **P9 (Temporal/Historical):** Understanding HOW knowledge evolved is often as valuable as the current state. Entities contain their history. **Bedrock Reference:** kno-foundational-principles.md § History Architecture This schema defines: - **_history**: Lightweight metadata block for simple entities - **policy**: History retention strategy (full, hybrid, changelog, external, none) - **embedded**: Version snapshots stored within the container - **external**: Reference to external VCS for deep history - **changelog**: Human-readable change summaries ## History vs Provenance These are DISTINCT concerns (DR-002): | Concern | Answers | Schema | |----------------|--------------------------------------|-------------| | **History** | How did this entity evolve over time?| history-schema.kno | | **Provenance** | Where did this entity come from? | provenance.kno | History tracks VERSION LINEAGE; Provenance tracks ORIGIN and OWNERSHIP. ## History Architecture (from bedrock) | Policy | Embedded | External | Use Case | | ----------- | --------------- | ----------------- | --------------------------------------- | | `full` | All versions | None | Specifications, audit-critical entities | | `hybrid` | Last N versions | Older in .kno VCS | Most entities (default retention: 10) | | `changelog` | Summaries only | None | Low-audit entities | | `external` | None | All in .kno VCS | Large/binary entities | | `none` | None | None | Ephemeral scratch entities (never in Hive) | ## VCS-Mandatory Rule **Bedrock Reference:** kno-foundational-principles.md § VCS-Mandatory Rule Every entity stored in the Hive MUST be recorded in a compliant VCS backend. The `depth_policy` controls HOW MUCH history is embedded in the container, but VCS recording itself is non-negotiable for any entity that reaches the Hive. | depth_policy | VCS Recording | Notes | | ------------ | ------------- | ---------------------------------------- | | `full` | Required | All versions embedded AND in VCS | | `hybrid` | Required | Recent embedded, all in VCS | | `changelog` | Required | Summaries embedded, full versions in VCS | | `external` | Required | All history in VCS only | | `none` | Exempt | Entity must NOT be in Hive | The `none` policy is ONLY valid for ephemeral scratch entities that never reach the Hive. If an entity is promoted to Hive (e.g., via the synthesis pipeline), it MUST have a policy other than `none`. ## Authority Model **Embedded history is the canonical source of truth. VCS backend history is supplementary.** When embedded history and VCS history diverge (e.g., due to a transient VCS outage), the embedded record takes precedence: | Source | Authority | Purpose | | ------------------- | --------- | ------------------------------------------ | | Embedded (`_history`)| Canonical | Self-contained record inside the entity | | VCS backend | Secondary | Verification, deep history, time-travel | **Why embedded wins:** - **P2 (Self-Contained)** — The entity must carry its own truth. Relying on an external backend for authority would violate self-containment. - **Graceful degradation** — Entity saves succeed even when the VCS backend is temporarily unavailable (fire-and-forget pattern). The embedded history is always written synchronously as part of the entity save. - **Portability** — A .kno entity transferred between systems carries its history with it. The VCS backend may not be available in the destination environment. The VCS backend provides complementary value: full deep history (when `depth_policy` limits embedded retention), cross-entity queries, integrity verification, and time-travel. But if a conflict arises, the entity's own embedded history record is authoritative. **Reconciliation:** When a VCS backend recovers from an outage, reconciliation tooling (Epic 4, #242) compares embedded history against VCS records and replays any missing commits. The embedded record drives the reconciliation — never the reverse. ## Composition Pattern Schemas that include history declare: ```yaml composes: - history@0.1 ``` This brings in _history block, policy, embedded, external, and changelog fields. ## VCS Backend Contract (v0.1.0) History storage is **backend-agnostic**. The schema defines a VCS contract that any compliant backend must satisfy: | Operation | Required | Purpose | |-----------|----------|---------| | commit | Yes | Store a new entity version | | resolve | Yes | Retrieve content at a version | | list_versions | Yes | Enumerate version history | | diff | Yes | Compute changes between versions | | time_travel | Yes | Resolve entity state at a timestamp | | verify | Yes | Validate hash chain integrity | | branch | No | Create parallel editing branches | | merge | No | Merge branches (conflicts as data) | | sync | No | Push/pull between backend instances | **Reference implementation:** TerminusDB (immutable delta-encoded document graph database with native time-travel). Alternative backends (PostgreSQL, Git, S3 versioning) are first-class citizens — any backend satisfying the core operations is fully compliant. ## Resolved Open Questions - **OQ-19 (History Depth):** Policy-driven. The `retention` field controls embedded depth; backends store ALL versions. These are independent concepts. - **OQ-20 (Verification):** Linear hash chain using SHA-256. Each version holds `content_hash` + `parent_hash`. Genesis has `parent_hash: null`. Verification traverses latest → genesis in O(N). changelog: - version: "0.2.0" changes: - "Added VCS-Mandatory Rule cross-reference and constraint documentation" - "Tightened `none` policy scope: only valid for ephemeral scratch entities not in Hive" - "Changed default policy from `none` to `hybrid` (aligns with VCS-Mandatory Rule)" - "Added depth_policy constraint field for `none` policy" - version: "0.1.0" changes: - "Added backend-agnostic VCS contract (core + collaboration operations)" - "Added pluggable VCS backends schema with TerminusDB reference implementation" - "Resolved OQ-19: policy-driven depth (embedded vs backend are independent)" - "Resolved OQ-20: linear hash chain verification algorithm (SHA-256)" - "Added depth_policy materialization rules" - "Added verification algorithm specification" - "Expanded description with VCS contract and resolved questions" - version: "0.0.2" changes: - "Aligned with bedrock docs (kno-foundational-principles.md § History Architecture)" - "Changed retention → policy enum (full, hybrid, changelog, external, none)" - "Changed offloaded → external block structure" - "Added embedded[] array for version snapshots" - "Removed Layer 1/Level 2 terminology" - "Added parent_hash for hash chain verification" - version: "0.0.1" changes: - "Initial history schema" - "Extracted from kno-spec-schema.kno _history block" - "Added archive history specification" - "Documented history vs provenance distinction" schema: # ------------------------------------------------------------------------- # LIGHTWEIGHT HISTORY (_history block) # ------------------------------------------------------------------------- lightweight: description: | The _history block provides lightweight temporal metadata for simple entities. Underscore prefix indicates metadata. For full history management, use the policy + embedded/external fields defined in the container_history section below. fields: _history: type: object required: false description: "Lightweight history metadata block" fields: version: type: integer minimum: 1 description: | Monotonic version counter. Increments on each modification. Used for optimistic concurrency control and merge detection. examples: [1, 42, 157] created: type: string format: date-time description: "Entity creation timestamp (ISO 8601)" examples: ["2026-01-01T12:00:00Z"] modified: type: string format: date-time description: "Last modification timestamp (ISO 8601)" examples: ["2026-01-06T14:30:00Z"] created_by: type: string description: | Author or system that created the entity. Can be user id, agent id, or system identifier. examples: ["usr_abc123", "claude", "pspace-import-pipeline"] modified_by: type: string description: "Author or system that last modified the entity" examples: ["usr_def456", "claude", "pspace-converter"] previous_versions: type: array items: type: string description: | References to previous version snapshots (lightweight). For full history management, use container_history. examples: [["v1", "v2", "v3"]] merge_base: type: string description: | Version that served as base for last merge (if any). Used for three-way merge detection. examples: ["v41"] # ------------------------------------------------------------------------- # CHANGELOG (human-readable change log) # ------------------------------------------------------------------------- changelog: description: | Human-readable change summaries. Each entry documents what changed in a version. This is CONTENT, not just metadata. fields: changelog: type: array items: type: object fields: version: type: string format: semver description: "Version number this change applies to" examples: ["0.1.0", "1.0.0", "2.3.1"] date: type: string format: date description: "Date of the change (ISO 8601 date)" examples: ["2026-01-06"] author: type: string description: "Who made the change" examples: ["claude", "max", "pspace-team"] summary: type: string description: "One-line summary of changes" examples: ["Added validation rules for identity fields"] changes: type: array items: type: string description: "List of specific changes in this version" examples: - - "Added canonical_id field" - "Removed deprecated xri field" - "Updated validation patterns" breaking: type: boolean default: false description: "Whether this version has breaking changes" migration: type: string description: "Migration instructions if breaking" examples: ["Run `kno migrate --to 0.2.0` to update files"] # ------------------------------------------------------------------------- # CONTAINER HISTORY (managed via manifest.kno) # ------------------------------------------------------------------------- container_history: description: | Full version history for .kno containers. This section defines fields used in manifest.kno to manage history storage. **Bedrock Reference:** kno-foundational-principles.md § History Architecture Container structure (unpacked): ``` entity.kno/ ├── manifest.kno # Contains history configuration ├── content.kno # Current version content └── history/ ├── v3.0.0.kno # Embedded snapshot ├── v2.0.0.kno # Embedded snapshot └── v1.0.0.kno # Embedded snapshot (or externalized) ``` fields: policy: type: enum values: - full # All versions embedded in container - hybrid # Last N versions embedded, older externalized - changelog # Only summaries, no full snapshots - external # All history in external VCS entity - none # No history tracking (entity must not be in Hive) default: hybrid description: | History retention policy. Determines where version snapshots are stored (embedded in container vs external VCS). examples: ["full", "hybrid", "none"] retention: type: integer minimum: 1 default: 10 description: | For 'hybrid' policy: number of versions to keep embedded. Older versions are externalized to the VCS entity. examples: [5, 10, 20] rationale: type: string description: | Human-readable explanation of why this history policy was chosen for this entity. examples: - "Specification requires full audit trail" - "Standard entity - recent history accessible" embedded: type: array description: | List of version snapshots embedded in this container. Each entry references a .kno file within the container. items: type: object fields: version: type: string required: true description: "Semantic version string" examples: ["3.0.0", "2.0.0", "1.0.0"] snapshot: type: string required: true description: "Path to snapshot file within container" examples: ["history/v3.0.0.kno", "history/v2.0.0.kno"] hash: type: string pattern: "^sha256:[a-f0-9]{64}$" description: "Content hash for integrity verification" parent_hash: type: string pattern: "^sha256:[a-f0-9]{64}$" description: | Hash of the previous version in the chain. Enables hash chain verification without loading all versions. date: type: string format: date-time description: "When this version was created" external: type: object description: | Reference to external VCS entity holding deep history. Used for 'hybrid' and 'external' policies. fields: vcs_uri: type: string required: true description: "XRI or URI of the external VCS entity" examples: ["pspace://vcs:entity-id-history"] before_version: type: string description: "Oldest version NOT in embedded (first in external)" examples: ["1.0.0"] root_hash: type: string pattern: "^sha256:[a-f0-9]{64}$" description: | Hash of the oldest embedded version, for chain verification against external history. # ------------------------------------------------------------------------- # OPERATION LOG (fine-grained changes) # ------------------------------------------------------------------------- operation_log: description: | Fine-grained operation log for entities requiring audit trails. Tracks individual changes within versions. Enables CRDT-style merge and audit trail. fields: operations: type: array items: type: object fields: id: type: string format: ulid description: "Unique operation identifier" timestamp: type: string format: date-time description: "When operation occurred" author: type: string description: "Who performed the operation" type: type: enum values: - create # Entity created - update # Field updated - delete # Entity deleted (soft) - merge # Versions merged - pack # .kno.yaml → .kno container # kno-yaml-allowed: pack op enum describes legacy-to-current conversion - unpack # .kno container → .kno.yaml # kno-yaml-allowed: unpack op enum describes current-to-legacy conversion description: "Type of operation" path: type: string description: "JSON path to changed field" examples: ["$.title", "$.relationships.depends_on[0]"] previous: type: any description: "Previous value (for update)" current: type: any description: "New value (for update/create)" metadata: type: object description: "Additional operation context" fields: reason: type: string description: "Why this change was made" ticket: type: string description: "Related issue/ticket reference" # ------------------------------------------------------------------------- # VCS CONTRACT (backend-agnostic version control interface) # ------------------------------------------------------------------------- vcs_contract: description: | Backend-agnostic version control interface for .kno entity history. This defines the operational contract that any VCS backend must satisfy to serve as a history store for .kno entities. The contract is intentionally minimal — backends MUST implement core operations and MAY implement collaboration operations. **Design principle:** TerminusDB is Possibility's reference implementation, but the contract is backend-portable. Anyone deploying a .kno-based system can substitute their preferred backend (PostgreSQL, Git, S3 versioning, etc.) as long as it satisfies the core operations defined here. fields: backend_type: type: string required: true description: | Identifier for the VCS backend implementation. Used to select the correct adapter at runtime. examples: ["terminusdb", "postgresql", "git", "s3"] backend_uri: type: string required: true description: "Connection URI for the backend instance" examples: - "http://localhost:6363" - "postgresql://user:pass@host:5432/versions" # pragma: allowlist secret - "s3://bucket/kno-history" backend_options: type: object description: "Backend-specific configuration (opaque to the contract)" capabilities: type: object description: "Declares which operations this backend supports" fields: core: type: array items: type: string description: | Core operations (ALL required for compliance): commit, resolve, list_versions, diff, time_travel, verify collaboration: type: array items: type: string description: | Optional collaboration operations: branch, merge, sync extensions: type: array items: type: string description: | Backend-specific extensions beyond the contract: graph_query, full_text_search, schema_validation, etc. core_operations: description: | REQUIRED operations. Every compliant backend MUST implement all six. These define the minimum interface for version storage, retrieval, and integrity verification. items: commit: description: "Store a new version of an entity" input: entity_id: "ULID — canonical entity identifier" content: "Complete .kno entity content (parsed YAML)" metadata: author: "Who made the change (user XRI or system id)" message: "Human-readable change description" content_hash: "SHA-256 hash of serialized content" parent_hash: "Content hash of previous version (null for genesis)" trigger: "One of: initial_import, manual_edit, schema_evolution, source_refresh, synthesis, merge" output: version_ref: "Backend-specific version identifier" content_hash: "Confirmed SHA-256 content hash" timestamp: "Server-assigned commit timestamp (ISO 8601)" resolve: description: "Retrieve entity content at a specific version, or latest if omitted" input: entity_id: "ULID" version_ref: "Backend-specific version ref (optional — latest if omitted)" output: "Complete .kno entity content at the requested version" list_versions: description: "Enumerate version history for an entity, newest-first" input: entity_id: "ULID" limit: "Max entries to return (default: 50)" offset: "Pagination offset (default: 0)" after: "Only versions after this timestamp (ISO 8601)" before: "Only versions before this timestamp (ISO 8601)" output: "Array of {version_ref, content_hash, parent_hash, author, timestamp, trigger}" diff: description: "Compute structured field-level changes between two versions" input: entity_id: "ULID" from_ref: "Starting version reference" to_ref: "Ending version reference" output: changes: "Array of {path, operation (add|remove|replace), old_value, new_value}" time_travel: description: "Retrieve entity state at a given point in time" input: entity_id: "ULID" timestamp: "Target point in time (ISO 8601)" output: "Entity content at the latest version committed before the timestamp" verify: description: "Verify hash chain integrity across version history" input: entity_id: "ULID" from_ref: "Start of range (optional — latest if omitted)" to_ref: "End of range (optional — genesis if omitted)" output: valid: "Boolean — whether the chain verified successfully" versions_checked: "Number of versions in the verified range" first_invalid: "Version ref of first integrity failure (null if valid)" chain_root: "Content hash of the genesis version" collaboration_operations: description: | OPTIONAL operations for backends supporting multi-writer workflows. Not required for basic version storage. Backends that implement these MUST advertise them in their capabilities declaration. items: branch: description: "Create a named branch for parallel editing" required: false merge: description: | Merge two branches. Conflicts are represented as first-class data objects (not error states), inspired by jj's conflicts-as-data design principle. required: false sync: description: | Synchronize history between two backend instances. Supports push, pull, and bidirectional sync. required: false # ------------------------------------------------------------------------- # VCS BACKENDS (pluggable implementations) # ------------------------------------------------------------------------- vcs_backends: description: | Pluggable backend registry. Each backend maps the abstract VCS contract operations to its native primitives. Backends are registered by type identifier and discovered at runtime via configuration. The system loads the appropriate adapter based on the backend_type field in the entity's history configuration. **Extensibility:** Third parties can register additional backends by implementing the VCS contract interface and adding an entry to this registry. fields: registry: type: object description: | Map of backend type identifiers to their implementation details and concept mappings. fields: terminusdb: type: object description: | **Reference implementation.** TerminusDB is an immutable, delta-encoded document graph database with native time-travel, WOQL (Datalog-based) query, and push/pull/clone collaboration. fields: status: type: string const: "reference_implementation" docker_image: type: string const: "terminusdb/terminusdb-server:v12.0.2" default_port: type: integer const: 6363 client_library: type: string const: "@terminusdb/terminusdb-client" concept_mapping: type: object description: "How abstract VCS concepts map to TerminusDB primitives" fields: entity: maps_to: "TerminusDB Document" notes: "Each .kno entity is a JSON document in TerminusDB" version: maps_to: "TerminusDB Commit" notes: "Each commit captures a complete document state" branch: maps_to: "TerminusDB Branch" notes: "Named branches for parallel editing" diff: maps_to: "TerminusDB apply endpoint" notes: "Uses before_commit/after_commit for structured diffs" time_travel: maps_to: "Commit/branch path specifier" notes: "Native — all data at any commit is immediately available" content_hash: maps_to: "TerminusDB-Data-Version header" notes: "Returned on every document operation" sync: maps_to: "TerminusDB push/pull/clone" notes: "Built-in collaboration primitives" unique_capabilities: type: array description: "Capabilities beyond the base contract" items: - "WOQL graph queries across entity relationships" - "GraphQL endpoint for structured queries" - "Delta-encoded storage (space-efficient history)" - "Lock-free optimistic concurrency" - "Schema validation at database level" - "Immutable store (deletes are masks, data never overwritten)" postgresql: type: object description: | PostgreSQL-based backend using a versions table with JSONB content storage. Suitable for deployments that prefer relational infrastructure. fields: status: type: string const: "planned" concept_mapping: type: object fields: entity: maps_to: "Row in kno_object_versions table" version: maps_to: "Row with version_number + content_hash" diff: maps_to: "JSONB diff between version rows" time_travel: maps_to: "Query by timestamp range" git: type: object description: | Git-based backend storing .kno files as commits in a repository. Natural fit for file-oriented workflows. fields: status: type: string const: "planned" concept_mapping: type: object fields: entity: maps_to: "File in repository" version: maps_to: "Git commit" branch: maps_to: "Git branch" diff: maps_to: "Git diff" time_travel: maps_to: "git log --before" # ------------------------------------------------------------------------- # VERIFICATION (OQ-20 resolution: hash chain integrity) # ------------------------------------------------------------------------- verification: description: | Hash chain verification algorithm for entity version integrity. **Resolves OQ-20:** "What verification mechanism should be used?" Answer: Linear hash chain using SHA-256, NOT a Merkle tree. Rationale: - Entity history is LINEAR (one parent per version), not tree-shaped - Linear chains are simpler to implement and verify - O(N) traversal from latest to genesis is acceptable for entity histories - Backends like TerminusDB provide additional immutability guarantees - Merkle trees add complexity unjustified for this use case fields: algorithm: type: object description: "Hash chain construction and verification rules" fields: hash_function: type: string const: "sha256" description: "SHA-256 is the required hash algorithm" content_serialization: type: string description: | Entity content is serialized as canonical YAML (sorted keys, consistent formatting) before hashing. This ensures deterministic hashes regardless of key ordering. chain_direction: type: string const: "latest_to_genesis" description: | Each version points BACKWARD to its parent via parent_hash. Verification traverses from the latest version toward genesis. genesis_rule: type: string description: | The first version (genesis) has parent_hash: null. This is the termination condition for chain traversal. verification_steps: type: array description: "Ordered steps to verify a hash chain" items: - "1. Start at the latest (or specified) version" - "2. Compute SHA-256 of the version's canonical YAML" - "3. Compare computed hash to the stored content_hash" - "4. If parent_hash exists, find version with that content_hash" - "5. Repeat steps 2-4 until parent_hash is null (genesis)" - "6. All hashes match + genesis reached = chain VALID" - "7. Any mismatch or missing parent = chain INVALID" complexity: type: string const: "O(N)" description: | Linear in the number of versions. Acceptable because entity histories are bounded (not unbounded streams). defense_in_depth: type: string description: | The hash chain provides portable, application-level integrity. Backends may provide additional guarantees (e.g., TerminusDB's immutable store). These are complementary — the hash chain is portable across backends, while backend guarantees are not. # ------------------------------------------------------------------------- # DEPTH POLICY (OQ-19 resolution: embedded vs backend depth) # ------------------------------------------------------------------------- depth_policy: description: | Rules governing how many versions are embedded in .kno containers versus stored in the VCS backend. **Resolves OQ-19:** "How should history depth be managed?" Answer: Embedded depth and backend depth are INDEPENDENT concepts. - **Embedded depth** = governed by the `retention` field. Controls how many versions travel with the .kno container for self-containment (P2: Self-Contained). - **Backend depth** = ALL versions, always. The VCS backend never discards history. This is the authoritative lineage (P9: Temporal). This separation satisfies both P2 (recent history travels with the entity) and P9 (complete history exists in the backend). **VCS-Mandatory Rule:** Entities stored in the Hive MUST be recorded in a compliant VCS backend. The `none` policy is exempt from VCS recording because `none`-policy entities must NOT reside in the Hive. See kno-foundational-principles.md § VCS-Mandatory Rule. fields: policy_matrix: type: object description: "How each policy maps to embedded and backend depth" fields: full: embedded_depth: "ALL versions embedded in container" backend_depth: "ALL versions in backend" use_case: "Specifications, RFCs, audit-critical entities" hybrid: embedded_depth: "Last N versions (governed by retention, default 10)" backend_depth: "ALL versions in backend" use_case: "Standard documents — most common policy" changelog: embedded_depth: "Zero snapshots; only changelog summaries" backend_depth: "ALL versions in backend" use_case: "Entities where change summaries suffice" external: embedded_depth: "Zero — all history in backend only" backend_depth: "ALL versions in backend" use_case: "Large entities, binary-heavy containers" none: embedded_depth: "Zero — no history tracking" backend_depth: "NOT stored in backend" use_case: "Ephemeral scratch entities (never stored in Hive)" constraint: "VCS-Mandatory Rule: entities with none policy must NOT be in Hive" materialization: type: object description: | How embedded snapshots are populated from the VCS backend when a .kno container is exported or packed. fields: steps: type: array description: "Ordered steps for materializing embedded history" items: - "1. Read entity's history policy and retention depth" - "2. Query backend: list_versions(entity_id, limit=retention)" - "3. For each version, resolve full content from backend" - "4. Compute content_hash and verify against backend" - "5. Write snapshots to container's history/ directory" - "6. Set external.vcs_uri to backend's entity reference" - "7. Set external.before_version to oldest non-embedded" - "8. Set external.root_hash to oldest embedded version hash" triggers: type: array description: "Events that trigger materialization" items: - "Container export (pack operation)" - "Explicit refresh request" - "Policy change (e.g., hybrid → full)" note: | Materialization does NOT occur on every commit. Embedded snapshots are a periodic snapshot of the backend's authoritative history. # =========================================================================== # COMPOSITION PATTERN # =========================================================================== composition: description: | History is a COMPOSABLE schema. Other schemas include history fields by declaring composition. When a schema composes history: - _history block becomes available - changelog field becomes available - For containers, policy/embedded/external fields apply - VCS backend configuration becomes available (optional) - Verification and depth policy rules apply example: | # In document-schema.kno: composes: - identity@0.1 - history@0.1 # Brings in _history, changelog - quality@0.1 # =========================================================================== # VALIDATION RULES # =========================================================================== validation: rules: - name: "version_monotonic" severity: error message: "_history.version must increase on each modification" check: "history.version > previous.history.version" when: "exists(previous)" - name: "modified_after_created" severity: error message: "modified timestamp must be >= created timestamp" check: "_history.modified >= _history.created" when: "exists(_history.modified) && exists(_history.created)" - name: "changelog_matches_version" severity: warning message: "Current version should have a changelog entry" check: "any(changelog, version == $.version)" when: "exists(changelog)" - name: "breaking_has_migration" severity: warning message: "Breaking changes should include migration instructions" check: "all(changelog where breaking == true, exists(migration))" when: "exists(changelog)" # ============================================================================= # SOURCE (P4 — for this schema itself) # ============================================================================= source: | # This schema was extracted from the _history block in kno-spec-schema.kno # and expanded into a full composable primitive. # # Original location: kno-spec-schema.kno > spec.schema.standard.fields._history # # Design decision: History is separated from provenance (DR-002). # History = version lineage over time. # Provenance = origin, ownership, attestation. source_format: yaml source_hash: "sha256:tbd" # ============================================================================= # CONTAINER TIER — Navigation Index # ============================================================================= _index: - path: "identity" line: 14 keywords: [id, type, version, history] - path: "spec/fields" line: 100 keywords: [version, created, modified, changelog, snapshots] - path: "spec/retention" line: 200 keywords: [retention, full, summary, minimal, purge] - path: "spec/composition" line: 280 keywords: [composes, composable, Layer-1, primitive] - path: "validation" line: 450 keywords: [rules, version_required, created_required] contains: - xri: "#identity" role: section title: "Identity Metadata" keywords: [id, type, version] - xri: "#spec" role: section title: "Specification Content" keywords: [fields, retention, composition] - xri: "#source" role: section title: "Source Provenance" keywords: [source, origin, extraction]