Skip to content

v1.2.1

Latest

Choose a tag to compare

@sathish-mg sathish-mg released this 17 Aug 15:54
· 2 commits to main since this release
0a9f3d8

Fixed

  • A grain carrying a subject without a relation or object reached no
    index at all
    (#23). Structural indexing required all three positions, so
    an Event about a message id or a person was invisible to
    recall(ns, subject, …) — a silent empty result on a filter every surface
    accepts. The same root cause was the serious one: forget_subject and
    subject_report select through those indexes, so the identity's own grain
    survived erasure and went undisclosed in a DSAR, while the erasure
    reported success. Such grains now get a subject-anchored row (relation and
    object NULL, because the grain asserts neither — which also keeps the row
    inert to every relation-bound query). Never written to heads/
    entity_latest: a log entry about a subject has no "current value". Existing
    files are healed on open by a link_index stamp bump; the rebuild replays
    the rows and reconstructs cur from supersession state, so a reindex neither
    duplicates a grain nor resurrects a superseded one. Pinned on both backends
    (subject_without_relation_is_indexed).
  • DEFINE QUERY stored bodies that could never RUN (#24). Define-time
    validation skipped parsing entirely whenever the body contained $ — the
    shape most saved queries have — and fell back to a keyword blocklist, so any
    syntax error was stored and first surfaced when a caller ran it, typically an
    unattended agent long after the author had moved on. The body is now parsed
    at DEFINE. Bodies whose parameters sit in positions demanding a literal
    (RECENT $limit) are still accepted: the check re-parses with the parameters
    standing in, so only a body malformed however it is bound is refused
    (CAL-E059). The read-only and destructive guards are unchanged.
  • A Skill's instructions could not be reached through any rendered path
    (#25). The field that is the skill was absent from the grain type's
    queryable fields (PROJECT name, instructionsCAL-E060) and no format
    emitted it, leaving raw JSON recall — which defeats budgeted assembly — as
    the only way to read it. instructions and when_to_use are now projectable
    and render at full disclosure.

Added

  • WITH progressive_disclosure(summary|headlines|full) now executes
    (#25). It was documented in docs/cal-reference.md but parsed and discarded,
    warning CAL-W004. It is the body axis, orthogonal to metadata: summary
    and headlines clip free-text bodies (40/80 chars, the same ladder budgeted
    template renders already use), and full leaves them whole and adds the
    long-form definition bodies no other tier carries — a Skill's when_to_use
    and instructions, so they reach a budgeted ASSEMBLE instead of being
    injected around it. Omitting the option renders exactly as before, byte for
    byte.
  • The CAS blob store reaches the CLI and both bindings (#27):
    areev blob put <FILE>|--stdin prints the cas:// URI (idempotent by
    construction), areev blob get <cas-uri> writes hash-verified bytes to
    stdout, and put_blob/get_blob ship in Python and Node — bytes in, bytes
    out, the one documented exception to the scalars-in/JSON-out convention.
    blob get deliberately does not open the memory: the embedded backend's
    file lock is exclusive, so while a run holds a memory even a reader is
    refused, which put an attachment out of reach of the very --tool-cmd
    subprocess the run spawned to process it. Reading the sidecar needs no lock
    and answers no consistency question — a blob is immutable and its address is
    its checksum, re-verified on read. Encrypted memories still open, since
    decryption needs the derived key. No MCP tool, deliberately: blob bytes would
    have to be base64'd into a tool result and land whole in the model's context.
  • Evalset-backed outcome metrics (#29). A recommendation may carry
    metric = "evalset:<EVALSET_HASH>:<field>", resolved by areev loop outcomes
    from the summaries areev eval run journals — passed, failed, total
    and error_rate work against any evalset, and any other field is read from
    the summary the harness wrote. This moves the honesty boundary legitimately
    rather than breaking it: an evalset run is itself an internal, bounded,
    attributable measurement. Two safeguards are load-bearing. A run journaled
    before the apply is never evidence (no run since → not yet measurable,
    and the checkpoint stays due; scoring the baseline against itself would
    report held forever, a fabricated receipt). And MetricSnapshot.higher_is_better
    states the direction, because the built-in metrics are recurrence counts
    where lower is better while an accuracy is the opposite — read the wrong way,
    the Verify gate would propose reverting the rules that worked. The regression
    comparison now lives in one function both the engine and outcome_review
    call. The apply gate (--gating-run) and the outcome edge read those
    summaries through one shared reader, so a rule cannot be admitted on one
    reading of an evalset and judged on another.