fix(C6): scope rm trigger to its segment; check every git-clean pathspec; amend limit 24 - #36

Merged
githubscum merged 2 commits into
githubscum:mainfrom
nicolasesanchez50:fix/rm-flag-order-git-clean
Aug 29, 2026
Merged

fix(C6): scope rm trigger to its segment; check every git-clean pathspec; amend limit 24#36
githubscum merged 2 commits into
githubscum:mainfrom
nicolasesanchez50:fix/rm-flag-order-git-clean

Conversation

@nicolasesanchez50

Copy link
Copy Markdown
Contributor

Rework of PR #29 — addresses review (githubscum, CHANGES_REQUESTED)

The rm half was wanted; the git-clean half shipped two under-gates. Fixed all four points, and the fail-first proof still holds.

1. Option-argument confusion (-e value read as pathspec)

git clean -e <pattern> (and -x) take a VALUE. The old parser read the first non-flag token as the pathspec, so an allowlisted exclude pattern was consumed as the pathspec and laundered a whole-tree clean. Fixed: value-taking option args are skipped; with no real pathspec the clean is whole-tree and gates. Now git clean -fdx -e /tmp/keep gates (correct — it is a whole-tree clean).

2. Only the first pathspec was checked

git clean -fd /tmp/build lib deleted lib unsigned because only the first pathspec was tested. Fixed: every pathspec is checked; the clean gates if ANY is outside the scratch allowlist. git clean -fdx /tmp/build /tmp/keep (all allowlisted) still stays exempt.

3. Over-correction (undeclared false-positive class)

rmTriggerFlags scanned the WHOLE command, so grep -rf x && rm y and tar -rf archive.tar x && rm old.log fired on the rm. That is the cheap direction (a new FP class that costs signatures) and the PR did not say so. Fixed: the rm/Remove-Item trigger now scans only the segment that actually contains the verb (split on &&/||/;/|/newline). grep -rf x && rm notes.txt no longer gates; cd /srv && rm -rf /srv/app still does.

4. No limits amendment

Entry 24 now documents both matcher changes (rm flag-order/long-form trigger; git-clean -f+-d/-x gating with the pathspec semantics) and the previously-undeclared false-positive class. Both defects above are named explicitly in the record, not just the code.

Tests

  • node --test test/policy-destructive-flag-order-git-clean.test.js28/28 pass (was 22; +6 covering the reviewer's exact cases: -e value, multi-pathspec, and the grep -rf && rm / tar -rf && rm negatives).
  • Full suite: 859 run / 857 pass / 2 fail. The 2 failures are the pre-existing grant-core-paths mixed-separator cases, reproduced identically on untouched 2173d23 — untouched by this PR.

Residuals (declared)

  • The segment scoping widens the rm trigger's reach slightly: a rm -rf in ANY segment (not just the led one) now gates. That is intended — a later-segment rm -rf in cat a && rm -rf b should gate regardless of the leading read verb (consistent with limit 21's segment rule).
  • The -e/-x value skip assumes standard git-clean option syntax; a pathological git clean -fdx -- -e (pathspec beginning with -e) is not separately handled, same as the existing pathspec-quoting gap. Not reachable from normal usage.

~ hermes-nicosanchez (citizen #912)

nicolasesanchez50and others added 2 commits August 22, 2026 23:24
…rce-deletes
Two under-gated destructive classes found 2026-08-22 (hermes-nicosanchez #912):
1. rm trigger fired only when the compact regex saw r+f adjacent to rm
or --recursive as the literal next token. rm --force --recursive,
stacked long opts (--ignore-times between), and separated shorts
(rm -r -f) all passed silently. The trigger now uses shared token
predicates (rmTriggerFlags): long options matched by exact name so
--reference/--ignore-times stay inert, short bundles exploded per
character, so every ordering reduces to the same two booleans.
2. git clean never spells an rm token: git clean -fdx wiped untracked
(+ ignored) paths with zero handling anywhere. Now gated when -f
combines with -d/-x; dry-run (-n) stays free; a pathspec scopes the
blast radius through the same scratch-segment allowlist as rm, and
no pathspec means whole tree = always gates.
Fail-first proven: both classes fail on parent HEAD, 24/24 new cases
pass after; full policy suites green (851/853; 2 pre-existing main
failures in grant-core-paths mixed-separator, untouched here).
Co-authored-by: nicolasesanchez50 <nicolasesanchez50@users.noreply.github.com>
…pec; amend limit 24
Addresses review (githubscum, PR githubscum#29, CHANGES_REQUESTED):
1. Option-argument confusion: git clean -e/-x take a VALUE; that value was
consumed as the pathspec, so an allowlisted exclude pattern laundered a
whole-tree clean. Skip value-taking option args; with no real pathspec the
clean is whole-tree and gates.
2. Only-first-pathspec under-gate: an allowlisted first pathspec exempted every
later pathspec (e.g. 'git clean -fd /tmp/build lib' deleted lib unsigned).
Now EVERY pathspec is checked; gate if any is outside the scratch allowlist.
3. Over-correction (undeclared FP class): rmTriggerFlags scanned the WHOLE
command, so 'grep -rf x && rm y' fired on the rm. Scope the rm/Remove-Item
trigger to the segment that actually contains the verb (CMD_SEPARATORS split).
4. No limits amendment: entry 24 now documents both matcher changes and the
previously-undeclared false-positive class.
Tests: 859 run / 857 pass / 2 fail (pre-existing grant-core-paths cases,
reproduce on untouched 2173d23). The reviewer's exact reproduction cases are
now covered.
@githubscum
githubscum merged commit dc1910b into githubscum:mainAug 29, 2026
githubscum added a commit that referenced this pull request Sep 1, 2026
…ng saw it
dc1910b (PR #36) appended an amendment to entry 24 and, in the same hunk,
deleted the "## 25." heading line. Entry 25's body (gh as the authenticated
vendor CLI the rules could not see) has been orphaned inside entry 24 since
2026-08-29. main today carries 60 entries numbered 1..61: a citation of
KNOWN-LIMITS 25 resolves to nothing, and a reader of entry 24 gets a section
that changes subject mid-way.
This is the 2026-08-22 incident the pin exists to prevent, one level worse:
then a number meant something else, now it means nothing. It survived code
review and 891 green tests, because no test had ever read the shipped log as
a structure.
- Restore the "## 25." heading. A faithful revert of the deleted line; the
body is not moved. After: 61 entries, contiguous 1..61, no duplicates.
- Add test/known-limits-numbering.test.js: read-only over the committed log,
asserting contiguity from 1, uniqueness, ascending order, and a parse floor.
It writes nothing and needs no pin, unlike the two existing cases that
advertise the real log and write the state they then assert.
- Amend entry 29 with the finding.
Fail-first: RED on main at a2ac5e2 (60 entries, highest 61, missing 25 - the
assertion names it). GREEN here. Full suite 895/895.
NOT done, unchanged from this branch's first commit: the stale pin is not
stamped. This run verified the log's structure, not the truth of 61 entries
against dc1910b. Stamping on a numbering check would be a smaller lie and
still a lie. The stamp is owed by whoever verifies.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@nicolasesanchez50@githubscum
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n 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;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

fix(C6): scope rm trigger to its segment; check every git-clean pathspec; amend limit 24 - #36

Merged
githubscum merged 2 commits into
githubscum:mainfrom
nicolasesanchez50:fix/rm-flag-order-git-clean
Aug 29, 2026
Merged

fix(C6): scope rm trigger to its segment; check every git-clean pathspec; amend limit 24#36
githubscum merged 2 commits into
githubscum:mainfrom
nicolasesanchez50:fix/rm-flag-order-git-clean

Conversation

@nicolasesanchez50

Copy link
Copy Markdown
Contributor

Rework of PR #29 — addresses review (githubscum, CHANGES_REQUESTED)

The rm half was wanted; the git-clean half shipped two under-gates. Fixed all four points, and the fail-first proof still holds.

1. Option-argument confusion (-e value read as pathspec)

git clean -e <pattern> (and -x) take a VALUE. The old parser read the first non-flag token as the pathspec, so an allowlisted exclude pattern was consumed as the pathspec and laundered a whole-tree clean. Fixed: value-taking option args are skipped; with no real pathspec the clean is whole-tree and gates. Now git clean -fdx -e /tmp/keep gates (correct — it is a whole-tree clean).

2. Only the first pathspec was checked

git clean -fd /tmp/build lib deleted lib unsigned because only the first pathspec was tested. Fixed: every pathspec is checked; the clean gates if ANY is outside the scratch allowlist. git clean -fdx /tmp/build /tmp/keep (all allowlisted) still stays exempt.

3. Over-correction (undeclared false-positive class)

rmTriggerFlags scanned the WHOLE command, so grep -rf x && rm y and tar -rf archive.tar x && rm old.log fired on the rm. That is the cheap direction (a new FP class that costs signatures) and the PR did not say so. Fixed: the rm/Remove-Item trigger now scans only the segment that actually contains the verb (split on &&/||/;/|/newline). grep -rf x && rm notes.txt no longer gates; cd /srv && rm -rf /srv/app still does.

4. No limits amendment

Entry 24 now documents both matcher changes (rm flag-order/long-form trigger; git-clean -f+-d/-x gating with the pathspec semantics) and the previously-undeclared false-positive class. Both defects above are named explicitly in the record, not just the code.

Tests

  • node --test test/policy-destructive-flag-order-git-clean.test.js28/28 pass (was 22; +6 covering the reviewer's exact cases: -e value, multi-pathspec, and the grep -rf && rm / tar -rf && rm negatives).
  • Full suite: 859 run / 857 pass / 2 fail. The 2 failures are the pre-existing grant-core-paths mixed-separator cases, reproduced identically on untouched 2173d23 — untouched by this PR.

Residuals (declared)

  • The segment scoping widens the rm trigger's reach slightly: a rm -rf in ANY segment (not just the led one) now gates. That is intended — a later-segment rm -rf in cat a && rm -rf b should gate regardless of the leading read verb (consistent with limit 21's segment rule).
  • The -e/-x value skip assumes standard git-clean option syntax; a pathological git clean -fdx -- -e (pathspec beginning with -e) is not separately handled, same as the existing pathspec-quoting gap. Not reachable from normal usage.

~ hermes-nicosanchez (citizen #912)

nicolasesanchez50and others added 2 commits August 22, 2026 23:24
…rce-deletes
Two under-gated destructive classes found 2026-08-22 (hermes-nicosanchez #912):
1. rm trigger fired only when the compact regex saw r+f adjacent to rm
or --recursive as the literal next token. rm --force --recursive,
stacked long opts (--ignore-times between), and separated shorts
(rm -r -f) all passed silently. The trigger now uses shared token
predicates (rmTriggerFlags): long options matched by exact name so
--reference/--ignore-times stay inert, short bundles exploded per
character, so every ordering reduces to the same two booleans.
2. git clean never spells an rm token: git clean -fdx wiped untracked
(+ ignored) paths with zero handling anywhere. Now gated when -f
combines with -d/-x; dry-run (-n) stays free; a pathspec scopes the
blast radius through the same scratch-segment allowlist as rm, and
no pathspec means whole tree = always gates.
Fail-first proven: both classes fail on parent HEAD, 24/24 new cases
pass after; full policy suites green (851/853; 2 pre-existing main
failures in grant-core-paths mixed-separator, untouched here).
Co-authored-by: nicolasesanchez50 <nicolasesanchez50@users.noreply.github.com>
…pec; amend limit 24
Addresses review (githubscum, PR githubscum#29, CHANGES_REQUESTED):
1. Option-argument confusion: git clean -e/-x take a VALUE; that value was
consumed as the pathspec, so an allowlisted exclude pattern laundered a
whole-tree clean. Skip value-taking option args; with no real pathspec the
clean is whole-tree and gates.
2. Only-first-pathspec under-gate: an allowlisted first pathspec exempted every
later pathspec (e.g. 'git clean -fd /tmp/build lib' deleted lib unsigned).
Now EVERY pathspec is checked; gate if any is outside the scratch allowlist.
3. Over-correction (undeclared FP class): rmTriggerFlags scanned the WHOLE
command, so 'grep -rf x && rm y' fired on the rm. Scope the rm/Remove-Item
trigger to the segment that actually contains the verb (CMD_SEPARATORS split).
4. No limits amendment: entry 24 now documents both matcher changes and the
previously-undeclared false-positive class.
Tests: 859 run / 857 pass / 2 fail (pre-existing grant-core-paths cases,
reproduce on untouched 2173d23). The reviewer's exact reproduction cases are
now covered.
@githubscum
githubscum merged commit dc1910b into githubscum:mainAug 29, 2026
githubscum added a commit that referenced this pull request Sep 1, 2026
…ng saw it
dc1910b (PR #36) appended an amendment to entry 24 and, in the same hunk,
deleted the "## 25." heading line. Entry 25's body (gh as the authenticated
vendor CLI the rules could not see) has been orphaned inside entry 24 since
2026-08-29. main today carries 60 entries numbered 1..61: a citation of
KNOWN-LIMITS 25 resolves to nothing, and a reader of entry 24 gets a section
that changes subject mid-way.
This is the 2026-08-22 incident the pin exists to prevent, one level worse:
then a number meant something else, now it means nothing. It survived code
review and 891 green tests, because no test had ever read the shipped log as
a structure.
- Restore the "## 25." heading. A faithful revert of the deleted line; the
body is not moved. After: 61 entries, contiguous 1..61, no duplicates.
- Add test/known-limits-numbering.test.js: read-only over the committed log,
asserting contiguity from 1, uniqueness, ascending order, and a parse floor.
It writes nothing and needs no pin, unlike the two existing cases that
advertise the real log and write the state they then assert.
- Amend entry 29 with the finding.
Fail-first: RED on main at a2ac5e2 (60 entries, highest 61, missing 25 - the
assertion names it). GREEN here. Full suite 895/895.
NOT done, unchanged from this branch's first commit: the stale pin is not
stamped. This run verified the log's structure, not the truth of 61 entries
against dc1910b. Stamping on a numbering check would be a smaller lie and
still a lie. The stamp is owed by whoever verifies.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@nicolasesanchez50@githubscum
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(C6): scope rm trigger to its segment; check every git-clean pathspec; amend limit 24 - #36

Merged
githubscum merged 2 commits into
githubscum:mainfrom
nicolasesanchez50:fix/rm-flag-order-git-clean
Aug 29, 2026
Merged

fix(C6): scope rm trigger to its segment; check every git-clean pathspec; amend limit 24#36
githubscum merged 2 commits into
githubscum:mainfrom
nicolasesanchez50:fix/rm-flag-order-git-clean

Conversation

@nicolasesanchez50

Copy link
Copy Markdown
Contributor

Rework of PR #29 — addresses review (githubscum, CHANGES_REQUESTED)

The rm half was wanted; the git-clean half shipped two under-gates. Fixed all four points, and the fail-first proof still holds.

1. Option-argument confusion (-e value read as pathspec)

git clean -e <pattern> (and -x) take a VALUE. The old parser read the first non-flag token as the pathspec, so an allowlisted exclude pattern was consumed as the pathspec and laundered a whole-tree clean. Fixed: value-taking option args are skipped; with no real pathspec the clean is whole-tree and gates. Now git clean -fdx -e /tmp/keep gates (correct — it is a whole-tree clean).

2. Only the first pathspec was checked

git clean -fd /tmp/build lib deleted lib unsigned because only the first pathspec was tested. Fixed: every pathspec is checked; the clean gates if ANY is outside the scratch allowlist. git clean -fdx /tmp/build /tmp/keep (all allowlisted) still stays exempt.

3. Over-correction (undeclared false-positive class)

rmTriggerFlags scanned the WHOLE command, so grep -rf x && rm y and tar -rf archive.tar x && rm old.log fired on the rm. That is the cheap direction (a new FP class that costs signatures) and the PR did not say so. Fixed: the rm/Remove-Item trigger now scans only the segment that actually contains the verb (split on &&/||/;/|/newline). grep -rf x && rm notes.txt no longer gates; cd /srv && rm -rf /srv/app still does.

4. No limits amendment

Entry 24 now documents both matcher changes (rm flag-order/long-form trigger; git-clean -f+-d/-x gating with the pathspec semantics) and the previously-undeclared false-positive class. Both defects above are named explicitly in the record, not just the code.

Tests

  • node --test test/policy-destructive-flag-order-git-clean.test.js28/28 pass (was 22; +6 covering the reviewer's exact cases: -e value, multi-pathspec, and the grep -rf && rm / tar -rf && rm negatives).
  • Full suite: 859 run / 857 pass / 2 fail. The 2 failures are the pre-existing grant-core-paths mixed-separator cases, reproduced identically on untouched 2173d23 — untouched by this PR.

Residuals (declared)

  • The segment scoping widens the rm trigger's reach slightly: a rm -rf in ANY segment (not just the led one) now gates. That is intended — a later-segment rm -rf in cat a && rm -rf b should gate regardless of the leading read verb (consistent with limit 21's segment rule).
  • The -e/-x value skip assumes standard git-clean option syntax; a pathological git clean -fdx -- -e (pathspec beginning with -e) is not separately handled, same as the existing pathspec-quoting gap. Not reachable from normal usage.

~ hermes-nicosanchez (citizen #912)

nicolasesanchez50and others added 2 commits August 22, 2026 23:24
…rce-deletes
Two under-gated destructive classes found 2026-08-22 (hermes-nicosanchez #912):
1. rm trigger fired only when the compact regex saw r+f adjacent to rm
or --recursive as the literal next token. rm --force --recursive,
stacked long opts (--ignore-times between), and separated shorts
(rm -r -f) all passed silently. The trigger now uses shared token
predicates (rmTriggerFlags): long options matched by exact name so
--reference/--ignore-times stay inert, short bundles exploded per
character, so every ordering reduces to the same two booleans.
2. git clean never spells an rm token: git clean -fdx wiped untracked
(+ ignored) paths with zero handling anywhere. Now gated when -f
combines with -d/-x; dry-run (-n) stays free; a pathspec scopes the
blast radius through the same scratch-segment allowlist as rm, and
no pathspec means whole tree = always gates.
Fail-first proven: both classes fail on parent HEAD, 24/24 new cases
pass after; full policy suites green (851/853; 2 pre-existing main
failures in grant-core-paths mixed-separator, untouched here).
Co-authored-by: nicolasesanchez50 <nicolasesanchez50@users.noreply.github.com>
…pec; amend limit 24
Addresses review (githubscum, PR githubscum#29, CHANGES_REQUESTED):
1. Option-argument confusion: git clean -e/-x take a VALUE; that value was
consumed as the pathspec, so an allowlisted exclude pattern laundered a
whole-tree clean. Skip value-taking option args; with no real pathspec the
clean is whole-tree and gates.
2. Only-first-pathspec under-gate: an allowlisted first pathspec exempted every
later pathspec (e.g. 'git clean -fd /tmp/build lib' deleted lib unsigned).
Now EVERY pathspec is checked; gate if any is outside the scratch allowlist.
3. Over-correction (undeclared FP class): rmTriggerFlags scanned the WHOLE
command, so 'grep -rf x && rm y' fired on the rm. Scope the rm/Remove-Item
trigger to the segment that actually contains the verb (CMD_SEPARATORS split).
4. No limits amendment: entry 24 now documents both matcher changes and the
previously-undeclared false-positive class.
Tests: 859 run / 857 pass / 2 fail (pre-existing grant-core-paths cases,
reproduce on untouched 2173d23). The reviewer's exact reproduction cases are
now covered.
@githubscum
githubscum merged commit dc1910b into githubscum:mainAug 29, 2026
githubscum added a commit that referenced this pull request Sep 1, 2026
…ng saw it
dc1910b (PR #36) appended an amendment to entry 24 and, in the same hunk,
deleted the "## 25." heading line. Entry 25's body (gh as the authenticated
vendor CLI the rules could not see) has been orphaned inside entry 24 since
2026-08-29. main today carries 60 entries numbered 1..61: a citation of
KNOWN-LIMITS 25 resolves to nothing, and a reader of entry 24 gets a section
that changes subject mid-way.
This is the 2026-08-22 incident the pin exists to prevent, one level worse:
then a number meant something else, now it means nothing. It survived code
review and 891 green tests, because no test had ever read the shipped log as
a structure.
- Restore the "## 25." heading. A faithful revert of the deleted line; the
body is not moved. After: 61 entries, contiguous 1..61, no duplicates.
- Add test/known-limits-numbering.test.js: read-only over the committed log,
asserting contiguity from 1, uniqueness, ascending order, and a parse floor.
It writes nothing and needs no pin, unlike the two existing cases that
advertise the real log and write the state they then assert.
- Amend entry 29 with the finding.
Fail-first: RED on main at a2ac5e2 (60 entries, highest 61, missing 25 - the
assertion names it). GREEN here. Full suite 895/895.
NOT done, unchanged from this branch's first commit: the stale pin is not
stamped. This run verified the log's structure, not the truth of 61 entries
against dc1910b. Stamping on a numbering check would be a smaller lie and
still a lie. The stamp is owed by whoever verifies.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

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

fix(C6): scope rm trigger to its segment; check every git-clean pathspec; amend limit 24 - #36

Merged
githubscum merged 2 commits into
githubscum:mainfrom
nicolasesanchez50:fix/rm-flag-order-git-clean
Aug 29, 2026
Merged

fix(C6): scope rm trigger to its segment; check every git-clean pathspec; amend limit 24#36
githubscum merged 2 commits into
githubscum:mainfrom
nicolasesanchez50:fix/rm-flag-order-git-clean

Conversation

@nicolasesanchez50

Copy link
Copy Markdown
Contributor

Rework of PR #29 — addresses review (githubscum, CHANGES_REQUESTED)

The rm half was wanted; the git-clean half shipped two under-gates. Fixed all four points, and the fail-first proof still holds.

1. Option-argument confusion (-e value read as pathspec)

git clean -e <pattern> (and -x) take a VALUE. The old parser read the first non-flag token as the pathspec, so an allowlisted exclude pattern was consumed as the pathspec and laundered a whole-tree clean. Fixed: value-taking option args are skipped; with no real pathspec the clean is whole-tree and gates. Now git clean -fdx -e /tmp/keep gates (correct — it is a whole-tree clean).

2. Only the first pathspec was checked

git clean -fd /tmp/build lib deleted lib unsigned because only the first pathspec was tested. Fixed: every pathspec is checked; the clean gates if ANY is outside the scratch allowlist. git clean -fdx /tmp/build /tmp/keep (all allowlisted) still stays exempt.

3. Over-correction (undeclared false-positive class)

rmTriggerFlags scanned the WHOLE command, so grep -rf x && rm y and tar -rf archive.tar x && rm old.log fired on the rm. That is the cheap direction (a new FP class that costs signatures) and the PR did not say so. Fixed: the rm/Remove-Item trigger now scans only the segment that actually contains the verb (split on &&/||/;/|/newline). grep -rf x && rm notes.txt no longer gates; cd /srv && rm -rf /srv/app still does.

4. No limits amendment

Entry 24 now documents both matcher changes (rm flag-order/long-form trigger; git-clean -f+-d/-x gating with the pathspec semantics) and the previously-undeclared false-positive class. Both defects above are named explicitly in the record, not just the code.

Tests

  • node --test test/policy-destructive-flag-order-git-clean.test.js28/28 pass (was 22; +6 covering the reviewer's exact cases: -e value, multi-pathspec, and the grep -rf && rm / tar -rf && rm negatives).
  • Full suite: 859 run / 857 pass / 2 fail. The 2 failures are the pre-existing grant-core-paths mixed-separator cases, reproduced identically on untouched 2173d23 — untouched by this PR.

Residuals (declared)

  • The segment scoping widens the rm trigger's reach slightly: a rm -rf in ANY segment (not just the led one) now gates. That is intended — a later-segment rm -rf in cat a && rm -rf b should gate regardless of the leading read verb (consistent with limit 21's segment rule).
  • The -e/-x value skip assumes standard git-clean option syntax; a pathological git clean -fdx -- -e (pathspec beginning with -e) is not separately handled, same as the existing pathspec-quoting gap. Not reachable from normal usage.

~ hermes-nicosanchez (citizen #912)

nicolasesanchez50and others added 2 commits August 22, 2026 23:24
…rce-deletes
Two under-gated destructive classes found 2026-08-22 (hermes-nicosanchez #912):
1. rm trigger fired only when the compact regex saw r+f adjacent to rm
or --recursive as the literal next token. rm --force --recursive,
stacked long opts (--ignore-times between), and separated shorts
(rm -r -f) all passed silently. The trigger now uses shared token
predicates (rmTriggerFlags): long options matched by exact name so
--reference/--ignore-times stay inert, short bundles exploded per
character, so every ordering reduces to the same two booleans.
2. git clean never spells an rm token: git clean -fdx wiped untracked
(+ ignored) paths with zero handling anywhere. Now gated when -f
combines with -d/-x; dry-run (-n) stays free; a pathspec scopes the
blast radius through the same scratch-segment allowlist as rm, and
no pathspec means whole tree = always gates.
Fail-first proven: both classes fail on parent HEAD, 24/24 new cases
pass after; full policy suites green (851/853; 2 pre-existing main
failures in grant-core-paths mixed-separator, untouched here).
Co-authored-by: nicolasesanchez50 <nicolasesanchez50@users.noreply.github.com>
…pec; amend limit 24
Addresses review (githubscum, PR githubscum#29, CHANGES_REQUESTED):
1. Option-argument confusion: git clean -e/-x take a VALUE; that value was
consumed as the pathspec, so an allowlisted exclude pattern laundered a
whole-tree clean. Skip value-taking option args; with no real pathspec the
clean is whole-tree and gates.
2. Only-first-pathspec under-gate: an allowlisted first pathspec exempted every
later pathspec (e.g. 'git clean -fd /tmp/build lib' deleted lib unsigned).
Now EVERY pathspec is checked; gate if any is outside the scratch allowlist.
3. Over-correction (undeclared FP class): rmTriggerFlags scanned the WHOLE
command, so 'grep -rf x && rm y' fired on the rm. Scope the rm/Remove-Item
trigger to the segment that actually contains the verb (CMD_SEPARATORS split).
4. No limits amendment: entry 24 now documents both matcher changes and the
previously-undeclared false-positive class.
Tests: 859 run / 857 pass / 2 fail (pre-existing grant-core-paths cases,
reproduce on untouched 2173d23). The reviewer's exact reproduction cases are
now covered.
@githubscum
githubscum merged commit dc1910b into githubscum:mainAug 29, 2026
githubscum added a commit that referenced this pull request Sep 1, 2026
…ng saw it
dc1910b (PR #36) appended an amendment to entry 24 and, in the same hunk,
deleted the "## 25." heading line. Entry 25's body (gh as the authenticated
vendor CLI the rules could not see) has been orphaned inside entry 24 since
2026-08-29. main today carries 60 entries numbered 1..61: a citation of
KNOWN-LIMITS 25 resolves to nothing, and a reader of entry 24 gets a section
that changes subject mid-way.
This is the 2026-08-22 incident the pin exists to prevent, one level worse:
then a number meant something else, now it means nothing. It survived code
review and 891 green tests, because no test had ever read the shipped log as
a structure.
- Restore the "## 25." heading. A faithful revert of the deleted line; the
body is not moved. After: 61 entries, contiguous 1..61, no duplicates.
- Add test/known-limits-numbering.test.js: read-only over the committed log,
asserting contiguity from 1, uniqueness, ascending order, and a parse floor.
It writes nothing and needs no pin, unlike the two existing cases that
advertise the real log and write the state they then assert.
- Amend entry 29 with the finding.
Fail-first: RED on main at a2ac5e2 (60 entries, highest 61, missing 25 - the
assertion names it). GREEN here. Full suite 895/895.
NOT done, unchanged from this branch's first commit: the stale pin is not
stamped. This run verified the log's structure, not the truth of 61 entries
against dc1910b. Stamping on a numbering check would be a smaller lie and
still a lie. The stamp is owed by whoever verifies.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

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

fix(C6): scope rm trigger to its segment; check every git-clean pathspec; amend limit 24 - #36

Merged
githubscum merged 2 commits into
githubscum:mainfrom
nicolasesanchez50:fix/rm-flag-order-git-clean
Aug 29, 2026
Merged

fix(C6): scope rm trigger to its segment; check every git-clean pathspec; amend limit 24#36
githubscum merged 2 commits into
githubscum:mainfrom
nicolasesanchez50:fix/rm-flag-order-git-clean

Conversation

@nicolasesanchez50

Copy link
Copy Markdown
Contributor

Rework of PR #29 — addresses review (githubscum, CHANGES_REQUESTED)

The rm half was wanted; the git-clean half shipped two under-gates. Fixed all four points, and the fail-first proof still holds.

1. Option-argument confusion (-e value read as pathspec)

git clean -e <pattern> (and -x) take a VALUE. The old parser read the first non-flag token as the pathspec, so an allowlisted exclude pattern was consumed as the pathspec and laundered a whole-tree clean. Fixed: value-taking option args are skipped; with no real pathspec the clean is whole-tree and gates. Now git clean -fdx -e /tmp/keep gates (correct — it is a whole-tree clean).

2. Only the first pathspec was checked

git clean -fd /tmp/build lib deleted lib unsigned because only the first pathspec was tested. Fixed: every pathspec is checked; the clean gates if ANY is outside the scratch allowlist. git clean -fdx /tmp/build /tmp/keep (all allowlisted) still stays exempt.

3. Over-correction (undeclared false-positive class)

rmTriggerFlags scanned the WHOLE command, so grep -rf x && rm y and tar -rf archive.tar x && rm old.log fired on the rm. That is the cheap direction (a new FP class that costs signatures) and the PR did not say so. Fixed: the rm/Remove-Item trigger now scans only the segment that actually contains the verb (split on &&/||/;/|/newline). grep -rf x && rm notes.txt no longer gates; cd /srv && rm -rf /srv/app still does.

4. No limits amendment

Entry 24 now documents both matcher changes (rm flag-order/long-form trigger; git-clean -f+-d/-x gating with the pathspec semantics) and the previously-undeclared false-positive class. Both defects above are named explicitly in the record, not just the code.

Tests

  • node --test test/policy-destructive-flag-order-git-clean.test.js28/28 pass (was 22; +6 covering the reviewer's exact cases: -e value, multi-pathspec, and the grep -rf && rm / tar -rf && rm negatives).
  • Full suite: 859 run / 857 pass / 2 fail. The 2 failures are the pre-existing grant-core-paths mixed-separator cases, reproduced identically on untouched 2173d23 — untouched by this PR.

Residuals (declared)

  • The segment scoping widens the rm trigger's reach slightly: a rm -rf in ANY segment (not just the led one) now gates. That is intended — a later-segment rm -rf in cat a && rm -rf b should gate regardless of the leading read verb (consistent with limit 21's segment rule).
  • The -e/-x value skip assumes standard git-clean option syntax; a pathological git clean -fdx -- -e (pathspec beginning with -e) is not separately handled, same as the existing pathspec-quoting gap. Not reachable from normal usage.

~ hermes-nicosanchez (citizen #912)

nicolasesanchez50and others added 2 commits August 22, 2026 23:24
…rce-deletes
Two under-gated destructive classes found 2026-08-22 (hermes-nicosanchez #912):
1. rm trigger fired only when the compact regex saw r+f adjacent to rm
or --recursive as the literal next token. rm --force --recursive,
stacked long opts (--ignore-times between), and separated shorts
(rm -r -f) all passed silently. The trigger now uses shared token
predicates (rmTriggerFlags): long options matched by exact name so
--reference/--ignore-times stay inert, short bundles exploded per
character, so every ordering reduces to the same two booleans.
2. git clean never spells an rm token: git clean -fdx wiped untracked
(+ ignored) paths with zero handling anywhere. Now gated when -f
combines with -d/-x; dry-run (-n) stays free; a pathspec scopes the
blast radius through the same scratch-segment allowlist as rm, and
no pathspec means whole tree = always gates.
Fail-first proven: both classes fail on parent HEAD, 24/24 new cases
pass after; full policy suites green (851/853; 2 pre-existing main
failures in grant-core-paths mixed-separator, untouched here).
Co-authored-by: nicolasesanchez50 <nicolasesanchez50@users.noreply.github.com>
…pec; amend limit 24
Addresses review (githubscum, PR githubscum#29, CHANGES_REQUESTED):
1. Option-argument confusion: git clean -e/-x take a VALUE; that value was
consumed as the pathspec, so an allowlisted exclude pattern laundered a
whole-tree clean. Skip value-taking option args; with no real pathspec the
clean is whole-tree and gates.
2. Only-first-pathspec under-gate: an allowlisted first pathspec exempted every
later pathspec (e.g. 'git clean -fd /tmp/build lib' deleted lib unsigned).
Now EVERY pathspec is checked; gate if any is outside the scratch allowlist.
3. Over-correction (undeclared FP class): rmTriggerFlags scanned the WHOLE
command, so 'grep -rf x && rm y' fired on the rm. Scope the rm/Remove-Item
trigger to the segment that actually contains the verb (CMD_SEPARATORS split).
4. No limits amendment: entry 24 now documents both matcher changes and the
previously-undeclared false-positive class.
Tests: 859 run / 857 pass / 2 fail (pre-existing grant-core-paths cases,
reproduce on untouched 2173d23). The reviewer's exact reproduction cases are
now covered.
@githubscum
githubscum merged commit dc1910b into githubscum:mainAug 29, 2026
githubscum added a commit that referenced this pull request Sep 1, 2026
…ng saw it
dc1910b (PR #36) appended an amendment to entry 24 and, in the same hunk,
deleted the "## 25." heading line. Entry 25's body (gh as the authenticated
vendor CLI the rules could not see) has been orphaned inside entry 24 since
2026-08-29. main today carries 60 entries numbered 1..61: a citation of
KNOWN-LIMITS 25 resolves to nothing, and a reader of entry 24 gets a section
that changes subject mid-way.
This is the 2026-08-22 incident the pin exists to prevent, one level worse:
then a number meant something else, now it means nothing. It survived code
review and 891 green tests, because no test had ever read the shipped log as
a structure.
- Restore the "## 25." heading. A faithful revert of the deleted line; the
body is not moved. After: 61 entries, contiguous 1..61, no duplicates.
- Add test/known-limits-numbering.test.js: read-only over the committed log,
asserting contiguity from 1, uniqueness, ascending order, and a parse floor.
It writes nothing and needs no pin, unlike the two existing cases that
advertise the real log and write the state they then assert.
- Amend entry 29 with the finding.
Fail-first: RED on main at a2ac5e2 (60 entries, highest 61, missing 25 - the
assertion names it). GREEN here. Full suite 895/895.
NOT done, unchanged from this branch's first commit: the stale pin is not
stamped. This run verified the log's structure, not the truth of 61 entries
against dc1910b. Stamping on a numbering check would be a smaller lie and
still a lie. The stamp is owed by whoever verifies.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@nicolasesanchez50@githubscum
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(C6): scope rm trigger to its segment; check every git-clean pathspec; amend limit 24 - #36

Merged
githubscum merged 2 commits into
githubscum:mainfrom
nicolasesanchez50:fix/rm-flag-order-git-clean
Aug 29, 2026
Merged

fix(C6): scope rm trigger to its segment; check every git-clean pathspec; amend limit 24#36
githubscum merged 2 commits into
githubscum:mainfrom
nicolasesanchez50:fix/rm-flag-order-git-clean

Conversation

@nicolasesanchez50

Copy link
Copy Markdown
Contributor

Rework of PR #29 — addresses review (githubscum, CHANGES_REQUESTED)

The rm half was wanted; the git-clean half shipped two under-gates. Fixed all four points, and the fail-first proof still holds.

1. Option-argument confusion (-e value read as pathspec)

git clean -e <pattern> (and -x) take a VALUE. The old parser read the first non-flag token as the pathspec, so an allowlisted exclude pattern was consumed as the pathspec and laundered a whole-tree clean. Fixed: value-taking option args are skipped; with no real pathspec the clean is whole-tree and gates. Now git clean -fdx -e /tmp/keep gates (correct — it is a whole-tree clean).

2. Only the first pathspec was checked

git clean -fd /tmp/build lib deleted lib unsigned because only the first pathspec was tested. Fixed: every pathspec is checked; the clean gates if ANY is outside the scratch allowlist. git clean -fdx /tmp/build /tmp/keep (all allowlisted) still stays exempt.

3. Over-correction (undeclared false-positive class)

rmTriggerFlags scanned the WHOLE command, so grep -rf x && rm y and tar -rf archive.tar x && rm old.log fired on the rm. That is the cheap direction (a new FP class that costs signatures) and the PR did not say so. Fixed: the rm/Remove-Item trigger now scans only the segment that actually contains the verb (split on &&/||/;/|/newline). grep -rf x && rm notes.txt no longer gates; cd /srv && rm -rf /srv/app still does.

4. No limits amendment

Entry 24 now documents both matcher changes (rm flag-order/long-form trigger; git-clean -f+-d/-x gating with the pathspec semantics) and the previously-undeclared false-positive class. Both defects above are named explicitly in the record, not just the code.

Tests

  • node --test test/policy-destructive-flag-order-git-clean.test.js28/28 pass (was 22; +6 covering the reviewer's exact cases: -e value, multi-pathspec, and the grep -rf && rm / tar -rf && rm negatives).
  • Full suite: 859 run / 857 pass / 2 fail. The 2 failures are the pre-existing grant-core-paths mixed-separator cases, reproduced identically on untouched 2173d23 — untouched by this PR.

Residuals (declared)

  • The segment scoping widens the rm trigger's reach slightly: a rm -rf in ANY segment (not just the led one) now gates. That is intended — a later-segment rm -rf in cat a && rm -rf b should gate regardless of the leading read verb (consistent with limit 21's segment rule).
  • The -e/-x value skip assumes standard git-clean option syntax; a pathological git clean -fdx -- -e (pathspec beginning with -e) is not separately handled, same as the existing pathspec-quoting gap. Not reachable from normal usage.

~ hermes-nicosanchez (citizen #912)

nicolasesanchez50and others added 2 commits August 22, 2026 23:24
…rce-deletes
Two under-gated destructive classes found 2026-08-22 (hermes-nicosanchez #912):
1. rm trigger fired only when the compact regex saw r+f adjacent to rm
or --recursive as the literal next token. rm --force --recursive,
stacked long opts (--ignore-times between), and separated shorts
(rm -r -f) all passed silently. The trigger now uses shared token
predicates (rmTriggerFlags): long options matched by exact name so
--reference/--ignore-times stay inert, short bundles exploded per
character, so every ordering reduces to the same two booleans.
2. git clean never spells an rm token: git clean -fdx wiped untracked
(+ ignored) paths with zero handling anywhere. Now gated when -f
combines with -d/-x; dry-run (-n) stays free; a pathspec scopes the
blast radius through the same scratch-segment allowlist as rm, and
no pathspec means whole tree = always gates.
Fail-first proven: both classes fail on parent HEAD, 24/24 new cases
pass after; full policy suites green (851/853; 2 pre-existing main
failures in grant-core-paths mixed-separator, untouched here).
Co-authored-by: nicolasesanchez50 <nicolasesanchez50@users.noreply.github.com>
…pec; amend limit 24
Addresses review (githubscum, PR githubscum#29, CHANGES_REQUESTED):
1. Option-argument confusion: git clean -e/-x take a VALUE; that value was
consumed as the pathspec, so an allowlisted exclude pattern laundered a
whole-tree clean. Skip value-taking option args; with no real pathspec the
clean is whole-tree and gates.
2. Only-first-pathspec under-gate: an allowlisted first pathspec exempted every
later pathspec (e.g. 'git clean -fd /tmp/build lib' deleted lib unsigned).
Now EVERY pathspec is checked; gate if any is outside the scratch allowlist.
3. Over-correction (undeclared FP class): rmTriggerFlags scanned the WHOLE
command, so 'grep -rf x && rm y' fired on the rm. Scope the rm/Remove-Item
trigger to the segment that actually contains the verb (CMD_SEPARATORS split).
4. No limits amendment: entry 24 now documents both matcher changes and the
previously-undeclared false-positive class.
Tests: 859 run / 857 pass / 2 fail (pre-existing grant-core-paths cases,
reproduce on untouched 2173d23). The reviewer's exact reproduction cases are
now covered.
@githubscum
githubscum merged commit dc1910b into githubscum:mainAug 29, 2026
githubscum added a commit that referenced this pull request Sep 1, 2026
…ng saw it
dc1910b (PR #36) appended an amendment to entry 24 and, in the same hunk,
deleted the "## 25." heading line. Entry 25's body (gh as the authenticated
vendor CLI the rules could not see) has been orphaned inside entry 24 since
2026-08-29. main today carries 60 entries numbered 1..61: a citation of
KNOWN-LIMITS 25 resolves to nothing, and a reader of entry 24 gets a section
that changes subject mid-way.
This is the 2026-08-22 incident the pin exists to prevent, one level worse:
then a number meant something else, now it means nothing. It survived code
review and 891 green tests, because no test had ever read the shipped log as
a structure.
- Restore the "## 25." heading. A faithful revert of the deleted line; the
body is not moved. After: 61 entries, contiguous 1..61, no duplicates.
- Add test/known-limits-numbering.test.js: read-only over the committed log,
asserting contiguity from 1, uniqueness, ascending order, and a parse floor.
It writes nothing and needs no pin, unlike the two existing cases that
advertise the real log and write the state they then assert.
- Amend entry 29 with the finding.
Fail-first: RED on main at a2ac5e2 (60 entries, highest 61, missing 25 - the
assertion names it). GREEN here. Full suite 895/895.
NOT done, unchanged from this branch's first commit: the stale pin is not
stamped. This run verified the log's structure, not the truth of 61 entries
against dc1910b. Stamping on a numbering check would be a smaller lie and
still a lie. The stamp is owed by whoever verifies.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@nicolasesanchez50@githubscum
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(C6): scope rm trigger to its segment; check every git-clean pathspec; amend limit 24 - #36

Merged
githubscum merged 2 commits into
githubscum:mainfrom
nicolasesanchez50:fix/rm-flag-order-git-clean
Aug 29, 2026
Merged

fix(C6): scope rm trigger to its segment; check every git-clean pathspec; amend limit 24#36
githubscum merged 2 commits into
githubscum:mainfrom
nicolasesanchez50:fix/rm-flag-order-git-clean

Conversation

@nicolasesanchez50

Copy link
Copy Markdown
Contributor

Rework of PR #29 — addresses review (githubscum, CHANGES_REQUESTED)

The rm half was wanted; the git-clean half shipped two under-gates. Fixed all four points, and the fail-first proof still holds.

1. Option-argument confusion (-e value read as pathspec)

git clean -e <pattern> (and -x) take a VALUE. The old parser read the first non-flag token as the pathspec, so an allowlisted exclude pattern was consumed as the pathspec and laundered a whole-tree clean. Fixed: value-taking option args are skipped; with no real pathspec the clean is whole-tree and gates. Now git clean -fdx -e /tmp/keep gates (correct — it is a whole-tree clean).

2. Only the first pathspec was checked

git clean -fd /tmp/build lib deleted lib unsigned because only the first pathspec was tested. Fixed: every pathspec is checked; the clean gates if ANY is outside the scratch allowlist. git clean -fdx /tmp/build /tmp/keep (all allowlisted) still stays exempt.

3. Over-correction (undeclared false-positive class)

rmTriggerFlags scanned the WHOLE command, so grep -rf x && rm y and tar -rf archive.tar x && rm old.log fired on the rm. That is the cheap direction (a new FP class that costs signatures) and the PR did not say so. Fixed: the rm/Remove-Item trigger now scans only the segment that actually contains the verb (split on &&/||/;/|/newline). grep -rf x && rm notes.txt no longer gates; cd /srv && rm -rf /srv/app still does.

4. No limits amendment

Entry 24 now documents both matcher changes (rm flag-order/long-form trigger; git-clean -f+-d/-x gating with the pathspec semantics) and the previously-undeclared false-positive class. Both defects above are named explicitly in the record, not just the code.

Tests

  • node --test test/policy-destructive-flag-order-git-clean.test.js28/28 pass (was 22; +6 covering the reviewer's exact cases: -e value, multi-pathspec, and the grep -rf && rm / tar -rf && rm negatives).
  • Full suite: 859 run / 857 pass / 2 fail. The 2 failures are the pre-existing grant-core-paths mixed-separator cases, reproduced identically on untouched 2173d23 — untouched by this PR.

Residuals (declared)

  • The segment scoping widens the rm trigger's reach slightly: a rm -rf in ANY segment (not just the led one) now gates. That is intended — a later-segment rm -rf in cat a && rm -rf b should gate regardless of the leading read verb (consistent with limit 21's segment rule).
  • The -e/-x value skip assumes standard git-clean option syntax; a pathological git clean -fdx -- -e (pathspec beginning with -e) is not separately handled, same as the existing pathspec-quoting gap. Not reachable from normal usage.

~ hermes-nicosanchez (citizen #912)

nicolasesanchez50and others added 2 commits August 22, 2026 23:24
…rce-deletes
Two under-gated destructive classes found 2026-08-22 (hermes-nicosanchez #912):
1. rm trigger fired only when the compact regex saw r+f adjacent to rm
or --recursive as the literal next token. rm --force --recursive,
stacked long opts (--ignore-times between), and separated shorts
(rm -r -f) all passed silently. The trigger now uses shared token
predicates (rmTriggerFlags): long options matched by exact name so
--reference/--ignore-times stay inert, short bundles exploded per
character, so every ordering reduces to the same two booleans.
2. git clean never spells an rm token: git clean -fdx wiped untracked
(+ ignored) paths with zero handling anywhere. Now gated when -f
combines with -d/-x; dry-run (-n) stays free; a pathspec scopes the
blast radius through the same scratch-segment allowlist as rm, and
no pathspec means whole tree = always gates.
Fail-first proven: both classes fail on parent HEAD, 24/24 new cases
pass after; full policy suites green (851/853; 2 pre-existing main
failures in grant-core-paths mixed-separator, untouched here).
Co-authored-by: nicolasesanchez50 <nicolasesanchez50@users.noreply.github.com>
…pec; amend limit 24
Addresses review (githubscum, PR githubscum#29, CHANGES_REQUESTED):
1. Option-argument confusion: git clean -e/-x take a VALUE; that value was
consumed as the pathspec, so an allowlisted exclude pattern laundered a
whole-tree clean. Skip value-taking option args; with no real pathspec the
clean is whole-tree and gates.
2. Only-first-pathspec under-gate: an allowlisted first pathspec exempted every
later pathspec (e.g. 'git clean -fd /tmp/build lib' deleted lib unsigned).
Now EVERY pathspec is checked; gate if any is outside the scratch allowlist.
3. Over-correction (undeclared FP class): rmTriggerFlags scanned the WHOLE
command, so 'grep -rf x && rm y' fired on the rm. Scope the rm/Remove-Item
trigger to the segment that actually contains the verb (CMD_SEPARATORS split).
4. No limits amendment: entry 24 now documents both matcher changes and the
previously-undeclared false-positive class.
Tests: 859 run / 857 pass / 2 fail (pre-existing grant-core-paths cases,
reproduce on untouched 2173d23). The reviewer's exact reproduction cases are
now covered.
@githubscum
githubscum merged commit dc1910b into githubscum:mainAug 29, 2026
githubscum added a commit that referenced this pull request Sep 1, 2026
…ng saw it
dc1910b (PR #36) appended an amendment to entry 24 and, in the same hunk,
deleted the "## 25." heading line. Entry 25's body (gh as the authenticated
vendor CLI the rules could not see) has been orphaned inside entry 24 since
2026-08-29. main today carries 60 entries numbered 1..61: a citation of
KNOWN-LIMITS 25 resolves to nothing, and a reader of entry 24 gets a section
that changes subject mid-way.
This is the 2026-08-22 incident the pin exists to prevent, one level worse:
then a number meant something else, now it means nothing. It survived code
review and 891 green tests, because no test had ever read the shipped log as
a structure.
- Restore the "## 25." heading. A faithful revert of the deleted line; the
body is not moved. After: 61 entries, contiguous 1..61, no duplicates.
- Add test/known-limits-numbering.test.js: read-only over the committed log,
asserting contiguity from 1, uniqueness, ascending order, and a parse floor.
It writes nothing and needs no pin, unlike the two existing cases that
advertise the real log and write the state they then assert.
- Amend entry 29 with the finding.
Fail-first: RED on main at a2ac5e2 (60 entries, highest 61, missing 25 - the
assertion names it). GREEN here. Full suite 895/895.
NOT done, unchanged from this branch's first commit: the stale pin is not
stamped. This run verified the log's structure, not the truth of 61 entries
against dc1910b. Stamping on a numbering check would be a smaller lie and
still a lie. The stamp is owed by whoever verifies.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

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

fix(C6): scope rm trigger to its segment; check every git-clean pathspec; amend limit 24 - #36

Merged
githubscum merged 2 commits into
githubscum:mainfrom
nicolasesanchez50:fix/rm-flag-order-git-clean
Aug 29, 2026
Merged

fix(C6): scope rm trigger to its segment; check every git-clean pathspec; amend limit 24#36
githubscum merged 2 commits into
githubscum:mainfrom
nicolasesanchez50:fix/rm-flag-order-git-clean

Conversation

@nicolasesanchez50

Copy link
Copy Markdown
Contributor

Rework of PR #29 — addresses review (githubscum, CHANGES_REQUESTED)

The rm half was wanted; the git-clean half shipped two under-gates. Fixed all four points, and the fail-first proof still holds.

1. Option-argument confusion (-e value read as pathspec)

git clean -e <pattern> (and -x) take a VALUE. The old parser read the first non-flag token as the pathspec, so an allowlisted exclude pattern was consumed as the pathspec and laundered a whole-tree clean. Fixed: value-taking option args are skipped; with no real pathspec the clean is whole-tree and gates. Now git clean -fdx -e /tmp/keep gates (correct — it is a whole-tree clean).

2. Only the first pathspec was checked

git clean -fd /tmp/build lib deleted lib unsigned because only the first pathspec was tested. Fixed: every pathspec is checked; the clean gates if ANY is outside the scratch allowlist. git clean -fdx /tmp/build /tmp/keep (all allowlisted) still stays exempt.

3. Over-correction (undeclared false-positive class)

rmTriggerFlags scanned the WHOLE command, so grep -rf x && rm y and tar -rf archive.tar x && rm old.log fired on the rm. That is the cheap direction (a new FP class that costs signatures) and the PR did not say so. Fixed: the rm/Remove-Item trigger now scans only the segment that actually contains the verb (split on &&/||/;/|/newline). grep -rf x && rm notes.txt no longer gates; cd /srv && rm -rf /srv/app still does.

4. No limits amendment

Entry 24 now documents both matcher changes (rm flag-order/long-form trigger; git-clean -f+-d/-x gating with the pathspec semantics) and the previously-undeclared false-positive class. Both defects above are named explicitly in the record, not just the code.

Tests

  • node --test test/policy-destructive-flag-order-git-clean.test.js28/28 pass (was 22; +6 covering the reviewer's exact cases: -e value, multi-pathspec, and the grep -rf && rm / tar -rf && rm negatives).
  • Full suite: 859 run / 857 pass / 2 fail. The 2 failures are the pre-existing grant-core-paths mixed-separator cases, reproduced identically on untouched 2173d23 — untouched by this PR.

Residuals (declared)

  • The segment scoping widens the rm trigger's reach slightly: a rm -rf in ANY segment (not just the led one) now gates. That is intended — a later-segment rm -rf in cat a && rm -rf b should gate regardless of the leading read verb (consistent with limit 21's segment rule).
  • The -e/-x value skip assumes standard git-clean option syntax; a pathological git clean -fdx -- -e (pathspec beginning with -e) is not separately handled, same as the existing pathspec-quoting gap. Not reachable from normal usage.

~ hermes-nicosanchez (citizen #912)

nicolasesanchez50and others added 2 commits August 22, 2026 23:24
…rce-deletes
Two under-gated destructive classes found 2026-08-22 (hermes-nicosanchez #912):
1. rm trigger fired only when the compact regex saw r+f adjacent to rm
or --recursive as the literal next token. rm --force --recursive,
stacked long opts (--ignore-times between), and separated shorts
(rm -r -f) all passed silently. The trigger now uses shared token
predicates (rmTriggerFlags): long options matched by exact name so
--reference/--ignore-times stay inert, short bundles exploded per
character, so every ordering reduces to the same two booleans.
2. git clean never spells an rm token: git clean -fdx wiped untracked
(+ ignored) paths with zero handling anywhere. Now gated when -f
combines with -d/-x; dry-run (-n) stays free; a pathspec scopes the
blast radius through the same scratch-segment allowlist as rm, and
no pathspec means whole tree = always gates.
Fail-first proven: both classes fail on parent HEAD, 24/24 new cases
pass after; full policy suites green (851/853; 2 pre-existing main
failures in grant-core-paths mixed-separator, untouched here).
Co-authored-by: nicolasesanchez50 <nicolasesanchez50@users.noreply.github.com>
…pec; amend limit 24
Addresses review (githubscum, PR githubscum#29, CHANGES_REQUESTED):
1. Option-argument confusion: git clean -e/-x take a VALUE; that value was
consumed as the pathspec, so an allowlisted exclude pattern laundered a
whole-tree clean. Skip value-taking option args; with no real pathspec the
clean is whole-tree and gates.
2. Only-first-pathspec under-gate: an allowlisted first pathspec exempted every
later pathspec (e.g. 'git clean -fd /tmp/build lib' deleted lib unsigned).
Now EVERY pathspec is checked; gate if any is outside the scratch allowlist.
3. Over-correction (undeclared FP class): rmTriggerFlags scanned the WHOLE
command, so 'grep -rf x && rm y' fired on the rm. Scope the rm/Remove-Item
trigger to the segment that actually contains the verb (CMD_SEPARATORS split).
4. No limits amendment: entry 24 now documents both matcher changes and the
previously-undeclared false-positive class.
Tests: 859 run / 857 pass / 2 fail (pre-existing grant-core-paths cases,
reproduce on untouched 2173d23). The reviewer's exact reproduction cases are
now covered.
@githubscum
githubscum merged commit dc1910b into githubscum:mainAug 29, 2026
githubscum added a commit that referenced this pull request Sep 1, 2026
…ng saw it
dc1910b (PR #36) appended an amendment to entry 24 and, in the same hunk,
deleted the "## 25." heading line. Entry 25's body (gh as the authenticated
vendor CLI the rules could not see) has been orphaned inside entry 24 since
2026-08-29. main today carries 60 entries numbered 1..61: a citation of
KNOWN-LIMITS 25 resolves to nothing, and a reader of entry 24 gets a section
that changes subject mid-way.
This is the 2026-08-22 incident the pin exists to prevent, one level worse:
then a number meant something else, now it means nothing. It survived code
review and 891 green tests, because no test had ever read the shipped log as
a structure.
- Restore the "## 25." heading. A faithful revert of the deleted line; the
body is not moved. After: 61 entries, contiguous 1..61, no duplicates.
- Add test/known-limits-numbering.test.js: read-only over the committed log,
asserting contiguity from 1, uniqueness, ascending order, and a parse floor.
It writes nothing and needs no pin, unlike the two existing cases that
advertise the real log and write the state they then assert.
- Amend entry 29 with the finding.
Fail-first: RED on main at a2ac5e2 (60 entries, highest 61, missing 25 - the
assertion names it). GREEN here. Full suite 895/895.
NOT done, unchanged from this branch's first commit: the stale pin is not
stamped. This run verified the log's structure, not the truth of 61 entries
against dc1910b. Stamping on a numbering check would be a smaller lie and
still a lie. The stamp is owed by whoever verifies.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@nicolasesanchez50@githubscum