Skip to content

feat(validation): temporal-consistency check + first-class scalar properties#79

Merged
zircote merged 3 commits into
develop/v1.0.0from
feat/temporal-validation
Jun 25, 2026
Merged

feat(validation): temporal-consistency check + first-class scalar properties#79
zircote merged 3 commits into
develop/v1.0.0from
feat/temporal-validation

Conversation

@zircote

@zircote zircote commented Jun 25, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Add a temporal-consistency check to okf_validate.py: a derived-from / supersedes / cites edge whose target created is after the deriving concept is flagged. WARN by default (non-blocking); --strict-temporal promotes it to a hard ERROR (exit 1) for a known-clean corpus in CI.
  • Add a first-class scalar properties frontmatter field (string / number / boolean / null) to the schema and converter, for knowledge-graph literal-object triples that have no concept target.
  • Strengthen the converter's losslessness guarantee: every schema source field survives MIF → OKF → MIF → JSON* → MIF with no clobbering.

Addresses defects surfaced reviewing #65 (temporal inconsistency in the MemPalace example; the scalar-properties spec gap). The #65 example file is left untouched pending discussion #60.

Changes

  • scripts/okf_validate.py: temporal check (DERIVATION_TYPES, _parse_created, _temporal_findings, check chore(deps): bump actions/upload-artifact from 6.0.0 to 7.0.0 #6) with --strict-temporal. Skips (never crashes) on unresolved/dateless/malformed targets; date-only created compared at date granularity.
  • scripts/mif_convert.py: properties as a first-class lossless passthrough field; also restored compressedAt and memoryType to the passthrough lists + FRONTMATTER_ORDER (were silently dropped).
  • schema/mif.schema.json: properties field (scalar values only). Canonical only — published public/schema/* mirrors untouched.
  • Fixtures: test/temporal/{bad,good}, test/properties.
  • scripts/test_temporal_and_properties.py: 22 tests — temporal WARN/ERROR/no-false-positive across all three derivation types, equal-timestamp boundary, naive datetime, multi-violation; non-circular field-preservation enumerating every schema source field through the full JSON chain.

This change was independently reviewed (separate orchestrator) before opening; 7 findings fixed, incl. a yaml.YAMLError crash path, two lossless field drops, and a date-only false positive.

Test Plan

python -m pytest scripts/test_temporal_and_properties.py -q                       # 22 passed
python scripts/okf_validate.py profiles/ai-memory/examples --strict-temporal      # exit 0
python scripts/mif_convert.py roundtrip profiles/ai-memory/examples test/properties test/temporal  # lossless PASS
python scripts/okf_validate.py test/temporal/bad                                  # WARN, exit 0
python scripts/okf_validate.py test/temporal/bad --strict-temporal                # ERROR, exit 1
ruff check scripts/{okf_validate,mif_convert,test_temporal_and_properties}.py     # clean

CI validate.yml and schema-check.yml both pass (schema compiles; mirror aliases unchanged).

zircote added 2 commits June 25, 2026 13:22
…perties

okf_validate.py: flag derivation edges (derived-from/supersedes/cites) whose
target is created after the deriving concept. WARN by default (non-blocking);
--strict-temporal promotes to a hard error for known-clean corpora in CI.

mif_convert.py + schema: add a first-class scalar 'properties' field (literal
key/value pairs with no concept target), wired into both passthrough lists and
FRONTMATTER_ORDER so all conversions stay lossless.

tests: temporal WARN/ERROR/no-false-positive, properties roundtrip + schema
accept/reject, and a no-clobber guarantee across MIF -> OKF -> MIF -> JSON* -> MIF.
- okf_validate: catch yaml.YAMLError so a malformed-YAML derivation target
  is skipped, not a crash (reserved index.md/log.md targets are only ever
  parsed here); compare date-only 'created' at date granularity to avoid a
  same-day false positive under --strict-temporal.
- mif_convert: add compressedAt and memoryType to FRONTMATTER_ORDER and both
  passthrough lists; they were silently dropped on round-trip (lossless gap).
- tests: exercise the JSON serialization leg (json.dumps/loads); enumerate all
  schema source fields (non-circular); cover supersedes/cites, equal-timestamp
  boundary, naive datetime, target-missing-created, multi-violation. 11 -> 22.
@zircote zircote marked this pull request as ready for review June 25, 2026 17:49
Copilot AI review requested due to automatic review settings June 25, 2026 17:49

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds validation and conversion support for (1) temporal consistency across derivation relationships and (2) first-class scalar properties in MIF/OKF, plus tests/fixtures to enforce lossless round-tripping across the full conversion chain.

Changes:

  • Add a temporal-consistency check in okf_validate.py (WARN by default; ERROR with --strict-temporal).
  • Add scalar properties support to schema + converter passthrough/frontmatter ordering.
  • Add fixtures and a new pytest suite to cover temporal validation + properties + “no field clobber” guarantees.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
scripts/okf_validate.py Adds temporal-consistency validation and --strict-temporal mode.
scripts/mif_convert.py Preserves properties, memoryType, compressedAt across MIF↔OKF projections and canonical serialization.
schema/mif.schema.json Introduces properties (scalar-only values) to the schema.
scripts/test_temporal_and_properties.py Adds tests for temporal findings, scalar properties, and end-to-end field preservation.
test/temporal/good/* Fixtures for temporally consistent derivation relationships.
test/temporal/bad/* Fixtures for temporally inconsistent derivation relationships.
test/properties/concept.md Fixture demonstrating scalar properties frontmatter.

Comment thread scripts/test_temporal_and_properties.py
Comment thread scripts/okf_validate.py
Comment thread scripts/test_temporal_and_properties.py Outdated
- okf_validate: restrict temporal-check target reads to within the bundle; a
  target escaping via ../ must not cause reads of arbitrary files outside the
  bundle (matches the function's documented 'in-bundle' contract).
- tests: add explicit sys.path for scripts/ so imports also work under
  importmode=importlib / direct execution (already passed under pytest's prepend
  mode); correct an inaccurate comment claiming memoryType merges into the
  conceptType slot (it is a standalone passthrough key); add a bundle-escape
  regression test.
@zircote zircote merged commit ef96e8f into develop/v1.0.0 Jun 25, 2026
5 checks passed
@zircote zircote deleted the feat/temporal-validation branch June 25, 2026 18:23
zircote added a commit that referenced this pull request Jun 25, 2026
* docs(changelog): backfill Unreleased section for post-1.0.0 develop work

Adds a [Unreleased] section capturing work merged into develop/v1.0.0 since the
1.0.0 release: versioned schema mirrors (#72), the immutable 0.1.0 mirror
snapshot (#73), validate.yml SHA-pinning + all-PR trigger (#74), the schema-check
required gate (#75), and the temporal-consistency check, first-class scalar
properties field, and lossless round-trip fixes (#79).

* docs(changelog): consolidate to a single Unreleased section

Address Copilot review on #80:
- v1.0.0 is not released yet, so the in-progress 1.0.0 section is relabeled
  ## [Unreleased] and the #72-#75/#79 entries are merged into its subsections
  (Added/Changed/Fixed), rather than a separate top Unreleased.
- Remove the pre-existing stale ## [Unreleased] block (pre-1.0.0 'Memory
  Interchange Format'-era content, already superseded by the release sections).
- Reference links: [Unreleased] compares from v0.1.0; no broken [1.0.0] tag ref
  (there is no v1.0.0 release).

* docs(changelog): rebuild to a complete single Unreleased section

Restore every entry that the prior consolidation had dropped. Since v1.0.0 is
unreleased, all work since 0.1.0 now lives in one well-formed ## [Unreleased]
(Breaking Changes / Added / Changed / Removed / Fixed / Documentation /
Migration), merging the former [1.0.0] summary, the catch-all [Unreleased]
feature entries (subtype_of, EntityData, blocks, EntityReference, ontology
extends, VERSION.json, OntologyReference, citations, compression, ontologies,
Backstage, schema $id, discovery patterns, research docs, ...), and the
#72-#75/#79 work. [0.1.0] stub and reference links unchanged. No data lost
(verified against the original).
@zircote zircote added this to the release/v1 milestone Jun 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants