Skip to content

feat(assert): name the problem instead of printing exit code 127 - #991

Merged
Chemaclass merged 1 commit into
mainfrom
feat/982-command-not-found-message
Aug 8, 2026
Merged

feat(assert): name the problem instead of printing exit code 127#991
Chemaclass merged 1 commit into
mainfrom
feat/982-command-not-found-message

Conversation

@Chemaclass

Copy link
Copy Markdown
Member

🤔 Background

Related #982

assert_true / assert_false ran their argument as a command and reported a bare number:

Expected 'command or function with zero exit code'
but got 'exit code: 127'

127 is the shell's not-found code, 126 its not-executable code. Both are now named, with the argument that produced them.

The motivating case isn't exotic — assert_true "[ -d /tmp ]" is valid bash that works in an if, and produces exactly this, because the argument is run as a command word rather than evaluated. Someone seeing exit code: 127 has no reason to suspect their argument's shape and will check /tmp first.

🐛 assert_false had the worse half — a false pass

It failed only on exit code 0, so 127 counted as "non-zero, therefore false":

assert_false "definitley_not_a_command"# passed

A typo in the command name satisfied the assertion while running nothing. 126 and 127 now fail both assertions, because they mean the command never ran — which is neither true nor false.

⚠️ Why the wording avoids "command not found"

runner/diagnostics.sh classifies a test as a runtime error by scanning its output for that exact string. The obvious phrasing made every one of these failures report as both FailedandError for a single cause.

Found by writing it the obvious way first and watching the duplicate appear. The underlying fragility — the framework detecting shell errors by string-matching its own output stream — is worth its own issue and I'll file it.

📖 Docs

The bracket trap is described without using brackets: bashunit doc strips them while rendering, so the first draft came out as assert_true " -d /tmp " in the CLI, which teaches the wrong lesson. Snapshot regenerated.

✅ Verification

3 new tests, all confirmed RED first. make sa · make lint · bash build.sh bin -v✅ Build verified ✅ · fork budget unchanged · 1697 sequential / 1656 parallel-simple-strict.

Closes#982.
assert_true and assert_false ran their argument as a command and reported a bare
number when it failed:
Expected 'command or function with zero exit code'
but got 'exit code: 127'
127 is the shell's not-found code and 126 its not-executable code. Both are now
named, with the argument that produced them, so the failure points at its cause.
The case that motivated this is not an exotic one. `assert_true "[ -d /tmp ]"`
is valid bash that works in an `if`, and it produces exactly this failure,
because the argument is run as a command word rather than evaluated. A reader
seeing `exit code: 127` has no reason to suspect the shape of their argument and
will go and look at /tmp first.
assert_false had the worse half of the same problem. It failed only on exit code
0, so 127 counted as "non-zero, therefore false" and a typo in the command name
satisfied the assertion:
assert_false "definitley_not_a_command" # passed
That is a false pass -- the assertion reported success while running nothing.
126 and 127 now fail both assertions, because they mean the command never ran,
which is neither true nor false.
The wording avoids the literal phrase "command not found" on purpose.
runner/diagnostics.sh classifies a test as a runtime error by scanning its output
for that exact string, so the obvious phrasing made every one of these failures
report as both Failed and Error for a single cause. Found by writing it the
obvious way first and watching the duplicate appear. The underlying fragility --
the framework detecting shell errors by string-matching its own output stream --
is filed separately.
The docs describe the bracket trap without using brackets: `bashunit doc` strips
them while rendering, so the first draft rendered as `assert_true " -d /tmp "` in
the CLI, which teaches the wrong lesson. Snapshot regenerated.
1697 sequential / 1656 parallel; baseline + 3, all RED first.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancementNew feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Chemaclass
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
feat(assert): name the problem instead of printing exit code 127 by Chemaclass · Pull Request #991 · TypedDevs/bashunit · GitHub
Skip to content

feat(assert): name the problem instead of printing exit code 127 - #991

Merged
Chemaclass merged 1 commit into
mainfrom
feat/982-command-not-found-message
Aug 8, 2026
Merged

feat(assert): name the problem instead of printing exit code 127#991
Chemaclass merged 1 commit into
mainfrom
feat/982-command-not-found-message

Conversation

@Chemaclass

Copy link
Copy Markdown
Member

🤔 Background

Related #982

assert_true / assert_false ran their argument as a command and reported a bare number:

Expected 'command or function with zero exit code'
but got 'exit code: 127'

127 is the shell's not-found code, 126 its not-executable code. Both are now named, with the argument that produced them.

The motivating case isn't exotic — assert_true "[ -d /tmp ]" is valid bash that works in an if, and produces exactly this, because the argument is run as a command word rather than evaluated. Someone seeing exit code: 127 has no reason to suspect their argument's shape and will check /tmp first.

🐛 assert_false had the worse half — a false pass

It failed only on exit code 0, so 127 counted as "non-zero, therefore false":

assert_false "definitley_not_a_command"# passed

A typo in the command name satisfied the assertion while running nothing. 126 and 127 now fail both assertions, because they mean the command never ran — which is neither true nor false.

⚠️ Why the wording avoids "command not found"

runner/diagnostics.sh classifies a test as a runtime error by scanning its output for that exact string. The obvious phrasing made every one of these failures report as both FailedandError for a single cause.

Found by writing it the obvious way first and watching the duplicate appear. The underlying fragility — the framework detecting shell errors by string-matching its own output stream — is worth its own issue and I'll file it.

📖 Docs

The bracket trap is described without using brackets: bashunit doc strips them while rendering, so the first draft came out as assert_true " -d /tmp " in the CLI, which teaches the wrong lesson. Snapshot regenerated.

✅ Verification

3 new tests, all confirmed RED first. make sa · make lint · bash build.sh bin -v✅ Build verified ✅ · fork budget unchanged · 1697 sequential / 1656 parallel-simple-strict.

Closes#982.
assert_true and assert_false ran their argument as a command and reported a bare
number when it failed:
Expected 'command or function with zero exit code'
but got 'exit code: 127'
127 is the shell's not-found code and 126 its not-executable code. Both are now
named, with the argument that produced them, so the failure points at its cause.
The case that motivated this is not an exotic one. `assert_true "[ -d /tmp ]"`
is valid bash that works in an `if`, and it produces exactly this failure,
because the argument is run as a command word rather than evaluated. A reader
seeing `exit code: 127` has no reason to suspect the shape of their argument and
will go and look at /tmp first.
assert_false had the worse half of the same problem. It failed only on exit code
0, so 127 counted as "non-zero, therefore false" and a typo in the command name
satisfied the assertion:
assert_false "definitley_not_a_command" # passed
That is a false pass -- the assertion reported success while running nothing.
126 and 127 now fail both assertions, because they mean the command never ran,
which is neither true nor false.
The wording avoids the literal phrase "command not found" on purpose.
runner/diagnostics.sh classifies a test as a runtime error by scanning its output
for that exact string, so the obvious phrasing made every one of these failures
report as both Failed and Error for a single cause. Found by writing it the
obvious way first and watching the duplicate appear. The underlying fragility --
the framework detecting shell errors by string-matching its own output stream --
is filed separately.
The docs describe the bracket trap without using brackets: `bashunit doc` strips
them while rendering, so the first draft rendered as `assert_true " -d /tmp "` in
the CLI, which teaches the wrong lesson. Snapshot regenerated.
1697 sequential / 1656 parallel; baseline + 3, all RED first.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancementNew feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Chemaclass
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat(assert): name the problem instead of printing exit code 127 by Chemaclass · Pull Request #991 · TypedDevs/bashunit · GitHub
Skip to content

feat(assert): name the problem instead of printing exit code 127 - #991

Merged
Chemaclass merged 1 commit into
mainfrom
feat/982-command-not-found-message
Aug 8, 2026
Merged

feat(assert): name the problem instead of printing exit code 127#991
Chemaclass merged 1 commit into
mainfrom
feat/982-command-not-found-message

Conversation

@Chemaclass

Copy link
Copy Markdown
Member

🤔 Background

Related #982

assert_true / assert_false ran their argument as a command and reported a bare number:

Expected 'command or function with zero exit code'
but got 'exit code: 127'

127 is the shell's not-found code, 126 its not-executable code. Both are now named, with the argument that produced them.

The motivating case isn't exotic — assert_true "[ -d /tmp ]" is valid bash that works in an if, and produces exactly this, because the argument is run as a command word rather than evaluated. Someone seeing exit code: 127 has no reason to suspect their argument's shape and will check /tmp first.

🐛 assert_false had the worse half — a false pass

It failed only on exit code 0, so 127 counted as "non-zero, therefore false":

assert_false "definitley_not_a_command"# passed

A typo in the command name satisfied the assertion while running nothing. 126 and 127 now fail both assertions, because they mean the command never ran — which is neither true nor false.

⚠️ Why the wording avoids "command not found"

runner/diagnostics.sh classifies a test as a runtime error by scanning its output for that exact string. The obvious phrasing made every one of these failures report as both FailedandError for a single cause.

Found by writing it the obvious way first and watching the duplicate appear. The underlying fragility — the framework detecting shell errors by string-matching its own output stream — is worth its own issue and I'll file it.

📖 Docs

The bracket trap is described without using brackets: bashunit doc strips them while rendering, so the first draft came out as assert_true " -d /tmp " in the CLI, which teaches the wrong lesson. Snapshot regenerated.

✅ Verification

3 new tests, all confirmed RED first. make sa · make lint · bash build.sh bin -v✅ Build verified ✅ · fork budget unchanged · 1697 sequential / 1656 parallel-simple-strict.

Closes#982.
assert_true and assert_false ran their argument as a command and reported a bare
number when it failed:
Expected 'command or function with zero exit code'
but got 'exit code: 127'
127 is the shell's not-found code and 126 its not-executable code. Both are now
named, with the argument that produced them, so the failure points at its cause.
The case that motivated this is not an exotic one. `assert_true "[ -d /tmp ]"`
is valid bash that works in an `if`, and it produces exactly this failure,
because the argument is run as a command word rather than evaluated. A reader
seeing `exit code: 127` has no reason to suspect the shape of their argument and
will go and look at /tmp first.
assert_false had the worse half of the same problem. It failed only on exit code
0, so 127 counted as "non-zero, therefore false" and a typo in the command name
satisfied the assertion:
assert_false "definitley_not_a_command" # passed
That is a false pass -- the assertion reported success while running nothing.
126 and 127 now fail both assertions, because they mean the command never ran,
which is neither true nor false.
The wording avoids the literal phrase "command not found" on purpose.
runner/diagnostics.sh classifies a test as a runtime error by scanning its output
for that exact string, so the obvious phrasing made every one of these failures
report as both Failed and Error for a single cause. Found by writing it the
obvious way first and watching the duplicate appear. The underlying fragility --
the framework detecting shell errors by string-matching its own output stream --
is filed separately.
The docs describe the bracket trap without using brackets: `bashunit doc` strips
them while rendering, so the first draft rendered as `assert_true " -d /tmp "` in
the CLI, which teaches the wrong lesson. Snapshot regenerated.
1697 sequential / 1656 parallel; baseline + 3, all RED first.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancementNew feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Chemaclass
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat(assert): name the problem instead of printing exit code 127 by Chemaclass · Pull Request #991 · TypedDevs/bashunit · GitHub
Skip to content

feat(assert): name the problem instead of printing exit code 127 - #991

Merged
Chemaclass merged 1 commit into
mainfrom
feat/982-command-not-found-message
Aug 8, 2026
Merged

feat(assert): name the problem instead of printing exit code 127#991
Chemaclass merged 1 commit into
mainfrom
feat/982-command-not-found-message

Conversation

@Chemaclass

Copy link
Copy Markdown
Member

🤔 Background

Related #982

assert_true / assert_false ran their argument as a command and reported a bare number:

Expected 'command or function with zero exit code'
but got 'exit code: 127'

127 is the shell's not-found code, 126 its not-executable code. Both are now named, with the argument that produced them.

The motivating case isn't exotic — assert_true "[ -d /tmp ]" is valid bash that works in an if, and produces exactly this, because the argument is run as a command word rather than evaluated. Someone seeing exit code: 127 has no reason to suspect their argument's shape and will check /tmp first.

🐛 assert_false had the worse half — a false pass

It failed only on exit code 0, so 127 counted as "non-zero, therefore false":

assert_false "definitley_not_a_command"# passed

A typo in the command name satisfied the assertion while running nothing. 126 and 127 now fail both assertions, because they mean the command never ran — which is neither true nor false.

⚠️ Why the wording avoids "command not found"

runner/diagnostics.sh classifies a test as a runtime error by scanning its output for that exact string. The obvious phrasing made every one of these failures report as both FailedandError for a single cause.

Found by writing it the obvious way first and watching the duplicate appear. The underlying fragility — the framework detecting shell errors by string-matching its own output stream — is worth its own issue and I'll file it.

📖 Docs

The bracket trap is described without using brackets: bashunit doc strips them while rendering, so the first draft came out as assert_true " -d /tmp " in the CLI, which teaches the wrong lesson. Snapshot regenerated.

✅ Verification

3 new tests, all confirmed RED first. make sa · make lint · bash build.sh bin -v✅ Build verified ✅ · fork budget unchanged · 1697 sequential / 1656 parallel-simple-strict.

Closes#982.
assert_true and assert_false ran their argument as a command and reported a bare
number when it failed:
Expected 'command or function with zero exit code'
but got 'exit code: 127'
127 is the shell's not-found code and 126 its not-executable code. Both are now
named, with the argument that produced them, so the failure points at its cause.
The case that motivated this is not an exotic one. `assert_true "[ -d /tmp ]"`
is valid bash that works in an `if`, and it produces exactly this failure,
because the argument is run as a command word rather than evaluated. A reader
seeing `exit code: 127` has no reason to suspect the shape of their argument and
will go and look at /tmp first.
assert_false had the worse half of the same problem. It failed only on exit code
0, so 127 counted as "non-zero, therefore false" and a typo in the command name
satisfied the assertion:
assert_false "definitley_not_a_command" # passed
That is a false pass -- the assertion reported success while running nothing.
126 and 127 now fail both assertions, because they mean the command never ran,
which is neither true nor false.
The wording avoids the literal phrase "command not found" on purpose.
runner/diagnostics.sh classifies a test as a runtime error by scanning its output
for that exact string, so the obvious phrasing made every one of these failures
report as both Failed and Error for a single cause. Found by writing it the
obvious way first and watching the duplicate appear. The underlying fragility --
the framework detecting shell errors by string-matching its own output stream --
is filed separately.
The docs describe the bracket trap without using brackets: `bashunit doc` strips
them while rendering, so the first draft rendered as `assert_true " -d /tmp "` in
the CLI, which teaches the wrong lesson. Snapshot regenerated.
1697 sequential / 1656 parallel; baseline + 3, all RED first.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancementNew feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Chemaclass
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' feat(assert): name the problem instead of printing exit code 127 by Chemaclass · Pull Request #991 · TypedDevs/bashunit · GitHub
Skip to content

feat(assert): name the problem instead of printing exit code 127 - #991

Merged
Chemaclass merged 1 commit into
mainfrom
feat/982-command-not-found-message
Aug 8, 2026
Merged

feat(assert): name the problem instead of printing exit code 127#991
Chemaclass merged 1 commit into
mainfrom
feat/982-command-not-found-message

Conversation

@Chemaclass

Copy link
Copy Markdown
Member

🤔 Background

Related #982

assert_true / assert_false ran their argument as a command and reported a bare number:

Expected 'command or function with zero exit code'
but got 'exit code: 127'

127 is the shell's not-found code, 126 its not-executable code. Both are now named, with the argument that produced them.

The motivating case isn't exotic — assert_true "[ -d /tmp ]" is valid bash that works in an if, and produces exactly this, because the argument is run as a command word rather than evaluated. Someone seeing exit code: 127 has no reason to suspect their argument's shape and will check /tmp first.

🐛 assert_false had the worse half — a false pass

It failed only on exit code 0, so 127 counted as "non-zero, therefore false":

assert_false "definitley_not_a_command"# passed

A typo in the command name satisfied the assertion while running nothing. 126 and 127 now fail both assertions, because they mean the command never ran — which is neither true nor false.

⚠️ Why the wording avoids "command not found"

runner/diagnostics.sh classifies a test as a runtime error by scanning its output for that exact string. The obvious phrasing made every one of these failures report as both FailedandError for a single cause.

Found by writing it the obvious way first and watching the duplicate appear. The underlying fragility — the framework detecting shell errors by string-matching its own output stream — is worth its own issue and I'll file it.

📖 Docs

The bracket trap is described without using brackets: bashunit doc strips them while rendering, so the first draft came out as assert_true " -d /tmp " in the CLI, which teaches the wrong lesson. Snapshot regenerated.

✅ Verification

3 new tests, all confirmed RED first. make sa · make lint · bash build.sh bin -v✅ Build verified ✅ · fork budget unchanged · 1697 sequential / 1656 parallel-simple-strict.

Closes#982.
assert_true and assert_false ran their argument as a command and reported a bare
number when it failed:
Expected 'command or function with zero exit code'
but got 'exit code: 127'
127 is the shell's not-found code and 126 its not-executable code. Both are now
named, with the argument that produced them, so the failure points at its cause.
The case that motivated this is not an exotic one. `assert_true "[ -d /tmp ]"`
is valid bash that works in an `if`, and it produces exactly this failure,
because the argument is run as a command word rather than evaluated. A reader
seeing `exit code: 127` has no reason to suspect the shape of their argument and
will go and look at /tmp first.
assert_false had the worse half of the same problem. It failed only on exit code
0, so 127 counted as "non-zero, therefore false" and a typo in the command name
satisfied the assertion:
assert_false "definitley_not_a_command" # passed
That is a false pass -- the assertion reported success while running nothing.
126 and 127 now fail both assertions, because they mean the command never ran,
which is neither true nor false.
The wording avoids the literal phrase "command not found" on purpose.
runner/diagnostics.sh classifies a test as a runtime error by scanning its output
for that exact string, so the obvious phrasing made every one of these failures
report as both Failed and Error for a single cause. Found by writing it the
obvious way first and watching the duplicate appear. The underlying fragility --
the framework detecting shell errors by string-matching its own output stream --
is filed separately.
The docs describe the bracket trap without using brackets: `bashunit doc` strips
them while rendering, so the first draft rendered as `assert_true " -d /tmp "` in
the CLI, which teaches the wrong lesson. Snapshot regenerated.
1697 sequential / 1656 parallel; baseline + 3, all RED first.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancementNew feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Chemaclass
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat(assert): name the problem instead of printing exit code 127 by Chemaclass · Pull Request #991 · TypedDevs/bashunit · GitHub
Skip to content

feat(assert): name the problem instead of printing exit code 127 - #991

Merged
Chemaclass merged 1 commit into
mainfrom
feat/982-command-not-found-message
Aug 8, 2026
Merged

feat(assert): name the problem instead of printing exit code 127#991
Chemaclass merged 1 commit into
mainfrom
feat/982-command-not-found-message

Conversation

@Chemaclass

Copy link
Copy Markdown
Member

🤔 Background

Related #982

assert_true / assert_false ran their argument as a command and reported a bare number:

Expected 'command or function with zero exit code'
but got 'exit code: 127'

127 is the shell's not-found code, 126 its not-executable code. Both are now named, with the argument that produced them.

The motivating case isn't exotic — assert_true "[ -d /tmp ]" is valid bash that works in an if, and produces exactly this, because the argument is run as a command word rather than evaluated. Someone seeing exit code: 127 has no reason to suspect their argument's shape and will check /tmp first.

🐛 assert_false had the worse half — a false pass

It failed only on exit code 0, so 127 counted as "non-zero, therefore false":

assert_false "definitley_not_a_command"# passed

A typo in the command name satisfied the assertion while running nothing. 126 and 127 now fail both assertions, because they mean the command never ran — which is neither true nor false.

⚠️ Why the wording avoids "command not found"

runner/diagnostics.sh classifies a test as a runtime error by scanning its output for that exact string. The obvious phrasing made every one of these failures report as both FailedandError for a single cause.

Found by writing it the obvious way first and watching the duplicate appear. The underlying fragility — the framework detecting shell errors by string-matching its own output stream — is worth its own issue and I'll file it.

📖 Docs

The bracket trap is described without using brackets: bashunit doc strips them while rendering, so the first draft came out as assert_true " -d /tmp " in the CLI, which teaches the wrong lesson. Snapshot regenerated.

✅ Verification

3 new tests, all confirmed RED first. make sa · make lint · bash build.sh bin -v✅ Build verified ✅ · fork budget unchanged · 1697 sequential / 1656 parallel-simple-strict.

Closes#982.
assert_true and assert_false ran their argument as a command and reported a bare
number when it failed:
Expected 'command or function with zero exit code'
but got 'exit code: 127'
127 is the shell's not-found code and 126 its not-executable code. Both are now
named, with the argument that produced them, so the failure points at its cause.
The case that motivated this is not an exotic one. `assert_true "[ -d /tmp ]"`
is valid bash that works in an `if`, and it produces exactly this failure,
because the argument is run as a command word rather than evaluated. A reader
seeing `exit code: 127` has no reason to suspect the shape of their argument and
will go and look at /tmp first.
assert_false had the worse half of the same problem. It failed only on exit code
0, so 127 counted as "non-zero, therefore false" and a typo in the command name
satisfied the assertion:
assert_false "definitley_not_a_command" # passed
That is a false pass -- the assertion reported success while running nothing.
126 and 127 now fail both assertions, because they mean the command never ran,
which is neither true nor false.
The wording avoids the literal phrase "command not found" on purpose.
runner/diagnostics.sh classifies a test as a runtime error by scanning its output
for that exact string, so the obvious phrasing made every one of these failures
report as both Failed and Error for a single cause. Found by writing it the
obvious way first and watching the duplicate appear. The underlying fragility --
the framework detecting shell errors by string-matching its own output stream --
is filed separately.
The docs describe the bracket trap without using brackets: `bashunit doc` strips
them while rendering, so the first draft rendered as `assert_true " -d /tmp "` in
the CLI, which teaches the wrong lesson. Snapshot regenerated.
1697 sequential / 1656 parallel; baseline + 3, all RED first.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancementNew feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Chemaclass
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat(assert): name the problem instead of printing exit code 127 by Chemaclass · Pull Request #991 · TypedDevs/bashunit · GitHub
Skip to content

feat(assert): name the problem instead of printing exit code 127 - #991

Merged
Chemaclass merged 1 commit into
mainfrom
feat/982-command-not-found-message
Aug 8, 2026
Merged

feat(assert): name the problem instead of printing exit code 127#991
Chemaclass merged 1 commit into
mainfrom
feat/982-command-not-found-message

Conversation

@Chemaclass

Copy link
Copy Markdown
Member

🤔 Background

Related #982

assert_true / assert_false ran their argument as a command and reported a bare number:

Expected 'command or function with zero exit code'
but got 'exit code: 127'

127 is the shell's not-found code, 126 its not-executable code. Both are now named, with the argument that produced them.

The motivating case isn't exotic — assert_true "[ -d /tmp ]" is valid bash that works in an if, and produces exactly this, because the argument is run as a command word rather than evaluated. Someone seeing exit code: 127 has no reason to suspect their argument's shape and will check /tmp first.

🐛 assert_false had the worse half — a false pass

It failed only on exit code 0, so 127 counted as "non-zero, therefore false":

assert_false "definitley_not_a_command"# passed

A typo in the command name satisfied the assertion while running nothing. 126 and 127 now fail both assertions, because they mean the command never ran — which is neither true nor false.

⚠️ Why the wording avoids "command not found"

runner/diagnostics.sh classifies a test as a runtime error by scanning its output for that exact string. The obvious phrasing made every one of these failures report as both FailedandError for a single cause.

Found by writing it the obvious way first and watching the duplicate appear. The underlying fragility — the framework detecting shell errors by string-matching its own output stream — is worth its own issue and I'll file it.

📖 Docs

The bracket trap is described without using brackets: bashunit doc strips them while rendering, so the first draft came out as assert_true " -d /tmp " in the CLI, which teaches the wrong lesson. Snapshot regenerated.

✅ Verification

3 new tests, all confirmed RED first. make sa · make lint · bash build.sh bin -v✅ Build verified ✅ · fork budget unchanged · 1697 sequential / 1656 parallel-simple-strict.

Closes#982.
assert_true and assert_false ran their argument as a command and reported a bare
number when it failed:
Expected 'command or function with zero exit code'
but got 'exit code: 127'
127 is the shell's not-found code and 126 its not-executable code. Both are now
named, with the argument that produced them, so the failure points at its cause.
The case that motivated this is not an exotic one. `assert_true "[ -d /tmp ]"`
is valid bash that works in an `if`, and it produces exactly this failure,
because the argument is run as a command word rather than evaluated. A reader
seeing `exit code: 127` has no reason to suspect the shape of their argument and
will go and look at /tmp first.
assert_false had the worse half of the same problem. It failed only on exit code
0, so 127 counted as "non-zero, therefore false" and a typo in the command name
satisfied the assertion:
assert_false "definitley_not_a_command" # passed
That is a false pass -- the assertion reported success while running nothing.
126 and 127 now fail both assertions, because they mean the command never ran,
which is neither true nor false.
The wording avoids the literal phrase "command not found" on purpose.
runner/diagnostics.sh classifies a test as a runtime error by scanning its output
for that exact string, so the obvious phrasing made every one of these failures
report as both Failed and Error for a single cause. Found by writing it the
obvious way first and watching the duplicate appear. The underlying fragility --
the framework detecting shell errors by string-matching its own output stream --
is filed separately.
The docs describe the bracket trap without using brackets: `bashunit doc` strips
them while rendering, so the first draft rendered as `assert_true " -d /tmp "` in
the CLI, which teaches the wrong lesson. Snapshot regenerated.
1697 sequential / 1656 parallel; baseline + 3, all RED first.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancementNew feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Chemaclass
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); feat(assert): name the problem instead of printing exit code 127 by Chemaclass · Pull Request #991 · TypedDevs/bashunit · GitHub
Skip to content

feat(assert): name the problem instead of printing exit code 127 - #991

Merged
Chemaclass merged 1 commit into
mainfrom
feat/982-command-not-found-message
Aug 8, 2026
Merged

feat(assert): name the problem instead of printing exit code 127#991
Chemaclass merged 1 commit into
mainfrom
feat/982-command-not-found-message

Conversation

@Chemaclass

Copy link
Copy Markdown
Member

🤔 Background

Related #982

assert_true / assert_false ran their argument as a command and reported a bare number:

Expected 'command or function with zero exit code'
but got 'exit code: 127'

127 is the shell's not-found code, 126 its not-executable code. Both are now named, with the argument that produced them.

The motivating case isn't exotic — assert_true "[ -d /tmp ]" is valid bash that works in an if, and produces exactly this, because the argument is run as a command word rather than evaluated. Someone seeing exit code: 127 has no reason to suspect their argument's shape and will check /tmp first.

🐛 assert_false had the worse half — a false pass

It failed only on exit code 0, so 127 counted as "non-zero, therefore false":

assert_false "definitley_not_a_command"# passed

A typo in the command name satisfied the assertion while running nothing. 126 and 127 now fail both assertions, because they mean the command never ran — which is neither true nor false.

⚠️ Why the wording avoids "command not found"

runner/diagnostics.sh classifies a test as a runtime error by scanning its output for that exact string. The obvious phrasing made every one of these failures report as both FailedandError for a single cause.

Found by writing it the obvious way first and watching the duplicate appear. The underlying fragility — the framework detecting shell errors by string-matching its own output stream — is worth its own issue and I'll file it.

📖 Docs

The bracket trap is described without using brackets: bashunit doc strips them while rendering, so the first draft came out as assert_true " -d /tmp " in the CLI, which teaches the wrong lesson. Snapshot regenerated.

✅ Verification

3 new tests, all confirmed RED first. make sa · make lint · bash build.sh bin -v✅ Build verified ✅ · fork budget unchanged · 1697 sequential / 1656 parallel-simple-strict.

Closes#982.
assert_true and assert_false ran their argument as a command and reported a bare
number when it failed:
Expected 'command or function with zero exit code'
but got 'exit code: 127'
127 is the shell's not-found code and 126 its not-executable code. Both are now
named, with the argument that produced them, so the failure points at its cause.
The case that motivated this is not an exotic one. `assert_true "[ -d /tmp ]"`
is valid bash that works in an `if`, and it produces exactly this failure,
because the argument is run as a command word rather than evaluated. A reader
seeing `exit code: 127` has no reason to suspect the shape of their argument and
will go and look at /tmp first.
assert_false had the worse half of the same problem. It failed only on exit code
0, so 127 counted as "non-zero, therefore false" and a typo in the command name
satisfied the assertion:
assert_false "definitley_not_a_command" # passed
That is a false pass -- the assertion reported success while running nothing.
126 and 127 now fail both assertions, because they mean the command never ran,
which is neither true nor false.
The wording avoids the literal phrase "command not found" on purpose.
runner/diagnostics.sh classifies a test as a runtime error by scanning its output
for that exact string, so the obvious phrasing made every one of these failures
report as both Failed and Error for a single cause. Found by writing it the
obvious way first and watching the duplicate appear. The underlying fragility --
the framework detecting shell errors by string-matching its own output stream --
is filed separately.
The docs describe the bracket trap without using brackets: `bashunit doc` strips
them while rendering, so the first draft rendered as `assert_true " -d /tmp "` in
the CLI, which teaches the wrong lesson. Snapshot regenerated.
1697 sequential / 1656 parallel; baseline + 3, all RED first.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancementNew feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Chemaclass