forked from bchanot/claude
feat(doc-sync): MINOR-shape oracle + fail-loud commit (strengthen MINOR gate)
(1) lib/doc-shape.sh — deterministic shape oracle re-checks each LLM-classified MINOR patch before the silent auto-commit; a shape-suspect patch (added heading / oversize / new file / non-doc) escalates to the EXISTING SIGNIFICANT gate. Genuine MINOR still auto-commits (zero friction, BDR-036 preserved). A structural floor under the LLM call, not a semantic SIGNIFICANT-detector (BDR-040). (2) lib/doc-commit.sh — guard the commit itself: a rejected git commit (pre-commit hook / protected branch / signing) now fails loud with exit 5 + empty stdout, instead of a false "committed" + the previous HEAD's hash + exit 0 that left docs silently uncommitted (LRN-071, 3rd occurrence of the swallowed-commit pattern after LRN-066 and LRN-068/BLK-012). Wired doc-syncer STEP A4 (whole-set escalation: no=revert all, select=keep subset) + doc-commit.md (rc-5 consumer row + ACKNOWLEDGMENTS coherence). TDD RED->GREEN: run-doc-commit.sh 32/32, run-doc-shape.sh 19/19, behavioral C/D. shellcheck clean. Branch-guard (3) deferred. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C6bUdvHnajCNzgVQefZowj
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
4da2b905de
commit
09f5b28d99
+20
-3
@@ -16,7 +16,8 @@
|
||||
# doc-commit.sh pending <file>... # exit 0 if any passed file has changes, 1 if clean
|
||||
# doc-commit.sh commit "<message>" <file>... # surgical commit
|
||||
#
|
||||
# Exit codes (commit): 0 ok/no-op · 2 usage · 3 unsafe git state · 4 scope violation.
|
||||
# Exit codes (commit): 0 ok/no-op · 2 usage · 3 unsafe git state · 4 scope violation ·
|
||||
# 5 commit rejected (git commit exited non-zero — hook / protected branch / signing).
|
||||
# Output contract: diagnostics → stderr; on a real commit the short hash of the doc
|
||||
# commit is the ONLY thing on stdout (empty on no-op/abort), so callers can capture
|
||||
# it: doc_hash=$(doc-commit.sh commit "msg" README.md USAGE.md).
|
||||
@@ -78,7 +79,8 @@ docs_pending() {
|
||||
}
|
||||
|
||||
# Surgical commit of the passed doc paths only. Returns 0 (ok/no-op), 3 (unsafe),
|
||||
# 4 (scope violation). On a real commit, prints the doc-commit short hash to stdout.
|
||||
# 4 (scope violation), 5 (commit rejected by git). On a real commit, prints the
|
||||
# doc-commit short hash to stdout.
|
||||
commit_docs() {
|
||||
local msg="${1:?commit message required}"
|
||||
shift
|
||||
@@ -118,7 +120,22 @@ commit_docs() {
|
||||
echo "doc-commit: only ignored/no-op changes — no-op" >&2
|
||||
return 0
|
||||
fi
|
||||
git commit -q -m "$msg" -- "${changed[@]}"
|
||||
# FAIL-LOUD on the commit itself. With `set -uo pipefail` (no -e), a rejected
|
||||
# commit (pre-commit hook on a protected branch, signing failure, …) would NOT
|
||||
# abort: the printf below would falsely claim "committed" and rev-parse would
|
||||
# emit the PREVIOUS HEAD's hash with exit 0 — a silent masked failure. The
|
||||
# script is fail-closed+loud on scope (exit 4); it must be the same on its own
|
||||
# commit. Reject → loud, NO hash on stdout, exit 5 (distinct from rc 3 "could
|
||||
# not start": rc 5 = "tried, git refused").
|
||||
if ! git commit -q -m "$msg" -- "${changed[@]}"; then
|
||||
{
|
||||
echo "doc-commit: COMMIT REJECTED — git commit exited non-zero" \
|
||||
"(pre-commit hook? protected branch? signing?)."
|
||||
echo "doc-commit: NOTHING committed, working tree left as-is," \
|
||||
"NO hash emitted — investigate before retry."
|
||||
} >&2
|
||||
return 5
|
||||
fi
|
||||
printf 'doc-commit: committed %d file(s): %s\n' "${#changed[@]}" "${changed[*]}" >&2
|
||||
git rev-parse --short HEAD
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user