Skip to content

feat(ui): WebUI code review fixes — hljs, emoji, mobile, slash commands - #4

Merged
forkwright merged 3 commits into
mainfrom
feat/webui-refinements
Feb 17, 2026
Merged

feat(ui): WebUI code review fixes — hljs, emoji, mobile, slash commands#4
forkwright merged 3 commits into
mainfrom
feat/webui-refinements

Conversation

@forkwright

Copy link
Copy Markdown
Owner

Code Review Fixes

Addresses all 10 issues from the Svelte 5 WebUI code review plus minor nits.

Changes

# Issue Fix
1 Sessions visible as concept Removed — continuity not sessions. Slash commands (/new, /clear) for rare manual control
2 Agent emoji fetched but not shown Surfaced in AgentCard, Message, MessageList, empty state
3 highlight.js bloat (969KB) Selective imports: 10 languages → ~84KB (91% reduction)
4 Tool result matching fragile Backend sends toolId in events, frontend matches by ID not name
5 Duplicate CSS Extracted to chat-shared.css with .chat-* prefix
6 No session creation UX Slash command /new with autocomplete popup
7 loadAgents() sequential Promise.allSettled — parallel identity fetches
8 No mobile responsiveness Collapsible sidebar, hamburger, overlay, media queries
9 historyToMessages fragile Match by toolCallId, flush orphaned tool calls
10 Close button literal 'x' Proper × symbol, ✓/✕ for tool status

Additional

  • Context proximity indicator (thin bar above input, yellow/red as approaching distillation)
  • Keyboard :focus-visible styles globally
  • aria-label on interactive elements
  • Active agent name shown in TopBar on mobile
  • · separator instead of `." in SessionItem

Bundle Size

Before After Δ
JS (total) 1,031 KB 199 KB -81%
JS (gzipped) ~355 KB ~68 KB -81%
CSS 18.75 KB 20.62 KB +1.87 KB

Verification

  • vite build — clean, no warnings
  • vitest run — 29/29 tests pass
  • svelte-check — 0 errors, 0 warnings
  • oxlint — 0 errors, 0 warnings
  • ✅ Runtime tsc --noEmit — clean (backend toolId change)

Backend Change

infrastructure/runtime/src/nous/manager.ts: Added toolId to tool_result stream event type and yield site. Non-breaking — frontend previously matched by name.

forkwright and others added 3 commits February 17, 2026 17:20
Agents were confined strictly to their workspace directory (nous/{id}/),
causing "Path outside workspace" errors when reading shared resources
like ui/, shared/, infrastructure/. Read-only tools (read, ls, find, grep)
now accept the aletheia root as an additional allowed path. Write tools
(write, edit) remain workspace-confined for safety.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
With 6 agents sharing one Signal account, 3 concurrent turns meant
a long-running turn could block other agents from responding.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ommands

Summary of changes from code review:

1. highlight.js tree-shaking: selective imports for 10 languages instead of
   all 90+. Bundle reduction from 969KB to ~84KB (91% smaller).

2. Agent emoji: surfaced in AgentCard, Message avatars, MessageList streaming
   avatar, and empty state. Falls back to initials when no emoji.

3. Tool result matching: backend now sends toolId in tool_result events,
   frontend matches by toolId instead of toolName+status (fixes concurrent
   same-tool-name bug).

4. Duplicate CSS extracted: chat-shared.css with .chat-msg-* prefixed classes
   replaces identical styles in Message.svelte and MessageList.svelte.

5. Slash commands: /new (fresh session), /clear (clear display) with
   autocomplete popup, keyboard navigation (arrows, tab, enter, escape).

6. Context proximity indicator: thin progress bar above input shows context
   window utilization. Colors shift yellow > red approaching distillation.

7. loadAgents() parallelized: Promise.allSettled instead of sequential awaits.
   6 agents now load in ~1 round trip instead of 6.

8. Mobile responsiveness: collapsible sidebar with hamburger menu, overlay
   backdrop, media queries at 768px breakpoint. Active agent shown in TopBar
   on mobile.

9. historyToMessages() improved: tool_result matched by toolCallId instead
   of array position. Orphaned tool calls flushed to last assistant message.

10. UI polish: close buttons use × not 'x', tool status uses ✓/✕ not ok/!,
    expand uses − not -, dot separator · not '.', keyboard :focus-visible
    styles, aria-labels on interactive elements.

Build: 199KB JS (was 1031KB), 20.6KB CSS, 29 tests pass, 0 type errors.
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
2 Security Hotspots

See analysis details on SonarQube Cloud

@forkwright
forkwright merged commit e4e4fb7 into main Feb 17, 2026
11 of 13 checks passed
@forkwright
forkwright deleted the feat/webui-refinements branch February 17, 2026 23:36
forkwright added a commit that referenced this pull request Feb 18, 2026
…commands (#4)

Addresses all 10 issues from code review plus nits.

- highlight.js: 969KB → 84KB (selective imports, 10 languages)
- Agent emoji surfaced in avatars, empty state
- Tool result matching by toolId (backend + frontend)
- Duplicate CSS extracted to chat-shared.css
- Slash commands (/new, /clear) with autocomplete
- Context proximity indicator
- loadAgents() parallelized
- Mobile: collapsible sidebar, hamburger, media queries
- historyToMessages() toolCallId matching
- UI polish: ×, ✓/✕, ·, focus-visible, aria-labels

Bundle: 1031KB → 199KB JS (-81%)
forkwright pushed a commit that referenced this pull request May 9, 2026
…enums + provider verify + self-prompting (closes #1 #2 #4) (#147)

Manually merged via local validation (bypass of kanon CI gate). All
gates verified locally: fmt + check + clippy + kanon lint (PR-scoped).

Admin-Bypass: operator-blessed bypass during CI hygiene work (2026-05-09)
forkwright pushed a commit that referenced this pull request May 22, 2026
…enums + provider verify + self-prompting (closes #1 #2 #4) (#147)

Manually merged via local validation (bypass of kanon CI gate). All
gates verified locally: fmt + check + clippy + kanon lint (PR-scoped).

Admin-Bypass: operator-blessed bypass during CI hygiene work (2026-05-09)
forkwright added a commit that referenced this pull request May 29, 2026
#4316)

## Summary

Implements
[B-002](https://github.com/forkwright/aletheia/tree/main/planning/poiesis-evolution/B-002-poiesis-theme-registry.md)
from the poiesis-evolution planning cluster (kanon#985, merged 7199d54):
the new `poiesis-theme` sub-crate that owns the brand-truth surface
every poiesis render path consumes.

The crate ships **one source → three sinks**: a `themes/<id>.toml` file
resolves into a `ResolvedTheme`, which emits CSS custom properties, an
OOXML `theme1.xml` `clrScheme`+`fontScheme`, and a Pandoc-shaped
doc-vars map. Adding a brand is a new TOML file; no code change.

## What ships

- **`ThemeId` newtype** — parse-don't-validate boundary.
Registry-friendly, CSS-safe, URL-safe identifier with width 2..=64 and
alphabet `[a-z][a-z0-9_-]*`.
- **TOML token model** — `[color.{role,tone,surface}]`,
`[type.{family,scale,role}]`, `[space]`, `[grid]`, `[table]`, `[chart]`.
Components reference token names; the only place raw hex lives is
`[color.role]`.
- **`HexColor` newtype** — normalizes to canonical `#RRGGBB` so emission
is byte-stable across hosts and runs.
- **`Registry::load_dir`** — discovers `themes/<id>.toml`, enforces
filename-stem ↔ `meta.id` agreement, sorts deterministically.
- **`ResolvedTheme`** — dereferences tone and surface references to
concrete hex values; unknown roles surface as `ThemeError::UnknownRole`.
- **Three sinks** (all byte-stable, deterministic):
- `sinks::css::emit_css` — `:root { --color-<role>; --tone-<name>:
var(--color-<role>); --type-<role>-<slot>; … }`.
- `sinks::ooxml::emit_theme_xml` — `<a:theme>` with `<a:clrScheme>`
(dk1/lt1/dk2/lt2/accent1..6) + `<a:fontScheme>` (major=serif,
minor=sans). Native PowerPoint charts bind to `accent1..3`, so
recoloring the theme recolors charts.
- `sinks::docvars::{emit_docvars_json, emit_docvars_yaml}` —
Pandoc-friendly flat key→value map.
- **Three `THEME/*` lint rule shapes** (`lint::{RawColorLiteralRule,
RawFontLiteralRule, UnknownTokenRule}`) — each returns
RFC-6901-pointer-carrying violations the QA gate consumes.
- **Seed `summus` theme** — spec-03 brand palette (navy/teal/rose,
Geist/Newsreader/Geist Mono, 1920×1080 type scale).

## Deferred (the stub-then-real plan)

Per the B-002 acceptance gate carve-out (PR-body deferral path). Each
deferred item has a named successor entry that owns the work; nothing
here blocks because the missing pieces only land when the downstream
crates land.

| Deferred surface | Owner | Why deferred |
|---|---|---|
| Full `assets/<name>-base.pptx` raw-OOXML pack (slide master +
per-component layouts) |
[B-004](https://github.com/forkwright/aletheia/tree/main/planning/poiesis-evolution/B-004-poiesis-deck-pptx.md)
| Pack/unpack pattern belongs with the PPTX emitter that owns the rest
of the file shape. This PR emits the `theme1.xml` body the pack will
embed. |
| Reference assets generation (`reference.docx`, `reference.odt`,
`template.typ`, `template.latex`) |
[B-006](https://github.com/forkwright/aletheia/tree/main/planning/poiesis-evolution/B-006-poiesis-doc-pandoc.md)
| The doc-vars map ships now; document-specific reference assets compose
with the doc-pandoc pipeline. |
| `Renderer` trait `&ResolvedTheme` parameter wiring |
[B-001](https://github.com/forkwright/aletheia/tree/main/planning/poiesis-evolution/B-001-poiesis-model-registry.md)
| The `Renderer` trait evolves in `poiesis-core` as part of B-001's
envelope refactor; threading the `ThemeId` → `ResolvedTheme` through
that interface lands there. |
| `theme list/show/new/validate/compile` CLI verbs |
[B-010](https://github.com/forkwright/aletheia/tree/main/planning/poiesis-evolution/B-010-poiesis-mcp-cli.md)
| CLI surface aggregator. The registry API is ready; verbs are a thin
wrap on top. |
| Registering THEME/* rules with the basanos engine |
[B-008](https://github.com/forkwright/aletheia/tree/main/planning/poiesis-evolution/B-008-poiesis-qa-moat.md)
| Rule shapes (id, scan/check API, violation type) ship in this PR;
engine registration is the QA-moat crate's job. |
| Byte-stable CSS regression against the offsite deck |
[B-003](https://github.com/forkwright/aletheia/tree/main/planning/poiesis-evolution/B-003-poiesis-deck-html-pdf.md)
/
[B-011](https://github.com/forkwright/aletheia/tree/main/planning/poiesis-evolution/B-011-poiesis-testing-substrate.md)
| Need the deck artifact and the golden harness to assert against. |

## Acceptance gate coverage

| B-002 acceptance criterion | This PR |
|---|---|
| #1 `theme compile summus` emits CSS, OOXML, doc-vars matching spec |
CSS + OOXML `theme1.xml` + doc-vars all emit the spec-03 values; PPTX
pack deferred to B-004. |
| #2 swap `summus → ardent` restyles with zero spec edits |
Architecturally enabled (tone refs + sink emission are
theme-id-agnostic); end-to-end regression deferred to B-011 §theme-swap.
|
| #3 raw hex/font literal in a spec field fails
`THEME/raw-color-literal`/`-font-literal` with JSON-pointer | Rule
shapes + APIs ship; basanos engine registration deferred to B-008. |
| #4 unknown token fails `THEME/unknown-token` at load time |
`UnknownTokenRule::check` ships with pointer-carrying violations;
runtime path also surfaces `ThemeError::UnknownRole` if a renderer asks
for a missing tone. |

## Test plan

- [x] `cargo test -p poiesis-theme` — 68 unit + 2 integration green
- [x] `cargo clippy -p poiesis-theme --all-targets -- -D warnings` clean
- [x] `cargo fmt -p poiesis-theme -- --check` clean
- [x] `cargo check -p poiesis-core -p poiesis-lint` still passes (no
neighbour breakage)
- [x] `kanon lint` — 42 → 20 warnings; remaining 20 enumerated below
- [x] `kanon name_check summus` — `status: free`
- [x] Byte-stability tests across all three sinks (emit twice, assert
equal)
- [ ] Cross-target render proof (depends on B-003/B-004/B-006)

## Known kanon-lint warnings

The remaining 20 warnings are documented intentional architecture or
ambient project-wide:

- **9 × `RUST/pub-visibility` (Info)** — public items intended for
sibling-crate consumption by [B-001], [B-003], [B-004], [B-006],
[B-008]. Documented in `crates/poiesis/theme/CLAUDE.md` §Status table.
- **9 × `PERFORMANCE/clone-in-loop` (Warning)** in `sinks/docvars.rs` —
building a `serde_json::Value` tree from `IndexMap<String, _>` requires
owned `String` keys (serde_json's `Map` key type is `String`, not
`&str`). Refactoring to `Cow` would need a parallel JSON-tree
representation.
- **1 × `RUST/primitive-for-domain-id` (Warning)** on
`Violation.rule_id: String` — the rule id matches the basanos engine's
string-keyed rule registry; a newtype here would not improve the
boundary because the consumer carries the same shape.
- **1 × `OPERATIONS/no-runbook` (Info)** — project-wide, ambient.

## GNOMON layer check

- **`poiesis-theme` (crate)** — L1: 13-char identifier, pronounceable,
grep-friendly. L2: matches `poiesis-{core,lint,sheet,…}` sibling
convention. L3: English `theme` is the role; the Greek work (`poiesis =
ποίησις, "making"`) lives at the family-name layer. L4: composes with
siblings; no semantic collision; the crate sits at the
brand-truth/registry slot the family was missing.
- **`summus` (seed theme)** — L1: 6 chars, pronounceable, grep-friendly,
`status: free` per `kanon name_check`. L2: brand/theme name in the
`themes/<id>.toml` namespace; sibling slot to future themes (e.g.
`ardent`). L3: Latin "highest, supreme"; indicates the
flagship/canonical theme. Latin not Greek; locked by upstream apodeixis
Phase-00 spec, not chosen here. L4: composes — future themes form a
sibling palette.



## SonarCloud quality gate: spurious SCA finding

The SonarCloud "C Security Rating on New Code" failure on this PR is a
single SCA (dependency-analysis) annotation against the new crate's
`Cargo.toml`:

> Dependency versions are not predictable if the lock file (Cargo.lock)
is missing.

This is a **false positive** for a cargo-workspace member crate. Cargo
workspaces produce one shared `Cargo.lock` at the workspace root; member
crates do not (and should not) carry their own lockfile — see [The Cargo
Book §Cargo.toml vs
Cargo.lock](https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html)
and the [Cargo workspace
resolver](https://doc.rust-lang.org/cargo/reference/resolver.html). The
repo's authoritative `Cargo.lock` lives at the workspace root (also
touched by this PR for the new member's transitive deps), so every
dependency *is* pinned to an exact version — Sonar's SCA simply does not
walk back to the workspace root from a member `Cargo.toml`.

**Operator decision:** marked spurious. Suggested durable fix (separate,
repo-wide PR) is one of:

- Add a `sonar-project.properties` at the repo root with
`sonar.exclusions=crates/**/Cargo.toml` (excludes member manifests from
SCA only — root `Cargo.toml` + `Cargo.lock` still drive dependency
analysis), **or**
- Wait for SonarCloud SCA to learn cargo-workspace lockfile inheritance
(raised upstream at [SonarSource SCA
troubleshooting](https://docs.sonarsource.com/sonarqube-cloud/advanced-security/troubleshooting-the-dependency-analysis)).

Other checks on this PR are green (no AI attribution, gate-attestation
with `Gate-Passed: kanon 0.1.0`, cargo deny, scan). The included
refactor commit centralizes the spec-mandated XML namespace constant —
orthogonal quality work, not a Sonar fix.

---------

Co-authored-by: forkwright <forkwright@users.noreply.github.com>
forkwright added a commit that referenced this pull request May 29, 2026
## Summary

- Scaffolds the new aletheia-internal `poiesis-charts` crate per
[B-005](https://github.com/forkwright/kanon/blob/main/projects/aletheia/planning/poiesis-evolution/B-005-poiesis-charts.md)
(poiesis chart subsystem — hand-rolled SVG + Vega-Lite fallback).
- Lands the parse-don't-validate `Chart` model, the static render-path
decision rule, the deterministic SVG combo emitter that reproduces the
offsite slide-3 chart geometry, and the theme-binding seam
(`Themed`/`Resolved` color modes).
- Ships per-kind design notes for the eight stubbed emitter arms
(`bar`/`column`/`line`/`area`/`scatter`/`pie`/`doughnut`/`stat`) so the
implementation fan-out is unblocked.

## Crate shape

```
crates/poiesis/charts/
├── Cargo.toml          # poiesis-core + serde + snafu + tracing; insta dev-dep
├── CLAUDE.md
├── docs/design/        # one .md per stubbed kind
└── src/
    ├── lib.rs          # module map + determinism contract + #![deny(missing_docs)]
    ├── error.rs        # Error::{InvalidJson,BadSeriesShape,NakedNumber,VegaRequired,UnresolvedTone,UnresolvedFact,EmitterStub}
    ├── model.rs        # Chart, Series, Axes, FactCite, ChartKind::{render_path,name}
    ├── format.rs       # format_number (only f64→<text> path) + coord (only f64→attr path)
    ├── scale.rs        # Scale + nice() + ticks(); offsite y_left/y_right covered
    ├── theme.rs        # ResolvedTheme + ColorMode + summus stub (deleted when B-002 lands)
    └── render/
        ├── canvas.rs   # Deck (1600×540) + Doc canvases; PlotBox
        ├── kinds.rs    # mod combo;
        ├── kinds/combo.rs  # implemented arm
        └── vega.rs     # cfg(feature = \"charts-vega\") stub
```

## What's implemented vs. stubbed

| Arm | Status |
|---|---|
| `combo` | **Implemented** — renders the offsite navy/teal dual-axis
combo. `rx=3` columns, `r=9` markers, polyline. Themed mode emits
`var(--tone-*)`, Resolved emits literal hex. |
| `bar`, `column`, `line`, `area`, `scatter`, `pie`, `doughnut`, `stat`
| Stubbed (`Error::EmitterStub`). Per-kind design under
`docs/design/<kind>.md`. |
| `heatmap`, `boxplot`, `sankey`, `candlestick`, `log`/`time` scales |
Routed to `charts-vega` feature. Hard-fail with `Error::VegaRequired`
when disabled. |
| `combo` gridlines + tick text | Structural `<g class=\"gridlines\">` /
`<g class=\"axes\">` placeholders emitted. Tick math is in
`scale::ticks` but not yet wired into the emitter. |
| `insta` golden snapshot of the full offsite SVG | Pending — lands with
the gridline + tick text follow-up. |
| Vega-Lite shell-out wiring | Pending. `render/vega.rs` exists as a
feature-gated stub. |

## B-005 acceptance — current state

| # | Acceptance criterion | Status in this PR |
|---|---|---|
| 1 | Reproduce offsite slide-3 chart from schema | Geometry + colors +
corners + markers present; gridlines + tick text follow-up. |
| 2 | Colors come only from `theme: summus`; zero color literals in spec
| `ResolvedTheme::summus_stub` mirrors the offsite palette; tests assert
navy/teal route via theme. |
| 3 | All data points are `Cite(FactId)`; verify reconciles | `Point::y:
FactCite` types it in. Verifier integration lands with B-008. |
| 4 | Emitted SVG is deterministic (`insta` golden) |
Re-emit-must-be-byte-identical test in place; full byte-golden of the
offsite SVG follows the gridline/tick arm. |
| 5 | Same SVG embeds in HTML deck (`themed`) and PPTX (resolved or
baked) | `ColorMode::Themed`/`Resolved` both emit; HTML/PPTX wiring
lands with B-003/B-004. |
| 6 | Switching theme recolors with zero spec edits | `ResolvedTheme` is
the seam; swapping it switches every fill/stroke. |
| 7 | Vega-only kind with `charts-vega` off → hard parse error |
`Chart::validate` returns `Error::VegaRequired`. Tested. |

## Completion plan for follow-ups

Each stub is tracked in `crates/poiesis/charts/docs/design/<kind>.md`.
The natural ordering:

1. **`combo` gridlines + tick text + `insta` golden** — closes the
determinism leg of acceptance #4.
2. **`column` + `line` arms** — direct extracts from the `combo`
primitives (~70% reuse).
3. **`bar` + `area` + `scatter`** — small variations on column/line.
4. **`pie` + `doughnut` + `stat`** — share an arc-path primitive.
5. **Vega-Lite wiring in `render/vega.rs`** — under the `charts-vega`
feature.
6. **B-002 wire-up** — delete `ResolvedTheme::summus_stub` and depend on
`poiesis-theme` when it lands.

## Gate

- `cargo fmt --check` — PASS
- `cargo check --workspace` — PASS
- `cargo clippy -p poiesis-charts --all-targets -- -D warnings` — PASS
- `cargo test -p poiesis-charts` — PASS (30 tests)
- `kanon gate --tier full` — PASS (Gate-Passed trailer on HEAD)
- `mcp__kanon__standards_name_check word=charts` — free (no collisions)

## Naming

`charts` passes GNOMON L1–L4:

- **L1**: lowercase ASCII, pronounceable, grep-friendly, 6 chars.
- **L2**: follows the existing poiesis sub-crate register (`slides`,
`sheet`, `text`, `doc`, `lint`, `verify`, `intake`, `scaffold`,
`inspect`, `typst`, `diff` — English domain words rather than Greek
roots, deliberately distinct from the `aletheia/`/`theatron/`
Greek-named cognition substrate).
- **L3**: matches what the crate is — the chart subsystem of the report
family.
- **L4**: every chart kind name (`bar`, `column`, `line`, `area`,
`combo`, `scatter`, `pie`, `doughnut`, `stat`, `heatmap`, `boxplot`,
`sankey`, `candlestick`) is the canonical chart-vocabulary word —
name-checked free, no Greek strain.

## Test plan

- [ ] CI nextest on poiesis-charts
- [ ] Confirm `--all-targets` clippy still passes under workspace-wide
gates
- [ ] Operator review of `docs/design/*.md` before kicking off the
per-kind fan-out

## SonarCloud quality gate: spurious SCA finding

The SonarCloud "C Security Rating on New Code" failure on this PR is a
single SCA (dependency-analysis) annotation against the new crate's
`Cargo.toml`:

> Dependency versions are not predictable if the lock file (Cargo.lock)
is missing.

This is a **false positive** for a cargo-workspace member crate. Cargo
workspaces produce one shared `Cargo.lock` at the workspace root; member
crates do not (and should not) carry their own lockfile — see [The Cargo
Book §Cargo.toml vs
Cargo.lock](https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html)
and the [Cargo workspace
resolver](https://doc.rust-lang.org/cargo/reference/resolver.html). The
repo's authoritative `Cargo.lock` lives at the workspace root (also
touched by this PR for the new member's transitive deps), so every
dependency *is* pinned to an exact version — Sonar's SCA simply does not
walk back to the workspace root from a member `Cargo.toml`.

**Operator decision:** marked spurious. Suggested durable fix (separate,
repo-wide PR) is one of:

- Add a `sonar-project.properties` at the repo root with
`sonar.exclusions=crates/**/Cargo.toml` (excludes member manifests from
SCA only — root `Cargo.toml` + `Cargo.lock` still drive dependency
analysis), **or**
- Wait for SonarCloud SCA to learn cargo-workspace lockfile inheritance
(raised upstream at [SonarSource SCA
troubleshooting](https://docs.sonarsource.com/sonarqube-cloud/advanced-security/troubleshooting-the-dependency-analysis)).

Other checks on this PR are green (no AI attribution, gate-attestation
with `Gate-Passed: kanon 0.1.0`, cargo deny, scan). The included
refactor commit centralizes the spec-mandated XML namespace constant —
orthogonal quality work, not a Sonar fix.

---------

Co-authored-by: forkwright <forkwright@users.noreply.github.com>
forkwright added a commit that referenced this pull request Jun 9, 2026
B-006 Chunk E (B-012 acceptance #4). Bans the pandoc + pandoc_ast Rust
crates via cargo-deny [bans] with WHY reasons, enforcing the GPL-clean
subprocess boundary: aletheia invokes the pandoc binary as an external
subprocess and must never link a GPL Haskell-FFI binding. cargo deny
check bans passes on the current tree (no such crate present) and would
fail if one were added. Config-only; audit.toml/osv-scanner.toml left
unchanged (they only mirror advisory ignores). No legit deps
(resvg/zip/etc.) affected.

Co-authored-by: Cody Kickertz <admin@forkwright>
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.

1 participant