* test(#4429): regression coverage for three defects in the commit hook Failing-first coverage. Every conforming-subject row is red against the unfixed hook, and each defect gets an explicit CONTROL row that reconstructs the pre-fix form and asserts the defect reproduces -- without those, the passing rows would pass with or without the fix. 1. SIGPIPE (the reported defect). The pre-fix first-line extraction used a `head -1` pipeline; once CONFIG_OUT exceeds the 64 KiB pipe buffer printf is killed and `set -euo pipefail` aborts the hook. That fix is already on next -- it landed incidentally in #4537, whose message never mentions #4429 -- and nothing in the tree would notice its removal. 2. regcomp. The commit-type alternation grew with the CONFIGURED list and exceeded bash's 64 KiB compiled-pattern cap. Boundary rows pin the cliff at 6051/6052, with controls on BOTH sides so limit-1 is not vacuous. 3. Ambient subprocess statuses (found by this change's security review). Defects 1 and 2 cannot be separated: each configured type adds len+1 bytes to CONFIG_OUT and len+1 to the alternation, so the smallest payload that overflows the pipe (N=6059) already puts the alternation past the ceiling. The SIGPIPE control accepts either SIGPIPE (141, Linux) or a reported write error (macOS bash 3.2's builtin printf, exit 1). Asserting only the message would go red on every CI lane, since the remote matrix is Linux-only. Named to bucket with gsd-validate-commit-crash-policy.test.cjs, which covers this same hook: lint-test-file-count derives a test's owning module from its filename prefix, and `validate-commit-*` collided with the `validate` module, already at its 2-file cap. Harness note, learned from three vacuous control runs: hooks/lib/git-cmd.js requires ../gsd-core/bin/lib/token-scanner.cjs relative to the hooks dir's parent, so a copy in a bare tmpdir fails open and returns 0 for any input. The layout symlinks gsd-core beside the copy, and every row that can prove it asserts the run was substantive. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(#4429): bound the commit-type regex and isolate subprocess statuses Two fixes in the same file, both of the same shape: a value computed for one purpose was being read as authority about something else. 1. The commit-type alternation could not be compiled. COMMIT_TYPE_ALT joined every CONFIGURED type into one regex, so the pattern grew without bound. bash caps a compiled pattern at 64 KiB. Bisected on bash 3.2.57 (this repo's macOS target): a 65504-byte alternation compiles, 65515 fails. `[[ =~ ]]` returns 2 on a compile failure, and `if !` cannot tell that from "the subject does not conform" -- so the hook blocked a valid `feat(auth): ...` with CONVENTIONAL_COMMITS_VIOLATION while printing `feat` in its own valid_types. Match the shape with a fixed-size pattern, capture the type, then test membership against the COMMIT_TYPES array. The character class is exactly the `^[a-z][a-z0-9-]*$` safe-token filter the config loader already applies, so it captures every type that can legally reach COMMIT_TYPES and no token that cannot. Review verified equivalence over 46 handcrafted plus 6000 randomized adversarial subjects against a type list containing prefix-overlapping, digit-bearing and trailing-hyphen types: zero divergences. The loop adds no subprocess and no pipe, which is the hazard class #4429 is about. COMMIT_TYPE_ALT is now unused and removed. types pre-fix `feat(auth): ...` fixed 10 accept accept 6051 accept accept 6052 BLOCK accept 20000 BLOCK accept 2. Subprocess statuses were inherited from the environment. Each status is captured as `... || VAR=$?`, which assigns ONLY on the failure branch; on success the variable kept whatever it already held, and `${VAR:-0}` defaults only when unset or empty. So an EXPORTED CONFIG_STATUS, CMD_STATUS or CLASSIFY_STATUS -- from a CI wrapper, a .envrc, or another hook -- survived into the success path and was read as "the subprocess failed". Since the hook fails OPEN on a genuine subprocess failure by design (#3838), the result was a silent bypass. Measured: `CLASSIFY_STATUS=3 git commit -m "nope: bad"` printed "validator disabled for this call" and exited 0. The three are now initialised before use. The fail-open path is unchanged and verified byte-identical to origin/next with a failing node. hooks/dist/ is gitignored and rebuilt from hooks/ by scripts/build-hooks.js, so there is no second copy to sync. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * chore(#4429): register the new suite with the conformance manifests Both conformance-tier manifests embed the test-file list, so adding a test file makes them stale. Regenerated with their own generators: node scripts/gen-platform-conformance-tier.cjs --write node scripts/gen-platform-conformance-tier.cjs --target macos --write Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * test(#4429): pin both fail-open-prone controls to their named cause Two rows in the ambient-status block asserted `status === 0`, which the hook also returns when the harness layout is broken -- so either row could have passed for entirely the wrong reason. This is the same vacuity trap the rest of the suite already guards, applied inconsistently to the rows added last. Measured, rather than reasoned about: genuine ambient bypass (pre-fix hook, CLASSIFY_STATUS=3) rc=0, no CLASSIFIER_THREW orphaned layout (no gsd-core symlink) rc=0, CLASSIFIER_THREW genuine fail-open (node shim exits 3) rc=0, no CLASSIFIER_THREW So assertSubstantive separates the intended cause from the harness failure in both rows, and each now pins its pass to the cause it names. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * test(#4429): stop asserting a macOS-only regex cap on every platform First verification run was RED: 45636/45638 passed, both failures in this new suite on linux-node24. Cause is mine -- I measured the compiled-pattern ceiling on macOS and encoded it as a cross-platform expectation. Measured in the tester image itself: engine 6051 6052 20000 bash 3.2.57 / BSD libc (macOS) compiles rc 2 rc 2 bash 5.2.15 / glibc (Linux) compiles compiles compiles (228943 B) glibc has no reachable cap, so the regcomp defect cannot occur there and the control asserting a block at 6052 was red for a behaviour the platform cannot produce. The control now calibrates at runtime: it runs the pre-fix form and, when this engine compiled the alternation, it SKIPS with a message naming the reason rather than asserting. Skipped out loud, never silently passed -- a green row there would read as "the defect is covered" on a platform where it cannot occur. Both branches verified: the capped branch asserts (macOS 17/17, zero skipped), and the uncapped branch was exercised by forcing the payload to a size that always compiles, producing a skip and not a failure. Consequence stated rather than hidden: the remote matrix is Linux-only, so this one control is skipped in CI and really runs only on a macOS workstation. The rows that run everywhere are the ones carrying the regression weight -- the shipped hook accepting a conforming commit at every payload size, the gate still blocking unknown types, the SIGPIPE control, and all seven ambient-status rows. Note this also narrows the coupling claim: SIGPIPE and regcomp are coupled only on a capped engine. On glibc the SIGPIPE defect is directly testable without the regcomp fix. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * docs(#4429): scope the regex-cap claim to the platform it applies to The changeset told users the validator "built a regular expression bigger than bash can compile" past ~6,000 configured types. That is false on Linux: glibc compiled a 228,943-byte alternation without complaint, so a Linux reader would have been misled about their own exposure. These are user-facing release notes, so the claim is now scoped to macOS (bash 3.2 / BSD libc) and says explicitly that glibc was never affected by this half. The hook's own comment led with the same overstatement -- "bash caps a compiled pattern at 64 KiB" -- before qualifying it. Reworded so the first clause states what is actually true: the limit is a property of the platform's regex engine. Text only; no behaviour change. Suite 17/17, eslint and lint:ci clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * chore(#4429): backfill changeset PR number (#4723) * chore(#4429): backfill changeset PR number (#4723) --------- Co-authored-by: sim <sim@local> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
278 lines
11 KiB
JavaScript
278 lines
11 KiB
JavaScript
// GENERATED FILE — do not hand-edit. Run `node scripts/gen-platform-conformance-tier.cjs --write` to regenerate.
|
|
'use strict';
|
|
|
|
module.exports = {
|
|
CONFORMANCE_TIER_FILES: [
|
|
"tests/adr-index-gate.test.cjs",
|
|
"tests/adr857-core-without-capabilities.test.cjs",
|
|
"tests/agent-install-check.test.cjs",
|
|
"tests/agent-install-validation.test.cjs",
|
|
"tests/agent-skills.test.cjs",
|
|
"tests/antigravity-upgrades.test.cjs",
|
|
"tests/api-coverage-gate-e2e.test.cjs",
|
|
"tests/api-coverage.test.cjs",
|
|
"tests/assumption-delta-checkpoint-e2e.test.cjs",
|
|
"tests/assumption-delta.test.cjs",
|
|
"tests/audit-command-cutover.test.cjs",
|
|
"tests/augment-upgrades.test.cjs",
|
|
"tests/broken-windows.test.cjs",
|
|
"tests/capability-cli.test.cjs",
|
|
"tests/capability-command-dispatch.test.cjs",
|
|
"tests/capability-consent.test.cjs",
|
|
"tests/capability-ledger.test.cjs",
|
|
"tests/capability-lifecycle.test.cjs",
|
|
"tests/capability-loader.test.cjs",
|
|
"tests/capability-lock-mkdir-failure-3987.test.cjs",
|
|
"tests/capability-probe-fallback.test.cjs",
|
|
"tests/capability-source.test.cjs",
|
|
"tests/capability-state.test.cjs",
|
|
"tests/changeset-new.test.cjs",
|
|
"tests/check-env.test.cjs",
|
|
"tests/check-gap-analysis-plan-post-e2e.test.cjs",
|
|
"tests/check-glossary-refs.test.cjs",
|
|
"tests/check-predicate.test.cjs",
|
|
"tests/check-tdd-review-checkpoint-e2e.test.cjs",
|
|
"tests/check-ui-safety-gate.test.cjs",
|
|
"tests/check-update-config-dir.test.cjs",
|
|
"tests/chunked-planning-parallel.test.cjs",
|
|
"tests/ci-docs-guard-registry.test.cjs",
|
|
"tests/ci-rebase-check.test.cjs",
|
|
"tests/ci-test-scope.test.cjs",
|
|
"tests/cjs-command-router-adapter.test.cjs",
|
|
"tests/claude-md.test.cjs",
|
|
"tests/cline-install.test.cjs",
|
|
"tests/close-phase-todos-padded-resolves.test.cjs",
|
|
"tests/code-review-pipeline-regression.test.cjs",
|
|
"tests/code-review-tier3-files-override-scoping.test.cjs",
|
|
"tests/code-review.test.cjs",
|
|
"tests/codex-config-agents.test.cjs",
|
|
"tests/codex-config-hooks.test.cjs",
|
|
"tests/codex-config-install.test.cjs",
|
|
"tests/codex-config.test.cjs",
|
|
"tests/codex-inherit-smoke.test.cjs",
|
|
"tests/command-routing-hub.test.cjs",
|
|
"tests/commands.test.cjs",
|
|
"tests/commit-files-deletion.test.cjs",
|
|
"tests/commit-files-pathspec.test.cjs",
|
|
"tests/commonjs-marker.test.cjs",
|
|
"tests/compact-content-4139.test.cjs",
|
|
"tests/completion-ratio-scope-withholding.test.cjs",
|
|
"tests/config-defaults-runtime-exclusion.test.cjs",
|
|
"tests/config-get-default.test.cjs",
|
|
"tests/config-loader.test.cjs",
|
|
"tests/config-schema.property.test.cjs",
|
|
"tests/config.test.cjs",
|
|
"tests/copilot-install.test.cjs",
|
|
"tests/copilot-upgrades.test.cjs",
|
|
"tests/core-utils.test.cjs",
|
|
"tests/cursor-hook-workspace-roots.test.cjs",
|
|
"tests/cursor-hooks.test.cjs",
|
|
"tests/cursor-subagent-isolation.test.cjs",
|
|
"tests/dispatch-identity.test.cjs",
|
|
"tests/dispatcher.test.cjs",
|
|
"tests/drift-detection.test.cjs",
|
|
"tests/effort-surface-axis.test.cjs",
|
|
"tests/effort-sync-installed-runtime.test.cjs",
|
|
"tests/emitted-ack-trailer.test.cjs",
|
|
"tests/emitted-attribution.test.cjs",
|
|
"tests/emitted-provenance.test.cjs",
|
|
"tests/ensure-runtime-build.test.cjs",
|
|
"tests/eslint-rules.test.cjs",
|
|
"tests/execute-phase-decimal-arithmetic.test.cjs",
|
|
"tests/execute-phase-worktree-guard.test.cjs",
|
|
"tests/execute-plan-update-codebase-map-diff-base.test.cjs",
|
|
"tests/execute-wave-post-gate-pipeline-e2e.test.cjs",
|
|
"tests/executed-plan.test.cjs",
|
|
"tests/executor-mvp-tdd-section.test.cjs",
|
|
"tests/external-descriptor-confinement.test.cjs",
|
|
"tests/failing-direction.test.cjs",
|
|
"tests/fallow-runner.test.cjs",
|
|
"tests/faulty-deps.test.cjs",
|
|
"tests/feat-2483-review-claude-mds-guard.test.cjs",
|
|
"tests/features-index-gate.test.cjs",
|
|
"tests/frontmatter.test.cjs",
|
|
"tests/gap-checker.property.test.cjs",
|
|
"tests/gemini-runtime-removed.test.cjs",
|
|
"tests/gen-context-index.test.cjs",
|
|
"tests/gen-health-docs.test.cjs",
|
|
"tests/gen-section-manifest.test.cjs",
|
|
"tests/git-base-branch.test.cjs",
|
|
"tests/golden-install-tree.test.cjs",
|
|
"tests/graphify-graph-path.test.cjs",
|
|
"tests/graphify-visualization.test.cjs",
|
|
"tests/graphify.test.cjs",
|
|
"tests/gsd-agent-isolation-guard.test.cjs",
|
|
"tests/gsd-check-update-worker-atomic-cache.test.cjs",
|
|
"tests/gsd-check-update-worker-platform-gate.test.cjs",
|
|
"tests/gsd-mcp-server-bin.test.cjs",
|
|
"tests/gsd-statusline.test.cjs",
|
|
"tests/gsd-validate-commit-crash-policy.test.cjs",
|
|
"tests/gsd-validate-commit-sigpipe.test.cjs",
|
|
"tests/gsd-write-guard.test.cjs",
|
|
"tests/health-diagnostic-rules/config-validation.test.cjs",
|
|
"tests/health-diagnostic-rules/worktree-health.test.cjs",
|
|
"tests/health-diagnostic.test.cjs",
|
|
"tests/helpers-cleanup.test.cjs",
|
|
"tests/helpers-process-isolation.test.cjs",
|
|
"tests/hermes-skills-migration.test.cjs",
|
|
"tests/hooks-commonjs-marker.test.cjs",
|
|
"tests/hooks-crash-policy.test.cjs",
|
|
"tests/hooks-opt-in.test.cjs",
|
|
"tests/host-integration.test.cjs",
|
|
"tests/init-manager.test.cjs",
|
|
"tests/init.test.cjs",
|
|
"tests/install-minimal-hooks.test.cjs",
|
|
"tests/install-nested-layout.test.cjs",
|
|
"tests/install-path-detection.test.cjs",
|
|
"tests/install-regressions.test.cjs",
|
|
"tests/install-runtime-artifacts.test.cjs",
|
|
"tests/install-write-confinement.test.cjs",
|
|
"tests/install.test.cjs",
|
|
"tests/installer-migration-antigravity-retire-confighome-artifacts.test.cjs",
|
|
"tests/installer-migration-config-root-marker.test.cjs",
|
|
"tests/installer-migration-pi-retire-hooks-dir.test.cjs",
|
|
"tests/installer-migration-prune-stale-pristine.test.cjs",
|
|
"tests/installer-migration-rename-gsd-core.test.cjs",
|
|
"tests/installer-migrations.test.cjs",
|
|
"tests/intel.test.cjs",
|
|
"tests/inventory-nested-families.test.cjs",
|
|
"tests/io.test.cjs",
|
|
"tests/isolation-sentinel.test.cjs",
|
|
"tests/kilo-upgrades.test.cjs",
|
|
"tests/kimi-agent-converter.test.cjs",
|
|
"tests/kimi-upgrades.test.cjs",
|
|
"tests/kimi-variant-disambiguation.test.cjs",
|
|
"tests/lint-workflow-shellcheck-fetch.test.cjs",
|
|
"tests/live-config-guard.test.cjs",
|
|
"tests/lockfile-cve-audit.test.cjs",
|
|
"tests/locking-bugs-1909-1916-1925-1927.test.cjs",
|
|
"tests/loop-hooks-empty-points-e2e.test.cjs",
|
|
"tests/loop-hooks-ship-pre-e2e.test.cjs",
|
|
"tests/loop-hooks-verify-post-e2e.test.cjs",
|
|
"tests/mcp-catalog.property.test.cjs",
|
|
"tests/mcp-catalog.test.cjs",
|
|
"tests/milestone-archive.test.cjs",
|
|
"tests/milestone-window-single-owner.test.cjs",
|
|
"tests/model-resolver.test.cjs",
|
|
"tests/mutation-workflow-base-ref.test.cjs",
|
|
"tests/new-milestone-clear-phases.test.cjs",
|
|
"tests/no-bare-npm-exec.rule.test.cjs",
|
|
"tests/no-exact-case-env-access.rule.test.cjs",
|
|
"tests/no-path-literal-in-assert.rule.test.cjs",
|
|
"tests/no-pending-3212-markers.test.cjs",
|
|
"tests/no-phantom-issue-refs.test.cjs",
|
|
"tests/no-posix-mode-bit-assert.rule.test.cjs",
|
|
"tests/no-private-binary-resolution.rule.test.cjs",
|
|
"tests/no-unbounded-dirname-walk.rule.test.cjs",
|
|
"tests/no-unbounded-spawn.test.cjs",
|
|
"tests/no-unguarded-nonportable-exec.rule.test.cjs",
|
|
"tests/npm-audit-baseline.test.cjs",
|
|
"tests/npm-integrity-gate.test.cjs",
|
|
"tests/nsegment-phase-grammar.test.cjs",
|
|
"tests/onboard-command.test.cjs",
|
|
"tests/opencode-command-dir-plural.test.cjs",
|
|
"tests/opencode-plugin-adapter.test.cjs",
|
|
"tests/overlay-repo-helpers.test.cjs",
|
|
"tests/packaging-shipped-scripts-require-only-shipped.test.cjs",
|
|
"tests/path-replacement.test.cjs",
|
|
"tests/pause-work-context-detection.test.cjs",
|
|
"tests/pause-work-improvements.test.cjs",
|
|
"tests/perf-317-context-monitor-fs.test.cjs",
|
|
"tests/phase-completion-single-owner.test.cjs",
|
|
"tests/phase-estimation.test.cjs",
|
|
"tests/phase-locator.test.cjs",
|
|
"tests/phase.test.cjs",
|
|
"tests/phase6-capstone-conformance.test.cjs",
|
|
"tests/pi-config-dir-env-override.test.cjs",
|
|
"tests/plan-count-single-owner.test.cjs",
|
|
"tests/plan-phase-stall-detection.test.cjs",
|
|
"tests/plan-pre-hook-e2e.test.cjs",
|
|
"tests/plan-review-convergence.test.cjs",
|
|
"tests/planning-inspect.test.cjs",
|
|
"tests/planning-inspect.unit.test.cjs",
|
|
"tests/planning-lock-mkdir-failure-1884.test.cjs",
|
|
"tests/planning-prompt-drift.test.cjs",
|
|
"tests/planning-snapshot.test.cjs",
|
|
"tests/planning-workspace.test.cjs",
|
|
"tests/platform-conformance-tier.test.cjs",
|
|
"tests/platform-guard.unit.test.cjs",
|
|
"tests/plugin-manifest.test.cjs",
|
|
"tests/policy-160-route0-resume.test.cjs",
|
|
"tests/policy-shell-pinning.test.cjs",
|
|
"tests/portability-rule-disable-ban.test.cjs",
|
|
"tests/pr-branch-planning-filter.test.cjs",
|
|
"tests/precommit-alias-drift-hook.test.cjs",
|
|
"tests/prepush-enterprise-email-hook.test.cjs",
|
|
"tests/process-seam.test.cjs",
|
|
"tests/profile-output.test.cjs",
|
|
"tests/profile-pipeline.test.cjs",
|
|
"tests/prohibition-enforcement.test.cjs",
|
|
"tests/project-root.test.cjs",
|
|
"tests/quick-batch.test.cjs",
|
|
"tests/quick-branching.test.cjs",
|
|
"tests/quick-research.test.cjs",
|
|
"tests/quick-review-scope-tip-bound.test.cjs",
|
|
"tests/read-guard.test.cjs",
|
|
"tests/reapply-verify-hunks.test.cjs",
|
|
"tests/repo-layout.test.cjs",
|
|
"tests/representative-corpus.test.cjs",
|
|
"tests/require-fs-op-fallback.rule.test.cjs",
|
|
"tests/require-full-tmpdir-triad.rule.test.cjs",
|
|
"tests/require-userprofile-with-home.rule.test.cjs",
|
|
"tests/response-language-coverage.test.cjs",
|
|
"tests/retired-artifact-cleanup.test.cjs",
|
|
"tests/review-build-prompt-optional-sections.test.cjs",
|
|
"tests/review-default-reviewers-config.test.cjs",
|
|
"tests/review-lane-runner.test.cjs",
|
|
"tests/review-lane-windows-spawn-resolution.test.cjs",
|
|
"tests/review-model-config.test.cjs",
|
|
"tests/review-parallel-lanes.test.cjs",
|
|
"tests/review-plan-coverage-manifest.test.cjs",
|
|
"tests/reviewer-manifest-body.test.cjs",
|
|
"tests/reviewer-step-dispatch.test.cjs",
|
|
"tests/revision-remediation-binding.test.cjs",
|
|
"tests/roadmap-parser.test.cjs",
|
|
"tests/roadmap.test.cjs",
|
|
"tests/run-tests-harness.test.cjs",
|
|
"tests/run-tests-temp-root.test.cjs",
|
|
"tests/run-with-timeout.test.cjs",
|
|
"tests/runtime-artifact-layout-surface.test.cjs",
|
|
"tests/runtime-artifact-layout.test.cjs",
|
|
"tests/runtime-converters.test.cjs",
|
|
"tests/runtime-homes-descriptor-drive.test.cjs",
|
|
"tests/runtime-identity.test.cjs",
|
|
"tests/runtime-launcher-parity.test.cjs",
|
|
"tests/security.test.cjs",
|
|
"tests/settings-jsonc.test.cjs",
|
|
"tests/sh-hook-paths.test.cjs",
|
|
"tests/shared-hooks-dir-resolution.test.cjs",
|
|
"tests/shell-command-projection-dispatch.test.cjs",
|
|
"tests/shell-command-projection-path-sep.test.cjs",
|
|
"tests/ship-notes-wedged-pr.test.cjs",
|
|
"tests/skill-manifest.test.cjs",
|
|
"tests/slug-derivation-drift-guard.test.cjs",
|
|
"tests/state-todos-render.test.cjs",
|
|
"tests/state.test.cjs",
|
|
"tests/teams-status.test.cjs",
|
|
"tests/todos-workstream-scope.test.cjs",
|
|
"tests/unreachable-guard-drift.test.cjs",
|
|
"tests/unreachable-shell-guard.test.cjs",
|
|
"tests/unusable-input.test.cjs",
|
|
"tests/update-custom-backup.test.cjs",
|
|
"tests/user-artifact-staging.test.cjs",
|
|
"tests/verification-status.test.cjs",
|
|
"tests/verify-archive-dirs-live-path.test.cjs",
|
|
"tests/verify-command-grounding.test.cjs",
|
|
"tests/verify.test.cjs",
|
|
"tests/windsurf-hooks-bridge.test.cjs",
|
|
"tests/workflow-guard.test.cjs",
|
|
"tests/workflow-shell-pinning.test.cjs",
|
|
"tests/workstream-inventory.test.cjs",
|
|
"tests/workstream-scoped-paths.test.cjs",
|
|
"tests/workstream.test.cjs",
|
|
"tests/worktree-cleanup.test.cjs",
|
|
"tests/worktree-safety.test.cjs",
|
|
"tests/worktree.test.cjs",
|
|
],
|
|
};
|