diff --git a/.beads/.gitignore b/.beads/.gitignore deleted file mode 100644 index 304f708..0000000 --- a/.beads/.gitignore +++ /dev/null @@ -1,70 +0,0 @@ -# Dolt database (managed by Dolt, not git) -dolt/ -embeddeddolt/ - -# Runtime files -bd.sock -bd.sock.startlock -sync-state.json -last-touched -.exclusive-lock - -# Daemon runtime (lock, log, pid) -daemon.* - -# Push state (runtime, per-machine) -push-state.json - -# Lock files (various runtime locks) -*.lock - -# Credential key (encryption key for federation peer auth β€” never commit) -.beads-credential-key - -# Local version tracking (prevents upgrade notification spam after git ops) -.local_version - -# Worktree redirect file (contains relative path to main repo's .beads/) -# Must not be committed as paths would be wrong in other clones -redirect - -# Sync state (local-only, per-machine) -# These files are machine-specific and should not be shared across clones -.sync.lock -export-state/ -export-state.json - -# Ephemeral store (SQLite - wisps/molecules, intentionally not versioned) -ephemeral.sqlite3 -ephemeral.sqlite3-journal -ephemeral.sqlite3-wal -ephemeral.sqlite3-shm - -# Dolt server management (auto-started by bd) -dolt-server.pid -dolt-server.log -dolt-server.lock -dolt-server.port -dolt-server.activity - -# Corrupt backup directories (created by bd doctor --fix recovery) -*.corrupt.backup/ - -# Backup data (auto-exported JSONL, local-only) -backup/ - -# Per-project environment file (Dolt connection config, GH#2520) -.env - -# Legacy files (from pre-Dolt versions) -*.db -*.db?* -*.db-journal -*.db-wal -*.db-shm -db.sqlite -bd.db -# NOTE: Do NOT add negation patterns here. -# They would override fork protection in .git/info/exclude. -# Config files (metadata.json, config.yaml) are tracked by git by default -# since no pattern above ignores them. diff --git a/.beads/README.md b/.beads/README.md deleted file mode 100644 index dbfe363..0000000 --- a/.beads/README.md +++ /dev/null @@ -1,81 +0,0 @@ -# Beads - AI-Native Issue Tracking - -Welcome to Beads! This repository uses **Beads** for issue tracking - a modern, AI-native tool designed to live directly in your codebase alongside your code. - -## What is Beads? - -Beads is issue tracking that lives in your repo, making it perfect for AI coding agents and developers who want their issues close to their code. No web UI required - everything works through the CLI and integrates seamlessly with git. - -**Learn more:** [github.com/steveyegge/beads](https://github.com/steveyegge/beads) - -## Quick Start - -### Essential Commands - -```bash -# Create new issues -bd create "Add user authentication" - -# View all issues -bd list - -# View issue details -bd show - -# Update issue status -bd update --claim -bd update --status done - -# Sync with Dolt remote -bd dolt push -``` - -### Working with Issues - -Issues in Beads are: -- **Git-native**: Stored in Dolt database with version control and branching -- **AI-friendly**: CLI-first design works perfectly with AI coding agents -- **Branch-aware**: Issues can follow your branch workflow -- **Always in sync**: Auto-syncs with your commits - -## Why Beads? - -✨ **AI-Native Design** -- Built specifically for AI-assisted development workflows -- CLI-first interface works seamlessly with AI coding agents -- No context switching to web UIs - -πŸš€ **Developer Focused** -- Issues live in your repo, right next to your code -- Works offline, syncs when you push -- Fast, lightweight, and stays out of your way - -πŸ”§ **Git Integration** -- Automatic sync with git commits -- Branch-aware issue tracking -- Dolt-native three-way merge resolution - -## Get Started with Beads - -Try Beads in your own projects: - -```bash -# Install Beads -curl -sSL https://raw.githubusercontent.com/steveyegge/beads/main/scripts/install.sh | bash - -# Initialize in your repo -bd init - -# Create your first issue -bd create "Try out Beads" -``` - -## Learn More - -- **Documentation**: [github.com/steveyegge/beads/docs](https://github.com/steveyegge/beads/tree/main/docs) -- **Quick Start Guide**: Run `bd quickstart` -- **Examples**: [github.com/steveyegge/beads/examples](https://github.com/steveyegge/beads/tree/main/examples) - ---- - -*Beads: Issue tracking that moves at the speed of thought* ⚑ diff --git a/.beads/config.yaml b/.beads/config.yaml deleted file mode 100644 index 07342c6..0000000 --- a/.beads/config.yaml +++ /dev/null @@ -1,55 +0,0 @@ -# Beads Configuration File -# This file configures default behavior for all bd commands in this repository -# All settings can also be set via environment variables (BD_* prefix) -# or overridden with command-line flags - -# Issue prefix for this repository (used by bd init) -# If not set, bd init will auto-detect from directory name -# Example: issue-prefix: "myproject" creates issues like "myproject-1", "myproject-2", etc. -# issue-prefix: "" - -# Use no-db mode: JSONL-only, no Dolt database -# When true, bd will use .beads/issues.jsonl as the source of truth -# no-db: false - -# Enable JSON output by default -# json: false - -# Feedback title formatting for mutating commands (create/update/close/dep/edit) -# 0 = hide titles, N > 0 = truncate to N characters -# output: -# title-length: 255 - -# Default actor for audit trails (overridden by BEADS_ACTOR or --actor) -# actor: "" - -# Export events (audit trail) to .beads/events.jsonl on each flush/sync -# When enabled, new events are appended incrementally using a high-water mark. -# Use 'bd export --events' to trigger manually regardless of this setting. -# events-export: false - -# Multi-repo configuration (experimental - bd-307) -# Allows hydrating from multiple repositories and routing writes to the correct database -# repos: -# primary: "." # Primary repo (where this database lives) -# additional: # Additional repos to hydrate from (read-only) -# - ~/beads-planning # Personal planning repo -# - ~/work-planning # Work planning repo - -# JSONL backup (periodic export for off-machine recovery) -# Auto-enabled when a git remote exists. Override explicitly: -# backup: -# enabled: false # Disable auto-backup entirely -# interval: 15m # Minimum time between auto-exports -# git-push: false # Disable git push (export locally only) -# git-repo: "" # Separate git repo for backups (default: project repo) - -# Integration settings (access with 'bd config get/set') -# Non-secret keys (stored in the database): -# - jira.url, jira.project -# - linear.team_id -# - github.org, github.repo -# -# Secret keys (stored in this file but prefer env vars to avoid git exposure): -# - linear.api_key β†’ use LINEAR_API_KEY env var instead -# - github.token β†’ use GITHUB_TOKEN env var instead diff --git a/.beads/hooks/post-checkout b/.beads/hooks/post-checkout deleted file mode 100755 index 7d35c68..0000000 --- a/.beads/hooks/post-checkout +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env sh -# --- BEGIN BEADS INTEGRATION v1.0.4 --- -# This section is managed by beads. Do not remove these markers. -if command -v bd >/dev/null 2>&1; then - export BD_GIT_HOOK=1 - _bd_timeout=${BEADS_HOOK_TIMEOUT:-300} - if command -v timeout >/dev/null 2>&1; then - timeout "$_bd_timeout" bd hooks run post-checkout "$@" - _bd_exit=$? - if [ $_bd_exit -eq 124 ]; then - echo >&2 "beads: hook 'post-checkout' timed out after ${_bd_timeout}s β€” continuing without beads" - _bd_exit=0 - fi - else - bd hooks run post-checkout "$@" - _bd_exit=$? - fi - if [ $_bd_exit -eq 3 ]; then - echo >&2 "beads: database not initialized β€” skipping hook 'post-checkout'" - _bd_exit=0 - fi - if [ $_bd_exit -ne 0 ]; then exit $_bd_exit; fi -fi -# --- END BEADS INTEGRATION v1.0.4 --- diff --git a/.beads/hooks/post-merge b/.beads/hooks/post-merge deleted file mode 100755 index 1f458ba..0000000 --- a/.beads/hooks/post-merge +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env sh -# --- BEGIN BEADS INTEGRATION v1.0.4 --- -# This section is managed by beads. Do not remove these markers. -if command -v bd >/dev/null 2>&1; then - export BD_GIT_HOOK=1 - _bd_timeout=${BEADS_HOOK_TIMEOUT:-300} - if command -v timeout >/dev/null 2>&1; then - timeout "$_bd_timeout" bd hooks run post-merge "$@" - _bd_exit=$? - if [ $_bd_exit -eq 124 ]; then - echo >&2 "beads: hook 'post-merge' timed out after ${_bd_timeout}s β€” continuing without beads" - _bd_exit=0 - fi - else - bd hooks run post-merge "$@" - _bd_exit=$? - fi - if [ $_bd_exit -eq 3 ]; then - echo >&2 "beads: database not initialized β€” skipping hook 'post-merge'" - _bd_exit=0 - fi - if [ $_bd_exit -ne 0 ]; then exit $_bd_exit; fi -fi -# --- END BEADS INTEGRATION v1.0.4 --- diff --git a/.beads/hooks/pre-commit b/.beads/hooks/pre-commit deleted file mode 100755 index ad1fb16..0000000 --- a/.beads/hooks/pre-commit +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env sh -# --- BEGIN BEADS INTEGRATION v1.0.4 --- -# This section is managed by beads. Do not remove these markers. -if command -v bd >/dev/null 2>&1; then - export BD_GIT_HOOK=1 - _bd_timeout=${BEADS_HOOK_TIMEOUT:-300} - if command -v timeout >/dev/null 2>&1; then - timeout "$_bd_timeout" bd hooks run pre-commit "$@" - _bd_exit=$? - if [ $_bd_exit -eq 124 ]; then - echo >&2 "beads: hook 'pre-commit' timed out after ${_bd_timeout}s β€” continuing without beads" - _bd_exit=0 - fi - else - bd hooks run pre-commit "$@" - _bd_exit=$? - fi - if [ $_bd_exit -eq 3 ]; then - echo >&2 "beads: database not initialized β€” skipping hook 'pre-commit'" - _bd_exit=0 - fi - if [ $_bd_exit -ne 0 ]; then exit $_bd_exit; fi -fi -# --- END BEADS INTEGRATION v1.0.4 --- diff --git a/.beads/hooks/pre-push b/.beads/hooks/pre-push deleted file mode 100755 index 35c2a69..0000000 --- a/.beads/hooks/pre-push +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env sh -# --- BEGIN BEADS INTEGRATION v1.0.4 --- -# This section is managed by beads. Do not remove these markers. -if command -v bd >/dev/null 2>&1; then - export BD_GIT_HOOK=1 - _bd_timeout=${BEADS_HOOK_TIMEOUT:-300} - if command -v timeout >/dev/null 2>&1; then - timeout "$_bd_timeout" bd hooks run pre-push "$@" - _bd_exit=$? - if [ $_bd_exit -eq 124 ]; then - echo >&2 "beads: hook 'pre-push' timed out after ${_bd_timeout}s β€” continuing without beads" - _bd_exit=0 - fi - else - bd hooks run pre-push "$@" - _bd_exit=$? - fi - if [ $_bd_exit -eq 3 ]; then - echo >&2 "beads: database not initialized β€” skipping hook 'pre-push'" - _bd_exit=0 - fi - if [ $_bd_exit -ne 0 ]; then exit $_bd_exit; fi -fi -# --- END BEADS INTEGRATION v1.0.4 --- diff --git a/.beads/hooks/prepare-commit-msg b/.beads/hooks/prepare-commit-msg deleted file mode 100755 index a72277d..0000000 --- a/.beads/hooks/prepare-commit-msg +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env sh -# --- BEGIN BEADS INTEGRATION v1.0.4 --- -# This section is managed by beads. Do not remove these markers. -if command -v bd >/dev/null 2>&1; then - export BD_GIT_HOOK=1 - _bd_timeout=${BEADS_HOOK_TIMEOUT:-300} - if command -v timeout >/dev/null 2>&1; then - timeout "$_bd_timeout" bd hooks run prepare-commit-msg "$@" - _bd_exit=$? - if [ $_bd_exit -eq 124 ]; then - echo >&2 "beads: hook 'prepare-commit-msg' timed out after ${_bd_timeout}s β€” continuing without beads" - _bd_exit=0 - fi - else - bd hooks run prepare-commit-msg "$@" - _bd_exit=$? - fi - if [ $_bd_exit -eq 3 ]; then - echo >&2 "beads: database not initialized β€” skipping hook 'prepare-commit-msg'" - _bd_exit=0 - fi - if [ $_bd_exit -ne 0 ]; then exit $_bd_exit; fi -fi -# --- END BEADS INTEGRATION v1.0.4 --- diff --git a/.beads/interactions.jsonl b/.beads/interactions.jsonl deleted file mode 100644 index 71306cd..0000000 --- a/.beads/interactions.jsonl +++ /dev/null @@ -1,30 +0,0 @@ -{"id":"int-621ea914","kind":"field_change","created_at":"2026-06-04T17:50:54.012588Z","actor":"Yogthos","issue_id":"jolt-x8s","extra":{"field":"status","new_value":"closed","old_value":"open"}} -{"id":"int-978620fa","kind":"field_change","created_at":"2026-06-04T17:59:35.53184Z","actor":"Yogthos","issue_id":"jolt-lp5","extra":{"field":"status","new_value":"closed","old_value":"open"}} -{"id":"int-11c77978","kind":"field_change","created_at":"2026-06-04T18:06:01.464313Z","actor":"Yogthos","issue_id":"jolt-tws","extra":{"field":"status","new_value":"closed","old_value":"open"}} -{"id":"int-2eef7613","kind":"field_change","created_at":"2026-06-04T18:06:02.544998Z","actor":"Yogthos","issue_id":"jolt-wec","extra":{"field":"status","new_value":"closed","old_value":"open"}} -{"id":"int-a7573343","kind":"field_change","created_at":"2026-06-04T18:09:14.608401Z","actor":"Yogthos","issue_id":"jolt-alz","extra":{"field":"status","new_value":"closed","old_value":"open"}} -{"id":"int-40cd8348","kind":"field_change","created_at":"2026-06-04T18:09:15.510649Z","actor":"Yogthos","issue_id":"jolt-nte","extra":{"field":"status","new_value":"closed","old_value":"open"}} -{"id":"int-57f4d2b3","kind":"field_change","created_at":"2026-06-04T18:31:23.83434Z","actor":"Yogthos","issue_id":"jolt-9sb","extra":{"field":"status","new_value":"closed","old_value":"open"}} -{"id":"int-f46da620","kind":"field_change","created_at":"2026-06-04T18:33:45.099148Z","actor":"Yogthos","issue_id":"jolt-ytt","extra":{"field":"status","new_value":"closed","old_value":"open"}} -{"id":"int-677fb0a5","kind":"field_change","created_at":"2026-06-04T18:40:42.396722Z","actor":"Yogthos","issue_id":"jolt-40n","extra":{"field":"status","new_value":"closed","old_value":"open"}} -{"id":"int-10c63325","kind":"field_change","created_at":"2026-06-04T18:40:43.31635Z","actor":"Yogthos","issue_id":"jolt-4z9","extra":{"field":"status","new_value":"closed","old_value":"open"}} -{"id":"int-ba29d2c7","kind":"field_change","created_at":"2026-06-04T18:45:52.297233Z","actor":"Yogthos","issue_id":"jolt-gxr","extra":{"field":"status","new_value":"closed","old_value":"open"}} -{"id":"int-b7e06923","kind":"field_change","created_at":"2026-06-04T18:55:10.600885Z","actor":"Yogthos","issue_id":"jolt-7n5","extra":{"field":"status","new_value":"closed","old_value":"open"}} -{"id":"int-0d2b12ab","kind":"field_change","created_at":"2026-06-04T18:56:25.718778Z","actor":"Yogthos","issue_id":"jolt-90c","extra":{"field":"status","new_value":"closed","old_value":"open"}} -{"id":"int-a86d84ba","kind":"field_change","created_at":"2026-06-04T18:57:26.21495Z","actor":"Yogthos","issue_id":"jolt-h0n","extra":{"field":"status","new_value":"closed","old_value":"open"}} -{"id":"int-5ddb241f","kind":"field_change","created_at":"2026-06-04T18:57:27.904474Z","actor":"Yogthos","issue_id":"jolt-7dy","extra":{"field":"status","new_value":"deferred","old_value":"open"}} -{"id":"int-9a5516da","kind":"field_change","created_at":"2026-06-04T19:41:39.048731Z","actor":"Yogthos","issue_id":"jolt-4zg","extra":{"field":"status","new_value":"closed","old_value":"open"}} -{"id":"int-b700eb9e","kind":"field_change","created_at":"2026-06-04T19:48:03.780728Z","actor":"Yogthos","issue_id":"jolt-l8f","extra":{"field":"status","new_value":"closed","old_value":"open"}} -{"id":"int-700a80a8","kind":"field_change","created_at":"2026-06-04T19:56:36.343102Z","actor":"Yogthos","issue_id":"jolt-7dy","extra":{"field":"status","new_value":"closed","old_value":"deferred"}} -{"id":"int-0e80bc4f","kind":"field_change","created_at":"2026-06-04T20:23:37.457452Z","actor":"Yogthos","issue_id":"jolt-cn4","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Closed"}} -{"id":"int-8cd2e476","kind":"field_change","created_at":"2026-06-04T21:28:16.906665Z","actor":"Yogthos","issue_id":"jolt-y29","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Closed"}} -{"id":"int-6042189d","kind":"field_change","created_at":"2026-06-04T23:20:46.565771Z","actor":"Yogthos","issue_id":"jolt-ns4","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Done across 3 rounds (pushed a0c9696): build-time mutable/immutable toggle, structural-sharing persistent vectors (32-way trie), and persistent O(1)-prepend linked lists. Plus bit-clear/get-method and a batch of missing core fns. conformance 206/206, features 78/78, jank 120."}} -{"id":"int-80df5ed4","kind":"field_change","created_at":"2026-06-05T03:35:42.672628Z","actor":"Yogthos","issue_id":"jolt-i3g","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Done β€” SCI bootstrap now loads 422/422 with 0 failures. Fixed deftype protocol-method registration, with-meta on functions, select-keys over vectors, require :as+:refer, defmethod-on-fn; added clojure.set/join and host-module stubs. test-load-sci asserts 0 failures."}} -{"id":"int-b296d941","kind":"field_change","created_at":"2026-06-05T05:02:01.433529Z","actor":"Yogthos","issue_id":"jolt-do7","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Fixed: PHM/PHS canonicalize collection keys for value-based hashing/comparison; map literals & assoc promote to phm on collection keys; frequencies/group-by use phm base; set = is value-based. Also fixed set literals not evaluating elements and the REPL phm printer. Spec cases added. (commit pushed next)"}} -{"id":"int-885ca071","kind":"field_change","created_at":"2026-06-05T05:02:24.324962Z","actor":"Yogthos","issue_id":"jolt-e4p","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Won't-fix: backreferences and lookbehind are not expressible in a PEG engine (jolt regex compiles to Janet PEG); named groups are rare. Documented as unsupported in README's Regex section. Reopen if a concrete need arises."}} -{"id":"int-45c03ea2","kind":"field_change","created_at":"2026-06-05T05:23:54.397617Z","actor":"Yogthos","issue_id":"jolt-dd5","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Fixed: catch unwraps the :jolt/exception envelope so rethrow doesn't nest; var-set updates the current thread-binding frame (falls back to root). Spec cases restored."}} -{"id":"int-2acb82ed","kind":"field_change","created_at":"2026-06-05T13:05:03.712634Z","actor":"Yogthos","issue_id":"jolt-js6","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Ported clojure-test-suite as baseline-guarded integration battery; surfaced+fixed 2 evaluator macro bugs"}} -{"id":"int-2bd94166","kind":"field_change","created_at":"2026-06-05T13:18:36.785225Z","actor":"Yogthos","issue_id":"jolt-kxb","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"reduce-with-reduced steps lazy seqs incrementally; transducers short-circuit over infinite seqs"}} -{"id":"int-67ed276e","kind":"field_change","created_at":"2026-06-05T13:22:29.396671Z","actor":"Yogthos","issue_id":"jolt-dxx","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"merge follows Clojure (when some identity) (reduce conj ...) semantics; nil/empty/conj-entry cases fixed"}} -{"id":"int-e6dcd4a3","kind":"field_change","created_at":"2026-06-05T13:29:37.738114Z","actor":"Yogthos","issue_id":"jolt-1uw","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Fixed real gaps: invokable transients, assoc! odd args, use-after-persistent! invalidation, pop!-empty. Bad-shape type strictness left as accepted lenient divergence."}} -{"id":"int-ede75de6","kind":"field_change","created_at":"2026-06-05T13:35:45.843368Z","actor":"Yogthos","issue_id":"jolt-fy8","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Added ##Inf/##NaN literals + infinite?/NaN?, fixed intval? for inf; pass 1719->1955. Integer-valued-float ambiguity is a fundamental Janet-number divergence, documented in README."}} diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl deleted file mode 100644 index 34a56cf..0000000 --- a/.beads/issues.jsonl +++ /dev/null @@ -1,33 +0,0 @@ -{"_type":"issue","id":"jolt-y29","title":"CRITICAL: map literals don't evaluate values β€” (let [x 5] {:a x}) =\u003e {:a x}; fixing it eagerly hard-crashes SCI bootstrap (protocol maps ref unloaded sci.impl.core-protocols/records/deftype)","status":"closed","priority":1,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T21:08:30Z","created_by":"Yogthos","updated_at":"2026-06-04T21:28:17Z","closed_at":"2026-06-04T21:28:17Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"jolt-lp5","title":"CRITICAL: vec/into over lazy-seq leaks PV struct; into {} builds int keys","status":"closed","priority":1,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T17:46:15Z","created_by":"Yogthos","updated_at":"2026-06-04T17:59:35Z","closed_at":"2026-06-04T17:59:35Z","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"jolt-nte","title":"Build phased Clojure conformance harness (extracted assertions)","status":"closed","priority":1,"issue_type":"task","owner":"yogthos@gmail.com","created_at":"2026-06-04T17:46:15Z","created_by":"Yogthos","updated_at":"2026-06-04T18:09:15Z","closed_at":"2026-06-04T18:09:15Z","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"jolt-tws","title":"CRITICAL: iterate arity bug","status":"closed","priority":1,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T17:46:14Z","created_by":"Yogthos","updated_at":"2026-06-04T18:06:01Z","closed_at":"2026-06-04T18:06:01Z","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"jolt-x8s","title":"CRITICAL: collections not callable as IFn (vector/map/set)","status":"closed","priority":1,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T17:46:14Z","created_by":"Yogthos","updated_at":"2026-06-04T17:50:54Z","closed_at":"2026-06-04T17:50:54Z","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"jolt-alz","title":"CRITICAL: self-referential lazy-seq/lazy-cat yields only literal prefix","status":"closed","priority":1,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T17:46:13Z","created_by":"Yogthos","updated_at":"2026-06-04T18:09:15Z","closed_at":"2026-06-04T18:09:15Z","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"jolt-wec","title":"CRITICAL: multi-collection map returns unrealized thunk","status":"closed","priority":1,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T17:46:12Z","created_by":"Yogthos","updated_at":"2026-06-04T18:06:02Z","closed_at":"2026-06-04T18:06:02Z","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"jolt-5i5","title":"core.async Phase 2: dynamic var binding conveyance","description":"Snapshot/restore the global binding-stack per fiber so dynamic var bindings don't interleave across concurrent go blocks (Clojure binding conveyance).","status":"closed","priority":2,"issue_type":"feature","owner":"yogthos@gmail.com","created_at":"2026-06-05T18:55:08Z","created_by":"Yogthos","updated_at":"2026-06-05T19:22:50Z","closed_at":"2026-06-05T19:22:50Z","close_reason":"Binding stack moved to fiber-local dyn; go-spawn snapshots+installs for conveyance; concurrent isolation + inner shadowing verified (4 spec cases)","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"jolt-tkw","title":"core.async on Janet fibers β€” Phase 1: API layer","description":"Implement clojure.core.async API (chan/go/\u003c!/\u003e!/\u003c!!/\u003e!!/close!/alts!/timeout/put!/take!/buffers) on top of Janet ev/ channels and fibers. go = run body in a fiber (stackful, no CPS macro needed).","status":"closed","priority":2,"issue_type":"feature","owner":"yogthos@gmail.com","created_at":"2026-06-05T18:55:07Z","created_by":"Yogthos","updated_at":"2026-06-05T19:17:25Z","closed_at":"2026-06-05T19:17:25Z","close_reason":"Phase 1 complete: chan/go/\u003c!/\u003e!/close!/alts!/timeout/put!/take! on Janet fibers; two-channel design (values + done) gives drain-then-nil with no leaked fibers; 16 spec cases","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"jolt-lko","title":"clojure-test-suite: strictness β€” throw on malformed calls like Clojure","description":"Make jolt throw where Clojure throws (bad-shape conj!/assoc!, arithmetic on non-numbers, out-of-range indices, etc.) to satisfy the suite's ~292 p/thrown? assertions. Targeted input validation across affected fns; guard against regressing jolt's spec/conformance.","status":"closed","priority":2,"issue_type":"task","assignee":"Yogthos","owner":"yogthos@gmail.com","created_at":"2026-06-05T14:45:20Z","created_by":"Yogthos","updated_at":"2026-06-05T18:07:56Z","started_at":"2026-06-05T14:45:39Z","closed_at":"2026-06-05T18:07:56Z","close_reason":"Implemented Clojure-strict argument validation across ~30 fns; suite pass 3691-\u003e3898, p/thrown? bucket 292-\u003e~60 (remainder is platform: int 32-bit range, subs Unicode, min-key NaN, subvec floats, map-entry-as-2-vector)","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"jolt-kxb","title":"clojure-test-suite: transducers don't short-circuit over infinite seqs (hangs)","description":"(into [] (take 5) (range)) and similar transducer-over-infinite forms hang jolt's eager evaluator (no reduced/early-termination). 7 suite files time out. Make transducing honor reduced.","status":"closed","priority":2,"issue_type":"bug","assignee":"Yogthos","owner":"yogthos@gmail.com","created_at":"2026-06-05T13:05:18Z","created_by":"Yogthos","updated_at":"2026-06-05T13:18:37Z","started_at":"2026-06-05T13:09:59Z","closed_at":"2026-06-05T13:18:37Z","close_reason":"reduce-with-reduced steps lazy seqs incrementally; transducers short-circuit over infinite seqs","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"jolt-js6","title":"Port clojure-test-suite as integration battery","description":"Build a minimal clojure.test + portability shim so Jolt can load the external ~/src/clojure-test-suite (240 per-fn .cljc files in clojure.test format). Add a baseline-guarded integration runner following the jank-conformance pattern (skip if absent).","status":"closed","priority":2,"issue_type":"task","assignee":"Yogthos","owner":"yogthos@gmail.com","created_at":"2026-06-05T12:22:01Z","created_by":"Yogthos","updated_at":"2026-06-05T13:05:04Z","started_at":"2026-06-05T12:22:14Z","closed_at":"2026-06-05T13:05:04Z","close_reason":"Ported clojure-test-suite as baseline-guarded integration battery; surfaced+fixed 2 evaluator macro bugs","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"jolt-i3g","title":"Clear final 2 SCI bootstrap forms (Var/IVar collision + clojure.repl/template)","description":"namespaces.cljc forms 126/127 fail: (126) lang_stubs IVar collides with real vars.cljc IVar so unbind dispatch misses on sci.lang.Var; (127) clojure.repl + clojure.template namespaces missing. Fix: trim bootstrap stubs to let real modules own canonical protocols/types; port clojure.repl + clojure.template.","status":"closed","priority":2,"issue_type":"task","owner":"yogthos@gmail.com","created_at":"2026-06-05T03:21:40Z","created_by":"Yogthos","updated_at":"2026-06-05T03:35:43Z","closed_at":"2026-06-05T03:35:43Z","close_reason":"Done β€” SCI bootstrap now loads 422/422 with 0 failures. Fixed deftype protocol-method registration, with-meta on functions, select-keys over vectors, require :as+:refer, defmethod-on-fn; added clojure.set/join and host-module stubs. test-load-sci asserts 0 failures.","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"jolt-ns4","title":"Persistent collections + build-time mutable/immutable toggle","description":"Add JOLT_MUTABLE build flag (config.janet). Fix list-mutation bug (conj mutated original). Round 2: structural-sharing persistent vector (32-way trie) hooked into all core ops. Round 3: persistent lists / HAMT maps.","notes":"R1 (build flag + list mutation fix) and R2 (structural-sharing persistent vectors + mutable toggle) done \u0026 pushed (1eb2843). Immutable: conformance 206/206, features 71/71, jank 119. R3 (persistent linked lists) pending user decision: lists are immutable Janet arrays β€” O(1) sharing cons, O(n) conj.","status":"closed","priority":2,"issue_type":"feature","owner":"yogthos@gmail.com","created_at":"2026-06-04T22:15:39Z","created_by":"Yogthos","updated_at":"2026-06-04T23:20:46Z","closed_at":"2026-06-04T23:20:46Z","close_reason":"Done across 3 rounds (pushed a0c9696): build-time mutable/immutable toggle, structural-sharing persistent vectors (32-way trie), and persistent O(1)-prepend linked lists. Plus bit-clear/get-method and a batch of missing core fns. conformance 206/206, features 78/78, jank 120.","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"jolt-gxr","title":"HIGH: aliased namespace calls (require :as) don't resolve (s/join)","status":"closed","priority":2,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T18:09:58Z","created_by":"Yogthos","updated_at":"2026-06-04T18:45:52Z","closed_at":"2026-06-04T18:45:52Z","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"jolt-4z9","title":"HIGH: dispatch β€” multimethod :default, protocol-on-record, extend-protocol","status":"closed","priority":2,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T18:09:57Z","created_by":"Yogthos","updated_at":"2026-06-04T18:40:43Z","closed_at":"2026-06-04T18:40:43Z","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"jolt-40n","title":"HIGH: update/update-in/assoc-in fail on map literals (struct)","status":"closed","priority":2,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T18:09:56Z","created_by":"Yogthos","updated_at":"2026-06-04T18:40:42Z","closed_at":"2026-06-04T18:40:42Z","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"jolt-ytt","title":"HIGH: str semantics β€” (str nil)='nil' should be '', (str :b)='b' should be ':b'","status":"closed","priority":2,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T18:09:56Z","created_by":"Yogthos","updated_at":"2026-06-04T18:33:45Z","closed_at":"2026-06-04T18:33:45Z","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"jolt-9sb","title":"HIGH: destructuring gaps (nested seq, :strs, nested map, fn-param)","status":"closed","priority":2,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T18:09:55Z","created_by":"Yogthos","updated_at":"2026-06-04T18:31:24Z","closed_at":"2026-06-04T18:31:24Z","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"jolt-x3v","title":"core.async Phase 3: channel transducers","description":"Support (chan n xform) β€” apply a transducer to values flowing through a channel, plus dropping/sliding buffers.","status":"open","priority":3,"issue_type":"feature","owner":"yogthos@gmail.com","created_at":"2026-06-05T18:55:09Z","created_by":"Yogthos","updated_at":"2026-06-05T18:55:09Z","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"jolt-dxx","title":"clojure-test-suite: merge nil/empty + collection-key semantics","description":"merge.cljc has 18 fail / 11 err β€” highest in suite. Investigate nil/empty-map merge return values and collection-key behavior.","status":"closed","priority":3,"issue_type":"bug","assignee":"Yogthos","owner":"yogthos@gmail.com","created_at":"2026-06-05T13:05:17Z","created_by":"Yogthos","updated_at":"2026-06-05T13:22:29Z","started_at":"2026-06-05T13:18:50Z","closed_at":"2026-06-05T13:22:29Z","close_reason":"merge follows Clojure (when some identity) (reduce conj ...) semantics; nil/empty/conj-entry cases fixed","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"jolt-1uw","title":"clojure-test-suite: transient strictness gaps","description":"Transient ops (conj!/assoc!/disj!/pop!) don't throw on misuse (bad shapes, use-after-persistent!) where Clojure does. Surfaced by conj_bang/assoc_bang/pop_bang/persistent_bang/transient suite files (~50 fails). Lenient behavior; decide whether to enforce.","status":"closed","priority":3,"issue_type":"bug","assignee":"Yogthos","owner":"yogthos@gmail.com","created_at":"2026-06-05T13:05:16Z","created_by":"Yogthos","updated_at":"2026-06-05T13:29:38Z","started_at":"2026-06-05T13:22:51Z","closed_at":"2026-06-05T13:29:38Z","close_reason":"Fixed real gaps: invokable transients, assoc! odd args, use-after-persistent! invalidation, pop!-empty. Bad-shape type strictness left as accepted lenient divergence.","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"jolt-do7","title":"phm-typed maps as set elements / map keys hash by identity","description":"A map produced via hash-map/assoc (a Janet table/phm) used as a set element or map key hashes by identity, so #{{:a 1}} (struct elem) != #{(hash-map :a 1)} (phm elem) and such elements aren't retrievable by value. Map literals (structs) work. Needs value-based hashing for phm keys in PHM/PHS. Edge case; spec covers literal-map cases.","status":"closed","priority":3,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-05T04:07:50Z","created_by":"Yogthos","updated_at":"2026-06-05T05:02:01Z","closed_at":"2026-06-05T05:02:01Z","close_reason":"Fixed: PHM/PHS canonicalize collection keys for value-based hashing/comparison; map literals \u0026 assoc promote to phm on collection keys; frequencies/group-by use phm base; set = is value-based. Also fixed set literals not evaluating elements and the REPL phm printer. Spec cases added. (commit pushed next)","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"jolt-7dy","title":"MED: compiler path lacks IFn dispatch (collections-as-fn) β€” only interpreter fixed","status":"closed","priority":3,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T18:10:00Z","created_by":"Yogthos","updated_at":"2026-06-04T19:56:36Z","closed_at":"2026-06-04T19:56:36Z","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"jolt-90c","title":"MED: filter/take-while not lazy β€” infinite-seq (take N (filter p (range))) loops","status":"closed","priority":3,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T18:10:00Z","created_by":"Yogthos","updated_at":"2026-06-04T18:56:26Z","closed_at":"2026-06-04T18:56:26Z","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"jolt-7n5","title":"MED: REPL display β€” def/defn should print #'ns/name; lazy-seq printer realizes only head ((0 \u003cfunction\u003e))","status":"closed","priority":3,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T18:09:59Z","created_by":"Yogthos","updated_at":"2026-06-04T18:55:11Z","closed_at":"2026-06-04T18:55:11Z","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"jolt-h0n","title":"MED: missing core fns β€” letfn fnil trampoline doseq cycle partition-all reductions dedupe keep-indexed map-indexed transduce reduce-kv assoc-in peek subvec read-string format","status":"closed","priority":3,"issue_type":"feature","owner":"yogthos@gmail.com","created_at":"2026-06-04T18:09:58Z","created_by":"Yogthos","updated_at":"2026-06-04T18:57:26Z","closed_at":"2026-06-04T18:57:26Z","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"jolt-fy8","title":"clojure-test-suite: float?/double?/number-predicate divergences","description":"jolt doesn't distinguish float vs double (all Janet numbers); float_qmark/double_qmark and str formatting of numbers diverge from Clojure. Documented divergence; track for completeness.","status":"closed","priority":4,"issue_type":"task","assignee":"Yogthos","owner":"yogthos@gmail.com","created_at":"2026-06-05T13:05:19Z","created_by":"Yogthos","updated_at":"2026-06-05T13:35:46Z","started_at":"2026-06-05T13:30:05Z","closed_at":"2026-06-05T13:35:46Z","close_reason":"Added ##Inf/##NaN literals + infinite?/NaN?, fixed intval? for inf; pass 1719-\u003e1955. Integer-valued-float ambiguity is a fundamental Janet-number divergence, documented in README.","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"jolt-dd5","title":"throw of a caught ex-info rethrows wrapped; var-set on dynamic var in binding no-ops","description":"Edges found via spec: (1) (catch :default e (throw e)) re-wraps the ex-info so the outer catch's (ex-message e) is nil. (2) (var-set #'*v* x) inside (binding [*v* ...] ...) doesn't update the thread-binding. Both rare; core try/catch/ex-info and dynamic binding work.","status":"closed","priority":4,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-05T05:11:04Z","created_by":"Yogthos","updated_at":"2026-06-05T05:23:54Z","closed_at":"2026-06-05T05:23:54Z","close_reason":"Fixed: catch unwraps the :jolt/exception envelope so rethrow doesn't nest; var-set updates the current thread-binding frame (falls back to root). Spec cases restored.","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"jolt-e4p","title":"regex: lookbehind, backreferences (\\1), named groups (?\u003cn\u003e) unsupported (rare); engine is parse-\u003ePEG with backtracking","status":"closed","priority":4,"issue_type":"feature","owner":"yogthos@gmail.com","created_at":"2026-06-04T20:23:39Z","created_by":"Yogthos","updated_at":"2026-06-05T05:02:24Z","closed_at":"2026-06-05T05:02:24Z","close_reason":"Won't-fix: backreferences and lookbehind are not expressible in a PEG engine (jolt regex compiles to Janet PEG); named groups are rare. Documented as unsupported in README's Regex section. Reopen if a concrete need arises.","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"jolt-cn4","title":"regex engine is a common subset (PEG-backed); lookaround/backrefs/named-groups unsupported","status":"closed","priority":4,"issue_type":"feature","owner":"yogthos@gmail.com","created_at":"2026-06-04T19:27:50Z","created_by":"Yogthos","updated_at":"2026-06-04T20:23:37Z","closed_at":"2026-06-04T20:23:37Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"jolt-4zg","title":"char type: chars represented as 1-char strings; (seq \"ab\") yields strings not \\a \\b β€” deferred design decision","status":"closed","priority":4,"issue_type":"feature","owner":"yogthos@gmail.com","created_at":"2026-06-04T19:27:49Z","created_by":"Yogthos","updated_at":"2026-06-04T19:41:39Z","closed_at":"2026-06-04T19:41:39Z","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"jolt-l8f","title":"transduce + transducer arities (1-arg map/filter/take); niche, deferred","status":"closed","priority":4,"issue_type":"feature","owner":"yogthos@gmail.com","created_at":"2026-06-04T18:57:27Z","created_by":"Yogthos","updated_at":"2026-06-04T19:48:04Z","closed_at":"2026-06-04T19:48:04Z","dependency_count":0,"dependent_count":0,"comment_count":0} diff --git a/.beads/metadata.json b/.beads/metadata.json deleted file mode 100644 index 3fcd6a1..0000000 --- a/.beads/metadata.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "database": "dolt", - "backend": "dolt", - "dolt_mode": "embedded", - "dolt_database": "jolt", - "project_id": "6ed023e4-ac48-44e7-bb48-4da10fc635d8" -} \ No newline at end of file diff --git a/.clj-kondo/.cache/v1/clj/jolt.lang.persistent-hash-map.transit.json b/.clj-kondo/.cache/v1/clj/jolt.lang.persistent-hash-map.transit.json deleted file mode 100644 index e10a83e..0000000 --- a/.clj-kondo/.cache/v1/clj/jolt.lang.persistent-hash-map.transit.json +++ /dev/null @@ -1 +0,0 @@ -["^ ","~$bucket-count",["^ ","~:row",4,"~:col",1,"~:name","^0","~:ns","~$jolt.lang.persistent-hash-map","~:top-ns","^5","~:type","~:pos-int"],"~$bucket-contains?",["^ ","~:fixed-arities",["~#set",[2]],"~:private",true,"^4","^5","^3","^9","^7","~:fn","^2",1,"^6","^5","^1",71],"~$phm-empty",["^ ","^1",128,"^2",1,"^:",["^;",[1]],"^3","^>","^4","^5","^6","^5","^7","^="],"~$bucket-entries",["^ ","^:",["^;",[1]],"^<",true,"^4","^5","^3","^?","^7","^=","^2",1,"^6","^5","^1",52],"~$bucket-keys",["^ ","^:",["^;",[1]],"^<",true,"^4","^5","^3","^@","^7","^=","^2",1,"^6","^5","^1",59],"~$phm-count",["^ ","^1",125,"^2",1,"^:",["^;",[1]],"^3","^A","^4","^5","^6","^5","^7","^="],"~$copy-buckets",["^ ","^:",["^;",[3]],"^<",true,"^4","^5","^3","^B","^7","^=","^2",1,"^6","^5","^1",88],"~$map?",["^ ","^1",170,"^2",1,"^:",["^;",[1]],"^3","^C","^4","^5","^6","^5","^7","^="],"~$phm-conj",["^ ","^1",167,"^2",1,"^:",["^;",[2]],"^3","^D","^4","^5","^6","^5","^7","^="],"~$phm-dissoc",["^ ","^1",108,"^2",1,"^:",["^;",[2]],"^3","^E","^4","^5","^6","^5","^7","^="],"~$phm-seq",["^ ","^1",131,"^2",1,"^:",["^;",[1]],"^3","^F","^4","^5","^6","^5","^7","^="],"~$bucket-dissoc",["^ ","^:",["^;",[2]],"^<",true,"^4","^5","^3","^G","^7","^=","^2",1,"^6","^5","^1",37],"~$PersistentHashMap",["^ ","^1",6,"^2",1,"^3","^H","^4","^5","^6","^5","~:class",true],"~$phm-assoc",["^ ","^1",97,"^2",1,"^:",["^;",[3]],"^3","^J","^4","^5","^6","^5","^7","^="],"~$phm-from-pairs",["^ ","^:",["^;",[1]],"^<",true,"^4","^5","^3","^K","^7","^=","^2",1,"^6","^5","^1",158],"~$->PersistentHashMap",["^ ","^1",6,"^2",1,"^:",["^;",[3]],"^3","^L","^4","^5","^6","^5"],"~:filename","/Users/yogthos/src/jolt/src/jolt/clojure/lang/persistent_hash_map.clj","~$bucket-vals",["^ ","^:",["^;",[1]],"^<",true,"^4","^5","^3","^N","^7","^=","^2",1,"^6","^5","^1",65],"~$hash-key",["^ ","^:",["^;",[1]],"^<",true,"^4","^5","^3","^O","^7","^=","^2",1,"^6","^5","~:arities",["^ ","~i1",["^ ","~:ret",["^;",["~:number","~:nat-int"]],"~:arglist-str","[k]"]],"^1",10],"~$phm-get",["^ ","^1",79,"^2",1,"^:",["^;",[3,2]],"^3","^U","^4","^5","^6","^5","^7","^="],"~$phm-contains?",["^ ","^1",121,"^2",1,"^:",["^;",[2]],"^3","^V","^4","^5","^6","^5","^P",["^ ","~i2",["^ ","^Q",["^;",["~:boolean"]],"^T","[m k]"]],"^7","^="],"~$hash-map",["^ ","^1",164,"^2",1,"~:varargs-min-arity",0,"^3","^X","^4","^5","^6","^5","^7","^="],"~$phm-keys",["^ ","^1",140,"^2",1,"^:",["^;",[1]],"^3","^Z","^4","^5","^6","^5","^7","^="],"~$bucket-find",["^ ","^:",["^;",[2]],"^<",true,"^4","^5","^3","^[","^7","^=","^2",1,"^6","^5","^1",13],"~$phm-vals",["^ ","^1",149,"^2",1,"^:",["^;",[1]],"^3","^10","^4","^5","^6","^5","^7","^="],"~$bucket-assoc",["^ ","^:",["^;",[3]],"^<",true,"^4","^5","^3","^11","^7","^=","^2",1,"^6","^5","^1",21],"~$EMPTY-PHM",["^ ","^1",8,"^2",1,"^3","^12","^4","^5","^6","^5"]] \ No newline at end of file diff --git a/.clj-kondo/.cache/v1/clj/user.transit.json b/.clj-kondo/.cache/v1/clj/user.transit.json deleted file mode 100644 index f45bc1f..0000000 --- a/.clj-kondo/.cache/v1/clj/user.transit.json +++ /dev/null @@ -1 +0,0 @@ -["^ ","~$core-map",["^ ","~:row",262,"~:col",1,"~:varargs-min-arity",1,"~:name","^0","~:ns","~$user","~:top-ns",null,"~:type","~:fn"],"~$core-not",["^ ","^1",12,"^2",1,"~:fixed-arities",["~#set",[1]],"^4","^:","^5","^6","^7",null,"~:arities",["^ ","~i1",["^ ","~:ret",["^<",["~:boolean"]],"~:arglist-str","[x]"]],"^8","^9"],"~$core->=",["^ ","^1",98,"^2",1,"^;",["^<",[2]],"^4","^A","^5","^6","^7",null,"^=",["^ ","~i2",["^ ","^>","^?","^@","[a b]"]],"^8","^9"],"~$core-quot",["^ ","^1",70,"^2",1,"^;",["^<",[2]],"^4","^B","^5","^6","^7",null,"^8","^9"],"~$core-sub",["^ ","^;",["^<",[]],"^5","^6","^4","^C","^8","^9","^2",1,"^7",null,"^3",0,"^1",51],"~$core-<=",["^ ","^1",97,"^2",1,"^;",["^<",[2]],"^4","^D","^5","^6","^7",null,"^=",["^ ","~i2",["^ ","^>","^?","^@","[a b]"]],"^8","^9"],"~$core-not=",["^ ","^1",93,"^2",1,"^3",0,"^4","^E","^5","^6","^7",null,"^=",["^ ","~:varargs",["^ ","^>","^?","~:min-arity",0,"^@","[& args]"]],"^8","^9"],"~$core-inc",["^ ","^1",66,"^2",1,"^4","^H","^5","^6","^7",null],"~$core-rem",["^ ","^1",69,"^2",1,"^4","^I","^5","^6","^7",null],"~$core-false?",["^ ","^1",25,"^2",1,"^;",["^<",[1]],"^4","^J","^5","^6","^7",null,"^=",["^ ","~i1",["^ ","^>","^?","^@","[x]"]],"^8","^9"],"~$core-=",["^ ","^1",79,"^2",1,"^3",0,"^4","^K","^5","^6","^7",null,"^8","^9"],"~$core-zipmap",["^ ","^1",250,"^2",1,"^;",["^<",[2]],"^4","^L","^5","^6","^7",null,"^8","^9"],"~$core-dec",["^ ","^1",67,"^2",1,"^4","^M","^5","^6","^7",null],"~$core-zero?",["^ ","^1",28,"^2",1,"^;",["^<",[1]],"^4","^N","^5","^6","^7",null,"^=",["^ ","~i1",["^ ","^>",["^<",["~:nil","^?"]],"^@","[x]"]],"^8","^9"],"~$core-contains?",["^ ","^1",161,"^2",1,"^;",["^<",[2]],"^4","^P","^5","^6","^7",null,"^8","^9"],"~$core-every?",["^ ","^1",40,"^2",1,"^;",["^<",[2]],"^4","^Q","^5","^6","^7",null,"^8","^9"],"~$core-mod",["^ ","^1",68,"^2",1,"^4","^R","^5","^6","^7",null],"~$core-neg?",["^ ","^1",30,"^2",1,"^;",["^<",[1]],"^4","^S","^5","^6","^7",null,"^=",["^ ","~i1",["^ ","^>",["^<",["^O","^?"]],"^@","[x]"]],"^8","^9"],"~$core-vector?",["^ ","^1",19,"^2",1,"^;",["^<",[1]],"^4","^T","^5","^6","^7",null,"^8","^9"],"~$core-coll?",["^ ","^1",22,"^2",1,"^;",["^<",[1]],"^4","^U","^5","^6","^7",null,"^8","^9"],"~$core-count",["^ ","^1",169,"^2",1,"^;",["^<",[1]],"^4","^V","^5","^6","^7",null,"^8","^9"],"~$core-empty?",["^ ","^1",34,"^2",1,"^;",["^<",[1]],"^4","^W","^5","^6","^7",null,"^=",["^ ","~i1",["^ ","^>",["^<",["^?"]],"^@","[coll]"]],"^8","^9"],"~$core-max",["^ ","^1",72,"^2",1,"^3",0,"^4","^X","^5","^6","^7",null,"^8","^9"],"~$core-identical?",["^ ","^1",26,"^2",1,"^;",["^<",[2]],"^4","^Y","^5","^6","^7",null,"^=",["^ ","~i2",["^ ","^>","^?","^@","[a b]"]],"^8","^9"],"~$core-number?",["^ ","^1",15,"^2",1,"^;",["^<",[1]],"^4","^Z","^5","^6","^7",null,"^=",["^ ","~i1",["^ ","^>","^?","^@","[x]"]],"^8","^9"],"~$core-odd?",["^ ","^1",32,"^2",1,"^;",["^<",[1]],"^4","^[","^5","^6","^7",null,"^=",["^ ","~i1",["^ ","^>","^?","^@","[n]"]],"^8","^9"],"~$core->",["^ ","^1",96,"^2",1,"^;",["^<",[2]],"^4","^10","^5","^6","^7",null,"^=",["^ ","~i2",["^ ","^>","^?","^@","[a b]"]],"^8","^9"],"~$core-pos?",["^ ","^1",29,"^2",1,"^;",["^<",[1]],"^4","^11","^5","^6","^7",null,"^=",["^ ","~i1",["^ ","^>",["^<",["^O","^?"]],"^@","[x]"]],"^8","^9"],"~$core-even?",["^ ","^1",31,"^2",1,"^;",["^<",[1]],"^4","^12","^5","^6","^7",null,"^=",["^ ","~i1",["^ ","^>","^?","^@","[n]"]],"^8","^9"],"~$core-get-in",["^ ","^1",151,"^2",1,"^;",["^<",[4]],"^4","^13","^5","^6","^7",null,"^8","^9"],"~$core-conj",["^ ","^1",104,"^2",1,"^3",1,"^4","^14","^5","^6","^7",null,"^8","^9"],"~$core-min",["^ ","^1",73,"^2",1,"^3",0,"^4","^15","^5","^6","^7",null,"^8","^9"],"~:filename","/Users/yogthos/src/jolt/src/jolt/core.janet","~$core-map?",["^ ","^1",20,"^2",1,"^;",["^<",[1]],"^4","^17","^5","^6","^7",null,"^8","^9"],"~$core-keys",["^ ","^1",237,"^2",1,"^;",["^<",[1]],"^4","^18","^5","^6","^7",null,"^8","^9"],"~$core-symbol?",["^ ","^1",18,"^2",1,"^;",["^<",[1]],"^4","^19","^5","^6","^7",null,"^8","^9"],"~$core-merge",["^ ","^1",224,"^2",1,"^3",0,"^4","^1:","^5","^6","^7",null,"^8","^9"],"~$core-assoc",["^ ","^1",127,"^2",1,"^3",1,"^4","^1;","^5","^6","^7",null,"^8","^9"],"~$s",["^ ","^1",241,"^2",20,"^4","~$s","^5","^6","^7",null],"~$core-dissoc",["^ ","^1",134,"^2",1,"^3",1,"^4","^1<","^5","^6","^7",null,"^8","^9"],"~$core-+",["^ ","^;",["^<",[]],"^5","^6","^4","^1=","^8","^9","^2",1,"^7",null,"^=",["^ ","^F",["^ ","^>",["^<",["~:number","~:nat-int"]],"^G",0,"^@","[& args]"]],"^3",0,"^1",49],"~$core-cons",["^ ","^1",189,"^2",1,"^;",["^<",[2]],"^4","^1@","^5","^6","^7",null,"^8","^9"],"~$core-true?",["^ ","^1",24,"^2",1,"^;",["^<",[1]],"^4","^1A","^5","^6","^7",null,"^=",["^ ","~i1",["^ ","^>","^?","^@","[x]"]],"^8","^9"],"~$core-into",["^ ","^1",211,"^2",1,"^;",["^<",[2]],"^4","^1B","^5","^6","^7",null,"^8","^9"],"~$core-seq?",["^ ","^1",21,"^2",1,"^;",["^<",[1]],"^4","^1C","^5","^6","^7",null,"^8","^9"],"~$core-*",["^ ","^;",["^<",[]],"^5","^6","^4","^1D","^8","^9","^2",1,"^7",null,"^=",["^ ","^F",["^ ","^>",["^<",["^1>","~:pos-int"]],"^G",0,"^@","[& args]"]],"^3",0,"^1",57],"~$core-some?",["^ ","^1",13,"^2",1,"^;",["^<",[1]],"^4","^1F","^5","^6","^7",null,"^=",["^ ","~i1",["^ ","^>","^?","^@","[x]"]],"^8","^9"],"~$core-nil?",["^ ","^1",11,"^2",1,"^;",["^<",[1]],"^4","^1G","^5","^6","^7",null,"^=",["^ ","~i1",["^ ","^>","^?","^@","[x]"]],"^8","^9"],"~$core-select-keys",["^ ","^1",243,"^2",1,"^;",["^<",[2]],"^4","^1H","^5","^6","^7",null,"^8","^9"],"~$core-merge-with",["^ ","^1",229,"^2",1,"^3",1,"^4","^1I","^5","^6","^7",null,"^8","^9"],"~$core-rest",["^ ","^1",178,"^2",1,"^;",["^<",[1]],"^4","^1J","^5","^6","^7",null,"^8","^9"],"~$core-<",["^ ","^1",95,"^2",1,"^;",["^<",[2]],"^4","^1K","^5","^6","^7",null,"^=",["^ ","~i2",["^ ","^>","^?","^@","[a b]"]],"^8","^9"],"~$core-keyword?",["^ ","^1",17,"^2",1,"^;",["^<",[1]],"^4","^1L","^5","^6","^7",null,"^=",["^ ","~i1",["^ ","^>","^?","^@","[x]"]],"^8","^9"],"~$core-first",["^ ","^1",174,"^2",1,"^;",["^<",[1]],"^4","^1M","^5","^6","^7",null,"^8","^9"],"~$core-seq",["^ ","^1",196,"^2",1,"^;",["^<",[1]],"^4","^1N","^5","^6","^7",null,"^8","^9"],"~$core-get",["^ ","^1",140,"^2",1,"^;",["^<",[4]],"^4","^1O","^5","^6","^7",null,"^8","^9"],"~$core-fn?",["^ ","^1",16,"^2",1,"^;",["^<",[1]],"^4","^1P","^5","^6","^7",null,"^8","^9"],"~$core-next",["^ ","^1",185,"^2",1,"^;",["^<",[1]],"^4","^1Q","^5","^6","^7",null,"^8","^9"],"~$core-vals",["^ ","^1",240,"^2",1,"^;",["^<",[1]],"^4","^1R","^5","^6","^7",null,"^8","^9"],"~$core-vec",["^ ","^1",205,"^2",1,"^;",["^<",[1]],"^4","^1S","^5","^6","^7",null,"^8","^9"],"~$core-string?",["^ ","^1",14,"^2",1,"^;",["^<",[1]],"^4","^1T","^5","^6","^7",null,"^=",["^ ","~i1",["^ ","^>","^?","^@","[x]"]],"^8","^9"]] \ No newline at end of file diff --git a/.gitignore b/.gitignore index 178757f..8aea5a4 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,6 @@ test/_*.janet .dolt/ *.db .beads-credential-key + +# Beads issue tracker (local dev tooling) +.beads/ diff --git a/AGENTS.md b/AGENTS.md deleted file mode 100644 index bc2ae10..0000000 --- a/AGENTS.md +++ /dev/null @@ -1,96 +0,0 @@ -# Agent Instructions - -This project uses **bd** (beads) for issue tracking. Run `bd prime` for full workflow context. - -> **Architecture in one line:** Issues live in a local Dolt database -> (`.beads/dolt/`); cross-machine sync uses `bd dolt push/pull` (a -> git-compatible protocol), stored under `refs/dolt/data` on your git -> remote β€” separate from `refs/heads/*` where your code lives. -> `.beads/issues.jsonl` is a passive export, not the wire protocol. -> -> See [SYNC_CONCEPTS.md](https://github.com/gastownhall/beads/blob/main/docs/SYNC_CONCEPTS.md) -> for the one-screen overview and anti-patterns (don't treat JSONL as the -> source of truth; don't `bd import` during normal operation; don't -> reach for third-party Dolt hosting before trying the default). - -## Quick Reference - -```bash -bd ready # Find available work -bd show # View issue details -bd update --claim # Claim work atomically -bd close # Complete work -bd dolt push # Push beads data to remote -``` - -## Non-Interactive Shell Commands - -**ALWAYS use non-interactive flags** with file operations to avoid hanging on confirmation prompts. - -Shell commands like `cp`, `mv`, and `rm` may be aliased to include `-i` (interactive) mode on some systems, causing the agent to hang indefinitely waiting for y/n input. - -**Use these forms instead:** -```bash -# Force overwrite without prompting -cp -f source dest # NOT: cp source dest -mv -f source dest # NOT: mv source dest -rm -f file # NOT: rm file - -# For recursive operations -rm -rf directory # NOT: rm -r directory -cp -rf source dest # NOT: cp -r source dest -``` - -**Other commands that may prompt:** -- `scp` - use `-o BatchMode=yes` for non-interactive -- `ssh` - use `-o BatchMode=yes` to fail instead of prompting -- `apt-get` - use `-y` flag -- `brew` - use `HOMEBREW_NO_AUTO_UPDATE=1` env var - - -## Beads Issue Tracker - -This project uses **bd (beads)** for issue tracking. Run `bd prime` to see full workflow context and commands. - -### Quick Reference - -```bash -bd ready # Find available work -bd show # View issue details -bd update --claim # Claim work -bd close # Complete work -``` - -### Rules - -- Use `bd` for ALL task tracking β€” do NOT use TodoWrite, TaskCreate, or markdown TODO lists -- Run `bd prime` for detailed command reference and session close protocol -- Use `bd remember` for persistent knowledge β€” do NOT use MEMORY.md files - -**Architecture in one line:** issues live in a local Dolt DB; sync uses `refs/dolt/data` on your git remote; `.beads/issues.jsonl` is a passive export. See https://github.com/gastownhall/beads/blob/main/docs/SYNC_CONCEPTS.md for details and anti-patterns. - -## Session Completion - -**When ending a work session**, you MUST complete ALL steps below. Work is NOT complete until `git push` succeeds. - -**MANDATORY WORKFLOW:** - -1. **File issues for remaining work** - Create issues for anything that needs follow-up -2. **Run quality gates** (if code changed) - Tests, linters, builds -3. **Update issue status** - Close finished work, update in-progress items -4. **PUSH TO REMOTE** - This is MANDATORY: - ```bash - git pull --rebase - git push - git status # MUST show "up to date with origin" - ``` -5. **Clean up** - Clear stashes, prune remote branches -6. **Verify** - All changes committed AND pushed -7. **Hand off** - Provide context for next session - -**CRITICAL RULES:** -- Work is NOT complete until `git push` succeeds -- NEVER stop before pushing - that leaves work stranded locally -- NEVER say "ready to push when you are" - YOU must push -- If push fails, resolve and retry until it succeeds - diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index cd553b9..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1,70 +0,0 @@ -# Project Instructions for AI Agents - -This file provides instructions and context for AI coding agents working on this project. - - -## Beads Issue Tracker - -This project uses **bd (beads)** for issue tracking. Run `bd prime` to see full workflow context and commands. - -### Quick Reference - -```bash -bd ready # Find available work -bd show # View issue details -bd update --claim # Claim work -bd close # Complete work -``` - -### Rules - -- Use `bd` for ALL task tracking β€” do NOT use TodoWrite, TaskCreate, or markdown TODO lists -- Run `bd prime` for detailed command reference and session close protocol -- Use `bd remember` for persistent knowledge β€” do NOT use MEMORY.md files - -**Architecture in one line:** issues live in a local Dolt DB; sync uses `refs/dolt/data` on your git remote; `.beads/issues.jsonl` is a passive export. See https://github.com/gastownhall/beads/blob/main/docs/SYNC_CONCEPTS.md for details and anti-patterns. - -## Session Completion - -**When ending a work session**, you MUST complete ALL steps below. Work is NOT complete until `git push` succeeds. - -**MANDATORY WORKFLOW:** - -1. **File issues for remaining work** - Create issues for anything that needs follow-up -2. **Run quality gates** (if code changed) - Tests, linters, builds -3. **Update issue status** - Close finished work, update in-progress items -4. **PUSH TO REMOTE** - This is MANDATORY: - ```bash - git pull --rebase - git push - git status # MUST show "up to date with origin" - ``` -5. **Clean up** - Clear stashes, prune remote branches -6. **Verify** - All changes committed AND pushed -7. **Hand off** - Provide context for next session - -**CRITICAL RULES:** -- Work is NOT complete until `git push` succeeds -- NEVER stop before pushing - that leaves work stranded locally -- NEVER say "ready to push when you are" - YOU must push -- If push fails, resolve and retry until it succeeds - - - -## Build & Test - -_Add your build and test commands here_ - -```bash -# Example: -# npm install -# npm test -``` - -## Architecture Overview - -_Add a brief overview of your project architecture_ - -## Conventions & Patterns - -_Add your project-specific conventions here_ diff --git a/PLAN.md b/PLAN.md deleted file mode 100644 index 9e5ad6e..0000000 --- a/PLAN.md +++ /dev/null @@ -1,170 +0,0 @@ -# Jolt β€” Complete Implementation Plan - -## Architecture Goal - -Minimal Janet bootstrap β†’ SCI/CLJS Clojure source runs on Jolt. - -Three layers: -1. **Janet runtime**: types.janet, reader.janet, evaluator.janet, compiler.janet (~4,200 lines) -2. **Clojure core**: core.janet (~1,400 lines), phm.janet (~200 lines) -3. **Clojure source** (.clj files loadable at runtime): stdlib modules, SCI - -## Current State - -Tests are organized in three layers (see the README "Test" section): -`test/spec/` (the black-box contract), `test/integration/` (cross-cutting and -external-suite regression batteries), and `test/unit/` (white-box component -tests). `jpm test` is green. - -| Metric | Value | -|--------|-------| -| Spec contract | ~1,000 cases across 24 `test/spec/` files | -| Integration batteries | 12 (conformance, SCI bootstrap/runtime, jank, clojure-test-suite, compile-mode, API, systematic-coverage) | -| Unit tests | 9 files (reader, evaluator, types, collections, regex, compiler) | -| Clojure conformance | 218/218 | -| clojure-test-suite | ~3,920 assertions pass (remainder are documented platform/design divergences) | -| Source lines | ~8,600 (`src/jolt/*.janet`; core.janet ~4,000) | -| SCI source files loading | 9/9 | -| Reader literals | full numeric syntax (`N`/`M`/ratio/radix/exponent/`##Inf`); see `doc/grammar.ebnf` | - -## Phase Plan - -### Phase 0-10: Foundation βœ“ - -| Phase | Description | Status | -|-------|-------------|--------| -| 0 | `defn` bug fix, bare symbol resolution | βœ“ | -| 1 | Var/Namespace system, ns form extensions | βœ“ | -| 2 | PersistentHashMap implementation | βœ“ | -| 3 | Var system: var-get/set/?, alter-var-root, intern, binding | βœ“ | -| 4 | deftype/defrecord completion | βœ“ | -| 5 | Multimethods + Hierarchy | βœ“ | -| 6 | Reader extensions: tagged literals, :jolt/tagged handler | βœ“ | -| 7 | LazySeq + PersistentHashSet | βœ“ | -| 8 | Protocol system: defprotocol, extend-type, extend-protocol, reify, satisfies? | βœ“ | -| 9 | REPL fixes: buffer-based output, collection rendering, cond fix | βœ“ | -| 10 | Standard Library: clojure.string, clojure.set, clojure.walk, clojure.zip, clojure.edn, clojure.java_io, jolt.interop, jolt.shell, jolt.http | βœ“ | - -### Phase 11: Fix Pre-existing Failures βœ“ - -- `types.janet`: `ns?` now accepts both structs and tables -- `core.janet`: `comment` macro wired into core-bindings -- `sci/lang_stubs.clj`: minimal SCI type stubs for bootstrap -- `test-load-sci.janet`: load stubs before SCI source files -- **Result: SciVar fixed. 1 remaining (deftype with `#?@` β€” Phase 15)** - -### Phase 12: Core Feature Completion βœ“ - -- `apply` support in evaluator + compiler -- `str` handles nil correctly -- 6 CLJS test files created (~120 assertions) -- `#()` anonymous fn reader with `%`, `%1`, `%2` arg handling - -### Phase 13: Protocol Completion βœ“ - -- reify dispatch: protocol methods work on reified objects -- `#()` reader macro with gensym-based `%` arg handling -- IFn protocol support in default invocation arm -- clojure.walk loads and `keywordize-keys` works -- 4 test sections: reify dispatch, anon fn, extend-type, walk loading - -### Phase 14: Extend CLJS Ported Tests βœ“ - -- `cljs-port-2.janet` expanded: 10 sections (12-21), 35β†’60 assertions -- `cljs-port-5.janet` created: sections 22-24, destructuring, metadata, fn composition -- `pr-str` compiler fix: maps to new `core-pr-str` (not `core-str`) -- `every-pred` added to core.janet -- `var-dynamic?` and `with-meta` tests restored - -### Phase 15: SCI Bootstrap βœ“ - -- βœ… `sci.lang` namespace loads completely (all 10 forms, including Var, Type, Namespace deftypes) -- βœ… 9 SCI source files load without errors (impl/macros, impl/protocols, impl/types, impl/unrestrict, impl/vars, lang, impl/utils, impl/namespaces, core) -- βœ… `prefer-method`/`remove-method`/`remove-all-methods` promoted to special forms (fix: auto-deref gave functions to `get`/`put`) -- βœ… All 5 pre-existing test failures fixed: - - `cljs-port-1.janet` β€” `#{}` Janet comment issue replaced with count-based comparisons - - `cljs-port-2.janet` β€” `with-meta` added as core binding with table/setproto - - `cljs-port-3b.janet` β€” `load-string` multi-form loader for string.clj and set.clj - - `cljs-port-5.janet` β€” `var-dynamic?` core binding + `^:dynamic` def handler fix - - `phase5-test.janet` β€” `remove-method` special form fixed to eval-form first arg -- New core infrastructure: `core-with-meta` (supports structs/tables via prototype), `core-var-dynamic?`, `load-string` API, `^:dynamic` propagation in `def` handler -- `core-str` now returns `"nil"` for nil (Clojure-compatible) -- `core-meta` checks `:jolt/meta` for with-meta'd values -- Test suite: **317/317 pass, 0 fail** - -### Phase 16: Remaining Core Library + Tests βœ… - -- βœ… `eval` implemented as special form (interpreter + compiler), tested in `eval-test.janet` (4 assertions) -- βœ… `&` rest destructuring, `seq` nil handling, `vector`/`list` equality verified working -- βœ… `syntax-quote` confirmed working with unquote -- βœ… 5 new CLJS ported test files (cljs-port-6 through -10): anon fns, symbols/keywords/lists, destructuring, range/concat/partition/sort, seq predicates/complement, when/if-let/doto -- βœ… 16 total CLJS ported test files, 440 assertions across 31 test files -- βœ… 317/317 tests pass, 0 failing scripts - -### Phase 19: Clojure Conformance Hardening βœ… - -Added `test/conformance.janet` β€” a harness that evaluates `(= expected actual)` -inside jolt (using jolt's own `=`, i.e. real Clojure semantics), seeded from -`~/src/clojure/test`. Drove fixes for a large class of real-Clojure idioms the -bespoke `.janet` suite never exercised. **80/80 conformance, 46/46 legacy suite, -0 SCI-load failures.** - -CRITICAL (core semantics): -- Collections as IFn (`([v] i)`, `({m} k)`, `(#{s} x)`) via unified `jolt-invoke` -- Unified vector representation on Janet tuples (PersistentVector was broken/disconnected) -- `=`/`reduce`/`vec`/`into` now realize lazy-seqs; `into {}`/`into ()` fixed -- Lazy `iterate`/`range`(infinite)/single-coll `map` (over lazy input) -- Truly lazy `concat` β†’ self-referential `lazy-cat`/`lazy-seq` work (`fib-seq`) - -HIGH: -- Unified recursive destructuring (nested seq/map, `:strs`/`:syms`/`:or`/`:as`, fn-params) -- `defn` docstring/attr-map handling (docstring'd fns were silently param-less) -- Clojure `str`/`pr-str` (nilβ†’"", keywords/symbols, collections render readably) -- `update`/`update-in`/`assoc-in` on immutable maps; multimethod `:default` key dispatch -- defrecord inline protocol methods with field scope -- `require` loads stdlib namespaces from disk + aliased-ns resolution (`s/join`) - -MED: -- New: peek/pop/subvec/reduce-kv/cycle/partition-all/reductions/dedupe/ - keep-indexed/map-indexed/trampoline/format/read-string/fnil + letfn/doseq macros -- Recursive `jolt-equal?` (nested sequential + order-independent map equality) -- Lazy `filter`/`take-while`/`remove` over lazy input -- REPL: lazy-seq printer walks full chain (capped); `def`/`defn` print `#'ns/name` - -**Gap-closing batch** (conformance grew to 157 cases): full atoms; typed -volatiles + delays (deref/force/realized?); quot/rem/mod sign semantics; a regex -subsystem (`src/jolt/regex.janet`, regexβ†’PEG, `#"..."` literals, re-find/matches/ -seq, string split/replace); sorted-map/sorted-set; `Math/*` statics; ex-info/ -ex-data/ex-message; namespaced keywords; ~40 added core fns (split-at, take-nth, -butlast, filterv/mapv, reduced, min/max-key, find, some-fn, sequential?/ifn?/…) -plus defonce/macroexpand-1/letfn/doseq; and fixes to doto, assoc/update-on-vector, -frequencies, coll?, sort, partition. - -**Feature batch** (conformance now 184): proper **char type** (`\a` reads to a -char value, char?/char/int/str, string seq/first/nth yield chars, `\a` printing); -**transducers** (map/filter/take/… no-coll arity returns a transducer; transduce/ -into-xform/sequence/eduction/reduced; reduce honors reduced); **compiler-path -IFn dispatch** (jolt-call makes collections callable in `:compile?` mode; compiled -set/char literals); and a **multi-line REPL** (accumulates until the form is -balanced). - -Deferred: full regex (lookaround/backrefs β€” the PEG-backed engine covers the -common subset). STM (refs/agents/dosync) intentionally skipped. - -### Phase 17: Optimization - -- Compiler improvements: inline small core functions -- PersistentHashMap dynamic bucket growth -- Benchmarks - -### Phase 18: Standard Library Completion - -- Complete EDN reader/writer -- Complete java.io wrappers -- clojure.zip tests - -## Implementation Order - -1. βœ… Phases 0-16 (completed) -2. Phase 17 (optimization: compiler inlining, PHM bucket growth, benchmarks) -3. Phase 18 (stdlib: EDN reader/writer, java.io wrappers, clojure.zip tests) diff --git a/clojure-features.clj b/clojure-features.clj deleted file mode 100644 index 793cdf5..0000000 --- a/clojure-features.clj +++ /dev/null @@ -1,241 +0,0 @@ -;; ============================================================ -;; Comprehensive Clojure Features Demo -;; ============================================================ - -;; 1. Destructuring (sequential & associative) -(defn destructure-demo [] - (println "\n--- Destructuring ---") - - ;; Sequential destructuring - (let [[a b c] [10 20 30]] - (println (str "Seq destructure: a=" a ", b=" b ", c=" c))) - - ;; Associative destructuring with defaults - (let [{:keys [name age city] :or {city "Unknown"}} {:name "Alice" :age 30}] - (println (str "Map destructure: name=" name ", age=" age ", city=" city))) - - ;; Nested destructuring - (let [{[x y] :coords} {:coords [1.0 2.5]}] - (println (str "Nested destructure: x=" x ", y=" y)))) - -;; 2. Atoms – state management -(defn atom-demo [] - (println "\n--- Atoms ---") - (def counter (atom 0)) - - ;; swap! (function-based update) - (swap! counter inc) - (println (str "After swap! inc: " @counter)) - - ;; reset! (set new value) - (reset! counter 100) - (println (str "After reset! to 100: " @counter)) - - ;; compare-and-set! (CAS) - (let [old @counter] - (if (compare-and-set! counter old (+ old 5)) - (println (str "CAS success: " @counter)) - (println "CAS failed"))) - - ;; Using atom with swap! and multiple updates - (swap! counter #(-> % (* 2) (+ 3))) - (println (str "After thread-first swap!: " @counter))) - -;; 3. Lazy sequences – infinite & transformed -(defn lazy-seq-demo [] - (println "\n--- Lazy Sequences ---") - - ;; Infinite lazy seq: natural numbers - (def naturals (iterate inc 0)) - - ;; Take first 10 even numbers using filter (lazy) - (def first-ten-evens (take 10 (filter even? naturals))) - (println (str "First 10 evens: " (pr-str first-ten-evens))) - - ;; Map and take-while (lazy) - (def squares-under-50 - (take-while #(< % 50) (map #(* % %) (range)))) - (println (str "Squares under 50: " (pr-str squares-under-50))) - - ;; Cycle and interpose (lazy) - (def repeated-pattern (take 10 (cycle [:a :b :c]))) - (println (str "Cycled pattern: " (pr-str repeated-pattern))) - - ;; Lazy seq from recursion (not fully lazy, but demonstrates lazy cons) - (defn my-iterate [f x] - (lazy-seq (cons x (my-iterate f (f x))))) - (def powers-of-two (take 8 (my-iterate #(* 2 %) 1))) - (println (str "Powers of two: " (pr-str powers-of-two)))) - -;; 4. Transducers – composable transformations -(defn transducer-demo [] - (println "\n--- Transducers ---") - - ;; Compose mapping and filtering as a transducer - (def xf (comp (map inc) (filter odd?))) - - ;; Apply to a collection (into) - (def result (into [] xf (range 10))) - (println (str "Transducer result: " (pr-str result))) - - ;; Use with sequence (sequence) - (def seq-result (sequence xf (range 10))) - (println (str "Transducer seq: " (pr-str seq-result)))) - -;; 5. Protocols & Records – polymorphism -(defprotocol Shape - (area [this]) - (description [this])) - -(defrecord Circle [radius] - Shape - (area [_] (* Math/PI radius radius)) - (description [_] (str "Circle with radius " radius))) - -(defrecord Rectangle [width height] - Shape - (area [_] (* width height)) - (description [_] (str "Rectangle " width "x" height))) - -(defn protocol-demo [] - (println "\n--- Protocols & Records ---") - (def c (->Circle 5)) - (def r (->Rectangle 3 4)) - (println (str (description c) " -> area: " (area c))) - (println (str (description r) " -> area: " (area r)))) - -;; 6. Multimethods – dispatch on arbitrary values -(defmulti shape-type :kind) -(defmethod shape-type :circle [_] "round") -(defmethod shape-type :rectangle [_] "angular") -(defmethod shape-type :default [_] "unknown") - -(defn multimethod-demo [] - (println "\n--- Multimethods ---") - (def s1 {:kind :circle :radius 5}) - (def s2 {:kind :rectangle :width 3 :height 4}) - (def s3 {:kind :triangle}) - (println (str "Circle type: " (shape-type s1))) - (println (str "Rectangle type: " (shape-type s2))) - (println (str "Triangle type: " (shape-type s3)))) - -;; 7. Macros – compile-time code generation -(defmacro log-call [expr] - `(let [result# ~expr] - (println (str "Called: " (pr-str '~expr) " -> " result#)) - result#)) - -(defn macro-demo [] - (println "\n--- Macros ---") - (log-call (* 2 3)) - (log-call (map inc [1 2 3])) - (log-call (reduce + (range 1 6)))) - -;; 8. Recursion – linear and tail-recursive -(defn recursion-demo [] - (println "\n--- Recursion ---") - ;; Linear recursion: factorial - (defn fact [n] - (if (<= n 1) 1 (* n (fact (dec n))))) - (println (str "Factorial 5: " (fact 5))) - - ;; Tail recursion with recur - (defn fact-tail [n] - (loop [i n acc 1] - (if (zero? i) acc - (recur (dec i) (* acc i))))) - (println (str "Tail-factorial 5: " (fact-tail 5))) - - ;; Mutual recursion with trampoline - (declare even?) - (defn odd? [n] - (if (zero? n) false (even? (dec n)))) - (defn even? [n] - (if (zero? n) true (odd? (dec n)))) - (println (str "Is 6 even? " (even? 6)))) - -;; 9. Higher-order functions – partial, comp, juxt -(defn hof-demo [] - (println "\n--- Higher-Order Functions ---") - (def add5 (partial + 5)) - (println (str "Partial (+5) applied to 10: " (add5 10))) - - (def inc-and-double (comp #(* 2 %) inc)) - (println (str "Comp (double∘inc) on 3: " (inc-and-double 3))) - - (def stats (juxt identity inc dec)) - (println (str "Juxt on 5: " (stats 5)))) - -;; 10. Threading macros (-> and ->>) -(defn threading-demo [] - (println "\n--- Threading Macros ---") - (def result - (->> (range 20) - (filter odd?) - (map #(* % 3)) - (take 5) - (reduce +))) - (println (str "Threaded pipeline result: " result)) - - (def threaded-sqrt - (-> 25 Math/sqrt long (+ 10))) - (println (str "Thread-first sqrt: " threaded-sqrt))) - -;; 11. Exception handling with try/catch/finally -(defn exception-demo [] - (println "\n--- Exception Handling ---") - (try - (throw (ex-info "something broke" {:code 42})) - (catch :default e - (println (str "Caught: " (ex-message e) " " (pr-str (ex-data e))))) - (finally - (println "Finally block executed.")))) - -;; 12. Clojure's sequence comprehension: for (list comprehension) -(defn for-demo [] - (println "\n--- For Comprehension ---") - (def combos - (for [x (range 3) - y (range 3) - :when (not= x y)] - [x y])) - (println (str "Combinations (x!=y): " (pr-str combos)))) - -;; 13. Clojure's core.async? Not pure Clojure, skip. - -;; 14. Janet host interop β€” Jolt runs on Janet, so host interop is Janet-style: -;; `.` dispatches on a table/struct (the receiver is passed as the first -;; arg), and Janet's standard library is reachable through jolt.interop. -(defn janet-interop-demo [] - (println "\n--- Janet Interop ---") - ;; Method-style call on a Janet table: self is passed as the first argument. - (def counter {:value 41 - :describe (fn [self] (str "counter = " (:value self)))}) - (println (str "Method call: " (. counter describe))) - ;; Field access sugar: (.-k m) is (. m :k) - (println (str "Field access: " (.-value counter))) - ;; Reach Janet's standard library through jolt.interop. - (require '[jolt.interop :as j]) - (println (str "Janet type: " (j/janet-type [1 2 3]))) - (println (str "Table keys: " (pr-str (j/janet-table-keys {:a 1 :b 2}))))) - -;; ---------- Main entry point ---------- -(defn -main [] - (println "=== Clojure Features Demo ===") - (destructure-demo) - (atom-demo) - (lazy-seq-demo) - (transducer-demo) - (protocol-demo) - (multimethod-demo) - (macro-demo) - (recursion-demo) - (hof-demo) - (threading-demo) - (exception-demo) - (for-demo) - (janet-interop-demo) - (println "\n=== Demo Complete ===")) - -;; Run if executed as script -(-main) diff --git a/fix-core.janet b/fix-core.janet deleted file mode 100644 index d73ce4d..0000000 --- a/fix-core.janet +++ /dev/null @@ -1,14 +0,0 @@ -(def lines (string/split "\n" (slurp "src/jolt/core.janet"))) -(def new-lines @[]) -(each l lines - (array/push new-lines l) - (if (= l " new-val))") - (do - (array/push new-lines "") - (array/push new-lines "# Hierarchy (minimal stubs for sci bootstrap)") - (array/push new-lines "(defn core-derive [tag parent] nil)") - (array/push new-lines "(defn core-isa? ([child parent] false) ([h child parent] false))") - (array/push new-lines "(defn core-ancestors ([tag] #{}) ([h tag] #{}))") - (array/push new-lines "(defn core-descendants ([tag] #{}) ([h tag] #{}))")))) -(spit "src/jolt/core.janet" (string/join new-lines "\n")) -(print "done") diff --git a/preprocess.janet b/preprocess.janet deleted file mode 100644 index c6d0049..0000000 --- a/preprocess.janet +++ /dev/null @@ -1,21 +0,0 @@ -# Preprocess a cljc file: resolve #?(:clj ...) and #?@(:clj ...) reader conditionals -# at read time. Output a plain .clj file that Jolt can parse without reader conditionals. - -(use ./src/jolt/reader) - -(defn preprocess [filepath] - (def src (slurp filepath)) - (var s src) - (var out @[]) - (var count 0) - (while (> (length (string/trim s)) 0) - (def [form rest] (parse-next s)) - (set s rest) - (++ count) - (if (nil? form) - nil - (array/push out (string form)))) - (string/join out "\n")) - -(def filepath (if (> (length (dyn :args @[])) 0) (in (dyn :args) 0) "/Users/yogthos/src/sci/src/sci/impl/utils.cljc")) -(print (preprocess filepath)) diff --git a/test-defprotocol.janet b/test-defprotocol.janet deleted file mode 100644 index 6eea727..0000000 --- a/test-defprotocol.janet +++ /dev/null @@ -1,26 +0,0 @@ -(use ./src/jolt/evaluator) -(use ./src/jolt/types) -(use ./src/jolt/reader) -(use ./src/jolt/api) - -(def ctx (init)) - -# Test simple defprotocol expansion -(def proto-name {:jolt/type :symbol :ns nil :name "IBox"}) -(def sig1 @[{:jolt/type :symbol :ns nil :name "setVal"} {:jolt/type :symbol :ns nil :name "_this"} {:jolt/type :symbol :ns nil :name "_v"}]) -(def sig2 @[{:jolt/type :symbol :ns nil :name "getVal"} {:jolt/type :symbol :ns nil :name "_this"}]) - -# Call core-defprotocol directly -(use ./src/jolt/core) -(def expanded (core-defprotocol proto-name sig1 sig2)) -(print "expanded: " (string expanded)) - -# Try to eval it -(def [ok err] (protect (eval-form ctx @{} expanded))) -(if ok - (do - (print "eval OK!") - (let [ns (ctx-find-ns ctx (ctx-current-ns ctx))] - (printf "IBox: %q\n" (ns-find ns "IBox")) - (printf "setVal: %q\n" (ns-find ns "setVal")))) - (printf "eval FAIL: %q\n" err)) diff --git a/test-eval.janet b/test-eval.janet deleted file mode 100644 index e1851d2..0000000 --- a/test-eval.janet +++ /dev/null @@ -1,42 +0,0 @@ -(use ./src/jolt/evaluator) -(use ./src/jolt/types) -(use ./src/jolt/reader) -(use ./src/jolt/api) - -(def ctx (init)) - -(defn load-all [] - (each fp ["/Users/yogthos/src/sci/src/sci/impl/macros.cljc" - "/Users/yogthos/src/sci/src/sci/impl/protocols.cljc" - "/Users/yogthos/src/sci/src/sci/impl/utils.cljc" - "/Users/yogthos/src/sci/src/sci/impl/types.cljc" - "/Users/yogthos/src/sci/src/sci/impl/unrestrict.cljc"] - (def src (slurp fp)) - (var s src) - (while (> (length (string/trim s)) 0) - (def [f r] (parse-next s)) (set s r) - (if (not (nil? f)) (protect (eval-form ctx @{} f))))) - (def vs (slurp "/Users/yogthos/src/sci/src/sci/impl/vars.cljc")) - (var s vs) (var c 0) - (while (and (> (length (string/trim s)) 0) (< c 27)) - (def [f r] (parse-next s)) (set s r) (++ c) - (if (not (nil? f)) (protect (eval-form ctx @{} f)))) - (each fp ["/Users/yogthos/src/sci/src/sci/lang.cljc" - "/Users/yogthos/src/sci/src/sci/core.cljc"] - (def src (slurp fp)) - (var s src) - (while (> (length (string/trim s)) 0) - (def [f r] (parse-next s)) (set s r) - (if (not (nil? f)) (protect (eval-form ctx @{} f)))))) - -(load-all) - -(print "=== Testing eval-string ===") - -# Call sci.core/eval-string via our own eval -(def src "(do (require (quote [sci.core :as sci])) (sci/eval-string (sci/init) (str (+ 1 2))))") -(printf "eval: %s\n" src) -(try - (def result (eval-form ctx @{} (parse-string src))) - (printf "result: %q\n" result) - ([err] (printf "FAIL: %q\n" err))) diff --git a/test-form15.janet b/test-form15.janet deleted file mode 100644 index c53023b..0000000 --- a/test-form15.janet +++ /dev/null @@ -1,13 +0,0 @@ -(use ./src/jolt/reader) - -(def src (slurp "/Users/yogthos/src/sci/src/sci/impl/utils.cljc")) -(var s src) -(for i 1 14 - (let [p (parse-next s)] - (set s (in p 1)))) - -(def [form15 rest] (parse-next s)) -(if (array? form15) - (printf "form15: (%s ...)" (get (first form15) :name)) - (printf "form15: %q" form15)) -(printf " => OK, rest: %d bytes" (length rest)) diff --git a/test-ivar.janet b/test-ivar.janet deleted file mode 100644 index 8cea3cc..0000000 --- a/test-ivar.janet +++ /dev/null @@ -1,16 +0,0 @@ -(use ./src/jolt/evaluator) -(use ./src/jolt/types) -(use ./src/jolt/reader) -(use ./src/jolt/api) - -(def ctx (init)) -(eval-form ctx @{} (parse-string "(ns sci.lang)")) -(eval-form ctx @{} (parse-string "(definterface IVar)")) - -# Resolve sci.lang/IVar by evaluating as a qualified symbol -(def sym (parse-string "sci.lang/IVar")) -(printf "sym: %q\n" sym) -(try - (def v (eval-form ctx @{} sym)) - (printf "resolved: %q\n" v) - ([err] (printf "error: %q\n" err))) diff --git a/test-load-sci.janet b/test-load-sci.janet deleted file mode 100644 index aa9fb3e..0000000 --- a/test-load-sci.janet +++ /dev/null @@ -1,44 +0,0 @@ -(use ./src/jolt/evaluator) -(use ./src/jolt/types) -(use ./src/jolt/reader) -(use ./src/jolt/api) - -(def ctx (init)) - -(defn load-file-quiet [ctx fp stop-at] - (def src (slurp fp)) - (var s src) - (var c 0) - (var good 0) - (var bad 0) - (while (and (> (length (string/trim s)) 0) (or (not stop-at) (< c stop-at))) - (def pr (protect (parse-next s))) - (if (not (pr 0)) (do (printf "%s PARSE CRASH: %q\n" fp (pr 1)) (break))) - (let [[f r] (pr 1)] - (set s r) - (++ c) - (if (not (nil? f)) - (let [pr2 (protect (eval-form ctx @{} f))] - (if (pr2 0) (++ good) (++ bad)))))) - {:count c :good good :bad bad}) - -(each fp ["/Users/yogthos/src/sci/src/sci/impl/macros.cljc" - "/Users/yogthos/src/sci/src/sci/impl/protocols.cljc" - "/Users/yogthos/src/sci/src/sci/impl/utils.cljc" - "/Users/yogthos/src/sci/src/sci/impl/types.cljc" - "/Users/yogthos/src/sci/src/sci/impl/unrestrict.cljc"] - (load-file-quiet ctx fp nil)) - -(load-file-quiet ctx "/Users/yogthos/src/sci/src/sci/impl/vars.cljc" 27) -(load-file-quiet ctx "/Users/yogthos/src/sci/src/sci/lang.cljc" nil) - -# Summary -(printf "\nSummary:\n") -(printf "ns: %s\n" (ctx-current-ns ctx)) - -# Try loading sci.core -(print "\nLoading sci.core...") -(def r (load-file-quiet ctx "/Users/yogthos/src/sci/src/sci/core.cljc" nil)) -(printf "sci.core: %d forms, %d ok, %d fail\n" (r :count) (r :good) (r :bad)) - -(printf "ns: %s\n" (ctx-current-ns ctx)) diff --git a/test-parse-utils.janet b/test-parse-utils.janet deleted file mode 100644 index 6f14db6..0000000 --- a/test-parse-utils.janet +++ /dev/null @@ -1,18 +0,0 @@ -(use ./src/jolt/reader) -(def s (slurp "/Users/yogthos/src/sci/src/sci/impl/utils.cljc")) -(var ss s) -(var i 0) -(while (< i 14) - (def [f r] (parse-next ss)) - (set ss r) - (++ i)) -(try - (def [form rest] (parse-next ss)) - (if (array? form) - (let [h (first form)] - (if (and (struct? h) (= :symbol (h :jolt/type))) - (print (string "form: (" (h :name) "...)")) - (print (string "form: array head " (type h))))) - (print (string "form: " (type form) " " (string form)))) - (print (string "OK rest: " (string/slice rest 0 80))) - ([err] (print (string "FAIL: " err)))) diff --git a/test/integration/features-test.janet b/test/integration/features-test.janet index bb255f2..7785451 100644 --- a/test/integration/features-test.janet +++ b/test/integration/features-test.janet @@ -1,6 +1,7 @@ -# Regression tests mirroring clojure-features.clj, plus expanded coverage of -# related features. Each case asserts (= expected actual) evaluated inside Jolt -# (so comparisons use Jolt's own Clojure-semantics =). Run via `jpm test`. +# Feature regression tests: a broad sweep of Clojure features (destructuring, +# multimethods, protocols, laziness, …). Each case asserts (= expected actual) +# evaluated inside Jolt (so comparisons use Jolt's own Clojure-semantics =). +# Run via `jpm test`. (use ../../src/jolt/api) (var pass 0) @@ -143,11 +144,3 @@ (when (pos? (length fails)) (error (string (length fails) " feature regression(s)"))) (print "All feature tests passed!") - -# Smoke test: the demo file itself loads and runs end-to-end without error. -(when (os/stat "clojure-features.clj") - (print "\n--- running clojure-features.clj (smoke test) ---") - (def res (protect (load-string (init) (slurp "clojure-features.clj")))) - (unless (= (res 0) true) - (error (string "clojure-features.clj failed to run: " (res 1)))) - (print "--- clojure-features.clj ran cleanly ---"))