Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .ai-context/ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Architecture

Each public module is one sourceable file under `lib/bash/<module>/lib_<module>.sh`.
`std` provides initialization, logging, checked commands, imports, filesystem
helpers, and cleanup registration. `arg`, `str`, `list`, `file`, `git`, and `gh`
add composable utilities. `cli` declares command models; `app` supplies typed
configuration and application lifecycle policy. `process` offers preview
supervision primitives rather than a second stable runner API.

Sourcing stdlib is passive. Standalone consumers initialize through `base_init`;
`bin/base-bash` preloads stdlib, initializes once, sources the application, and
calls its `main`. Package-relative imports use `base_std_import` or the launcher's
import helper. Public functions use `base_<module>_...`; framework-owned state

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor inaccuracy in a blanket naming-convention claim: "Public functions use base_<module>_..." is not 100% true — lib/bash/std/lib_std.sh exports base_init and base_require_version as public entry points, neither of which follows the module-prefixed base_std_... pattern. Spot-checking the other modules (arg/str/list/file/git/gh/cli/app/process), std is the only one with exceptions. Low severity since these are well-known top-level bootstrap functions documented elsewhere (README.md), but the blanket claim as written is technically inaccurate and could mislead someone writing new public API against this doc's stated convention.

uses `BASE_BASH_LIBS_...`. Applications retain ownership of their command and
configuration semantics.

Keep existing single-file library boundaries. Production libraries use explicit
status checks rather than `set -e`, `set -u`, or `pipefail`. Logs belong on stderr;
stdout remains available for command data. Release bundles, API checks, and
consumer fixtures establish compatibility independently of any one application.

Sources: [module map](../lib/bash/README.md), [stdlib contract](../lib/bash/std/README.md),
[standards](../STANDARDS.md), and [launcher](../bin/base-bash).
11 changes: 11 additions & 0 deletions .ai-context/INDEX.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# base-bash-libs AI context index

Read in this order:

1. [Project](PROJECT.md): purpose, audience, scope, and boundaries.
2. [Architecture](ARCHITECTURE.md): components, contracts, and source map.
3. [Workflows](WORKFLOWS.md): setup, validation, and contribution practices.
4. [Maintenance](README.md): sources, update rules, and export behavior.

The pack is curated orientation. Canonical repository sources linked from each
page take precedence when exact implementation or policy details matter.
21 changes: 21 additions & 0 deletions .ai-context/PROJECT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Base Bash

`base-bash-libs` is an independently consumable Bash application framework and
standard library. It provides checked execution, logging, cleanup, structured
CLIs, typed configuration, and reusable shell helpers. Its consumers include
Base, standalone scripts, and the separate Beacon reference application.

Use it where Bash is an intentional runtime constraint and shared application
infrastructure is useful. It does not require the Base workspace runtime and
does not own an application's domain policy. Homebrew installation, vendored
release bundles, source checkouts, and submodules are supported consumption paths.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inaccurate conflation of consumption paths: "Homebrew installation, vendored release bundles, source checkouts, and submodules are supported consumption paths" merges two distinct, separately-documented things into a nonexistent hybrid category. README.md's real categories are Homebrew / Source Checkout (git checkout, tarball extract, or copied tree) / Vendored or Submodule Layout (placement pattern, covers both vendored copies and git submodules) — plus an independently-documented standalone release-archive download path (README.md:294, "Pinned checkout, archive, Homebrew, vendored, and standalone consumption..."). "Vendored release bundles" names neither the real "vendored" placement pattern nor the real "release archive" download path accurately, and omits the standalone archive-download path entirely. A reader could wrongly conclude there's no independent "download the verified tarball" consumption path, or misunderstand what "vendoring" means in this repo (placement, not bundling a release archive).

The documented minimum is Bash 4.2.53; macOS system Bash is insufficient.

The public API manifest and versioning policy define stability. The `process`
module is preview functionality; do not infer stable status merely because it
ships in a release. Use VERSION and immutable release evidence for exact package
identity instead of treating this summary as a current-release registry.

Sources: [README](../README.md), [API contract](../docs/v2-api-contract.md),
[API manifest](../base_api_manifest.yaml), and
[support matrix](../docs/support-matrix.md).
27 changes: 27 additions & 0 deletions .ai-context/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# AI context for base-bash-libs

This directory is the repository's curated orientation for AI-assisted work and
portable export. It summarizes verified repository behavior; it is not generated
runtime evidence or an authoritative release/status registry. Start with
[INDEX.md](INDEX.md).

Keep purpose, architecture, commands, and workflows aligned with code and

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy-paste residue referencing a nonexistent category: "Keep purpose, architecture, commands, and workflows aligned with code and canonical documentation" lists "commands" as one of four things to keep aligned, and CONTRIBUTING.md:128 (added in the same PR) repeats "architecture, commands, or contributor workflows." But this pack's own INDEX.md only enumerates PROJECT (purpose) / ARCHITECTURE / WORKFLOWS / README (maintenance) — there is no COMMANDS.md page here, unlike base's own .ai-context pack (which this was clearly modeled on and which does have a COMMANDS.md for its command surface). A maintainer told to "keep commands aligned" has no artifact to update, making the instruction ambiguous/unfulfillable as written.

canonical documentation. Update the affected pages in the same meaningful PR;
for typo-only or internal changes with no contract impact, record no context
impact in the PR. Resolve disagreements by correcting this pack from its sources.
Do not copy credentials, local databases, private machine paths, personal records,

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cross-repo duplication, different wording: this Safety text ("Do not copy credentials, local databases, private machine paths, personal records, or transient logs") restates base's own .ai-context/README.md Safety section ("Do not put secrets, API keys, tokens, private local paths, private customer details, or personal notes") — same policy, independently hand-authored in different words in a second repo. basefoundry-dot-github has no shared .ai-context template (only LICENSE/README/profile), so this is a second hand-copied instance rather than a single source of truth. A future policy tightening (e.g. "no screenshots" or a new excluded-data category) must be hand-propagated to every repo's copy and will silently drift, exactly as the two independently-worded lists already have.

or transient logs into it. Link to evidence rather than copying runtime data.

From this checkout, with Base available:

```bash
basectl export-context --list-files
basectl export-context --print
```

Markdown exports combine Markdown files in INDEX order, then append unlisted
files deterministically. Links outside this directory are source references;
the exporter does not inline their targets. Keep core explanations self-contained.
Use real regular files, not symlinks. Store generated bundles outside the project
and keep generation timestamps out of source pages so unchanged exports remain
byte-identical. This pack is picked up automatically by workspace export jobs.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unsupported/false claim: "This pack is picked up automatically by workspace export jobs." I grepped the entire base ecosystem (base, base-cli, base-demo, base-bash-libs, base-cli-demo, base-bash-libs-demo, base-platform-tools, basefoundry-dot-github) for any CI workflow, cron, or batch job that runs basectl export-context automatically, and found none — it's a manual, single-project, on-demand command (no --all/batch mode exists in cli/python/base_export_context/engine.py). base's own .ai-context/README.md makes no such automatic-pickup claim. A contributor reading this line could reasonably skip manually running export-context after editing the pack, believing some job keeps it in sync — nothing does, so the pack can silently go stale with no detection.

27 changes: 27 additions & 0 deletions .ai-context/WORKFLOWS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Workflows

Start with the [v2 quickstart](../docs/v2/quickstart.md) and a verified immutable
release when building a consumer. `base-bash check --project .` inspects a
consumer without changing it. Library development uses the repository checks:

```bash
./tests/validate.sh
./tests/lint-warnings.sh
git diff --check
```

Focused BATS tests accompany behavior changes. The complete validator also
covers API/namespace contracts, release artifacts, consumer examples, and
compatibility. Use supported Bash and the documented development dependencies;
run timeout/process tests with non-terminal stdin.

Tracked work starts from an issue and a dedicated canonical worktree. Move its

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Restates rather than links: "Tracked work starts from an issue and a dedicated canonical worktree. Move its Project item to In Progress before implementation and In Review when the PR opens... Ordinary PRs do not change VERSION. Releases must enter through scripts/release..." restates substance already fully stated in AGENTS.md's "Release Work" section and CONTRIBUTING.md's Project/worktree/good-first-issue workflow steps, rather than only linking to them (the "Sources" line at the bottom already cites both). A future change to the release guard or the Project-status workflow now needs updates in three places (AGENTS.md, CONTRIBUTING.md, and this file) to stay consistent, and a maintainer updating only the canonical doc could leave this summary stale without any signal.

Project item to In Progress before implementation and In Review when the PR opens.
Leave contributor-reserved good-first-issue work to its intended audience unless
explicitly selected. Ordinary PRs do not change VERSION. Releases must enter
through `scripts/release` and follow the repository's release process, including
artifact and downstream evidence.

Sources: [contribution guide](../CONTRIBUTING.md), [agent guidance](../AGENTS.md),
[release process](../docs/release-process.md), and
[versioning policy](../docs/versioning-policy.md).
14 changes: 14 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,17 @@ before dispatching again; rotating a valid token is unnecessary. See the

Run the offline workflow regression tests with
`python3 tests/project-intake-test.py`; they also run in `./tests/validate.sh`.

## AI Context Maintenance

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same-PR duplication: this new "AI Context Maintenance" section restates .ai-context/README.md's own maintenance text, added in the same PR — both state update-on-meaningful-change, the typo-only exemption, "state impact in PR," canonical-docs-win, no-secrets, and the basectl export-context validation commands. Two new copies of one policy are created together in this diff; CONTRIBUTING.md should link to .ai-context/README.md rather than restate its substance, or a future policy tightening (e.g. a new no-secrets exception) only gets applied to one copy and the two silently drift from each other starting from this PR's own merge.


Start AI-assisted orientation with [.ai-context/INDEX.md](.ai-context/INDEX.md).
Maintain these curated summaries alongside meaningful changes to product scope,
architecture, commands, or contributor workflows. Canonical docs and code remain
the source of truth; update the pack when they disagree. State context impact in

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Toothless instruction: "State context impact in the PR, including a reason when no update is needed" reads as a sibling to the existing required Demo/Docs/API/CI Impact sections, but isn't backed by the same machinery. base_manifest.yaml's github.pr.required_sections maps docs/**→Docs Impact, lib/bash/**→API Impact, .github/**→CI Impact, and label security→Security Notes — there is no rule for .ai-context/**, and .github/pull_request_template.md has no "Context Impact" heading at all. A contributor following this instruction has no designated place to put the statement and nothing enforces or even prompts for it, unlike every other impact section CONTRIBUTING.md/AGENTS.md reference. Concrete failure: a contributor omits the statement entirely (or writes it somewhere ad hoc) while believing it's equally enforced — nothing surfaces the omission.

the PR, including a reason when no update is needed. Typo-only and internal changes
without behavioral or architectural impact usually need no context update.

Validate changes with `basectl export-context --list-files` and

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No mechanical enforcement (altitude): this instructs contributors to manually run basectl export-context --list-files/--print and git diff --check "from the checkout", but nothing in CI actually runs them. tests/validate.sh (the repo's CI entrypoint) never references .ai-context or export-context, and its required_files existence-check array does not list any of the 5 new .ai-context/*.md files either — so the pack can be deleted, left stale, or develop broken relative links and CI stays green forever. This is the same honor-system-only gap the related base project's 2026-10-18 docs-drift audit flagged (proposing a PR Impact-block + docs-impact CI lane, not yet implemented) — this PR adds more manual-only documentation-sync surface rather than wiring one of its own already-documented commands (e.g. basectl export-context --list-files, which fails non-zero on missing/broken/symlinked files) into tests/validate.sh.

`basectl export-context --print` from the checkout, plus `git diff --check`.
Keep the pack self-contained enough for offline reading, free of secrets and
private runtime data, and independent of generated timestamps or export bundles.
20 changes: 9 additions & 11 deletions lib/bash/std/tests/lib_std.bats
Original file line number Diff line number Diff line change
Expand Up @@ -3212,7 +3212,7 @@ EOF

@test "base_std_run reports external timeout-clock failures as infrastructure without retrying" {
local fake_bin="$TEST_TMPDIR/broken-timeout-clock"
local counter_file="$TEST_TMPDIR/broken-timeout-counter"
local clock_count_file="$TEST_TMPDIR/broken-timeout-clock-count"
local stderr_file="$TEST_TMPDIR/broken-timeout.err"
local rc

Expand All @@ -3223,28 +3223,26 @@ if [[ "${1-}" == --version ]]; then
printf 'timeout (GNU coreutils) 9.5\n'
exit 0
fi
exit 7
EOF
create_script "$TEST_TMPDIR/should-not-run.sh" <<'EOF'
#!/usr/bin/env bash
count=0
[[ -f "$1" ]] && count="$(cat "$1")"
printf '%s\n' "$((count + 1))" > "$1"
/bin/sleep 3
[[ -f "$BASE_TEST_TIMEOUT_CLOCK_COUNT" ]] && count="$(< "$BASE_TEST_TIMEOUT_CLOCK_COUNT")"
printf '%s\n' "$((count + 1))" > "$BASE_TEST_TIMEOUT_CLOCK_COUNT"
exit 7
EOF
ln -s "$(command -v mktemp)" "$fake_bin/mktemp"
ln -s "$(command -v rm)" "$fake_bin/rm"

if PATH="$fake_bin" base_std_run --no-exit --max-attempts 3 --timeout 1 \
/bin/bash "$TEST_TMPDIR/should-not-run.sh" "$counter_file" \
# A broken clock can stop the child before its first instruction. Count
# clock executions to prove no retry without depending on child scheduling.
if BASE_TEST_TIMEOUT_CLOCK_COUNT="$clock_count_file" PATH="$fake_bin" \
base_std_run --no-exit --max-attempts 3 --timeout 1 /bin/sleep 3 \
2>"$stderr_file"; then
rc=0
else
rc=$?
fi

[ "$rc" -eq 125 ]
[ "$(cat "$counter_file")" = "1" ]
[ "$(< "$clock_count_file")" = "1" ]
[[ "$(cat "$stderr_file")" == *"could not be supervised safely"* ]]
[[ "$(cat "$stderr_file")" != *"attempt 1 of 3; retrying"* ]]
}
Expand Down
Loading