Skip to the content.

boop Framework – TODO

Active work items. Completed items live in DEVLOG.md. Design rationale lives in the relevant docs/ files. Inline TODOs in source files should reference entries here by section name.


Documentation & Code Comment Fact-Check Audit

Full survey of every factual claim in every .md file under docs/ and every comment in every source file under the repo root, boop, bin/, Geometry/, Games/, Collection/, Math/, Testing/, Config/, Data/, Text/, Signal/, SemVer/, Mixins/, and tests/.

Specifically look for:


_Self / _Class Default Audit (survey + evaluate — NOT a rewrite)

This is an audit. Audit means survey and report, not refactor. The job is to walk every method that defaults _Self to _Class (directly, or via ${_Self:-${_Class:-ClassName}}), describe what it actually does, and judge whether that default is right for that specific method. Do NOT blindly align every class to one preamble — intent differs per method, and aligning without thinking is exactly how this went wrong before.

Design intent — the default is a FEATURE, not a bug

_Self deliberately falls back to _Class so the same inherited accessor and method logic can operate on either an object or the class itself. Class-level properties act as prototype defaults for new instances:

So by default a constructor should consult the class for any attribute defined on the class but not set on the object, and seed the new object from the class value when one exists. That prototype behavior is the whole point of the _Self:-_Class default.

If a given method should NOT behave that way, that method simply doesn’t use the default — write it however it needs to be. The decision is per-method. Uniformity is not the goal; correctness-of-intent is.

What this audit produces

For each method, report what it does and classify its use (or non-use) of the _Self:-_Class default as one of:

The codebase is currently mixed: some methods default _Self to _Class, others to empty (${_Self:-}). Reconciling that inconsistency — deciding which each method should be and why — is part of the audit, not a foregone conclusion in either direction.

How we work this

One file at a time. No hurry. Look the methods over, discuss as much as it takes, record notes below, come back another day, change focus when we feel like it. We finish when we finish. Nothing here gets changed in code until we’ve talked it through and agreed on the call for that method.

Files to survey (check off as evaluated)

Findings

(per-file notes go here as we go — method, current default, classification, reasoning, and any agreed action)

boop (surveyed 2026-06-10)

Only three functions use the ${_Self:-${_Class:-boop}} pattern, and all three are the identity primitives — verdict: neat feature, no change:

Everything else in boop deliberately defaults _Self to empty (${_Self:-}) and never falls back to class — these are low-level primitives fed an explicit _Self by the baked dispatch wrappers: isObject, __boop.get, __boop.set, __boop.isa, __boop.mixes, __boop.toString, __boop.inspect, __boop.destroy, __boop.trueClass, __boop.new. Correct as-is. So boop is internally consistent: identity resolvers use the class fallback, storage primitives don’t.

OPEN THREAD (revisit — not a _Self issue, but adjacent): the prototype-inheritance behavior the design intends (a new Box inheriting Box.color when its own color is unset). Today it is NOT wired up:

Suspicion (to verify): the automatic fallback existed a week/month ago and was removed. TODO tomorrow: git log -p/git blame around __boop.get and getOrClass to find when/why it was removed, then decide: re-implement implicit instance→class fallback, build inheritValueFor, or (at minimum) fix the stale registerClass comment.


Error Severity Reclassification — DONE (2026-06-07)

All data-condition _Crash calls reclassified to _Error + return 1. Contract documented in docs/STANDARDS.md “Error Handling” section.

_Crash now reserved exclusively for: security/injection violations, framework internal corruption, class/mixin declaration errors, version constraint failures, and abstract method stubs. Everything a caller can reasonably recover from uses _Error + return 1 so _FatalLevel applies.

Files changed: Collection/List/List, Collection/Container/Container, Math/Math, Text/String/String, SemVer/SemVer, Testing/TestSuite/TestSuite, Signal/Signal. All test suites pass.


Phase 1 (SemVer, boop version guard, class version token, _Require version checking) is done – see DEVLOG.

Component What it enables Fallback without it
ArgParser key=value, positional, flag parsing for constructors and methods Warn, ignore args / use current ad-hoc loops
Help --help on classes, auto-generated from descriptors Warn, no help output

:: Syntax – Future Uses

Mixins done (see DEVLOG). Remaining:


Args – Pending Items

Core done. 71 tests. Docs at docs/Args.md.


I/O Classes (Phase 5)

Stream – Remaining Work

Stream – Optimization Opportunities

★ Garbage Collection / Object Lifecycle

DONE — $obj.destroy implemented in core (2026-05-26). See docs/boop.md “Destroying Objects” section.

Remaining:

Delimiter Consistency Audit

Every method that joins or splits values should respect _Delimiter and _EOL consistently. Current coverage is good but not fully audited.

Internal Descriptor Separator (low priority)

Comma reserved in method/property/mixin names. Consider $'\x1f' or pipe as alternative. Same applies to Taggable’s comma-separated storage.


Return System Filesystem Mode

boop.passPath – filesystem-backed return path via call stack introspection. Useful for large payloads that don’t fit comfortably in variables. Consider _File as a Tier 2 inherited var on boop.pass.


Implicit Object Declaration on Return (_AS=)

Explore whether boop.pass could auto-wrap a return value as an object of a specified class. Might not be worth the complexity.


Try/Catch Mechanism – Low Priority

Bash has no native try/catch. Every approach has serious tradeoffs. Revisit if a compelling use case emerges.


Extensive Logging Hooks

Remaining areas lack coverage:

Log-level bypass (replacing silenced functions with : no-op) is already implemented. Verify it covers all tiers correctly.


Per-Class Work

boop (root class)

Math

Collection (Container, List, Map, Iterator)

Games (Card, PlayingCard, Deck, Blackjack)

JSON

Geometry (Box, Cube)


YAML Parser (Data.YAML)

Pure-bash YAML subset parser. Storage: Map.Fast (flat compound keys), same backend as Data.JSON. API mirrors Config.

Stage 1 — the 80% subset:

Stage 2 — flow syntax + multi-line:

Stage 3 — deferred:


boson — Structured Data Query Tool

“Bash Oriented Scripting Object Notation” — a jq-like query engine for structured data. Operates on any Map.Fast (JSON, YAML, Config).

STATUS (2026-06-07): Stage 1 and Stage 2 shipped. Stage 1: path/iteration/raw

# CLI usage (working today)
boson '.users[0].name' < data.json
boson -r '.users[].email' < data.json                       # raw, one per line
boson --emit '.database' < config.json                      # sourceable assignments
boson --into=host '.database.host' < c.json
boson -E '.database' < c.json                               # eponymous (leaf-name vars)
boson -r '.users[] | select(.age > 30) | .name' < d.json   # pipe + select
boson -r '.items[] | select(.tag =~ "^err") | .msg' < d.json  # regex predicate

Staged Roadmap

Stage Features Status
1 Path expressions (.foo.bar[2]), array iteration ([]), raw output DONE
Sourceable output: --emit, --into=VAR, -E/--eponymous DONE (doc-order preserved)
2 Pipe chaining, select() with comparisons, -n/-z, has(), =~ DONE
3 String interpolation ("Hello \(.name)"), object construction ({k: .v}) TODO
4 map/reduce/group_by, sort_by TODO
5 Recursive descent (..), multiple outputs TODO

What exists already:

What needs building (Stage 3+):


XML Parser (Future — Low Priority)

May not be worth pure-bash implementation. Deferred indefinitely.


Class-File Documentation Pass

File-level overview, per-method comment blocks, clear voice. Files remaining: Container, List, Map, Map::Fast, Stack, Queue, Set, Config, JSON, Math, Card, Deck, PlayingCard, TestSuite, Args, SemVer, Mixins/*. (Signal, String, DateTime already well-commented.)


Documentation Sync Pass — DONE (2026-06-07)

All local -I references removed from docs. STANDARDS.md “Inherited Identity Variables” section rewritten to document the actual mechanism (direct assignment in dispatch wrappers; framework targets bash 4.3+ and deliberately avoids local -I which is bash 5.0 only). Files updated: STANDARDS.md, Container.md, comparison.md, bash_style.md.


README Accuracy Audit — DONE (2026-06-07)

Properties section rewritten (bash stores everything as strings, no type system). _Cast/_Delegate/_Bless expanded with descriptions and examples. Added See docs/boop.md reference after _Super description.


★ Adoption & Distribution

1. Packaging, Bundling, and the Installer Mixin

The model: every tool is a gateway to the framework.

The bundle+installer pattern is the standard delivery vehicle for all boop-based standalone tools — boson, BusyBox fallbacks, example scripts, anything intended to be dropped onto a system and run. The shape is always the same: self-contained single file that works immediately with just bash, and optionally bootstraps the full framework on demand.

This means:

Standalone tools are distributed as single-file bundles — the framework + required classes concatenated inline, then the tool’s own code. They work immediately with no installation. But they also carry the Installer mixin, which can bootstrap the full framework on demand.

Naming convention (settled 2026-06-04): bundles are named bundle-<tool> (e.g. bundle-boson). collider’s default output uses this prefix; it groups all bundles together and keeps them visually distinct from the bare-named dev scripts they were built from. The bare name (boson) is reserved for the public release / the boopRoot-dependent dev script. Bundles are rename-safe — nothing inside keys off the filename — so a user may drop the prefix locally. (A trailing-dot or trailing-colon marker for dev scripts was considered and rejected: Windows and git cannot represent either filename.)

# Just use it — zero install, single file
boson '.name' < data.json

# What's inside?
boson --about          # "boson v1.0 — built on boop v0.1.0"

# Want the full framework?
boson --install              # → ~/.local/lib/boop + .booprc
boson --install /opt/boop    # custom location

Bundle format:

Installer mixin provides:

Bundle build tool (collider):

A real tool, not a cat pipeline. The bundler must:

  1. Resolve the dependency graph statically. Parse each class file for . boop ClassName, _Require, _Load, _Import, and boopClass ... isa:Parent. These are the edges. Recurse until all transitive deps are collected.

  2. Topological sort. Parents before children, deps before dependents. A class that declares isa:Box must appear after Box in the bundle. A class that does . boop Config must appear after Config.

  3. Neutralize source lines. Every . boop ClassName line in a bundled class file becomes a no-op (comment it out or replace with : # bundled). The framework’s __boop_loaded guard handles the boop-itself case, but class-level source lines would trigger filesystem resolution that doesn’t exist in a bundle context.

  4. Preserve load guards. boop.init ClassName || return 0 stays — it’s the idempotency mechanism. If the bundle is sourced into a shell that already has boop loaded, the guards prevent double-reg.

  5. Optional: strip comment-only lines. Lines matching ^\s*# (but NOT shebangs, NOT # shellcheck directives) can be removed for a ~35% size reduction. This is a separate pass, off by default. Inline comments (code # comment) are NOT stripped — that requires a real parser to distinguish # in strings/expansions from actual comments. Not worth the complexity for marginal gains.

  6. Append the Installer mixin gated behind --install detection.

Size budget (current stdlib):

What the bundler does NOT do:

Deferred:

2. Object Lifecycle / GC

DONE — see “Garbage Collection / Object Lifecycle” section above.

3. Error Recovery Beyond _Crash

Superseded by the Error Severity Reclassification (see top of this file). Once data-condition crashes become _Error + return 1, normal exit codes handle recovery. _Guard is unnecessary — the only remaining crashes are framework corruption and security violations, which should not be caught.

4. Reduced Naming Ceremony

The __ClassName_methodName_varname convention is correct but verbose. Every local is 30+ characters.

Options:

5. BusyBox Coverage Survey

BusyBox bundles ~300 Unix tools into a single binary for minimal environments where sed, tr, awk, etc. may not be present.

The pitch: not “replace BusyBox” but “consolation prize drop-in for systems where bash is present but specific tools aren’t.” On any given system — stripped container images, minimal cloud instances, embedded Linux, odd CI environments — something you expect to just be there sometimes isn’t. A boop script that gracefully falls back to a pure-bash implementation is more portable than one that crashes with command not found.

What boop can cover (~40–50% of BusyBox surface area)

Text processing and data manipulation — the half that’s pure computation with no kernel interface:

Tool(s) boop equivalent Status
bc Math Done — arbitrary precision, better than bc
date DateTime Done
grep (basic) Stream + regex mode Slower, no binary
cut, awk field split Stream -f/-F/-W Core use case
wc Stream accumulation Trivial to build
head/tail Stream with record limits Mostly covered
cat Stream passthrough Trivial
tr String.replace Done
sort/uniq List + sort callback Doable; slow on large input
basename/dirname Parameter expansion Pure bash already
seq, yes, true/false Trivial loops/builtins Trivial
expr Math Done
printf/echo Builtins Already there
Config/INI parsing Config Done, arguably more capable
JSON Data.JSON Done
sed (basic substitution) String pipeline Partial — no in-place file edit

Partial / awkward

Tool Limitation
find No filesystem traversal class — doable in bash, just tedious
xargs Buildable; arg-splitting edge cases are fiddly
tee Needs multi-FD output (Stream multi-FD model — planned)
diff Doable but pure-bash LCS is slow on large files
wget/curl (basic) /dev/tcp handles simple HTTP GETs; no HTTPS
nc /dev/tcp covers basic cases; Stream::Socket would handle properly

Hard limits — cannot replicate

Category Reason
Compression (gzip, tar, xz) Binary format + null-byte problem in bash variables
Checksums (md5sum, sha256sum) Bitwise ops are theoretically possible but agonizingly slow
Filesystem (mount, mkfs, mknod) Kernel interface — must be external
Process/init (ps deep, init, syslog) /proc is readable; kill needs syscall; init is a different world
User management (passwd, login) Security-critical — should never be pure bash
Hardware (ifconfig, udhcpc, mdev) Kernel interface
Editors (vi, nano) Possible in theory; enormous scope
Shell (ash, sh) Can’t replace the thing running you

Size and speed

Implementation approach

Don’t build monolithic replacements. Build thin boop wrappers that:

  1. Check for the real tool (command -v grep) and use it if present
  2. Fall back to the pure-bash equivalent if not
  3. Accept the same common flags so call sites don’t need to change

The consolation-prize version doesn’t need to match every flag or handle every edge case — just the 80% that scripts actually use.


6. lens — Text Stream Inspection Tool

DONE (2026-06-04) — fully implemented and tested. 38 assertions in tests/tools/test_lens cover all modes. See DEVLOG.

Design (as built):

One filtering axis per invocation:

These modes are mutually exclusive. Relative/absolute position also exclusive with each other. --not inverts any mode (including fields and chars). --number and --count are universal formatting options. Multiple files are processed independently (per-file headers, or -H filename prefixes, or a grand total in --count mode).

Stream delimiter options pass through: -d/-D/-E for record, -f/-F/-W for field. Enables paragraph mode, CRLF, multi-char delimiters out of the box.

Layered help: --help (compact synopsis), --options (full reference), --examples (cookbook), --about, --boop.

Deferred (not yet built):

Built 2026-06-05 (commits 8ce3bcc, 6741fcb) — now need suite tests + docs:

Proposed features (designed, not built):


7. Real-World Example Scripts

The blackjack game demonstrates the framework but not its utility.

Candidates:

7. Shell Completion for boopShell

Tab-completing $obj.<TAB> in the interactive REPL.

Implementation path:

8. Functional Collection Pipelines

$list | filter fn | map fn | collect without subshells.

Implementation path:


Feasibility Notes (2026-05-26)

Item Effort Complexity Blockers
Single-file bundle 1-2 hours Low Ordering deps correctly
Install script 2-3 hours Low Testing across platforms
$obj.destroy 4-6 hours Medium Companion array naming conventions vary
_Guard error recovery N/A N/A Superseded by error reclassification
Result objects 1-2 days High Pervasive API change if adopted broadly
Preprocessor for names 1-2 days High Adds build step, debugging indirection
Example scripts 1 day each Low Just writing them
Shell completion 4-8 hours Medium Readline integration, edge cases
filter/map/reduce 3-4 hours Low API design (new list vs mutate)

NUL Byte Warning — Documentation Coverage

Add explicit NUL byte warning (cannot hold or detect; silently truncated) near the top of documentation for any class or utility that handles values through bash variables:


_Self / _Class Default Audit (duplicate — see canonical entry above)

This was a second, also-incorrect copy of the old “preamble” entry. It framed the _Self:-_Class default as a bug to be stamped out. It is not — the default is intentional (class-level properties act as prototype defaults for instances). The real task is the survey-and-evaluate audit described in the canonical _Self / _Class Default Audit section near the top of this file. Work it there.


Documentation & Code Comment Fact-Check Audit

Full codebase sweep to verify all claims in docs and source comments against the actual implementation. Do NOT do this during an active feature sprint — schedule as a standalone pass.

Checklist: