CI/CD: add CI and release workflows - #44
Closed
saieeshward wants to merge 116 commits into
Closed
Conversation
…ner format for passing structured context between AI agents and rendering it for humans.
- TOON (Token-Oriented Object Notation) used for injecting shared/data.yaml and decision-chain.yaml to agents (~40% token reduction per call) - Agent output remains JSON for reliability and schema validation - Updated XON-SPEC.md Section 14 with full TOON injection protocol - Updated implementation checklist with TOON requirement - Updated spec/agent-guide.md to declare TOON format for injected data - Updated spec/xon.md with injection serialisation note - Updated ARCHITECTURE.html tech stack and token budget diagram - Added Apache 2.0 LICENSE file
Format renamed to LACE — Living Agent Context Envelope. - XON-SPEC.md → LACE-SPEC.md - spec/xon.md → spec/lace.md - All content updated: name, expansion, pronunciation, file extension (.lace), MIME type (application/vnd.lace), protocol (lace://), manifest keys (lace_version), postMessage type (lace-edit), CSS tokens (--lace-*) - Origin metaphor updated: envelope/lace-weaving replaces nerve-axon metaphor
Format renamed to CLAN — Context Lineage Agent Notation. - LACE-SPEC.md → CLAN-SPEC.md - spec/lace.md → spec/clan.md - All content updated: name, expansion, pronunciation, file extension (.clan), MIME type (application/vnd.clan), protocol (clan://), manifest keys (clan_version), postMessage type (clan-edit) - Metaphor updated: lineage/ancestry replaces lace-weaving
Four changes informed by MAIF (arXiv 2511.15097): 1. SHA-256 hashes on all manifest file entries — tamper detection at near-zero cost; verified on open, warning on mismatch. 2. parent_sha256 in lineage block — cryptographically verifiable lineage chain; any modification to a parent file is detectable when walking the provenance history. 3. Lazy loading contract — SDK must not read entries outside the required role set for the current operation. agent/ never read when rendering for humans; human/ never read when assembling agent context. 4. Concurrency implementation note — single-threaded and correct before any parallelism. Based on documented 96% throughput regression in comparable systems from premature parallelism.
Decision-chain compression redesigned from scratch: - Removed LLM dependency from write path entirely - Two-tier model: verbatim window (default N=5) + compressed tail - SDK NLP pipeline: YAKE keyword extraction + sentence scoring + position weights (last sentence +0.20) + numeric lock + identifier preservation. Pure Rust via yake-rust crate. ~0.5ms per entry. - Short-circuit: entries already under char budget stored verbatim - pinned: true field — agents opt entries out of compression permanently - CompressorFn callback API for optional AI override - App-layer optional enhancement: SmolLM2-135M or platform NLP API - Updated CLAN-SPEC.md §7, §20 checklist - Updated spec/clan.md embedded reference - Updated spec/agent-guide.md with pinning instructions for agents - Updated SESSION-SUMMARY.md with all session decisions
clan-sdk (Rust library):
- container.rs — ZIP read/write with lazy loading + SHA-256 per entry
- manifest.rs — full manifest model, validation, UUID v4 checks
- hash.rs — SHA-256 with sha256:<hex> prefix, verify helpers
- decision.rs — decision-chain model with pinned flag
- toon.rs — TOON serialiser (Token-Oriented Object Notation)
- compress.rs — YAKE-style NLP pipeline: keyword extraction + sentence
scoring + position weights + numeric lock + identifier
preservation. Verbatim window N=5, CompressorFn override.
- validate.rs — §17 structural + content + integrity validation
- inject.rs — agent context assembly in spec §14 injection order
- pack.rs — pack next-gen .clan from agent output (all 3 modes)
- create.rs — bootstrap .clan from title/brief; static export
clan-cli (binary):
- clan create — new .clan from title + brief
- clan validate — structural + content validation report
- clan read — agent context, human HTML, data, decision chain
- clan info — manifest metadata + sha256 + lineage
- clan pack — pack agent JSON output into next .clan
- clan export-static — flatten .clan to single JSON for SDK-less agents
15 tests passing. Full round-trip verified:
create → validate → pack → validate → info (lineage) → export-static
Tauri 2 + React + TypeScript desktop viewer for .clan files.
Rust backend (app/src-tauri/src/main.rs):
- open_clan: open .clan file, return manifest info + validation status
- get_human_html: render human/index.html with {{token}} data binding
resolution from shared/data.yaml and human/patches.yaml application
- get_data / get_chain / get_agent_state / get_context: lazy reads
React frontend (app/src/):
- Toolbar: file open, agent panel toggle, validation badge
- Sidebar: document metadata, identity (id + sha256), lineage
- DocumentView: renders agent HTML in sandboxed iframe with base styles
- AgentPanel: collapsible panel with Decisions / State / Context tabs
- Welcome: onboarding screen with open button
Full workspace builds clean. 15 tests passing.
- Remove empty dialog plugin config from tauri.conf.json (caused PluginInitialization error: expected unit, got map) - Remove unused package metadata from app/src-tauri/Cargo.toml
Tauri 2 blocks all plugin calls by default. The file picker was failing with 'permission not allowed' because dialog:allow-open was not declared in a capabilities file. Added default.json granting core:default, dialog:allow-open, and dialog:allow-save.
Agent HTML fragments cannot use external URLs (spec §8 security), so the viewer injects base CSS. Previous base was minimal — improved to provide rich typography, card/grid/table patterns, code blocks, badges, utility colours, and smooth scrollbar. Visually closes the gap with standalone HTML that can load external fonts/libraries.
Rendering:
- Remove HTML fragment restriction — agents can now produce full HTML
documents with html/head/body tags, Google Fonts, CDN stylesheets,
external images, anything. Only <script> tags and on* handlers are
stripped by the SDK to prevent XSS.
- Tauri CSP relaxed: allows external fonts, styles, images from https.
- DocumentView detects full doc vs fragment automatically.
- iframe sandbox upgraded to allow-scripts + allow-same-origin so the
viewer's edit bridge can execute (agent scripts already stripped at pack time).
Edit mode (Phase 7):
- Toolbar: ✏️ Edit button (only shown when a file is open); active state
shows green "● EDITING" badge.
- Edit bridge: JS injected by the viewer (not from agents) makes every
element with data-adf-id contenteditable with an indigo outline.
On blur, sends postMessage({ type: 'clan-edit', id, content }) to parent.
- App.tsx: listens for clan-edit messages, calls save_patch Tauri command,
then re-fetches and re-renders the HTML with patches applied.
- save_patch Rust command: reads patches.yaml from the open .clan ZIP,
upserts the patch by id, repacks the archive, writes back to disk,
reloads in-memory ClanFile so state stays current.
- patch.rs: new SDK module for Patches model and apply_patch_and_repack().
- strip_scripts(): replaces ammonia::clean() — allows all HTML, removes
only script blocks and on* event handlers.
Race condition fix:
- Store editMode in a ref so onLoad always sees the current value
- Send edit-mode state on iframe onLoad (not just on editMode change)
so the bridge never misses the activation signal
Edit bridge improvements:
- Remove early-exit guard that prevented re-activation
- Track wired elements with data-clan-editing to avoid double-binding
- Add outline-offset and transition for polished visual indicator
- Inject a floating toast hint ('Click any highlighted element to edit it')
that fades after 3s so users know edit mode is active
- Deactivate properly cleans up data-clan-editing attribute
Four bugs fixed:
1. apply_patches (main.rs): old code used find('<') to locate the end of
element content, which stopped at the first child tag (e.g. <br/>, <span>).
For <h1>text<br/><span>more</span></h1>, patching only replaced "text"
and kept the span — causing both the edited text AND the original span
text to appear. Replaced with find_closing_tag() which tracks nesting
depth and finds the real </tagN> match.
2. Concurrent patch race (App.tsx): handlePatch was fully async with no
guard. Two rapid blur events (e.g. tab between fields) would start
two concurrent save_patch + get_human_html chains. The second
get_human_html could resolve before the first patch was visible,
leaving state inconsistent. Added patchInFlight ref to drop
concurrent calls while a save is in progress.
3. Validator false positives (validate.rs): content_checks still flagged
<html>, <head>, <body> as forbidden — but spec was updated to allow
full HTML documents. Removed those checks; only <script> and on*
attributes remain flagged.
4. Validation detail invisible (Toolbar.tsx): badge showed only "issues"
with no way to read the actual messages. Added title={validation} so
hovering the badge shows the full validation report.
Logging added to main.rs: save_patch, get_human_html, and apply_patches
all write to /tmp/clan-debug.log with timestamps.
Three changes driven by Agent 3 post-mortem: 1. clan agent-help Compact (<200 token) agent-specific quick reference. Shows only what an agent needs: read agent, pack, pack-html. Warns explicitly not to run `clan read data` after `clan read agent` (same content, ~4,250 wasted tokens). Human --help remains unchanged. 2. clan pack-html + pack_html() SDK function Eliminates the largest measured token cost from the Agent 3 run: JSON-encoding a 12 KB HTML string expanded it to ~62 KB (~15,500 tokens of output, pure overhead). Agents now write a raw .html file, the operator runs pack-html. Accepts optional YAML frontmatter (--- block at file top) for structured data + decision entry. Tested end-to-end against invest-final.clan. 3. Better clan create context.md template The blank brief produced a blank design mandate — agents defaulted to "functional and complete" because context.md said nothing about quality. Template now includes Design Requirements section: full HTML docs, Google Fonts, dark theme, SVG assets for charts, typography hierarchy, data-adf-id coverage. Users can edit or delete it; it sets the floor by default. spec/agent-guide.md updated with duplicate-read warning and pack-html path docs.
Root cause: the iframe had sandbox="allow-scripts allow-same-origin" which gave agent scripts same-origin access to the Tauri shell — meaning a compromised agent could call window.__TAURI__ and invoke OS-level commands. This was the real reason <script> tags were banned. Fix: remove allow-same-origin. srcDoc iframes without allow-same-origin get a null/opaque origin. Agent scripts are fully isolated — no Tauri IPC, no parent localStorage, no app state. postMessage (used by the edit bridge) is explicitly cross-origin compatible and is unaffected. Result: agents now have full JS capability — D3, Chart.js, count-up animations, SVG manipulation, scroll effects, interactive filters, tabs/accordions, anything. The sandbox still prevents actual harm; it just no longer prevents useful work. Changes: - DocumentView.tsx: sandbox="allow-scripts allow-popups" (removed allow-same-origin) - pack.rs: removed strip_scripts() call from full-html packing path - validate.rs: removed <script> and on* content warnings (no longer forbidden) - CLAN-SPEC.md, spec/clan.md, spec/agent-guide.md: updated security rules
final-clan-visual.clan — visual demonstration of the unrestricted rendering spec: complete <!DOCTYPE html> document with Playfair Display + IBM Plex fonts via Google Fonts CDN, animated ticker tape, hero stats, tax card grid, allocation bar charts, platform table, getting-started steps. 105 data-adf-id attributes. Modeled on irish-investor-guide.html to benchmark agent visual output quality. job-research pipeline — three-agent simulation run: job-research.clan agent 1 input (research brief) job-research-a2.clan agent 2 pass (analysis) job-research-a3.clan agent 3 pass (final output) job-context.json static export used for agent 1 These files captured the token-overhead and design-quality issues that drove the agent-help, pack-html, and JS-unlock changes in this branch. Updated clan-research-report.clan and invest-final.clan carry the updated embedded spec (agent-guide.md with JS-allowed and pack-html instructions).
…it-mode Feature/unrestricted render edit mode
…eedom Feature/agent full creative freedom
This basically removed the null error.
- Numbers-at-a-glance strip under the pitch - Handoff-layers matrix (guided/unguided x CLAN/ad-hoc) - Measured claims table with thresholds (ratios + percent equivalents) - Merge-catch and HITL comparison tables - Honest token table (where CLAN loses) + verification status table
…-lean commands - Drop unmeasured-claims bullet and findings-count line (noise for release readers) - Why a CLI: command-by-command table of token savings (read agent, patch-data, patch-html, pack-html, merge) tied to the measured 42% revision saving
…ms pass, no regressions First scorecard run on a second platform (macOS arm64; prior runs Windows). Values reproduce exactly: revision 0.576, synthesis 0.557, provenance 1.125.
…e positive
CLAN_NO_HINTS="" (empty string) was treated as disabled by is_none().
Changed to map_or(true, |v| v.is_empty()) so empty = hints on. This
fixes the T20 false positive in the conformance harness (the test sets
CLAN_NO_HINTS="" intending hints-on, but hints were always off).
F2b: file_state_hints now accepts patch_keys: Option<&[String]>.
cmd_patch_data passes the top-level merge-patch keys. When all changed
keys are {{bound}} in human/index.html, the stale hint is suppressed
(view auto-renders). When some keys are unbound, the hint names them
("data key(s) not reflected in view (x, y) — use pack-html or
patch-html"). Generic stale hint fires only when key context is absent.
New helpers: extract_binding_keys() — single-pass {{key}} scanner.
New tests: patch_data_bound_key_suppresses_stale_hint,
patch_data_unbound_key_names_orphan_in_hint. All 47 CLI + 120 SDK
tests pass. 26/26 D-CONF (T20 now correct). Run 2026-06-12-F recorded.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…/clan into feature/MultiAgentic
…issing icons - Add create-release job so CLI and desktop jobs upload into one release instead of racing to create it - Build macOS viewer as universal-apple-darwin (one DMG for arm64 + x86_64) - Track the Tauri icon set (PNGs + icns) the bundler requires in CI - Bump tauri.conf.json version 1.0.0 -> 1.1.0 to match the workspace
… constellation mark Generated full platform set (icns/ico/PNGs) from design/assets/clan-icon.svg via 'cargo tauri icon'. The old icons were a flat #6366f1 square with no mark.
Replace the hardcoded static SVG copy in Toolbar with the designed ClanMark component from design/ClanMark.tsx (duo-tone, animated lineage variant). The mark now animates while a file is loading.
app/src-tauri was excluded from the rust job (needs GTK/WebKit system packages) so viewer Rust breakage only surfaced at release time. New job installs the same deps as the release desktop build, builds the frontend (generate_context! embeds dist at compile time), then clippy + tests clan-app. Also inherit the workspace version (was stuck at 1.0.0).
…tGTK deps" This reverts commit b05877f.
…n wall times, EXPECT-RED gaps, binary install - Replace stale scorecard table with latest run (0.639x revision, 0.487x synthesis, TOON 57.5%, scaffold a=2,668) incl. both EXPECT-RED rows - New long-chain section: H1/H2 wall times, synthesis-hop timing, cold resume, unguided protocol discovery - Expand 'Where CLAN loses': no crossover by hop 10, modest wall-time gains, unpopulated L5 layer, run-to-run variance disclosure - Point install at Releases binaries; note Windows+macOS conformance
Also added tasks for new files The Windows release now produces one MSI that installs the viewer and the `clan` CLI (added to the per-machine PATH), replacing the separate viewer MSI and standalone CLI zip. - tauri.windows.conf.json: Windows-only config (auto-merged) — msi-only target, bundle `clan` as an externalBin sidecar, wire the WiX PATH fragment. - wix/cli-path.wxs: append INSTALLDIR to the system PATH (removed on uninstall), anchored to an HKLM keypath. - release.yml: drop the Windows target from cli-binaries; build + stage the CLI sidecar in the Windows desktop job before tauri-action. - .gitignore: ignore the generated app/src-tauri/binaries/. Verified by building CLAN Viewer_1.1.2_x64_en-US.msi locally: contains both clan.exe and clan-app.exe in INSTALLDIR, PATH Environment entry present, one bundle (no NSIS).
Linux .deb and .rpm now install the `clan` CLI to /usr/bin (on PATH) alongside the viewer, mirroring the combined Windows MSI. - tauri.linux.conf.json: Linux-only config (auto-merged) mapping binaries/clan -> /usr/bin/clan via deb.files and rpm.files. - release.yml: build + stage the CLI in the Linux desktop job before tauri-action. The AppImage stays viewer-only (it can't place files on the host PATH), so the standalone Linux CLI tarball is kept for AppImage users. macOS is unchanged (no .pkg/postinstall in Tauri) — viewer DMG and CLI tarballs remain separate. Note: .deb/.rpm bundling only runs on Linux, so this was not built locally (Windows host); it will be exercised in CI on the next tag.
Feat/combined windows msi
The v1.1.2 launch-file-open feature added pending_open to AppState but the test helper empty_state() was not updated, so clan-app failed to compile and aborted cargo test --workspace (exit 101). Restores a green workspace test run (186 passed / 0 failed).
- TestResult.clan: full-suite run (14 tests) with corrected H-H1 (rep4 5/8 fidelity + false-provenance finding) and H-H2 blocked (crossover unproven; resume-on-dirty-state polluted the measure). - run-claim-specific.workflow.js: B-FORKMERGE/B-UNGUIDED/B-META/L-H3. - heavy workflow: measure step uses node measure-heavy.mjs (no pwsh on mac).
- Add Highlights block + Campaign 3 (full TESTBOOK heavy run). - Feature fork/merge, metamorphosis, teachability, cold-resume wins. - Flag synthesis-hop ratio NOT ROBUST (0.487x -H -> 1.047x -I). - Add provenance-integrity finding (rep4 5/8 + false-provenance) and non-idempotent-append caveat; crossover unproven even at heavy scale. - Test counts 165 -> 186 (banner, scorecard, Status).
ci(release): v1.1.0 release fixes — universal DMG, runner fix, icons
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds two GitHub Actions workflows (see TODO.md):
main: Rust (fmt/clippy/test on clan-sdk+clan-cli), Frontend (lint/tsc/build), and the conformance harness against a releaseclanbinary.v*tag: CLI binaries (linux/macOS/windows) + Tauri desktop bundles via tauri-action.Opening this PR to exercise CI.