Skip to content

Releases

v0.9.0

Choose a tag to compare

@github-actions github-actions released this 11 Oct 21:19
0370fa3

Added

  • Lossless continuous judgments. The generated Judgment model now carries
    the Layers 0.11.0 continuousValue arm as a typed DecimalValue coefficient
    and exponent, while ExperimentDef.taskType lists continuous among its
    known values. JudgmentStudy.judgments() exposes that response as
    JudgmentRow.continuous_value: Decimal | None, preserving participant and
    item identity and keeping continuous responses distinct from the existing
    integer scalar_value. The long-format Arrow and Parquet view stores the
    exact decimal text in a continuous_value column rather than converting it
    to binary floating point.

Changed

  • Vendored Layers lexicons 0.11.0. The vendored release is pinned to commit
    da20595e19874358f5c0fcd37462d8e457ec0cdb; the regenerated lexicon tree hash
    is 87f116cc92d112e697e0fde39368185a8301a1a422e9cfcf20d911b940f8615f.
    Generated integer fields now validate through a strict converter, so
    malformed and nonfinite continuous components raise dx.ValidationError at
    the typed boundary.

v0.8.1

Choose a tag to compare

@github-actions github-actions released this 25 Sep 21:30
955447d

Fixed

  • CoNLL-U token spans index the text the sentence declares. A sentence
    that carries a # text comment keeps that text, but spans were still
    computed as though the text were the forms joined by single spaces. Every
    corpus that writes SpaceAfter=No therefore drifted one byte per run-on
    token, and a reader validating spans against the text rejected the file:
    Universal Dependencies English-EWT failed on its first sentence, whose
    spans ran seven bytes past a 129-byte text. Spans now locate forms in the
    declared text and retain UTF-8 byte offsets whatever the corpus's spacing.
    Multiword range rows are preserved by both parser paths and through Layers
    records: each component word shares the range's complete surface span, as in
    the published Layers UD data. A form that cannot be aligned receives no span
    rather than a fabricated or out-of-bounds one.

v0.8.0

Choose a tag to compare

@github-actions github-actions released this 15 Sep 19:46
d73f4b9

Fixed

  • Repository history reads work on repositories committed under panproto
    0.73 or later.
    panproto 0.73 changed the committed-data carrier from the
    source JSON bytes to canonical MessagePack, so Repository.content_at could
    no longer decode committed values and the byte-equality tombstone check never
    matched, resurfacing forgotten records. content_at and diff now read
    committed values through panproto's schema-aware decoded_data_at, which
    decodes both the historical JSON carrier and the current canonical one, and
    tombstones are recognized semantically after decoding. content_at still
    returns plain JSON values keyed by AT-URI with tombstoned records excluded.
    The ancestry fold also rejects malformed keyed data sets and preserves
    non-ASCII record content. The test suite pins fixture repositories committed
    under panproto 0.71, 0.72.1, and 0.74.3 with the same history and checks that
    all three read back identically.
  • Commit identifiers are stable across panproto releases. The identifiers
    returned by Repository.log() are now the stored object identifiers, the
    same ones head() and resolve() return, rather than a re-hash of the
    commit projected through the current commit shape. A repository committed
    under panproto 0.71 or 0.72, whose commit objects lack fields the current
    shape gives defaults, reports the identifiers it was written with, so
    log() identifiers can be relied on for pinning. Identifiers are checked
    against the persisted bytes on every read: a stored commit or data object
    whose bytes no longer hash to its identifier fails log() and content_at
    with a VcsError, for historical and current repositories alike.

Changed

  • The panproto floor is now >=0.74.3, the first release carrying
    decoded_data_at and the stored-identifier log traversal, and the didactic
    floor is now >=0.15.0. Repositories written under this floor use the
    canonical MessagePack carrier and need lairs 0.8.0 or later to read.

v0.7.1

Choose a tag to compare

@github-actions github-actions released this 02 Sep 20:27

Changed

  • lairs toc --counts counts a repository in one getRepo pass. Counting
    no longer drains every collection with paged listRecords; it fetches the
    repository CAR once and tallies Merkle-search-tree keys per collection without
    decoding record values, falling back to paged counting only when getRepo is
    unavailable. On a repository with hundreds of thousands of records this turns
    thousands of sequential requests into a single download (PdsClient.count_records
    and count_repo_car expose the same path). An exact count of a very large
    repository still transfers the whole repository, since ATProto exposes no
    cheaper exact count, but it is now one streamed request rather than per-page
    latency.

Added

  • lairs toc --max-count N (and table_of_contents(count_cap=...)) caps each
    collection's count at N and stops early, so a very large repository is not
    transferred in full to be counted. A collection with more than N records is
    reported as capped and prints as N+.

v0.7.0

Choose a tag to compare

@github-actions github-actions released this 02 Sep 15:56
58ef87d

Added

  • Federated project domains. repo.decomp.io (Universal Decompositional
    Semantics) and repo.megaattitude.io (MegaAttitude) are live PDS endpoints and
    ship as built-in discovery sources alongside repo.layers.pub, so all three
    project domains are browsable out of the box. lairs sources list shows all
    three; the index dedups by dataset URI, so crawling every source stays
    idempotent while they share a PDS.
  • Catalogue-collection datasets in the global browse. lairs index search
    and the TUI Explore pane surface catalogue-collection datasets (UniMorph,
    VerbNet, WordNet, MegaAttitude), not only corpora, through a new
    search_collections and CollectionHit. Corpus-only facets (expression
    bounds, quality metric, annotation rounds) match no collection.
  • Collection datasets in the Discover tab. The TUI Discover crawl lists
    collection-shaped datasets alongside corpora, tags each row with its type
    (corpus or the collection's kind), and indexes or mutes either card type;
    DiscoveryIndex.mute accepts a collection card, keyed by URI as before.
  • Judgment-study browsing. lairs.data.JudgmentStudy and
    load_judgment_study load an experiment definition and its judgment sets and
    expose the study the way it is explored: its response scale, its participants,
    its items (with resolved text), the raw participant-by-item judgments, and
    per-item and per-participant distributions. lairs judgments <uri> prints the
    scale, each item's response distribution, and the participants. Item text
    resolves by bulk-loading the stimulus expression accounts the judgments
    reference rather than one fetch per item.
  • Judgment materialization. JudgmentStudy.to_arrow and .materialize
    write the judgments as a long-format participant-by-item table (each row
    carrying the scalar or categorical response, confidence, and reading/response
    time) plus per-item and per-participant views, and lairs judgments <uri> --out <dir> writes
    judgments.parquet, items.parquet, and participants.parquet, so a study is
    queryable with DuckDB and the explorer's Query tab.
  • Judgment views in the explorer's Browse tab. A judgment set renders its
    participant's response distribution as a per-value histogram with the mean and
    range for scalar tasks (in addition to the per-label counts for categorical
    tasks) plus the median reading/response time, and an experiment definition
    shows its scale and guidelines.
  • Signal (neural recording) view in the Browse tab. A media record carrying
    a signal block gains a Signal view with the recording's parameters (modality,
    device, sampling frequency, duration, channel count, reference and placement
    schemes) and its channel and sensor layout. The sampled waveform lives in the
    carrier blob, which the index never stores, so the view shows the layout, not
    the samples.
  • Region reading times. JudgmentStudy.region_responses flattens every
    per-region measure a judgment carries: the region's analysis role
    (region_role), the reading and eye-movement measures (reading_time_ms,
    first_fixation_ms, gaze_duration_ms, go_past_ms, total_time_ms,
    regressions_out, regressions_in, fixation_count), and any per-region
    response (response_time_ms, scalar_value, categorical_value).
    materialize writes them as region_responses.parquet, and the Browse
    judgment Distribution view summarizes them as a region count and median
    reading time. Requires Layers lexicon 0.10.0 (see below).

Changed

  • Vendored Layers lexicon 0.10.0, which adds an optional regionResponses
    array to pub.layers.judgment.defs#judgment so region-level reading and
    eye-tracking measurements have a home. Additive and backward compatible.
  • Documentation. Clarified the guides, concepts, reference, and tutorials, and
    fixed the README quickstart to pass a PdsClient so it runs as written.

v0.6.0

Choose a tag to compare

@github-actions github-actions released this 20 Aug 14:37

Added

  • Data-access surfaces. Typed read surfaces over a repository's pub.layers.*
    records: Corpus, Acquisition, Collection, and signal-bearing Media, plus
    the lazy Dataset view, all built on a shared PDS graph loader (lairs.data)
    that enumerates an authority's collections and follows AT-URI references across
    account boundaries into a model pool keyed by AT-URI.

  • Single-actor collection discovery. lairs.discovery.collections lists an
    actor's pub.layers.catalog.collection records as CollectionSummary rows,
    preferring a configured appview's server-side facets and falling back to a direct
    PDS read.

  • DNS handle resolution. IdentityResolver.resolve_handle now races the
    _atproto DNS TXT record against the .well-known/atproto-did HTTP method and
    returns the first did:, so a handle served only over DNS resolves without an
    injected client. Adds a dnspython dependency and a dns_timeout setting.

  • lairs index build defaults to the Layers PDS. --endpoint and
    --source are no longer a required choice: with neither flag, the crawl
    targets the first enabled configured source, which on a default install is
    the built-in Layers PDS (repo.layers.pub). lairs index build --into ./index
    is now enough to index the public corpus. A user who re-points or disables the
    built-in in sources.toml moves the default with it; when every source is
    disabled, the command reports that and exits non-zero rather than crawling
    nothing. The new lairs.discovery.default_source exposes the same resolution
    to library callers.

  • Incremental re-crawls. com.atproto.sync.listRepos reports each
    repository's current commit revision, and the new
    PdsClient.list_repo_listings surfaces it as a RepoListing alongside the
    head CID (list_repos remains as a DID-only view). build_index accepts a
    revs mapping and skips any repository whose revision matches the one
    recorded at the last crawl, reported as repos_unchanged on the
    CrawlReport and stored as RepoCrawlState.last_seen_rev. lairs index build supplies the mapping whenever it enumerates the service itself, so a
    re-crawl costs one listRepos pass plus a describeRepo for only the
    repositories that actually moved. An explicit --seed-did list carries no
    revisions, so those repositories are always described.

Changed

  • Dependency floors raised to didactic>=0.9.1 and panproto>=0.71.0,
    picking up upstream fixes.
  • The adapter registries are concretely parameterized. Registry[Codec],
    Registry[Exporter], and Registry[KnowledgeBase] used the protocols bare,
    so all eight type arguments were implicitly unknown. Every codec is
    Codec[CorpusFragment, FragmentRecord] and every knowledge base is
    KnowledgeBase[Entity, Candidate, Edge], so those are now exact; an
    exporter's view is always pyarrow.Table while its spec and result differ per
    adapter, so those are closed unions over the shipped adapters. A third-party
    exporter introducing a new spec or result type widens the aliases. With the
    registries typed, ty's missing-type-argument rule is promoted to an error,
    leaving possibly-missing-attribute as the one rule at its default.
  • --source renamed to --source-type on datasets, toc, and search.
    On those commands the flag selects the discovery mechanism (auto, pds,
    or appview), which collided with --source on lairs index build, where it
    names a configured source. The two meanings now have two names. Because
    argparse accepts unambiguous prefixes, existing --source pds invocations
    keep working on the renamed commands, but scripts should move to
    --source-type.

Fixed

  • The tfdata exporter validates before it requires tensorflow. export
    imported tensorflow before reading the Arrow view, so a bad column raised
    ModuleNotFoundError instead of the intended lairs error whenever the
    optional extra was absent, contradicting the method's own documented
    contract. The Arrow read and its null-column check now run first.

v0.5.0

Choose a tag to compare

@github-actions github-actions released this 30 Jun 01:17
9770d36

Added

  • Configured dataset sources. A Source model and a sources.toml config
    (under the XDG config directory, overridable with LAIRS_SOURCES_FILE) name
    the PDS and relay endpoints lairs crawls for datasets, so a PDS that is
    deliberately off the firehose stays discoverable. lairs ships a built-in
    default for the public Layers PDS (repo.layers.pub); a user can add sources
    or override a built-in, including disabling it. lairs index build accepts
    --source <name> as an alternative to --endpoint, and lairs sources list
    shows the configured sources.
  • Discover tab in the TUI. A new Discover tab (4) browses the configured
    sources and crawls a chosen source in the background, listing each dataset with
    its state (indexed, new, or muted). Pressing enter or space on a row
    indexes a new dataset (so it appears on Explore) or permanently mutes an
    indexed one. The crawl reuses the same listRepos path as lairs index build
    through a new streaming discover function in lairs.discovery.
  • Auto-index on launch. With no --index, the TUI uses a default index
    location (under the XDG state directory, overridable with LAIRS_INDEX_DIR)
    and, on launch, crawls the enabled sources and indexes every newly discovered
    dataset that is not muted, so Explore fills in on its own. lairs tui --no-auto-index skips the launch crawl.
  • Permanent muting with review. A muted dataset is recorded as a
    MutedDataset in the index and excluded from auto-indexing until unmuted. A
    settings modal (ctrl+s) lists the configured sources and every muted dataset,
    with an unmute action so a later crawl can pick it up again.

v0.4.1

Choose a tag to compare

@github-actions github-actions released this 29 Jun 18:18
7b4bf30

Fixed

  • Querying a materialized dataset with no annotations. A dataset without
    annotation layers materialized an annotations.parquet with no columns, which
    DuckDB cannot read, so the Query tab and QueryEngine failed to open the
    dataset (and tui --data crashed). materialize now skips a column-less view
    rather than writing an unreadable Parquet, and QueryEngine.open skips any
    Parquet it cannot register (raising only when none are readable), so querying
    an annotation-less dataset works.

v0.4.0

Choose a tag to compare

@github-actions github-actions released this 29 Jun 17:19
7f26dfb

Added

  • Cross-account materialization. load_corpus (and the lairs materialize
    and lairs inspect commands built on it) now follow AT-URI references across
    account boundaries, transitively, to pull in the component records a dataset is
    built from (its expressions, and the records those reference in turn), since a
    Layers dataset typically fans out across many single-purpose accounts rather
    than living in one. A new follow_refs parameter, exposed on the CLI as
    --follow-refs / --no-follow-refs (enabled by default), controls this, for
    example to read only the corpus's own account when the components are already
    materialized. References are fetched by exact AT-URI, so only the records the
    corpus actually cites are loaded.

Fixed

  • Reading records back from a PDS. lairs pull and load_corpus (and the
    materialize and inspect commands) validated each record with the wire
    $type field that the generated models do not declare, so every real PDS
    record failed validation and was silently skipped (pull reported zero
    records; materialize wrote empty views). They now strip $type before
    validation through the shared decode helper, so records read back correctly.

v0.3.0

Choose a tag to compare

@github-actions github-actions released this 26 Jun 16:45
c83aa20

Added

  • Aggregate per-dataset changelog entries. build_aggregate_entry assembles
    a single pub.layers.changelog.entry for a dataset anchor from the diffs of the
    many component records that make up that dataset (a new ComponentChange value
    type), grouping changes into ChangeSections by each component's category and
    pointing ChangeItem.targets at the changed components. The version is bumped
    once from the whole aggregate, monotonic from the supplied previous version, and
    an aggregate with no real change does not bump. A scale guard keeps each item's
    true count in its description and caps the enumerated targets at
    targets_per_item, so a change touching many records is summarised, never
    silently truncated.