Skip to content

CI/CD: add CI and release workflows - #44

Closed
saieeshward wants to merge 116 commits into
mainfrom
feature/MultiAgentic
Closed

CI/CD: add CI and release workflows#44
saieeshward wants to merge 116 commits into
mainfrom
feature/MultiAgentic

Conversation

@saieeshward

Copy link
Copy Markdown
Owner

Adds two GitHub Actions workflows (see TODO.md):

  • ci.yml — on PR + push to main: Rust (fmt/clippy/test on clan-sdk+clan-cli), Frontend (lint/tsc/build), and the conformance harness against a release clan binary.
  • release.yml — on v* tag: CLI binaries (linux/macOS/windows) + Tauri desktop bundles via tauri-action.

Opening this PR to exercise CI.

EESH-843 and others added 30 commits May 29, 2026 01:42
…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.
EESH-843 and others added 28 commits June 12, 2026 01:44
- 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>
…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).
…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.
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
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.

2 participants