Conversation
- Added strict: bool field to SimpleAgent struct - Added resolve_strict(explicit: Option<bool>) -> bool helper (explicit > env var > false) - Added is_strict() accessor - Updated load() signature: now load(config_path, strict) - Updated all 3 construction sites (create, create_with_params, load) - Added strict enforcement in verify(), verify_self() — returns Err(SignatureVerificationFailed) instead of Ok(valid=false) - verify_by_id() delegates to verify() so inherits strict behavior - Fixed all callers: audit/mod.rs, bin/cli.rs, deprecated module-level load() - Added 5 new tests (resolve_strict defaults, explicit overrides, env var, is_strict accessor, strict+malformed input) Python (jacspy): - PyO3: load(config_path, strict) with #[pyo3(signature)], added is_strict() - simple.py: _strict module state, _resolve_strict(), is_strict(). load(strict=), create(strict=). verify(), verify_self(), verify_by_id() raise VerificationError in strict mode - async_simple.py: load(strict=), create(strict=) pass through - mcp.py: Already had strict support; fixed _resolve_strict to handle Optional[bool] Node.js (jacsnpm): - simple.ts: strictMode state, resolveStrict(), isStrict(), LoadOptions interface. load(configPath, options). verifySelf(), verify(), verifyById() throw in strict mode - simple.d.ts: Added LoadOptions interface, isStrict(), updated load() signature Versions: All 8 manifests bumped to 0.6.2 Tests: 391 passing (359 lib + 32 binding-core/MCP) ✻ Cogitated for 25m 39s ⏺ Background command "Run jacs core tests" completed (exit code 0) ⏺ That's the background task that already completed earlier — the jacs core tests passed (359 tests, 0 failures). All Phase 2 strict mode work is done and verified. Waiting for your next instructions. ⏺ Background command "Run full test suite (jacs lib, binding-core, mcp)" completed (exit code 0) ⏺ That's also the background task that already completed — 32 binding-core/MCP tests passed. Combined with the 359 lib tests, all 391 tests pass at v0.6.2. Phase 2 strict mode is fully implemented and verified across all layers.
agent/mod.rs: - Added key_store: Option<Box<dyn KeyStore>> and ephemeral: bool fields to Agent struct - Added Agent::ephemeral(algorithm) — creates agent with InMemoryKeyStore + memory storage + ConfigBuilder defaults - Added set_keys_raw() — stores raw private key in SecretBox without AES encryption - Added is_ephemeral() and get_key_store() accessors - Guarded create_agent_and_load() — ephemeral uses key_store directly, skips fs_load_keys and fs_save_remote_public_key - Guarded load() — skips fs_load_keys for ephemeral agents - Updated all Agent struct construction sites (new, builder.build) - 7 new tests: create without config/env vars, create_agent_and_load, sign+verify round-trip, ready check, no files on disk, pq2025 crypt/mod.rs: - Added generate_keys_with_store(&dyn KeyStore) — ephemeral uses set_keys_raw, persistent uses set_keys - Refactored generate_keys() to delegate to generate_keys_with_store(&FsEncryptedStore) - Added ephemeral branches in sign_string() and sign_batch() — skips AES decryption for ephemeral agents Test results: 376 lib tests pass, 32 binding-core/MCP pass, all crates compile.
┌───────────────────────────────┬────────────────────────────────────────────────────┐ │ Layer │ Status │ ├───────────────────────────────┼────────────────────────────────────────────────────┤ │ 3.1 InMemoryKeyStore │ Done (10 tests) │ ├───────────────────────────────┼────────────────────────────────────────────────────┤ │ 3.2 Agent::ephemeral() │ Done (7 tests) │ ├───────────────────────────────┼────────────────────────────────────────────────────┤ │ 3.3 SimpleAgent::ephemeral() │ Done (4 tests) │ ├───────────────────────────────┼────────────────────────────────────────────────────┤ │ 3.4 Python quickstart() │ Done │ ├───────────────────────────────┼────────────────────────────────────────────────────┤ │ 3.5 Node.js quickstart() │ Done │ ├───────────────────────────────┼────────────────────────────────────────────────────┤ │ 3.4a Error messages │ Partial (Python/Node done, Rust JacsError pending) │ ├───────────────────────────────┼────────────────────────────────────────────────────┤ │ 3.6 CLI quickstart │ Not started │ ├───────────────────────────────┼────────────────────────────────────────────────────┤ │ 3.7 Config friction reduction │ Not started │ ├───────────────────────────────┼────────────────────────────────────────────────────┤ │ 3.8 DX validation │ Not started │ ├───────────────────────────────┼────────────────────────────────────────────────────┤ │ U1 find_config migration │ Not started │ └───────────────────────────────┴────────────────────────────────────────────────────┘
3.4a: Error Messages
- Updated JacsError::AgentNotLoaded in error.rs to mention quickstart()
- Updated test to verify new message
U1: find_config Migration
- Replaced deprecated find_config("./") with load_config_12factor_optional(None) in Agent::new() and Agent::load_by_id()
- Replaced load_config(&path) with load_config_12factor(Some(&path)) in Agent::load_by_config()
- Updated CLI config read to use load_config_12factor_optional
Layer 6: CLI Quickstart
- Added jacs quickstart command with --algorithm, --sign, --file, --persist flags
- Info mode prints agent details and usage hints
- Sign mode reads JSON from stdin or file, signs it, prints signed document
Layer 7: Config Friction Reduction
- SimpleAgent::create() now writes minimal 2-field config (jacs_agent_id_and_version + jacs_agent_key_algorithm)
- create_with_params() only includes non-default paths
- jacs.config.example.json simplified from 11 fields to 3 (including $schema)
Layer 8: DX Validation (via subagent)
- All 3 READMEs (root, jacspy, jacsnpm) now lead with quickstart() in Quick Start
- load() path moved to "Advanced: Loading a persistent agent"
- API tables include quickstart() as first entry
- jacspy/examples/quickstart.py rewritten to lead with quickstart()
- jacsnpm/examples/quickstart.js updated with quickstart() primary path
Bug Fix
- Fixed binding-core temp file race condition by using thread-unique filenames
Test Results
- 380 lib tests pass (all existing + 21 new from Layers 1-3)
- 32 binding-core tests pass (race condition fixed)
- 11 files changed, +300/-127 lines
Tasks completed: 1. Rust NAPI - Arc<AgentWrapper> + generic AsyncTask structs (AgentStringTask, AgentBoolTask, AgentVoidTask) 2. TypeScript - simple.ts, client.ts, testing.ts all updated with async default + Sync suffix variants 3. Tests - 119 passing, 0 failing (both async and sync coverage) 4. Docs - Updated 6 jacsbook pages + jacsnpm README for v0.7.0 async-first API 5. Version bump - package.json and Cargo.toml both at v0.7.0 Key docs updated: - jacsnpm/README.md - Full async-first API docs - jacsbook/src/nodejs/simple-api.md - Async/sync API tables + all examples - jacsbook/src/nodejs/basic-usage.md - All code examples with await - jacsbook/src/nodejs/api.md - Full JacsAgent API with async/sync variants - jacsbook/src/getting-started/quick-start.md - Node.js tabs updated - jacsbook/src/reference/migration.md - v0.6.x → v0.7.0 migration guide - jacsbook/src/examples/nodejs.md - Setup section updated
- examples/langchain/basic-agent.ts: Made initializeJACSTools() async, added await to load(), verifySelf(), signMessage(), verify(), createAgreement(), checkAgreement() - examples/langchain/signing-callback.ts: Constructor simplified to just check isLoaded() (can't be async), signOutput() and verifyAll() made async with await on signMessage() and verify(), await jacs.load() in main() Task 9 — multi_agent_agreement.ts (completed): - examples/multi_agent_agreement.ts: main() → async main(), await on all 3 ephemeral() calls, createAgreement(), 3x signAgreement(), verifySelf(), error handler added to main().catch() - Python version (multi_agent_agreement.py) — no changes needed (Python API is synchronous) Test results: 119 jacsnpm tests passing, 101 moltyjacs tests passing.
┌──────────────────────┬────────────────────────────────────────────┬───────────────────────────────┐ │ Component │ Files │ Tests │ ├──────────────────────┼────────────────────────────────────────────┼───────────────────────────────┤ │ Rust sign_batch │ binding-core/src/lib.rs, jacspy/src/lib.rs │ 4 Rust + 2 Python │ ├──────────────────────┼────────────────────────────────────────────┼───────────────────────────────┤ │ Base adapter │ jacs/adapters/base.py │ 21 │ ├──────────────────────┼────────────────────────────────────────────┼───────────────────────────────┤ │ LangChain/LangGraph │ jacs/adapters/langchain.py │ 23 (19 pass, 4 skip w/o deps) │ ├──────────────────────┼────────────────────────────────────────────┼───────────────────────────────┤ │ FastAPI │ jacs/adapters/fastapi.py │ 11 │ ├──────────────────────┼────────────────────────────────────────────┼───────────────────────────────┤ │ CrewAI │ jacs/adapters/crewai.py │ 19 │ ├──────────────────────┼────────────────────────────────────────────┼───────────────────────────────┤ │ Anthropic/Claude SDK │ jacs/adapters/anthropic.py │ 17 │ └──────────────────────┴────────────────────────────────────────────┴───────────────────────────────┘ Install extras pip install jacs[langchain] # LangChain/LangGraph pip install jacs[fastapi] # FastAPI/Starlette pip install jacs[crewai] # CrewAI pip install jacs[anthropic] # Anthropic/Claude SDK pip install jacs[all] # Everything Key design decisions - All adapters reuse BaseJacsAdapter → JacsClient (no duplicated sign/verify logic) - All framework imports are lazy (no hard deps) - Strict mode raises, permissive mode logs + passes through - Docs in jacsbook, README, and quickstart all updated Still needed before release - Run the full Python test suite (maturin develop && pytest) - Verify moltyjacs compatibility - Consider updating existing langchain examples to use new adapter pattern
- Added createJacsTools(options) - returns 11 LangChain DynamicStructuredTool instances exposing the full JACS API:
- jacs_sign, jacs_verify, jacs_create_agreement, jacs_sign_agreement, jacs_check_agreement, jacs_verify_self, jacs_trust_agent, jacs_list_trusted,
jacs_is_trusted, jacs_audit, jacs_agent_info
- Kept all existing auto-signing wrappers (signedTool, jacsWrapToolCall, jacsToolNode)
- Uses lazy Zod imports (available via @langchain/core)
- Strict/permissive error handling
- 35 tests (was 19)
MCP Tool Registration (mcp.ts) - Full Tool Suite
- Added registerJacsTools(server, client) - one-call registration of 17 MCP tools on any MCP Server
- Added getJacsMcpToolDefinitions() - returns tool definition array
- Added handleJacsMcpToolCall(client, name, args) - handles tool execution
- Tools mirror the Rust jacs-mcp server: sign, verify, agreements, trust, audit, HAI integration, file signing, key re-encryption
- Gaps vs Rust: agent state CRUD (6 tools) and messaging (4 tools) aren't exposed via NAPI bindings
- 41 tests (was 28)
Package.json
- Added ./langchain subpath export
- Added @langchain/core and @langchain/langgraph as optional peer deps
- Added langchain.js, langchain.d.ts, langchain.js.map to files array
- Added test:langchain script, updated test:adapters to include langchain
Documentation
- README: Added LangChain.js section (toolkit + auto-signing), updated MCP section with tool registration
- jacsbook: Created nodejs/langchain.md, updated nodejs/mcp.md with tool registration section, updated SUMMARY.md
- Jacsbook builds clean
Test Results
- 254 total jacsnpm tests passing (135 adapter tests across 5 adapters)
- TypeScript compiles clean
- Added asyncio_mode = "auto" to pyproject.toml [tool.pytest.ini_options]
- The async fixture loaded_agent now works correctly with pytest-asyncio auto mode
2. Created MCP adapter (jacs/adapters/mcp.py)
Two integration patterns, matching the Rust jacs-mcp approach:
As MCP tools (LLM-callable):
from fastmcp import FastMCP
from jacs.adapters.mcp import register_jacs_tools
mcp = FastMCP("jacs-server")
register_jacs_tools(mcp) # 9 tools: sign_document, verify_document, agreements, audit, etc.
mcp.run()
As MCP middleware (sign all tool outputs):
from jacs.adapters.mcp import JacsMCPMiddleware
mcp.add_middleware(JacsMCPMiddleware())
3. Added gitignore entries for generated test artifacts
- jacs_data/, jacs_keys/, jacs.config.json in jacspy/.gitignore
- **/jacs_data/, **/jacs_keys/ in root .gitignore
Test results
- Full suite: 219 passed, 10 skipped, 0 errors
- All adapters (incl. MCP): 118 passed, 4 skipped
- MCP adapter alone: 19 passed
…───────────────────────────────────────────┐ │ # │ Item │ Deliverable │ ├─────┼─────────────────┼───────────────────────────────────────────────────────────────────────────────────────┤ │ 1 │ MA-4 bug fix │ Fixed fake algorithms in A2A agent card (agent_card.rs, extension.rs, crypt/mod.rs) │ ├─────┼─────────────────┼───────────────────────────────────────────────────────────────────────────────────────┤ │ 2 │ Version bump │ All packages at 0.8.0 (10 files in JACS, 1 in moltyjacs) │ ├─────┼─────────────────┼───────────────────────────────────────────────────────────────────────────────────────┤ │ 3 │ Main README │ Rewritten — 83 lines, "Sign it. Prove it.", decision tree bullets, honest positioning │ ├─────┼─────────────────┼───────────────────────────────────────────────────────────────────────────────────────┤ │ 4 │ Algorithm Guide │ New jacsbook page (advanced/algorithm-guide.md) — sizes, decision tree, PQ section │ ├─────┼─────────────────┼───────────────────────────────────────────────────────────────────────────────────────┤ │ 5 │ Decision Tree │ New jacsbook page (getting-started/decision-tree.md) — framework table, adoption path │ ├─────┼─────────────────┼───────────────────────────────────────────────────────────────────────────────────────┤ │ 6 │ Binding READMEs │ jacspy, jacsnpm, jacsgo — new positioning, Go marked community-maintained │ ├─────┼─────────────────┼───────────────────────────────────────────────────────────────────────────────────────┤ │ 7 │ Media docs │ trust-blind-spot.md + why-trust-infrastructure.md in hai/docs/media/ │ └─────┴─────────────────┴───────────────────────────────────────────────────────────────────────────────────────┘ What remains (Wave 2 + 3) Wave 2 — Framework quickstarts (8.2): - 209-214: Six "JACS + X in 5 minutes" guides (LangGraph, CrewAI, FastAPI, Vercel AI, Express, MCP) - 8.2b: Multi-Agent Agreement quickstart Wave 3 — Infrastructure docs + deep positioning (8.3 + 8.4): - 216-220: MCP transport, A2A module, HAI client, trust store docs - 8.3b: A2A standalone quickstart - 8.4c: Deployment compatibility - 8.4e: DNS trust model documentation - 8.4f: Troubleshooting installation - 8.4g: Failure mode documentation - 8.4h: SEO/discoverability
├─────┼─────────────────────────────────────────────────────────────┼────────┤
│ 17 │ Python quickstarts (LangChain, CrewAI, FastAPI, MCP) │ Done │
├─────┼─────────────────────────────────────────────────────────────┼────────┤
│ 18 │ Node.js quickstarts (LangChain.js, Vercel AI, Express, MCP) │ Done │
├─────┼─────────────────────────────────────────────────────────────┼────────┤
│ 19 │ Multi-Agent Agreement quickstart │ Done │
└─────┴─────────────────────────────────────────────────────────────┴────────┘
Overall Phase 8 Progress
Section: Prep: Version bump + MA-4 bug fix
Status: Done
────────────────────────────────────────
Section: 8.1 Decision tree (203-208)
Status: Done — README bullets + jacsbook page
────────────────────────────────────────
Section: 8.2 Framework quickstarts (209-215, 8.2a, 8.2b)
Status: Done — 8 framework quickstarts + agreement quickstart
────────────────────────────────────────
Section: 8.3 Surface infra (216-220, MA-4, 8.3a-c)
Status: Partial — MA-4 done, algorithm guide done. Still need: MCP transport docs, A2A module docs, HAI client docs, trust store docs, A2A standalone quickstart
────────────────────────────────────────
Section: 8.4 Positioning (221-225, 8.4a-h)
Status: Partial — README rewrite done, binding READMEs done, "zero of 29" media done, Go decision done. Still need: deployment compat, DNS trust model,
troubleshooting installation, failure modes, SEO
Ready for Wave 3? The remaining items are:
- 8.3: Infrastructure docs (MCP transport, A2A, HAI client, trust store, A2A quickstart)
- 8.4: Deployment compatibility, DNS trust model, troubleshooting, failure modes, SEO
- New jacs verify <file> top-level command — standalone, no agent required - --json, --remote <url>, --key-dir flags - Human-readable output: signer ID, timestamp, algorithm, valid/invalid - 7 CLI integration tests 9.2 Verification API - verify_standalone() tested in Python (7 tests) and Node.js (4 tests) - verify_dns() wired to Rust native binding in Python (4 tests) - generateVerifyLink() added to Node.js JacsClient (13 tests) - generate_verify_link() tested in Python (6 tests) 9.3 Observability - Structured tracing::info! events for sign, verify, and agreement lifecycle - OTEL spans (#[tracing::instrument]) on signing/verification procedures - Agreement events: created, signature_added, quorum_reached, expired - 7 structured logging tests with custom capture layer - Full observability guide in jacsbook 9.4 Cross-Language Interop - Rust generates Ed25519 + pq2025 fixtures (4 tests) - Python verifies + countersigns (12 tests) - Node.js verifies Rust + Python fixtures + full chain test (19 tests) - Bug fix: verify_document_standalone path resolution for cross-language keys - 35 cross-language tests total Documentation - jacsbook/src/getting-started/verification.md — full verification guide - jacsbook/src/guides/observability.md — event reference + OTEL + Datadog/Splunk - jacsbook/src/reference/cli-commands.md — jacs verify reference - README.md — verification section + cross-language compatibility - jacspy/README.md + jacsnpm/README.md — standalone verification examples Total new tests: ~70+ Total lines added: ~2,258 across 92 files
Phase 10: Hardening, CLI Distribution, and Future Prep -- Complete Task: 10.3 Chaos tests (MA-5a-e) Status: Done Details: 6 tests in chaos_agreement_tests.rs -- partial signing, quorum failure, tampered signature, tampered body, in-memory consistency, DNS key placeholder ──────────────────────────────────────── Task: 10.3 MA-5f Failure modes doc Status: Done Details: failure-modes.md added to jacsbook with all 5 scenarios ──────────────────────────────────────── Task: 10.1 Streaming adapter audit Status: Done Details: Vercel AI wrapStream already tested. Added guides/streaming.md explaining buffer-then-sign pattern ──────────────────────────────────────── Task: 10.2 pq2025 benchmark Status: Done Details: Added to sign_and_check_sig.rs using SimpleAgent::ephemeral ──────────────────────────────────────── Task: 10.2 Agreement benchmarks Status: Done Details: New agreement_benchmarks.rs -- N-party signing (2,5,10,25) + concurrent signing (10,50,100 agents) ──────────────────────────────────────── Task: CLI Distribution: GitHub Actions Status: Done Details: release-cli.yml -- 5 targets, cli/v* tag trigger, SHA-256 checksums ──────────────────────────────────────── Task: CLI Distribution: npm postinstall Status: Done Details: scripts/install-cli.js -- platform detection, auto-download, non-fatal on failure ──────────────────────────────────────── Task: CLI Distribution: pip launcher Status: Done Details: cli_runner.py -- download-on-first-use, jacs entry point ──────────────────────────────────────── Task: DX: "What's Next?" callouts Status: Done Details: Added to all 3 READMEs + jacsbook quickstart ──────────────────────────────────────── Task: Binding test verification Status: Done Details: All green except 7 pre-existing jacsnpm failures Files created/modified: - jacs/tests/chaos_agreement_tests.rs (new, 6 tests) - jacs/docs/jacsbook/src/advanced/failure-modes.md (updated) - jacs/docs/jacsbook/src/guides/streaming.md (new) - jacs/docs/jacsbook/src/SUMMARY.md (updated) - jacs/docs/jacsbook/src/getting-started/quick-start.md (updated) - jacs/benches/sign_and_check_sig.rs (added pq2025 benchmark) - jacs/benches/agreement_benchmarks.rs (new) - jacs/Cargo.toml (added bench entry) - .github/workflows/release-cli.yml (new) - jacsnpm/scripts/install-cli.js (new) - jacsnpm/package.json (added postinstall + bin) - jacspy/python/jacs/cli_runner.py (new) - jacspy/pyproject.toml (added scripts entry) - README.md, jacspy/README.md, jacsnpm/README.md (What's Next callouts)
…for path-based agent verify. Standalone cross-language verify path/root handling fixed in lib.rs (absolute path normalization, key/data root fallback, unique temp config file names). Node quickstart config/state issues fixed in: simple.ts client.ts plus rebuilt JS outputs. Fixture mutation gating (your recommendation) implemented across Rust/Python/Node using UPDATE_CROSS_LANG_FIXTURES=1: mod.rs test_cross_language.py cross-language.test.js Python CI async marker issue fixed by adding pytest-asyncio: python.yml /Users/jonathan.hendler/personal/JACS/jacspy/Makefile Additional regression fixed in langchain adapter import flow: langchain.py Validation run results: cargo test -p jacs test_cli_script_flow -- --nocapture -> pass npm run test:cross-language --silent (in jacsnpm) -> pass (19 passing) test_cross_language.py -q (in jacspy) -> pass (62 passed, 4 skipped)
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.
No description provided.