From e59d960f27d8c0bf85238a7803a6b30dfd626d14 Mon Sep 17 00:00:00 2001 From: Codex Test Date: Tue, 17 Mar 2026 07:04:36 +1100 Subject: [PATCH 1/5] fix(hooks): cache staged validation --- .githooks/README.md | 6 + .githooks/install.sh | 67 ++-- .githooks/pre-commit | 448 +++++++++++++--------- .githooks/script-index.md | 2 +- contribute/CONTRIBUTING/GIT-HOOKS.md | 2 + docs-guide/catalog/scripts-catalog.mdx | 4 +- lpd | 39 +- tasks/reports/script-classifications.json | 40 +- tests/README.md | 8 +- tests/WHEN-TESTS-RUN.md | 3 +- tests/package.json | 1 + tests/run-all.js | 67 +++- tests/script-index.md | 1 + tests/unit/precommit-staged-cache.test.js | 208 ++++++++++ tools/lib/precommit-staged-cache.js | 234 +++++++++++ tools/lib/script-index.md | 1 + 16 files changed, 872 insertions(+), 259 deletions(-) create mode 100644 tests/unit/precommit-staged-cache.test.js create mode 100644 tools/lib/precommit-staged-cache.js diff --git a/.githooks/README.md b/.githooks/README.md index 7c77879b5..38de44663 100644 --- a/.githooks/README.md +++ b/.githooks/README.md @@ -28,8 +28,14 @@ Owned concerns: - fast staged local/offline checks - structure + style + staged static test validations - staged generator sync for managed artifacts +- reuses cached pass results when the staged snapshot and hook/test inputs are unchanged - runtime budget enforcement (default: `<= 60s`) +Install behavior: + +- configures worktree-local `core.hooksPath=.githooks` +- runs hooks directly from tracked repo files instead of copying stale hook files into `.git/hooks` + Out-of-scope concerns: - browser sweeps diff --git a/.githooks/install.sh b/.githooks/install.sh index aafb17d65..1130429d8 100755 --- a/.githooks/install.sh +++ b/.githooks/install.sh @@ -3,54 +3,63 @@ # @category utility # @purpose tooling:dev-tools # @scope .githooks -# @owner docs +# @domain docs # @needs E-C6, F-C1 -# @purpose-statement Installs git hooks by setting core.hooksPath to .githooks/ +# @purpose-statement Installs git hooks by routing this worktree to .githooks via worktree-local core.hooksPath # @pipeline manual — developer tool # @usage bash .githooks/install.sh [flags] # Install git hooks -# Support both regular repos and worktrees -GIT_COMMON_DIR=$(git rev-parse --git-common-dir 2>/dev/null) -if [ -z "$GIT_COMMON_DIR" ] || [ "$GIT_COMMON_DIR" = "--git-common-dir" ]; then - GIT_COMMON_DIR=".git" -fi -HOOKS_DIR="$GIT_COMMON_DIR/hooks" -SOURCE_DIR=".githooks" +set -euo pipefail + +REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)" +SOURCE_DIR="$REPO_ROOT/.githooks" + +cd "$REPO_ROOT" -if [ ! -d "$HOOKS_DIR" ]; then - echo "Error: hooks directory not found at $HOOKS_DIR" +if ! git rev-parse --git-dir >/dev/null 2>&1; then + echo "Error: this command must run inside a git worktree." exit 1 fi if [ ! -d "$SOURCE_DIR" ]; then - echo "Error: .githooks directory not found. Are you in the repository root?" + echo "Error: .githooks directory not found at $SOURCE_DIR" + exit 1 +fi + +if [ ! -f "$SOURCE_DIR/pre-commit" ] || [ ! -f "$SOURCE_DIR/pre-push" ]; then + echo "Error: required hook entrypoints are missing from $SOURCE_DIR" exit 1 fi -echo "Installing git hooks..." +echo "Installing git hooks for this worktree..." -# Install pre-commit hook -if [ -f "$SOURCE_DIR/pre-commit" ]; then - cp "$SOURCE_DIR/pre-commit" "$HOOKS_DIR/pre-commit" - chmod +x "$HOOKS_DIR/pre-commit" - echo "✓ Installed pre-commit hook" -else - echo "✗ pre-commit hook not found in $SOURCE_DIR" +git config extensions.worktreeConfig true + +SHARED_HOOKS_PATH=$(git config --local --get-all core.hooksPath 2>/dev/null || true) +if [ -n "$SHARED_HOOKS_PATH" ]; then + git config --local --unset-all core.hooksPath || true + echo "✓ Cleared shared core.hooksPath override" fi -# Install pre-push hook -if [ -f "$SOURCE_DIR/pre-push" ]; then - cp "$SOURCE_DIR/pre-push" "$HOOKS_DIR/pre-push" - chmod +x "$HOOKS_DIR/pre-push" - echo "✓ Installed pre-push hook" -else - echo "✗ pre-push hook not found in $SOURCE_DIR" +git config --worktree core.hooksPath .githooks +chmod +x "$SOURCE_DIR/pre-commit" "$SOURCE_DIR/pre-push" + +RESOLVED_HOOKS_PATH=$(git config --worktree --path --get core.hooksPath 2>/dev/null || true) +if [ -z "$RESOLVED_HOOKS_PATH" ]; then + echo "Error: failed to resolve worktree-local core.hooksPath" + exit 1 fi +if [[ "$RESOLVED_HOOKS_PATH" != /* ]]; then + RESOLVED_HOOKS_PATH="$REPO_ROOT/$RESOLVED_HOOKS_PATH" +fi + +echo "✓ Using worktree-local core.hooksPath: $RESOLVED_HOOKS_PATH" +echo "✓ Hook entrypoints are executable" echo "" echo "Git hooks installed successfully!" echo "" -echo "The pre-commit hook will now check for style guide violations." -echo "The pre-push hook will enforce codex task contracts on codex/* branches." +echo "The pre-commit hook now runs directly from .githooks/pre-commit." +echo "The pre-push hook now runs directly from .githooks/pre-push." echo "See .githooks/README.md for details." diff --git a/.githooks/pre-commit b/.githooks/pre-commit index b5f49b5e6..c941867f3 100755 --- a/.githooks/pre-commit +++ b/.githooks/pre-commit @@ -3,7 +3,7 @@ # @category orchestrator # @purpose infrastructure:pipeline-orchestration # @scope .githooks -# @owner docs +# @domain docs # @needs R-R29 # @purpose-statement Pre-commit hook orchestrator — runs structural checks, unit tests, codex validation, and docs-index freshness check before allowing commit # @pipeline P1 (commit, hook entry point) @@ -12,14 +12,15 @@ # Checks for common violations before allowing commits # # To install this hook, run: -# cp .githooks/pre-commit .git/hooks/pre-commit -# chmod +x .git/hooks/pre-commit +# bash .githooks/install.sh +# # or: lpd hooks install # # Bypass flags (use sparingly): # SKIP_STRUCTURE_CHECK=1 - Skip root directory and snippets structure checks # SKIP_STYLE_CHECK=1 - Skip style guide compliance checks # SKIP_VERIFICATION=1 - Skip verification scripts # SKIP_TESTS=1 - Skip test suite +# DISABLE_PRECOMMIT_STAGED_CACHE=1 - Force rerun of the expensive staged validation suite # SKIP_ALL=1 - Skip all checks (use with extreme caution) # # Human-only override flags: @@ -43,6 +44,7 @@ SKIP_STRUCTURE_CHECK=${SKIP_STRUCTURE_CHECK:-0} SKIP_STYLE_CHECK=${SKIP_STYLE_CHECK:-0} SKIP_VERIFICATION=${SKIP_VERIFICATION:-0} SKIP_TESTS=${SKIP_TESTS:-0} +DISABLE_PRECOMMIT_STAGED_CACHE=${DISABLE_PRECOMMIT_STAGED_CACHE:-0} SKIP_ALL=${SKIP_ALL:-0} ALLOW_DELETIONS=${ALLOW_DELETIONS:-0} CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "") @@ -64,6 +66,78 @@ get_staged_docs_pages() { STAGED_DOCS_PAGES=$(get_staged_docs_pages) +PRECOMMIT_STAGED_CACHE_HIT=0 +PRECOMMIT_STAGED_CACHE_KEY="" +PRECOMMIT_STAGED_CACHE_INDEX_TREE="" +PRECOMMIT_STAGED_CACHE_FILE="" +PRECOMMIT_STAGED_CACHE_CREATED_AT="" + +can_use_precommit_staged_cache() { + if [ "$DISABLE_PRECOMMIT_STAGED_CACHE" = "1" ]; then + return 1 + fi + + if [ "$SKIP_VERIFICATION" = "1" ] || [ "$SKIP_TESTS" = "1" ]; then + return 1 + fi + + if ! command -v node &>/dev/null || [ ! -f "tools/lib/precommit-staged-cache.js" ]; then + return 1 + fi + + return 0 +} + +read_precommit_staged_cache() { + if ! can_use_precommit_staged_cache; then + return 1 + fi + + local output="" + output=$(node - "$PWD" <<'NODE' +const cache = require('./tools/lib/precommit-staged-cache'); +const repoRoot = process.argv[2]; + +try { + const result = cache.readCache({ repoRoot }); + process.stdout.write([ + result.hit ? '1' : '0', + result.key || '', + result.indexTree || '', + result.cacheFilePath || '', + result.entry?.createdAt || '' + ].join('\t')); +} catch (error) { + process.stderr.write(`${error.message}\n`); + process.exit(1); +} +NODE + ) || return 1 + + IFS=$'\t' read -r PRECOMMIT_STAGED_CACHE_HIT PRECOMMIT_STAGED_CACHE_KEY PRECOMMIT_STAGED_CACHE_INDEX_TREE PRECOMMIT_STAGED_CACHE_FILE PRECOMMIT_STAGED_CACHE_CREATED_AT <<< "$output" + [ "$PRECOMMIT_STAGED_CACHE_HIT" = "1" ] +} + +write_precommit_staged_cache() { + if ! can_use_precommit_staged_cache; then + return 1 + fi + + node - "$PWD" "$CURRENT_BRANCH" <<'NODE' +const cache = require('./tools/lib/precommit-staged-cache'); +const repoRoot = process.argv[2]; +const branch = process.argv[3]; + +cache.writeCache({ + repoRoot, + metadata: { + branch, + source: 'pre-commit' + } +}); +NODE +} + get_forbidden_staged_generated_outputs() { if ! command -v node &>/dev/null || [ ! -f "tools/lib/generated-artifacts.js" ]; then return 0 @@ -823,35 +897,6 @@ else fi fi -# Run verification scripts (legacy path disabled for faster staged-only hooks) -if [ "$SKIP_VERIFICATION" = "1" ]; then - echo -e "${YELLOW}⚠️ Verification scripts bypassed (SKIP_VERIFICATION=1)${NC}" -else - echo "" - echo -e "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" - echo -e "${YELLOW}Skipping legacy verify.sh in pre-commit (staged-only fast mode).${NC}" - echo -e "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" - FORBIDDEN_GENERATED_OUTPUTS=$(get_forbidden_staged_generated_outputs) - if [ -n "$FORBIDDEN_GENERATED_OUTPUTS" ]; then - echo -e "${RED}Forbidden staged ephemeral generated outputs detected:${NC}" - while IFS= read -r path; do - [ -z "$path" ] && continue - echo " - $path" - WARNINGS+=("❌ Forbidden staged ephemeral generated output: $path") - VIOLATIONS=$((VIOLATIONS + 1)) - done <<< "$FORBIDDEN_GENERATED_OUTPUTS" - echo "Move local-only reports to an ignored scratch path instead of committing them." - exit 1 - fi - echo "Checking generated file banners..." - if node tools/scripts/enforce-generated-file-banners.js --check --staged; then - echo -e "${GREEN}✓ Generated file banner check passed${NC}" - else - echo "Generated file banners missing or incorrect. Run: node tools/scripts/enforce-generated-file-banners.js --write" - exit 1 - fi -fi - run_node_check() { local label="$1" local failure_message="$2" @@ -954,7 +999,7 @@ const tags = [ '@category', '@purpose', '@scope', - '@owner', + '@domain', '@needs', '@purpose-statement', '@pipeline', @@ -999,7 +1044,7 @@ const tags = [ '@category', '@purpose', '@scope', - '@owner', + '@domain', '@needs', '@purpose-statement', '@pipeline', @@ -1077,13 +1122,12 @@ NODE print_governance_dependency_error() { echo "" - echo "✗ Governance auto-repair is unavailable in this checkout." + echo "✗ Governance auto-repair tooling is unavailable or outdated in this checkout." echo "" - echo " REPAIR-00a is not merged here yet." echo " Expected tools/scripts/validators/governance/audit-script-inventory.js" - echo " to support --staged-only and --quiet." + echo " with --staged-only and --quiet support, plus the matching governance helpers." echo "" - echo " Update from docs-v2 after REPAIR-00a merges, then retry." + echo " Sync the checkout to the current governance baseline and ensure repo dependencies are installed." echo " Run 'cd tools && npm run repair:governance -- --dry-run' for more detail." echo " To skip: SKIP_VERIFICATION=1 git commit -m 'message'" echo "" @@ -1295,170 +1339,228 @@ run_governance_auto_repair() { ) } -# Component governance checks -if [ "$SKIP_TESTS" != "1" ]; then - STAGED_COMPONENTS=$(git diff --cached --name-only --diff-filter=ACM -- snippets/components | grep -E '\.jsx$' | grep -v '/_archive/' || true) - if [ -n "$STAGED_COMPONENTS" ]; then - run_node_check \ - "Running component JSDoc validation (staged)..." \ - "❌ Component JSDoc validation failed" \ - tools/scripts/validators/components/check-component-docs.js --staged - - run_node_check \ - "Running component styling validation (staged)..." \ - "❌ Component styling validation failed" \ - tools/scripts/validators/components/check-component-css.js --staged - - if [ $VIOLATIONS -eq 0 ]; then - echo -e "${YELLOW}Repairing derived component metadata...${NC}" - if node tools/scripts/remediators/components/repair-component-metadata.js --staged --fix 2>&1; then - echo "$STAGED_COMPONENTS" | xargs git add 2>/dev/null - echo -e "${GREEN}✓ Component metadata repaired${NC}" - else - VIOLATIONS=$((VIOLATIONS + 1)) - WARNINGS+=("❌ Component metadata has NEEDS_HUMAN errors - inspect repair-component-metadata output") - echo -e "${RED}❌ Component metadata repair found issues requiring human attention${NC}" - fi - fi - - if [ $VIOLATIONS -eq 0 ]; then - echo -e "${YELLOW}Regenerating component registry...${NC}" - if node tools/scripts/generate-component-registry.js 2>&1; then - git add docs-guide/component-registry.json docs-guide/component-registry-schema.json 2>/dev/null - echo -e "${GREEN}✓ Component registry regenerated${NC}" - else - VIOLATIONS=$((VIOLATIONS + 1)) - WARNINGS+=("❌ Component registry generation failed") - echo -e "${RED}❌ Component registry generation failed${NC}" - fi - fi - - if [ $VIOLATIONS -eq 0 ]; then - echo -e "${YELLOW}Regenerating component usage map...${NC}" - if node tools/scripts/scan-component-imports.js 2>&1; then - git add docs-guide/component-usage-map.json 2>/dev/null - echo -e "${GREEN}✓ Component usage map regenerated${NC}" - else - VIOLATIONS=$((VIOLATIONS + 1)) - WARNINGS+=("❌ Component usage map generation failed") - echo -e "${RED}❌ Component usage map generation failed${NC}" - fi - fi +RUN_PRECOMMIT_EXPENSIVE_SUITE=1 - if [ $VIOLATIONS -eq 0 ] && [ -f "tools/scripts/generate-docs-guide-components-index.js" ]; then - echo -e "${YELLOW}Regenerating components catalog...${NC}" - if node tools/scripts/generate-docs-guide-components-index.js --fix 2>&1; then - git add docs-guide/catalog/components-catalog.mdx 2>/dev/null - echo -e "${GREEN}✓ Components catalog regenerated${NC}" - else - VIOLATIONS=$((VIOLATIONS + 1)) - WARNINGS+=("❌ Components catalog generation failed") - echo -e "${RED}❌ Components catalog generation failed${NC}" - fi - fi +if [ $VIOLATIONS -gt 0 ]; then + echo "" + echo -e "${YELLOW}Skipping expensive staged validation because blocking pre-check violations already exist.${NC}" + RUN_PRECOMMIT_EXPENSIVE_SUITE=0 +elif read_precommit_staged_cache; then + echo "" + echo -e "${GREEN}✓ Reusing cached staged validation for unchanged staged content${NC}" + if [ -n "$PRECOMMIT_STAGED_CACHE_CREATED_AT" ]; then + echo " Cached at: $PRECOMMIT_STAGED_CACHE_CREATED_AT" fi + RUN_PRECOMMIT_EXPENSIVE_SUITE=0 fi -# Run test suite (fast mode for pre-commit) -if [ "$SKIP_TESTS" = "1" ]; then - echo -e "${YELLOW}⚠️ Test suite bypassed (SKIP_TESTS=1)${NC}" -else - echo "" - echo -e "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" - echo -e "${YELLOW}Running test suite (staged files only)...${NC}" - if [ -f "tests/run-all.js" ] && command -v node &>/dev/null; then - if [ -d "tools/node_modules" ]; then - export NODE_PATH="$(pwd)/tools/node_modules:${NODE_PATH:-}" - elif [ -d "tests/node_modules" ]; then - export NODE_PATH="$(pwd)/tests/node_modules:${NODE_PATH:-}" - else - echo -e "${YELLOW}⚠️ Dependencies not installed. Run 'cd tools && npm install' or 'cd tests && npm install' to enable tests${NC}" +if [ "$RUN_PRECOMMIT_EXPENSIVE_SUITE" = "1" ]; then + # Run verification scripts (legacy path disabled for faster staged-only hooks) + if [ "$SKIP_VERIFICATION" = "1" ]; then + echo -e "${YELLOW}⚠️ Verification scripts bypassed (SKIP_VERIFICATION=1)${NC}" + else + echo "" + echo -e "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e "${YELLOW}Skipping legacy verify.sh in pre-commit (staged-only fast mode).${NC}" + echo -e "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + FORBIDDEN_GENERATED_OUTPUTS=$(get_forbidden_staged_generated_outputs) + if [ -n "$FORBIDDEN_GENERATED_OUTPUTS" ]; then + echo -e "${RED}Forbidden staged ephemeral generated outputs detected:${NC}" + while IFS= read -r path; do + [ -z "$path" ] && continue + echo " - $path" + WARNINGS+=("❌ Forbidden staged ephemeral generated output: $path") + VIOLATIONS=$((VIOLATIONS + 1)) + done <<< "$FORBIDDEN_GENERATED_OUTPUTS" + echo "Move local-only reports to an ignored scratch path instead of committing them." + exit 1 fi - - if [ "$SKIP_VERIFICATION" != "1" ] && [ $VIOLATIONS -eq 0 ]; then - if ! run_governance_auto_repair; then - exit 1 - fi + echo "Checking generated file banners..." + if node tools/scripts/enforce-generated-file-banners.js --check --staged; then + echo -e "${GREEN}✓ Generated file banner check passed${NC}" + else + echo "Generated file banners missing or incorrect. Run: node tools/scripts/enforce-generated-file-banners.js --write" + exit 1 fi + fi - if [ -f "tools/scripts/generate-pages-index.js" ]; then + # Component governance checks + if [ "$SKIP_TESTS" != "1" ]; then + STAGED_COMPONENTS=$(git diff --cached --name-only --diff-filter=ACM -- snippets/components | grep -E '\.jsx$' | grep -v '/_archive/' || true) + if [ -n "$STAGED_COMPONENTS" ]; then run_node_check \ - "Running v2/pages index generation (staged changes)..." \ - "❌ v2/pages index generation failed - fix index sync issues" \ - tools/scripts/generate-pages-index.js --staged --write --stage - fi + "Running component JSDoc validation (staged)..." \ + "❌ Component JSDoc validation failed" \ + tools/scripts/validators/components/check-component-docs.js --staged - if [ -f "tools/scripts/remediators/content/repair-mdx-safe-markdown.js" ]; then run_node_check \ - "Running staged MDX-safe markdown auto-repair..." \ - "❌ MDX-safe markdown auto-repair failed - inspect repair-mdx-safe-markdown output" \ - tools/scripts/remediators/content/repair-mdx-safe-markdown.js --write --staged --stage - fi + "Running component styling validation (staged)..." \ + "❌ Component styling validation failed" \ + tools/scripts/validators/components/check-component-css.js --staged + + if [ $VIOLATIONS -eq 0 ]; then + echo -e "${YELLOW}Repairing derived component metadata...${NC}" + if node tools/scripts/remediators/components/repair-component-metadata.js --staged --fix 2>&1; then + echo "$STAGED_COMPONENTS" | xargs git add 2>/dev/null + echo -e "${GREEN}✓ Component metadata repaired${NC}" + else + VIOLATIONS=$((VIOLATIONS + 1)) + WARNINGS+=("❌ Component metadata has NEEDS_HUMAN errors - inspect repair-component-metadata output") + echo -e "${RED}❌ Component metadata repair found issues requiring human attention${NC}" + fi + fi - if [ -f "tools/scripts/validators/content/check-mdx-safe-markdown.js" ]; then - run_node_check \ - "Running staged MDX-safe markdown validation..." \ - "❌ MDX-safe markdown validation failed - inspect check-mdx-safe-markdown output" \ - tools/scripts/validators/content/check-mdx-safe-markdown.js --staged - fi + if [ $VIOLATIONS -eq 0 ]; then + echo -e "${YELLOW}Regenerating component registry...${NC}" + if node tools/scripts/generate-component-registry.js 2>&1; then + git add docs-guide/component-registry.json docs-guide/component-registry-schema.json 2>/dev/null + echo -e "${GREEN}✓ Component registry regenerated${NC}" + else + VIOLATIONS=$((VIOLATIONS + 1)) + WARNINGS+=("❌ Component registry generation failed") + echo -e "${RED}❌ Component registry generation failed${NC}" + fi + fi - if [ -f "tools/scripts/generate-docs-index.js" ]; then - if should_check_generated_artifact "docs-index.json"; then - echo -e "${YELLOW}Checking generated artifact freshness...${NC}" - GENERATED_ARTIFACT_SUMMARY=$(format_generated_artifact_message "docs-index.json" "summary") - DOCS_INDEX_ARGS="--staged" - if echo "$STAGED_FILES_SNAPSHOT_ALL" | grep -Eq '^docs\.json$'; then - DOCS_INDEX_ARGS="" + if [ $VIOLATIONS -eq 0 ]; then + echo -e "${YELLOW}Regenerating component usage map...${NC}" + if node tools/scripts/scan-component-imports.js 2>&1; then + git add docs-guide/component-usage-map.json 2>/dev/null + echo -e "${GREEN}✓ Component usage map regenerated${NC}" + else + VIOLATIONS=$((VIOLATIONS + 1)) + WARNINGS+=("❌ Component usage map generation failed") + echo -e "${RED}❌ Component usage map generation failed${NC}" fi - if node tools/scripts/generate-docs-index.js --check $DOCS_INDEX_ARGS >/dev/null 2>&1; then - echo -e "${GREEN}✓ ${GENERATED_ARTIFACT_SUMMARY} is up to date${NC}" + fi + + if [ $VIOLATIONS -eq 0 ] && [ -f "tools/scripts/generate-docs-guide-components-index.js" ]; then + echo -e "${YELLOW}Regenerating components catalog...${NC}" + if node tools/scripts/generate-docs-guide-components-index.js --fix 2>&1; then + git add docs-guide/catalog/components-catalog.mdx 2>/dev/null + echo -e "${GREEN}✓ Components catalog regenerated${NC}" else VIOLATIONS=$((VIOLATIONS + 1)) - GENERATED_ARTIFACT_GENERATOR=$(format_generated_artifact_message "docs-index.json" "generator") - WARNINGS+=("❌ Generated artifact freshness issue: docs-index.json is stale. Run: ${GENERATED_ARTIFACT_GENERATOR}") - echo -e "${RED}❌ ${GENERATED_ARTIFACT_SUMMARY} is stale${NC}" - echo " Source files changed within its declared manifest scope." - echo " Remediation: ${GENERATED_ARTIFACT_GENERATOR}" - exit 1 + WARNINGS+=("❌ Components catalog generation failed") + echo -e "${RED}❌ Components catalog generation failed${NC}" fi - else - echo -e "${GREEN}✓ No manifest-declared docs-index sources staged, skipping docs-index freshness check${NC}" fi fi + fi - if [ -f "tools/scripts/remediators/content/sync-docs-paths.js" ]; then - run_node_check \ - "Running staged docs path sync..." \ - "❌ Docs path sync failed - inspect sync-docs-paths output" \ - tools/scripts/remediators/content/sync-docs-paths.js --write --staged --stage - fi + # Run test suite (fast mode for pre-commit) + if [ "$SKIP_TESTS" = "1" ]; then + echo -e "${YELLOW}⚠️ Test suite bypassed (SKIP_TESTS=1)${NC}" + else + echo "" + echo -e "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e "${YELLOW}Running test suite (staged files only)...${NC}" + if [ -f "tests/run-all.js" ] && command -v node &>/dev/null; then + if [ -d "tools/node_modules" ]; then + export NODE_PATH="$(pwd)/tools/node_modules:${NODE_PATH:-}" + elif [ -d "tests/node_modules" ]; then + export NODE_PATH="$(pwd)/tests/node_modules:${NODE_PATH:-}" + else + echo -e "${YELLOW}⚠️ Dependencies not installed. Run 'cd tools && npm install' or 'cd tests && npm install' to enable tests${NC}" + fi + + if [ "$SKIP_VERIFICATION" != "1" ] && [ $VIOLATIONS -eq 0 ]; then + if ! run_governance_auto_repair; then + exit 1 + fi + fi + + if [ -f "tools/scripts/generate-pages-index.js" ]; then + run_node_check \ + "Running v2/pages index generation (staged changes)..." \ + "❌ v2/pages index generation failed - fix index sync issues" \ + tools/scripts/generate-pages-index.js --staged --write --stage + fi - run_node_check \ - "Running core staged test suite..." \ - "❌ Core staged test suite failed - see output above" \ - tests/run-all.js --staged --skip-browser + if [ -f "tools/scripts/remediators/content/repair-mdx-safe-markdown.js" ]; then + run_node_check \ + "Running staged MDX-safe markdown auto-repair..." \ + "❌ MDX-safe markdown auto-repair failed - inspect repair-mdx-safe-markdown output" \ + tools/scripts/remediators/content/repair-mdx-safe-markdown.js --write --staged --stage + fi - if [ -n "$STAGED_DOCS_PAGES" ]; then - if [ -f "tests/integration/v2-link-audit.js" ]; then + if [ -f "tools/scripts/validators/content/check-mdx-safe-markdown.js" ]; then run_node_check \ - "Running staged V2 link audit..." \ - "❌ Staged V2 link audit failed - see /tmp/livepeer-link-audit-precommit.md" \ - tests/integration/v2-link-audit.js --staged --strict --report /tmp/livepeer-link-audit-precommit.md + "Running staged MDX-safe markdown validation..." \ + "❌ MDX-safe markdown validation failed - inspect check-mdx-safe-markdown output" \ + tools/scripts/validators/content/check-mdx-safe-markdown.js --staged + fi + + if [ -f "tools/scripts/generate-docs-index.js" ]; then + if should_check_generated_artifact "docs-index.json"; then + echo -e "${YELLOW}Checking generated artifact freshness...${NC}" + GENERATED_ARTIFACT_SUMMARY=$(format_generated_artifact_message "docs-index.json" "summary") + DOCS_INDEX_ARGS="--staged" + if echo "$STAGED_FILES_SNAPSHOT_ALL" | grep -Eq '^docs\.json$'; then + DOCS_INDEX_ARGS="" + fi + if node tools/scripts/generate-docs-index.js --check $DOCS_INDEX_ARGS >/dev/null 2>&1; then + echo -e "${GREEN}✓ ${GENERATED_ARTIFACT_SUMMARY} is up to date${NC}" + else + VIOLATIONS=$((VIOLATIONS + 1)) + GENERATED_ARTIFACT_GENERATOR=$(format_generated_artifact_message "docs-index.json" "generator") + WARNINGS+=("❌ Generated artifact freshness issue: docs-index.json is stale. Run: ${GENERATED_ARTIFACT_GENERATOR}") + echo -e "${RED}❌ ${GENERATED_ARTIFACT_SUMMARY} is stale${NC}" + echo " Source files changed within its declared manifest scope." + echo " Remediation: ${GENERATED_ARTIFACT_GENERATOR}" + exit 1 + fi + else + echo -e "${GREEN}✓ No manifest-declared docs-index sources staged, skipping docs-index freshness check${NC}" + fi fi - if [ -f "tests/integration/v2-wcag-audit.js" ]; then + if [ -f "tools/scripts/remediators/content/sync-docs-paths.js" ]; then run_node_check \ - "Running staged V2 WCAG accessibility audit..." \ - "❌ Staged V2 WCAG accessibility audit failed - see /tmp/livepeer-wcag-audit-precommit.md" \ - tests/integration/v2-wcag-audit.js --staged --fix --stage --max-pages 10 --fail-impact serious --report /tmp/livepeer-wcag-audit-precommit.md --report-json /tmp/livepeer-wcag-audit-precommit.json + "Running staged docs path sync..." \ + "❌ Docs path sync failed - inspect sync-docs-paths output" \ + tools/scripts/remediators/content/sync-docs-paths.js --write --staged --stage + fi + + run_all_args=(tests/run-all.js --staged --skip-browser) + if [ "$SKIP_VERIFICATION" != "1" ]; then + run_all_args+=(--skip-mdx-safe-markdown-check --skip-pages-index --skip-script-docs) + fi + run_node_check \ + "Running core staged test suite..." \ + "❌ Core staged test suite failed - see output above" \ + "${run_all_args[@]}" + + if [ -n "$STAGED_DOCS_PAGES" ]; then + if [ -f "tests/integration/v2-link-audit.js" ]; then + run_node_check \ + "Running staged V2 link audit..." \ + "❌ Staged V2 link audit failed - see /tmp/livepeer-link-audit-precommit.md" \ + tests/integration/v2-link-audit.js --staged --strict --report /tmp/livepeer-link-audit-precommit.md + fi + + if [ -f "tests/integration/v2-wcag-audit.js" ]; then + run_node_check \ + "Running staged V2 WCAG accessibility audit..." \ + "❌ Staged V2 WCAG accessibility audit failed - see /tmp/livepeer-wcag-audit-precommit.md" \ + tests/integration/v2-wcag-audit.js --staged --fix --stage --max-pages 10 --fail-impact serious --report /tmp/livepeer-wcag-audit-precommit.md --report-json /tmp/livepeer-wcag-audit-precommit.json + fi + else + echo -e "${GREEN}✓ No staged docs pages, skipping link audit and WCAG audit${NC}" fi else - echo -e "${GREEN}✓ No staged docs pages, skipping link audit and WCAG audit${NC}" + echo -e "${YELLOW}⚠️ Test suite not available, skipping...${NC}" + fi + echo -e "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + fi + + if [ $VIOLATIONS -eq 0 ]; then + if write_precommit_staged_cache >/dev/null 2>&1; then + echo -e "${GREEN}✓ Cached staged validation results for reuse${NC}" + else + echo -e "${YELLOW}⚠️ Could not persist staged validation cache; future commits will rerun the expensive suite${NC}" fi - else - echo -e "${YELLOW}⚠️ Test suite not available, skipping...${NC}" fi - echo -e "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" fi # Report results diff --git a/.githooks/script-index.md b/.githooks/script-index.md index 70513d29c..930481146 100644 --- a/.githooks/script-index.md +++ b/.githooks/script-index.md @@ -5,7 +5,7 @@ | Script | Summary | Usage | Domain | |---|---|---|---| -| `.githooks/install.sh` | Installs git hooks by setting core.hooksPath to .githooks/ | `bash .githooks/install.sh [flags]` | docs | +| `.githooks/install.sh` | Installs git hooks by routing this worktree to .githooks via worktree-local core.hooksPath | `bash .githooks/install.sh [flags]` | docs | | `.githooks/pre-commit` | Pre-commit hook orchestrator — runs structural checks, unit tests, codex validation, and docs-index freshness check before allowing commit | `bash .githooks/pre-commit [flags]` | docs | | `.githooks/pre-commit-no-deletions` | Variant pre-commit hook that blocks file deletions (safety net for content preservation) | `bash .githooks/pre-commit-no-deletions [flags]` | docs | | `.githooks/pre-push` | Pre-push hook — blocks push if AI stash files present, codex locks stale, or task contract invalid | `bash .githooks/pre-push [flags]` | docs | diff --git a/contribute/CONTRIBUTING/GIT-HOOKS.md b/contribute/CONTRIBUTING/GIT-HOOKS.md index f84856425..c2c1bd043 100644 --- a/contribute/CONTRIBUTING/GIT-HOOKS.md +++ b/contribute/CONTRIBUTING/GIT-HOOKS.md @@ -22,6 +22,8 @@ lpd hooks status - fast staged local/offline checks only - structure/style/static checks + staged generator sync +- fail-fast when cheap blocking violations already exist +- reuses the expensive staged validation result when staged content and hook inputs are unchanged - enforces pre-commit runtime budget (default `<= 60s`) ### Pre-push (`.githooks/pre-push`) diff --git a/docs-guide/catalog/scripts-catalog.mdx b/docs-guide/catalog/scripts-catalog.mdx index e6c3cfc9d..7ecefca8a 100644 --- a/docs-guide/catalog/scripts-catalog.mdx +++ b/docs-guide/catalog/scripts-catalog.mdx @@ -24,7 +24,7 @@ Run command: node tests/unit/script-docs.test.js --write --rebuild-indexes | Script | Summary | Usage | Domain | |---|---|---|---| -| `.githooks/install.sh` | Installs git hooks by setting core.hooksPath to .githooks/ | `bash .githooks/install.sh [flags]` | docs | +| `.githooks/install.sh` | Installs git hooks by routing this worktree to .githooks via worktree-local core.hooksPath | `bash .githooks/install.sh [flags]` | docs | | `.githooks/pre-commit` | Pre-commit hook orchestrator — runs structural checks, unit tests, codex validation, and docs-index freshness check before allowing commit | `bash .githooks/pre-commit [flags]` | docs | | `.githooks/pre-commit-no-deletions` | Variant pre-commit hook that blocks file deletions (safety net for content preservation) | `bash .githooks/pre-commit-no-deletions [flags]` | docs | | `.githooks/pre-push` | Pre-push hook — blocks push if AI stash files present, codex locks stale, or task contract invalid | `bash .githooks/pre-push [flags]` | docs | @@ -96,6 +96,7 @@ Run command: node tests/unit/script-docs.test.js --write --rebuild-indexes | `tests/unit/openapi-rolling-issue.test.js` | Tests OpenAPI rolling issue tracker — validates issue creation and dedup logic | `node tests/unit/openapi-rolling-issue.test.js [flags]` | docs | | `tests/unit/orchestrator-guides-research-review.test.js` | Tests orchestrator-guides-research-review.js — validates live Orchestrators Guides tranche extraction, report summary helpers, and registry-drift detection for the research packet generator. | `node tests/unit/orchestrator-guides-research-review.test.js` | docs | | `tests/unit/ownerless-governance.test.js` | Validates the ownerless governance manifest, primary gate-layer contract, and forbidden human-owner dependency in governed policy and GitHub surfaces. | `node tests/unit/ownerless-governance.test.js [--staged|--files a,b]` | docs | +| `tests/unit/precommit-staged-cache.test.js` | Tests precommit-staged-cache.js — validates staged-tree cache hits, invalidation, and pruning | `node tests/unit/precommit-staged-cache.test.js` | docs | | `tests/unit/quality.test.js` | Content quality checks — validates frontmatter completeness, thin content detection, placeholder flagging | `node tests/unit/quality.test.js [flags]` | docs | | `tests/unit/repair-governance.test.js` | Tests repair-governance.js for safe dry-run, fix, rollback, strict exit handling, and workflow contract coverage. | `node tests/unit/repair-governance.test.js` | docs | | `tests/unit/repair-spelling.test.js` | Unit tests for repair-spelling.js — validates deterministic spelling fixes and exclusion ranges | `node tests/unit/repair-spelling.test.js [flags]` | docs | @@ -295,6 +296,7 @@ Run command: node tests/unit/script-docs.test.js --write --rebuild-indexes | `tools/lib/load-js-yaml.js` | YAML loader utility — resolves js-yaml from repo-local installs and falls back to a minimal parser for task-contract style files in bare worktrees | `node -e "require('./tools/lib/load-js-yaml')"` | docs | | `tools/lib/load-minimatch.js` | Glob matcher loader — resolves minimatch from repo-local installs and falls back to a simple glob matcher for bare worktrees | `node -e "require('./tools/lib/load-minimatch')"` | docs | | `tools/lib/mdx-safe-markdown.js` | Shared MDX-safe markdown helpers that collect first-party markdown files, detect unsafe patterns, and apply deterministic repairs. | `node tools/lib/mdx-safe-markdown.js [flags]` | docs | +| `tools/lib/precommit-staged-cache.js` | Shared pre-commit staged-cache helpers — fingerprint staged content plus hook inputs and persist reusable pass markers | `const cache = require('./precommit-staged-cache');` | docs | | `tools/lib/script-governance-config.js` | Shared governance constants for script discovery, indexing, classification, and pipeline normalisation across the repo. | `const config = require('../lib/script-governance-config');` | docs | | `tools/lib/script-header-utils.js` | Shared helpers for extracting and reading top-of-file script governance headers without scanning into executable source. | `const { extractLeadingScriptHeader } = require('../lib/script-header-utils');` | docs | diff --git a/lpd b/lpd index cb5566cdb..22b3e3c19 100755 --- a/lpd +++ b/lpd @@ -613,32 +613,32 @@ run_cli_step() { } hook_status_check() { - local source_hook="$REPO_ROOT/.githooks/pre-commit" - # Support both regular repos and worktrees - local git_common_dir - git_common_dir=$(cd "$REPO_ROOT" && git rev-parse --git-common-dir 2>/dev/null) - if [ -z "$git_common_dir" ] || [ "$git_common_dir" = "--git-common-dir" ]; then - git_common_dir="$REPO_ROOT/.git" - fi - local target_hook="$git_common_dir/hooks/pre-commit" + local source_dir="$REPO_ROOT/.githooks" + local source_hook="$source_dir/pre-commit" + local source_pre_push="$source_dir/pre-push" + local hooks_path if [ ! -f "$source_hook" ]; then echo "missing-source" return 1 fi - if [ ! -f "$target_hook" ]; then + hooks_path="$(cd "$REPO_ROOT" && git config --path --get core.hooksPath 2>/dev/null || true)" + if [ -z "$hooks_path" ]; then echo "not-installed" return 1 fi + if [[ "$hooks_path" != /* ]]; then + hooks_path="$REPO_ROOT/$hooks_path" + fi - if [ ! -x "$target_hook" ]; then - echo "not-executable" + if [ "$hooks_path" != "$source_dir" ]; then + echo "wrong-path:$hooks_path" return 1 fi - if ! cmp -s "$source_hook" "$target_hook"; then - echo "out-of-date" + if [ ! -x "$source_hook" ] || [ ! -x "$source_pre_push" ]; then + echo "not-executable" return 1 fi @@ -667,16 +667,16 @@ cmd_hooks() { status="$(hook_status_check)" || true case "$status" in installed) - finish 0 "hooks status" "Hooks are installed and up to date." + finish 0 "hooks status" "Hooks are installed via worktree-local core.hooksPath." ;; not-installed) finish 1 "hooks status" "Hooks are not installed." ;; - out-of-date) - finish 1 "hooks status" "Installed hooks are out of date." + wrong-path:*) + finish 1 "hooks status" "Hooks are routed to the wrong path: ${status#wrong-path:}" ;; not-executable) - finish 1 "hooks status" "Hook exists but is not executable." + finish 1 "hooks status" "Hook entrypoints exist but are not executable." ;; *) finish 1 "hooks status" "Hook status check failed: $status" @@ -696,10 +696,10 @@ cmd_hooks() { Usage: lpd hooks install - - info: Install/update `.git/hooks/pre-commit` from `.githooks/pre-commit`. + - info: Configure this worktree to execute hooks directly from `.githooks/`. lpd hooks status - - info: Check whether the installed pre-commit hook exists, is executable, and matches source. + - info: Check whether this worktree routes hooks to `.githooks/` and whether entrypoints are executable. lpd hooks verify - info: Run hook verification checks from `.githooks/verify.sh`. @@ -720,6 +720,7 @@ Bypass Flags (pre-commit; use sparingly): - `SKIP_STYLE_CHECK=1` : skip style-guide compliance checks. - `SKIP_VERIFICATION=1` : skip verification script checks. - `SKIP_TESTS=1` : skip staged test suite checks. + - `DISABLE_PRECOMMIT_STAGED_CACHE=1` : rerun the expensive staged suite even if the staged snapshot already passed. - `SKIP_ALL=1` : skip all pre-commit checks. Human-Only Overrides: diff --git a/tasks/reports/script-classifications.json b/tasks/reports/script-classifications.json index aa04c8053..51801dd4b 100644 --- a/tasks/reports/script-classifications.json +++ b/tasks/reports/script-classifications.json @@ -471,6 +471,16 @@ "purpose_statement": "Tests docs-research-adjudication.js — validates adjudication-ledger schema, report-aware outcome recording, and trust-tier summary rules for measured research-skill review outcomes.", "pipeline": "manual — experimental research system" }, + { + "path": "tests/unit/docs-research-packet.test.js", + "script": "docs-research-packet.test", + "category": "generator", + "purpose": "tooling:dev-tools", + "scope": "tests/unit, tools/scripts/docs-research-packet.js, tools/config/scoped-navigation/docs-gate-work.json", + "needs": "R-R27, R-R30", + "purpose_statement": "Tests docs-research-packet.js — validates nav, manifest, and path tranche derivation plus packet-summary rollups for the generic research packet engine.", + "pipeline": "manual — packet generator validation" + }, { "path": "tests/unit/docs-route-scope.test.js", "script": "docs-route-scope.test", @@ -635,16 +645,6 @@ "purpose_statement": "Tests OpenAPI rolling issue tracker — validates issue creation and dedup logic", "pipeline": "manual — not yet in pipeline" }, - { - "path": "tests/unit/docs-research-packet.test.js", - "script": "docs-research-packet.test", - "category": "generator", - "purpose": "tooling:dev-tools", - "scope": "tests/unit, tools/scripts/docs-research-packet.js, tools/config/scoped-navigation/docs-gate-work.json", - "needs": "R-R27, R-R30", - "purpose_statement": "Tests docs-research-packet.js — validates nav, manifest, and path tranche derivation plus packet-summary rollups for the generic research packet engine.", - "pipeline": "manual — packet generator validation" - }, { "path": "tests/unit/orchestrator-guides-research-review.test.js", "script": "orchestrator-guides-research-review.test", @@ -665,6 +665,16 @@ "purpose_statement": "Validates the ownerless governance manifest, primary gate-layer contract, and forbidden human-owner dependency in governed policy and GitHub surfaces.", "pipeline": "P1, P3" }, + { + "path": "tests/unit/precommit-staged-cache.test.js", + "script": "precommit-staged-cache.test", + "category": "validator", + "purpose": "qa:repo-health", + "scope": "tests/unit, tools/lib/precommit-staged-cache.js", + "needs": "R-R14, R-R29", + "purpose_statement": "Tests precommit-staged-cache.js — validates staged-tree cache hits, invalidation, and pruning", + "pipeline": "P1, manual" + }, { "path": "tests/unit/quality.test.js", "script": "quality.test", @@ -1212,6 +1222,16 @@ "purpose_statement": "Shared MDX-safe markdown helpers that collect first-party markdown files, detect unsafe patterns, and apply deterministic repairs.", "pipeline": "indirect -- library module" }, + { + "path": "tools/lib/precommit-staged-cache.js", + "script": "precommit-staged-cache", + "category": "orchestrator", + "purpose": "infrastructure:pipeline-orchestration", + "scope": ".githooks, tests, tools/lib, tools/scripts", + "needs": "R-R29", + "purpose_statement": "Shared pre-commit staged-cache helpers — fingerprint staged content plus hook inputs and persist reusable pass markers", + "pipeline": "indirect -- library module" + }, { "path": "tools/lib/script-governance-config.js", "script": "script-governance-config", diff --git a/tests/README.md b/tests/README.md index d1662f332..aac92cad1 100644 --- a/tests/README.md +++ b/tests/README.md @@ -189,6 +189,7 @@ npm --prefix tests run test:pages-index npm --prefix tests run test:pages-index:write npm --prefix tests run test:pages-index:rebuild npm --prefix tests run test:generated-banners +npm --prefix tests run test:precommit-cache npm --prefix tests run test:browser npm --prefix tests run test:openapi:audit npm --prefix tests run test:openapi:issue @@ -239,21 +240,20 @@ Use those pages for workflow scope, commands, readiness, outputs, and source-of- - Full matrix: `tests/PR-CI-TESTS-AND-SCRIPT-RUN-MATRIX.md` ## Pre-commit Interaction -- Pre-commit runs `tests/run-all.js --staged --skip-browser` in fast mode. +- Pre-commit runs `tests/run-all.js --staged --skip-browser --skip-mdx-safe-markdown-check --skip-pages-index --skip-script-docs` in fast mode after those checks already ran earlier in the hook. - Docs navigation checks in this flow are check-only and do not rewrite `tasks/reports/navigation-links/navigation-report.*`. -- Pre-commit also runs domain audit on staged docs pages: - `node tests/integration/domain-pages-audit.js --staged --base-url https://docs.livepeer.org --version "$DOMAIN_AUDIT_VERSION"` - Pre-commit runs staged WCAG accessibility audit (conservative autofix enabled by default, blocks on remaining `serious`/`critical` issues): `node tests/integration/v2-wcag-audit.js --staged --fix --stage --max-pages 10 --fail-impact serious --report /tmp/livepeer-wcag-audit-precommit.md --report-json /tmp/livepeer-wcag-audit-precommit.json` - Pre-commit runs staged V2 link audit (strict internal validation, external classify-only): `node tests/integration/v2-link-audit.js --staged --strict --report /tmp/livepeer-link-audit-precommit.md` -- Set `DOMAIN_AUDIT_VERSION=v1|v2|both` to control scope in pre-commit. - Pre-commit enforces script header docs for newly added scripts and auto-updates script indexes: `node tests/unit/script-docs.test.js --staged --write --stage --autofill` Missing headers are auto-inserted, then commit remains blocked until placeholder values are filled. - Pre-commit also synchronizes `v2/pages` index files: `node tools/scripts/generate-pages-index.js --staged --write --stage` This regenerates top-level section `index.mdx` files, updates root `v2/pages/index.mdx`, marks missing `docs.json` pages with `⚠️`, and removes nested `index.mdx`/`index.md` files. +- Pre-commit fails fast on cheap blockers and skips the expensive staged suite until those are fixed. +- After the expensive staged suite passes once, repeat commits with unchanged staged content reuse a cache marker. Set `DISABLE_PRECOMMIT_STAGED_CACHE=1` to force a rerun. ## Script Header Template (Required for New Scripts) Newly added scripts must include these tags near the top of the file: diff --git a/tests/WHEN-TESTS-RUN.md b/tests/WHEN-TESTS-RUN.md index c0c580312..58abe5d9d 100644 --- a/tests/WHEN-TESTS-RUN.md +++ b/tests/WHEN-TESTS-RUN.md @@ -21,8 +21,9 @@ - Pages index sync (`tools/scripts/generate-pages-index.js --staged --write --stage`) - Staged WCAG accessibility audit with conservative autofix (`tests/integration/v2-wcag-audit.js --staged --fix --stage --max-pages 10 --fail-impact serious ...`) - Staged strict V2 link audit (`tests/integration/v2-link-audit.js --staged --strict ...`) -- Staged domain audit (`tests/integration/domain-pages-audit.js --staged ...`) - Staged selection will eventually exclude governed V2 non-publishable lanes through `.mintignore`; legacy buckets such as `_contextData`, `_plans-and-research`, `x-resources`, and nested `review.md` remain in inventory until move waves complete. +- Expensive staged validation runs only after cheap pre-checks pass. +- Repeat commits with unchanged staged content reuse the cached expensive-suite result unless `DISABLE_PRECOMMIT_STAGED_CACHE=1` is set. **Speed:** Fast (~10-30 seconds) for most commits, depends on staged scope diff --git a/tests/package.json b/tests/package.json index 4c8a0dd4b..8890e7931 100644 --- a/tests/package.json +++ b/tests/package.json @@ -27,6 +27,7 @@ "test:pages-index:rebuild": "node ../tools/scripts/generate-pages-index.js --write --rebuild-indexes", "test:generated-banners": "node ../tools/scripts/enforce-generated-file-banners.js --check", "test:scripts": "node unit/script-docs.test.js", + "test:precommit-cache": "node unit/precommit-staged-cache.test.js", "test:components:governance": "node unit/component-governance-utils.test.js && node unit/component-governance-generators.test.js", "test:browser": "node integration/browser.test.js", "test:openapi:audit": "node integration/openapi-reference-audit.js --full --strict", diff --git a/tests/run-all.js b/tests/run-all.js index bd02e9f76..84826a03b 100644 --- a/tests/run-all.js +++ b/tests/run-all.js @@ -4,7 +4,7 @@ * @category orchestrator * @purpose infrastructure:pipeline-orchestration * @scope tests - * @owner docs + * @domain docs * @needs R-R29 * @purpose-statement Test orchestrator — dispatches all unit test suites. Called by pre-commit hook and npm test. * @pipeline P1, P2, P3 @@ -37,6 +37,7 @@ const checkAgentDocsFreshnessTests = require('./unit/check-agent-docs-freshness. const rootAllowlistFormatTests = require('./unit/root-allowlist-format.test'); const exportPortableSkillsTests = require('./unit/export-portable-skills.test'); const docsGuideSotTests = require('./unit/docs-guide-sot.test'); +const precommitStagedCacheTests = require('./unit/precommit-staged-cache.test'); const uiTemplateGeneratorTests = require('./unit/ui-template-generator.test'); const componentGovernanceUtilsTests = require('./unit/component-governance-utils.test'); const componentGovernanceGeneratorTests = require('./unit/component-governance-generators.test'); @@ -54,6 +55,9 @@ const skipBrowser = args.includes('--skip-browser'); const watch = args.includes('--watch'); const runWcag = args.includes('--wcag'); const wcagNoFix = args.includes('--wcag-no-fix'); +const skipMdxSafeMarkdownCheck = args.includes('--skip-mdx-safe-markdown-check'); +const skipPagesIndex = args.includes('--skip-pages-index'); +const skipScriptDocs = args.includes('--skip-script-docs'); let totalErrors = 0; let totalWarnings = 0; @@ -194,16 +198,20 @@ async function runAllTests() { // Repo-wide MDX-safe Markdown Validation console.log('\n🧱 Running Repo-wide MDX-safe Markdown Validation...'); - const mdxSafeMarkdownResult = normalizeSuiteResult(mdxSafeMarkdownValidator.run({ - args: { - stagedOnly, - files: [], - json: false - } - })); - totalErrors += mdxSafeMarkdownResult.errors.length; - totalWarnings += mdxSafeMarkdownResult.warnings.length; - console.log(` ${mdxSafeMarkdownResult.errors.length} errors, ${mdxSafeMarkdownResult.warnings.length} warnings`); + if (skipMdxSafeMarkdownCheck) { + console.log(' skipped (handled earlier in pre-commit)'); + } else { + const mdxSafeMarkdownResult = normalizeSuiteResult(mdxSafeMarkdownValidator.run({ + args: { + stagedOnly, + files: [], + json: false + } + })); + totalErrors += mdxSafeMarkdownResult.errors.length; + totalWarnings += mdxSafeMarkdownResult.warnings.length; + console.log(` ${mdxSafeMarkdownResult.errors.length} errors, ${mdxSafeMarkdownResult.warnings.length} warnings`); + } // MDX Guardrails console.log('\n🛡️ Running MDX Guardrail Tests...'); @@ -277,10 +285,14 @@ async function runAllTests() { // Script Docs Enforcement console.log('\n🧾 Running Script Documentation Enforcement...'); - const scriptDocsResult = normalizeSuiteResult(scriptDocsTests.runTests({ stagedOnly })); - totalErrors += scriptDocsResult.errors.length; - totalWarnings += scriptDocsResult.warnings.length; - console.log(` ${scriptDocsResult.errors.length} errors, ${scriptDocsResult.warnings.length} warnings`); + if (skipScriptDocs) { + console.log(' skipped (handled earlier in pre-commit)'); + } else { + const scriptDocsResult = normalizeSuiteResult(scriptDocsTests.runTests({ stagedOnly })); + totalErrors += scriptDocsResult.errors.length; + totalWarnings += scriptDocsResult.warnings.length; + console.log(` ${scriptDocsResult.errors.length} errors, ${scriptDocsResult.warnings.length} warnings`); + } // Skill Docs Enforcement console.log('\n📘 Running Skill Documentation Enforcement...'); @@ -341,6 +353,15 @@ async function runAllTests() { console.log(' skipped (no staged docs-guide source-of-truth changes)'); } + // Pre-commit Cache Unit Tests + console.log('\n🧮 Running Pre-commit Cache Unit Tests...'); + const precommitStagedCacheResult = normalizeSuiteResult(await precommitStagedCacheTests.runTests()); + totalErrors += precommitStagedCacheResult.errors.length; + totalWarnings += precommitStagedCacheResult.warnings.length; + console.log( + ` ${precommitStagedCacheResult.errors.length} errors, ${precommitStagedCacheResult.warnings.length} warnings` + ); + // UI Template Generator console.log('\n🧱 Running UI Template Generator Checks...'); if (hasStagedUiTemplateChanges()) { @@ -398,13 +419,17 @@ async function runAllTests() { // Pages Index Sync Validation console.log('\n🗂️ Running Pages Index Sync Validation...'); - const pagesIndexResult = normalizeSuiteResult(pagesIndexGenerator.run({ stagedOnly })); - totalErrors += pagesIndexResult.errors.length; - totalWarnings += pagesIndexResult.warnings.length; - if (pagesIndexResult.skipped) { - console.log(' skipped (no staged v2/pages changes)'); + if (skipPagesIndex) { + console.log(' skipped (handled earlier in pre-commit)'); } else { - console.log(` ${pagesIndexResult.errors.length} errors, ${pagesIndexResult.warnings.length} warnings`); + const pagesIndexResult = normalizeSuiteResult(pagesIndexGenerator.run({ stagedOnly })); + totalErrors += pagesIndexResult.errors.length; + totalWarnings += pagesIndexResult.warnings.length; + if (pagesIndexResult.skipped) { + console.log(' skipped (no staged v2/pages changes)'); + } else { + console.log(` ${pagesIndexResult.errors.length} errors, ${pagesIndexResult.warnings.length} warnings`); + } } // Generated Banner Enforcement diff --git a/tests/script-index.md b/tests/script-index.md index b3eeca92a..9ac75f8cb 100644 --- a/tests/script-index.md +++ b/tests/script-index.md @@ -56,6 +56,7 @@ | `tests/unit/openapi-rolling-issue.test.js` | Tests OpenAPI rolling issue tracker — validates issue creation and dedup logic | `node tests/unit/openapi-rolling-issue.test.js [flags]` | docs | | `tests/unit/orchestrator-guides-research-review.test.js` | Tests orchestrator-guides-research-review.js — validates live Orchestrators Guides tranche extraction, report summary helpers, and registry-drift detection for the research packet generator. | `node tests/unit/orchestrator-guides-research-review.test.js` | docs | | `tests/unit/ownerless-governance.test.js` | Validates the ownerless governance manifest, primary gate-layer contract, and forbidden human-owner dependency in governed policy and GitHub surfaces. | `node tests/unit/ownerless-governance.test.js [--staged\|--files a,b]` | docs | +| `tests/unit/precommit-staged-cache.test.js` | Tests precommit-staged-cache.js — validates staged-tree cache hits, invalidation, and pruning | `node tests/unit/precommit-staged-cache.test.js` | docs | | `tests/unit/quality.test.js` | Content quality checks — validates frontmatter completeness, thin content detection, placeholder flagging | `node tests/unit/quality.test.js [flags]` | docs | | `tests/unit/repair-governance.test.js` | Tests repair-governance.js for safe dry-run, fix, rollback, strict exit handling, and workflow contract coverage. | `node tests/unit/repair-governance.test.js` | docs | | `tests/unit/repair-spelling.test.js` | Unit tests for repair-spelling.js — validates deterministic spelling fixes and exclusion ranges | `node tests/unit/repair-spelling.test.js [flags]` | docs | diff --git a/tests/unit/precommit-staged-cache.test.js b/tests/unit/precommit-staged-cache.test.js new file mode 100644 index 000000000..8399aabb2 --- /dev/null +++ b/tests/unit/precommit-staged-cache.test.js @@ -0,0 +1,208 @@ +#!/usr/bin/env node +/** + * @script precommit-staged-cache.test + * @category validator + * @purpose qa:repo-health + * @scope tests/unit, tools/lib/precommit-staged-cache.js + * @domain docs + * @needs R-R14, R-R29 + * @purpose-statement Tests precommit-staged-cache.js — validates staged-tree cache hits, invalidation, and pruning + * @pipeline P1, manual + * @usage node tests/unit/precommit-staged-cache.test.js + */ + +const assert = require('assert'); +const fs = require('fs'); +const os = require('os'); +const path = require('path'); +const { spawnSync } = require('child_process'); + +const { + getCacheDir, + readCache, + writeCache +} = require('../../tools/lib/precommit-staged-cache'); + +function mkTmpDir(prefix) { + return fs.mkdtempSync(path.join(os.tmpdir(), prefix)); +} + +function writeFile(absolutePath, content) { + fs.mkdirSync(path.dirname(absolutePath), { recursive: true }); + fs.writeFileSync(absolutePath, content, 'utf8'); +} + +function buildGitEnv() { + const env = { ...process.env }; + Object.keys(env).forEach((key) => { + if (key.startsWith('GIT_')) { + delete env[key]; + } + }); + return env; +} + +function runGit(repoRoot, args) { + const result = spawnSync('git', args, { + cwd: repoRoot, + encoding: 'utf8', + env: buildGitEnv() + }); + + if (result.status !== 0) { + throw new Error((result.stderr || result.stdout || `git ${args.join(' ')}`).trim()); + } + + return String(result.stdout || '').trim(); +} + +function initRepo() { + const repoRoot = mkTmpDir('precommit-staged-cache-'); + const hooksDir = path.join(repoRoot, '.git-hooks-disabled'); + + runGit(repoRoot, ['init']); + runGit(repoRoot, ['config', 'user.name', 'Codex Test']); + runGit(repoRoot, ['config', 'user.email', 'codex@example.com']); + fs.mkdirSync(hooksDir, { recursive: true }); + runGit(repoRoot, ['config', 'core.hooksPath', hooksDir]); + + writeFile(path.join(repoRoot, '.githooks/pre-commit'), '#!/bin/bash\necho precommit\n'); + writeFile(path.join(repoRoot, 'tests/run-all.js'), 'module.exports = {};\n'); + writeFile(path.join(repoRoot, 'tests/unit/precommit-staged-cache.test.js'), '// fixture\n'); + writeFile(path.join(repoRoot, 'tools/lib/precommit-staged-cache.js'), 'module.exports = {};\n'); + writeFile(path.join(repoRoot, 'docs/example.mdx'), '# Example\n'); + + runGit(repoRoot, ['add', '.']); + runGit(repoRoot, ['commit', '-m', 'test fixture']); + + return repoRoot; +} + +async function runTests() { + const errors = []; + const watchedFiles = [ + '.githooks/pre-commit', + 'tests/run-all.js', + 'tools/lib/precommit-staged-cache.js' + ]; + + try { + const repoRoot = initRepo(); + writeFile(path.join(repoRoot, 'docs/example.mdx'), '# Example\n\nUpdated.\n'); + runGit(repoRoot, ['add', 'docs/example.mdx']); + + const gitEnv = buildGitEnv(); + const initial = readCache({ repoRoot, watchedFiles, namespace: 'test-precommit-cache', gitEnv }); + assert.strictEqual(initial.hit, false, 'cache should miss before first write'); + + const written = writeCache({ + repoRoot, + watchedFiles, + namespace: 'test-precommit-cache', + metadata: { branch: 'docs-v2-dev' }, + gitEnv + }); + assert.ok(fs.existsSync(written.cacheFilePath), 'cache file should be written'); + + const reread = readCache({ repoRoot, watchedFiles, namespace: 'test-precommit-cache', gitEnv }); + assert.strictEqual(reread.hit, true, 'cache should hit after write for unchanged staged tree'); + assert.strictEqual(reread.entry.metadata.branch, 'docs-v2-dev'); + console.log(' ✓ cache hits after recording an unchanged staged tree'); + } catch (error) { + errors.push({ message: `cache hit after write: ${error.message}` }); + } + + try { + const repoRoot = initRepo(); + const gitEnv = buildGitEnv(); + writeFile(path.join(repoRoot, 'docs/example.mdx'), '# Example\n\nUpdated.\n'); + runGit(repoRoot, ['add', 'docs/example.mdx']); + writeCache({ repoRoot, watchedFiles, namespace: 'test-precommit-cache', gitEnv }); + + writeFile(path.join(repoRoot, 'docs/example.mdx'), '# Example\n\nUpdated twice.\n'); + runGit(repoRoot, ['add', 'docs/example.mdx']); + + const changedTree = readCache({ repoRoot, watchedFiles, namespace: 'test-precommit-cache', gitEnv }); + assert.strictEqual(changedTree.hit, false, 'cache should miss when staged content changes'); + console.log(' ✓ cache invalidates when the staged tree changes'); + } catch (error) { + errors.push({ message: `staged tree invalidation: ${error.message}` }); + } + + try { + const repoRoot = initRepo(); + const gitEnv = buildGitEnv(); + writeFile(path.join(repoRoot, 'docs/example.mdx'), '# Example\n\nUpdated.\n'); + runGit(repoRoot, ['add', 'docs/example.mdx']); + writeCache({ repoRoot, watchedFiles, namespace: 'test-precommit-cache', gitEnv }); + + writeFile(path.join(repoRoot, 'tests/run-all.js'), 'module.exports = { changed: true };\n'); + + const changedWatcher = readCache({ repoRoot, watchedFiles, namespace: 'test-precommit-cache', gitEnv }); + assert.strictEqual(changedWatcher.hit, false, 'cache should miss when a watched hook file changes'); + console.log(' ✓ cache invalidates when watched hook files change'); + } catch (error) { + errors.push({ message: `watched file invalidation: ${error.message}` }); + } + + try { + const repoRoot = initRepo(); + const gitEnv = buildGitEnv(); + writeFile(path.join(repoRoot, 'docs/example.mdx'), '# Example\n\nUpdated.\n'); + runGit(repoRoot, ['add', 'docs/example.mdx']); + + writeCache({ + repoRoot, + watchedFiles, + namespace: 'test-precommit-cache', + metadata: { id: 1 }, + maxEntries: 1, + gitEnv + }); + + writeFile(path.join(repoRoot, 'docs/example-2.mdx'), '# Another\n'); + runGit(repoRoot, ['add', 'docs/example-2.mdx']); + writeCache({ + repoRoot, + watchedFiles, + namespace: 'test-precommit-cache', + metadata: { id: 2 }, + maxEntries: 1, + gitEnv + }); + + const cacheDir = getCacheDir({ repoRoot, namespace: 'test-precommit-cache', gitEnv }); + const entries = fs.readdirSync(cacheDir).filter((entry) => entry.endsWith('.json')); + assert.strictEqual(entries.length, 1, 'cache pruning should keep only the requested number of entries'); + console.log(' ✓ cache pruning removes stale entries'); + } catch (error) { + errors.push({ message: `cache pruning: ${error.message}` }); + } + + return { + passed: errors.length === 0, + errors, + warnings: [], + total: 4 + }; +} + +if (require.main === module) { + runTests() + .then((result) => { + if (result.passed) { + console.log(`\n✅ precommit-staged-cache tests passed (${result.total} cases)`); + process.exit(0); + } + + console.error(`\n❌ ${result.errors.length} precommit-staged-cache test failure(s)`); + result.errors.forEach((entry) => console.error(` - ${entry.message}`)); + process.exit(1); + }) + .catch((error) => { + console.error(`\n❌ precommit-staged-cache tests crashed: ${error.message}`); + process.exit(1); + }); +} + +module.exports = { runTests }; diff --git a/tools/lib/precommit-staged-cache.js b/tools/lib/precommit-staged-cache.js new file mode 100644 index 000000000..6cb1df2df --- /dev/null +++ b/tools/lib/precommit-staged-cache.js @@ -0,0 +1,234 @@ +/** + * @script precommit-staged-cache + * @category orchestrator + * @purpose infrastructure:pipeline-orchestration + * @scope .githooks, tests, tools/lib, tools/scripts + * @domain docs + * @needs R-R29 + * @purpose-statement Shared pre-commit staged-cache helpers — fingerprint staged content plus hook inputs and persist reusable pass markers + * @pipeline indirect -- library module + * @usage const cache = require('./precommit-staged-cache'); + */ +const crypto = require('crypto'); +const fs = require('fs'); +const path = require('path'); +const { spawnSync } = require('child_process'); + +const DEFAULT_NAMESPACE = 'pre-commit-expensive-suite'; +const DEFAULT_MAX_ENTRIES = 25; +const DEFAULT_WATCHED_FILES = Object.freeze([ + '.githooks/pre-commit', + 'tests/run-all.js', + 'tests/integration/v2-link-audit.js', + 'tests/integration/v2-wcag-audit.js', + 'tests/unit/ai-tools-registry.test.js', + 'tests/unit/check-agent-docs-freshness.test.js', + 'tests/unit/component-governance-generators.test.js', + 'tests/unit/component-governance-utils.test.js', + 'tests/unit/copy-lint.test.js', + 'tests/unit/docs-authoring-rules.test.js', + 'tests/unit/docs-guide-sot.test.js', + 'tests/unit/docs-navigation.test.js', + 'tests/unit/docs-page-scope.test.js', + 'tests/unit/docs-path-sync.test.js', + 'tests/unit/export-portable-skills.test.js', + 'tests/unit/frontmatter-taxonomy.test.js', + 'tests/unit/links-imports.test.js', + 'tests/unit/mdx-guards.test.js', + 'tests/unit/mdx-safe-markdown.test.js', + 'tests/unit/mdx.test.js', + 'tests/unit/ownerless-governance.test.js', + 'tests/unit/precommit-staged-cache.test.js', + 'tests/unit/quality.test.js', + 'tests/unit/root-allowlist-format.test.js', + 'tests/unit/script-docs.test.js', + 'tests/unit/skill-docs.test.js', + 'tests/unit/spelling.test.js', + 'tests/unit/style-guide.test.js', + 'tests/unit/ui-template-generator.test.js', + 'tests/unit/usefulness-journey.test.js', + 'tests/unit/usefulness-rubric.test.js', + 'tools/lib/generated-artifacts.js', + 'tools/lib/precommit-staged-cache.js', + 'tools/lib/script-governance-config.js', + 'tools/scripts/enforce-generated-file-banners.js', + 'tools/scripts/generate-component-registry.js', + 'tools/scripts/generate-docs-guide-components-index.js', + 'tools/scripts/generate-docs-index.js', + 'tools/scripts/generate-pages-index.js', + 'tools/scripts/remediators/components/repair-component-metadata.js', + 'tools/scripts/remediators/content/repair-mdx-safe-markdown.js', + 'tools/scripts/remediators/content/sync-docs-paths.js', + 'tools/scripts/scan-component-imports.js', + 'tools/scripts/sync-codex-skills.js', + 'tools/scripts/validators/components/check-component-css.js', + 'tools/scripts/validators/components/check-component-docs.js', + 'tools/scripts/validators/components/check-naming-conventions.js', + 'tools/scripts/validators/content/check-mdx-safe-markdown.js', + 'tools/scripts/validators/governance/audit-script-inventory.js' +]); + +function normalizeRepoPath(filePath) { + return String(filePath || '').split(path.sep).join('/'); +} + +function runGit(repoRoot, args, options = {}) { + const result = spawnSync('git', args, { + cwd: repoRoot, + encoding: 'utf8', + env: options.gitEnv || process.env + }); + + if (result.status !== 0) { + throw new Error((result.stderr || result.stdout || `git ${args.join(' ')}`).trim()); + } + + return String(result.stdout || '').trim(); +} + +function resolveGitDir(repoRoot, options = {}) { + return path.resolve(repoRoot, runGit(repoRoot, ['rev-parse', '--git-dir'], options)); +} + +function getIndexTree(repoRoot, options = {}) { + return runGit(repoRoot, ['write-tree'], options); +} + +function hashFileContent(repoRoot, relativePath) { + const normalizedPath = normalizeRepoPath(relativePath); + const absolutePath = path.join(repoRoot, normalizedPath); + if (!fs.existsSync(absolutePath)) return `missing:${normalizedPath}`; + + const hash = crypto.createHash('sha256'); + hash.update(fs.readFileSync(absolutePath)); + return hash.digest('hex'); +} + +function normalizeWatchedFiles(watchedFiles = DEFAULT_WATCHED_FILES) { + return [...new Set((watchedFiles || []).map(normalizeRepoPath).filter(Boolean))].sort(); +} + +function getCacheDir({ repoRoot, namespace = DEFAULT_NAMESPACE, gitEnv }) { + return path.join(resolveGitDir(repoRoot, { gitEnv }), 'lpd-hook-cache', namespace); +} + +function computeCacheKey({ repoRoot, namespace = DEFAULT_NAMESPACE, watchedFiles = DEFAULT_WATCHED_FILES, gitEnv }) { + const normalizedFiles = normalizeWatchedFiles(watchedFiles); + const indexTree = getIndexTree(repoRoot, { gitEnv }); + const digest = crypto.createHash('sha256'); + + digest.update(`${namespace}\n${indexTree}\n`); + normalizedFiles.forEach((relativePath) => { + digest.update(`${relativePath}\0${hashFileContent(repoRoot, relativePath)}\n`); + }); + + return { + namespace, + indexTree, + watchedFiles: normalizedFiles, + key: digest.digest('hex') + }; +} + +function getCacheFilePath({ repoRoot, namespace = DEFAULT_NAMESPACE, key, gitEnv }) { + return path.join(getCacheDir({ repoRoot, namespace, gitEnv }), `${key}.json`); +} + +function pruneCacheDir(cacheDir, maxEntries = DEFAULT_MAX_ENTRIES) { + if (!fs.existsSync(cacheDir)) return; + + const entries = fs.readdirSync(cacheDir) + .filter((entry) => entry.endsWith('.json')) + .map((entry) => { + const absolutePath = path.join(cacheDir, entry); + const stats = fs.statSync(absolutePath); + return { + absolutePath, + mtimeMs: stats.mtimeMs + }; + }) + .sort((left, right) => right.mtimeMs - left.mtimeMs); + + entries.slice(Math.max(maxEntries, 0)).forEach((entry) => { + fs.rmSync(entry.absolutePath, { force: true }); + }); +} + +function readCache(options) { + const fingerprint = computeCacheKey(options); + const cacheFilePath = getCacheFilePath({ + repoRoot: options.repoRoot, + namespace: fingerprint.namespace, + key: fingerprint.key, + gitEnv: options.gitEnv + }); + + if (!fs.existsSync(cacheFilePath)) { + return { + ...fingerprint, + cacheFilePath, + hit: false, + entry: null + }; + } + + const entry = JSON.parse(fs.readFileSync(cacheFilePath, 'utf8')); + const hit = entry.key === fingerprint.key && entry.indexTree === fingerprint.indexTree; + + return { + ...fingerprint, + cacheFilePath, + hit, + entry + }; +} + +function writeCache({ + repoRoot, + namespace = DEFAULT_NAMESPACE, + watchedFiles = DEFAULT_WATCHED_FILES, + metadata = {}, + maxEntries = DEFAULT_MAX_ENTRIES, + gitEnv +}) { + const fingerprint = computeCacheKey({ repoRoot, namespace, watchedFiles, gitEnv }); + const cacheDir = getCacheDir({ repoRoot, namespace, gitEnv }); + const cacheFilePath = getCacheFilePath({ + repoRoot, + namespace, + key: fingerprint.key, + gitEnv + }); + + fs.mkdirSync(cacheDir, { recursive: true }); + + const entry = { + key: fingerprint.key, + namespace, + indexTree: fingerprint.indexTree, + watchedFiles: fingerprint.watchedFiles, + createdAt: new Date().toISOString(), + metadata + }; + + fs.writeFileSync(cacheFilePath, `${JSON.stringify(entry, null, 2)}\n`, 'utf8'); + pruneCacheDir(cacheDir, maxEntries); + + return { + ...fingerprint, + cacheFilePath, + entry + }; +} + +module.exports = { + DEFAULT_MAX_ENTRIES, + DEFAULT_NAMESPACE, + DEFAULT_WATCHED_FILES, + computeCacheKey, + getCacheDir, + getCacheFilePath, + normalizeWatchedFiles, + readCache, + writeCache +}; diff --git a/tools/lib/script-index.md b/tools/lib/script-index.md index 51fd3ecf1..031dae260 100644 --- a/tools/lib/script-index.md +++ b/tools/lib/script-index.md @@ -36,6 +36,7 @@ | `tools/lib/load-js-yaml.js` | YAML loader utility — resolves js-yaml from repo-local installs and falls back to a minimal parser for task-contract style files in bare worktrees | `node -e "require('./tools/lib/load-js-yaml')"` | docs | | `tools/lib/load-minimatch.js` | Glob matcher loader — resolves minimatch from repo-local installs and falls back to a simple glob matcher for bare worktrees | `node -e "require('./tools/lib/load-minimatch')"` | docs | | `tools/lib/mdx-safe-markdown.js` | Shared MDX-safe markdown helpers that collect first-party markdown files, detect unsafe patterns, and apply deterministic repairs. | `node tools/lib/mdx-safe-markdown.js [flags]` | docs | +| `tools/lib/precommit-staged-cache.js` | Shared pre-commit staged-cache helpers — fingerprint staged content plus hook inputs and persist reusable pass markers | `const cache = require('./precommit-staged-cache');` | docs | | `tools/lib/script-governance-config.js` | Shared governance constants for script discovery, indexing, classification, and pipeline normalisation across the repo. | `const config = require('../lib/script-governance-config');` | docs | | `tools/lib/script-header-utils.js` | Shared helpers for extracting and reading top-of-file script governance headers without scanning into executable source. | `const { extractLeadingScriptHeader } = require('../lib/script-header-utils');` | docs | {/* SCRIPT-INDEX:END */} From 1145c08949b3bce106e0eb4c22eef12fea68ecc7 Mon Sep 17 00:00:00 2001 From: Codex Test Date: Tue, 17 Mar 2026 07:09:19 +1100 Subject: [PATCH 2/5] fix(hooks): scope precommit basics --- .githooks/README.md | 1 + .githooks/pre-commit | 6 +- tests/README.md | 4 +- tests/WHEN-TESTS-RUN.md | 1 + tests/package.json | 1 + tests/run-all.js | 355 +++++++++++++++++++++------------------- 6 files changed, 194 insertions(+), 174 deletions(-) diff --git a/.githooks/README.md b/.githooks/README.md index 38de44663..3e5d8424d 100644 --- a/.githooks/README.md +++ b/.githooks/README.md @@ -27,6 +27,7 @@ Owned concerns: - fast staged local/offline checks - structure + style + staged static test validations +- scoped basic test lane only; repo-wide governance/unit suites stay out of pre-commit - staged generator sync for managed artifacts - reuses cached pass results when the staged snapshot and hook/test inputs are unchanged - runtime budget enforcement (default: `<= 60s`) diff --git a/.githooks/pre-commit b/.githooks/pre-commit index c941867f3..a0afcb920 100755 --- a/.githooks/pre-commit +++ b/.githooks/pre-commit @@ -1522,13 +1522,13 @@ if [ "$RUN_PRECOMMIT_EXPENSIVE_SUITE" = "1" ]; then tools/scripts/remediators/content/sync-docs-paths.js --write --staged --stage fi - run_all_args=(tests/run-all.js --staged --skip-browser) + run_all_args=(tests/run-all.js --staged --skip-browser --precommit-basic) if [ "$SKIP_VERIFICATION" != "1" ]; then run_all_args+=(--skip-mdx-safe-markdown-check --skip-pages-index --skip-script-docs) fi run_node_check \ - "Running core staged test suite..." \ - "❌ Core staged test suite failed - see output above" \ + "Running basic staged test suite..." \ + "❌ Basic staged test suite failed - see output above" \ "${run_all_args[@]}" if [ -n "$STAGED_DOCS_PAGES" ]; then diff --git a/tests/README.md b/tests/README.md index aac92cad1..49ec9ed35 100644 --- a/tests/README.md +++ b/tests/README.md @@ -189,6 +189,7 @@ npm --prefix tests run test:pages-index npm --prefix tests run test:pages-index:write npm --prefix tests run test:pages-index:rebuild npm --prefix tests run test:generated-banners +npm --prefix tests run test:precommit npm --prefix tests run test:precommit-cache npm --prefix tests run test:browser npm --prefix tests run test:openapi:audit @@ -240,7 +241,7 @@ Use those pages for workflow scope, commands, readiness, outputs, and source-of- - Full matrix: `tests/PR-CI-TESTS-AND-SCRIPT-RUN-MATRIX.md` ## Pre-commit Interaction -- Pre-commit runs `tests/run-all.js --staged --skip-browser --skip-mdx-safe-markdown-check --skip-pages-index --skip-script-docs` in fast mode after those checks already ran earlier in the hook. +- Pre-commit runs `tests/run-all.js --staged --skip-browser --precommit-basic --skip-mdx-safe-markdown-check --skip-pages-index --skip-script-docs` in fast mode after those checks already ran earlier in the hook. - Docs navigation checks in this flow are check-only and do not rewrite `tasks/reports/navigation-links/navigation-report.*`. - Pre-commit runs staged WCAG accessibility audit (conservative autofix enabled by default, blocks on remaining `serious`/`critical` issues): `node tests/integration/v2-wcag-audit.js --staged --fix --stage --max-pages 10 --fail-impact serious --report /tmp/livepeer-wcag-audit-precommit.md --report-json /tmp/livepeer-wcag-audit-precommit.json` @@ -252,6 +253,7 @@ Use those pages for workflow scope, commands, readiness, outputs, and source-of- - Pre-commit also synchronizes `v2/pages` index files: `node tools/scripts/generate-pages-index.js --staged --write --stage` This regenerates top-level section `index.mdx` files, updates root `v2/pages/index.mdx`, marks missing `docs.json` pages with `⚠️`, and removes nested `index.mdx`/`index.md` files. +- The hook lane intentionally stops at staged syntax/style/content basics. Repo-wide governance/unit suites stay in full `node tests/run-all.js` runs and CI. - Pre-commit fails fast on cheap blockers and skips the expensive staged suite until those are fixed. - After the expensive staged suite passes once, repeat commits with unchanged staged content reuse a cache marker. Set `DISABLE_PRECOMMIT_STAGED_CACHE=1` to force a rerun. diff --git a/tests/WHEN-TESTS-RUN.md b/tests/WHEN-TESTS-RUN.md index 58abe5d9d..2779f0648 100644 --- a/tests/WHEN-TESTS-RUN.md +++ b/tests/WHEN-TESTS-RUN.md @@ -23,6 +23,7 @@ - Staged strict V2 link audit (`tests/integration/v2-link-audit.js --staged --strict ...`) - Staged selection will eventually exclude governed V2 non-publishable lanes through `.mintignore`; legacy buckets such as `_contextData`, `_plans-and-research`, `x-resources`, and nested `review.md` remain in inventory until move waves complete. - Expensive staged validation runs only after cheap pre-checks pass. +- The hook test runner uses a `--precommit-basic` lane with staged syntax/style/content checks only; repo-wide governance/unit suites are deferred to full runs and CI. - Repeat commits with unchanged staged content reuse the cached expensive-suite result unless `DISABLE_PRECOMMIT_STAGED_CACHE=1` is set. **Speed:** Fast (~10-30 seconds) for most commits, depends on staged scope diff --git a/tests/package.json b/tests/package.json index 8890e7931..af45707c6 100644 --- a/tests/package.json +++ b/tests/package.json @@ -26,6 +26,7 @@ "test:pages-index:write": "node ../tools/scripts/generate-pages-index.js --write", "test:pages-index:rebuild": "node ../tools/scripts/generate-pages-index.js --write --rebuild-indexes", "test:generated-banners": "node ../tools/scripts/enforce-generated-file-banners.js --check", + "test:precommit": "node run-all.js --staged --skip-browser --precommit-basic", "test:scripts": "node unit/script-docs.test.js", "test:precommit-cache": "node unit/precommit-staged-cache.test.js", "test:components:governance": "node unit/component-governance-utils.test.js && node unit/component-governance-generators.test.js", diff --git a/tests/run-all.js b/tests/run-all.js index 84826a03b..685243a4a 100644 --- a/tests/run-all.js +++ b/tests/run-all.js @@ -55,6 +55,7 @@ const skipBrowser = args.includes('--skip-browser'); const watch = args.includes('--watch'); const runWcag = args.includes('--wcag'); const wcagNoFix = args.includes('--wcag-no-fix'); +const precommitBasic = args.includes('--precommit-basic'); const skipMdxSafeMarkdownCheck = args.includes('--skip-mdx-safe-markdown-check'); const skipPagesIndex = args.includes('--skip-pages-index'); const skipScriptDocs = args.includes('--skip-script-docs'); @@ -136,6 +137,10 @@ function hasStagedUiTemplateChanges() { ); } +function logPrecommitBasicSkip(summary) { + console.log(` skipped in --precommit-basic lane (${summary})`); +} + /** * Run all tests */ @@ -213,40 +218,45 @@ async function runAllTests() { console.log(` ${mdxSafeMarkdownResult.errors.length} errors, ${mdxSafeMarkdownResult.warnings.length} warnings`); } - // MDX Guardrails - console.log('\n🛡️ Running MDX Guardrail Tests...'); - const mdxGuardsResult = normalizeSuiteResult(mdxGuardsTests.runTests()); - totalErrors += mdxGuardsResult.errors.length; - totalWarnings += mdxGuardsResult.warnings.length; - console.log(` ${mdxGuardsResult.errors.length} errors, ${mdxGuardsResult.warnings.length} warnings`); - - // MDX-safe Markdown Unit Tests - console.log('\n🧪 Running MDX-safe Markdown Unit Tests...'); - const mdxSafeMarkdownUnitResult = normalizeSuiteResult(mdxSafeMarkdownUnitTests.runTests()); - totalErrors += mdxSafeMarkdownUnitResult.errors.length; - totalWarnings += mdxSafeMarkdownUnitResult.warnings.length; - console.log(` ${mdxSafeMarkdownUnitResult.errors.length} errors, ${mdxSafeMarkdownUnitResult.warnings.length} warnings`); - - // Docs Page Scope Tests - console.log('\n🗂️ Running Docs Page Scope Tests...'); - const docsPageScopeResult = normalizeSuiteResult(docsPageScopeTests.runTests()); - totalErrors += docsPageScopeResult.errors.length; - totalWarnings += docsPageScopeResult.warnings.length; - console.log(` ${docsPageScopeResult.errors.length} errors, ${docsPageScopeResult.warnings.length} warnings`); - - // Docs Authoring Rules Tests - console.log('\n🧭 Running Docs Authoring Rules Tests...'); - const docsAuthoringRulesResult = normalizeSuiteResult(docsAuthoringRulesTests.runTests()); - totalErrors += docsAuthoringRulesResult.errors.length; - totalWarnings += docsAuthoringRulesResult.warnings.length; - console.log(` ${docsAuthoringRulesResult.errors.length} errors, ${docsAuthoringRulesResult.warnings.length} warnings`); - - // Frontmatter Taxonomy Tests - console.log('\n🧾 Running Frontmatter Taxonomy Tests...'); - const frontmatterTaxonomyResult = normalizeSuiteResult(frontmatterTaxonomyTests.runTests()); - totalErrors += frontmatterTaxonomyResult.errors.length; - totalWarnings += frontmatterTaxonomyResult.warnings.length; - console.log(` ${frontmatterTaxonomyResult.errors.length} errors, ${frontmatterTaxonomyResult.warnings.length} warnings`); + if (precommitBasic) { + console.log('\n🧪 Running Repo-wide Governance Unit Suites...'); + logPrecommitBasicSkip('hook lane is limited to staged syntax/style/content basics'); + } else { + // MDX Guardrails + console.log('\n🛡️ Running MDX Guardrail Tests...'); + const mdxGuardsResult = normalizeSuiteResult(mdxGuardsTests.runTests()); + totalErrors += mdxGuardsResult.errors.length; + totalWarnings += mdxGuardsResult.warnings.length; + console.log(` ${mdxGuardsResult.errors.length} errors, ${mdxGuardsResult.warnings.length} warnings`); + + // MDX-safe Markdown Unit Tests + console.log('\n🧪 Running MDX-safe Markdown Unit Tests...'); + const mdxSafeMarkdownUnitResult = normalizeSuiteResult(mdxSafeMarkdownUnitTests.runTests()); + totalErrors += mdxSafeMarkdownUnitResult.errors.length; + totalWarnings += mdxSafeMarkdownUnitResult.warnings.length; + console.log(` ${mdxSafeMarkdownUnitResult.errors.length} errors, ${mdxSafeMarkdownUnitResult.warnings.length} warnings`); + + // Docs Page Scope Tests + console.log('\n🗂️ Running Docs Page Scope Tests...'); + const docsPageScopeResult = normalizeSuiteResult(docsPageScopeTests.runTests()); + totalErrors += docsPageScopeResult.errors.length; + totalWarnings += docsPageScopeResult.warnings.length; + console.log(` ${docsPageScopeResult.errors.length} errors, ${docsPageScopeResult.warnings.length} warnings`); + + // Docs Authoring Rules Tests + console.log('\n🧭 Running Docs Authoring Rules Tests...'); + const docsAuthoringRulesResult = normalizeSuiteResult(docsAuthoringRulesTests.runTests()); + totalErrors += docsAuthoringRulesResult.errors.length; + totalWarnings += docsAuthoringRulesResult.warnings.length; + console.log(` ${docsAuthoringRulesResult.errors.length} errors, ${docsAuthoringRulesResult.warnings.length} warnings`); + + // Frontmatter Taxonomy Tests + console.log('\n🧾 Running Frontmatter Taxonomy Tests...'); + const frontmatterTaxonomyResult = normalizeSuiteResult(frontmatterTaxonomyTests.runTests()); + totalErrors += frontmatterTaxonomyResult.errors.length; + totalWarnings += frontmatterTaxonomyResult.warnings.length; + console.log(` ${frontmatterTaxonomyResult.errors.length} errors, ${frontmatterTaxonomyResult.warnings.length} warnings`); + } // Spelling Tests console.log('\n🔤 Running Spelling Tests...'); @@ -269,154 +279,159 @@ async function runAllTests() { totalWarnings += linksResult.warnings.length; console.log(` ${linksResult.errors.length} errors, ${linksResult.warnings.length} warnings`); - // Docs Navigation Validation - console.log('\n🧭 Running Docs Navigation Validation...'); - const docsNavigationResult = normalizeSuiteResult(docsNavigationTests.runTests({ writeReport: false })); - totalErrors += docsNavigationResult.errors.length; - totalWarnings += docsNavigationResult.warnings.length; - console.log(` ${docsNavigationResult.errors.length} errors, ${docsNavigationResult.warnings.length} warnings`); - - // Docs Path Sync Validation - console.log('\n🛤️ Running Docs Path Sync Validation...'); - const docsPathSyncResult = normalizeSuiteResult(docsPathSyncTests.runTests()); - totalErrors += docsPathSyncResult.errors.length; - totalWarnings += docsPathSyncResult.warnings.length; - console.log(` ${docsPathSyncResult.errors.length} errors, ${docsPathSyncResult.warnings.length} warnings`); - - // Script Docs Enforcement - console.log('\n🧾 Running Script Documentation Enforcement...'); - if (skipScriptDocs) { - console.log(' skipped (handled earlier in pre-commit)'); + if (precommitBasic) { + console.log('\n🧭 Running Extended Governance and Repo-wide Suites...'); + logPrecommitBasicSkip('run full test lane or CI for repo-wide governance and unit coverage'); } else { - const scriptDocsResult = normalizeSuiteResult(scriptDocsTests.runTests({ stagedOnly })); - totalErrors += scriptDocsResult.errors.length; - totalWarnings += scriptDocsResult.warnings.length; - console.log(` ${scriptDocsResult.errors.length} errors, ${scriptDocsResult.warnings.length} warnings`); - } + // Docs Navigation Validation + console.log('\n🧭 Running Docs Navigation Validation...'); + const docsNavigationResult = normalizeSuiteResult(docsNavigationTests.runTests({ writeReport: false })); + totalErrors += docsNavigationResult.errors.length; + totalWarnings += docsNavigationResult.warnings.length; + console.log(` ${docsNavigationResult.errors.length} errors, ${docsNavigationResult.warnings.length} warnings`); + + // Docs Path Sync Validation + console.log('\n🛤️ Running Docs Path Sync Validation...'); + const docsPathSyncResult = normalizeSuiteResult(docsPathSyncTests.runTests()); + totalErrors += docsPathSyncResult.errors.length; + totalWarnings += docsPathSyncResult.warnings.length; + console.log(` ${docsPathSyncResult.errors.length} errors, ${docsPathSyncResult.warnings.length} warnings`); + + // Script Docs Enforcement + console.log('\n🧾 Running Script Documentation Enforcement...'); + if (skipScriptDocs) { + console.log(' skipped (handled earlier in pre-commit)'); + } else { + const scriptDocsResult = normalizeSuiteResult(scriptDocsTests.runTests({ stagedOnly })); + totalErrors += scriptDocsResult.errors.length; + totalWarnings += scriptDocsResult.warnings.length; + console.log(` ${scriptDocsResult.errors.length} errors, ${scriptDocsResult.warnings.length} warnings`); + } - // Skill Docs Enforcement - console.log('\n📘 Running Skill Documentation Enforcement...'); - const skillDocsResult = normalizeSuiteResult(skillDocsTests.runTests({ stagedOnly })); - totalErrors += skillDocsResult.errors.length; - totalWarnings += skillDocsResult.warnings.length; - console.log(` ${skillDocsResult.errors.length} errors, ${skillDocsResult.warnings.length} warnings`); - - // AI-tools Registry Governance - console.log('\n🗂️ Running AI-tools Registry Checks...'); - const aiToolsRegistryResult = normalizeSuiteResult(aiToolsRegistryTests.runTests({ stagedOnly })); - totalErrors += aiToolsRegistryResult.errors.length; - totalWarnings += aiToolsRegistryResult.warnings.length; - if (aiToolsRegistryResult.skipped) { - console.log(' skipped (no staged AI-tools governance changes)'); - } else { + // Skill Docs Enforcement + console.log('\n📘 Running Skill Documentation Enforcement...'); + const skillDocsResult = normalizeSuiteResult(skillDocsTests.runTests({ stagedOnly })); + totalErrors += skillDocsResult.errors.length; + totalWarnings += skillDocsResult.warnings.length; + console.log(` ${skillDocsResult.errors.length} errors, ${skillDocsResult.warnings.length} warnings`); + + // AI-tools Registry Governance + console.log('\n🗂️ Running AI-tools Registry Checks...'); + const aiToolsRegistryResult = normalizeSuiteResult(aiToolsRegistryTests.runTests({ stagedOnly })); + totalErrors += aiToolsRegistryResult.errors.length; + totalWarnings += aiToolsRegistryResult.warnings.length; + if (aiToolsRegistryResult.skipped) { + console.log(' skipped (no staged AI-tools governance changes)'); + } else { + console.log( + ` ${aiToolsRegistryResult.errors.length} errors, ${aiToolsRegistryResult.warnings.length} warnings` + ); + } + + // Ownerless Governance + console.log('\n🧭 Running Ownerless Governance Checks...'); + const ownerlessGovernanceResult = normalizeSuiteResult(ownerlessGovernanceTests.runTests({ stagedOnly })); + totalErrors += ownerlessGovernanceResult.errors.length; + totalWarnings += ownerlessGovernanceResult.warnings.length; + console.log(` ${ownerlessGovernanceResult.errors.length} errors, ${ownerlessGovernanceResult.warnings.length} warnings`); + + // Agent Docs Freshness + console.log('\n🤖 Running Agent Docs Freshness Checks...'); + const agentDocsFreshnessResult = normalizeSuiteResult(checkAgentDocsFreshnessTests.runTests()); + totalErrors += agentDocsFreshnessResult.errors.length; + totalWarnings += agentDocsFreshnessResult.warnings.length; + console.log(` ${agentDocsFreshnessResult.errors.length} errors, ${agentDocsFreshnessResult.warnings.length} warnings`); + + // Root Allowlist Format + console.log('\n🧱 Running Root Allowlist Format Checks...'); + const rootAllowlistFormatResult = normalizeSuiteResult(rootAllowlistFormatTests.runTests()); + totalErrors += rootAllowlistFormatResult.errors.length; + totalWarnings += rootAllowlistFormatResult.warnings.length; + console.log(` ${rootAllowlistFormatResult.errors.length} errors, ${rootAllowlistFormatResult.warnings.length} warnings`); + + // Portable Skill Export + console.log('\n📦 Running Portable Skill Export Checks...'); + const exportPortableSkillsResult = normalizeSuiteResult(await exportPortableSkillsTests.runTests()); + totalErrors += exportPortableSkillsResult.errors.length; + totalWarnings += exportPortableSkillsResult.warnings.length; + console.log(` ${exportPortableSkillsResult.errors.length} errors, ${exportPortableSkillsResult.warnings.length} warnings`); + + // Docs-guide Source of Truth + console.log('\n📚 Running Docs-guide Source-of-Truth Checks...'); + if (hasStagedDocsGuideSotChanges()) { + const docsGuideSotResult = normalizeSuiteResult(docsGuideSotTests.runTests({ stagedOnly })); + totalErrors += docsGuideSotResult.errors.length; + totalWarnings += docsGuideSotResult.warnings.length; + console.log(` ${docsGuideSotResult.errors.length} errors, ${docsGuideSotResult.warnings.length} warnings`); + } else { + console.log(' skipped (no staged docs-guide source-of-truth changes)'); + } + + // Pre-commit Cache Unit Tests + console.log('\n🧮 Running Pre-commit Cache Unit Tests...'); + const precommitStagedCacheResult = normalizeSuiteResult(await precommitStagedCacheTests.runTests()); + totalErrors += precommitStagedCacheResult.errors.length; + totalWarnings += precommitStagedCacheResult.warnings.length; console.log( - ` ${aiToolsRegistryResult.errors.length} errors, ${aiToolsRegistryResult.warnings.length} warnings` + ` ${precommitStagedCacheResult.errors.length} errors, ${precommitStagedCacheResult.warnings.length} warnings` ); - } - // Ownerless Governance - console.log('\n🧭 Running Ownerless Governance Checks...'); - const ownerlessGovernanceResult = normalizeSuiteResult(ownerlessGovernanceTests.runTests({ stagedOnly })); - totalErrors += ownerlessGovernanceResult.errors.length; - totalWarnings += ownerlessGovernanceResult.warnings.length; - console.log(` ${ownerlessGovernanceResult.errors.length} errors, ${ownerlessGovernanceResult.warnings.length} warnings`); - - // Agent Docs Freshness - console.log('\n🤖 Running Agent Docs Freshness Checks...'); - const agentDocsFreshnessResult = normalizeSuiteResult(checkAgentDocsFreshnessTests.runTests()); - totalErrors += agentDocsFreshnessResult.errors.length; - totalWarnings += agentDocsFreshnessResult.warnings.length; - console.log(` ${agentDocsFreshnessResult.errors.length} errors, ${agentDocsFreshnessResult.warnings.length} warnings`); - - // Root Allowlist Format - console.log('\n🧱 Running Root Allowlist Format Checks...'); - const rootAllowlistFormatResult = normalizeSuiteResult(rootAllowlistFormatTests.runTests()); - totalErrors += rootAllowlistFormatResult.errors.length; - totalWarnings += rootAllowlistFormatResult.warnings.length; - console.log(` ${rootAllowlistFormatResult.errors.length} errors, ${rootAllowlistFormatResult.warnings.length} warnings`); - - // Portable Skill Export - console.log('\n📦 Running Portable Skill Export Checks...'); - const exportPortableSkillsResult = normalizeSuiteResult(await exportPortableSkillsTests.runTests()); - totalErrors += exportPortableSkillsResult.errors.length; - totalWarnings += exportPortableSkillsResult.warnings.length; - console.log(` ${exportPortableSkillsResult.errors.length} errors, ${exportPortableSkillsResult.warnings.length} warnings`); - - // Docs-guide Source of Truth - console.log('\n📚 Running Docs-guide Source-of-Truth Checks...'); - if (hasStagedDocsGuideSotChanges()) { - const docsGuideSotResult = normalizeSuiteResult(docsGuideSotTests.runTests({ stagedOnly })); - totalErrors += docsGuideSotResult.errors.length; - totalWarnings += docsGuideSotResult.warnings.length; - console.log(` ${docsGuideSotResult.errors.length} errors, ${docsGuideSotResult.warnings.length} warnings`); - } else { - console.log(' skipped (no staged docs-guide source-of-truth changes)'); - } + // UI Template Generator + console.log('\n🧱 Running UI Template Generator Checks...'); + if (hasStagedUiTemplateChanges()) { + const uiTemplateGeneratorResult = normalizeSuiteResult(uiTemplateGeneratorTests.runTests()); + totalErrors += uiTemplateGeneratorResult.errors.length; + totalWarnings += uiTemplateGeneratorResult.warnings.length; + console.log(` ${uiTemplateGeneratorResult.errors.length} errors, ${uiTemplateGeneratorResult.warnings.length} warnings`); + } else { + console.log(' skipped (no staged UI template changes)'); + } - // Pre-commit Cache Unit Tests - console.log('\n🧮 Running Pre-commit Cache Unit Tests...'); - const precommitStagedCacheResult = normalizeSuiteResult(await precommitStagedCacheTests.runTests()); - totalErrors += precommitStagedCacheResult.errors.length; - totalWarnings += precommitStagedCacheResult.warnings.length; - console.log( - ` ${precommitStagedCacheResult.errors.length} errors, ${precommitStagedCacheResult.warnings.length} warnings` - ); + // Component Governance Utility Tests + console.log('\n🧩 Running Component Governance Utility Tests...'); + const componentGovernanceUtilsResult = normalizeSuiteResult(componentGovernanceUtilsTests.runTests()); + totalErrors += componentGovernanceUtilsResult.errors.length; + totalWarnings += componentGovernanceUtilsResult.warnings.length; + console.log( + ` ${componentGovernanceUtilsResult.errors.length} errors, ${componentGovernanceUtilsResult.warnings.length} warnings` + ); - // UI Template Generator - console.log('\n🧱 Running UI Template Generator Checks...'); - if (hasStagedUiTemplateChanges()) { - const uiTemplateGeneratorResult = normalizeSuiteResult(uiTemplateGeneratorTests.runTests()); - totalErrors += uiTemplateGeneratorResult.errors.length; - totalWarnings += uiTemplateGeneratorResult.warnings.length; - console.log(` ${uiTemplateGeneratorResult.errors.length} errors, ${uiTemplateGeneratorResult.warnings.length} warnings`); - } else { - console.log(' skipped (no staged UI template changes)'); - } + // Component Governance Generator Tests + console.log('\n🗂️ Running Component Governance Generator Tests...'); + if (hasStagedComponentGovernanceChanges()) { + const componentGovernanceGeneratorResult = normalizeSuiteResult(componentGovernanceGeneratorTests.runTests()); + totalErrors += componentGovernanceGeneratorResult.errors.length; + totalWarnings += componentGovernanceGeneratorResult.warnings.length; + console.log( + ` ${componentGovernanceGeneratorResult.errors.length} errors, ${componentGovernanceGeneratorResult.warnings.length} warnings` + ); + } else { + console.log(' skipped (no staged component governance changes)'); + } - // Component Governance Utility Tests - console.log('\n🧩 Running Component Governance Utility Tests...'); - const componentGovernanceUtilsResult = normalizeSuiteResult(componentGovernanceUtilsTests.runTests()); - totalErrors += componentGovernanceUtilsResult.errors.length; - totalWarnings += componentGovernanceUtilsResult.warnings.length; - console.log( - ` ${componentGovernanceUtilsResult.errors.length} errors, ${componentGovernanceUtilsResult.warnings.length} warnings` - ); + // Usefulness Unit Tests + console.log('\n📈 Running Usefulness Unit Tests...'); + const usefulnessRubricCheck = spawnSync( + 'node', + ['tests/unit/usefulness-rubric.test.js'], + { cwd: REPO_ROOT, encoding: 'utf8' } + ); + if (usefulnessRubricCheck.stdout) process.stdout.write(usefulnessRubricCheck.stdout); + if (usefulnessRubricCheck.stderr) process.stderr.write(usefulnessRubricCheck.stderr); + if (usefulnessRubricCheck.status !== 0) totalErrors += 1; - // Component Governance Generator Tests - console.log('\n🗂️ Running Component Governance Generator Tests...'); - if (hasStagedComponentGovernanceChanges()) { - const componentGovernanceGeneratorResult = normalizeSuiteResult(componentGovernanceGeneratorTests.runTests()); - totalErrors += componentGovernanceGeneratorResult.errors.length; - totalWarnings += componentGovernanceGeneratorResult.warnings.length; - console.log( - ` ${componentGovernanceGeneratorResult.errors.length} errors, ${componentGovernanceGeneratorResult.warnings.length} warnings` + const usefulnessJourneyCheck = spawnSync( + 'node', + ['tests/unit/usefulness-journey.test.js'], + { cwd: REPO_ROOT, encoding: 'utf8' } ); - } else { - console.log(' skipped (no staged component governance changes)'); + if (usefulnessJourneyCheck.stdout) process.stdout.write(usefulnessJourneyCheck.stdout); + if (usefulnessJourneyCheck.stderr) process.stderr.write(usefulnessJourneyCheck.stderr); + if (usefulnessJourneyCheck.status !== 0) totalErrors += 1; + const usefulnessFailures = (usefulnessRubricCheck.status === 0 ? 0 : 1) + (usefulnessJourneyCheck.status === 0 ? 0 : 1); + console.log(` ${usefulnessFailures} errors, 0 warnings`); } - // Usefulness Unit Tests - console.log('\n📈 Running Usefulness Unit Tests...'); - const usefulnessRubricCheck = spawnSync( - 'node', - ['tests/unit/usefulness-rubric.test.js'], - { cwd: REPO_ROOT, encoding: 'utf8' } - ); - if (usefulnessRubricCheck.stdout) process.stdout.write(usefulnessRubricCheck.stdout); - if (usefulnessRubricCheck.stderr) process.stderr.write(usefulnessRubricCheck.stderr); - if (usefulnessRubricCheck.status !== 0) totalErrors += 1; - - const usefulnessJourneyCheck = spawnSync( - 'node', - ['tests/unit/usefulness-journey.test.js'], - { cwd: REPO_ROOT, encoding: 'utf8' } - ); - if (usefulnessJourneyCheck.stdout) process.stdout.write(usefulnessJourneyCheck.stdout); - if (usefulnessJourneyCheck.stderr) process.stderr.write(usefulnessJourneyCheck.stderr); - if (usefulnessJourneyCheck.status !== 0) totalErrors += 1; - const usefulnessFailures = (usefulnessRubricCheck.status === 0 ? 0 : 1) + (usefulnessJourneyCheck.status === 0 ? 0 : 1); - console.log(` ${usefulnessFailures} errors, 0 warnings`); - // Pages Index Sync Validation console.log('\n🗂️ Running Pages Index Sync Validation...'); if (skipPagesIndex) { From a7e3bd171a9fd3f712e918e89d4f8fefa7305859 Mon Sep 17 00:00:00 2001 From: AlisonWonderland Date: Tue, 17 Mar 2026 07:48:57 +1100 Subject: [PATCH 3/5] orch update --- ai-tools/ai-skills/page-authoring/SKILL.md | 2 +- docs.json | 249 +++++++++--------- .../_workspace/reviews/guides/human-review.md | 5 +- 3 files changed, 132 insertions(+), 124 deletions(-) diff --git a/ai-tools/ai-skills/page-authoring/SKILL.md b/ai-tools/ai-skills/page-authoring/SKILL.md index eaeddf8e1..b6d63198a 100644 --- a/ai-tools/ai-skills/page-authoring/SKILL.md +++ b/ai-tools/ai-skills/page-authoring/SKILL.md @@ -104,7 +104,7 @@ Do not hardcode your own enum list in local docs or prompts. - Prefer governed snippets/components before inventing new presentation patterns - Use cards for navigation, tables for exact comparisons, steps for sequential task completion, and accordions for optional depth - If styling pressure is high, solve it in a component primitive rather than in page-level MDX -- **Never stack consecutive tables.** Two StyledTables back-to-back is a layout failure. Use tabs, accordions, cards, bordered boxes, or prose to break up tabular content. The component library has over 100 components - use them. +- **Maximum 1-2 tables per page.** Tables support prose - they do not replace it. A page with more tables than paragraphs is a spreadsheet, not documentation. If information feels tabular, consider whether cards, accordions, or bordered boxes communicate it better. Never stack consecutive tables. ### Terminology and context diff --git a/docs.json b/docs.json index 646342647..50ceb1194 100644 --- a/docs.json +++ b/docs.json @@ -2857,158 +2857,164 @@ { "tab": "Orchestrators", "icon": "microchip", - "anchors": [ + "groups": [ { - "anchor": "Orchestrators", + "group": "Start Here", "icon": "microchip", - "groups": [ + "pages": [ + "v2/orchestrators/portal", + "v2/orchestrators/navigator" + ] + }, + { + "group": "Concepts", + "icon": "book-open", + "pages": [ + "v2/orchestrators/concepts/role", + "v2/orchestrators/concepts/capabilities", + "v2/orchestrators/concepts/architecture", + "v2/orchestrators/concepts/incentive-model" + ] + }, + { + "group": "Quickstart", + "icon": "bolt", + "pages": [ + "v2/orchestrators/quickstart/guide", + "v2/orchestrators/quickstart/video-transcoding", + "v2/orchestrators/quickstart/tutorial", + "v2/orchestrators/quickstart/ai-prompt-start" + ] + }, + { + "group": "Setup", + "icon": "gear", + "pages": [ + "v2/orchestrators/setup/guide", + "v2/orchestrators/setup/rcs-requirements", + "v2/orchestrators/setup/rs-install", + "v2/orchestrators/setup/configure", + "v2/orchestrators/setup/connect-and-activate", + "v2/orchestrators/setup/test", + "v2/orchestrators/setup/r-monitor" + ] + }, + { + "group": "Guides", + "icon": "chart-line", + "pages": [ { - "group": "Start Here", - "icon": "microchip", + "group": "Operator Considerations", "pages": [ - "v2/orchestrators/portal", - "v2/orchestrators/navigator" + "v2/orchestrators/guides/operator-considerations/operator-rationale", + "v2/orchestrators/guides/operator-considerations/business-case", + "v2/orchestrators/guides/operator-considerations/operator-impact", + "v2/orchestrators/guides/operator-considerations/requirements" ] }, { - "group": "Concepts", - "icon": "book-open", + "group": "Deployment Details", "pages": [ - "v2/orchestrators/concepts/role", - "v2/orchestrators/concepts/capabilities", - "v2/orchestrators/concepts/architecture", - "v2/orchestrators/concepts/incentive-model" + "v2/orchestrators/guides/deployment-details/setup-options", + "v2/orchestrators/guides/deployment-details/draft1-setup-options", + "v2/orchestrators/guides/deployment-details/x-deprecated/dep-3-setup-options", + "v2/orchestrators/guides/deployment-details/siphon-setup", + "v2/orchestrators/guides/deployment-details/dual-mode-configuration", + "v2/orchestrators/guides/deployment-details/orchestrator-transcoder-setup", + "v2/orchestrators/guides/deployment-details/join-a-pool", + "v2/orchestrators/guides/deployment-details/new-join-a-pool" ] }, { - "group": "Quickstart", - "icon": "bolt", + "group": "Workloads and AI", "pages": [ - "v2/orchestrators/quickstart/guide", - "v2/orchestrators/quickstart/video-transcoding" + "v2/orchestrators/guides/ai-and-job-workloads/workload-options", + "v2/orchestrators/guides/ai-and-job-workloads/video-transcoding-operations", + "v2/orchestrators/guides/ai-and-job-workloads/ai-inference-operations", + "v2/orchestrators/guides/ai-and-job-workloads/diffusion-pipeline-setup", + "v2/orchestrators/guides/ai-and-job-workloads/llm-pipeline-setup", + "v2/orchestrators/guides/ai-and-job-workloads/realtime-ai-setup", + "v2/orchestrators/guides/ai-and-job-workloads/audio-and-vision-pipelines", + "v2/orchestrators/guides/ai-and-job-workloads/model-demand-reference", + "v2/orchestrators/guides/ai-and-job-workloads/model-hosting" ] }, { - "group": "Setup", - "icon": "gear", + "group": "Staking and Earning", "pages": [ - "v2/orchestrators/setup/guide", - "v2/orchestrators/setup/rcs-requirements", - "v2/orchestrators/setup/rs-install", - "v2/orchestrators/setup/r-configure", - "v2/orchestrators/setup/sc-connect", - "v2/orchestrators/setup/activate", - "v2/orchestrators/setup/test", - "v2/orchestrators/setup/r-monitor" + "v2/orchestrators/guides/staking-and-rewards/earning-model", + "v2/orchestrators/guides/staking-and-rewards/reward-mechanics", + "v2/orchestrators/guides/payments-and-pricing/payment-receipts", + "v2/orchestrators/guides/payments-and-pricing/payments", + "v2/orchestrators/guides/staking-and-rewards/delegate-operations", + "v2/orchestrators/guides/staking-and-rewards/network-participation" ] }, { - "group": "Guides", - "icon": "chart-line", + "group": "Config and Optimisation", "pages": [ - { - "group": "Feasibility & Hardware", - "pages": [ - "v2/orchestrators/guides/feasibility-and-hardware/feasibility-economics", - "v2/orchestrators/guides/feasibility-and-hardware/hardware-reference", - "v2/orchestrators/guides/feasibility-and-hardware/benchmarking", - "v2/orchestrators/guides/feasibility-and-hardware/session-limits" - ] - }, - { - "group": "Setup Paths", - "pages": [ - "v2/orchestrators/guides/setup-paths/setup-navigator", - "v2/orchestrators/guides/setup-paths/find-your-path", - "v2/orchestrators/guides/setup-paths/join-a-pool", - "v2/orchestrators/guides/setup-paths/siphon-setup" - ] - }, - { - "group": "Staking & Rewards", - "pages": [ - "v2/orchestrators/guides/staking-and-rewards/earnings", - "v2/orchestrators/guides/staking-and-rewards/rewards-and-fees", - "v2/orchestrators/guides/staking-and-rewards/attracting-delegates", - "v2/orchestrators/guides/staking-and-rewards/payments", - "v2/orchestrators/guides/staking-and-rewards/governance" - ] - }, - { - "group": "Workloads & AI", - "pages": [ - "v2/orchestrators/guides/workloads-and-ai/job-types", - "v2/orchestrators/guides/workloads-and-ai/video-transcoding", - "v2/orchestrators/guides/workloads-and-ai/ai-workloads-guide", - "v2/orchestrators/guides/workloads-and-ai/batch-ai-setup", - "v2/orchestrators/guides/workloads-and-ai/realtime-ai-setup", - "v2/orchestrators/guides/workloads-and-ai/model-vram-reference" - ] - }, - { - "group": "Monitoring & Troubleshooting", - "pages": [ - "v2/orchestrators/guides/monitoring-and-troubleshooting/tools", - "v2/orchestrators/guides/monitoring-and-troubleshooting/explorer-guide", - "v2/orchestrators/guides/monitoring-and-troubleshooting/metrics-monitoring", - "v2/orchestrators/guides/monitoring-and-troubleshooting/troubleshooting" - ] - }, - { - "group": "Advanced Operations", - "pages": [ - "v2/orchestrators/guides/advanced-operations/run-a-pool", - "v2/orchestrators/guides/advanced-operations/gateways-orchestrators", - "v2/orchestrators/guides/advanced-operations/large-scale-operations", - "v2/orchestrators/guides/advanced-operations/orchestrator-transcoder-setup" - ] - } + "v2/orchestrators/guides/config-and-optimisation/pricing-strategy", + "v2/orchestrators/guides/config-and-optimisation/capacity-planning", + "v2/orchestrators/guides/config-and-optimisation/ai-model-management", + "v2/orchestrators/guides/config-and-optimisation/reward-call-tuning" ] }, { - "group": "Resources", - "icon": "books", + "group": "Monitoring and Tools", "pages": [ - "v2/orchestrators/resources/faq", - "v2/orchestrators/resources/community-guides", - "v2/orchestrators/resources/community-pools", - { - "group": "Technical Reference", - "pages": [ - "v2/orchestrators/resources/technical/cli-flags", - "v2/orchestrators/resources/technical/x-contract-addresses", - "v2/orchestrators/resources/gpu-support", - "v2/orchestrators/resources/arbitrum-rpc", - "v2/orchestrators/resources/arbitrum-exchanges", - "v2/orchestrators/resources/technical/x-troubleshooting", - "v2/orchestrators/resources/technical/x-changelog", - "v2/orchestrators/resources/technical/x-support-status" - ] - }, - { - "group": "Guides Index [Review]", - "pages": [ - "v2/orchestrators/resources/x-guides", - "v2/orchestrators/resources/x-help", - "v2/orchestrators/resources/x-payments" - ] - } + "v2/orchestrators/guides/monitoring-and-tooling/operator-toolbox", + "v2/orchestrators/guides/monitoring-and-tooling/explorer-operations", + "v2/orchestrators/guides/monitoring-and-tooling/metrics-and-alerting", + "v2/orchestrators/guides/monitoring-and-tooling/troubleshooting" + ] + }, + { + "group": "Advanced Operations", + "pages": [ + "v2/orchestrators/guides/advanced-operations/gateway-relationships", + "v2/orchestrators/guides/advanced-operations/gateway-orchestrator-interface", + "v2/orchestrators/guides/advanced-operations/pool-operators", + "v2/orchestrators/guides/advanced-operations/scale-operations" + ] + }, + { + "group": "Roadmap and Funding", + "pages": [ + "v2/orchestrators/guides/roadmap-and-funding/funding-and-support", + "v2/orchestrators/guides/roadmap-and-funding/orchestrator-profiles" + ] + }, + { + "group": "Tutorials", + "pages": [ + "v2/orchestrators/guides/tutorials/byoc-cpu-smoke-test", + "v2/orchestrators/guides/tutorials/zero-to-first-reward", + "v2/orchestrators/guides/tutorials/ai-earning-quickstart", + "v2/orchestrators/guides/tutorials/add-ai-to-video-node", + "v2/orchestrators/guides/tutorials/full-ai-pipeline-tutorial", + "v2/orchestrators/guides/tutorials/realtime-ai-tutorial" ] } ] }, { - "anchor": "Resource HUB", + "group": "Resources", "icon": "books", "pages": [ - "v2/resources/redirect" - ] - }, - { - "anchor": " ", - "icon": "horizontal-rule", - "pages": [ - " " + "v2/orchestrators/resources/faq", + "v2/orchestrators/resources/glossary", + "v2/orchestrators/resources/community-guides", + "v2/orchestrators/resources/community-pools", + { + "group": "Technical Reference", + "pages": [ + "v2/orchestrators/resources/technical/cli-flags", + "v2/orchestrators/resources/technical/x-contract-addresses", + "v2/orchestrators/resources/gpu-support", + "v2/orchestrators/resources/arbitrum-rpc", + "v2/orchestrators/resources/arbitrum-exchanges" + ] + } ] } ] @@ -3172,7 +3178,6 @@ "group": "Resources", "icon": "books", "pages": [ - "v2/resources/redirect", "v2/resources/resources-portal", "contribute/CONTRIBUTING" ] diff --git a/v2/orchestrators/_workspace/reviews/guides/human-review.md b/v2/orchestrators/_workspace/reviews/guides/human-review.md index 24643f493..91c1a5f51 100644 --- a/v2/orchestrators/_workspace/reviews/guides/human-review.md +++ b/v2/orchestrators/_workspace/reviews/guides/human-review.md @@ -40,6 +40,8 @@ Patterns from human review to feed back into authoring skills. | # | Issue | Context | Human decision | Type | |---|-------|---------|---------------|------| +| 24 | Too many tables on one page | draft1 has 6 StyledTables. Page is almost entirely tabular with almost zero prose. | Max 1-2 tables per page. Tables should support prose, not replace it. | Layout | +| 25 | No prose, all tables | Page reads like a spreadsheet, not documentation. Tables are data, not explanation. | Pages need prose to explain WHY and WHAT. Tables are supporting evidence, not the content itself. | Content | | 21 | Proposed rewrite leads with definitions | AI proposed "Ground zero: Definitions" as the first section - defining axes before presenting options | Definitions ARE the options. Don't define axes then present options separately. Combine. | Structure | | 22 | "What are my options?" is a lazy framing of the reader's question | AI framed the page purpose as answering "what are my options for running an orchestrator?" | The reader is past "should I?" - they're here because they're ready to set up. The real question is "which setup path matches my situation?" | Content | | 23 | Preamble before the answer | Multiple proposed structures put context, definitions, or framing before the actual options | Answer the reader's question IMMEDIATELY. First thing on the page. No preamble. | Structure | @@ -63,7 +65,8 @@ Patterns from human review to feed back into authoring skills. | **Preamble before the answer** - pages put context/definitions/framing before the thing the reader came for | setup-options | Authoring skill: answer the reader's question FIRST. Context supports the answer, it doesn't precede it. | | **Lazy question framing** - AI identifies the reader's question as generic ("what are my options?") instead of specific | setup-options | Authoring skill: identify the SPECIFIC question the reader has at this point in their journey, not a generic version. The reader's journey position determines the question. | | **Single value prop anchoring** - AI latches onto one reason per option and repeats it across every response | setup-options (pool node = "no LPT" every time) | Authoring skill: minimum 5 distinct value props per option across different dimensions (financial, operational, risk, time, complexity, flexibility). Challenge own anchoring. | -| **Consecutive tables** - stacking StyledTable after StyledTable creates a wall of tabular data with no visual relief | setup-options (draft1 has 6 consecutive tables) | Authoring skill: never stack tables. Use tabs, accordions, cards, bordered boxes, or prose between tables. 100+ components exist - use them. | +| **Consecutive tables** - stacking StyledTable after StyledTable creates a wall of tabular data with no visual relief | setup-options (draft1 has 6 tables) | Authoring skill: never stack tables. Max 1-2 tables per page. Use tabs, accordions, cards, bordered boxes, or prose between tables. | +| **Tables replacing prose** - page is almost entirely tabular with no explanatory text | setup-options (draft1) | Authoring skill: tables support prose, they don't replace it. A page with no prose is a spreadsheet, not documentation. | --- From 08167a5a02723f81432db434c866195d289071a5 Mon Sep 17 00:00:00 2001 From: AlisonWonderland Date: Tue, 17 Mar 2026 07:50:21 +1100 Subject: [PATCH 4/5] orch update --- docs.json | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/docs.json b/docs.json index 50ceb1194..fbb750c6c 100644 --- a/docs.json +++ b/docs.json @@ -2584,11 +2584,11 @@ ] }, { - "tab": "Gateways", + "tab": "Gateways NEW", "icon": "torii-gate", "anchors": [ { - "anchor": "Gateways", + "anchor": "Gateways NEW", "icon": "torii-gate", "groups": [ { @@ -2703,7 +2703,7 @@ ] }, { - "group": "AI & Job Pipelines", + "group": "AI and Job Pipelines", "pages": [ "v2/gateways/guides/node-pipelines/guide", "v2/gateways/guides/node-pipelines/video-pipelines", @@ -2713,7 +2713,7 @@ ] }, { - "group": "Payments & Pricing", + "group": "Payments and Pricing", "pages": [ "v2/gateways/guides/payments-and-pricing/payment-guide", "v2/gateways/guides/payments-and-pricing/funding-guide", @@ -2837,20 +2837,6 @@ ] } ] - }, - { - "anchor": "Resource HUB", - "icon": "books", - "pages": [ - "v2/resources/redirect" - ] - }, - { - "anchor": " ", - "icon": "horizontal-rule", - "pages": [ - " " - ] } ] }, From fb44600bfb2978e6bc368668e7c669b2e6653e4e Mon Sep 17 00:00:00 2001 From: AlisonWonderland Date: Tue, 17 Mar 2026 08:12:39 +1100 Subject: [PATCH 5/5] update docs.json --- docs.json | 297 +++++++++++++----- .../navigation-links/navigation-report.json | 8 +- .../navigation-links/navigation-report.md | 6 +- v2/gateways/quickstart/gateway-setup.mdx | 2 +- v2/index.mdx | 111 +++---- v2/orchestrators/index.mdx | 111 +++---- v2/orchestrators/portal.mdx | 2 +- 7 files changed, 335 insertions(+), 202 deletions(-) diff --git a/docs.json b/docs.json index fbb750c6c..83be66b2b 100644 --- a/docs.json +++ b/docs.json @@ -2096,10 +2096,7 @@ { "group": "Home", "icon": "house-heart", - "pages": [ - "v2/home/mission-control", - "v2/home/primer" - ] + "pages": ["v2/home/mission-control", "v2/home/primer"] }, { "group": "Livepeer", @@ -2126,16 +2123,12 @@ { "anchor": "Resource HUB", "icon": "books", - "pages": [ - "v2/resources/redirect" - ] + "pages": ["v2/resources/redirect"] }, { "anchor": " ", "icon": "horizontal-rule", - "pages": [ - " " - ] + "pages": [" "] } ] }, @@ -2197,16 +2190,12 @@ { "anchor": "Resource HUB", "icon": "books", - "pages": [ - "v2/resources/redirect" - ] + "pages": ["v2/resources/redirect"] }, { "anchor": " ", "icon": "horizontal-rule", - "pages": [ - " " - ] + "pages": [" "] } ] }, @@ -2230,16 +2219,12 @@ { "group": "Daydream", "icon": "camera-movie", - "pages": [ - "v2/solutions/daydream/overview" - ] + "pages": ["v2/solutions/daydream/overview"] }, { "group": "Livepeer Studio", "icon": "film-canister", - "pages": [ - "v2/solutions/livepeer-studio/overview" - ] + "pages": ["v2/solutions/livepeer-studio/overview"] }, { "group": "Stream.place", @@ -2261,16 +2246,12 @@ { "group": "Embody Avatars", "icon": "user-robot", - "pages": [ - "v2/solutions/embody/overview" - ] + "pages": ["v2/solutions/embody/overview"] }, { "group": "Frameworks", "icon": "clapperboard-play", - "pages": [ - "v2/solutions/frameworks/overview" - ] + "pages": ["v2/solutions/frameworks/overview"] } ] }, @@ -2330,9 +2311,7 @@ }, { "group": "Player & embed", - "pages": [ - "v2/solutions/livepeer-studio/player" - ] + "pages": ["v2/solutions/livepeer-studio/player"] }, { "group": "Reference", @@ -2471,16 +2450,12 @@ { "anchor": "Resource HUB", "icon": "books", - "pages": [ - "v2/resources/redirect" - ] + "pages": ["v2/resources/redirect"] }, { "anchor": " ", "icon": "horizontal-rule", - "pages": [ - " " - ] + "pages": [" "] } ] }, @@ -2570,21 +2545,17 @@ { "anchor": "Resource HUB", "icon": "books", - "pages": [ - "v2/resources/redirect" - ] + "pages": ["v2/resources/redirect"] }, { "anchor": " ", "icon": "horizontal-rule", - "pages": [ - " " - ] + "pages": [" "] } ] }, { - "tab": "Gateways NEW", + "tab": "Gateways", "icon": "torii-gate", "anchors": [ { @@ -3066,16 +3037,12 @@ { "anchor": "Resource HUB", "icon": "books", - "pages": [ - "v2/resources/redirect" - ] + "pages": ["v2/resources/redirect"] }, { "anchor": " ", "icon": "horizontal-rule", - "pages": [ - " " - ] + "pages": [" "] } ] }, @@ -3129,25 +3096,19 @@ { "group": "Help Center", "icon": "comments-question-check", - "pages": [ - "v2/community/faq" - ] + "pages": ["v2/community/faq"] } ] }, { "anchor": "Resource HUB", "icon": "books", - "pages": [ - "v2/resources/redirect" - ] + "pages": ["v2/resources/redirect"] }, { "anchor": " ", "icon": "horizontal-rule", - "pages": [ - " " - ] + "pages": [" "] } ] }, @@ -3207,9 +3168,7 @@ { "group": "Developer References", "icon": "book", - "pages": [ - "v2/resources/livepeer-glossary" - ] + "pages": ["v2/resources/livepeer-glossary"] }, { "group": "Gateway References", @@ -3221,37 +3180,27 @@ { "group": "Orchestrator References", "icon": "microchip", - "pages": [ - "v2/resources/livepeer-glossary" - ] + "pages": ["v2/resources/livepeer-glossary"] }, { "group": "LPT & Delegator References", "icon": "hand-holding-dollar", - "pages": [ - "v2/resources/livepeer-glossary" - ] + "pages": ["v2/resources/livepeer-glossary"] }, { "group": "Community Resources", "icon": "", - "pages": [ - "v2/resources/livepeer-glossary" - ] + "pages": ["v2/resources/livepeer-glossary"] }, { "group": "Partner Resources", "icon": "handshake", - "pages": [ - "v2/resources/livepeer-glossary" - ] + "pages": ["v2/resources/livepeer-glossary"] }, { "group": "Help Center", "icon": "comments-question-check", - "pages": [ - "v2/resources/livepeer-glossary" - ] + "pages": ["v2/resources/livepeer-glossary"] }, { "group": "Technical References", @@ -3259,9 +3208,7 @@ "pages": [ { "group": "Protocol References", - "pages": [ - " " - ] + "pages": [" "] } ] }, @@ -3278,9 +3225,7 @@ { "anchor": "Help Center", "icon": "comments-question-check", - "pages": [ - "v2/resources/redirect" - ] + "pages": ["v2/resources/redirect"] }, { "anchor": " ", @@ -3446,6 +3391,192 @@ ] } ] + }, + { + "language": "es", + "tabs": [ + { + "tab": "About", + "icon": "camera-movie", + "anchors": [ + { + "anchor": "About Livepeer", + "icon": "play", + "groups": [ + { + "group": "About Livepeer", + "icon": "graduation-cap", + "pages": [ + "v2/es/about/portal", + "v2/es/about/livepeer-overview", + "v2/es/about/core-concepts", + "v2/es/about/mental-model" + ] + }, + { + "group": "Livepeer Protocol", + "icon": "cube", + "pages": [ + "v2/es/about/livepeer-protocol/overview", + "v2/es/about/livepeer-protocol/core-mechanisms", + "v2/es/about/livepeer-protocol/livepeer-token", + "v2/es/about/livepeer-protocol/governance-model", + "v2/es/about/livepeer-protocol/treasury", + "v2/es/about/livepeer-protocol/economics", + "v2/es/about/livepeer-protocol/technical-architecture" + ] + }, + { + "group": "Livepeer Network", + "icon": "circle-nodes", + "pages": [ + "v2/es/about/livepeer-network/overview", + "v2/es/about/livepeer-network/actors", + "v2/es/about/livepeer-network/job-lifecycle", + "v2/es/about/livepeer-network/marketplace", + "v2/es/about/livepeer-network/technical-architecture", + "v2/es/about/livepeer-network/interfaces" + ] + }, + { + "group": "Resources", + "icon": "books", + "pages": [ + "v2/es/about/resources/livepeer-whitepaper", + "v2/es/about/resources/livepeer-glossary", + "v2/es/about/resources/blockchain-contracts", + "v2/es/about/resources/technical-roadmap" + ] + } + ] + } + ] + } + ] + }, + { + "language": "fr", + "tabs": [ + { + "tab": "About", + "icon": "camera-movie", + "anchors": [ + { + "anchor": "About Livepeer", + "icon": "play", + "groups": [ + { + "group": "About Livepeer", + "icon": "graduation-cap", + "pages": [ + "v2/fr/about/portal", + "v2/fr/about/livepeer-overview", + "v2/fr/about/core-concepts", + "v2/fr/about/mental-model" + ] + }, + { + "group": "Livepeer Protocol", + "icon": "cube", + "pages": [ + "v2/fr/about/livepeer-protocol/overview", + "v2/fr/about/livepeer-protocol/core-mechanisms", + "v2/fr/about/livepeer-protocol/livepeer-token", + "v2/fr/about/livepeer-protocol/governance-model", + "v2/fr/about/livepeer-protocol/treasury", + "v2/fr/about/livepeer-protocol/economics", + "v2/fr/about/livepeer-protocol/technical-architecture" + ] + }, + { + "group": "Livepeer Network", + "icon": "circle-nodes", + "pages": [ + "v2/fr/about/livepeer-network/overview", + "v2/fr/about/livepeer-network/actors", + "v2/fr/about/livepeer-network/job-lifecycle", + "v2/fr/about/livepeer-network/marketplace", + "v2/fr/about/livepeer-network/technical-architecture", + "v2/fr/about/livepeer-network/interfaces" + ] + }, + { + "group": "Resources", + "icon": "books", + "pages": [ + "v2/fr/about/resources/livepeer-whitepaper", + "v2/fr/about/resources/livepeer-glossary", + "v2/fr/about/resources/blockchain-contracts", + "v2/fr/about/resources/technical-roadmap" + ] + } + ] + } + ] + } + ] + }, + { + "language": "cn", + "tabs": [ + { + "tab": "About", + "icon": "camera-movie", + "anchors": [ + { + "anchor": "About Livepeer", + "icon": "play", + "groups": [ + { + "group": "About Livepeer", + "icon": "graduation-cap", + "pages": [ + "v2/cn/about/portal", + "v2/cn/about/livepeer-overview", + "v2/cn/about/core-concepts", + "v2/cn/about/mental-model" + ] + }, + { + "group": "Livepeer Protocol", + "icon": "cube", + "pages": [ + "v2/cn/about/livepeer-protocol/overview", + "v2/cn/about/livepeer-protocol/core-mechanisms", + "v2/cn/about/livepeer-protocol/livepeer-token", + "v2/cn/about/livepeer-protocol/governance-model", + "v2/cn/about/livepeer-protocol/treasury", + "v2/cn/about/livepeer-protocol/economics", + "v2/cn/about/livepeer-protocol/technical-architecture" + ] + }, + { + "group": "Livepeer Network", + "icon": "circle-nodes", + "pages": [ + "v2/cn/about/livepeer-network/overview", + "v2/cn/about/livepeer-network/actors", + "v2/cn/about/livepeer-network/job-lifecycle", + "v2/cn/about/livepeer-network/marketplace", + "v2/cn/about/livepeer-network/technical-architecture", + "v2/cn/about/livepeer-network/interfaces" + ] + }, + { + "group": "Resources", + "icon": "books", + "pages": [ + "v2/cn/about/resources/livepeer-whitepaper", + "v2/cn/about/resources/livepeer-glossary", + "v2/cn/about/resources/blockchain-contracts", + "v2/cn/about/resources/technical-roadmap" + ] + } + ] + } + ] + } + ] } ] } diff --git a/tasks/reports/navigation-links/navigation-report.json b/tasks/reports/navigation-links/navigation-report.json index 81f45adab..3d8fe530b 100644 --- a/tasks/reports/navigation-links/navigation-report.json +++ b/tasks/reports/navigation-links/navigation-report.json @@ -1,13 +1,13 @@ { - "generatedAt": "2026-03-09T04:18:18.404Z", - "totalEntries": 1181, + "generatedAt": "2026-03-16T20:55:39.113Z", + "totalEntries": 1329, "syntaxErrors": [], "missingRoutes": [ { "file": "docs.json", "rule": "Missing route", - "value": "v2/gateways/guides-and-tools/gateway-job-pipelines/overview", - "normalized": "v2/gateways/guides-and-tools/gateway-job-pipelines/overview", + "value": "v2/gateways/guides-and-resources/gateway-job-pipelines/overview", + "normalized": "v2/gateways/guides-and-resources/gateway-job-pipelines/overview", "pointer": "navigation.versions[1].languages[0].tabs[8].anchors[0].groups[4].pages[0]", "suggestions": [ { diff --git a/tasks/reports/navigation-links/navigation-report.md b/tasks/reports/navigation-links/navigation-report.md index ed25aaf4b..b427a106b 100644 --- a/tasks/reports/navigation-links/navigation-report.md +++ b/tasks/reports/navigation-links/navigation-report.md @@ -1,7 +1,7 @@ # Docs Navigation Route Report -- Generated at (UTC): 2026-03-09T04:18:18.404Z -- Entries scanned: 1181 +- Generated at (UTC): 2026-03-16T20:55:39.113Z +- Entries scanned: 1329 - Syntax errors: 0 - Missing routes: 1 - Missing routes with suggestions: 1 @@ -12,7 +12,7 @@ ## Missing Routes -- `v2/gateways/guides-and-tools/gateway-job-pipelines/overview` (normalized: `v2/gateways/guides-and-tools/gateway-job-pipelines/overview`) +- `v2/gateways/guides-and-resources/gateway-job-pipelines/overview` (normalized: `v2/gateways/guides-and-resources/gateway-job-pipelines/overview`) - Pointer: `navigation.versions[1].languages[0].tabs[8].anchors[0].groups[4].pages[0]` - Suggested remaps: - `v1/ai/api-reference/overview` (same leaf segment match [score=0.65]) diff --git a/v2/gateways/quickstart/gateway-setup.mdx b/v2/gateways/quickstart/gateway-setup.mdx index 533f8ac81..99b11befe 100644 --- a/v2/gateways/quickstart/gateway-setup.mdx +++ b/v2/gateways/quickstart/gateway-setup.mdx @@ -5,7 +5,7 @@ pageType: quickstart audience: gateway-operator purpose: how_to lastVerified: '2026-03-17' -sidebarTitle: Run a Gateway Quickstart +sidebarTitle: Run a Gateway keywords: - livepeer - gateways diff --git a/v2/index.mdx b/v2/index.mdx index e698b9a5f..204433e83 100644 --- a/v2/index.mdx +++ b/v2/index.mdx @@ -2097,77 +2097,78 @@ Run command: node tools/scripts/generate-pages-index.js --write #### Advanced Operations - [⚠️ Advanced Sources](orchestrators/guides/advanced-operations/advanced-sources.md) - [⚠️ Advanced Operations Guide](orchestrators/guides/advanced-operations/dep-guide.mdx) -- [⚠️ Gateway and Orchestrator Interface](orchestrators/guides/advanced-operations/gateway-orchestrator-interface.mdx) -- [⚠️ Gateway Relationships](orchestrators/guides/advanced-operations/gateway-relationships.mdx) -- [⚠️ Pool Operators](orchestrators/guides/advanced-operations/pool-operators.mdx) -- [⚠️ Scale Operations](orchestrators/guides/advanced-operations/scale-operations.mdx) +- [Gateway and Orchestrator Interface](orchestrators/guides/advanced-operations/gateway-orchestrator-interface.mdx) +- [Gateway Relationships](orchestrators/guides/advanced-operations/gateway-relationships.mdx) +- [Pool Operators](orchestrators/guides/advanced-operations/pool-operators.mdx) +- [Scale Operations](orchestrators/guides/advanced-operations/scale-operations.mdx) #### Ai And Job Workloads -- [⚠️ AI Inference Operations](orchestrators/guides/ai-and-job-workloads/ai-inference-operations.mdx) +- [AI Inference Operations](orchestrators/guides/ai-and-job-workloads/ai-inference-operations.mdx) - [⚠️ Ai Sources](orchestrators/guides/ai-and-job-workloads/ai-sources.md) -- [⚠️ Audio and Vision Pipelines](orchestrators/guides/ai-and-job-workloads/audio-and-vision-pipelines.mdx) -- [⚠️ Diffusion Pipeline Setup](orchestrators/guides/ai-and-job-workloads/diffusion-pipeline-setup.mdx) -- [⚠️ LLM Pipeline Setup](orchestrators/guides/ai-and-job-workloads/llm-pipeline-setup.mdx) -- [⚠️ Model and Demand Reference](orchestrators/guides/ai-and-job-workloads/model-demand-reference.mdx) -- [⚠️ Model Hosting](orchestrators/guides/ai-and-job-workloads/model-hosting.mdx) -- [⚠️ Cascade Setup](orchestrators/guides/ai-and-job-workloads/realtime-ai-setup.mdx) -- [⚠️ Video Transcoding Operations](orchestrators/guides/ai-and-job-workloads/video-transcoding-operations.mdx) -- [⚠️ Workload Options](orchestrators/guides/ai-and-job-workloads/workload-options.mdx) +- [Audio and Vision Pipelines](orchestrators/guides/ai-and-job-workloads/audio-and-vision-pipelines.mdx) +- [Diffusion Pipeline Setup](orchestrators/guides/ai-and-job-workloads/diffusion-pipeline-setup.mdx) +- [LLM Pipeline Setup](orchestrators/guides/ai-and-job-workloads/llm-pipeline-setup.mdx) +- [Model and Demand Reference](orchestrators/guides/ai-and-job-workloads/model-demand-reference.mdx) +- [Model Hosting](orchestrators/guides/ai-and-job-workloads/model-hosting.mdx) +- [Cascade Setup](orchestrators/guides/ai-and-job-workloads/realtime-ai-setup.mdx) +- [Video Transcoding Operations](orchestrators/guides/ai-and-job-workloads/video-transcoding-operations.mdx) +- [Workload Options](orchestrators/guides/ai-and-job-workloads/workload-options.mdx) #### Config And Optimisation -- [⚠️ AI Model Management](orchestrators/guides/config-and-optimisation/ai-model-management.mdx) -- [⚠️ Capacity Planning](orchestrators/guides/config-and-optimisation/capacity-planning.mdx) -- [⚠️ Pricing Strategy](orchestrators/guides/config-and-optimisation/pricing-strategy.mdx) -- [⚠️ Reward Call Tuning](orchestrators/guides/config-and-optimisation/reward-call-tuning.mdx) +- [AI Model Management](orchestrators/guides/config-and-optimisation/ai-model-management.mdx) +- [Capacity Planning](orchestrators/guides/config-and-optimisation/capacity-planning.mdx) +- [Pricing Strategy](orchestrators/guides/config-and-optimisation/pricing-strategy.mdx) +- [Reward Call Tuning](orchestrators/guides/config-and-optimisation/reward-call-tuning.mdx) #### Deployment Details -- [⚠️ Dual Mode Configuration](orchestrators/guides/deployment-details/dual-mode-configuration.mdx) -- [⚠️ Join a Pool](orchestrators/guides/deployment-details/join-a-pool.mdx) -- [⚠️ Join a Pool](orchestrators/guides/deployment-details/new-join-a-pool.mdx) -- [⚠️ Orchestrator-Transcoder Split Setup](orchestrators/guides/deployment-details/orchestrator-transcoder-setup.mdx) -- [⚠️ Setup Options](orchestrators/guides/deployment-details/setup-options.mdx) -- [⚠️ Siphon Split Setup](orchestrators/guides/deployment-details/siphon-setup.mdx) +- [Setup Options](orchestrators/guides/deployment-details/draft1-setup-options.mdx) +- [Dual Mode Configuration](orchestrators/guides/deployment-details/dual-mode-configuration.mdx) +- [Join a Pool](orchestrators/guides/deployment-details/join-a-pool.mdx) +- [Join a Pool](orchestrators/guides/deployment-details/new-join-a-pool.mdx) +- [Orchestrator-Transcoder Split Setup](orchestrators/guides/deployment-details/orchestrator-transcoder-setup.mdx) +- [Setup Options](orchestrators/guides/deployment-details/setup-options.mdx) +- [Siphon Split Setup](orchestrators/guides/deployment-details/siphon-setup.mdx) ##### Reports Audits - [⚠️ Notes](orchestrators/guides/deployment-details/reports-audits/notes.md) - [⚠️ Setup Sources](orchestrators/guides/deployment-details/reports-audits/setup-sources.md) #### Monitoring And Tooling -- [⚠️ Explorer Operations](orchestrators/guides/monitoring-and-tooling/explorer-operations.mdx) -- [⚠️ Metrics and Alerting](orchestrators/guides/monitoring-and-tooling/metrics-and-alerting.mdx) +- [Explorer Operations](orchestrators/guides/monitoring-and-tooling/explorer-operations.mdx) +- [Metrics and Alerting](orchestrators/guides/monitoring-and-tooling/metrics-and-alerting.mdx) - [⚠️ Monitoring Sources](orchestrators/guides/monitoring-and-tooling/monitoring-sources.md) -- [⚠️ Operator Toolbox](orchestrators/guides/monitoring-and-tooling/operator-toolbox.mdx) -- [⚠️ Troubleshooting](orchestrators/guides/monitoring-and-tooling/troubleshooting.mdx) +- [Operator Toolbox](orchestrators/guides/monitoring-and-tooling/operator-toolbox.mdx) +- [Troubleshooting](orchestrators/guides/monitoring-and-tooling/troubleshooting.mdx) #### Operator Considerations -- [⚠️ Business Case](orchestrators/guides/operator-considerations/business-case.mdx) +- [Business Case](orchestrators/guides/operator-considerations/business-case.mdx) - [⚠️ Feasibilits Sources](orchestrators/guides/operator-considerations/feasibilits-sources.md) -- [⚠️ Operator Impact](orchestrators/guides/operator-considerations/operator-impact.mdx) -- [⚠️ Operating Rationale](orchestrators/guides/operator-considerations/operator-rationale.mdx) -- [⚠️ Requirements](orchestrators/guides/operator-considerations/requirements.mdx) +- [Operator Impact](orchestrators/guides/operator-considerations/operator-impact.mdx) +- [Operating Rationale](orchestrators/guides/operator-considerations/operator-rationale.mdx) +- [Requirements](orchestrators/guides/operator-considerations/requirements.mdx) #### Payments And Pricing -- [⚠️ Payment Receipts](orchestrators/guides/payments-and-pricing/payment-receipts.mdx) -- [⚠️ Payments](orchestrators/guides/payments-and-pricing/payments.mdx) +- [Payment Receipts](orchestrators/guides/payments-and-pricing/payment-receipts.mdx) +- [Payments](orchestrators/guides/payments-and-pricing/payments.mdx) #### Roadmap And Funding -- [⚠️ Funding and Support](orchestrators/guides/roadmap-and-funding/funding-and-support.mdx) -- [⚠️ Orchestrator Profiles](orchestrators/guides/roadmap-and-funding/orchestrator-profiles.mdx) +- [Funding and Support](orchestrators/guides/roadmap-and-funding/funding-and-support.mdx) +- [Orchestrator Profiles](orchestrators/guides/roadmap-and-funding/orchestrator-profiles.mdx) #### Staking And Rewards -- [⚠️ Delegate Operations](orchestrators/guides/staking-and-rewards/delegate-operations.mdx) -- [⚠️ Earning Model](orchestrators/guides/staking-and-rewards/earning-model.mdx) -- [⚠️ Network Participation](orchestrators/guides/staking-and-rewards/network-participation.mdx) -- [⚠️ Reward Mechanics](orchestrators/guides/staking-and-rewards/reward-mechanics.mdx) +- [Delegate Operations](orchestrators/guides/staking-and-rewards/delegate-operations.mdx) +- [Earning Model](orchestrators/guides/staking-and-rewards/earning-model.mdx) +- [Network Participation](orchestrators/guides/staking-and-rewards/network-participation.mdx) +- [Reward Mechanics](orchestrators/guides/staking-and-rewards/reward-mechanics.mdx) #### Tutorials -- [⚠️ Add AI to a Video Node](orchestrators/guides/tutorials/add-ai-to-video-node.mdx) -- [⚠️ AI Earning Quickstart](orchestrators/guides/tutorials/ai-earning-quickstart.mdx) -- [⚠️ BYOC CPU Smoke Test](orchestrators/guides/tutorials/byoc-cpu-smoke-test.mdx) +- [Add AI to a Video Node](orchestrators/guides/tutorials/add-ai-to-video-node.mdx) +- [AI Earning Quickstart](orchestrators/guides/tutorials/ai-earning-quickstart.mdx) +- [BYOC CPU Smoke Test](orchestrators/guides/tutorials/byoc-cpu-smoke-test.mdx) - [⚠️ BYOC smoke-test: CPU gateway and orchestrator (off-chain to on-chain)](orchestrators/guides/tutorials/byoc-cpu-tutorial.mdx) -- [⚠️ Full AI Pipeline Tutorial](orchestrators/guides/tutorials/full-ai-pipeline-tutorial.mdx) -- [⚠️ Realtime AI Tutorial](orchestrators/guides/tutorials/realtime-ai-tutorial.mdx) -- [⚠️ Zero to First Reward](orchestrators/guides/tutorials/zero-to-first-reward.mdx) +- [Full AI Pipeline Tutorial](orchestrators/guides/tutorials/full-ai-pipeline-tutorial.mdx) +- [Realtime AI Tutorial](orchestrators/guides/tutorials/realtime-ai-tutorial.mdx) +- [Zero to First Reward](orchestrators/guides/tutorials/zero-to-first-reward.mdx) ##### Gateway Tutorial Composable Pages @@ -2180,7 +2181,7 @@ Run command: node tools/scripts/generate-pages-index.js --write - [⚠️ Add AI to Your Node](orchestrators/quickstart/AI-prompt-start.mdx) - [⚠️ How to Get Started](orchestrators/quickstart/dep-x-setup-paths.mdx) - [Orchestrator Quickstart](orchestrators/quickstart/guide.mdx) -- [⚠️ Quickstart Tutorial](orchestrators/quickstart/tutorial.mdx) +- [Quickstart Tutorial](orchestrators/quickstart/tutorial.mdx) - [Quickstart: Verify Your Hardware](orchestrators/quickstart/video-transcoding.mdx) ### Resources @@ -2189,22 +2190,22 @@ Run command: node tools/scripts/generate-pages-index.js --write - [Community Guides & Tutorials](orchestrators/resources/community-guides.mdx) - [Community Orchestrator Pools](orchestrators/resources/community-pools.mdx) - [FAQ and Troubleshooting](orchestrators/resources/faq.mdx) -- [⚠️ Orchestrator Terminology Glossary](orchestrators/resources/glossary.mdx) +- [Orchestrator Terminology Glossary](orchestrators/resources/glossary.mdx) - [GPU Support Matrix](orchestrators/resources/gpu-support.mdx) -- [Orchestrator Guides](orchestrators/resources/x-guides.mdx) -- [X-help](orchestrators/resources/x-help.mdx) -- [Orchestrator Payments](orchestrators/resources/x-payments.mdx) +- [⚠️ Orchestrator Guides](orchestrators/resources/x-guides.mdx) +- [⚠️ X-help](orchestrators/resources/x-help.mdx) +- [⚠️ Orchestrator Payments](orchestrators/resources/x-payments.mdx) #### Technical - [CLI Flags Reference](orchestrators/resources/technical/cli-flags.mdx) -- [X-changelog](orchestrators/resources/technical/x-changelog.mdx) +- [⚠️ X-changelog](orchestrators/resources/technical/x-changelog.mdx) - [Livepeer Arbitrum Contract Adresses](orchestrators/resources/technical/x-contract-addresses.mdx) -- [Support Status](orchestrators/resources/technical/x-support-status.mdx) -- [Troubleshooting](orchestrators/resources/technical/x-troubleshooting.mdx) +- [⚠️ Support Status](orchestrators/resources/technical/x-support-status.mdx) +- [⚠️ Troubleshooting](orchestrators/resources/technical/x-troubleshooting.mdx) ### Setup -- [⚠️ Configure Your Orchestrator](orchestrators/setup/configure.mdx) -- [⚠️ Connect to Arbitrum](orchestrators/setup/connect-and-activate.mdx) +- [Configure Your Orchestrator](orchestrators/setup/configure.mdx) +- [Connect to Arbitrum](orchestrators/setup/connect-and-activate.mdx) - [Run an Orchestrator](orchestrators/setup/guide.mdx) - [Set Up Monitoring](orchestrators/setup/r-monitor.mdx) - [Setup Checklist](orchestrators/setup/rcs-requirements.mdx) diff --git a/v2/orchestrators/index.mdx b/v2/orchestrators/index.mdx index b4e74e9ba..d3f1782f9 100644 --- a/v2/orchestrators/index.mdx +++ b/v2/orchestrators/index.mdx @@ -40,77 +40,78 @@ Run command: node tools/scripts/generate-pages-index.js --write ### Advanced Operations - [⚠️ Advanced Sources](guides/advanced-operations/advanced-sources.md) - [⚠️ Advanced Operations Guide](guides/advanced-operations/dep-guide.mdx) -- [⚠️ Gateway and Orchestrator Interface](guides/advanced-operations/gateway-orchestrator-interface.mdx) -- [⚠️ Gateway Relationships](guides/advanced-operations/gateway-relationships.mdx) -- [⚠️ Pool Operators](guides/advanced-operations/pool-operators.mdx) -- [⚠️ Scale Operations](guides/advanced-operations/scale-operations.mdx) +- [Gateway and Orchestrator Interface](guides/advanced-operations/gateway-orchestrator-interface.mdx) +- [Gateway Relationships](guides/advanced-operations/gateway-relationships.mdx) +- [Pool Operators](guides/advanced-operations/pool-operators.mdx) +- [Scale Operations](guides/advanced-operations/scale-operations.mdx) ### Ai And Job Workloads -- [⚠️ AI Inference Operations](guides/ai-and-job-workloads/ai-inference-operations.mdx) +- [AI Inference Operations](guides/ai-and-job-workloads/ai-inference-operations.mdx) - [⚠️ Ai Sources](guides/ai-and-job-workloads/ai-sources.md) -- [⚠️ Audio and Vision Pipelines](guides/ai-and-job-workloads/audio-and-vision-pipelines.mdx) -- [⚠️ Diffusion Pipeline Setup](guides/ai-and-job-workloads/diffusion-pipeline-setup.mdx) -- [⚠️ LLM Pipeline Setup](guides/ai-and-job-workloads/llm-pipeline-setup.mdx) -- [⚠️ Model and Demand Reference](guides/ai-and-job-workloads/model-demand-reference.mdx) -- [⚠️ Model Hosting](guides/ai-and-job-workloads/model-hosting.mdx) -- [⚠️ Cascade Setup](guides/ai-and-job-workloads/realtime-ai-setup.mdx) -- [⚠️ Video Transcoding Operations](guides/ai-and-job-workloads/video-transcoding-operations.mdx) -- [⚠️ Workload Options](guides/ai-and-job-workloads/workload-options.mdx) +- [Audio and Vision Pipelines](guides/ai-and-job-workloads/audio-and-vision-pipelines.mdx) +- [Diffusion Pipeline Setup](guides/ai-and-job-workloads/diffusion-pipeline-setup.mdx) +- [LLM Pipeline Setup](guides/ai-and-job-workloads/llm-pipeline-setup.mdx) +- [Model and Demand Reference](guides/ai-and-job-workloads/model-demand-reference.mdx) +- [Model Hosting](guides/ai-and-job-workloads/model-hosting.mdx) +- [Cascade Setup](guides/ai-and-job-workloads/realtime-ai-setup.mdx) +- [Video Transcoding Operations](guides/ai-and-job-workloads/video-transcoding-operations.mdx) +- [Workload Options](guides/ai-and-job-workloads/workload-options.mdx) ### Config And Optimisation -- [⚠️ AI Model Management](guides/config-and-optimisation/ai-model-management.mdx) -- [⚠️ Capacity Planning](guides/config-and-optimisation/capacity-planning.mdx) -- [⚠️ Pricing Strategy](guides/config-and-optimisation/pricing-strategy.mdx) -- [⚠️ Reward Call Tuning](guides/config-and-optimisation/reward-call-tuning.mdx) +- [AI Model Management](guides/config-and-optimisation/ai-model-management.mdx) +- [Capacity Planning](guides/config-and-optimisation/capacity-planning.mdx) +- [Pricing Strategy](guides/config-and-optimisation/pricing-strategy.mdx) +- [Reward Call Tuning](guides/config-and-optimisation/reward-call-tuning.mdx) ### Deployment Details -- [⚠️ Dual Mode Configuration](guides/deployment-details/dual-mode-configuration.mdx) -- [⚠️ Join a Pool](guides/deployment-details/join-a-pool.mdx) -- [⚠️ Join a Pool](guides/deployment-details/new-join-a-pool.mdx) -- [⚠️ Orchestrator-Transcoder Split Setup](guides/deployment-details/orchestrator-transcoder-setup.mdx) -- [⚠️ Setup Options](guides/deployment-details/setup-options.mdx) -- [⚠️ Siphon Split Setup](guides/deployment-details/siphon-setup.mdx) +- [Setup Options](guides/deployment-details/draft1-setup-options.mdx) +- [Dual Mode Configuration](guides/deployment-details/dual-mode-configuration.mdx) +- [Join a Pool](guides/deployment-details/join-a-pool.mdx) +- [Join a Pool](guides/deployment-details/new-join-a-pool.mdx) +- [Orchestrator-Transcoder Split Setup](guides/deployment-details/orchestrator-transcoder-setup.mdx) +- [Setup Options](guides/deployment-details/setup-options.mdx) +- [Siphon Split Setup](guides/deployment-details/siphon-setup.mdx) #### Reports Audits - [⚠️ Notes](guides/deployment-details/reports-audits/notes.md) - [⚠️ Setup Sources](guides/deployment-details/reports-audits/setup-sources.md) ### Monitoring And Tooling -- [⚠️ Explorer Operations](guides/monitoring-and-tooling/explorer-operations.mdx) -- [⚠️ Metrics and Alerting](guides/monitoring-and-tooling/metrics-and-alerting.mdx) +- [Explorer Operations](guides/monitoring-and-tooling/explorer-operations.mdx) +- [Metrics and Alerting](guides/monitoring-and-tooling/metrics-and-alerting.mdx) - [⚠️ Monitoring Sources](guides/monitoring-and-tooling/monitoring-sources.md) -- [⚠️ Operator Toolbox](guides/monitoring-and-tooling/operator-toolbox.mdx) -- [⚠️ Troubleshooting](guides/monitoring-and-tooling/troubleshooting.mdx) +- [Operator Toolbox](guides/monitoring-and-tooling/operator-toolbox.mdx) +- [Troubleshooting](guides/monitoring-and-tooling/troubleshooting.mdx) ### Operator Considerations -- [⚠️ Business Case](guides/operator-considerations/business-case.mdx) +- [Business Case](guides/operator-considerations/business-case.mdx) - [⚠️ Feasibilits Sources](guides/operator-considerations/feasibilits-sources.md) -- [⚠️ Operator Impact](guides/operator-considerations/operator-impact.mdx) -- [⚠️ Operating Rationale](guides/operator-considerations/operator-rationale.mdx) -- [⚠️ Requirements](guides/operator-considerations/requirements.mdx) +- [Operator Impact](guides/operator-considerations/operator-impact.mdx) +- [Operating Rationale](guides/operator-considerations/operator-rationale.mdx) +- [Requirements](guides/operator-considerations/requirements.mdx) ### Payments And Pricing -- [⚠️ Payment Receipts](guides/payments-and-pricing/payment-receipts.mdx) -- [⚠️ Payments](guides/payments-and-pricing/payments.mdx) +- [Payment Receipts](guides/payments-and-pricing/payment-receipts.mdx) +- [Payments](guides/payments-and-pricing/payments.mdx) ### Roadmap And Funding -- [⚠️ Funding and Support](guides/roadmap-and-funding/funding-and-support.mdx) -- [⚠️ Orchestrator Profiles](guides/roadmap-and-funding/orchestrator-profiles.mdx) +- [Funding and Support](guides/roadmap-and-funding/funding-and-support.mdx) +- [Orchestrator Profiles](guides/roadmap-and-funding/orchestrator-profiles.mdx) ### Staking And Rewards -- [⚠️ Delegate Operations](guides/staking-and-rewards/delegate-operations.mdx) -- [⚠️ Earning Model](guides/staking-and-rewards/earning-model.mdx) -- [⚠️ Network Participation](guides/staking-and-rewards/network-participation.mdx) -- [⚠️ Reward Mechanics](guides/staking-and-rewards/reward-mechanics.mdx) +- [Delegate Operations](guides/staking-and-rewards/delegate-operations.mdx) +- [Earning Model](guides/staking-and-rewards/earning-model.mdx) +- [Network Participation](guides/staking-and-rewards/network-participation.mdx) +- [Reward Mechanics](guides/staking-and-rewards/reward-mechanics.mdx) ### Tutorials -- [⚠️ Add AI to a Video Node](guides/tutorials/add-ai-to-video-node.mdx) -- [⚠️ AI Earning Quickstart](guides/tutorials/ai-earning-quickstart.mdx) -- [⚠️ BYOC CPU Smoke Test](guides/tutorials/byoc-cpu-smoke-test.mdx) +- [Add AI to a Video Node](guides/tutorials/add-ai-to-video-node.mdx) +- [AI Earning Quickstart](guides/tutorials/ai-earning-quickstart.mdx) +- [BYOC CPU Smoke Test](guides/tutorials/byoc-cpu-smoke-test.mdx) - [⚠️ BYOC smoke-test: CPU gateway and orchestrator (off-chain to on-chain)](guides/tutorials/byoc-cpu-tutorial.mdx) -- [⚠️ Full AI Pipeline Tutorial](guides/tutorials/full-ai-pipeline-tutorial.mdx) -- [⚠️ Realtime AI Tutorial](guides/tutorials/realtime-ai-tutorial.mdx) -- [⚠️ Zero to First Reward](guides/tutorials/zero-to-first-reward.mdx) +- [Full AI Pipeline Tutorial](guides/tutorials/full-ai-pipeline-tutorial.mdx) +- [Realtime AI Tutorial](guides/tutorials/realtime-ai-tutorial.mdx) +- [Zero to First Reward](guides/tutorials/zero-to-first-reward.mdx) #### Gateway Tutorial Composable Pages @@ -123,7 +124,7 @@ Run command: node tools/scripts/generate-pages-index.js --write - [⚠️ Add AI to Your Node](quickstart/AI-prompt-start.mdx) - [⚠️ How to Get Started](quickstart/dep-x-setup-paths.mdx) - [Orchestrator Quickstart](quickstart/guide.mdx) -- [⚠️ Quickstart Tutorial](quickstart/tutorial.mdx) +- [Quickstart Tutorial](quickstart/tutorial.mdx) - [Quickstart: Verify Your Hardware](quickstart/video-transcoding.mdx) ## Resources @@ -132,22 +133,22 @@ Run command: node tools/scripts/generate-pages-index.js --write - [Community Guides & Tutorials](resources/community-guides.mdx) - [Community Orchestrator Pools](resources/community-pools.mdx) - [FAQ and Troubleshooting](resources/faq.mdx) -- [⚠️ Orchestrator Terminology Glossary](resources/glossary.mdx) +- [Orchestrator Terminology Glossary](resources/glossary.mdx) - [GPU Support Matrix](resources/gpu-support.mdx) -- [Orchestrator Guides](resources/x-guides.mdx) -- [X-help](resources/x-help.mdx) -- [Orchestrator Payments](resources/x-payments.mdx) +- [⚠️ Orchestrator Guides](resources/x-guides.mdx) +- [⚠️ X-help](resources/x-help.mdx) +- [⚠️ Orchestrator Payments](resources/x-payments.mdx) ### Technical - [CLI Flags Reference](resources/technical/cli-flags.mdx) -- [X-changelog](resources/technical/x-changelog.mdx) +- [⚠️ X-changelog](resources/technical/x-changelog.mdx) - [Livepeer Arbitrum Contract Adresses](resources/technical/x-contract-addresses.mdx) -- [Support Status](resources/technical/x-support-status.mdx) -- [Troubleshooting](resources/technical/x-troubleshooting.mdx) +- [⚠️ Support Status](resources/technical/x-support-status.mdx) +- [⚠️ Troubleshooting](resources/technical/x-troubleshooting.mdx) ## Setup -- [⚠️ Configure Your Orchestrator](setup/configure.mdx) -- [⚠️ Connect to Arbitrum](setup/connect-and-activate.mdx) +- [Configure Your Orchestrator](setup/configure.mdx) +- [Connect to Arbitrum](setup/connect-and-activate.mdx) - [Run an Orchestrator](setup/guide.mdx) - [Set Up Monitoring](setup/r-monitor.mdx) - [Setup Checklist](setup/rcs-requirements.mdx) diff --git a/v2/orchestrators/portal.mdx b/v2/orchestrators/portal.mdx index 94aa4e691..f2a2cdfff 100644 --- a/v2/orchestrators/portal.mdx +++ b/v2/orchestrators/portal.mdx @@ -97,7 +97,7 @@ Get Situated */} Anyone can add a GPU to the Livepeer network and earn from idle GPU downtimes - either by adding it to a pool or setting up their own orchestrator container.

-