You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
--project / --add-fields accept block-addressed sources: { $content: PREDICATE } narrows a document's body to the selected blocks (rendered at their original depth), $blocks / { $blocks: PREDICATE } lists each selected block as type / path / text data, and { $matches: REGEX } greps matching lines with their section paths.
find markdown output renders $blocks and $matches entries one line each as key › section path › text, and switches to the fenced-block form with the narrowed body when a parameterized $content field is projected.
--project accepts a bare block predicate — --project '$header: {}' renders each document's body narrowed to the selected blocks (the headers-only form) under key and content fields, so --format json/yaml output keeps the document identity that the markdown fence already carries.
update gains a block-edit flag per operator — --replace, --replace-text, --insert-before, --insert-after, --append, --delete — each taking a { <selector>, payload } mapping and composing with --set / --unset into one atomic update. A validation failure (unmet expect, overlapping selections, incompatible target) prints the offending blocks and exits non-zero without writing. --replace-text accepts a from-less argument ({ $header: Goals, to: Aims }) that rewrites the block's entire own text — the clean way to rename a header or restate a line.
A block edit targeting a $header acts on the heading line alone: --delete '{ $header: Goals }' dissolves the section (contents re-attach to the parent and re-level) and --replace '{ $header: Goals, content: "## Aims" }' retitles it (contents kept), while --delete '{ $section: Goals }' removes the whole tree. --insert-after '{ $header: Goals, content: ... }' adds content at the top of the section, below the heading line.
update and delete gain --expect — a document-level guard asserting the number of matched documents (N or { min, max }); on a mismatch the command lists the matched documents as key › title and exits non-zero without writing. Both also gain --strict, which requires an expect guard on every mutating application (the document-level --expect and each block operator's expect) and aborts before writing if any is missing; --dry-run is exempt so counts can be learned.
find --blocks PRED adds a blocks field listing each block matching the predicate (lowers to addFields: { blocks: { $blocks: PRED } }), and find --matches PATTERN restricts results to documents whose content matches PATTERN and adds a matches grep field (lowers to a $content membership filter plus addFields: { matches: { $matches: PATTERN } }).
find --filter accepts the $content block-membership operator — --filter '$content: { $header: Status }' selects documents that contain at least one block satisfying the predicate.
Changed
update -k / --key is repeatable, matching find: one key lowers to $eq, two or more to $in (body-overwrite mode still takes exactly one). Previously it accepted a single key only.
update writes only documents whose rendered content actually changes and reports honestly — Updated N document(s) when every matched document changed, Matched N document(s), M changed otherwise (No documents matched when none) — so a no-op edit (e.g. expect: 0) leaves the file, and its mtime, untouched.
Fixed
--project / --add-fields now parse the argument as a YAML mapping whenever it contains a : or {, and report a parse error on malformed input instead of silently falling back to the comma list. Previously an unbraced multi-field mapping like --project 'a: { $content: ... }, b: { $content: ... }' failed the YAML parse, degraded to the comma list, and emitted a: null, b: null with no error. The comma list keeps the name, name=source, and bare $selector forms; write multi-field or block projections as a braced mapping.
iwec
Added
iwe_query tool runs an IWE query/block-selection operation document — operation is find / count / update / delete and document is the operation as a YAML string. It exposes the $content membership filter, the $content / $blocks / $matches projection sources, and the block update operators ($replace, $replaceText, $insertBefore, $insertAfter, $append, $delete). find and count read; update applies frontmatter and block edits; delete removes documents with reference cleanup. The tool is always strict: every mutating application must carry an expect guard or the operation is refused with the missing guards named. update / delete accept dry_run to preview without writing.
liwe
Added
query::block module with the BlockPredicate grammar for addressing blocks inside a document: text and regex predicates, $within / $contains axes, per-type operators ($section, $header, $paragraph, $item, $list, $quote, $code, $table, $ref, $hr), $references, and $and / $or / $nor composition.
Block-addressed projection sources: { $content: PREDICATE } renders the selected blocks, $blocks reports each selected block as type / path / text, and { $matches: REGEX } greps matching lines with their section paths — all evaluated through the new query::block_eval::BlockIndex.
IntoBlockPredicate trait accepting scalar shorthands wherever a block predicate is expected.
FindOp::add_fields sets an additive (addFields) projection; CountOp and DeleteOp implement From<FindOp>, reinterpreting a built find with its projection dropped.
project accepts a $-prefixed block predicate mapping (project: { $header: {} }), lowering it to a key field and a content field carrying the narrowed body.
Block update operators in the update document — $replace, $replaceText, $insertBefore, $insertAfter, $append, $delete — each pairing a block predicate selector with its payload and an optional expect guard, validated and applied atomically; represented by BlockUpdate, BlockUpdateOp, and Expect on Update::block_ops.
Unit block operators act on their target as selected: a $header node covers its heading line alone ($delete dissolves the section, a heading $replace retitles it) while a $section covers the whole tree.
UpdateOp and DeleteOp carry an optional expect guard asserting the number of matched documents; on violation nothing is written and the error lists each matched document.
$content filter operator (Filter::Content) matches documents holding at least one block satisfying a block predicate; it composes with every other filter clause.
query::strict_guard_violations names the mutating applications that lack an expect guard.
Changed
query::execute returns Result<Outcome, block_update::EvalError> (was Outcome) so a failed block update reports its validation error instead of writing; find, count, and delete always return Ok.
Update carries block_ops: Vec<BlockUpdate> alongside the frontmatter operators.
Projection carries a base: ProjectionBase (Empty / Frontmatter / Document) in place of mode: ProjectionMode, so FindOp::project is a plain Projection (was Option<Projection>); Projection::document_fields() replaces Projection::default_for_find().
ProjectionContext is constructed with ProjectionContext::new(graph, key) (was a public struct literal).
Fixed
A mis-typed project mapping now reports a parse error instead of being silently read as a comma list of frontmatter field names and yielding null.
Removed
query::prelude module (with its WithFilter trait) — the Rust builder functions moved into the test suite; construct Operation, FindOp, and Filter directly.
query::project::apply_projection_or_default — apply_projection covers the no-projection case.