diff --git a/product-source/hololake-platform/.github/HOOKS.md b/product-source/hololake-platform/.github/HOOKS.md index 55d2cee..6a2d870 100644 --- a/product-source/hololake-platform/.github/HOOKS.md +++ b/product-source/hololake-platform/.github/HOOKS.md @@ -5,13 +5,18 @@ surfaces; GLS-0844 (GHNQG) is the quality authority. ## Installation -`pnpm install` runs the `prepare` script and installs the hooks into -`.git/hooks`. To reinstall them, run: +`pnpm install` runs the `prepare` script and binds Git's local hook path to +this product's `.husky/` directory. This also works when the product is nested +inside a larger Git worktree. To restore the binding without installing +dependencies, run: ```bash -pnpm exec husky +bash scripts/install-guanghu-native-hooks.sh ``` +The hook itself enters the product root before running any protocol command, +so its behavior does not depend on the caller's current directory. + ## Native policy - Commit on `main` or in a detached verification worktree intended for direct diff --git a/product-source/hololake-platform/.husky/pre-commit b/product-source/hololake-platform/.husky/pre-commit index 1d9bd04..9d10a4a 100755 --- a/product-source/hololake-platform/.husky/pre-commit +++ b/product-source/hololake-platform/.husky/pre-commit @@ -1,5 +1,8 @@ #!/usr/bin/env sh set -eu +hook_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) +cd "$hook_dir/.." + bash scripts/test-guanghu-native-authority.sh node scripts/validate-guanghu-native-profile.mjs diff --git a/product-source/hololake-platform/.husky/pre-push b/product-source/hololake-platform/.husky/pre-push index 6cf79a4..d246d11 100755 --- a/product-source/hololake-platform/.husky/pre-push +++ b/product-source/hololake-platform/.husky/pre-push @@ -1,6 +1,9 @@ #!/usr/bin/env sh set -eu +hook_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) +cd "$hook_dir/.." + if [ -t 0 ]; then push_input="" else diff --git a/product-source/hololake-platform/package.json b/product-source/hololake-platform/package.json index d0d869e..7e5561a 100644 --- a/product-source/hololake-platform/package.json +++ b/product-source/hololake-platform/package.json @@ -42,7 +42,7 @@ "package:internal:windows": "HOLOLAKE_DISTRIBUTION=personal HOLOLAKE_SOURCE_REPOSITORY_ID=REPO-008 HOLOLAKE_SOURCE_CHANNEL_ID=HLP-CHANNEL-0001 pnpm guard:deployment-source && ./scripts/build-internal-release.sh windows", "package:team:macos": "HOLOLAKE_DISTRIBUTION=team HOLOLAKE_SOURCE_REPOSITORY_ID=REPO-008 HOLOLAKE_SOURCE_CHANNEL_ID=HLP-CHANNEL-0001 pnpm guard:deployment-source && HOLOLAKE_TAURI_CONFIG=src-tauri/tauri.team.conf.json HOLOLAKE_APP_NAME='HoloLake Lighthouse Team Beta 0.2.0' HOLOLAKE_INSTALLER_BASENAME='HoloLake-Lighthouse-{version}-Team-Beta-Mac-aarch64' ./scripts/build-internal-release.sh macos", "package:team:windows": "HOLOLAKE_DISTRIBUTION=team HOLOLAKE_SOURCE_REPOSITORY_ID=REPO-008 HOLOLAKE_SOURCE_CHANNEL_ID=HLP-CHANNEL-0001 pnpm guard:deployment-source && HOLOLAKE_TAURI_CONFIG=src-tauri/tauri.team.conf.json HOLOLAKE_INSTALLER_BASENAME='HoloLake-Era-{version}-Team-Foundation-Windows-x64-setup' ./scripts/build-internal-release.sh windows", - "prepare": "husky" + "prepare": "bash scripts/install-guanghu-native-hooks.sh" }, "dependencies": { "@anthropic-ai/sdk": "^0.78.0", diff --git a/product-source/hololake-platform/scripts/install-guanghu-native-hooks.sh b/product-source/hololake-platform/scripts/install-guanghu-native-hooks.sh new file mode 100755 index 0000000..7bdbbaa --- /dev/null +++ b/product-source/hololake-platform/scripts/install-guanghu-native-hooks.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env sh +set -eu + +product_root=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd) +git_root=$(git -C "$product_root" rev-parse --show-toplevel 2>/dev/null || true) + +if [ -z "$git_root" ]; then + echo "GHNQG_FAIL_0 gate=automatic_protocol_bindings reason=git_root_missing" >&2 + exit 1 +fi + +product_prefix=$(git -C "$product_root" rev-parse --show-prefix) +hooks_path="${product_prefix}.husky" + +git -C "$git_root" config --local core.hooksPath "$hooks_path" +chmod +x "$product_root/.husky/pre-commit" "$product_root/.husky/pre-push" + +configured=$(git -C "$git_root" config --local --get core.hooksPath) +if [ "$configured" != "$hooks_path" ]; then + echo "GHNQG_FAIL_0 gate=automatic_protocol_bindings reason=hooks_path_mismatch" >&2 + exit 1 +fi + +echo "GHNQG_HOOKS_ACTIVE path=$hooks_path" diff --git a/product-source/hololake-platform/scripts/test-guanghu-native-authority.sh b/product-source/hololake-platform/scripts/test-guanghu-native-authority.sh index 2f15809..d2d8e47 100755 --- a/product-source/hololake-platform/scripts/test-guanghu-native-authority.sh +++ b/product-source/hololake-platform/scripts/test-guanghu-native-authority.sh @@ -10,6 +10,7 @@ active_authority_surfaces=( ".github/workflows/ci.yml" ".github/workflows/README.md" ".husky/pre-push" + "scripts/install-guanghu-native-hooks.sh" "scripts/run-hololake-native-quality-gate.sh" ".claude/settings.local.json" ".chunk/config.json" @@ -47,6 +48,10 @@ if grep -Ein \ fi grep -Fq 'GLS-0844' "${repository_root}/AGENTS.md" +grep -Fq 'install-guanghu-native-hooks.sh' "${repository_root}/package.json" +grep -Fq 'core.hooksPath' "${repository_root}/scripts/install-guanghu-native-hooks.sh" +grep -Fq 'cd "$hook_dir/.."' "${repository_root}/.husky/pre-commit" +grep -Fq 'cd "$hook_dir/.."' "${repository_root}/.husky/pre-push" grep -Fq 'GHNQG_PASS_100' "${repository_root}/.husky/pre-push" grep -Fq 'run-hololake-native-quality-gate.sh' "${repository_root}/.husky/pre-push" grep -Fq 'run-hololake-native-quality-gate.sh' "${repository_root}/.github/workflows/ci.yml" diff --git a/product-source/hololake-platform/scripts/validate-guanghu-native-profile.mjs b/product-source/hololake-platform/scripts/validate-guanghu-native-profile.mjs index 0062399..bf6945a 100644 --- a/product-source/hololake-platform/scripts/validate-guanghu-native-profile.mjs +++ b/product-source/hololake-platform/scripts/validate-guanghu-native-profile.mjs @@ -48,6 +48,7 @@ for (const required of [ } const packageJson = JSON.parse(source('package.json')) +requireTruth(packageJson.scripts.prepare.includes('install-guanghu-native-hooks.sh'), 'trigger_hook_install') requireTruth(packageJson.scripts.predev === 'pnpm test:native-authority', 'trigger_predev') requireTruth(packageJson.scripts.pretest === 'pnpm test:native-authority', 'trigger_pretest') requireTruth( @@ -56,11 +57,14 @@ requireTruth( 'trigger_prebuild', ) requireTruth(source('.husky/pre-commit').includes('test-guanghu-native-authority.sh'), 'trigger_precommit') +requireTruth(source('.husky/pre-commit').includes('cd "$hook_dir/.."'), 'trigger_precommit_product_root') requireTruth( source('.husky/pre-push').includes('test:native-authority') || source('.husky/pre-push').includes('run-hololake-native-quality-gate.sh'), 'trigger_prepush', ) +requireTruth(source('.husky/pre-push').includes('cd "$hook_dir/.."'), 'trigger_prepush_product_root') +requireTruth(source('scripts/install-guanghu-native-hooks.sh').includes('core.hooksPath'), 'trigger_hooks_path') requireTruth(source('.github/workflows/ci.yml').includes('test:native-authority'), 'trigger_ci') requireTruth( source('.github/workflows/ci.yml').includes('run-hololake-native-quality-gate.sh'),