Seven reported defects, six of them false positives or negatives in the same family: dcg was judging the text of a command rather than what the command would actually do. A SQL keyword that was only ever a filename, a POSIX end-of-options marker, a variable dcg had already proven elsewhere in the same command, a German commit message -- each was read as evidence of something it was not.
Fixed
-
A SQL keyword used as an ordinary filename no longer denies (#394).
cat truncate x,sort truncate bandwc -l truncate xwere denied asdatabase.mysql:truncate-table, because the rule matched the bare wordTRUNCATEfollowed by an identifier with no SQL execution context at all. Both the MySQL and PostgreSQL TRUNCATE rules now require the statement to start in statement position under a SQL client, somysql -eandpsql -cforms still deny while file readers pass. -
The POSIX end-of-options marker keeps the literal temp exemption (#395).
rm -rf -- /tmp/foois what a careful script writes so an operand beginning with-cannot be parsed as a flag -- strictly safer than the spelling dcg already allowed, and it was denied bycore.filesystem:rm-rf-general. Every temp-dir rm safe pattern now admits an optional bare--. It widens the accepted syntax, not the eligible operands: a home-directory operand and a traversal out of/tmpstill deny, and--no-preserve-rootis not a bare--. -
A proven
$VARrm operand gets the same exemption its literal value gets (#396). dcg has folded a single literal assignment for the redirect rule since [#275], so a redirect into"$D/f"was allowed while a recursive delete of the same proven path was denied -- the same value, proven by the same machinery, judged differently. That inversion rewarded hard-coding a temp path overmktemp -d, which is backwards. The proven value is now spliced into the segment and the real rm classifier is asked again, so only a command that would independently be allowed is allowed: a non-temp value, traversal past it, a second non-temp operand, a re-bound or subshell-bound name, a value carrying a space or a glob, and the ambient$TMPDIRall still deny. -
bun -e,bun -p,deno -eandbun execpayloads are extracted likenode -e(#397). An identical inline payload was denied undernodeand allowed underbun;bun exechands its argument to a shell and was not modeled as an inline payload at all. -
Dashed
git-<sub>executables are treated as git (#400).git-reset --hard,git-clean -fdxandgit-checkoutare the real dashed builtins and bypassed thecore.gitrules that their spaced spellings hit. -
Duplicate snake_case and camelCase keys in hook input no longer fail open (#410). A payload carrying both
tool_inputandtoolInputfailed deserialization, and the failure defaulted to allow. Conflicting spellings are now reconciled and evaluated; genuinely malformed input still takes the documented default, and says so. -
dcg explainreports the resolved outcome, not the rule default (#417).explainanddcg test -vvvskipped policy resolution, so a rule overridden towarn,askorlogwas still reported asDENY-- the one command whose job is to tell you what will happen disagreed with what happened.
Partially fixed
- A quoted heredoc body is no longer read as PowerShell shape (#412). An
ordinary hyphenated word at the start of a line in a commit message
(
Read-only) looked like a verb-noun cmdlet and down-trusted aBash-labeled command toUnknown, where the fail-closed union denied it. The shape test now runs on the heredoc-masked view. The reported command remains denied: it embeds the heredoc in"$(...)"and its body carries an unbalanced", which defeats the trigger scanner behind the mask, so the body is never delimited. [#412] stays open with the root cause recorded.
Internal
cargo clippy --all-targets -- -D warningsandcargo fmt --checkare clean again; both are release gates and both were failing on main.