Skip to content

v0.7.0 — Seeing the Sentences

Choose a tag to compare

@sci2sci-opensource sci2sci-opensource released this 29 Mar 18:29
· 113 commits to master since this release

v0.7.0 — Seeing the Sentences

v0.6.0 gave parseltongue a workbench — systems that inspect code by speaking parseltongue to each other. v0.7.0 gives that workbench eyes: a visualization engine that renders any scope query as an interactive HTML document, a search engine that ranks and enriches results with provenance, a stack-based evaluator that eliminates recursion limits, and a published GitHub Pages site where the demos run live. The workbench can now show you what it sees.


New

Interactive Visualization Engine

Renders any scope result — lens, screen, hologram, search, ops — as a self-contained HTML file with three synchronized view modes.

Cards — one card per node. Kind dot (colored by fact/axiom/theorem/term/diff), name, truncated value, input edges. Click for full detail. Filter by kind toggles, live search bar.

Layers — depth-based stacked SVG layout. Layer 0 (roots) at bottom, consequences at top. Nodes as pills with colored edges (declare / use / pull). Focus mode zooms to a single layer with its immediate context. Edge highlighting on hover.

Graph — D3 force-directed layout with zoom/pan. Nodes colored by kind, edges colored by relationship type. Click opens the detail panel; hover highlights connected edges.

Detail panel — the right-side panel on any node click. Full quote text with file:line locations, confidence scores from the QuoteVerifier, evidence classification (verified / unverified / missing), derivation tree showing the full proof chain.

Taint computation (taints.py) — forward-propagating evidence quality analysis. A taint source is any node whose evidence doesn't pass a predicate (no evidence, or unverified status). Taint propagates through edges: any node consuming a tainted input is itself tainted. The viz colors tainted nodes and shows reason chains.

Diff viz — integrated with hologram dissection. (fmt "viz" (scope hologram (dissect "diff-name"))) renders both sides of a consistency diff as a visual hologram. Also wired into find and fuzzy — lens results that contain diffs show them inline.

Module structure — extracted from a monolithic 2000-line Python f-string into separate template files with proper syntax highlighting:

visualisation/
  renderer.py              # VizRenderer + Python enrichment helpers
  notebook_renderer.py     # pgmd notebook rendering (composes on app.html)
  taints.py                # taint computation + propagation
  templates/
    app.html               # HTML skeleton with named slots
    core.js                # init, DATA/LAYERS globals, search, filter, tabs, taint
    cards.js               # Cards view
    layers.js              # Layers view — stacked SVG with focus mode
    graph.js               # D3 graph view
    detail.js              # Detail panel + derivation tree + evidence rendering
    notebook.js            # pgmd notebook tab
    source.js              # Source code view with line highlighting
    highlight.html         # S-expression syntax highlight template

JS files are plain JS — no {{ escaping. Assembly via Python string.Template substitution in named slots.

Search Engine v2

Replaces the v1 DocumentIndex.trace() path with a line-level inverted index backed by DocumentSearchIndex.

Strategy cascade: direct → stemmed → n-gram → meta, each producing a posting set. cascade returns first non-empty; merge combines all with decreasing confidence weights (1.0 / 0.7 / 0.4 / 0.5); rrf (default) uses Reciprocal Rank Fusion across all strategies.

BM25 ranking: document-level BM25 with meta boost overlay. Each posting gets a _score = BM25(query, doc) × meta_boost × Π(rule penalties). Standard k1=1.2, b=0.75. Ranking rules are composable predicate-based multipliers — e.g. test files get penalty 0.3, __init__.py gets 0.5. Rules auto-suppress when query terms overlap (searching "test" disables the test penalty).

Synonym expansion: three expansion scopes — universal (content + meta), documents (content indices only), meta (meta indices only). Bidirectional within scope. Baked into the corpus-level inverted index at build time, so the stemmed strategy already covers synonym matches with no extra pass.

COW snapshots: all query-visible state — documents, corpus_words, corpus_stems, stem_df, name_stems, doc_lengths, avgdl — lives in a single immutable _Snapshot dataclass. Writers build a complete new snapshot, swap one reference. Readers grab self._snap once per query. No locks, no races under CPython GIL.

Quote provenance enrichment: search results annotated with pltg node names that quote each source line. Content-hash matching (SHA-256 prefix) resolves verifier doc names (e.g. "engine.py") to file-indexed paths (e.g. "parseltongue/core/engine.py"). Cached _build_line_callers index — O(1) per posting hit instead of O(docs × ranges). Cache invalidates when _quote_ranges identity changes.

Cache serialization: saves line-level indices (word→lines, stem→lines, n-grams, metadata, corpus indices) as JSON-friendly dicts. Sets → sorted lists for deterministic round-trips. Survives bench cache cycles without rebuilding from text.

SearchSystem2: same BenchSubsystem interface, but backed by DocumentSearchIndex — uses search() (lookup + enrich) instead of _collect, pre-split SearchDocument.lines instead of per-call splitlines(), and exposes the (strategy ...) operator for explicit strategy selection.

Operations System v2

OperationsSystem v2: fast Python dispatch replacing pltg rewrite axioms for set operations. Two regimes:

  • Pointer (and-forms, not-forms, or-forms): set ops on extracted keys, bodies untouched. When all forms share one tag, that system's morphism decides identity. Mixed tags: partition by tag, per-tag dispatch, merge.
  • Vectorized (count-forms, limit-forms): len/slice on the list itself.

Plus str format, str join, list get, list unique, list filter for map-reduce pipelines across scopes. Falls through to pltg engine for unknown operations.

Stack Engine

Default evaluation engine is now continuation-based. A single while True loop replaces the recursive _eval → _rewrite → _eval call chain. Eliminates Python RecursionError on deep derivation graphs.

Continuation tags — 10 typed frames manage all control flow on an explicit stack:

Tag Purpose
_K_ARGS Evaluating arguments left-to-right for a callable head
_K_IF_COND Pending then/else branch after condition evaluates
_K_LET_BIND Sequential let binding with trail-based env restore
_K_BIND_PAIR :bind pair evaluation — substitutes ?-vars then evaluates
_K_SELF_ARGS Parallel self argument evaluation
_K_HEAD Compound head resolution (rare — most heads are Symbols resolved inline)
_K_STRICT_ARG Force-evaluating (strict ...) arguments before rewrite
_K_PROJECT_BASIS Evaluating the basis of a (project basis body) form
_K_TRAIL_UNDO Scope exit — restores env mutations from :bind/let
_K_CONTEXT Tracer context boundary — pops trace frame, records rewrite log

Trail-based environment — let and :bind mutate the env dict in place, recording (key, old_value_or_MISSING) pairs in a trail list. _K_TRAIL_UNDO restores all mutations in reverse order on scope exit. Replaces O(n) env.copy() per scope with O(k) trail entries where k = bindings set.

Tail-call signaling — the _TAIL_CALL sentinel and _tc_expr slot avoid allocating return tuples. When a rewrite produces a new head, the lazy rewrite path sets _tc_expr and returns the sentinel; the main loop picks it up as the next expression. Same mechanism handles if, let, strict, quote, and project — all set expr and continue without pushing frames.

Rewrite cache — keyed by expression identity (id(expr)), populated after first _rewrite call. Skips redundant rewrite passes for expressions seen multiple times in the same evaluation.

Tracing — integrated at the continuation level. _K_CONTEXT frames mirror a _tracer_stack that records rewrite rule applications and variable resolutions per named entity. When a term/theorem/fact definition is entered, a context frame is pushed; when the continuation unwinds, the trace log captures which rules fired and which symbols were resolved. This is what enables dynamic fact assembly — facts, derives, and diffs injected at runtime via load_source() are traced through the same continuation machinery as static definitions.

Vital — Tracing, Staining & Live Probe

The vital/ module (parseltongue/core/inspect/vital/) provides runtime dependency capture — discovering edges that only exist during evaluation, not in static structure. Biology-inspired naming: genes are "expressed" (activated) and "suppressed" (silenced); a "stain" makes invisible structure visible.

Two instrumentation paths, one interface:

  • Tracer (stack engine) — zero-cost native tracing. express() flips the engine's _tracing flag; the continuation stack records edges via _K_CONTEXT frames as it evaluates. suppress() extracts edges from _trace_log. No monkey-patching, no observer hooks — the engine does all the work.
  • Stain (recursive engine) — monkey-patches _eval and _rewrite to intercept calls. Maintains a context stack and depth counter. Records three edge kinds: resolve (symbol lookup), effect (callable dispatch), rewrite (axiom application — matches against the rule set to identify which axiom fired). Four capture modes: "names" (only named entities), "heads" (+ expression heads), "all" (every _eval call), or int N (up to N levels from nearest named context).

trace_engine() auto-detects the engine type and returns the appropriate tracer.

Live probe — merges traced runtime edges with static probe structure. Phase 1 builds the static graph via _walk_engine. Phase 2 augments with stain/tracer edges via _augment_with_stain — runtime-only dependencies (dynamic term resolution, axiom rewrites, effect dispatch) appear as graph edges that static analysis cannot see. Phase 3 adds a synthetic __output__ root.

probe_diffs_to_possibilities() extends this to diffs specifically — walks both sides of every diff, augments with runtime edges, and inserts DIFF nodes. Diffs are fundamentally live: each side may reference dynamic terms that only resolve at runtime.

This is what makes dynamic fact assembly observable. The data governance demo builds its entire pltg graph at runtime — Python reads CSVs and markdown contracts, injects hundreds of facts and cross-layer diffs on the fly via load_source(). The system's structure isn't known statically. Vital staining traces through the dynamically-built graph and produces a real dependency visualization where every node is a fact that was actually evaluated and every edge is a resolution that actually happened.

Hologram integration — the (stain expr) operator in the hologram scope is a pure marker: it wraps expr in a [__stain__, expr] tag. When dissect or compose encounter a stained argument, they route through live_probe instead of static probe — so (dissect (stain "diff-name")) traces the engine at evaluation time and produces a hologram where every edge is a real runtime resolution. Without (stain ...), dissect/compose use static probe only.

# Static dissect — edges from definition graph only
pg-bench eval '(fmt "viz" (scope hologram (dissect "policy-check")))'
# Stained dissect — edges from live evaluation
pg-bench eval '(fmt "viz" (scope hologram (dissect (stain "policy-check"))))'
pg-bench stain all-contract-facts-ok all-product-facts-ok

Default live probing — when the bench technician transitions from frozen to live, it calls _live_probe_all: traces all theorems via trace_engine, probes from roots, and passes the live-probed structure to the VizRenderer. This means all viz output — including rendered pgmd notebooks — uses live-probed structure by default. Every edge in a notebook's margin pills, taint propagation, and detail panel reflects actual runtime evaluation, not just static declaration.

History — Time Travel Over Indexed States

Append-only timeline built on a custom storage stack:

OrdinalPGZ — custom binary format with two independent zlib streams per file. Stream 1 is a compact header (entry count, filenames, offsets); stream 2 is the bulk text block. SHA-256 integrity covers both streams. Header-only reads decompress just stream 1 (~1% of the data) for instant key enumeration without touching the text. Magic bytes TXS\x01, convenience labels between entries for manual inspection of decompressed data.

LayeredTexts — delta-cache rotation on top of OrdinalPGZ. Each pg-bench index commits an immutable delta layer ({prefix}.texts.{n}.pgz). Reads merge layers newest-first — first hit per key wins. Tombstones (zero-length entries) mark deletions. Rolling merge: when layer count exceeds max_layers, oldest layers are automatically merged into a new base and remaining layers renumbered. compact() flattens everything into a single base.

History — time travel built on LayeredTexts. Metadata persisted in a separate OrdinalPGZ file (instant layer inspection without scanning layer files). Restore is non-destructive — computes a reverse delta and appends it as a new commit. History stays append-only; you can undo a restore by restoring again.

pg-bench history layers                    # all layers with metadata (instant — reads meta file only)
pg-bench history files -l 2                # files at layer 2
pg-bench history diff --from 1 --to 3     # what changed between layers
pg-bench history diff-file NAME            # unified diff of one file
pg-bench history restore 2                 # restore to layer 2 (appends reverse delta)
pg-bench history restore-file NAME 2       # restore one file
pg-bench history compact --yes             # rolling-merge all layers into one base

GitHub Pages — Guides, Construct & Interactive Demos

Published documentation site deployed automatically via GitHub Actions on push to master.

Site sections:

  • Home — project overview
  • Quickstart — getting started guide
  • Demos — interactive demos running in-browser via Pyodide
  • Construct — the learning system (see below)

Dark/light theme toggle. Project branding with SVG logo.

Build pipeline (pages/build.py):

  • Builds the parseltongue wheel and bundles it as a site asset — the full engine ships to the browser
  • Pyodide runner pages: each Python/pltg demo gets an auto-generated page that loads Pyodide, installs the parseltongue wheel via micropip, injects all demo resources (.pltg, .txt, .json, .md) into Pyodide's virtual filesystem, and runs demo.py — the full parseltongue engine runs live in the browser, no server needed
  • Editable demos: the demo.py source is rendered as a contenteditable code block with Prism syntax highlighting. Users can modify the code and re-run — interactive experimentation with the real engine
  • Dynamic demo discovery — scans parseltongue/core/demos/ automatically, extracts titles and descriptions from demo.py docstrings, classifies as pgmd/pltg/py
  • pgmd rendering — renders .pgmd notebooks via pg render into self-contained HTML
  • Construct rendering — renders scripts (for agents) and scenarios (for humans) via pg render
  • Applies project theme (css_variables from parseltongue.core.theme)

Construct — Learning System for Humans and Agents

"The place where both agents and humans learn Parseltongue." Two mirrored modes:

  • Scripts are for agents. An LLM loads a script with pg learn <name> and gains operational knowledge — guides available via the CLI and in the repository
  • Scenarios are for humans. Interactive notebooks that build understanding of what Parseltongue is, how to work with it, and how to keep LLM agents accountable during collaborative sessions

Each topic is available in both modes: agents access scripts via pg learn <name> on the CLI, humans read scenarios as interactive pages on GitHub Pages (or ask their agent to render one locally).

Topic What it covers Script Scenario
white-rabbit Introduction — what Parseltongue is and why it exists — ready
kung-fu Bench mastery — inspection, search, lens, diagnosis ready —
to-connect pgmd notebooks — prose wired through with truth ready —
dodge-bullets Screening, diagnostics, consistency — —
jump-program Resolving dynamic refs, building consistent graphs — —
no-spoon-bending Effects, verify_manual, bending accepted terms — —
read-the-code Grounding layer — documents and data to facts and axioms — —
about-matrix Systems, composition, fundamental language — —
the-truth Epistemics, std lib, grounding module, diffs — —
to-exit Scoping, projection, delegates — —
to-fly Graph navigation, search, cross-navigation — —

"Follow the White Rabbit" is the first published scenario — an interactive document explaining what Parseltongue is, why LLMs lying is an engineering problem, and walking through the system from first principles with live parseltongue blocks running inside the document itself.

pgmd Notebooks — Parser, AST & Renderer

pgmd (Parseltongue Markdown) is the project's notebook format — Markdown with embedded pltg blocks and inline node references, like Jupyter notebooks for parseltongue. v0.7.0 adds the full stack: parser, AST, Markdown engine, and visual renderer.

Markdown parser (core/notebooks/mdparser/) — a full AST-producing Markdown parser based on mistune 3.2.0, internalized into the project. Block parser (headings, code fences, block quotes, lists, HTML blocks), inline parser (emphasis, links, code spans, autolinks), and list parser — each producing structured AST token dicts with type, children, and attributes.

mdparser/
  core.py            # BlockState, InlineState, Parser base, BaseRenderer
  block_parser.py    # ATX/setext headings, fenced code, block quotes, thematic breaks, HTML
  inline_parser.py   # emphasis, links, images, code spans, autolinks, line breaks
  list_parser.py     # ordered/unordered lists with tight/loose detection
  markdown.py        # Markdown — wires block + inline parsers, renders or returns AST
  helpers.py         # HTML tag patterns, link parsing, unescape
  util.py            # escape_url, expand_tab, unikey
  plugins/
    pgmd_ref.py      # [[type:name]] inline reference plugin
    table.py         # GFM table support

pgmd_ref plugin — parses [[fact:revenue]], [[term:margin]], [[~term:ltv]] (silent ref — footnote only) inline syntax into structured AST tokens with prefix/suffix support ($[[fact:x]], [[fact:nrr]]%, [[term:ratio]]x). Hooked into the inline parser at higher priority than link parsing so refs inside table cells work correctly.

pgmd parser (core/notebooks/pgmd.py) — splits .pgmd files into typed blocks: prose (markdown), pltg (executable — fenced scheme with ;; pltg marker), code (display-only). YAML frontmatter stripping, inline [[type:name]] reference extraction, pltg source extraction.

Notebook renderer (visualisation/notebook_renderer.py) — renders pgmd into a document where the prose itself is the visualization. [[fact:revenue]] in markdown becomes the actual computed value inline — bold, colored by kind, with a superscript footnote number. [[~term:ltv]] produces a silent footnote (number only). Each paragraph gets margin pills — small colored badges showing which pltg nodes are referenced in that paragraph, clickable to open the detail panel.

The rendered output includes:

  • Inline resolved values — [[fact:revenue]] → $15M¹ with kind-colored text, prefix/suffix support ($[[fact:x]], [[fact:nrr]]%)
  • Footnote system — deduplicated footnote numbering, footnote list at bottom with kind dots and values
  • Margin pills per paragraph — node badges aligned to each prose element, showing what's referenced where
  • Taint propagation — taint sources get red ✖, propagated taint gets yellow ⚠, with reason chains in tooltips. Taint flows through the prose: if a fact is unverified, every paragraph referencing it shows the warning
  • Collapsible pltg blocks — syntax-highlighted code with output rows (result, stdout, stderr, errors), node pills showing what the block produced
  • Diagnostics panel — errors/warnings/info grouped by severity, collapsible
  • Full markdown via the mdparser AST — headings, tables, lists, block quotes, code blocks, emphasis, links, images
  • S-expression syntax highlighting with context-aware coloring for directives and keywords
  • Scientific notation and smart number formatting (percentages, millions, comma-separated)

Composes on top of app.html as single source of truth — no template duplication. The notebook is a tab alongside Cards, Layers, Graph. The underlying probe structure is live by default — the bench technician traces all theorems at startup and passes the live-probed graph to the renderer, so every margin pill, taint chain, and detail panel edge reflects actual runtime evaluation.

Engine Self-Inspection — pgmd Notebook Demo

A pgmd notebook where the engine inspects itself. Loads core.pltg (the validation system for parseltongue's own codebase), then walks the graph structure — layers, node kinds, derivation chains — with inline computed values, taint propagation, and derivation paths rendered live. The notebook is the visualization: every [[term:name]] in the prose resolves to its actual computed value, margin pills show which nodes each paragraph references, and the detail panel traces any claim back through the full proof chain. Ships as both a core demo (parseltongue/core/demos/engine_overview/) and a rendered page on GitHub Pages.

AI2AI — pgmd Investment Memo Analysis

Full end-to-end demo of pgmd notebooks analyzing a Series A investment memo. A source document (series_a_memo.txt — a fictional VC memo for a neurosymbolic AI company) is annotated through four different pgmd patterns:

  • Explicit (explicit.pgmd): inline pltg computation — derives gross margin, LTV/CAC, burn rate directly from imported facts, with prose referencing computed terms via [[term:name]] and [[fact:name]] interpolation. Axioms validate business rules inline (e.g. (> ?margin 0.6))
  • Implicit (implicit.pgmd): deferred computation — pgmd prose references facts without inline blocks, resolved at render time
  • Standalone (standalone.pgmd): self-contained analysis with its own fact definitions
  • Review workflow (review-implicit.pltg): pltg review layer that cross-checks notebook claims against source facts

Supporting infrastructure: ai2ai_facts.pltg (financial facts extracted from the memo), ai2ai_rules.pltg (validation rules for investment criteria), render_all.py (batch rendering of all notebooks).

Data Governance Demo

Full data governance pipeline showcasing the stack engine's dynamic fact assembly. A biopharma company maintains three layers of data governance: technical catalog (CSVs), legal contracts (.md), and business catalog (.md). Each layer is authored independently; over time, drift accumulates.

The demo's generate.py creates a realistic data estate with ~15-20% injected corruptions (path drift, SLA mismatches, phantom references, expired contracts, classification conflicts, retention violations). Then demo.py dynamically discovers and assembles the entire pltg graph at runtime: Python code reads CSVs and parses markdown contracts, extracts facts from each row and field, and injects them into the running system via load_source(). Cross-layer diffs are generated on the fly as discrepancies are found. The system's structure isn't declared upfront — it's built dynamically as data is discovered, and parseltongue catches every injected corruption through 10 cross-layer consistency checks.

data_governance_pltg/
  main.pltg             # entry point
  checker.pltg          # governance checker with per-field validation
  policy_rules.pltg     # declarative policy rules
  operators.py          # custom operators for governance domain
  generate.py           # manifest + violation generator with deterministic seed
  demo.py               # dynamic fact extraction + cross-layer checks
  run_viz.sh            # one-shot viz generation

Evaluation → Screening Rename

evaluate renamed to screen throughout. New screen.py replaces evaluation.py as the primary consistency view module. (scope screen ...) is the canonical scope name. Old (scope evaluation ...) kept as alias.

Project Auto-Configuration

config.py — single source of truth for bench index settings. Detects project languages by scanning file extensions, generates pg.toml (extensions, detected languages) and .pgignore (gitignore-style ignore patterns) automatically.

Language detection — walks the project directory (depth-limited), inverts a 101-language preset map (LANGUAGE_PRESETS) to identify which languages are present from file extensions alone. Compound extensions (.ansible.yml, .pg.md) handled via endswith() since Path.suffix only returns the last segment. Parseltongue's own extensions derived from loader/files.py — never hardcoded.

.gitignore absorption — reads .gitignore before the detection scan to prune the walk (skips venvs, build dirs, node_modules). Absorbed patterns are merged into the generated .pgignore so bench respects the same ignore rules as git, plus language-specific ignores (e.g. __pycache__/, target/, .next/).

Auto-init on first use — if pg.toml doesn't exist when the bench indexes, config generates it automatically. Thread-safe: threading.Lock() + double-check pattern + atomic writes via tempfile.mkstemp + os.replace.

pg-bench init — explicit CLI command with per-file modes: --toml skip|force|append, --pgignore skip|force|append. skip (default) won't touch existing files. force overwrites. append adds missing entries without destroying hand-edited config.

Binary extension blocklist — BINARY_EXTENSIONS frozenset prevents indexing images, archives, compiled artifacts.

Development Roadmap Tracker

Git-based task tracking (roadmap/). One markdown file per task, lifecycle: pending/ → in_progress/ → completed/. TRACKER.md is the status table. Claim via PR (adds proposal + branch), complete in feature PR (moves file + tags commit with pg-task:slug).


Improved

Bench CLI

Major additions since v0.6.0:

  • pg-bench init: project auto-configuration with per-file modes (skip/force/append), --force/--append shorthand flags
  • pg-bench screen: full screening interface — --what issues|warnings|danglings|ok|stats, --focus "namespace.". Replaced diagnose as primary command (alias kept)
  • pg-bench history: all time-travel commands (layers, files, diff, diff-file, restore, restore-file, compact)
  • Worker logging: structured logging system for daemon workers with configurable levels
  • Auto-glob in (in ...): bare document names auto-glob — (in "engine" ...) → *engine*
  • find and fuzzy with diff viz: lens results that contain diffs render inline hologram views
  • Dynamic demo discovery: pg-bench demo auto-discovers available demos
  • Index extensions from config: --ext default changed from hardcoded [".py", ".pltg", ".md", ".txt"] to reading pg.toml; extensions only sent to server when explicitly provided via CLI

Bench Technician

  • Quote provenance available from frozen cache — callers work immediately on startup (~200ms), not only after live transition
  • Scope registration from any cached result (frozen or live)
  • Background reload with hot-patching keeps stale data available during refresh
  • Session logbook with home backup: records who booked the bench — user and assistant identities persisted to .parseltongue-bench/logbook.jsonl. Dual-write: every entry is also appended to ~/.parseltongue/pg-bench/logbook.jsonl with a project field, so the home copy doubles as a machine-level log across all projects. If the local logbook is wiped (e.g. rm -rf .parseltongue-bench/), read_logbook falls back to the home copy filtered by project. The logbook feeds into taint computation: verify_manual signatures are checked against known session participants, and unrecognized signers produce taint

Hologram System

  • Vital staining integration — (scope hologram (dissect (stain "name"))) traces evaluation through the stack engine at execution time
  • Diff viz integration — dissected holograms render as interactive HTML with both sides visible
  • compose and dissect wired into find/fuzzy for inline hologram views in lens results

Lens System

  • Diff integration with hologram dissection
  • Improved evidence classification in viz output

Evidence & Signatures

  • verify_manual with signatures: (verify-manual name signature) stores a symbolic signature on the Evidence dataclass — a plain string recording who verified the item, appended to the explanation as [Signed: X]. Items without evidence get a synthetic Evidence(document="manual") with the signature attached. Signatures are currently symbolic (not cryptographic) — the infrastructure is designed to be extended later with cryptographic signing and hash-chained append-only logbooks with home-directory backup for tamper resistance.
  • Taint predicate checks signatures against the logbook: the default taint predicate in taints.py inspects verify_manual items. If the item's signature doesn't match any user/assistant in the session logbook, it becomes a taint source with reason "signed by 'X' — not a known session participant". Without a booked session, all manually verified items are tainted.
  • Session identity (v.py): constants USER and ASSISTANT — the default session origin identity, used to silence stdlib taints and as the default logbook participants.

File Types

  • loader/files.py: canonical file type registry. Maps extensions to types: .pg/.pltg → parseltongue script, .pgmd/.pg.md → pgmd notebook, .md → markdown (pgmd-compatible). file_type() resolves compound extensions (.pg.md first). is_renderable() checks pgmd compatibility. Used by the build pipeline, notebook renderer, and demo discovery.

Theme

  • theme.py: shared Catppuccin Mocha (dark) + Latte (light) palette — single source of truth for colors across viz templates, GitHub Pages CSS, and notebook rendering. css_variables() emits CSS custom properties for both palettes. Font stacks (system-ui + JetBrains Mono) defined here.

README

Overhauled for v0.7.0. Hero section with engine self-inspection notebook screenshot, materialized knowledge graph image, and live demo link. Agentic Quick Start section with copy-paste prompt for coding agents (install, pg learn, start working). Running section covers both entry points: parseltongue TUI with command table and pg/pg-bench persistent daemon with full feature coverage (search with RRF ranking, structural lenses, holograms, consistency screening, time-travel history, interactive viz, pgmd notebooks). Updated demo count to 15 with live demos link. Removed Project Structure section.

Infrastructure

  • GitHub Actions: new pages.yml for automated GitHub Pages deployment
  • Security scanners: updated security.yml
  • Tooling: mypy, ruff, black configuration updates; ruff excludes tests
  • GPG signatures: verification instructions for release integrity
  • typing-extensions added as dependency
  • click>=8.0 added to base dependencies — required by bench_cli.py which is a core entry point (pg/pg-bench), not a cli extra

Breaking Changes

  • Default engine switched from recursive to stack-based. Behavior is identical; tracing output format differs.
  • (scope evaluation ...) renamed to (scope screen ...). Old name kept as alias.
  • OperationsSystem v2 (Python dispatch) replaces pltg rewrite axioms for set ops. Falls through to pltg engine for unknown operations — existing custom ops still work.

Migration

No action needed for most users. If you reference evaluation scope directly, update to screen (alias still works).


What's Changed

Full Changelog: v0.6.0...v0.7.0