Skip to content
Merged
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,6 @@ todos/

# test artefacts
/tmp/

# fixture files that intentionally resemble secrets/env files
!test/fixtures/golden-repo/.env.example
21 changes: 21 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,27 @@ bats test/*.bats # all tests
bats test/smoosh_args.bats # specific file
```

## Golden File Tests

The golden file suite (`test/smoosh_golden.bats`) verifies that smoosh output
is byte-for-byte correct across all modes, formats, and feature combinations.

If you intentionally change smoosh's output format (for example, adding a new
header field or changing the section separator), regenerate the expected files:

```bash
UPDATE_GOLDEN=1 bats test/smoosh_golden.bats
```

Then review the diff to confirm the changes are intentional before committing:

```bash
git diff test/golden/
```

The golden files live in `test/golden/expected/`. Never edit them by hand —
always use `UPDATE_GOLDEN=1` to regenerate them from a passing smoosh run.

## Updating the Demos

The demos are recorded with [VHS](https://github.com/charmbracelet/vhs)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ smoosh counts words using `wc -w`, which splits on whitespace. Code files
with dense syntax (JSON, minified JS) count differently than prose.

**Is it overengineered for a shell script?**
Absolutely. 198 tests, 100% file inclusion verification, CDATA escaping for
Absolutely. 228 tests, 100% file inclusion verification, CDATA escaping for
XML output, and a box-drawing letter logo. But your codebase deserves to be
smooshed properly.

Expand Down
14 changes: 10 additions & 4 deletions smoosh
Original file line number Diff line number Diff line change
Expand Up @@ -898,8 +898,13 @@ write_chunk_footer() {

# add_line_numbers FILE
# Print file content to stdout with right-aligned line numbers.
# Captures via $() to strip trailing newlines — GNU nl adds one for files
# that lack it; BSD nl preserves the original. printf '%s' ensures consistent
# output on both, and the caller's printf '\n' adds exactly one.
add_line_numbers() {
nl -ba -nrz -w4 -s' | ' -- "${1}" 2>/dev/null || cat -- "${1}"
local numbered
numbered="$(nl -ba -nrz -w4 -s' | ' -- "${1}" 2>/dev/null || cat -- "${1}")"
printf '%s' "${numbered}"
}

# write_file_entry FD REL_PATH
Expand Down Expand Up @@ -929,9 +934,10 @@ write_file_entry() {
add_line_numbers "${abs_path}" |
sed 's/]]>/]]]]><![CDATA[>/g' >&"${fd}"
else
# Group sed+fallback so only one redirect is applied to the combined stdout.
{ sed 's/]]>/]]]]><![CDATA[>/g' -- "${abs_path}" 2>/dev/null ||
cat -- "${abs_path}"; } >&"${fd}"
# Pipe through sed rather than sed -- file: BSD sed does not support --
# as end-of-options (it treats it as a literal filename, causing doubled
# output via the || fallback).
cat -- "${abs_path}" | sed 's/]]>/]]]]><![CDATA[>/g' >&"${fd}"
fi
elif [[ "${LINE_NUMBERS}" == "true" ]]; then
add_line_numbers "${abs_path}" >&"${fd}"
Expand Down
265 changes: 265 additions & 0 deletions test/ACCEPTANCE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,265 @@
# smoosh Acceptance Test Runbook

This document describes the manual acceptance tests for smoosh. Run these
before any major release or when the automated tests are insufficient to
verify a change — for example, when interactive mode, network behaviour, or
AI tool integration is involved.

All automated tests can be run with `bats test/*.bats`. The scenarios below
cover what cannot be automated: interactive TTY behaviour and end-to-end
upload flows with real AI tools.

---

## Setup

Install smoosh or build from source:

brew install K1-R1/tap/smoosh # installed release
# or
./smoosh --version # local dev build (run from repo root)

Pick a real git repository to test against — the smoosh repo itself works
well. All examples below use `.` for the current directory.

---

## 1. Interactive Mode

smoosh opens an interactive guided experience when called with no arguments
in a real terminal (TTY).

**Steps:**

1. Open a terminal (not inside a script or pipe).
2. Change into any git repository: `cd /path/to/some/repo`
3. Run `smoosh` with no arguments.

**Expected behaviour:**

- The logo and tagline appear.
- smoosh scans the repo and shows a summary table: docs, code, config, and
other file counts with example extensions.
- A prompt asks which mode to use (`docs`, `code`, `all`, or `q` to quit).
- After selecting a mode, smoosh processes and writes output to `_smooshes/`.
- A summary table shows file count, word count, token estimate, and chunk count.

**Pass criteria:**

- [ ] Interactive prompt appears (not skipped)
- [ ] Repo scan table shows plausible file counts
- [ ] Selecting `docs` produces `.md` output files
- [ ] Output lands in `_smooshes/`
- [ ] No error messages or stack traces

---

## 2. Remote Repository

smoosh can clone and process a remote repo in a single command.

**Steps:**

smoosh https://github.com/K1-R1/smoosh

**Expected behaviour:**

- smoosh clones the repo to a temp directory.
- Processes it in docs mode (default).
- Writes output to `_smooshes/` in the current directory (not inside the
clone).
- Cleans up the temp clone on exit.

**Pass criteria:**

- [ ] Clone succeeds (no "Remote clone failed" error)
- [ ] Output files appear in `_smooshes/` of the working directory
- [ ] Output contains smoosh's own `README.md` content
- [ ] Temp clone is removed after the run

---

## 3. NotebookLM Upload

Verify that smoosh output can be uploaded to NotebookLM and queried.

**Steps:**

1. Run smoosh on a real codebase:

cd /path/to/some/repo
smoosh --code

2. Go to [notebooklm.google.com](https://notebooklm.google.com) and create
a new notebook.
3. Click **Add source → Upload file**.
4. Upload each `.md` file from `_smooshes/`.
5. Wait for processing (usually 30–60 seconds).
6. Ask a question that can only be answered with the uploaded content, for
example:
- "What functions are defined in this codebase?"
- "What does the main entry point do?"
- "List all the files included in this upload."

**Pass criteria:**

- [ ] Upload succeeds (no error from NotebookLM)
- [ ] NotebookLM answers questions using specific file content (cites sources)
- [ ] Answer is not a hallucination (verifiable against the actual code)
- [ ] Word count per file is within NotebookLM's 500,000-word limit per source

**NotebookLM plan limits (early 2026):**

| Plan | Max sources | Max words/source |
|-------|-------------|------------------|
| Free | 50 | 500,000 |
| Plus | 300 | 500,000 |
| Ultra | 600 | 500,000 |

---

## 4. Claude Projects Upload

Verify that smoosh output can be added to a Claude Project and queried.

**Steps:**

1. Run smoosh:

smoosh --code

2. Go to [claude.ai](https://claude.ai) and open or create a Project.
3. Open the project knowledge panel.
4. Upload the files from `_smooshes/`.
5. Start a conversation and ask a code-specific question, for example:
- "What language is the main entry point written in?"
- "Are there any tests in this codebase?"

**Pass criteria:**

- [ ] Upload succeeds
- [ ] Claude answers using specific content from the uploaded files
- [ ] Claude does not claim it cannot access the files

---

## 5. ChatGPT Upload

Verify that smoosh output can be attached to a ChatGPT conversation.

**Steps:**

1. Run smoosh:

smoosh --code

2. Open [chatgpt.com](https://chatgpt.com) and start a new conversation.
3. Attach the files from `_smooshes/` using the paperclip icon.
4. Ask a specific question about the uploaded codebase.

**Pass criteria:**

- [ ] Files attach without errors
- [ ] ChatGPT answers using content from the uploaded files
- [ ] For repos with multiple chunks: all chunks can be attached

---

## 6. Secrets Detection

Verify that secrets are flagged and excluded from output.

**Steps:**

1. Create a temporary test repo:

mkdir /tmp/secrets-test && cd /tmp/secrets-test
git init && git config user.email "t@t.com" && git config user.name "T"
echo '# Docs' > README.md
echo 'AWS_ACCESS_KEY_ID = "AKIAIOSFODNN7EXAMPLE"' > creds.py
git add -A && git commit -m "init"

2. Run smoosh:

smoosh --code .

**Expected behaviour:**

- smoosh prints a secrets warning mentioning `creds.py`.
- The warning includes a disclaimer ("basic pattern matching only").
- `creds.py` does not appear in the output files.
- `README.md` appears in the output files.
- Exit code is 0 (secrets detected is a warning, not a failure).

**Pass criteria:**

- [ ] Warning appears on stderr
- [ ] `creds.py` content is absent from `_smooshes/` output
- [ ] `README.md` content is present in `_smooshes/` output
- [ ] Exit code is 0

---

## 7. Agent / CI Usage

Verify that smoosh works in a headless, non-interactive environment.

**Steps:**

smoosh --code --no-interactive --json --quiet . 2>/dev/null

**Expected behaviour:** an error — `--json` and `--quiet` cannot be combined.

Then:

smoosh --code --no-interactive --json . 2>/dev/null | jq .

**Expected behaviour:**

- Valid JSON is printed to stdout.
- JSON includes `repo`, `files_processed`, `total_words`, `chunks`, and
`exit_code` fields.
- Exit code is 0.

**Pass criteria:**

- [ ] `--json` and `--quiet` together print an error and exit 1
- [ ] `--json` alone produces valid, parseable JSON
- [ ] `exit_code` in JSON matches the actual process exit code

---

## 8. Regression: Golden File Tests

The automated golden file tests (run as part of `bats test/*.bats`) verify
that smoosh output is byte-for-byte identical to the checked-in expected
files. Run them to confirm no regressions:

bats test/smoosh_golden.bats

All 30 tests should pass.

If you intentionally change smoosh's output format (for example, adding a
new header field), regenerate the golden files:

UPDATE_GOLDEN=1 bats test/smoosh_golden.bats

Then review `git diff test/golden/` to confirm the changes are intentional
before committing.

---

## Completing a Release Acceptance Run

Tick every checkbox above, then record the result:

| Scenario | Result | Notes |
|----------|--------|-------|
| 1. Interactive mode | Pass / Fail | |
| 2. Remote repository | Pass / Fail | |
| 3. NotebookLM upload | Pass / Fail | |
| 4. Claude Projects upload | Pass / Fail | |
| 5. ChatGPT upload | Pass / Fail | |
| 6. Secrets detection | Pass / Fail | |
| 7. Agent / CI usage | Pass / Fail | |
| 8. Golden file tests | Pass / Fail | |
3 changes: 3 additions & 0 deletions test/fixtures/golden-repo/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
DATABASE_URL=postgres://localhost:5432/mydb
SECRET_KEY=your-secret-key-here
DEBUG=false
8 changes: 8 additions & 0 deletions test/fixtures/golden-repo/.github/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: echo "Golden fixture CI workflow"
7 changes: 7 additions & 0 deletions test/fixtures/golden-repo/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.PHONY: all clean

all:
@echo "Golden fixture Makefile"

clean:
@echo "Nothing to clean"
4 changes: 4 additions & 0 deletions test/fixtures/golden-repo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Golden Repo

This is the readme for the golden test fixture repository.
It contains files that exercise every smoosh capability.
11 changes: 11 additions & 0 deletions test/fixtures/golden-repo/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
"""Golden fixture Python module."""


def greet(name):
"""Return a greeting string."""
return "Hello, " + name


def add(a, b):
"""Return the sum of two numbers."""
return a + b
4 changes: 4 additions & 0 deletions test/fixtures/golden-repo/aws-creds.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Golden fixture secrets file.
# This file contains a fake AWS key for secrets detection testing.
AWS_ACCESS_KEY_ID = "AKIAIOSFODNN7EXAMPLE"
AWS_SECRET_ACCESS_KEY = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
4 changes: 4 additions & 0 deletions test/fixtures/golden-repo/cdata-break.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# CDATA Edge Case

This file contains the sequence ]]> which breaks CDATA sections.
The sequence ]]> must be escaped to ]]]]><\![CDATA[> in XML output.
4 changes: 4 additions & 0 deletions test/fixtures/golden-repo/deep/nested/path/doc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Deeply Nested Document

This document lives at a deeply nested path to test path handling.
smoosh should include this file with its full relative path preserved.
Empty file.
5 changes: 5 additions & 0 deletions test/fixtures/golden-repo/guide.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
User Guide
==========

This guide covers the basic usage of the golden fixture project.
See the readme for an overview of the project structure.
Loading