diff --git a/.mokogitea/CLAUDE.md b/.mokogitea/CLAUDE.md index 62ff862..7d04f8d 100644 --- a/.mokogitea/CLAUDE.md +++ b/.mokogitea/CLAUDE.md @@ -44,7 +44,7 @@ composer check # Run all checks ### CLI Framework -All CLI tools extend `MokoEnterprise\CliFramework` (`lib/Enterprise/CliFramework.php`). +All CLI tools extend `MokoCli\CliFramework` (`lib/Enterprise/CliFramework.php`). Built-in flags: `--help`, `--verbose`, `--quiet`, `--dry-run`. After adding a CLI tool, register it in `bin/moko` COMMAND_MAP. @@ -73,4 +73,4 @@ PHPStan runs with `--memory-limit=512M`. CI enforces PHPCS errors; PHPStan is `c - **Workflow directory**: `.mokogitea/` (not `.gitea/` or `.github/`) - **Wiki**: documentation lives in the Gitea wiki, not `docs/` files - **New CLI tools**: extend `CliFramework`, not `CLIApp` (legacy) -- **Standards**: [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki/Home) +- **Standards**: [MokoCli](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki/Home) diff --git a/.mokogitea/branch-protection.yml b/.mokogitea/branch-protection.yml index 8cade6a..80df873 100644 --- a/.mokogitea/branch-protection.yml +++ b/.mokogitea/branch-protection.yml @@ -63,7 +63,7 @@ jobs: # Platform/standards/infra repos to exclude EXCLUDE="gitea-org-config org-profile gitea-private .mokogitea-private mokoplatform MokoTesting" - EXCLUDE="$EXCLUDE MokoStandards-Template-Client MokoStandards-Template-Dolibarr MokoStandards-Template-Generic MokoStandards-Template-Joomla MokoDoliProjTemplate" + EXCLUDE="$EXCLUDE MokoCli-Template-Client MokoCli-Template-Dolibarr MokoCli-Template-Generic MokoCli-Template-Joomla MokoDoliProjTemplate" if [ -n "${{ inputs.repos }}" ]; then # User-specified repos diff --git a/.mokogitea/renovate.yml b/.mokogitea/renovate.yml index e281428..d8f2802 100644 --- a/.mokogitea/renovate.yml +++ b/.mokogitea/renovate.yml @@ -62,7 +62,7 @@ jobs: API="${GITEA_URL}/api/v1" EXCLUDE="gitea-org-config org-profile gitea-private .mokogitea-private mokoplatform MokoTesting" - EXCLUDE="$EXCLUDE MokoStandards-Template-Client MokoStandards-Template-Dolibarr MokoStandards-Template-Generic MokoStandards-Template-Joomla MokoDoliProjTemplate" + EXCLUDE="$EXCLUDE MokoCli-Template-Client MokoCli-Template-Dolibarr MokoCli-Template-Generic MokoCli-Template-Joomla MokoDoliProjTemplate" if [ -n "${{ inputs.repos }}" ]; then REPOS=$(echo "${{ inputs.repos }}" | tr ',' ' ') diff --git a/.mokogitea/workflows/ci-generic.yml b/.mokogitea/workflows/ci-generic.yml index 18ae768..2f7116e 100644 --- a/.mokogitea/workflows/ci-generic.yml +++ b/.mokogitea/workflows/ci-generic.yml @@ -4,7 +4,7 @@ # # FILE INFORMATION # DEFGROUP: Gitea.Workflow -# INGROUP: MokoStandards.CI +# INGROUP: MokoCli.CI # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic # PATH: /.gitea/workflows/ci-generic.yml # VERSION: 01.00.00 diff --git a/.mokogitea/workflows/deploy-manual.yml b/.mokogitea/workflows/deploy-manual.yml index bb133ed..be87c13 100644 --- a/.mokogitea/workflows/deploy-manual.yml +++ b/.mokogitea/workflows/deploy-manual.yml @@ -4,8 +4,8 @@ # # FILE INFORMATION # DEFGROUP: Gitea.Workflow -# INGROUP: MokoStandards.Deploy -# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API +# INGROUP: MokoCli.Deploy +# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoCli-API # PATH: /templates/workflows/joomla/deploy-manual.yml.template # VERSION: 04.07.00 # BRIEF: Manual SFTP deploy to dev server for Joomla repos @@ -40,7 +40,7 @@ jobs: run: | php -v && composer --version - - name: Setup MokoStandards tools + - name: Setup MokoCli tools env: GA_TOKEN: ${{ secrets.GA_TOKEN || secrets.GA_TOKEN || github.token }} MOKO_CLONE_TOKEN: ${{ secrets.GA_TOKEN || secrets.GA_TOKEN || github.token }} @@ -48,7 +48,7 @@ jobs: COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GA_TOKEN || github.token }}"}}' run: | git clone --depth 1 --branch main --quiet \ - "https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoStandards-API.git" \ + "https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoCli-API.git" \ /tmp/mokostandards-api 2>/dev/null || true if [ -d "/tmp/mokostandards-api" ] && [ -f "/tmp/mokostandards-api/composer.json" ]; then cd /tmp/mokostandards-api && composer install --no-dev --no-interaction --quiet 2>/dev/null || true diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index c2b02a6..2f50654 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: moko-platform.Automation -# VERSION: 01.00.00 +# VERSION: 09.29.02 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/.mokogitea/workflows/pr-check.yml b/.mokogitea/workflows/pr-check.yml index d34108c..5e391db 100644 --- a/.mokogitea/workflows/pr-check.yml +++ b/.mokogitea/workflows/pr-check.yml @@ -1,534 +1,508 @@ -# Copyright (C) 2026 Moko Consulting -# -# SPDX-License-Identifier: GPL-3.0-or-later -# -# FILE INFORMATION -# DEFGROUP: Gitea.Workflow -# INGROUP: moko-platform.CI -# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/moko-platform -# PATH: /templates/workflows/universal/pr-check.yml.template -# VERSION: 09.23.00 -# BRIEF: PR gate — branch policy + code validation before merge - -name: "Universal: PR Check" - -on: - pull_request: - types: [opened, synchronize, reopened, edited] - -permissions: - contents: read - pull-requests: write - -env: - FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true - -jobs: - # ── Branch Policy ────────────────────────────────────────────────────── - branch-policy: - name: Branch Policy - runs-on: ubuntu-latest - steps: - - name: Check branch merge target - run: | - HEAD="${{ github.head_ref }}" - BASE="${{ github.base_ref }}" - - echo "PR: ${HEAD} → ${BASE}" - - ALLOWED=true - REASON="" - - case "$HEAD" in - feature/*|feat/*) - if [ "$BASE" != "dev" ]; then - ALLOWED=false - REASON="Feature branches must target 'dev', not '${BASE}'" - fi - ;; - fix/*|bugfix/*) - if [ "$BASE" != "dev" ]; then - ALLOWED=false - REASON="Fix branches must target 'dev', not '${BASE}'" - fi - ;; - patch/*) - if [ "$BASE" != "dev" ] && [ "$BASE" != "rc" ]; then - ALLOWED=false - REASON="Patch branches must target 'dev' or 'rc', not '${BASE}'" - fi - ;; - hotfix/*) - if [ "$BASE" != "dev" ] && [ "$BASE" != "main" ]; then - ALLOWED=false - REASON="Hotfix branches can only target 'dev' or 'main', not '${BASE}'" - fi - ;; - rc) - if [ "$BASE" != "main" ]; then - ALLOWED=false - REASON="RC branch can only merge into 'main', not '${BASE}'" - fi - ;; - dev) - if [ "$BASE" != "main" ]; then - ALLOWED=false - REASON="Dev branch can only merge into 'main', not '${BASE}'" - fi - ;; - esac - - if [ "$ALLOWED" = false ]; then - echo "::error::${REASON}" - echo "## Branch Policy Violation" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "${REASON}" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "### Allowed merge paths:" >> $GITHUB_STEP_SUMMARY - echo "- \`feature/*\` → \`dev\`" >> $GITHUB_STEP_SUMMARY - echo "- \`fix/*\` → \`dev\`" >> $GITHUB_STEP_SUMMARY - echo "- \`hotfix/*\` → \`dev\` or \`main\`" >> $GITHUB_STEP_SUMMARY - echo "- \`dev\` → \`main\`" >> $GITHUB_STEP_SUMMARY - echo "- \`rc/*\` → \`main\`" >> $GITHUB_STEP_SUMMARY - exit 1 - fi - - echo "Branch policy: OK (${HEAD} → ${BASE})" - echo "## Branch Policy: Passed" >> $GITHUB_STEP_SUMMARY - - # ── Secret Scanning ────────────────────────────────────────────────── - gitleaks: - name: Secret Scan - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Install Gitleaks - run: | - GITLEAKS_VERSION="8.21.2" - curl -sSL "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz" \ - | tar -xz -C /usr/local/bin gitleaks - - - name: Scan PR commits for secrets - run: | - if gitleaks detect --source . --verbose \ - --log-opts=${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }} 2>&1; then - echo "**No secrets detected.**" >> $GITHUB_STEP_SUMMARY - else - echo "::error::Potential secrets detected in PR commits" - exit 1 - fi - - # ── Code Validation ──────────────────────────────────────────────────── - validate: - name: Validate PR - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Check for merge conflict markers - run: | - CONFLICTS=$(grep -rn '<<<<<<< \|>>>>>>> \|^=======$' --include='*.php' --include='*.xml' --include='*.css' --include='*.js' --include='*.json' --include='*.md' --include='*.yml' --include='*.yaml' --include='*.ini' --include='*.txt' . 2>/dev/null | grep -v '.git/' || true) - if [ -n "$CONFLICTS" ]; then - echo "::error::Merge conflict markers found in source files" - echo "## Conflict Markers Found" >> $GITHUB_STEP_SUMMARY - echo '```' >> $GITHUB_STEP_SUMMARY - echo "$CONFLICTS" >> $GITHUB_STEP_SUMMARY - echo '```' >> $GITHUB_STEP_SUMMARY - exit 1 - fi - echo "No conflict markers found" - - - name: Detect platform - id: platform - run: | - # Read platform from XML manifest ( tag) or plain text fallback - PLATFORM=$(sed -n 's/.*\([^<]*\)<\/platform>.*/\1/p' .mokogitea/manifest.xml 2>/dev/null | head -1) - [ -z "$PLATFORM" ] && PLATFORM=$(cat .mokogitea/manifest.xml 2>/dev/null | tr -d '[:space:]') - [ -z "$PLATFORM" ] && PLATFORM="generic" - echo "platform=$PLATFORM" >> "$GITHUB_OUTPUT" - - - name: Setup PHP - if: steps.platform.outputs.platform == 'joomla' || steps.platform.outputs.platform == 'dolibarr' - run: | - if ! command -v php &> /dev/null; then - sudo apt-get update -qq - sudo apt-get install -y -qq php-cli php-mbstring php-xml >/dev/null 2>&1 - fi - - - name: PHP syntax check - if: steps.platform.outputs.platform == 'joomla' || steps.platform.outputs.platform == 'dolibarr' - run: | - ERRORS=0 - while IFS= read -r -d '' file; do - if ! php -l "$file" 2>&1 | grep -q "No syntax errors"; then - ERRORS=$((ERRORS + 1)) - fi - done < <(find . -name "*.php" -not -path "./.git/*" -not -path "./vendor/*" -print0) - echo "PHP lint: ${ERRORS} error(s)" - [ "$ERRORS" -eq 0 ] || { echo "::error::PHP syntax errors found"; exit 1; } - - - name: Joomla JEXEC guard check - if: steps.platform.outputs.platform == 'joomla' - run: | - ERRORS=0 - while IFS= read -r -d '' file; do - # Skip vendor, node_modules, and index.html stub files - case "$file" in ./vendor/*|./node_modules/*) continue ;; esac - # Check first 10 lines for JEXEC or JPATH guard - if ! head -20 "$file" | grep -qE "defined\s*\(\s*['\"](_JEXEC|JPATH_BASE|\\\\JPATH_PLATFORM)['\"]"; then - echo "::error file=${file}::Missing JEXEC guard: ${file}" - ERRORS=$((ERRORS + 1)) - fi - done < <(find . -name "*.php" -path "*/src/*" -not -path "./.git/*" -not -path "./vendor/*" -print0) - if [ "$ERRORS" -gt 0 ]; then - echo "::error::${ERRORS} PHP file(s) missing defined('_JEXEC') or die guard" - echo "## JEXEC Guard Check: Failed" >> $GITHUB_STEP_SUMMARY - echo "${ERRORS} file(s) in src/ are missing the Joomla execution guard." >> $GITHUB_STEP_SUMMARY - exit 1 - fi - echo "JEXEC guard: OK" - - - name: Joomla directory listing protection - if: steps.platform.outputs.platform == 'joomla' - run: | - MISSING=0 - SOURCE_DIR="src" - [ ! -d "$SOURCE_DIR" ] && exit 0 - while IFS= read -r dir; do - if [ ! -f "${dir}/index.html" ]; then - echo "::warning::Missing index.html in ${dir} (directory listing protection)" - MISSING=$((MISSING + 1)) - fi - done < <(find "$SOURCE_DIR" -type d -not -path "./.git/*" -not -path "*/vendor/*" -not -path "*/node_modules/*") - if [ "$MISSING" -gt 0 ]; then - echo "## Directory Protection" >> $GITHUB_STEP_SUMMARY - echo "${MISSING} director(ies) missing index.html" >> $GITHUB_STEP_SUMMARY - fi - echo "Directory protection: ${MISSING} missing (advisory)" - - - name: Joomla script file and asset checks - if: steps.platform.outputs.platform == 'joomla' - run: | - ERRORS=0 - MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" -exec grep -l '/dev/null | head -1) - [ -z "$MANIFEST" ] && exit 0 - MANIFEST_DIR=$(dirname "$MANIFEST") - - # Check scriptfile exists if declared - SCRIPTFILE=$(sed -n 's/.*\([^<]*\)<\/scriptfile>.*/\1/p' "$MANIFEST" 2>/dev/null) - if [ -n "$SCRIPTFILE" ]; then - if [ ! -f "${MANIFEST_DIR}/${SCRIPTFILE}" ]; then - echo "::error::Manifest declares ${SCRIPTFILE} but file not found at ${MANIFEST_DIR}/${SCRIPTFILE}" - ERRORS=$((ERRORS + 1)) - else - echo "Script file: ${MANIFEST_DIR}/${SCRIPTFILE} (OK)" - fi - fi - - # Require joomla.asset.json and validate it - ASSET_JSON=$(find "$MANIFEST_DIR" -name "joomla.asset.json" -not -path "./.git/*" 2>/dev/null | head -1) - if [ -z "$ASSET_JSON" ]; then - echo "::error::joomla.asset.json not found — Joomla asset system is required" - ERRORS=$((ERRORS + 1)) - else - if command -v php &> /dev/null; then - php -r "json_decode(file_get_contents('$ASSET_JSON')); if(json_last_error()!==JSON_ERROR_NONE){echo json_last_error_msg();exit(1);}" 2>&1 || { - echo "::error::joomla.asset.json is not valid JSON" - ERRORS=$((ERRORS + 1)) - } - fi - echo "joomla.asset.json: valid" - fi - - # Validate all XML files in src/ are well-formed - XML_ERRORS=0 - if command -v php &> /dev/null; then - while IFS= read -r -d '' xmlfile; do - if ! php -r "libxml_use_internal_errors(true); \$x = simplexml_load_file('$xmlfile'); if(!\$x){foreach(libxml_get_errors() as \$e) echo trim(\$e->message) . ' in $xmlfile'; exit(1);}" 2>&1; then - XML_ERRORS=$((XML_ERRORS + 1)) - fi - done < <(find "$MANIFEST_DIR" -name "*.xml" -not -path "./.git/*" -print0) - fi - if [ "$XML_ERRORS" -gt 0 ]; then - echo "::error::${XML_ERRORS} XML file(s) are malformed" - ERRORS=$((ERRORS + 1)) - else - echo "XML well-formedness: OK" - fi - - [ "$ERRORS" -gt 0 ] && exit 1 - echo "Joomla asset checks: OK" - - - name: Validate platform manifest - run: | - PLATFORM="${{ steps.platform.outputs.platform }}" - case "$PLATFORM" in - joomla) - MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" -exec grep -l '/dev/null | head -1) - if [ -z "$MANIFEST" ]; then - echo "::warning::No Joomla manifest found (WaaS site)" - exit 0 - fi - echo "Manifest: ${MANIFEST}" - if command -v php &> /dev/null; then - php -r "libxml_use_internal_errors(true); \$x = simplexml_load_file('$MANIFEST'); if(!\$x){foreach(libxml_get_errors() as \$e) echo \$e->message; exit(1);}" || { echo "::error::Manifest XML is malformed"; exit 1; } - fi - for ELEMENT in name version description; do - grep -q "<${ELEMENT}>" "$MANIFEST" || { echo "::error::Missing <${ELEMENT}> in manifest"; exit 1; } - done - # Block legacy raw/branch update server URLs on MokoGitea - RAW_URLS=$(grep -n 'raw/branch' "$MANIFEST" | grep -i 'mokoconsulting\|mokogitea\|git\.mokoconsulting\.tech' || true) - if [ -n "$RAW_URLS" ]; then - echo "::error::Manifest contains legacy raw/branch update server URL on MokoGitea. Use the Gitea Pages URL instead (e.g. /{REPO}/updates.xml not /{REPO}/raw/branch/main/updates.xml)" - echo "$RAW_URLS" - exit 1 - fi - echo "Joomla manifest valid" - ;; - dolibarr) - MOD_FILE=$(find . -maxdepth 4 -name "mod*.class.php" ! -path "./.git/*" -exec grep -l 'extends DolibarrModules' {} \; 2>/dev/null | head -1) - if [ -z "$MOD_FILE" ]; then - echo "::error::No mod*.class.php found" - exit 1 - fi - echo "Dolibarr module: ${MOD_FILE}" - ;; - *) - echo "Generic platform — no manifest validation" - ;; - esac - - - name: Check update stream format - run: | - PLATFORM="${{ steps.platform.outputs.platform }}" - case "$PLATFORM" in - joomla) - if [ -f "updates.xml" ]; then - if command -v php &> /dev/null; then - php -r "libxml_use_internal_errors(true); \$x = simplexml_load_file('updates.xml'); if(!\$x){foreach(libxml_get_errors() as \$e) echo \$e->message; exit(1);}" || { echo "::error::updates.xml is malformed"; exit 1; } - fi - echo "updates.xml valid" - fi - ;; - dolibarr) - [ -f "update.txt" ] && echo "update.txt present" || echo "::warning::No update.txt" - ;; - esac - - - name: Validate Joomla language files - if: steps.platform.outputs.platform == 'joomla' - run: | - ERRORS=0 - WARNINGS=0 - - # Require both en-GB and en-US language directories - LANG_ROOT=$(find . -path "*/language" -type d -not -path "./.git/*" 2>/dev/null | head -1) - if [ -z "$LANG_ROOT" ]; then - echo "No language/ directory found — skipping" - exit 0 - fi - - if [ ! -d "$LANG_ROOT/en-GB" ]; then - echo "::error::Missing en-GB language directory (${LANG_ROOT}/en-GB)" - ERRORS=$((ERRORS + 1)) - fi - if [ ! -d "$LANG_ROOT/en-US" ]; then - echo "::error::Missing en-US language directory (${LANG_ROOT}/en-US)" - ERRORS=$((ERRORS + 1)) - fi - - # Check that en-GB and en-US have matching .ini files - if [ -d "$LANG_ROOT/en-GB" ] && [ -d "$LANG_ROOT/en-US" ]; then - for GB_INI in "$LANG_ROOT/en-GB"/*.ini; do - [ ! -f "$GB_INI" ] && continue - US_INI="$LANG_ROOT/en-US/$(basename "$GB_INI")" - if [ ! -f "$US_INI" ]; then - echo "::error::$(basename "$GB_INI") exists in en-GB but missing from en-US" - ERRORS=$((ERRORS + 1)) - fi - done - for US_INI in "$LANG_ROOT/en-US"/*.ini; do - [ ! -f "$US_INI" ] && continue - GB_INI="$LANG_ROOT/en-GB/$(basename "$US_INI")" - if [ ! -f "$GB_INI" ]; then - echo "::error::$(basename "$US_INI") exists in en-US but missing from en-GB" - ERRORS=$((ERRORS + 1)) - fi - done - fi - - # Find all .ini language files - INI_FILES=$(find . -path "*/language/*/*.ini" -not -path "./.git/*" 2>/dev/null) - if [ -z "$INI_FILES" ]; then - echo "No .ini language files found" - [ "$ERRORS" -gt 0 ] && exit 1 - exit 0 - fi - - echo "Found $(echo "$INI_FILES" | wc -l) language file(s)" - - for FILE in $INI_FILES; do - FNAME=$(basename "$FILE") - LINENUM=0 - SEEN_KEYS="" - - while IFS= read -r line || [ -n "$line" ]; do - LINENUM=$((LINENUM + 1)) - - # Skip empty lines and comments - [ -z "$line" ] && continue - echo "$line" | grep -qE '^\s*;' && continue - echo "$line" | grep -qE '^\s*$' && continue - - # Must match KEY="VALUE" format - if ! echo "$line" | grep -qE '^[A-Z_][A-Z0-9_]*=".*"$'; then - echo "::error file=${FILE},line=${LINENUM}::Malformed line: ${line}" - ERRORS=$((ERRORS + 1)) - continue - fi - - # Extract key and check for duplicates - KEY=$(echo "$line" | sed 's/=.*//') - if echo "$SEEN_KEYS" | grep -qx "$KEY"; then - echo "::error file=${FILE},line=${LINENUM}::Duplicate key: ${KEY}" - ERRORS=$((ERRORS + 1)) - fi - SEEN_KEYS="${SEEN_KEYS} - ${KEY}" - done < "$FILE" - - echo " ${FILE}: checked ${LINENUM} lines" - done - - # Cross-check en-GB vs en-US key consistency - GB_DIR=$(find . -path "*/language/en-GB" -type d -not -path "./.git/*" 2>/dev/null | head -1) - US_DIR=$(find . -path "*/language/en-US" -type d -not -path "./.git/*" 2>/dev/null | head -1) - - if [ -n "$GB_DIR" ] && [ -n "$US_DIR" ]; then - for GB_FILE in "$GB_DIR"/*.ini; do - [ ! -f "$GB_FILE" ] && continue - FNAME=$(basename "$GB_FILE") - US_FILE="$US_DIR/$FNAME" - [ ! -f "$US_FILE" ] && continue - - GB_KEYS=$(grep -oP '^[A-Z_][A-Z0-9_]*(?==)' "$GB_FILE" 2>/dev/null | sort) - US_KEYS=$(grep -oP '^[A-Z_][A-Z0-9_]*(?==)' "$US_FILE" 2>/dev/null | sort) - - # Keys in en-GB but not en-US - MISSING_US=$(comm -23 <(echo "$GB_KEYS") <(echo "$US_KEYS")) - if [ -n "$MISSING_US" ]; then - echo "::warning::Keys in en-GB/$FNAME but missing from en-US/$FNAME:" - echo "$MISSING_US" | while read -r k; do echo " - $k"; done - WARNINGS=$((WARNINGS + 1)) - fi - - # Keys in en-US but not en-GB - MISSING_GB=$(comm -13 <(echo "$GB_KEYS") <(echo "$US_KEYS")) - if [ -n "$MISSING_GB" ]; then - echo "::warning::Keys in en-US/$FNAME but missing from en-GB/$FNAME:" - echo "$MISSING_GB" | while read -r k; do echo " - $k"; done - WARNINGS=$((WARNINGS + 1)) - fi - done - fi - - { - echo "### Language File Validation" - echo "| Metric | Count |" - echo "|---|---|" - echo "| Files checked | $(echo "$INI_FILES" | wc -l) |" - echo "| Errors | ${ERRORS} |" - echo "| Warnings | ${WARNINGS} |" - } >> $GITHUB_STEP_SUMMARY - - if [ "$ERRORS" -gt 0 ]; then - echo "::error::Language validation failed with ${ERRORS} error(s)" - exit 1 - fi - echo "Language files: OK (${WARNINGS} warning(s))" - - - name: Check changelog has unreleased entry - run: | - if [ ! -f "CHANGELOG.md" ]; then - echo "::warning::No CHANGELOG.md found" - exit 0 - fi - # Check for content under [Unreleased] section - if ! grep -q "## \[Unreleased\]" CHANGELOG.md; then - echo "::error::CHANGELOG.md missing [Unreleased] section" - exit 1 - fi - # Check there's at least one entry (Added/Changed/Fixed/Removed) under Unreleased - UNRELEASED_CONTENT=$(sed -n '/## \[Unreleased\]/,/## \[/p' CHANGELOG.md | grep -cE '^\s*-\s' || true) - if [ "$UNRELEASED_CONTENT" -eq 0 ]; then - echo "::error::CHANGELOG.md [Unreleased] section has no entries. Add a changelog entry describing your changes." - echo "## Changelog Check: Failed" >> $GITHUB_STEP_SUMMARY - echo "The \`[Unreleased]\` section in CHANGELOG.md has no entries." >> $GITHUB_STEP_SUMMARY - echo "Add a line like \`- Description of your change\` under a heading (\`### Added\`, \`### Changed\`, \`### Fixed\`, etc.)" >> $GITHUB_STEP_SUMMARY - exit 1 - fi - echo "Changelog: ${UNRELEASED_CONTENT} entry/entries in [Unreleased]" - - - name: Verify package source - run: | - SOURCE_DIR="src" - [ ! -d "$SOURCE_DIR" ] && SOURCE_DIR="htdocs" - if [ ! -d "$SOURCE_DIR" ]; then - echo "::warning::No src/ or htdocs/ directory" - exit 0 - fi - FILE_COUNT=$(find "$SOURCE_DIR" -type f | wc -l) - echo "Source: ${FILE_COUNT} files" - [ "$FILE_COUNT" -gt 0 ] || { echo "::error::Source directory is empty"; exit 1; } - - # ── Pre-Release RC Build ───────────────────────────────────────────────── - pre-release: - name: Build RC Package - runs-on: ubuntu-latest - needs: [branch-policy, validate] - - steps: - - name: Trigger RC pre-release - env: - GA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }} - REPO: ${{ github.repository }} - BRANCH: ${{ github.head_ref }} - GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }} - run: | - curl -s -X POST "${GITEA_URL}/api/v1/repos/${REPO}/actions/workflows/pre-release.yml/dispatches" -H "Authorization: token ${GITEA_TOKEN}" -H "Content-Type: application/json" -d "{\"ref\":\"${BRANCH}\",\"inputs\":{\"stability\":\"release-candidate\"}}" - echo "### Pre-Release" >> $GITHUB_STEP_SUMMARY - echo "Triggered RC build on branch \`${BRANCH}\`" >> $GITHUB_STEP_SUMMARY - - # ── Issue Reporter ────────────────────────────────────────────────────── - report-issues: - name: Report Issues - runs-on: ubuntu-latest - needs: [branch-policy, validate] - if: >- - always() && - needs.validate.result == 'failure' - - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - sparse-checkout: automation/ci-issue-reporter.sh - sparse-checkout-cone-mode: false - - - name: "File issue for PR validation failure" - env: - GITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }} - GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }} - run: | - chmod +x automation/ci-issue-reporter.sh - ./automation/ci-issue-reporter.sh \ - --gate "PR Validation" \ - --workflow "PR Check" \ - --severity error \ - --details "PR validation failed (syntax, manifest, changelog, or source checks). See the CI run for the specific check that failed." +# Copyright (C) 2026 Moko Consulting +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# FILE INFORMATION +# DEFGROUP: Gitea.Workflow +# INGROUP: mokoplatform.CI +# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/mokoplatform +# PATH: /templates/workflows/universal/pr-check.yml.template +# VERSION: 09.23.00 +# BRIEF: PR gate — branch policy + code validation before merge + +name: "Universal: PR Check" + +on: + pull_request: + types: [opened, synchronize, reopened, edited] + +permissions: + contents: read + pull-requests: write + +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + # ── Branch Policy ────────────────────────────────────────────────────── + branch-policy: + name: Branch Policy + runs-on: ubuntu-latest + steps: + - name: Check branch merge target + run: | + HEAD="${{ github.head_ref }}" + BASE="${{ github.base_ref }}" + + echo "PR: ${HEAD} → ${BASE}" + + ALLOWED=true + REASON="" + + case "$HEAD" in + feature/*|feat/*) + if [ "$BASE" != "dev" ]; then + ALLOWED=false + REASON="Feature branches must target 'dev', not '${BASE}'" + fi + ;; + fix/*|bugfix/*) + if [ "$BASE" != "dev" ]; then + ALLOWED=false + REASON="Fix branches must target 'dev', not '${BASE}'" + fi + ;; + patch/*) + if [ "$BASE" != "dev" ] && [ "$BASE" != "rc" ]; then + ALLOWED=false + REASON="Patch branches must target 'dev' or 'rc', not '${BASE}'" + fi + ;; + hotfix/*) + if [ "$BASE" != "dev" ] && [ "$BASE" != "main" ]; then + ALLOWED=false + REASON="Hotfix branches can only target 'dev' or 'main', not '${BASE}'" + fi + ;; + rc) + if [ "$BASE" != "main" ]; then + ALLOWED=false + REASON="RC branch can only merge into 'main', not '${BASE}'" + fi + ;; + dev) + if [ "$BASE" != "main" ]; then + ALLOWED=false + REASON="Dev branch can only merge into 'main', not '${BASE}'" + fi + ;; + esac + + if [ "$ALLOWED" = false ]; then + echo "::error::${REASON}" + echo "## Branch Policy Violation" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "${REASON}" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "### Allowed merge paths:" >> $GITHUB_STEP_SUMMARY + echo "- \`feature/*\` → \`dev\`" >> $GITHUB_STEP_SUMMARY + echo "- \`fix/*\` → \`dev\`" >> $GITHUB_STEP_SUMMARY + echo "- \`hotfix/*\` → \`dev\` or \`main\`" >> $GITHUB_STEP_SUMMARY + echo "- \`dev\` → \`main\`" >> $GITHUB_STEP_SUMMARY + echo "- \`rc/*\` → \`main\`" >> $GITHUB_STEP_SUMMARY + exit 1 + fi + + echo "Branch policy: OK (${HEAD} → ${BASE})" + echo "## Branch Policy: Passed" >> $GITHUB_STEP_SUMMARY + + # ── Code Validation ──────────────────────────────────────────────────── + validate: + name: Validate PR + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Check for merge conflict markers + run: | + CONFLICTS=$(grep -rn '<<<<<<< \|>>>>>>> \|^=======$' --include='*.php' --include='*.xml' --include='*.css' --include='*.js' --include='*.json' --include='*.md' --include='*.yml' --include='*.yaml' --include='*.ini' --include='*.txt' . 2>/dev/null | grep -v '.git/' || true) + if [ -n "$CONFLICTS" ]; then + echo "::error::Merge conflict markers found in source files" + echo "## Conflict Markers Found" >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + echo "$CONFLICTS" >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + exit 1 + fi + echo "No conflict markers found" + + - name: Detect platform + id: platform + run: | + # Read platform from XML manifest ( tag) or plain text fallback + PLATFORM=$(sed -n 's/.*\([^<]*\)<\/platform>.*/\1/p' .mokogitea/manifest.xml 2>/dev/null | head -1) + [ -z "$PLATFORM" ] && PLATFORM=$(cat .mokogitea/manifest.xml 2>/dev/null | tr -d '[:space:]') + [ -z "$PLATFORM" ] && PLATFORM="generic" + echo "platform=$PLATFORM" >> "$GITHUB_OUTPUT" + + - name: Setup PHP + if: steps.platform.outputs.platform == 'joomla' || steps.platform.outputs.platform == 'dolibarr' + run: | + if ! command -v php &> /dev/null; then + sudo apt-get update -qq + sudo apt-get install -y -qq php-cli php-mbstring php-xml >/dev/null 2>&1 + fi + + - name: PHP syntax check + if: steps.platform.outputs.platform == 'joomla' || steps.platform.outputs.platform == 'dolibarr' + run: | + ERRORS=0 + while IFS= read -r -d '' file; do + if ! php -l "$file" 2>&1 | grep -q "No syntax errors"; then + ERRORS=$((ERRORS + 1)) + fi + done < <(find . -name "*.php" -not -path "./.git/*" -not -path "./vendor/*" -print0) + echo "PHP lint: ${ERRORS} error(s)" + [ "$ERRORS" -eq 0 ] || { echo "::error::PHP syntax errors found"; exit 1; } + + - name: Joomla JEXEC guard check + if: steps.platform.outputs.platform == 'joomla' + run: | + ERRORS=0 + while IFS= read -r -d '' file; do + # Skip vendor, node_modules, and index.html stub files + case "$file" in ./vendor/*|./node_modules/*) continue ;; esac + # Check first 10 lines for JEXEC or JPATH guard + if ! head -20 "$file" | grep -qE "defined\s*\(\s*['\"](_JEXEC|JPATH_BASE|\\\\JPATH_PLATFORM)['\"]"; then + echo "::error file=${file}::Missing JEXEC guard: ${file}" + ERRORS=$((ERRORS + 1)) + fi + done < <(find . -name "*.php" -path "*/src/*" -not -path "./.git/*" -not -path "./vendor/*" -print0) + if [ "$ERRORS" -gt 0 ]; then + echo "::error::${ERRORS} PHP file(s) missing defined('_JEXEC') or die guard" + echo "## JEXEC Guard Check: Failed" >> $GITHUB_STEP_SUMMARY + echo "${ERRORS} file(s) in src/ are missing the Joomla execution guard." >> $GITHUB_STEP_SUMMARY + exit 1 + fi + echo "JEXEC guard: OK" + + - name: Joomla directory listing protection + if: steps.platform.outputs.platform == 'joomla' + run: | + MISSING=0 + SOURCE_DIR="src" + [ ! -d "$SOURCE_DIR" ] && exit 0 + while IFS= read -r dir; do + if [ ! -f "${dir}/index.html" ]; then + echo "::warning::Missing index.html in ${dir} (directory listing protection)" + MISSING=$((MISSING + 1)) + fi + done < <(find "$SOURCE_DIR" -type d -not -path "./.git/*" -not -path "*/vendor/*" -not -path "*/node_modules/*") + if [ "$MISSING" -gt 0 ]; then + echo "## Directory Protection" >> $GITHUB_STEP_SUMMARY + echo "${MISSING} director(ies) missing index.html" >> $GITHUB_STEP_SUMMARY + fi + echo "Directory protection: ${MISSING} missing (advisory)" + + - name: Joomla script file and asset checks + if: steps.platform.outputs.platform == 'joomla' + run: | + ERRORS=0 + MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" -exec grep -l '/dev/null | head -1) + [ -z "$MANIFEST" ] && exit 0 + MANIFEST_DIR=$(dirname "$MANIFEST") + + # Check scriptfile exists if declared + SCRIPTFILE=$(sed -n 's/.*\([^<]*\)<\/scriptfile>.*/\1/p' "$MANIFEST" 2>/dev/null) + if [ -n "$SCRIPTFILE" ]; then + if [ ! -f "${MANIFEST_DIR}/${SCRIPTFILE}" ]; then + echo "::error::Manifest declares ${SCRIPTFILE} but file not found at ${MANIFEST_DIR}/${SCRIPTFILE}" + ERRORS=$((ERRORS + 1)) + else + echo "Script file: ${MANIFEST_DIR}/${SCRIPTFILE} (OK)" + fi + fi + + # Require joomla.asset.json and validate it + ASSET_JSON=$(find "$MANIFEST_DIR" -name "joomla.asset.json" -not -path "./.git/*" 2>/dev/null | head -1) + if [ -z "$ASSET_JSON" ]; then + echo "::error::joomla.asset.json not found — Joomla asset system is required" + ERRORS=$((ERRORS + 1)) + else + if command -v php &> /dev/null; then + php -r "json_decode(file_get_contents('$ASSET_JSON')); if(json_last_error()!==JSON_ERROR_NONE){echo json_last_error_msg();exit(1);}" 2>&1 || { + echo "::error::joomla.asset.json is not valid JSON" + ERRORS=$((ERRORS + 1)) + } + fi + echo "joomla.asset.json: valid" + fi + + # Validate all XML files in src/ are well-formed + XML_ERRORS=0 + if command -v php &> /dev/null; then + while IFS= read -r -d '' xmlfile; do + if ! php -r "libxml_use_internal_errors(true); \$x = simplexml_load_file('$xmlfile'); if(!\$x){foreach(libxml_get_errors() as \$e) echo trim(\$e->message) . ' in $xmlfile'; exit(1);}" 2>&1; then + XML_ERRORS=$((XML_ERRORS + 1)) + fi + done < <(find "$MANIFEST_DIR" -name "*.xml" -not -path "./.git/*" -print0) + fi + if [ "$XML_ERRORS" -gt 0 ]; then + echo "::error::${XML_ERRORS} XML file(s) are malformed" + ERRORS=$((ERRORS + 1)) + else + echo "XML well-formedness: OK" + fi + + [ "$ERRORS" -gt 0 ] && exit 1 + echo "Joomla asset checks: OK" + + - name: Validate platform manifest + run: | + PLATFORM="${{ steps.platform.outputs.platform }}" + case "$PLATFORM" in + joomla) + MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" -exec grep -l '/dev/null | head -1) + if [ -z "$MANIFEST" ]; then + echo "::warning::No Joomla manifest found (WaaS site)" + exit 0 + fi + echo "Manifest: ${MANIFEST}" + if command -v php &> /dev/null; then + php -r "libxml_use_internal_errors(true); \$x = simplexml_load_file('$MANIFEST'); if(!\$x){foreach(libxml_get_errors() as \$e) echo \$e->message; exit(1);}" || { echo "::error::Manifest XML is malformed"; exit 1; } + fi + for ELEMENT in name version description; do + grep -q "<${ELEMENT}>" "$MANIFEST" || { echo "::error::Missing <${ELEMENT}> in manifest"; exit 1; } + done + # Block legacy raw/branch update server URLs on MokoGitea + RAW_URLS=$(grep -n 'raw/branch' "$MANIFEST" | grep -i 'mokoconsulting\|mokogitea\|git\.mokoconsulting\.tech' || true) + if [ -n "$RAW_URLS" ]; then + echo "::error::Manifest contains legacy raw/branch update server URL on MokoGitea. Use the Gitea Pages URL instead (e.g. /{REPO}/updates.xml not /{REPO}/raw/branch/main/updates.xml)" + echo "$RAW_URLS" + exit 1 + fi + echo "Joomla manifest valid" + ;; + dolibarr) + MOD_FILE=$(find . -maxdepth 4 -name "mod*.class.php" ! -path "./.git/*" -exec grep -l 'extends DolibarrModules' {} \; 2>/dev/null | head -1) + if [ -z "$MOD_FILE" ]; then + echo "::error::No mod*.class.php found" + exit 1 + fi + echo "Dolibarr module: ${MOD_FILE}" + ;; + *) + echo "Generic platform — no manifest validation" + ;; + esac + + - name: Check update stream format + run: | + PLATFORM="${{ steps.platform.outputs.platform }}" + case "$PLATFORM" in + joomla) + if [ -f "updates.xml" ]; then + if command -v php &> /dev/null; then + php -r "libxml_use_internal_errors(true); \$x = simplexml_load_file('updates.xml'); if(!\$x){foreach(libxml_get_errors() as \$e) echo \$e->message; exit(1);}" || { echo "::error::updates.xml is malformed"; exit 1; } + fi + echo "updates.xml valid" + fi + ;; + dolibarr) + [ -f "update.txt" ] && echo "update.txt present" || echo "::warning::No update.txt" + ;; + esac + + - name: Validate Joomla language files + if: steps.platform.outputs.platform == 'joomla' + run: | + ERRORS=0 + WARNINGS=0 + + # Require both en-GB and en-US language directories + LANG_ROOT=$(find . -path "*/language" -type d -not -path "./.git/*" 2>/dev/null | head -1) + if [ -z "$LANG_ROOT" ]; then + echo "No language/ directory found — skipping" + exit 0 + fi + + if [ ! -d "$LANG_ROOT/en-GB" ]; then + echo "::error::Missing en-GB language directory (${LANG_ROOT}/en-GB)" + ERRORS=$((ERRORS + 1)) + fi + if [ ! -d "$LANG_ROOT/en-US" ]; then + echo "::error::Missing en-US language directory (${LANG_ROOT}/en-US)" + ERRORS=$((ERRORS + 1)) + fi + + # Check that en-GB and en-US have matching .ini files + if [ -d "$LANG_ROOT/en-GB" ] && [ -d "$LANG_ROOT/en-US" ]; then + for GB_INI in "$LANG_ROOT/en-GB"/*.ini; do + [ ! -f "$GB_INI" ] && continue + US_INI="$LANG_ROOT/en-US/$(basename "$GB_INI")" + if [ ! -f "$US_INI" ]; then + echo "::error::$(basename "$GB_INI") exists in en-GB but missing from en-US" + ERRORS=$((ERRORS + 1)) + fi + done + for US_INI in "$LANG_ROOT/en-US"/*.ini; do + [ ! -f "$US_INI" ] && continue + GB_INI="$LANG_ROOT/en-GB/$(basename "$US_INI")" + if [ ! -f "$GB_INI" ]; then + echo "::error::$(basename "$US_INI") exists in en-US but missing from en-GB" + ERRORS=$((ERRORS + 1)) + fi + done + fi + + # Find all .ini language files + INI_FILES=$(find . -path "*/language/*/*.ini" -not -path "./.git/*" 2>/dev/null) + if [ -z "$INI_FILES" ]; then + echo "No .ini language files found" + [ "$ERRORS" -gt 0 ] && exit 1 + exit 0 + fi + + echo "Found $(echo "$INI_FILES" | wc -l) language file(s)" + + for FILE in $INI_FILES; do + FNAME=$(basename "$FILE") + LINENUM=0 + SEEN_KEYS="" + + while IFS= read -r line || [ -n "$line" ]; do + LINENUM=$((LINENUM + 1)) + + # Skip empty lines and comments + [ -z "$line" ] && continue + echo "$line" | grep -qE '^\s*;' && continue + echo "$line" | grep -qE '^\s*$' && continue + + # Must match KEY="VALUE" format + if ! echo "$line" | grep -qE '^[A-Z_][A-Z0-9_]*=".*"$'; then + echo "::error file=${FILE},line=${LINENUM}::Malformed line: ${line}" + ERRORS=$((ERRORS + 1)) + continue + fi + + # Extract key and check for duplicates + KEY=$(echo "$line" | sed 's/=.*//') + if echo "$SEEN_KEYS" | grep -qx "$KEY"; then + echo "::error file=${FILE},line=${LINENUM}::Duplicate key: ${KEY}" + ERRORS=$((ERRORS + 1)) + fi + SEEN_KEYS="${SEEN_KEYS} + ${KEY}" + done < "$FILE" + + echo " ${FILE}: checked ${LINENUM} lines" + done + + # Cross-check en-GB vs en-US key consistency + GB_DIR=$(find . -path "*/language/en-GB" -type d -not -path "./.git/*" 2>/dev/null | head -1) + US_DIR=$(find . -path "*/language/en-US" -type d -not -path "./.git/*" 2>/dev/null | head -1) + + if [ -n "$GB_DIR" ] && [ -n "$US_DIR" ]; then + for GB_FILE in "$GB_DIR"/*.ini; do + [ ! -f "$GB_FILE" ] && continue + FNAME=$(basename "$GB_FILE") + US_FILE="$US_DIR/$FNAME" + [ ! -f "$US_FILE" ] && continue + + GB_KEYS=$(grep -oP '^[A-Z_][A-Z0-9_]*(?==)' "$GB_FILE" 2>/dev/null | sort) + US_KEYS=$(grep -oP '^[A-Z_][A-Z0-9_]*(?==)' "$US_FILE" 2>/dev/null | sort) + + # Keys in en-GB but not en-US + MISSING_US=$(comm -23 <(echo "$GB_KEYS") <(echo "$US_KEYS")) + if [ -n "$MISSING_US" ]; then + echo "::warning::Keys in en-GB/$FNAME but missing from en-US/$FNAME:" + echo "$MISSING_US" | while read -r k; do echo " - $k"; done + WARNINGS=$((WARNINGS + 1)) + fi + + # Keys in en-US but not en-GB + MISSING_GB=$(comm -13 <(echo "$GB_KEYS") <(echo "$US_KEYS")) + if [ -n "$MISSING_GB" ]; then + echo "::warning::Keys in en-US/$FNAME but missing from en-GB/$FNAME:" + echo "$MISSING_GB" | while read -r k; do echo " - $k"; done + WARNINGS=$((WARNINGS + 1)) + fi + done + fi + + { + echo "### Language File Validation" + echo "| Metric | Count |" + echo "|---|---|" + echo "| Files checked | $(echo "$INI_FILES" | wc -l) |" + echo "| Errors | ${ERRORS} |" + echo "| Warnings | ${WARNINGS} |" + } >> $GITHUB_STEP_SUMMARY + + if [ "$ERRORS" -gt 0 ]; then + echo "::error::Language validation failed with ${ERRORS} error(s)" + exit 1 + fi + echo "Language files: OK (${WARNINGS} warning(s))" + + - name: Check changelog has unreleased entry + run: | + if [ ! -f "CHANGELOG.md" ]; then + echo "::warning::No CHANGELOG.md found" + exit 0 + fi + # Check for content under [Unreleased] section + if ! grep -q "## \[Unreleased\]" CHANGELOG.md; then + echo "::error::CHANGELOG.md missing [Unreleased] section" + exit 1 + fi + # Check there's at least one entry (Added/Changed/Fixed/Removed) under Unreleased + UNRELEASED_CONTENT=$(sed -n '/## \[Unreleased\]/,/## \[/p' CHANGELOG.md | grep -cE '^\s*-\s' || true) + if [ "$UNRELEASED_CONTENT" -eq 0 ]; then + echo "::error::CHANGELOG.md [Unreleased] section has no entries. Add a changelog entry describing your changes." + echo "## Changelog Check: Failed" >> $GITHUB_STEP_SUMMARY + echo "The \`[Unreleased]\` section in CHANGELOG.md has no entries." >> $GITHUB_STEP_SUMMARY + echo "Add a line like \`- Description of your change\` under a heading (\`### Added\`, \`### Changed\`, \`### Fixed\`, etc.)" >> $GITHUB_STEP_SUMMARY + exit 1 + fi + echo "Changelog: ${UNRELEASED_CONTENT} entry/entries in [Unreleased]" + + - name: Verify package source + run: | + SOURCE_DIR="src" + [ ! -d "$SOURCE_DIR" ] && SOURCE_DIR="htdocs" + if [ ! -d "$SOURCE_DIR" ]; then + echo "::warning::No src/ or htdocs/ directory" + exit 0 + fi + FILE_COUNT=$(find "$SOURCE_DIR" -type f | wc -l) + echo "Source: ${FILE_COUNT} files" + [ "$FILE_COUNT" -gt 0 ] || { echo "::error::Source directory is empty"; exit 1; } + + # ── Pre-Release RC Build ───────────────────────────────────────────────── + pre-release: + name: Build RC Package + runs-on: ubuntu-latest + needs: [branch-policy, validate] + + steps: + - name: Trigger RC pre-release + env: + GA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }} + REPO: ${{ github.repository }} + BRANCH: ${{ github.head_ref }} + GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }} + run: | + curl -s -X POST "${GITEA_URL}/api/v1/repos/${REPO}/actions/workflows/pre-release.yml/dispatches" -H "Authorization: token ${GITEA_TOKEN}" -H "Content-Type: application/json" -d "{\"ref\":\"${BRANCH}\",\"inputs\":{\"stability\":\"release-candidate\"}}" + echo "### Pre-Release" >> $GITHUB_STEP_SUMMARY + echo "Triggered RC build on branch \`${BRANCH}\`" >> $GITHUB_STEP_SUMMARY + + # ── Issue Reporter ────────────────────────────────────────────────────── + report-issues: + name: Report Issues + runs-on: ubuntu-latest + needs: [branch-policy, validate] + if: >- + always() && + needs.validate.result == 'failure' + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + sparse-checkout: automation/ci-issue-reporter.sh + sparse-checkout-cone-mode: false + + - name: "File issue for PR validation failure" + env: + GITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }} + GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }} + run: | + chmod +x automation/ci-issue-reporter.sh + ./automation/ci-issue-reporter.sh \ + --gate "PR Validation" \ + --workflow "PR Check" \ + --severity error \ + --details "PR validation failed (syntax, manifest, changelog, or source checks). See the CI run for the specific check that failed." diff --git a/.mokogitea/workflows/repo-health.yml b/.mokogitea/workflows/repo-health.yml index 154f77d..b2b9263 100644 --- a/.mokogitea/workflows/repo-health.yml +++ b/.mokogitea/workflows/repo-health.yml @@ -1,712 +1,711 @@ -# ============================================================================ -# Copyright (C) 2025 Moko Consulting -# -# This file is part of a Moko Consulting project. -# -# SPDX-License-Identifier: GPL-3.0-or-later -# -# FILE INFORMATION -# DEFGROUP: Gitea.Workflow -# INGROUP: mokocli.Validation -# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/mokocli -# PATH: /templates/workflows/joomla/repo_health.yml.template -# VERSION: 09.23.00 -# BRIEF: Enforces repository guardrails by validating scripts governance, tooling availability, and core repository health artifacts. -# ============================================================================ - -name: "Generic: Repo Health" - -defaults: - run: - shell: bash - -on: - workflow_dispatch: - inputs: - profile: - description: 'Validation profile: all, scripts, or repo' - required: true - default: all - type: choice - options: - - all - - scripts - - repo - pull_request: - branches: - - main - -permissions: - contents: read - -env: - # Scripts governance policy - SCRIPTS_REQUIRED_DIRS: - SCRIPTS_ALLOWED_DIRS: scripts,scripts/fix,scripts/lib,scripts/release,scripts/run,scripts/validate - - # Repo health policy - REPO_REQUIRED_ARTIFACTS: README.md,LICENSE,CHANGELOG.md,CONTRIBUTING.md,CODE_OF_CONDUCT.md,.mokogitea/workflows/ - REPO_OPTIONAL_FILES: SECURITY.md,GOVERNANCE.md,.editorconfig,.gitattributes,.gitignore,README.md,docs/ - REPO_DISALLOWED_DIRS: - REPO_DISALLOWED_FILES: TODO.md,todo.md - - # Extended checks toggles - EXTENDED_CHECKS: "true" - - # File / directory variables - DOCS_INDEX: docs/docs-index.md - SCRIPT_DIR: scripts - WORKFLOWS_DIR: .mokogitea/workflows - SHELLCHECK_PATTERN: '*.sh' - SPDX_FILE_GLOBS: '*.sh,*.php,*.js,*.ts,*.css,*.xml,*.yml,*.yaml' - FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true - -jobs: - access_check: - name: Access control - runs-on: ubuntu-latest - timeout-minutes: 10 - permissions: - contents: read - - outputs: - allowed: ${{ steps.perm.outputs.allowed }} - permission: ${{ steps.perm.outputs.permission }} - - steps: - - name: Check actor permission (admin only) - id: perm - env: - TOKEN: ${{ secrets.MOKOGITEA_TOKEN || secrets.MOKOGITEA_TOKEN || github.token }} - REPO: ${{ github.repository }} - ACTOR: ${{ github.actor }} - run: | - set -euo pipefail - ALLOWED=false - PERMISSION=unknown - METHOD="" - - # Hardcoded authorized users — always allowed - case "$ACTOR" in - jmiller|gitea-actions[bot]) - ALLOWED=true - PERMISSION=admin - METHOD="hardcoded allowlist" - ;; - *) - # Detect platform and check permissions via API - API_BASE="${GITHUB_API_URL:-${GITEA_API_URL:-https://api.github.com}}" - RESP=$(curl -sf -H "Authorization: token ${TOKEN}" \ - "${API_BASE}/repos/${REPO}/collaborators/${ACTOR}/permission" 2>/dev/null || echo '{}') - PERMISSION=$(echo "$RESP" | grep -oP '"permission"\s*:\s*"\K[^"]+' || echo "unknown") - if [ "$PERMISSION" = "admin" ] || [ "$PERMISSION" = "maintain" ] || [ "$PERMISSION" = "owner" ]; then - ALLOWED=true - fi - METHOD="collaborator API" - ;; - esac - - echo "permission=${PERMISSION}" >> "$GITHUB_OUTPUT" - echo "allowed=${ALLOWED}" >> "$GITHUB_OUTPUT" - - { - echo "## Access Authorization" - echo "" - echo "| Field | Value |" - echo "|-------|-------|" - echo "| **Actor** | \`${ACTOR}\` |" - echo "| **Repository** | \`${REPO}\` |" - echo "| **Permission** | \`${PERMISSION}\` |" - echo "| **Method** | ${METHOD} |" - echo "| **Authorized** | ${ALLOWED} |" - echo "" - if [ "$ALLOWED" = "true" ]; then - echo "${ACTOR} authorized (${METHOD})" - else - echo "${ACTOR} is NOT authorized. Requires admin or maintain role." - fi - } >> "${GITHUB_STEP_SUMMARY}" - - - name: Deny execution when not permitted - if: ${{ steps.perm.outputs.allowed != 'true' }} - run: | - set -euo pipefail - printf '%s\n' 'ERROR: Access denied. Admin permission required.' >> "${GITHUB_STEP_SUMMARY}" - exit 1 - - scripts_governance: - name: Scripts governance - needs: access_check - if: ${{ needs.access_check.outputs.allowed == 'true' }} - runs-on: ubuntu-latest - timeout-minutes: 15 - permissions: - contents: read - - steps: - - name: Checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - with: - fetch-depth: 0 - - - name: Scripts folder checks - env: - PROFILE_RAW: ${{ github.event.inputs.profile }} - run: | - set -euo pipefail - - profile="${PROFILE_RAW:-all}" - case "${profile}" in - all|scripts|repo) ;; - *) - printf '%s\n' "ERROR: Unknown profile: ${profile}" >> "${GITHUB_STEP_SUMMARY}" - exit 1 - ;; - esac - - if [ "${profile}" = 'repo' ]; then - { - printf '%s\n' '### Scripts governance' - printf '%s\n' "Profile: ${profile}" - printf '%s\n' 'Status: SKIPPED' - printf '%s\n' 'Reason: profile excludes scripts governance' - printf '\n' - } >> "${GITHUB_STEP_SUMMARY}" - exit 0 - fi - - if [ ! -d "${SCRIPT_DIR}" ]; then - { - printf '%s\n' '### Scripts governance' - printf '%s\n' 'Status: OK (advisory)' - printf '%s\n' 'scripts/ directory not present. No scripts governance enforced.' - printf '\n' - } >> "${GITHUB_STEP_SUMMARY}" - exit 0 - fi - - if [ -n "${SCRIPTS_REQUIRED_DIRS:-}" ]; then IFS=',' read -r -a required_dirs <<< "${SCRIPTS_REQUIRED_DIRS}"; else required_dirs=(); fi - IFS=',' read -r -a allowed_dirs <<< "${SCRIPTS_ALLOWED_DIRS}" - - missing_dirs=() - unapproved_dirs=() - - for d in "${required_dirs[@]}"; do - req="${d%/}" - [ ! -d "${req}" ] && missing_dirs+=("${req}/") - done - - while IFS= read -r d; do - allowed=false - for a in "${allowed_dirs[@]}"; do - a_norm="${a%/}" - [ "${d%/}" = "${a_norm}" ] && allowed=true - done - [ "${allowed}" = false ] && unapproved_dirs+=("${d%/}/") - done < <(find "${SCRIPT_DIR}" -maxdepth 1 -mindepth 1 -type d 2>/dev/null | sed 's#^\./##') - - { - printf '%s\n' '### Scripts governance' - printf '%s\n' "Profile: ${profile}" - printf '%s\n' '| Area | Status | Notes |' - printf '%s\n' '|---|---|---|' - - if [ "${#missing_dirs[@]}" -gt 0 ]; then - printf '%s\n' '| Required directories | Warning | Missing required subfolders |' - else - printf '%s\n' '| Required directories | OK | All required subfolders present |' - fi - - if [ "${#unapproved_dirs[@]}" -gt 0 ]; then - printf '%s\n' '| Directory policy | Warning | Unapproved directories detected |' - else - printf '%s\n' '| Directory policy | OK | No unapproved directories |' - fi - - printf '%s\n' '| Enforcement mode | Advisory | scripts folder is optional |' - printf '\n' - - if [ "${#missing_dirs[@]}" -gt 0 ]; then - printf '%s\n' 'Missing required script directories:' - for m in "${missing_dirs[@]}"; do printf '%s\n' "- ${m}"; done - printf '\n' - else - printf '%s\n' 'Missing required script directories: none.' - printf '\n' - fi - - if [ "${#unapproved_dirs[@]}" -gt 0 ]; then - printf '%s\n' 'Unapproved script directories detected:' - for m in "${unapproved_dirs[@]}"; do printf '%s\n' "- ${m}"; done - printf '\n' - else - printf '%s\n' 'Unapproved script directories detected: none.' - printf '\n' - fi - - printf '%s\n' 'Scripts governance completed in advisory mode.' - printf '\n' - } >> "${GITHUB_STEP_SUMMARY}" - - repo_health: - name: Repository health - needs: access_check - if: ${{ needs.access_check.outputs.allowed == 'true' }} - runs-on: ubuntu-latest - timeout-minutes: 20 - permissions: - contents: read - - steps: - - name: Checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - with: - fetch-depth: 0 - - - name: Repository health checks - env: - PROFILE_RAW: ${{ github.event.inputs.profile }} - run: | - set -euo pipefail - - profile="${PROFILE_RAW:-all}" - case "${profile}" in - all|scripts|repo) ;; - *) - printf '%s\n' "ERROR: Unknown profile: ${profile}" >> "${GITHUB_STEP_SUMMARY}" - exit 1 - ;; - esac - - if [ "${profile}" = 'scripts' ]; then - { - printf '%s\n' '### Repository health' - printf '%s\n' "Profile: ${profile}" - printf '%s\n' 'Status: SKIPPED' - printf '%s\n' 'Reason: profile excludes repository health' - printf '\n' - } >> "${GITHUB_STEP_SUMMARY}" - exit 0 - fi - - IFS=',' read -r -a required_artifacts <<< "${REPO_REQUIRED_ARTIFACTS}" - IFS=',' read -r -a optional_files <<< "${REPO_OPTIONAL_FILES}" - if [ -n "${REPO_DISALLOWED_DIRS:-}" ]; then IFS=',' read -r -a disallowed_dirs <<< "${REPO_DISALLOWED_DIRS}"; else disallowed_dirs=(); fi - IFS=',' read -r -a disallowed_files <<< "${REPO_DISALLOWED_FILES:-}" - - missing_required=() - missing_optional=() - - # Source directory: src/ or htdocs/ (either is valid for extension repos) - SOURCE_DIR="" - if [ -d "src" ]; then - SOURCE_DIR="src" - elif [ -d "htdocs" ]; then - SOURCE_DIR="htdocs" - elif [ -d "deploy" ] || [ -d "cli" ] || [ -d "monitoring" ]; then - # Platform/tooling repos don't need src/ - SOURCE_DIR="" - else - missing_required+=("src/ or htdocs/ (source directory required)") - fi - - for item in "${required_artifacts[@]}"; do - if printf '%s' "${item}" | grep -q '/$'; then - d="${item%/}" - [ ! -d "${d}" ] && missing_required+=("${item}") - else - [ ! -f "${item}" ] && missing_required+=("${item}") - fi - done - - for f in "${optional_files[@]}"; do - if printf '%s' "${f}" | grep -q '/$'; then - d="${f%/}" - [ ! -d "${d}" ] && missing_optional+=("${f}") - else - [ ! -f "${f}" ] && missing_optional+=("${f}") - fi - done - - for d in "${disallowed_dirs[@]}"; do - d_norm="${d%/}" - [ -d "${d_norm}" ] && missing_required+=("${d_norm}/ (disallowed)") - done - - for f in "${disallowed_files[@]}"; do - [ -f "${f}" ] && missing_required+=("${f} (disallowed)") - done - - git fetch origin --prune - - dev_paths=() - dev_branches=() - - while IFS= read -r b; do - name="${b#origin/}" - if [ "${name}" = 'dev' ]; then - dev_branches+=("${name}") - else - dev_paths+=("${name}") - fi - done < <(git branch -r --list 'origin/dev*' | sed 's/^ *//') - - if [ "${#dev_paths[@]}" -eq 0 ] && [ "${#dev_branches[@]}" -eq 0 ]; then - missing_required+=("dev or dev/* branch") - fi - - content_warnings=() - - if [ -f 'CHANGELOG.md' ] && ! grep -Eq '^# Changelog' CHANGELOG.md; then - content_warnings+=("CHANGELOG.md missing '# Changelog' header") - fi - - if [ -f 'CHANGELOG.md' ] && grep -Eq '^[# ]*Unreleased' CHANGELOG.md; then - content_warnings+=("CHANGELOG.md contains Unreleased section (review release readiness)") - fi - - if [ -f 'LICENSE' ] && ! grep -qiE 'GNU GENERAL PUBLIC LICENSE|GPL' LICENSE; then - content_warnings+=("LICENSE does not look like a GPL text") - fi - - if [ -f 'README.md' ] && ! grep -qiE 'moko|Moko' README.md; then - content_warnings+=("README.md missing expected brand keyword") - fi - - export PROFILE_RAW="${profile}" - export MISSING_REQUIRED="$(printf '%s\n' "${missing_required[@]:-}")" - export MISSING_OPTIONAL="$(printf '%s\n' "${missing_optional[@]:-}")" - export CONTENT_WARNINGS="$(printf '%s\n' "${content_warnings[@]:-}")" - - report_json=$(printf '{"profile":"%s","missing_required":%d,"missing_optional":%d,"content_warnings":%d}' "$profile" "${#missing_required[@]}" "${#missing_optional[@]}" "${#content_warnings[@]}") - - { - printf '%s\n' '### Repository health' - printf '%s\n' "Profile: ${profile}" - printf '%s\n' '| Metric | Value |' - printf '%s\n' '|---|---|' - printf '%s\n' "| Missing required | ${#missing_required[@]} |" - printf '%s\n' "| Missing optional | ${#missing_optional[@]} |" - printf '%s\n' "| Content warnings | ${#content_warnings[@]} |" - printf '\n' - - printf '%s\n' '### Guardrails report (JSON)' - printf '%s\n' '```json' - printf '%s\n' "${report_json}" - printf '%s\n' '```' - printf '\n' - } >> "${GITHUB_STEP_SUMMARY}" - - if [ "${#missing_required[@]}" -gt 0 ]; then - { - printf '%s\n' '### Missing required repo artifacts' - for m in "${missing_required[@]}"; do printf '%s\n' "- ${m}"; done - printf '%s\n' 'ERROR: Guardrails failed. Missing required repository artifacts.' - printf '\n' - } >> "${GITHUB_STEP_SUMMARY}" - exit 1 - fi - - if [ "${#missing_optional[@]}" -gt 0 ]; then - { - printf '%s\n' '### Missing optional repo artifacts' - for m in "${missing_optional[@]}"; do printf '%s\n' "- ${m}"; done - printf '\n' - } >> "${GITHUB_STEP_SUMMARY}" - fi - - if [ "${#content_warnings[@]}" -gt 0 ]; then - { - printf '%s\n' '### Repo content warnings' - for m in "${content_warnings[@]}"; do printf '%s\n' "- ${m}"; done - printf '\n' - } >> "${GITHUB_STEP_SUMMARY}" - fi - - # -- Joomla-specific checks -- - joomla_findings=() - - MANIFEST="$(find . -maxdepth 2 -name '*.xml' -exec grep -l '/dev/null | head -1 || true)" - if [ -z "${MANIFEST}" ]; then - joomla_findings+=("Joomla XML manifest not found (no *.xml with tag)") - else - if ! grep -qP '' "${MANIFEST}"; then - joomla_findings+=("XML manifest: tag missing") - fi - if ! grep -qP 'type="(component|module|plugin|library|package|template|language)"' "${MANIFEST}"; then - joomla_findings+=("XML manifest: type attribute missing or invalid") - fi - if ! grep -qP '' "${MANIFEST}"; then - joomla_findings+=("XML manifest: tag missing") - fi - if ! grep -qP '' "${MANIFEST}"; then - joomla_findings+=("XML manifest: tag missing") - fi - if ! grep -qP ' missing (required for Joomla 5+)") - fi - fi - - INI_COUNT="$(find . -name '*.ini' -type f 2>/dev/null | wc -l)" - if [ "${INI_COUNT}" -eq 0 ]; then - joomla_findings+=("No .ini language files found") - fi - - if [ ! -f 'updates.xml' ]; then - joomla_findings+=("updates.xml missing in root (required for Joomla update server)") - fi - - if [ -n "${SOURCE_DIR}" ]; then - INDEX_DIRS=("${SOURCE_DIR}" "${SOURCE_DIR}/admin" "${SOURCE_DIR}/site") - for dir in "${INDEX_DIRS[@]}"; do - if [ -d "${dir}" ] && [ ! -f "${dir}/index.html" ]; then - joomla_findings+=("${dir}/index.html missing (directory listing protection)") - fi - done - fi - - if [ "${#joomla_findings[@]}" -gt 0 ]; then - { - printf '%s\n' '### Joomla extension checks' - printf '%s\n' '| Check | Status |' - printf '%s\n' '|---|---|' - for f in "${joomla_findings[@]}"; do - printf '%s\n' "| ${f} | Warning |" - done - printf '\n' - } >> "${GITHUB_STEP_SUMMARY}" - else - { - printf '%s\n' '### Joomla extension checks' - printf '%s\n' 'All Joomla-specific checks passed.' - printf '\n' - } >> "${GITHUB_STEP_SUMMARY}" - fi - - extended_enabled="${EXTENDED_CHECKS:-true}" - extended_findings=() - - if [ "${extended_enabled}" = 'true' ]; then - if [ -f '.github/CODEOWNERS' ] || [ -f 'CODEOWNERS' ] || [ -f 'docs/CODEOWNERS' ]; then - : - else - extended_findings+=("CODEOWNERS not found (.github/CODEOWNERS preferred)") - fi - - if ls "${WORKFLOWS_DIR}"/*.yml >/dev/null 2>&1 || ls "${WORKFLOWS_DIR}"/*.yaml >/dev/null 2>&1; then - bad_refs="$(grep -RIn --include='*.yml' --include='*.yaml' -E '^[[:space:]]*uses:[[:space:]]*[^#]+@(main|master)\b' "${WORKFLOWS_DIR}" 2>/dev/null || true)" - if [ -n "${bad_refs}" ]; then - extended_findings+=("Workflows reference actions @main/@master (pin versions): see log excerpt") - { - printf '%s\n' '### Workflow pinning advisory' - printf '%s\n' 'Found uses: entries pinned to main/master:' - printf '%s\n' '```' - printf '%s\n' "${bad_refs}" - printf '%s\n' '```' - printf '\n' - } >> "${GITHUB_STEP_SUMMARY}" - fi - fi - - if [ -f "${DOCS_INDEX}" ]; then - missing_links="" - while IFS= read -r docline; do - for link in $(echo "$docline" | grep -oE '\]\([^)]+\)' | sed 's/\](//' | sed 's/)$//' || true); do - case "$link" in http://*|https://*|"#"*|mailto:*) continue ;; esac - linkpath="${link%%#*}" - linkpath="${linkpath%%\?*}" - [ -z "$linkpath" ] && continue - if [ "${linkpath:0:1}" = "/" ]; then - testpath="${linkpath#/}" - else - testpath="$(dirname "${DOCS_INDEX}")/${linkpath}" - fi - [ ! -e "$testpath" ] && missing_links="${missing_links}${testpath} " - done - done < "${DOCS_INDEX}" - if [ -n "${missing_links}" ]; then - extended_findings+=("docs/docs-index.md contains broken relative links") - { - printf '%s\n' '### Docs index link integrity' - printf '%s\n' 'Broken relative links:' - for bl in ${missing_links}; do - printf '%s\n' "- ${bl}" - done - printf '\n' - } >> "${GITHUB_STEP_SUMMARY}" - fi - fi - - if [ -d "${SCRIPT_DIR}" ]; then - if ! command -v shellcheck >/dev/null 2>&1; then - sudo apt-get update -qq - sudo apt-get install -y shellcheck >/dev/null - fi - - sc_out='' - while IFS= read -r shf; do - [ -z "${shf}" ] && continue - out_one="$(shellcheck -S warning -x "${shf}" 2>/dev/null || true)" - if [ -n "${out_one}" ]; then - sc_out="${sc_out}${out_one}\n" - fi - done < <(find "${SCRIPT_DIR}" -type f -name "${SHELLCHECK_PATTERN}" 2>/dev/null | sort) - - if [ -n "${sc_out}" ]; then - extended_findings+=("ShellCheck warnings detected (advisory)") - sc_head="$(printf '%s' "${sc_out}" | head -n 200)" - { - printf '%s\n' '### ShellCheck (advisory)' - printf '%s\n' '```' - printf '%s\n' "${sc_head}" - printf '%s\n' '```' - printf '\n' - } >> "${GITHUB_STEP_SUMMARY}" - fi - fi - - spdx_missing=() - IFS=',' read -r -a spdx_globs <<< "${SPDX_FILE_GLOBS}" - spdx_args=() - for g in "${spdx_globs[@]}"; do spdx_args+=("${g}"); done - - while IFS= read -r f; do - [ -z "${f}" ] && continue - if ! head -n 40 "${f}" | grep -q 'SPDX-License-Identifier:'; then - spdx_missing+=("${f}") - fi - done < <(git ls-files "${spdx_args[@]}" 2>/dev/null || true) - - if [ "${#spdx_missing[@]}" -gt 0 ]; then - extended_findings+=("SPDX header missing in some tracked files (advisory)") - { - printf '%s\n' '### SPDX header advisory' - printf '%s\n' 'Files missing SPDX-License-Identifier (first 40 lines scan):' - for f in "${spdx_missing[@]}"; do printf '%s\n' "- ${f}"; done - printf '\n' - } >> "${GITHUB_STEP_SUMMARY}" - fi - - stale_cutoff_days=180 - stale_branches="$(git for-each-ref --format='%(refname:short) %(committerdate:unix)' refs/remotes/origin 2>/dev/null | awk -v now="$(date +%s)" -v days="${stale_cutoff_days}" '{if (now-$2 > days*86400) print $1}' | head -50)" - if [ -n "${stale_branches}" ]; then - extended_findings+=("Stale remote branches detected (advisory)") - { - printf '%s\n' '### Git hygiene advisory' - printf '%s\n' "Branches with last commit older than ${stale_cutoff_days} days (sample up to 50):" - while IFS= read -r b; do [ -n "${b}" ] && printf '%s\n' "- ${b}"; done <<< "${stale_branches}" - printf '\n' - } >> "${GITHUB_STEP_SUMMARY}" - fi - fi - - { - printf '%s\n' '### Guardrails coverage matrix' - printf '%s\n' '| Domain | Status | Notes |' - printf '%s\n' '|---|---|---|' - printf '%s\n' '| Access control | OK | Admin-only execution gate |' - printf '%s\n' '| Release policy | N/A | Releases handled by MokoGitea |' - printf '%s\n' '| Scripts governance | OK | Directory policy and advisory reporting |' - printf '%s\n' '| Repo required artifacts | OK | Required, optional, disallowed enforcement |' - printf '%s\n' '| Repo content heuristics | OK | Brand, license, changelog structure |' - if [ "${extended_enabled}" = 'true' ]; then - if [ "${#extended_findings[@]}" -gt 0 ]; then - printf '%s\n' '| Extended checks | Warning | See extended findings below |' - else - printf '%s\n' '| Extended checks | OK | No findings |' - fi - else - printf '%s\n' '| Extended checks | SKIPPED | EXTENDED_CHECKS disabled |' - fi - printf '\n' - } >> "${GITHUB_STEP_SUMMARY}" - - if [ "${extended_enabled}" = 'true' ] && [ "${#extended_findings[@]}" -gt 0 ]; then - { - printf '%s\n' '### Extended findings (advisory)' - for f in "${extended_findings[@]}"; do printf '%s\n' "- ${f}"; done - printf '\n' - } >> "${GITHUB_STEP_SUMMARY}" - fi - - printf '%s\n' 'Repository health guardrails passed.' >> "${GITHUB_STEP_SUMMARY}" - - - site-health: - name: Site Health - runs-on: ubuntu-latest - if: github.event_name == 'workflow_dispatch' - steps: - - uses: actions/checkout@v4 - - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: '8.3' - - - name: Uptime check - if: env.URLS != '' - run: | - echo "$URLS" > /tmp/urls.txt - php monitoring/uptime-probe.php --urls /tmp/urls.txt --timeout 15 || echo "::warning::Some sites are down" - rm -f /tmp/urls.txt - env: - URLS: ${{ vars.MONITORED_URLS }} - - - name: SSL certificate check - if: env.DOMAINS != '' - run: | - echo "$DOMAINS" > /tmp/domains.txt - php monitoring/ssl-check.php --domains /tmp/domains.txt --warn-days 30 || echo "::warning::SSL certificates expiring soon" - rm -f /tmp/domains.txt - env: - DOMAINS: ${{ vars.MONITORED_DOMAINS }} - - - name: Summary - if: always() - run: | - echo "### Site Health" >> $GITHUB_STEP_SUMMARY - echo "Uptime and SSL checks completed." >> $GITHUB_STEP_SUMMARY - - # ═══════════════════════════════════════════════════════════════════════ - # Issue Reporter — file issues for failed gates - # ═══════════════════════════════════════════════════════════════════════ - report-issues: - name: "Report Issues" - runs-on: ubuntu-latest - needs: [access_check, scripts_governance, repo_health] - if: >- - always() && - (needs.scripts_governance.result == 'failure' || - needs.repo_health.result == 'failure') - - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - sparse-checkout: automation/ci-issue-reporter.sh - sparse-checkout-cone-mode: false - - - name: "File issues for failed gates" - env: - GITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }} - GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }} - run: | - chmod +x automation/ci-issue-reporter.sh - REPORTER="./automation/ci-issue-reporter.sh" - WF="Repo Health" - - report_gate() { - local gate="$1" result="$2" details="$3" - if [ "$result" = "failure" ]; then - "$REPORTER" --gate "$gate" --details "$details" --workflow "$WF" --severity error - fi - } - - report_gate "Scripts Governance" \ - "${{ needs.scripts_governance.result }}" \ - "Scripts directory policy violations detected. Review required and allowed directories." - - report_gate "Repository Health" \ - "${{ needs.repo_health.result }}" \ - "Repository health checks failed — missing required artifacts, disallowed files, or content warnings. Check the CI run summary." +# ============================================================================ +# Copyright (C) 2025 Moko Consulting +# +# This file is part of a Moko Consulting project. +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# FILE INFORMATION +# DEFGROUP: Gitea.Workflow +# INGROUP: mokoplatform.Validation +# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/mokoplatform +# PATH: /templates/workflows/joomla/repo_health.yml.template +# VERSION: 09.23.00 +# BRIEF: Enforces repository guardrails by validating scripts governance, tooling availability, and core repository health artifacts. +# ============================================================================ + +name: "Generic: Repo Health" + +defaults: + run: + shell: bash + +on: + workflow_dispatch: + inputs: + profile: + description: 'Validation profile: all, scripts, or repo' + required: true + default: all + type: choice + options: + - all + - scripts + - repo + pull_request: + push: + +permissions: + contents: read + +env: + # Scripts governance policy + SCRIPTS_REQUIRED_DIRS: + SCRIPTS_ALLOWED_DIRS: scripts,scripts/fix,scripts/lib,scripts/release,scripts/run,scripts/validate + + # Repo health policy + REPO_REQUIRED_ARTIFACTS: README.md,LICENSE,CHANGELOG.md,CONTRIBUTING.md,CODE_OF_CONDUCT.md,.mokogitea/workflows/ + REPO_OPTIONAL_FILES: SECURITY.md,GOVERNANCE.md,.editorconfig,.gitattributes,.gitignore,README.md,docs/ + REPO_DISALLOWED_DIRS: + REPO_DISALLOWED_FILES: TODO.md,todo.md + + # Extended checks toggles + EXTENDED_CHECKS: "true" + + # File / directory variables + DOCS_INDEX: docs/docs-index.md + SCRIPT_DIR: scripts + WORKFLOWS_DIR: .mokogitea/workflows + SHELLCHECK_PATTERN: '*.sh' + SPDX_FILE_GLOBS: '*.sh,*.php,*.js,*.ts,*.css,*.xml,*.yml,*.yaml' + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + access_check: + name: Access control + runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + contents: read + + outputs: + allowed: ${{ steps.perm.outputs.allowed }} + permission: ${{ steps.perm.outputs.permission }} + + steps: + - name: Check actor permission (admin only) + id: perm + env: + TOKEN: ${{ secrets.MOKOGITEA_TOKEN || secrets.MOKOGITEA_TOKEN || github.token }} + REPO: ${{ github.repository }} + ACTOR: ${{ github.actor }} + run: | + set -euo pipefail + ALLOWED=false + PERMISSION=unknown + METHOD="" + + # Hardcoded authorized users — always allowed + case "$ACTOR" in + jmiller|gitea-actions[bot]) + ALLOWED=true + PERMISSION=admin + METHOD="hardcoded allowlist" + ;; + *) + # Detect platform and check permissions via API + API_BASE="${GITHUB_API_URL:-${GITEA_API_URL:-https://api.github.com}}" + RESP=$(curl -sf -H "Authorization: token ${TOKEN}" \ + "${API_BASE}/repos/${REPO}/collaborators/${ACTOR}/permission" 2>/dev/null || echo '{}') + PERMISSION=$(echo "$RESP" | grep -oP '"permission"\s*:\s*"\K[^"]+' || echo "unknown") + if [ "$PERMISSION" = "admin" ] || [ "$PERMISSION" = "maintain" ] || [ "$PERMISSION" = "owner" ]; then + ALLOWED=true + fi + METHOD="collaborator API" + ;; + esac + + echo "permission=${PERMISSION}" >> "$GITHUB_OUTPUT" + echo "allowed=${ALLOWED}" >> "$GITHUB_OUTPUT" + + { + echo "## Access Authorization" + echo "" + echo "| Field | Value |" + echo "|-------|-------|" + echo "| **Actor** | \`${ACTOR}\` |" + echo "| **Repository** | \`${REPO}\` |" + echo "| **Permission** | \`${PERMISSION}\` |" + echo "| **Method** | ${METHOD} |" + echo "| **Authorized** | ${ALLOWED} |" + echo "" + if [ "$ALLOWED" = "true" ]; then + echo "${ACTOR} authorized (${METHOD})" + else + echo "${ACTOR} is NOT authorized. Requires admin or maintain role." + fi + } >> "${GITHUB_STEP_SUMMARY}" + + - name: Deny execution when not permitted + if: ${{ steps.perm.outputs.allowed != 'true' }} + run: | + set -euo pipefail + printf '%s\n' 'ERROR: Access denied. Admin permission required.' >> "${GITHUB_STEP_SUMMARY}" + exit 1 + + scripts_governance: + name: Scripts governance + needs: access_check + if: ${{ needs.access_check.outputs.allowed == 'true' }} + runs-on: ubuntu-latest + timeout-minutes: 15 + permissions: + contents: read + + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + fetch-depth: 0 + + - name: Scripts folder checks + env: + PROFILE_RAW: ${{ github.event.inputs.profile }} + run: | + set -euo pipefail + + profile="${PROFILE_RAW:-all}" + case "${profile}" in + all|scripts|repo) ;; + *) + printf '%s\n' "ERROR: Unknown profile: ${profile}" >> "${GITHUB_STEP_SUMMARY}" + exit 1 + ;; + esac + + if [ "${profile}" = 'repo' ]; then + { + printf '%s\n' '### Scripts governance' + printf '%s\n' "Profile: ${profile}" + printf '%s\n' 'Status: SKIPPED' + printf '%s\n' 'Reason: profile excludes scripts governance' + printf '\n' + } >> "${GITHUB_STEP_SUMMARY}" + exit 0 + fi + + if [ ! -d "${SCRIPT_DIR}" ]; then + { + printf '%s\n' '### Scripts governance' + printf '%s\n' 'Status: OK (advisory)' + printf '%s\n' 'scripts/ directory not present. No scripts governance enforced.' + printf '\n' + } >> "${GITHUB_STEP_SUMMARY}" + exit 0 + fi + + if [ -n "${SCRIPTS_REQUIRED_DIRS:-}" ]; then IFS=',' read -r -a required_dirs <<< "${SCRIPTS_REQUIRED_DIRS}"; else required_dirs=(); fi + IFS=',' read -r -a allowed_dirs <<< "${SCRIPTS_ALLOWED_DIRS}" + + missing_dirs=() + unapproved_dirs=() + + for d in "${required_dirs[@]}"; do + req="${d%/}" + [ ! -d "${req}" ] && missing_dirs+=("${req}/") + done + + while IFS= read -r d; do + allowed=false + for a in "${allowed_dirs[@]}"; do + a_norm="${a%/}" + [ "${d%/}" = "${a_norm}" ] && allowed=true + done + [ "${allowed}" = false ] && unapproved_dirs+=("${d%/}/") + done < <(find "${SCRIPT_DIR}" -maxdepth 1 -mindepth 1 -type d 2>/dev/null | sed 's#^\./##') + + { + printf '%s\n' '### Scripts governance' + printf '%s\n' "Profile: ${profile}" + printf '%s\n' '| Area | Status | Notes |' + printf '%s\n' '|---|---|---|' + + if [ "${#missing_dirs[@]}" -gt 0 ]; then + printf '%s\n' '| Required directories | Warning | Missing required subfolders |' + else + printf '%s\n' '| Required directories | OK | All required subfolders present |' + fi + + if [ "${#unapproved_dirs[@]}" -gt 0 ]; then + printf '%s\n' '| Directory policy | Warning | Unapproved directories detected |' + else + printf '%s\n' '| Directory policy | OK | No unapproved directories |' + fi + + printf '%s\n' '| Enforcement mode | Advisory | scripts folder is optional |' + printf '\n' + + if [ "${#missing_dirs[@]}" -gt 0 ]; then + printf '%s\n' 'Missing required script directories:' + for m in "${missing_dirs[@]}"; do printf '%s\n' "- ${m}"; done + printf '\n' + else + printf '%s\n' 'Missing required script directories: none.' + printf '\n' + fi + + if [ "${#unapproved_dirs[@]}" -gt 0 ]; then + printf '%s\n' 'Unapproved script directories detected:' + for m in "${unapproved_dirs[@]}"; do printf '%s\n' "- ${m}"; done + printf '\n' + else + printf '%s\n' 'Unapproved script directories detected: none.' + printf '\n' + fi + + printf '%s\n' 'Scripts governance completed in advisory mode.' + printf '\n' + } >> "${GITHUB_STEP_SUMMARY}" + + repo_health: + name: Repository health + needs: access_check + if: ${{ needs.access_check.outputs.allowed == 'true' }} + runs-on: ubuntu-latest + timeout-minutes: 20 + permissions: + contents: read + + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + fetch-depth: 0 + + - name: Repository health checks + env: + PROFILE_RAW: ${{ github.event.inputs.profile }} + run: | + set -euo pipefail + + profile="${PROFILE_RAW:-all}" + case "${profile}" in + all|scripts|repo) ;; + *) + printf '%s\n' "ERROR: Unknown profile: ${profile}" >> "${GITHUB_STEP_SUMMARY}" + exit 1 + ;; + esac + + if [ "${profile}" = 'scripts' ]; then + { + printf '%s\n' '### Repository health' + printf '%s\n' "Profile: ${profile}" + printf '%s\n' 'Status: SKIPPED' + printf '%s\n' 'Reason: profile excludes repository health' + printf '\n' + } >> "${GITHUB_STEP_SUMMARY}" + exit 0 + fi + + IFS=',' read -r -a required_artifacts <<< "${REPO_REQUIRED_ARTIFACTS}" + IFS=',' read -r -a optional_files <<< "${REPO_OPTIONAL_FILES}" + if [ -n "${REPO_DISALLOWED_DIRS:-}" ]; then IFS=',' read -r -a disallowed_dirs <<< "${REPO_DISALLOWED_DIRS}"; else disallowed_dirs=(); fi + IFS=',' read -r -a disallowed_files <<< "${REPO_DISALLOWED_FILES:-}" + + missing_required=() + missing_optional=() + + # Source directory: src/ or htdocs/ (either is valid for extension repos) + SOURCE_DIR="" + if [ -d "src" ]; then + SOURCE_DIR="src" + elif [ -d "htdocs" ]; then + SOURCE_DIR="htdocs" + elif [ -d "deploy" ] || [ -d "cli" ] || [ -d "monitoring" ]; then + # Platform/tooling repos don't need src/ + SOURCE_DIR="" + else + missing_required+=("src/ or htdocs/ (source directory required)") + fi + + for item in "${required_artifacts[@]}"; do + if printf '%s' "${item}" | grep -q '/$'; then + d="${item%/}" + [ ! -d "${d}" ] && missing_required+=("${item}") + else + [ ! -f "${item}" ] && missing_required+=("${item}") + fi + done + + for f in "${optional_files[@]}"; do + if printf '%s' "${f}" | grep -q '/$'; then + d="${f%/}" + [ ! -d "${d}" ] && missing_optional+=("${f}") + else + [ ! -f "${f}" ] && missing_optional+=("${f}") + fi + done + + for d in "${disallowed_dirs[@]}"; do + d_norm="${d%/}" + [ -d "${d_norm}" ] && missing_required+=("${d_norm}/ (disallowed)") + done + + for f in "${disallowed_files[@]}"; do + [ -f "${f}" ] && missing_required+=("${f} (disallowed)") + done + + git fetch origin --prune + + dev_paths=() + dev_branches=() + + while IFS= read -r b; do + name="${b#origin/}" + if [ "${name}" = 'dev' ]; then + dev_branches+=("${name}") + else + dev_paths+=("${name}") + fi + done < <(git branch -r --list 'origin/dev*' | sed 's/^ *//') + + if [ "${#dev_paths[@]}" -eq 0 ] && [ "${#dev_branches[@]}" -eq 0 ]; then + missing_required+=("dev or dev/* branch") + fi + + content_warnings=() + + if [ -f 'CHANGELOG.md' ] && ! grep -Eq '^# Changelog' CHANGELOG.md; then + content_warnings+=("CHANGELOG.md missing '# Changelog' header") + fi + + if [ -f 'CHANGELOG.md' ] && grep -Eq '^[# ]*Unreleased' CHANGELOG.md; then + content_warnings+=("CHANGELOG.md contains Unreleased section (review release readiness)") + fi + + if [ -f 'LICENSE' ] && ! grep -qiE 'GNU GENERAL PUBLIC LICENSE|GPL' LICENSE; then + content_warnings+=("LICENSE does not look like a GPL text") + fi + + if [ -f 'README.md' ] && ! grep -qiE 'moko|Moko' README.md; then + content_warnings+=("README.md missing expected brand keyword") + fi + + export PROFILE_RAW="${profile}" + export MISSING_REQUIRED="$(printf '%s\n' "${missing_required[@]:-}")" + export MISSING_OPTIONAL="$(printf '%s\n' "${missing_optional[@]:-}")" + export CONTENT_WARNINGS="$(printf '%s\n' "${content_warnings[@]:-}")" + + report_json=$(printf '{"profile":"%s","missing_required":%d,"missing_optional":%d,"content_warnings":%d}' "$profile" "${#missing_required[@]}" "${#missing_optional[@]}" "${#content_warnings[@]}") + + { + printf '%s\n' '### Repository health' + printf '%s\n' "Profile: ${profile}" + printf '%s\n' '| Metric | Value |' + printf '%s\n' '|---|---|' + printf '%s\n' "| Missing required | ${#missing_required[@]} |" + printf '%s\n' "| Missing optional | ${#missing_optional[@]} |" + printf '%s\n' "| Content warnings | ${#content_warnings[@]} |" + printf '\n' + + printf '%s\n' '### Guardrails report (JSON)' + printf '%s\n' '```json' + printf '%s\n' "${report_json}" + printf '%s\n' '```' + printf '\n' + } >> "${GITHUB_STEP_SUMMARY}" + + if [ "${#missing_required[@]}" -gt 0 ]; then + { + printf '%s\n' '### Missing required repo artifacts' + for m in "${missing_required[@]}"; do printf '%s\n' "- ${m}"; done + printf '%s\n' 'ERROR: Guardrails failed. Missing required repository artifacts.' + printf '\n' + } >> "${GITHUB_STEP_SUMMARY}" + exit 1 + fi + + if [ "${#missing_optional[@]}" -gt 0 ]; then + { + printf '%s\n' '### Missing optional repo artifacts' + for m in "${missing_optional[@]}"; do printf '%s\n' "- ${m}"; done + printf '\n' + } >> "${GITHUB_STEP_SUMMARY}" + fi + + if [ "${#content_warnings[@]}" -gt 0 ]; then + { + printf '%s\n' '### Repo content warnings' + for m in "${content_warnings[@]}"; do printf '%s\n' "- ${m}"; done + printf '\n' + } >> "${GITHUB_STEP_SUMMARY}" + fi + + # -- Joomla-specific checks -- + joomla_findings=() + + MANIFEST="$(find . -maxdepth 2 -name '*.xml' -exec grep -l '/dev/null | head -1 || true)" + if [ -z "${MANIFEST}" ]; then + joomla_findings+=("Joomla XML manifest not found (no *.xml with tag)") + else + if ! grep -qP '' "${MANIFEST}"; then + joomla_findings+=("XML manifest: tag missing") + fi + if ! grep -qP 'type="(component|module|plugin|library|package|template|language)"' "${MANIFEST}"; then + joomla_findings+=("XML manifest: type attribute missing or invalid") + fi + if ! grep -qP '' "${MANIFEST}"; then + joomla_findings+=("XML manifest: tag missing") + fi + if ! grep -qP '' "${MANIFEST}"; then + joomla_findings+=("XML manifest: tag missing") + fi + if ! grep -qP ' missing (required for Joomla 5+)") + fi + fi + + INI_COUNT="$(find . -name '*.ini' -type f 2>/dev/null | wc -l)" + if [ "${INI_COUNT}" -eq 0 ]; then + joomla_findings+=("No .ini language files found") + fi + + if [ ! -f 'updates.xml' ]; then + joomla_findings+=("updates.xml missing in root (required for Joomla update server)") + fi + + if [ -n "${SOURCE_DIR}" ]; then + INDEX_DIRS=("${SOURCE_DIR}" "${SOURCE_DIR}/admin" "${SOURCE_DIR}/site") + for dir in "${INDEX_DIRS[@]}"; do + if [ -d "${dir}" ] && [ ! -f "${dir}/index.html" ]; then + joomla_findings+=("${dir}/index.html missing (directory listing protection)") + fi + done + fi + + if [ "${#joomla_findings[@]}" -gt 0 ]; then + { + printf '%s\n' '### Joomla extension checks' + printf '%s\n' '| Check | Status |' + printf '%s\n' '|---|---|' + for f in "${joomla_findings[@]}"; do + printf '%s\n' "| ${f} | Warning |" + done + printf '\n' + } >> "${GITHUB_STEP_SUMMARY}" + else + { + printf '%s\n' '### Joomla extension checks' + printf '%s\n' 'All Joomla-specific checks passed.' + printf '\n' + } >> "${GITHUB_STEP_SUMMARY}" + fi + + extended_enabled="${EXTENDED_CHECKS:-true}" + extended_findings=() + + if [ "${extended_enabled}" = 'true' ]; then + if [ -f '.github/CODEOWNERS' ] || [ -f 'CODEOWNERS' ] || [ -f 'docs/CODEOWNERS' ]; then + : + else + extended_findings+=("CODEOWNERS not found (.github/CODEOWNERS preferred)") + fi + + if ls "${WORKFLOWS_DIR}"/*.yml >/dev/null 2>&1 || ls "${WORKFLOWS_DIR}"/*.yaml >/dev/null 2>&1; then + bad_refs="$(grep -RIn --include='*.yml' --include='*.yaml' -E '^[[:space:]]*uses:[[:space:]]*[^#]+@(main|master)\b' "${WORKFLOWS_DIR}" 2>/dev/null || true)" + if [ -n "${bad_refs}" ]; then + extended_findings+=("Workflows reference actions @main/@master (pin versions): see log excerpt") + { + printf '%s\n' '### Workflow pinning advisory' + printf '%s\n' 'Found uses: entries pinned to main/master:' + printf '%s\n' '```' + printf '%s\n' "${bad_refs}" + printf '%s\n' '```' + printf '\n' + } >> "${GITHUB_STEP_SUMMARY}" + fi + fi + + if [ -f "${DOCS_INDEX}" ]; then + missing_links="" + while IFS= read -r docline; do + for link in $(echo "$docline" | grep -oE '\]\([^)]+\)' | sed 's/\](//' | sed 's/)$//' || true); do + case "$link" in http://*|https://*|"#"*|mailto:*) continue ;; esac + linkpath="${link%%#*}" + linkpath="${linkpath%%\?*}" + [ -z "$linkpath" ] && continue + if [ "${linkpath:0:1}" = "/" ]; then + testpath="${linkpath#/}" + else + testpath="$(dirname "${DOCS_INDEX}")/${linkpath}" + fi + [ ! -e "$testpath" ] && missing_links="${missing_links}${testpath} " + done + done < "${DOCS_INDEX}" + if [ -n "${missing_links}" ]; then + extended_findings+=("docs/docs-index.md contains broken relative links") + { + printf '%s\n' '### Docs index link integrity' + printf '%s\n' 'Broken relative links:' + for bl in ${missing_links}; do + printf '%s\n' "- ${bl}" + done + printf '\n' + } >> "${GITHUB_STEP_SUMMARY}" + fi + fi + + if [ -d "${SCRIPT_DIR}" ]; then + if ! command -v shellcheck >/dev/null 2>&1; then + sudo apt-get update -qq + sudo apt-get install -y shellcheck >/dev/null + fi + + sc_out='' + while IFS= read -r shf; do + [ -z "${shf}" ] && continue + out_one="$(shellcheck -S warning -x "${shf}" 2>/dev/null || true)" + if [ -n "${out_one}" ]; then + sc_out="${sc_out}${out_one}\n" + fi + done < <(find "${SCRIPT_DIR}" -type f -name "${SHELLCHECK_PATTERN}" 2>/dev/null | sort) + + if [ -n "${sc_out}" ]; then + extended_findings+=("ShellCheck warnings detected (advisory)") + sc_head="$(printf '%s' "${sc_out}" | head -n 200)" + { + printf '%s\n' '### ShellCheck (advisory)' + printf '%s\n' '```' + printf '%s\n' "${sc_head}" + printf '%s\n' '```' + printf '\n' + } >> "${GITHUB_STEP_SUMMARY}" + fi + fi + + spdx_missing=() + IFS=',' read -r -a spdx_globs <<< "${SPDX_FILE_GLOBS}" + spdx_args=() + for g in "${spdx_globs[@]}"; do spdx_args+=("${g}"); done + + while IFS= read -r f; do + [ -z "${f}" ] && continue + if ! head -n 40 "${f}" | grep -q 'SPDX-License-Identifier:'; then + spdx_missing+=("${f}") + fi + done < <(git ls-files "${spdx_args[@]}" 2>/dev/null || true) + + if [ "${#spdx_missing[@]}" -gt 0 ]; then + extended_findings+=("SPDX header missing in some tracked files (advisory)") + { + printf '%s\n' '### SPDX header advisory' + printf '%s\n' 'Files missing SPDX-License-Identifier (first 40 lines scan):' + for f in "${spdx_missing[@]}"; do printf '%s\n' "- ${f}"; done + printf '\n' + } >> "${GITHUB_STEP_SUMMARY}" + fi + + stale_cutoff_days=180 + stale_branches="$(git for-each-ref --format='%(refname:short) %(committerdate:unix)' refs/remotes/origin 2>/dev/null | awk -v now="$(date +%s)" -v days="${stale_cutoff_days}" '{if (now-$2 > days*86400) print $1}' | head -50)" + if [ -n "${stale_branches}" ]; then + extended_findings+=("Stale remote branches detected (advisory)") + { + printf '%s\n' '### Git hygiene advisory' + printf '%s\n' "Branches with last commit older than ${stale_cutoff_days} days (sample up to 50):" + while IFS= read -r b; do [ -n "${b}" ] && printf '%s\n' "- ${b}"; done <<< "${stale_branches}" + printf '\n' + } >> "${GITHUB_STEP_SUMMARY}" + fi + fi + + { + printf '%s\n' '### Guardrails coverage matrix' + printf '%s\n' '| Domain | Status | Notes |' + printf '%s\n' '|---|---|---|' + printf '%s\n' '| Access control | OK | Admin-only execution gate |' + printf '%s\n' '| Release policy | N/A | Releases handled by MokoGitea |' + printf '%s\n' '| Scripts governance | OK | Directory policy and advisory reporting |' + printf '%s\n' '| Repo required artifacts | OK | Required, optional, disallowed enforcement |' + printf '%s\n' '| Repo content heuristics | OK | Brand, license, changelog structure |' + if [ "${extended_enabled}" = 'true' ]; then + if [ "${#extended_findings[@]}" -gt 0 ]; then + printf '%s\n' '| Extended checks | Warning | See extended findings below |' + else + printf '%s\n' '| Extended checks | OK | No findings |' + fi + else + printf '%s\n' '| Extended checks | SKIPPED | EXTENDED_CHECKS disabled |' + fi + printf '\n' + } >> "${GITHUB_STEP_SUMMARY}" + + if [ "${extended_enabled}" = 'true' ] && [ "${#extended_findings[@]}" -gt 0 ]; then + { + printf '%s\n' '### Extended findings (advisory)' + for f in "${extended_findings[@]}"; do printf '%s\n' "- ${f}"; done + printf '\n' + } >> "${GITHUB_STEP_SUMMARY}" + fi + + printf '%s\n' 'Repository health guardrails passed.' >> "${GITHUB_STEP_SUMMARY}" + + + site-health: + name: Site Health + runs-on: ubuntu-latest + if: github.event_name == 'workflow_dispatch' + steps: + - uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + + - name: Uptime check + if: env.URLS != '' + run: | + echo "$URLS" > /tmp/urls.txt + php monitoring/uptime-probe.php --urls /tmp/urls.txt --timeout 15 || echo "::warning::Some sites are down" + rm -f /tmp/urls.txt + env: + URLS: ${{ vars.MONITORED_URLS }} + + - name: SSL certificate check + if: env.DOMAINS != '' + run: | + echo "$DOMAINS" > /tmp/domains.txt + php monitoring/ssl-check.php --domains /tmp/domains.txt --warn-days 30 || echo "::warning::SSL certificates expiring soon" + rm -f /tmp/domains.txt + env: + DOMAINS: ${{ vars.MONITORED_DOMAINS }} + + - name: Summary + if: always() + run: | + echo "### Site Health" >> $GITHUB_STEP_SUMMARY + echo "Uptime and SSL checks completed." >> $GITHUB_STEP_SUMMARY + + # ═══════════════════════════════════════════════════════════════════════ + # Issue Reporter — file issues for failed gates + # ═══════════════════════════════════════════════════════════════════════ + report-issues: + name: "Report Issues" + runs-on: ubuntu-latest + needs: [access_check, scripts_governance, repo_health] + if: >- + always() && + (needs.scripts_governance.result == 'failure' || + needs.repo_health.result == 'failure') + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + sparse-checkout: automation/ci-issue-reporter.sh + sparse-checkout-cone-mode: false + + - name: "File issues for failed gates" + env: + GITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }} + GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }} + run: | + chmod +x automation/ci-issue-reporter.sh + REPORTER="./automation/ci-issue-reporter.sh" + WF="Repo Health" + + report_gate() { + local gate="$1" result="$2" details="$3" + if [ "$result" = "failure" ]; then + "$REPORTER" --gate "$gate" --details "$details" --workflow "$WF" --severity error + fi + } + + report_gate "Scripts Governance" \ + "${{ needs.scripts_governance.result }}" \ + "Scripts directory policy violations detected. Review required and allowed directories." + + report_gate "Repository Health" \ + "${{ needs.repo_health.result }}" \ + "Repository health checks failed — missing required artifacts, disallowed files, or content warnings. Check the CI run summary." diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c8f0ad..790b901 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,8 @@ Copyright (C) 2026 Moko Consulting SPDX-License-Identifier: GPL-3.0-or-later FILE INFORMATION -DEFGROUP: MokoStandards.Root -INGROUP: MokoStandards +DEFGROUP: MokoCli.Root +INGROUP: MokoCli REPO: https://git.mokoconsulting.tech/MokoConsulting/mokoplatform PATH: /CHANGELOG.md BRIEF: Release changelog @@ -12,6 +12,24 @@ BRIEF: Release changelog # Changelog ## [Unreleased] +### Added +- `security:advisories` command — cross-repo security advisory aggregator (#150) + - Scans org repos for known CVEs via `composer audit` + - Aggregates results into a single report with severity breakdown + - Auto-creates tracking issues for critical/high vulnerabilities (`--create-issues`) + - Checkpoint-based resumability with `--resume` + - Export to JSON/CSV with `--export` + +### Changed +- `manifest:read` rewritten to use Gitea manifest API as primary source (#283) + - Falls back to auto-detection from source tree (Joomla, Dolibarr, generic) + - No longer requires `.mokogitea/manifest.xml` file + - Backward-compatible field aliases for existing CI consumers +- Renamed `MokoStandards` namespace → `MokoCli` across all files +- Renamed `MokoEnterprise` namespace → `MokoCli` across all files +- Renamed `MokoStandardsParser` class → `ManifestParser` +- Fixed `composer.json` autoload paths: `src/` → `source/` + ## [09.29.00] --- 2026-06-09 ## [09.28.00] --- 2026-06-07 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bf60cc5..c0b4858 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,161 +1,161 @@ -# Contributing to Moko Consulting Projects - -Thank you for your interest in contributing. All Moko Consulting repositories follow this universal workflow and version policy. - -## Branching Workflow - -``` -feature/* ──PR──> dev ──draft PR──> (renamed to rc) ──merge──> main -``` - -### Step by step - -1. **Create a feature branch** from `dev`: - ```bash - git checkout dev && git pull - git checkout -b feature/my-change - ``` - -2. **Work and commit** on your feature branch. Push to origin. - -3. **Open a PR**: `feature/my-change` → `dev`. After review and checks, merge it. - -4. **When ready for release**, open a **draft PR**: `dev` → `main`. - - This automatically renames the source branch to `rc` (release candidate) - - An RC pre-release is built and uploaded - -5. **Alpha and beta branches** are created by manually renaming the branch before the RC stage: - - Rename `dev` to `alpha` for early testing → alpha pre-release is built - - Rename `alpha` to `beta` for feature-complete testing → beta pre-release is built - - When the draft PR is created, the branch is renamed to `rc` - -6. **Once PR checks pass** on the `rc` branch, mark the PR as ready and merge to `main`. - -7. **Merging to main** triggers the stable release pipeline: - - Minor version bump (e.g., `02.09.xx` → `02.10.00`) - - Stability suffix stripped (clean version) - - Gitea release created with ZIP/tar.gz packages - - `updates.xml` updated (Joomla extensions) - - `dev` branch recreated from `main` - -### Branch summary - -| Branch | Purpose | Created by | -|--------|---------|-----------| -| `feature/*` | New features and fixes | Developer | -| `dev` | Integration branch | Auto-recreated after release | -| `alpha` | Alpha pre-release testing | Manual rename from `dev` | -| `beta` | Beta pre-release testing | Manual rename from `alpha` | -| `rc` | Release candidate | Auto-renamed on draft PR to main | -| `main` | Stable releases | Protected, merge only | -| `version/XX.YY.ZZ` | Archived release snapshots | Auto-created by CI | - -### Protected branches - -| Branch | Direct push | Merge via | -|--------|------------|-----------| -| `main` | Blocked (CI bot whitelisted) | PR merge only | -| `dev` | Blocked (CI bot whitelisted) | PR merge from feature/* | -| `rc` | Blocked (CI bot whitelisted) | Auto-created on draft PR | -| `alpha` | Blocked (CI bot whitelisted) | Manual rename | -| `beta` | Blocked (CI bot whitelisted) | Manual rename | -| `feature/*` | Open | N/A (source branch) | - -## Version Policy - -### Format - -All versions use `XX.YY.ZZ` — three two-digit segments, zero-padded: - -- **XX** — Major version (breaking changes) -- **YY** — Minor version (new features, bumped on release to main) -- **ZZ** — Patch version (auto-incremented on every push to dev/feature branches) - -Rollover: patch `99` → `00` increments minor; minor `99` → `00` increments major. - -### Stability suffixes - -Each branch appends a suffix to indicate stability: - -| Branch | Suffix | Example | -|--------|--------|---------| -| `main` | (none) | `02.09.00` | -| `dev` | `-dev` | `02.09.01-dev` | -| `feature/*` | `-dev` | `02.09.01-dev` | -| `alpha` | `-alpha` | `02.09.01-alpha` | -| `beta` | `-beta` | `02.09.01-beta` | -| `rc` | `-rc` | `02.09.01-rc` | - -### Auto version bump - -On every push to `dev`, `feature/*`, or `patch/*`: - -1. Patch version incremented -2. Stability suffix `-dev` applied -3. All version-bearing files updated (manifests, CHANGELOG, PHP headers, etc.) -4. Commit created with `[skip ci]` to avoid loops - -### Release version flow - -Version bumps happen at specific release events: - -| Event | Bump | Example | -|-------|------|---------| -| Feature merged to dev | Patch bump after dev release | `02.09.01-dev` → release → `02.09.02-dev` | -| Dev promoted to RC | Minor bump | `02.09.02-dev` → `02.10.00-rc` | -| RC merged to main | Minor bump | `02.10.00-rc` → `02.11.00` (stable) | -| Dev recreated from main | Patch bump | `02.11.00` → `02.11.01-dev` | - -### Release stream copies - -When a higher-stability release is published, copies are created for all lesser streams with the same base version: - -- **RC `02.10.00-rc`** also creates: `02.10.00-dev`, `02.10.00-alpha`, `02.10.00-beta` -- **Stable `02.11.00`** also creates: `02.11.00-dev`, `02.11.00-alpha`, `02.11.00-beta`, `02.11.00-rc` - -This ensures Joomla sites on ANY stability channel see the update (Joomla only shows versions higher than what's installed). - -### Version files - -The version tools update all files containing version stamps: - -- `.mokogitea/manifest.xml` (canonical source) -- Joomla XML manifests (`` tag) -- `README.md`, `CHANGELOG.md` (`VERSION:` pattern) -- `package.json`, `pyproject.toml` -- Any text file with a `VERSION: XX.YY.ZZ` label - -Files synced from other repos (with a `# REPO:` header) are not touched. - -## Code Standards - -- **PHP**: PSR-12, tabs for indentation -- **Copyright**: all files must include the Moko Consulting copyright header -- **License**: SPDX identifier `GPL-3.0-or-later` (or as specified per repo) -- **Attribution**: use `Authored-by: Moko Consulting` in commits, not individual names - -## Commit Messages - -Use conventional commit format: - -``` -type(scope): short description - -Optional body with context. - -Authored-by: Moko Consulting -``` - -Types: `feat`, `fix`, `chore`, `docs`, `style`, `refactor`, `test`, `ci` - -Special flags in commit messages: -- `[skip ci]` — skip all CI workflows -- `[skip bump]` — skip auto version bump only - -## Reporting Issues - -Use the repository's issue tracker with the appropriate template. - ---- - -*Moko Consulting * +# Contributing to Moko Consulting Projects + +Thank you for your interest in contributing. All Moko Consulting repositories follow this universal workflow and version policy. + +## Branching Workflow + +``` +feature/* ──PR──> dev ──draft PR──> (renamed to rc) ──merge──> main +``` + +### Step by step + +1. **Create a feature branch** from `dev`: + ```bash + git checkout dev && git pull + git checkout -b feature/my-change + ``` + +2. **Work and commit** on your feature branch. Push to origin. + +3. **Open a PR**: `feature/my-change` → `dev`. After review and checks, merge it. + +4. **When ready for release**, open a **draft PR**: `dev` → `main`. + - This automatically renames the source branch to `rc` (release candidate) + - An RC pre-release is built and uploaded + +5. **Alpha and beta branches** are created by manually renaming the branch before the RC stage: + - Rename `dev` to `alpha` for early testing → alpha pre-release is built + - Rename `alpha` to `beta` for feature-complete testing → beta pre-release is built + - When the draft PR is created, the branch is renamed to `rc` + +6. **Once PR checks pass** on the `rc` branch, mark the PR as ready and merge to `main`. + +7. **Merging to main** triggers the stable release pipeline: + - Minor version bump (e.g., `02.09.xx` → `02.10.00`) + - Stability suffix stripped (clean version) + - Gitea release created with ZIP/tar.gz packages + - `updates.xml` updated (Joomla extensions) + - `dev` branch recreated from `main` + +### Branch summary + +| Branch | Purpose | Created by | +|--------|---------|-----------| +| `feature/*` | New features and fixes | Developer | +| `dev` | Integration branch | Auto-recreated after release | +| `alpha` | Alpha pre-release testing | Manual rename from `dev` | +| `beta` | Beta pre-release testing | Manual rename from `alpha` | +| `rc` | Release candidate | Auto-renamed on draft PR to main | +| `main` | Stable releases | Protected, merge only | +| `version/XX.YY.ZZ` | Archived release snapshots | Auto-created by CI | + +### Protected branches + +| Branch | Direct push | Merge via | +|--------|------------|-----------| +| `main` | Blocked (CI bot whitelisted) | PR merge only | +| `dev` | Blocked (CI bot whitelisted) | PR merge from feature/* | +| `rc` | Blocked (CI bot whitelisted) | Auto-created on draft PR | +| `alpha` | Blocked (CI bot whitelisted) | Manual rename | +| `beta` | Blocked (CI bot whitelisted) | Manual rename | +| `feature/*` | Open | N/A (source branch) | + +## Version Policy + +### Format + +All versions use `XX.YY.ZZ` — three two-digit segments, zero-padded: + +- **XX** — Major version (breaking changes) +- **YY** — Minor version (new features, bumped on release to main) +- **ZZ** — Patch version (auto-incremented on every push to dev/feature branches) + +Rollover: patch `99` → `00` increments minor; minor `99` → `00` increments major. + +### Stability suffixes + +Each branch appends a suffix to indicate stability: + +| Branch | Suffix | Example | +|--------|--------|---------| +| `main` | (none) | `02.09.00` | +| `dev` | `-dev` | `02.09.01-dev` | +| `feature/*` | `-dev` | `02.09.01-dev` | +| `alpha` | `-alpha` | `02.09.01-alpha` | +| `beta` | `-beta` | `02.09.01-beta` | +| `rc` | `-rc` | `02.09.01-rc` | + +### Auto version bump + +On every push to `dev`, `feature/*`, or `patch/*`: + +1. Patch version incremented +2. Stability suffix `-dev` applied +3. All version-bearing files updated (manifests, CHANGELOG, PHP headers, etc.) +4. Commit created with `[skip ci]` to avoid loops + +### Release version flow + +Version bumps happen at specific release events: + +| Event | Bump | Example | +|-------|------|---------| +| Feature merged to dev | Patch bump after dev release | `02.09.01-dev` → release → `02.09.02-dev` | +| Dev promoted to RC | Minor bump | `02.09.02-dev` → `02.10.00-rc` | +| RC merged to main | Minor bump | `02.10.00-rc` → `02.11.00` (stable) | +| Dev recreated from main | Patch bump | `02.11.00` → `02.11.01-dev` | + +### Release stream copies + +When a higher-stability release is published, copies are created for all lesser streams with the same base version: + +- **RC `02.10.00-rc`** also creates: `02.10.00-dev`, `02.10.00-alpha`, `02.10.00-beta` +- **Stable `02.11.00`** also creates: `02.11.00-dev`, `02.11.00-alpha`, `02.11.00-beta`, `02.11.00-rc` + +This ensures Joomla sites on ANY stability channel see the update (Joomla only shows versions higher than what's installed). + +### Version files + +The version tools update all files containing version stamps: + +- `.mokogitea/manifest.xml` (canonical source) +- Joomla XML manifests (`` tag) +- `README.md`, `CHANGELOG.md` (`VERSION:` pattern) +- `package.json`, `pyproject.toml` +- Any text file with a `VERSION: XX.YY.ZZ` label + +Files synced from other repos (with a `# REPO:` header) are not touched. + +## Code Standards + +- **PHP**: PSR-12, tabs for indentation +- **Copyright**: all files must include the Moko Consulting copyright header +- **License**: SPDX identifier `GPL-3.0-or-later` (or as specified per repo) +- **Attribution**: use `Authored-by: Moko Consulting` in commits, not individual names + +## Commit Messages + +Use conventional commit format: + +``` +type(scope): short description + +Optional body with context. + +Authored-by: Moko Consulting +``` + +Types: `feat`, `fix`, `chore`, `docs`, `style`, `refactor`, `test`, `ci` + +Special flags in commit messages: +- `[skip ci]` — skip all CI workflows +- `[skip bump]` — skip auto version bump only + +## Reporting Issues + +Use the repository's issue tracker with the appropriate template. + +--- + +*Moko Consulting * diff --git a/README.md b/README.md index 4626eb2..6872f85 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ DEFGROUP: MokoPlatform.Root INGROUP: MokoPlatform REPO: https://git.mokoconsulting.tech/MokoConsulting/mokoplatform PATH: /README.md -VERSION: 09.29.01 +VERSION: 09.29.02 BRIEF: Project overview and documentation --> @@ -16,8 +16,8 @@ BRIEF: Project overview and documentation PHP implementation of mokoplatform — enterprise standards, automation framework, workflow templates, and bulk sync tooling. -> **Primary platform**: [Gitea — git.mokoconsulting.tech](https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API) -> **Backup mirror**: [GitHub](https://github.com/MokoConsulting/MokoStandards-API) *(read-only mirror)* +> **Primary platform**: [Gitea — git.mokoconsulting.tech](https://git.mokoconsulting.tech/MokoConsulting/MokoCli-API) +> **Backup mirror**: [GitHub](https://github.com/MokoConsulting/MokoCli-API) *(read-only mirror)* ## What Lives Here diff --git a/automation/bulk_joomla_template.php b/automation/bulk_joomla_template.php index 17fc272..734fa64 100644 --- a/automation/bulk_joomla_template.php +++ b/automation/bulk_joomla_template.php @@ -28,7 +28,7 @@ declare(strict_types=1); require_once __DIR__ . '/../vendor/autoload.php'; require_once __DIR__ . '/../lib/Enterprise/CliFramework.php'; -use MokoEnterprise\{ +use MokoCli\{ AuditLogger, CliFramework, Config, diff --git a/automation/bulk_sync.php b/automation/bulk_sync.php index dc026b1..4e9a396 100755 --- a/automation/bulk_sync.php +++ b/automation/bulk_sync.php @@ -21,7 +21,7 @@ declare(strict_types=1); require_once __DIR__ . '/../vendor/autoload.php'; require_once __DIR__ . '/../lib/Enterprise/CliFramework.php'; -use MokoEnterprise\{ +use MokoCli\{ ApiClient, AuditLogger, CheckpointManager, diff --git a/automation/enrich_manifest_xml.php b/automation/enrich_manifest_xml.php index 2c9d160..3509e0b 100644 --- a/automation/enrich_manifest_xml.php +++ b/automation/enrich_manifest_xml.php @@ -21,8 +21,8 @@ declare(strict_types=1); require_once __DIR__ . '/../vendor/autoload.php'; require_once __DIR__ . '/../lib/Enterprise/CliFramework.php'; -use MokoEnterprise\CliFramework; -use MokoEnterprise\MokoStandardsParser; +use MokoCli\CliFramework; +use MokoCli\ManifestParser; class EnrichManifestXmlCli extends CliFramework { @@ -43,7 +43,7 @@ class EnrichManifestXmlCli extends CliFramework $skipStr = $this->getArgument('--skip'); $skipRepos = $skipStr !== '' ? array_map('trim', explode(',', $skipStr)) : []; - $parser = new MokoStandardsParser(); + $parser = new ManifestParser(); $tmpBase = sys_get_temp_dir() . '/moko-enrich-' . getmypid(); echo "=== mokoplatform XML Manifest Enrichment ===\n"; @@ -113,8 +113,8 @@ class EnrichManifestXmlCli extends CliFramework } $enrichment['build']['language'] = $enrichment['build']['language'] ?? $repo['language'] - ?? MokoStandardsParser::platformLanguage($platform); - $enrichment['build']['package_type'] = $enrichment['build']['package_type'] ?? MokoStandardsParser::platformPackageType($platform); + ?? ManifestParser::platformLanguage($platform); + $enrichment['build']['package_type'] = $enrichment['build']['package_type'] ?? ManifestParser::platformPackageType($platform); $enrichedXml = $this->enrichManifestXml($existingXml, $enrichment); $dc = count($enrichment['deploy'] ?? []); @@ -312,7 +312,7 @@ class EnrichManifestXmlCli extends CliFramework return $xml; } - $ns = MokoStandardsParser::NAMESPACE_URI; + $ns = ManifestParser::NAMESPACE_URI; $root = $dom->documentElement; foreach (['build', 'deploy', 'scripts'] as $tag) { diff --git a/automation/enrich_mokostandards_xml.php b/automation/enrich_mokostandards_xml.php index 7baa3f2..99f22bf 100644 --- a/automation/enrich_mokostandards_xml.php +++ b/automation/enrich_mokostandards_xml.php @@ -21,8 +21,8 @@ declare(strict_types=1); require_once __DIR__ . '/../vendor/autoload.php'; require_once __DIR__ . '/../lib/Enterprise/CliFramework.php'; -use MokoEnterprise\CliFramework; -use MokoEnterprise\MokoStandardsParser; +use MokoCli\CliFramework; +use MokoCli\ManifestParser; class EnrichMokostandardsXmlCli extends CliFramework { @@ -43,7 +43,7 @@ class EnrichMokostandardsXmlCli extends CliFramework $skipStr = $this->getArgument('--skip'); $skipRepos = $skipStr !== '' ? array_map('trim', explode(',', $skipStr)) : []; - $parser = new MokoStandardsParser(); + $parser = new ManifestParser(); $tmpBase = sys_get_temp_dir() . '/moko-enrich-' . getmypid(); echo "=== mokoplatform XML Manifest Enrichment ===\n"; @@ -113,8 +113,8 @@ class EnrichMokostandardsXmlCli extends CliFramework } $enrichment['build']['language'] = $enrichment['build']['language'] ?? $repo['language'] - ?? MokoStandardsParser::platformLanguage($platform); - $enrichment['build']['package_type'] = $enrichment['build']['package_type'] ?? MokoStandardsParser::platformPackageType($platform); + ?? ManifestParser::platformLanguage($platform); + $enrichment['build']['package_type'] = $enrichment['build']['package_type'] ?? ManifestParser::platformPackageType($platform); $enrichedXml = $this->enrichManifestXml($existingXml, $enrichment); $dc = count($enrichment['deploy'] ?? []); @@ -315,7 +315,7 @@ class EnrichMokostandardsXmlCli extends CliFramework return $xml; } - $ns = MokoStandardsParser::NAMESPACE_URI; + $ns = ManifestParser::NAMESPACE_URI; $root = $dom->documentElement; foreach (['build', 'deploy', 'scripts'] as $tag) { diff --git a/automation/migrate_to_gitea.php b/automation/migrate_to_gitea.php index 7b0d8af..686e3d6 100644 --- a/automation/migrate_to_gitea.php +++ b/automation/migrate_to_gitea.php @@ -25,12 +25,12 @@ declare(strict_types=1); require_once __DIR__ . '/../vendor/autoload.php'; -use MokoEnterprise\CheckpointManager; -use MokoEnterprise\CliFramework; -use MokoEnterprise\Config; -use MokoEnterprise\PlatformAdapterFactory; -use MokoEnterprise\GitHubAdapter; -use MokoEnterprise\MokoGiteaAdapter; +use MokoCli\CheckpointManager; +use MokoCli\CliFramework; +use MokoCli\Config; +use MokoCli\PlatformAdapterFactory; +use MokoCli\GitHubAdapter; +use MokoCli\MokoGiteaAdapter; /** * Gitea Migration Script diff --git a/automation/push_files.php b/automation/push_files.php index cac9645..c6d5b55 100644 --- a/automation/push_files.php +++ b/automation/push_files.php @@ -21,7 +21,7 @@ declare(strict_types=1); require_once __DIR__ . '/../vendor/autoload.php'; require_once __DIR__ . '/../lib/Enterprise/CliFramework.php'; -use MokoEnterprise\{ +use MokoCli\{ ApiClient, AuditLogger, CliFramework, diff --git a/automation/push_manifest_xml.php b/automation/push_manifest_xml.php index 62fc581..aa77bbd 100644 --- a/automation/push_manifest_xml.php +++ b/automation/push_manifest_xml.php @@ -18,8 +18,8 @@ declare(strict_types=1); require_once __DIR__ . '/../vendor/autoload.php'; require_once __DIR__ . '/../lib/Enterprise/CliFramework.php'; -use MokoEnterprise\CliFramework; -use MokoEnterprise\MokoStandardsParser; +use MokoCli\CliFramework; +use MokoCli\ManifestParser; class PushManifestXmlCli extends CliFramework { @@ -44,7 +44,7 @@ class PushManifestXmlCli extends CliFramework $skipStr = $this->getArgument('--skip'); $skipRepos = $skipStr !== '' ? array_map('trim', explode(',', $skipStr)) : []; - $parser = new MokoStandardsParser(); + $parser = new ManifestParser(); $tmpBase = sys_get_temp_dir() . '/moko-manifest-push-' . getmypid(); echo "=== mokoplatform XML Manifest Push ===\n"; @@ -97,8 +97,8 @@ class PushManifestXmlCli extends CliFramework 'description' => $repo['description'] ?? '', 'license' => 'GPL-3.0-or-later', 'topics' => $repo['topics'] ?? [], - 'language' => $repo['language'] ?? MokoStandardsParser::platformLanguage($platform), - 'package_type' => MokoStandardsParser::platformPackageType($platform), + 'language' => $repo['language'] ?? ManifestParser::platformLanguage($platform), + 'package_type' => ManifestParser::platformPackageType($platform), 'last_synced' => date('c'), ]); diff --git a/automation/push_mokostandards_xml.php b/automation/push_mokostandards_xml.php index 2a96517..4e7877c 100644 --- a/automation/push_mokostandards_xml.php +++ b/automation/push_mokostandards_xml.php @@ -18,8 +18,8 @@ declare(strict_types=1); require_once __DIR__ . '/../vendor/autoload.php'; require_once __DIR__ . '/../lib/Enterprise/CliFramework.php'; -use MokoEnterprise\CliFramework; -use MokoEnterprise\MokoStandardsParser; +use MokoCli\CliFramework; +use MokoCli\ManifestParser; class PushMokostandardsXmlCli extends CliFramework { @@ -44,7 +44,7 @@ class PushMokostandardsXmlCli extends CliFramework $skipStr = $this->getArgument('--skip'); $skipRepos = $skipStr !== '' ? array_map('trim', explode(',', $skipStr)) : []; - $parser = new MokoStandardsParser(); + $parser = new ManifestParser(); $tmpBase = sys_get_temp_dir() . '/moko-manifest-push-' . getmypid(); echo "=== mokoplatform XML Manifest Push ===\n"; @@ -97,8 +97,8 @@ class PushMokostandardsXmlCli extends CliFramework 'description' => $repo['description'] ?? '', 'license' => 'GPL-3.0-or-later', 'topics' => $repo['topics'] ?? [], - 'language' => $repo['language'] ?? MokoStandardsParser::platformLanguage($platform), - 'package_type' => MokoStandardsParser::platformPackageType($platform), + 'language' => $repo['language'] ?? ManifestParser::platformLanguage($platform), + 'package_type' => ManifestParser::platformPackageType($platform), 'last_synced' => date('c'), ]); diff --git a/automation/repo_cleanup.php b/automation/repo_cleanup.php index 8a8a75b..f852231 100644 --- a/automation/repo_cleanup.php +++ b/automation/repo_cleanup.php @@ -21,7 +21,7 @@ declare(strict_types=1); require_once __DIR__ . '/../vendor/autoload.php'; require_once __DIR__ . '/../lib/Enterprise/CliFramework.php'; -use MokoEnterprise\{ApiClient, AuditLogger, CliFramework, Config, GitPlatformAdapter, MetricsCollector, PlatformAdapterFactory}; +use MokoCli\{ApiClient, AuditLogger, CliFramework, Config, GitPlatformAdapter, MetricsCollector, PlatformAdapterFactory}; /** * Enterprise Repository Cleanup diff --git a/bin/moko b/bin/moko index b28c3b2..db6a660 100644 --- a/bin/moko +++ b/bin/moko @@ -9,11 +9,11 @@ * SPDX-License-Identifier: GPL-3.0-or-later * * FILE INFORMATION - * DEFGROUP: MokoStandards.CLI - * INGROUP: MokoStandards + * DEFGROUP: MokoCli.CLI + * INGROUP: MokoCli * REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform * PATH: /bin/moko - * BRIEF: Unified CLI dispatcher — run any MokoStandards script without needing GitHub Actions + * BRIEF: Unified CLI dispatcher — run any MokoCli script without needing GitHub Actions * * USAGE * php bin/moko [options] (all platforms) @@ -220,6 +220,9 @@ const COMMAND_MAP = [ // Licensing 'license' => 'cli/license_manage.php', + // Security + 'security:advisories' => 'security/advisory_scan.php', + // Shell completion 'completion' => 'cli/completion.php', @@ -292,10 +295,10 @@ function printHelp(): void { echo <<<'HELP' ╔══════════════════════════════════════════════════════════╗ -║ MokoStandards CLI (bin/moko) ║ +║ MokoCli CLI (bin/moko) ║ ╚══════════════════════════════════════════════════════════╝ -Run any MokoStandards script locally without GitHub Actions. +Run any MokoCli script locally without GitHub Actions. USAGE php bin/moko [options] (all platforms) @@ -397,7 +400,7 @@ function loadPluginCommands(): array $commands = []; foreach (glob("{$pluginDir}/*Plugin.php") as $file) { - $className = 'MokoEnterprise\\Plugins\\' + $className = 'MokoCli\\Plugins\\' . pathinfo($file, PATHINFO_FILENAME); if (!class_exists($className)) { diff --git a/cli/archive_repo.php b/cli/archive_repo.php index 89c2b01..25ca9bb 100644 --- a/cli/archive_repo.php +++ b/cli/archive_repo.php @@ -20,9 +20,9 @@ declare(strict_types=1); require_once __DIR__ . '/../vendor/autoload.php'; require_once __DIR__ . '/../lib/Enterprise/CliFramework.php'; -use MokoEnterprise\CliFramework; -use MokoEnterprise\Config; -use MokoEnterprise\PlatformAdapterFactory; +use MokoCli\CliFramework; +use MokoCli\Config; +use MokoCli\PlatformAdapterFactory; class ArchiveRepoCli extends CliFramework { diff --git a/cli/audit_query.php b/cli/audit_query.php index 4b28232..24b0771 100644 --- a/cli/audit_query.php +++ b/cli/audit_query.php @@ -25,7 +25,7 @@ declare(strict_types=1); require_once __DIR__ . '/../lib/Enterprise/CliFramework.php'; -use MokoEnterprise\CliFramework; +use MokoCli\CliFramework; /** * CLI tool to search, filter, and export audit logs. diff --git a/cli/badge_update.php b/cli/badge_update.php index aa4658b..be63432 100644 --- a/cli/badge_update.php +++ b/cli/badge_update.php @@ -17,7 +17,7 @@ declare(strict_types=1); require_once __DIR__ . '/../lib/Enterprise/CliFramework.php'; -use MokoEnterprise\CliFramework; +use MokoCli\CliFramework; class BadgeUpdateCli extends CliFramework { diff --git a/cli/branch_rename.php b/cli/branch_rename.php index 48780be..6008c55 100644 --- a/cli/branch_rename.php +++ b/cli/branch_rename.php @@ -10,7 +10,7 @@ * INGROUP: mokoplatform * REPO: https://git.mokoconsulting.tech/MokoConsulting/mokoplatform * PATH: /cli/branch_rename.php - * VERSION: 09.29.01 + * VERSION: 09.29.02 * BRIEF: Rename a git branch via Gitea API (create new, update PR, delete old) */ @@ -18,7 +18,7 @@ declare(strict_types=1); require_once __DIR__ . '/../lib/Enterprise/CliFramework.php'; -use MokoEnterprise\CliFramework; +use MokoCli\CliFramework; class BranchRenameCli extends CliFramework { diff --git a/cli/bulk_workflow_push.php b/cli/bulk_workflow_push.php index a04c2f3..63aa010 100644 --- a/cli/bulk_workflow_push.php +++ b/cli/bulk_workflow_push.php @@ -1,407 +1,309 @@ -#!/usr/bin/env php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: mokocli.CLI - * INGROUP: mokocli - * REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli - * PATH: /cli/bulk_workflow_push.php - * VERSION: 09.29.01 - * BRIEF: Push a workflow file to all governed repos via the Gitea Contents API - */ - -declare(strict_types=1); - -require_once __DIR__ . '/../lib/Enterprise/CliFramework.php'; - -use MokoEnterprise\CliFramework; - -class BulkWorkflowPushCli extends CliFramework -{ - private int $updated = 0; - private int $created = 0; - private int $skipped = 0; - private int $errors = 0; - - protected function configure(): void - { - $this->setDescription('Push a workflow file to all governed repos via the Gitea Contents API'); - $this->addArgument('--gitea-url', 'Gitea URL (default: https://git.mokoconsulting.tech)', 'https://git.mokoconsulting.tech'); - $this->addArgument('--token', 'Gitea API token', ''); - $this->addArgument('--org', 'Target organization', ''); - $this->addArgument('--file', 'Local workflow file to push', ''); - $this->addArgument('--dest', 'Destination path in repos (default: .mokogitea/workflows/)', ''); - $this->addArgument('--branch', 'Target branch (default: main)', 'main'); - } - - protected function run(): int - { - $giteaUrl = rtrim($this->getArgument('--gitea-url'), '/'); - $token = $this->getArgument('--token'); - $org = $this->getArgument('--org'); - $workflowFile = $this->getArgument('--file'); - $destPath = $this->getArgument('--dest'); - $branch = $this->getArgument('--branch'); - - if ($token === '') { - $this->log('ERROR', '--token is required.'); - return 1; - } - - if ($workflowFile === '') { - $this->log('ERROR', '--file is required.'); - return 1; - } - - if (!file_exists($workflowFile)) { - $this->log('ERROR', "File not found: {$workflowFile}"); - return 1; - } - - if ($org === '') { - $this->log('ERROR', '--org is required.'); - return 1; - } - - if ($destPath === '') { - $destPath = '.mokogitea/workflows/' . basename($workflowFile); - } - - $localContent = file_get_contents($workflowFile); - - if ($localContent === false) { - $this->log('ERROR', "Could not read file: {$workflowFile}"); - return 1; - } - - $this->log('INFO', "Pushing: {$workflowFile}"); - $this->log('INFO', " -> {$destPath} (branch: {$branch})"); - $this->log('INFO', " -> Org: {$org} @ {$giteaUrl}"); - - if ($this->dryRun) { - $this->log('INFO', '[DRY RUN] No changes will be made.'); - } - - echo "\n"; - - $repos = $this->fetchOrgRepos($giteaUrl, $token, $org); - - if ($repos === null) { - return 1; - } - - $this->log('INFO', "Found " . count($repos) . " repo(s) in \"{$org}\"."); - echo "\n"; - fprintf(STDERR, "%-45s | %s\n", 'Repo', 'Status'); - fprintf(STDERR, "%s\n", str_repeat('-', 70)); - - $encodedContent = base64_encode($localContent); - - foreach ($repos as $repo) { - $this->pushToRepo($giteaUrl, $token, $repo, $encodedContent, $localContent, $destPath, $branch); - } - - echo "\n"; - $this->log('INFO', "Done: {$this->created} created, {$this->updated} updated, " - . "{$this->skipped} skipped, {$this->errors} error(s)."); - - return $this->errors > 0 ? 1 : 0; - } - - private function pushToRepo( - string $giteaUrl, - string $token, - string $repoFullName, - string $encodedContent, - string $localContent, - string $destPath, - string $branch - ): void { - [$owner, $repoName] = explode('/', $repoFullName, 2); - - $existing = $this->apiRequest( - $giteaUrl, - $token, - 'GET', - "/api/v1/repos/{$owner}/{$repoName}/contents/" - . "{$destPath}?ref={$branch}" - ); - - if ($existing['code'] === 200) { - $data = json_decode($existing['body'], true); - $remoteSha = $data['sha'] ?? ''; - $remoteContent = base64_decode($data['content'] ?? ''); - - if ($remoteContent === $localContent) { - fprintf(STDERR, "%-45s | %s\n", $repoFullName, 'IDENTICAL (skipped)'); - $this->skipped++; - return; - } - - if ($this->dryRun) { - fprintf(STDERR, "%-45s | %s\n", $repoFullName, 'WOULD UPDATE'); - $this->updated++; - return; - } - - $payload = json_encode([ - 'content' => $encodedContent, - 'sha' => $remoteSha, - 'message' => "chore: sync {$destPath} " - . "from mokocli [skip ci]", - 'branch' => $branch, - ]); - - $response = $this->apiRequest( - $giteaUrl, - $token, - 'PUT', - "/api/v1/repos/{$owner}/{$repoName}/contents/" - . $destPath, - $payload - ); - - if ($response['code'] === 200) { - fprintf(STDERR, "%-45s | %s\n", $repoFullName, 'UPDATED'); - $this->updated++; - } elseif ($response['code'] === 403) { - // Branch protection — fall back to chore branch + PR - $this->pushViaPR($giteaUrl, $token, $owner, $repoName, $encodedContent, $remoteSha, $destPath, $branch); - } else { - fprintf(STDERR, "%-45s | %s\n", $repoFullName, "ERROR (HTTP {$response['code']})"); - $this->errors++; - } - } elseif ($existing['code'] === 404) { - if ($this->dryRun) { - fprintf(STDERR, "%-45s | %s\n", $repoFullName, 'WOULD CREATE'); - $this->created++; - return; - } - - $payload = json_encode([ - 'content' => $encodedContent, - 'message' => "chore: add {$destPath} " - . "from mokocli [skip ci]", - 'branch' => $branch, - ]); - - $response = $this->apiRequest( - $giteaUrl, - $token, - 'POST', - "/api/v1/repos/{$owner}/{$repoName}/contents/" - . $destPath, - $payload - ); - - if ($response['code'] === 201) { - fprintf(STDERR, "%-45s | %s\n", $repoFullName, 'CREATED'); - $this->created++; - } elseif ($response['code'] === 403) { - $this->pushViaPR($giteaUrl, $token, $owner, $repoName, $encodedContent, '', $destPath, $branch); - } else { - fprintf(STDERR, "%-45s | %s\n", $repoFullName, "ERROR (HTTP {$response['code']})"); - $this->errors++; - } - } else { - fprintf(STDERR, "%-45s | %s\n", $repoFullName, "ERROR (HTTP {$existing['code']})"); - $this->errors++; - } - } - - /** - * Fallback: push via chore branch + PR when direct push is blocked (403). - */ - private function pushViaPR( - string $giteaUrl, - string $token, - string $owner, - string $repoName, - string $encodedContent, - string $remoteSha, - string $destPath, - string $targetBranch - ): void { - $repoFullName = "{$owner}/{$repoName}"; - $choreBranch = 'chore/workflow-sync'; - $commitMsg = "chore: sync {$destPath} from mokocli [skip ci]"; - $apiBase = "/api/v1/repos/{$owner}/{$repoName}"; - - // 1. Create chore branch from target - $branchPayload = json_encode([ - 'new_branch_name' => $choreBranch, - 'old_branch_name' => $targetBranch, - ]); - $branchResp = $this->apiRequest($giteaUrl, $token, 'POST', "{$apiBase}/branches", $branchPayload); - if ($branchResp['code'] !== 201 && $branchResp['code'] !== 409) { - fprintf(STDERR, "%-45s | %s\n", $repoFullName, "ERROR (branch create HTTP {$branchResp['code']})"); - $this->errors++; - return; - } - - // If branch already exists (409), get the current SHA of the file on that branch - if ($branchResp['code'] === 409 || $remoteSha === '') { - $existing = $this->apiRequest($giteaUrl, $token, 'GET', - "{$apiBase}/contents/{$destPath}?ref={$choreBranch}"); - if ($existing['code'] === 200) { - $data = json_decode($existing['body'], true); - $remoteSha = $data['sha'] ?? ''; - } - } - - // 2. Push file to chore branch - $filePayload = ['content' => $encodedContent, 'message' => $commitMsg, 'branch' => $choreBranch]; - if ($remoteSha !== '') { - $filePayload['sha'] = $remoteSha; - $method = 'PUT'; - } else { - $method = 'POST'; - } - $fileResp = $this->apiRequest($giteaUrl, $token, $method, - "{$apiBase}/contents/{$destPath}", json_encode($filePayload)); - if ($fileResp['code'] !== 200 && $fileResp['code'] !== 201) { - // 422 = file unchanged, still create PR if branch is new - if ($fileResp['code'] !== 422) { - fprintf(STDERR, "%-45s | %s\n", $repoFullName, "ERROR (file push HTTP {$fileResp['code']})"); - $this->errors++; - return; - } - } - - // 3. Create PR - $prPayload = json_encode([ - 'title' => "chore: sync workflows from mokocli", - 'body' => "Automated workflow sync via bulk_workflow_push.", - 'head' => $choreBranch, - 'base' => $targetBranch, - ]); - $prResp = $this->apiRequest($giteaUrl, $token, 'POST', "{$apiBase}/pulls", $prPayload); - - if ($prResp['code'] === 201) { - $prData = json_decode($prResp['body'], true); - $prNumber = $prData['number'] ?? '?'; - - // 4. Auto-merge the PR - $mergePayload = json_encode(['Do' => 'merge', 'merge_message_field' => $commitMsg]); - $mergeResp = $this->apiRequest($giteaUrl, $token, 'POST', - "{$apiBase}/pulls/{$prNumber}/merge", $mergePayload); - - if ($mergeResp['code'] === 200 || $mergeResp['code'] === 204) { - fprintf(STDERR, "%-45s | %s\n", $repoFullName, "UPDATED (via PR #{$prNumber}, merged)"); - $this->updated++; - } else { - fprintf(STDERR, "%-45s | %s\n", $repoFullName, "PR #{$prNumber} created (merge HTTP {$mergeResp['code']})"); - $this->updated++; - } - } elseif ($prResp['code'] === 409 || $prResp['code'] === 422) { - fprintf(STDERR, "%-45s | %s\n", $repoFullName, 'PR already exists'); - $this->skipped++; - } else { - fprintf(STDERR, "%-45s | %s\n", $repoFullName, "ERROR (PR create HTTP {$prResp['code']})"); - $this->errors++; - } - } - - private function fetchOrgRepos(string $giteaUrl, string $token, string $org): ?array - { - $this->log('INFO', "Fetching repos from org: {$org}"); - - $page = 1; - $repos = []; - - while (true) { - $response = $this->apiRequest( - $giteaUrl, - $token, - 'GET', - "/api/v1/orgs/{$org}/repos?" - . "limit=50&page={$page}" - ); - - if ($response['code'] < 200 || $response['code'] >= 300) { - if ($page === 1) { - $this->log('ERROR', "Could not fetch repos " - . "(HTTP {$response['code']})."); - return null; - } - - break; - } - - $data = json_decode($response['body'], true); - - if (!is_array($data) || count($data) === 0) { - break; - } - - foreach ($data as $repo) { - if (!empty($repo['archived'])) { - continue; - } - - $fullName = $repo['full_name'] ?? ''; - - if ($fullName !== '') { - $repos[] = $fullName; - } - } - - $page++; - } - - return $repos; - } - - private function apiRequest( - string $giteaUrl, - string $token, - string $method, - string $endpoint, - ?string $body = null - ): array { - $url = $giteaUrl . $endpoint; - - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $url); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); - curl_setopt($ch, CURLOPT_HTTPHEADER, [ - 'Content-Type: application/json', - 'Accept: application/json', - "Authorization: token {$token}", - ]); - - if ($body !== null) { - curl_setopt($ch, CURLOPT_POSTFIELDS, $body); - } - - $responseBody = curl_exec($ch); - $httpCode = (int) curl_getinfo( - $ch, - CURLINFO_HTTP_CODE - ); - - if (curl_errno($ch)) { - $error = curl_error($ch); - curl_close($ch); - - return [ - 'code' => 0, - 'body' => "cURL error: {$error}", - ]; - } - - curl_close($ch); - - return ['code' => $httpCode, 'body' => $responseBody]; - } -} - -$app = new BulkWorkflowPushCli(); -exit($app->execute()); +#!/usr/bin/env php + + * + * This file is part of a Moko Consulting project. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * FILE INFORMATION + * DEFGROUP: mokoplatform.CLI + * INGROUP: mokoplatform + * REPO: https://git.mokoconsulting.tech/MokoConsulting/mokoplatform + * PATH: /cli/bulk_workflow_push.php + * VERSION: 09.29.02 + * BRIEF: Push a workflow file to all governed repos via the Gitea Contents API + */ + +declare(strict_types=1); + +require_once __DIR__ . '/../lib/Enterprise/CliFramework.php'; + +use MokoCli\CliFramework; + +class BulkWorkflowPushCli extends CliFramework +{ + private int $updated = 0; + private int $created = 0; + private int $skipped = 0; + private int $errors = 0; + + protected function configure(): void + { + $this->setDescription('Push a workflow file to all governed repos via the Gitea Contents API'); + $this->addArgument('--gitea-url', 'Gitea URL (default: https://git.mokoconsulting.tech)', 'https://git.mokoconsulting.tech'); + $this->addArgument('--token', 'Gitea API token', ''); + $this->addArgument('--org', 'Target organization', ''); + $this->addArgument('--file', 'Local workflow file to push', ''); + $this->addArgument('--dest', 'Destination path in repos (default: .mokogitea/workflows/)', ''); + $this->addArgument('--branch', 'Target branch (default: main)', 'main'); + } + + protected function run(): int + { + $giteaUrl = rtrim($this->getArgument('--gitea-url'), '/'); + $token = $this->getArgument('--token'); + $org = $this->getArgument('--org'); + $workflowFile = $this->getArgument('--file'); + $destPath = $this->getArgument('--dest'); + $branch = $this->getArgument('--branch'); + + if ($token === '') { + $this->log('ERROR', '--token is required.'); + return 1; + } + + if ($workflowFile === '') { + $this->log('ERROR', '--file is required.'); + return 1; + } + + if (!file_exists($workflowFile)) { + $this->log('ERROR', "File not found: {$workflowFile}"); + return 1; + } + + if ($org === '') { + $this->log('ERROR', '--org is required.'); + return 1; + } + + if ($destPath === '') { + $destPath = '.mokogitea/workflows/' . basename($workflowFile); + } + + $localContent = file_get_contents($workflowFile); + + if ($localContent === false) { + $this->log('ERROR', "Could not read file: {$workflowFile}"); + return 1; + } + + $this->log('INFO', "Pushing: {$workflowFile}"); + $this->log('INFO', " -> {$destPath} (branch: {$branch})"); + $this->log('INFO', " -> Org: {$org} @ {$giteaUrl}"); + + if ($this->dryRun) { + $this->log('INFO', '[DRY RUN] No changes will be made.'); + } + + echo "\n"; + + $repos = $this->fetchOrgRepos($giteaUrl, $token, $org); + + if ($repos === null) { + return 1; + } + + $this->log('INFO', "Found " . count($repos) . " repo(s) in \"{$org}\"."); + echo "\n"; + fprintf(STDERR, "%-45s | %s\n", 'Repo', 'Status'); + fprintf(STDERR, "%s\n", str_repeat('-', 70)); + + $encodedContent = base64_encode($localContent); + + foreach ($repos as $repo) { + $this->pushToRepo($giteaUrl, $token, $repo, $encodedContent, $localContent, $destPath, $branch); + } + + echo "\n"; + $this->log('INFO', "Done: {$this->created} created, {$this->updated} updated, " + . "{$this->skipped} skipped, {$this->errors} error(s)."); + + return $this->errors > 0 ? 1 : 0; + } + + private function pushToRepo( + string $giteaUrl, + string $token, + string $repoFullName, + string $encodedContent, + string $localContent, + string $destPath, + string $branch + ): void { + [$owner, $repoName] = explode('/', $repoFullName, 2); + + $existing = $this->apiRequest( + $giteaUrl, + $token, + 'GET', + "/api/v1/repos/{$owner}/{$repoName}/contents/" + . "{$destPath}?ref={$branch}" + ); + + if ($existing['code'] === 200) { + $data = json_decode($existing['body'], true); + $remoteSha = $data['sha'] ?? ''; + $remoteContent = base64_decode($data['content'] ?? ''); + + if ($remoteContent === $localContent) { + fprintf(STDERR, "%-45s | %s\n", $repoFullName, 'IDENTICAL (skipped)'); + $this->skipped++; + return; + } + + if ($this->dryRun) { + fprintf(STDERR, "%-45s | %s\n", $repoFullName, 'WOULD UPDATE'); + $this->updated++; + return; + } + + $payload = json_encode([ + 'content' => $encodedContent, + 'sha' => $remoteSha, + 'message' => "chore: sync {$destPath} " + . "from mokoplatform [skip ci]", + 'branch' => $branch, + ]); + + $response = $this->apiRequest( + $giteaUrl, + $token, + 'PUT', + "/api/v1/repos/{$owner}/{$repoName}/contents/" + . $destPath, + $payload + ); + + if ($response['code'] === 200) { + fprintf(STDERR, "%-45s | %s\n", $repoFullName, 'UPDATED'); + $this->updated++; + } else { + fprintf(STDERR, "%-45s | %s\n", $repoFullName, "ERROR (HTTP {$response['code']})"); + $this->errors++; + } + } elseif ($existing['code'] === 404) { + if ($this->dryRun) { + fprintf(STDERR, "%-45s | %s\n", $repoFullName, 'WOULD CREATE'); + $this->created++; + return; + } + + $payload = json_encode([ + 'content' => $encodedContent, + 'message' => "chore: add {$destPath} " + . "from mokoplatform [skip ci]", + 'branch' => $branch, + ]); + + $response = $this->apiRequest( + $giteaUrl, + $token, + 'POST', + "/api/v1/repos/{$owner}/{$repoName}/contents/" + . $destPath, + $payload + ); + + if ($response['code'] === 201) { + fprintf(STDERR, "%-45s | %s\n", $repoFullName, 'CREATED'); + $this->created++; + } else { + fprintf(STDERR, "%-45s | %s\n", $repoFullName, "ERROR (HTTP {$response['code']})"); + $this->errors++; + } + } else { + fprintf(STDERR, "%-45s | %s\n", $repoFullName, "ERROR (HTTP {$existing['code']})"); + $this->errors++; + } + } + + private function fetchOrgRepos(string $giteaUrl, string $token, string $org): ?array + { + $this->log('INFO', "Fetching repos from org: {$org}"); + + $page = 1; + $repos = []; + + while (true) { + $response = $this->apiRequest( + $giteaUrl, + $token, + 'GET', + "/api/v1/orgs/{$org}/repos?" + . "limit=50&page={$page}" + ); + + if ($response['code'] < 200 || $response['code'] >= 300) { + if ($page === 1) { + $this->log('ERROR', "Could not fetch repos " + . "(HTTP {$response['code']})."); + return null; + } + + break; + } + + $data = json_decode($response['body'], true); + + if (!is_array($data) || count($data) === 0) { + break; + } + + foreach ($data as $repo) { + if (!empty($repo['archived'])) { + continue; + } + + $fullName = $repo['full_name'] ?? ''; + + if ($fullName !== '') { + $repos[] = $fullName; + } + } + + $page++; + } + + return $repos; + } + + private function apiRequest( + string $giteaUrl, + string $token, + string $method, + string $endpoint, + ?string $body = null + ): array { + $url = $giteaUrl . $endpoint; + + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); + curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Content-Type: application/json', + 'Accept: application/json', + "Authorization: token {$token}", + ]); + + if ($body !== null) { + curl_setopt($ch, CURLOPT_POSTFIELDS, $body); + } + + $responseBody = curl_exec($ch); + $httpCode = (int) curl_getinfo( + $ch, + CURLINFO_HTTP_CODE + ); + + if (curl_errno($ch)) { + $error = curl_error($ch); + curl_close($ch); + + return [ + 'code' => 0, + 'body' => "cURL error: {$error}", + ]; + } + + curl_close($ch); + + return ['code' => $httpCode, 'body' => $responseBody]; + } +} + +$app = new BulkWorkflowPushCli(); +exit($app->execute()); diff --git a/cli/bulk_workflow_trigger.php b/cli/bulk_workflow_trigger.php index 47fb140..c525668 100644 --- a/cli/bulk_workflow_trigger.php +++ b/cli/bulk_workflow_trigger.php @@ -12,7 +12,7 @@ * INGROUP: mokoplatform * REPO: https://git.mokoconsulting.tech/MokoConsulting/mokoplatform * PATH: /cli/bulk_workflow_trigger.php - * VERSION: 09.29.01 + * VERSION: 09.29.02 * BRIEF: Trigger a workflow across multiple repos at once */ @@ -20,7 +20,7 @@ declare(strict_types=1); require_once __DIR__ . '/../lib/Enterprise/CliFramework.php'; -use MokoEnterprise\CliFramework; +use MokoCli\CliFramework; class BulkWorkflowTriggerCli extends CliFramework { diff --git a/cli/changelog_promote.php b/cli/changelog_promote.php index 41188d4..e56ac76 100644 --- a/cli/changelog_promote.php +++ b/cli/changelog_promote.php @@ -17,7 +17,7 @@ declare(strict_types=1); require_once __DIR__ . '/../lib/Enterprise/CliFramework.php'; -use MokoEnterprise\CliFramework; +use MokoCli\CliFramework; class ChangelogPromoteCli extends CliFramework { diff --git a/cli/changelog_prune.php b/cli/changelog_prune.php index 2a7c8bb..8e2e6a7 100644 --- a/cli/changelog_prune.php +++ b/cli/changelog_prune.php @@ -17,7 +17,7 @@ declare(strict_types=1); require_once __DIR__ . '/../lib/Enterprise/CliFramework.php'; -use MokoEnterprise\CliFramework; +use MokoCli\CliFramework; class ChangelogPruneCli extends CliFramework { diff --git a/cli/client_dashboard.php b/cli/client_dashboard.php index 1909f08..20fc247 100644 --- a/cli/client_dashboard.php +++ b/cli/client_dashboard.php @@ -12,7 +12,7 @@ * INGROUP: mokoplatform * REPO: https://git.mokoconsulting.tech/MokoConsulting/mokoplatform * PATH: /cli/client_dashboard.php - * VERSION: 09.29.01 + * VERSION: 09.29.02 * BRIEF: Generate unified client dashboard HTML */ @@ -20,7 +20,7 @@ declare(strict_types=1); require_once __DIR__ . '/../lib/Enterprise/CliFramework.php'; -use MokoEnterprise\CliFramework; +use MokoCli\CliFramework; class ClientDashboardCli extends CliFramework { diff --git a/cli/client_health_check.php b/cli/client_health_check.php index dc84e10..1a72b2c 100644 --- a/cli/client_health_check.php +++ b/cli/client_health_check.php @@ -17,7 +17,7 @@ declare(strict_types=1); require_once __DIR__ . '/../lib/Enterprise/CliFramework.php'; -use MokoEnterprise\CliFramework; +use MokoCli\CliFramework; class ClientHealthCheckCli extends CliFramework { diff --git a/cli/client_inventory.php b/cli/client_inventory.php index 38c084b..5f7446c 100644 --- a/cli/client_inventory.php +++ b/cli/client_inventory.php @@ -12,7 +12,7 @@ * INGROUP: mokoplatform * REPO: https://git.mokoconsulting.tech/MokoConsulting/mokoplatform * PATH: /cli/client_inventory.php - * VERSION: 09.29.01 + * VERSION: 09.29.02 * BRIEF: Discover and list all client-waas repos with their server configuration status */ @@ -20,7 +20,7 @@ declare(strict_types=1); require_once __DIR__ . '/../lib/Enterprise/CliFramework.php'; -use MokoEnterprise\CliFramework; +use MokoCli\CliFramework; class ClientInventoryCli extends CliFramework { diff --git a/cli/client_provision.php b/cli/client_provision.php index c70d408..0934566 100644 --- a/cli/client_provision.php +++ b/cli/client_provision.php @@ -12,7 +12,7 @@ * INGROUP: mokoplatform * REPO: https://git.mokoconsulting.tech/MokoConsulting/mokoplatform * PATH: /cli/client_provision.php - * VERSION: 09.29.01 + * VERSION: 09.29.02 * BRIEF: Provision a new client environment end-to-end */ @@ -20,7 +20,7 @@ declare(strict_types=1); require_once __DIR__ . '/../lib/Enterprise/CliFramework.php'; -use MokoEnterprise\CliFramework; +use MokoCli\CliFramework; class ClientProvisionCli extends CliFramework { diff --git a/cli/completion.php b/cli/completion.php index 5025a97..8900b22 100644 --- a/cli/completion.php +++ b/cli/completion.php @@ -17,7 +17,7 @@ declare(strict_types=1); require_once __DIR__ . '/../lib/Enterprise/CliFramework.php'; -use MokoEnterprise\CliFramework; +use MokoCli\CliFramework; class CompletionCli extends CliFramework { diff --git a/cli/create_project.php b/cli/create_project.php index 299045c..e07cc95 100644 --- a/cli/create_project.php +++ b/cli/create_project.php @@ -19,7 +19,7 @@ declare(strict_types=1); require_once __DIR__ . '/../lib/Enterprise/CliFramework.php'; -use MokoEnterprise\CliFramework; +use MokoCli\CliFramework; class CreateProjectCli extends CliFramework { @@ -80,10 +80,10 @@ class CreateProjectCli extends CliFramework return 2; } - $config = \MokoEnterprise\Config::load(); + $config = \MokoCli\Config::load(); $platformName = $config->getString('platform', 'gitea'); try { - $adapter = \MokoEnterprise\PlatformAdapterFactory::create($config); + $adapter = \MokoCli\PlatformAdapterFactory::create($config); $api = $adapter->getApiClient(); } catch (\Exception $e) { $this->log('ERROR', "Platform initialization failed: " . $e->getMessage()); @@ -205,7 +205,7 @@ class CreateProjectCli extends CliFramework return $data['data'] ?? []; } - private function restGet(string $path, string $token, ?\MokoEnterprise\ApiClient $apiClient = null): array + private function restGet(string $path, string $token, ?\MokoCli\ApiClient $apiClient = null): array { if ($apiClient !== null) { try { @@ -217,7 +217,7 @@ class CreateProjectCli extends CliFramework return []; } - private function detectRepoPlatform(string $org, string $repo, string $token, ?\MokoEnterprise\ApiClient $apiClient = null): string + private function detectRepoPlatform(string $org, string $repo, string $token, ?\MokoCli\ApiClient $apiClient = null): string { foreach (['.github/.mokostandards', '.mokogitea/.mokostandards', '.mokostandards'] as $path) { $data = $this->restGet("repos/{$org}/{$repo}/contents/{$path}", $token, $apiClient); diff --git a/cli/create_repo.php b/cli/create_repo.php index 26f4d7f..13118fe 100644 --- a/cli/create_repo.php +++ b/cli/create_repo.php @@ -20,9 +20,9 @@ declare(strict_types=1); require_once __DIR__ . '/../vendor/autoload.php'; require_once __DIR__ . '/../lib/Enterprise/CliFramework.php'; -use MokoEnterprise\CliFramework; -use MokoEnterprise\Config; -use MokoEnterprise\PlatformAdapterFactory; +use MokoCli\CliFramework; +use MokoCli\Config; +use MokoCli\PlatformAdapterFactory; class CreateRepoCli extends CliFramework { @@ -138,7 +138,7 @@ class CreateRepoCli extends CliFramework echo "Step 4: Creating README.md...\n"; $baseUrl = $platformName === 'gitea' ? $config->getString('gitea.url', 'https://git.mokoconsulting.tech') : 'https://github.com'; $repoUrl = "{$baseUrl}/{$org}/{$name}"; - $standardsUrl = "{$baseUrl}/{$org}/MokoStandards"; + $standardsUrl = "{$baseUrl}/{$org}/MokoCli"; $readmeContent = " diff --git a/mcp/servers/mokocrm_api/README.md b/mcp/servers/mokocrm_api/README.md index c207119..80b3186 100644 --- a/mcp/servers/mokocrm_api/README.md +++ b/mcp/servers/mokocrm_api/README.md @@ -367,4 +367,4 @@ This project is licensed under the GNU General Public License v3.0 or later -- s --- -*[Moko Consulting](https://mokoconsulting.tech) -- [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki/Home)* +*[Moko Consulting](https://mokoconsulting.tech) -- [MokoCli](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki/Home)* diff --git a/mcp/servers/mokocrm_api/SECURITY.md b/mcp/servers/mokocrm_api/SECURITY.md index 522ffe7..3f246f7 100644 --- a/mcp/servers/mokocrm_api/SECURITY.md +++ b/mcp/servers/mokocrm_api/SECURITY.md @@ -10,7 +10,7 @@ DEFGROUP: dolibarr-api-mcp.Documentation INGROUP: dolibarr-api-mcp REPO: https://git.mokoconsulting.tech/MokoConsulting/dolibarr-api-mcp PATH: /SECURITY.md -VERSION: 09.29.01 +VERSION: 09.29.02 BRIEF: Security vulnerability reporting and handling policy --> @@ -18,7 +18,7 @@ BRIEF: Security vulnerability reporting and handling policy ## Purpose and Scope -This document defines the security vulnerability reporting, response, and disclosure policy for dolibarr-api-mcp and all repositories governed by MokoStandards. +This document defines the security vulnerability reporting, response, and disclosure policy for dolibarr-api-mcp and all repositories governed by MokoCli. ## Supported Versions diff --git a/mcp/servers/mokodreamhost/.mokogitea/CLAUDE.md b/mcp/servers/mokodreamhost/.mokogitea/CLAUDE.md index 7926d19..be1c53e 100644 --- a/mcp/servers/mokodreamhost/.mokogitea/CLAUDE.md +++ b/mcp/servers/mokodreamhost/.mokogitea/CLAUDE.md @@ -39,4 +39,4 @@ src/ - **Attribution**: `Authored-by: Moko Consulting` - **Workflow directory**: `.mokogitea/` (not `.gitea/` or `.github/`) - **Wiki**: documentation lives in the Gitea wiki, not `docs/` files -- **Standards**: [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki/Home) +- **Standards**: [MokoCli](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki/Home) diff --git a/mcp/servers/mokodreamhost/README.md b/mcp/servers/mokodreamhost/README.md index 0660b66..02fa64f 100644 --- a/mcp/servers/mokodreamhost/README.md +++ b/mcp/servers/mokodreamhost/README.md @@ -156,4 +156,4 @@ Full documentation is available on the [Wiki](https://git.mokoconsulting.tech/Mo --- -*[Moko Consulting](https://mokoconsulting.tech) -- [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki/Home)* +*[Moko Consulting](https://mokoconsulting.tech) -- [MokoCli](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki/Home)* diff --git a/mcp/servers/mokomonitor/.mokogitea/CLAUDE.md b/mcp/servers/mokomonitor/.mokogitea/CLAUDE.md index 0ec3c30..c12dc4f 100644 --- a/mcp/servers/mokomonitor/.mokogitea/CLAUDE.md +++ b/mcp/servers/mokomonitor/.mokogitea/CLAUDE.md @@ -41,4 +41,4 @@ src/ - **Attribution**: `Authored-by: Moko Consulting` - **Workflow directory**: `.mokogitea/` (not `.gitea/` or `.github/`) - **Wiki**: documentation lives in the Gitea wiki, not `docs/` files -- **Standards**: [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki/Home) +- **Standards**: [MokoCli](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki/Home) diff --git a/mcp/servers/mokomonitor/.mokogitea/workflows/gitleaks.yml b/mcp/servers/mokomonitor/.mokogitea/workflows/gitleaks.yml index b29f881..f95b1ad 100644 --- a/mcp/servers/mokomonitor/.mokogitea/workflows/gitleaks.yml +++ b/mcp/servers/mokomonitor/.mokogitea/workflows/gitleaks.yml @@ -4,8 +4,8 @@ # # FILE INFORMATION # DEFGROUP: Gitea.Workflow -# INGROUP: MokoStandards.Security -# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoStandards-API +# INGROUP: MokoCli.Security +# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoCli-API # PATH: /templates/workflows/gitleaks.yml.template # VERSION: 01.00.00 # BRIEF: Secret scanning — detect leaked credentials, API keys, and tokens diff --git a/mcp/servers/mokomonitor/.mokogitea/workflows/repo-health.yml b/mcp/servers/mokomonitor/.mokogitea/workflows/repo-health.yml index badb732..94c0441 100644 --- a/mcp/servers/mokomonitor/.mokogitea/workflows/repo-health.yml +++ b/mcp/servers/mokomonitor/.mokogitea/workflows/repo-health.yml @@ -7,8 +7,8 @@ # # FILE INFORMATION # DEFGROUP: Gitea.Workflow -# INGROUP: MokoStandards.Validation -# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoStandards-API +# INGROUP: MokoCli.Validation +# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoCli-API # PATH: /templates/workflows/joomla/repo_health.yml.template # VERSION: 04.06.00 # BRIEF: Enforces repository guardrails by validating release configuration, scripts governance, tooling availability, and core repository health artifacts. diff --git a/mcp/servers/mokomonitor/README.md b/mcp/servers/mokomonitor/README.md index 37a04eb..bdfc0d4 100644 --- a/mcp/servers/mokomonitor/README.md +++ b/mcp/servers/mokomonitor/README.md @@ -48,7 +48,7 @@ monitor-mcp provides MCP tools for monitoring server infrastructure and Grafana --- -> **[MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki)** -- central standards hub for all Moko Consulting projects. +> **[MokoCli](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki)** -- central standards hub for all Moko Consulting projects. --- @@ -70,4 +70,4 @@ This project is licensed under the GNU General Public License v3.0 or later -- s --- -*[Moko Consulting](https://mokoconsulting.tech) -- [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki/Home)* +*[Moko Consulting](https://mokoconsulting.tech) -- [MokoCli](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki/Home)* diff --git a/mcp/servers/mokomonitor/mcp_mokomonitor/.mokogitea/CLAUDE.md b/mcp/servers/mokomonitor/mcp_mokomonitor/.mokogitea/CLAUDE.md index 0ec3c30..c12dc4f 100644 --- a/mcp/servers/mokomonitor/mcp_mokomonitor/.mokogitea/CLAUDE.md +++ b/mcp/servers/mokomonitor/mcp_mokomonitor/.mokogitea/CLAUDE.md @@ -41,4 +41,4 @@ src/ - **Attribution**: `Authored-by: Moko Consulting` - **Workflow directory**: `.mokogitea/` (not `.gitea/` or `.github/`) - **Wiki**: documentation lives in the Gitea wiki, not `docs/` files -- **Standards**: [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki/Home) +- **Standards**: [MokoCli](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki/Home) diff --git a/mcp/servers/mokomonitor/mcp_mokomonitor/.mokogitea/workflows/gitleaks.yml b/mcp/servers/mokomonitor/mcp_mokomonitor/.mokogitea/workflows/gitleaks.yml index b29f881..f95b1ad 100644 --- a/mcp/servers/mokomonitor/mcp_mokomonitor/.mokogitea/workflows/gitleaks.yml +++ b/mcp/servers/mokomonitor/mcp_mokomonitor/.mokogitea/workflows/gitleaks.yml @@ -4,8 +4,8 @@ # # FILE INFORMATION # DEFGROUP: Gitea.Workflow -# INGROUP: MokoStandards.Security -# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoStandards-API +# INGROUP: MokoCli.Security +# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoCli-API # PATH: /templates/workflows/gitleaks.yml.template # VERSION: 01.00.00 # BRIEF: Secret scanning — detect leaked credentials, API keys, and tokens diff --git a/mcp/servers/mokomonitor/mcp_mokomonitor/.mokogitea/workflows/repo-health.yml b/mcp/servers/mokomonitor/mcp_mokomonitor/.mokogitea/workflows/repo-health.yml index badb732..94c0441 100644 --- a/mcp/servers/mokomonitor/mcp_mokomonitor/.mokogitea/workflows/repo-health.yml +++ b/mcp/servers/mokomonitor/mcp_mokomonitor/.mokogitea/workflows/repo-health.yml @@ -7,8 +7,8 @@ # # FILE INFORMATION # DEFGROUP: Gitea.Workflow -# INGROUP: MokoStandards.Validation -# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoStandards-API +# INGROUP: MokoCli.Validation +# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoCli-API # PATH: /templates/workflows/joomla/repo_health.yml.template # VERSION: 04.06.00 # BRIEF: Enforces repository guardrails by validating release configuration, scripts governance, tooling availability, and core repository health artifacts. diff --git a/mcp/servers/mokossh/.mokogitea/CLAUDE.md b/mcp/servers/mokossh/.mokogitea/CLAUDE.md index ad843ea..917a71e 100644 --- a/mcp/servers/mokossh/.mokogitea/CLAUDE.md +++ b/mcp/servers/mokossh/.mokogitea/CLAUDE.md @@ -65,4 +65,4 @@ SSH key: `jmiller_private.openssh` - **Never commit** `.env`, `.claude/`, `.mcp.json`, `TODO.md` - **Attribution**: `Authored-by: Moko Consulting` - **Workflow directory**: `.mokogitea/` (not `.gitea/` or `.github/`) -- **Standards**: [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki/Home) +- **Standards**: [MokoCli](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki/Home) diff --git a/mcp/servers/mokossh/.mokogitea/ISSUE_TEMPLATE/config.yml b/mcp/servers/mokossh/.mokogitea/ISSUE_TEMPLATE/config.yml index 7c403f1..14db946 100644 --- a/mcp/servers/mokossh/.mokogitea/ISSUE_TEMPLATE/config.yml +++ b/mcp/servers/mokossh/.mokogitea/ISSUE_TEMPLATE/config.yml @@ -7,7 +7,7 @@ contact_links: - name: 💬 Ask a Question url: https://mokoconsulting.tech/ about: Get help or ask questions through our website - - name: 📚 MokoStandards Documentation + - name: 📚 MokoCli Documentation url: https://git.mokoconsulting.tech/MokoConsulting/mokoplatform about: View our coding standards and best practices - name: 🔒 Report a Security Vulnerability diff --git a/mcp/servers/mokossh/.mokogitea/ISSUE_TEMPLATE/documentation.md b/mcp/servers/mokossh/.mokogitea/ISSUE_TEMPLATE/documentation.md index ed4dabc..96d4fbc 100644 --- a/mcp/servers/mokossh/.mokogitea/ISSUE_TEMPLATE/documentation.md +++ b/mcp/servers/mokossh/.mokogitea/ISSUE_TEMPLATE/documentation.md @@ -42,7 +42,7 @@ Suggested text here ## Standards Alignment -- [ ] Follows MokoStandards documentation guidelines +- [ ] Follows MokoCli documentation guidelines - [ ] Uses en_US/en_GB localization - [ ] Includes proper SPDX headers where applicable diff --git a/mcp/servers/mokossh/.mokogitea/ISSUE_TEMPLATE/feature_request.md b/mcp/servers/mokossh/.mokogitea/ISSUE_TEMPLATE/feature_request.md index 7b76dc9..6161deb 100644 --- a/mcp/servers/mokossh/.mokogitea/ISSUE_TEMPLATE/feature_request.md +++ b/mcp/servers/mokossh/.mokogitea/ISSUE_TEMPLATE/feature_request.md @@ -37,7 +37,7 @@ If you have ideas about how this could be implemented, share them here: Add any other context, mockups, or screenshots about the feature request here. ## Relevant Standards -Does this relate to any standards in [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/MokoStandards)? +Does this relate to any standards in [MokoCli](https://git.mokoconsulting.tech/MokoConsulting/MokoCli)? - [ ] Accessibility (WCAG 2.1 AA) - [ ] Localization (en_US/en_GB) - [ ] Security best practices diff --git a/mcp/servers/mokossh/.mokogitea/ISSUE_TEMPLATE/security.md b/mcp/servers/mokossh/.mokogitea/ISSUE_TEMPLATE/security.md index f57b284..69bae34 100644 --- a/mcp/servers/mokossh/.mokogitea/ISSUE_TEMPLATE/security.md +++ b/mcp/servers/mokossh/.mokogitea/ISSUE_TEMPLATE/security.md @@ -35,7 +35,7 @@ Use this template only for: ## Standards Reference -Does this relate to security standards in [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/MokoStandards)? +Does this relate to security standards in [MokoCli](https://git.mokoconsulting.tech/MokoConsulting/MokoCli)? - [ ] SPDX license identifiers - [ ] Secret management - [ ] Dependency security diff --git a/mcp/servers/mokossh/.mokogitea/workflows/auto-assign.yml b/mcp/servers/mokossh/.mokogitea/workflows/auto-assign.yml index c0f538f..ab7f573 100644 --- a/mcp/servers/mokossh/.mokogitea/workflows/auto-assign.yml +++ b/mcp/servers/mokossh/.mokogitea/workflows/auto-assign.yml @@ -3,8 +3,8 @@ # # FILE INFORMATION # DEFGROUP: GitHub.Workflow -# INGROUP: MokoStandards.Workflows.Shared -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCli.Workflows.Shared +# REPO: https://github.com/mokoconsulting-tech/MokoCli # PATH: /.mokogitea/workflows/auto-assign.yml # VERSION: 04.06.00 # BRIEF: Auto-assign jmiller to unassigned issues and PRs every 15 minutes diff --git a/mcp/servers/mokossh/.mokogitea/workflows/auto-dev-issue.yml b/mcp/servers/mokossh/.mokogitea/workflows/auto-dev-issue.yml index bdd7db7..a8774ab 100644 --- a/mcp/servers/mokossh/.mokogitea/workflows/auto-dev-issue.yml +++ b/mcp/servers/mokossh/.mokogitea/workflows/auto-dev-issue.yml @@ -6,8 +6,8 @@ # # FILE INFORMATION # DEFGROUP: GitHub.Workflow -# INGROUP: MokoStandards.Automation -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCli.Automation +# REPO: https://github.com/mokoconsulting-tech/MokoCli # PATH: /templates/workflows/shared/auto-dev-issue.yml.template # VERSION: 04.06.00 # BRIEF: Auto-create tracking issue with sub-issues for dev/rc branch workflow diff --git a/mcp/servers/mokossh/.mokogitea/workflows/changelog-validation.yml b/mcp/servers/mokossh/.mokogitea/workflows/changelog-validation.yml index 0601d2f..f104937 100644 --- a/mcp/servers/mokossh/.mokogitea/workflows/changelog-validation.yml +++ b/mcp/servers/mokossh/.mokogitea/workflows/changelog-validation.yml @@ -6,8 +6,8 @@ # # FILE INFORMATION # DEFGROUP: GitHub.Workflow.Template -# INGROUP: MokoStandards.CI -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCli.CI +# REPO: https://github.com/mokoconsulting-tech/MokoCli # PATH: /templates/workflows/shared/changelog-validation.yml.template # VERSION: 04.06.00 # BRIEF: Validates CHANGELOG.md format and version consistency diff --git a/mcp/servers/mokossh/.mokogitea/workflows/codeql-analysis.yml b/mcp/servers/mokossh/.mokogitea/workflows/codeql-analysis.yml index dd61fc3..0e4c735 100644 --- a/mcp/servers/mokossh/.mokogitea/workflows/codeql-analysis.yml +++ b/mcp/servers/mokossh/.mokogitea/workflows/codeql-analysis.yml @@ -6,8 +6,8 @@ # # FILE INFORMATION # DEFGROUP: GitHub.Workflow.Template -# INGROUP: MokoStandards.Security -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCli.Security +# REPO: https://github.com/mokoconsulting-tech/MokoCli # PATH: /templates/workflows/generic/codeql-analysis.yml.template # VERSION: 04.05.00 # BRIEF: CodeQL security scanning workflow (generic — all repo types) diff --git a/mcp/servers/mokossh/.mokogitea/workflows/enterprise-firewall-setup.yml b/mcp/servers/mokossh/.mokogitea/workflows/enterprise-firewall-setup.yml index 81866f2..af361ef 100644 --- a/mcp/servers/mokossh/.mokogitea/workflows/enterprise-firewall-setup.yml +++ b/mcp/servers/mokossh/.mokogitea/workflows/enterprise-firewall-setup.yml @@ -19,8 +19,8 @@ # FILE INFORMATION # DEFGROUP: GitHub.Workflow -# INGROUP: MokoStandards.Firewall -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCli.Firewall +# REPO: https://github.com/mokoconsulting-tech/MokoCli # PATH: /templates/workflows/shared/enterprise-firewall-setup.yml.template # VERSION: 04.06.00 # BRIEF: Enterprise firewall configuration — generates outbound allow-rules including SFTP deployment server diff --git a/mcp/servers/mokossh/.mokogitea/workflows/mcp-auto-release.yml b/mcp/servers/mokossh/.mokogitea/workflows/mcp-auto-release.yml index d3ef2ef..f4153ed 100644 --- a/mcp/servers/mokossh/.mokogitea/workflows/mcp-auto-release.yml +++ b/mcp/servers/mokossh/.mokogitea/workflows/mcp-auto-release.yml @@ -87,13 +87,13 @@ jobs: done # ── Version ────────────────────────────────────────────────────── - - name: Setup MokoStandards tools + - name: Setup MokoCli tools env: GH_TOKEN: ${{ secrets.GH_PAT || github.token }} COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_PAT || github.token }}"}}' run: | git clone --depth 1 --branch version/04 --quiet \ - "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \ + "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoCli.git" \ /tmp/mokostandards cd /tmp/mokostandards composer install --no-dev --no-interaction --quiet diff --git a/mcp/servers/mokossh/.mokogitea/workflows/repository-cleanup.yml b/mcp/servers/mokossh/.mokogitea/workflows/repository-cleanup.yml index bb90e00..0468b17 100644 --- a/mcp/servers/mokossh/.mokogitea/workflows/repository-cleanup.yml +++ b/mcp/servers/mokossh/.mokogitea/workflows/repository-cleanup.yml @@ -6,8 +6,8 @@ # # FILE INFORMATION # DEFGROUP: GitHub.Workflow -# INGROUP: MokoStandards.Maintenance -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCli.Maintenance +# REPO: https://github.com/mokoconsulting-tech/MokoCli # PATH: /templates/workflows/shared/repository-cleanup.yml.template # VERSION: 04.06.00 # BRIEF: Recurring repository maintenance — labels, branches, workflows, logs, doc indexes @@ -220,7 +220,7 @@ jobs: config|F9D0C4|Configuration file changes build|FFA500|Build system changes automation|8B4513|Automated processes or scripts - mokostandards|B60205|MokoStandards compliance + mokostandards|B60205|MokoCli compliance needs-review|FBCA04|Awaiting code review work-in-progress|D93F0B|Work in progress, not ready for merge breaking-change|D73A4A|Breaking API or functionality change @@ -249,8 +249,8 @@ jobs: health: good|FBCA04|Health score 70-89 health: fair|FFA500|Health score 50-69 health: poor|FF6B6B|Health score below 50 - standards-update|B60205|MokoStandards sync update - standards-drift|FBCA04|Repository drifted from MokoStandards + standards-update|B60205|MokoCli sync update + standards-drift|FBCA04|Repository drifted from MokoCli sync-report|0075CA|Bulk sync run report sync-failure|D73A4A|Bulk sync failure requiring attention push-failure|D73A4A|File push failure requiring attention @@ -469,7 +469,7 @@ jobs: # Custom Workflows Place repo-specific workflows here. Files in this directory are: - - **Never overwritten** by MokoStandards bulk sync + - **Never overwritten** by MokoCli bulk sync - **Never deleted** by the repository-cleanup workflow - Safe for custom CI, notifications, or repo-specific automation diff --git a/mcp/servers/mokossh/.mokogitea/workflows/standards-compliance.yml b/mcp/servers/mokossh/.mokogitea/workflows/standards-compliance.yml index 1927cb0..7774161 100644 --- a/mcp/servers/mokossh/.mokogitea/workflows/standards-compliance.yml +++ b/mcp/servers/mokossh/.mokogitea/workflows/standards-compliance.yml @@ -2,11 +2,11 @@ # SPDX-License-Identifier: GPL-3.0-or-later # FILE INFORMATION # DEFGROUP: GitHub.Workflow -# INGROUP: MokoStandards.Compliance -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCli.Compliance +# REPO: https://github.com/mokoconsulting-tech/MokoCli # PATH: /.mokogitea/workflows/standards-compliance.yml # VERSION: 04.06.00 -# BRIEF: MokoStandards compliance validation workflow +# BRIEF: MokoCli compliance validation workflow # NOTE: Validates repository structure, documentation, and coding standards name: "MCP: Standards Compliance" @@ -42,7 +42,7 @@ env: WORKFLOW_VERSION: "04.04.01" FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true -# MokoStandards Policy Compliance: +# MokoCli Policy Compliance: # - File formatting: Enforces organizational coding standards # - Reference: docs/policy/file-formatting.md @@ -252,7 +252,7 @@ jobs: echo "" >> $GITHUB_STEP_SUMMARY echo "### ❌ Validation Failed: LICENSE File Missing" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**Error:** LICENSE file is required for all MokoStandards-compliant repositories" >> $GITHUB_STEP_SUMMARY + echo "**Error:** LICENSE file is required for all MokoCli-compliant repositories" >> $GITHUB_STEP_SUMMARY echo "**Action Required:** Add LICENSE file with appropriate open-source license (GPL-3.0-or-later recommended)" >> $GITHUB_STEP_SUMMARY echo "" echo "❌ ERROR: LICENSE file not found - This is a critical requirement" @@ -323,11 +323,11 @@ jobs: [ ! -d "docs" ] && echo "- Create docs directory: \`mkdir docs && echo '# Documentation' > docs/README.md\`" >> $GITHUB_STEP_SUMMARY [ ! -d ".github" ] && echo "- Create .github directory: \`mkdir -p .github/workflows\`" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "📚 Reference: [MokoStandards Repository Structure](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/docs/policy/core-structure.md)" >> $GITHUB_STEP_SUMMARY + echo "📚 Reference: [MokoCli Repository Structure](https://github.com/mokoconsulting-tech/MokoCli/tree/main/docs/policy/core-structure.md)" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "### ❌ Validation Failed: Required Directories Missing" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**Status:** Repository structure does not meet MokoStandards requirements" >> $GITHUB_STEP_SUMMARY + echo "**Status:** Repository structure does not meet MokoCli requirements" >> $GITHUB_STEP_SUMMARY echo "**Missing:** $MISSING required director(y|ies)" >> $GITHUB_STEP_SUMMARY echo "**Compliance:** $PERCENT% ($PRESENT/$TOTAL directories present)" >> $GITHUB_STEP_SUMMARY echo "" @@ -384,17 +384,17 @@ jobs: echo "### 🔴 Critical Issues: $MISSING" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "**Remediation Steps:**" >> $GITHUB_STEP_SUMMARY - [ ! -f "README.md" ] && echo "- Create README.md: Use [template](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/templates/docs/required/README.md)" >> $GITHUB_STEP_SUMMARY + [ ! -f "README.md" ] && echo "- Create README.md: Use [template](https://github.com/mokoconsulting-tech/MokoCli/tree/main/templates/docs/required/README.md)" >> $GITHUB_STEP_SUMMARY [ ! -f "LICENSE" ] && echo "- Add LICENSE file: Choose from [OSI-approved licenses](https://opensource.org/licenses)" >> $GITHUB_STEP_SUMMARY - [ ! -f "CONTRIBUTING.md" ] && echo "- Create CONTRIBUTING.md: Use [template](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/templates/docs/required/CONTRIBUTING.md)" >> $GITHUB_STEP_SUMMARY - [ ! -f "SECURITY.md" ] && echo "- Create SECURITY.md: Use [template](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/templates/docs/required/SECURITY.md)" >> $GITHUB_STEP_SUMMARY - [ ! -f ".editorconfig" ] && echo "- Add .editorconfig: Use [template](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/templates/.editorconfig)" >> $GITHUB_STEP_SUMMARY + [ ! -f "CONTRIBUTING.md" ] && echo "- Create CONTRIBUTING.md: Use [template](https://github.com/mokoconsulting-tech/MokoCli/tree/main/templates/docs/required/CONTRIBUTING.md)" >> $GITHUB_STEP_SUMMARY + [ ! -f "SECURITY.md" ] && echo "- Create SECURITY.md: Use [template](https://github.com/mokoconsulting-tech/MokoCli/tree/main/templates/docs/required/SECURITY.md)" >> $GITHUB_STEP_SUMMARY + [ ! -f ".editorconfig" ] && echo "- Add .editorconfig: Use [template](https://github.com/mokoconsulting-tech/MokoCli/tree/main/templates/.editorconfig)" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "📚 Reference: [MokoStandards File Requirements](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/docs/policy/file-header-standards.md)" >> $GITHUB_STEP_SUMMARY + echo "📚 Reference: [MokoCli File Requirements](https://github.com/mokoconsulting-tech/MokoCli/tree/main/docs/policy/file-header-standards.md)" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "### ❌ Validation Failed: Required Files Missing" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**Status:** Repository files do not meet MokoStandards requirements" >> $GITHUB_STEP_SUMMARY + echo "**Status:** Repository files do not meet MokoCli requirements" >> $GITHUB_STEP_SUMMARY echo "**Missing:** $MISSING required file(s)" >> $GITHUB_STEP_SUMMARY echo "**Compliance:** $PERCENT% ($PRESENT/$TOTAL files present)" >> $GITHUB_STEP_SUMMARY echo "" @@ -437,7 +437,7 @@ jobs: echo "$TABS_IN_SPACES_FILES" >> $GITHUB_STEP_SUMMARY echo "\`\`\`" >> $GITHUB_STEP_SUMMARY echo "These languages require spaces (tabs will break): YAML, Python, Haskell, F#, CoffeeScript, Nim, JSON, RST" >> $GITHUB_STEP_SUMMARY - echo "All other files (including .md, .ps1, LICENSE, etc.) may use tabs per MokoStandards policy" >> $GITHUB_STEP_SUMMARY + echo "All other files (including .md, .ps1, LICENSE, etc.) may use tabs per MokoCli policy" >> $GITHUB_STEP_SUMMARY else echo "✅ No tabs found in files requiring spaces" >> $GITHUB_STEP_SUMMARY echo "Note: Tabs are allowed in most files (policy default). Only checked files requiring spaces." >> $GITHUB_STEP_SUMMARY @@ -483,7 +483,7 @@ jobs: echo "\`\`\`" >> $GITHUB_STEP_SUMMARY echo "$CRLF_FILES" >> $GITHUB_STEP_SUMMARY echo "\`\`\`" >> $GITHUB_STEP_SUMMARY - echo "MokoStandards requires LF line endings" >> $GITHUB_STEP_SUMMARY + echo "MokoCli requires LF line endings" >> $GITHUB_STEP_SUMMARY else echo "✅ Line endings are consistent (LF)" >> $GITHUB_STEP_SUMMARY fi @@ -504,13 +504,13 @@ jobs: tools: composer coverage: none - - name: Setup MokoStandards tools + - name: Setup MokoCli tools env: GH_TOKEN: ${{ secrets.GH_PAT || github.token }} COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_PAT || github.token }}"}}' run: | git clone --depth 1 --branch version/04 --quiet \ - "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \ + "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoCli.git" \ /tmp/mokostandards 2>/dev/null || true if [ -d "/tmp/mokostandards" ] && [ -f "/tmp/mokostandards/composer.json" ]; then cd /tmp/mokostandards @@ -524,7 +524,7 @@ jobs: echo "## 🔢 Version Consistency Validation" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - # Use MokoStandards tools (no Composer needed on the governed repo) + # Use MokoCli tools (no Composer needed on the governed repo) if [ -f "/tmp/mokostandards/api/validate/check_version_consistency.php" ]; then php /tmp/mokostandards/api/validate/check_version_consistency.php --path . --verbose 2>&1 | tee /tmp/version-check.log EXIT_CODE=${PIPESTATUS[0]} @@ -532,7 +532,7 @@ jobs: php api/validate/check_version_consistency.php --path . --verbose 2>&1 | tee /tmp/version-check.log EXIT_CODE=${PIPESTATUS[0]} else - echo "⏭️ MokoStandards tools not available — skipping version check" >> $GITHUB_STEP_SUMMARY + echo "⏭️ MokoCli tools not available — skipping version check" >> $GITHUB_STEP_SUMMARY exit 0 fi @@ -597,12 +597,12 @@ jobs: echo "⚠️ CodeQL workflow not found" >> $GITHUB_STEP_SUMMARY fi - # Check for MokoStandards-synced workflows + # Check for MokoCli-synced workflows for wf in deploy-dev.yml deploy-demo.yml deploy-rs.yml sync-version-on-merge.yml auto-release.yml standards-compliance.yml enterprise-firewall-setup.yml; do if [ -f "$WORKFLOWS_DIR/$wf" ]; then echo "✅ ${wf}" >> $GITHUB_STEP_SUMMARY else - echo "⚠️ ${wf} not found (synced from MokoStandards)" >> $GITHUB_STEP_SUMMARY + echo "⚠️ ${wf} not found (synced from MokoCli)" >> $GITHUB_STEP_SUMMARY fi done @@ -809,7 +809,7 @@ jobs: echo "" >> $GITHUB_STEP_SUMMARY echo "### ❌ Validation Failed: README.md Missing" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**Error:** README.md is required for all MokoStandards-compliant repositories" >> $GITHUB_STEP_SUMMARY + echo "**Error:** README.md is required for all MokoCli-compliant repositories" >> $GITHUB_STEP_SUMMARY echo "**Action Required:** Create README.md with project description, setup instructions, and usage examples" >> $GITHUB_STEP_SUMMARY echo "" echo "❌ ERROR: README.md not found - This is a critical requirement" @@ -915,7 +915,7 @@ jobs: echo "" >> $GITHUB_STEP_SUMMARY echo "### ❌ Validation Failed: CHANGELOG.md Missing" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**Error:** CHANGELOG.md is required for all MokoStandards-compliant repositories" >> $GITHUB_STEP_SUMMARY + echo "**Error:** CHANGELOG.md is required for all MokoCli-compliant repositories" >> $GITHUB_STEP_SUMMARY echo "**Action Required:** Create CHANGELOG.md following [Keep a Changelog](https://keepachangelog.com/) format" >> $GITHUB_STEP_SUMMARY echo "" echo "❌ ERROR: CHANGELOG.md not found - This is a critical requirement" @@ -1976,10 +1976,10 @@ jobs: if [ -f "composer.json" ]; then composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader else - echo "No composer.json — pulling MokoStandards tools" + echo "No composer.json — pulling MokoCli tools" if [ ! -d "/tmp/mokostandards" ]; then git clone --depth 1 --branch version/04 --quiet \ - "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \ + "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoCli.git" \ /tmp/mokostandards 2>/dev/null || true if [ -f "/tmp/mokostandards/composer.json" ]; then cd /tmp/mokostandards && composer install --no-dev --no-interaction --quiet 2>/dev/null || true @@ -2048,10 +2048,10 @@ jobs: if [ -f "composer.json" ]; then composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader else - echo "No composer.json — pulling MokoStandards tools" + echo "No composer.json — pulling MokoCli tools" if [ ! -d "/tmp/mokostandards" ]; then git clone --depth 1 --branch version/04 --quiet \ - "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \ + "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoCli.git" \ /tmp/mokostandards 2>/dev/null || true if [ -f "/tmp/mokostandards/composer.json" ]; then cd /tmp/mokostandards && composer install --no-dev --no-interaction --quiet 2>/dev/null || true @@ -2133,7 +2133,7 @@ jobs: # 1. Check .github/config.tf location (not root override files) echo "### Override Configuration Check" >> $GITHUB_STEP_SUMMARY - LEGACY_OVERRIDES=$(find . -maxdepth 1 -name "*override*.tf" -o -name "MokoStandards.override.tf" 2>/dev/null | wc -l || echo 0) + LEGACY_OVERRIDES=$(find . -maxdepth 1 -name "*override*.tf" -o -name "MokoCli.override.tf" 2>/dev/null | wc -l || echo 0) if [ "$LEGACY_OVERRIDES" -gt 0 ]; then echo "⚠️ Found legacy override files in root directory" >> $GITHUB_STEP_SUMMARY echo "**Expected Location**: .github/config.tf" >> $GITHUB_STEP_SUMMARY @@ -2299,7 +2299,7 @@ jobs: - name: Generate Compliance Report run: | set -x - echo "# 📊 MokoStandards Compliance Report" >> $GITHUB_STEP_SUMMARY + echo "# 📊 MokoCli Compliance Report" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY # Calculate overall status @@ -2486,7 +2486,7 @@ jobs: else echo "## 🎉 Excellent!" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "Your repository is **fully compliant** with MokoStandards!" >> $GITHUB_STEP_SUMMARY + echo "Your repository is **fully compliant** with MokoCli!" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "**Achievements:**" >> $GITHUB_STEP_SUMMARY echo "- ✅ All required directories and files present" >> $GITHUB_STEP_SUMMARY @@ -2501,12 +2501,12 @@ jobs: echo "---" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "📚 **Resources:**" >> $GITHUB_STEP_SUMMARY - echo "- [MokoStandards Documentation](https://github.com/mokoconsulting-tech/MokoStandards)" >> $GITHUB_STEP_SUMMARY - echo "- [Repository Structure Guide](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/docs/policy/core-structure.md)" >> $GITHUB_STEP_SUMMARY - echo "- [Documentation Standards](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/docs/policy/document-formatting.md)" >> $GITHUB_STEP_SUMMARY - echo "- [Coding Standards](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/docs/policy/coding-style-guide.md)" >> $GITHUB_STEP_SUMMARY + echo "- [MokoCli Documentation](https://github.com/mokoconsulting-tech/MokoCli)" >> $GITHUB_STEP_SUMMARY + echo "- [Repository Structure Guide](https://github.com/mokoconsulting-tech/MokoCli/tree/main/docs/policy/core-structure.md)" >> $GITHUB_STEP_SUMMARY + echo "- [Documentation Standards](https://github.com/mokoconsulting-tech/MokoCli/tree/main/docs/policy/document-formatting.md)" >> $GITHUB_STEP_SUMMARY + echo "- [Coding Standards](https://github.com/mokoconsulting-tech/MokoCli/tree/main/docs/policy/coding-style-guide.md)" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "_Generated by MokoStandards Compliance Workflow v${WORKFLOW_VERSION}_" >> $GITHUB_STEP_SUMMARY + echo "_Generated by MokoCli Compliance Workflow v${WORKFLOW_VERSION}_" >> $GITHUB_STEP_SUMMARY # Create tracking issue for non-compliance if on push if [ "$COMPLIANCE_PERCENT" -lt 100 ] && [ "${{ github.event_name }}" = "push" ]; then @@ -2530,9 +2530,9 @@ jobs: echo "### ✅ Full Standards Compliance Achieved" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "**Overall Compliance:** 100%" >> $GITHUB_STEP_SUMMARY - echo "**Status:** Repository meets all MokoStandards requirements" >> $GITHUB_STEP_SUMMARY + echo "**Status:** Repository meets all MokoCli requirements" >> $GITHUB_STEP_SUMMARY echo "" - echo "✅ SUCCESS: Repository is fully MokoStandards compliant" + echo "✅ SUCCESS: Repository is fully MokoCli compliant" - name: Create or reopen tracking issue for standards violations if: failure() diff --git a/mcp/servers/mokossh/.mokogitea/workflows/sync-version-on-merge.yml b/mcp/servers/mokossh/.mokogitea/workflows/sync-version-on-merge.yml index dbdcd6c..a3238bd 100644 --- a/mcp/servers/mokossh/.mokogitea/workflows/sync-version-on-merge.yml +++ b/mcp/servers/mokossh/.mokogitea/workflows/sync-version-on-merge.yml @@ -6,8 +6,8 @@ # # FILE INFORMATION # DEFGROUP: GitHub.Workflow -# INGROUP: MokoStandards.Automation -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCli.Automation +# REPO: https://github.com/mokoconsulting-tech/MokoCli # PATH: /templates/workflows/shared/sync-version-on-merge.yml.template # VERSION: 04.06.00 # BRIEF: Auto-bump patch version on every push to main and propagate to all file headers @@ -53,13 +53,13 @@ jobs: php-version: '8.1' tools: composer - - name: Setup MokoStandards tools + - name: Setup MokoCli tools env: GH_TOKEN: ${{ secrets.GH_PAT || github.token }} COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_PAT || github.token }}"}}' run: | git clone --depth 1 --branch version/04 --quiet \ - "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \ + "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoCli.git" \ /tmp/mokostandards cd /tmp/mokostandards composer install --no-dev --no-interaction --quiet diff --git a/mcp/servers/mokossh/README.md b/mcp/servers/mokossh/README.md index 427dcbe..8b5c8d2 100644 --- a/mcp/servers/mokossh/README.md +++ b/mcp/servers/mokossh/README.md @@ -72,7 +72,7 @@ ssh-mcp exposes 37 tools that let Claude Code manage remote servers over SSH. Ca --- -> **[MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki)** -- central standards hub for all Moko Consulting projects. +> **[MokoCli](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki)** -- central standards hub for all Moko Consulting projects. --- @@ -94,4 +94,4 @@ This project is licensed under the GNU General Public License v3.0 or later -- s --- -*[Moko Consulting](https://mokoconsulting.tech) -- [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki/Home)* +*[Moko Consulting](https://mokoconsulting.tech) -- [MokoCli](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki/Home)* diff --git a/mcp/servers/mokosuite_api/.mokogitea/CLAUDE.md b/mcp/servers/mokosuite_api/.mokogitea/CLAUDE.md index 1838600..fec64a0 100644 --- a/mcp/servers/mokosuite_api/.mokogitea/CLAUDE.md +++ b/mcp/servers/mokosuite_api/.mokogitea/CLAUDE.md @@ -40,4 +40,4 @@ src/ - **Attribution**: `Authored-by: Moko Consulting` - **Workflow directory**: `.mokogitea/` (not `.gitea/` or `.github/`) - **Wiki**: documentation lives in the Gitea wiki, not `docs/` files -- **Standards**: [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki/Home) +- **Standards**: [MokoCli](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki/Home) diff --git a/mcp/servers/mokosuite_api/.mokogitea/ISSUE_TEMPLATE/config.yml b/mcp/servers/mokosuite_api/.mokogitea/ISSUE_TEMPLATE/config.yml index 7c403f1..14db946 100644 --- a/mcp/servers/mokosuite_api/.mokogitea/ISSUE_TEMPLATE/config.yml +++ b/mcp/servers/mokosuite_api/.mokogitea/ISSUE_TEMPLATE/config.yml @@ -7,7 +7,7 @@ contact_links: - name: 💬 Ask a Question url: https://mokoconsulting.tech/ about: Get help or ask questions through our website - - name: 📚 MokoStandards Documentation + - name: 📚 MokoCli Documentation url: https://git.mokoconsulting.tech/MokoConsulting/mokoplatform about: View our coding standards and best practices - name: 🔒 Report a Security Vulnerability diff --git a/mcp/servers/mokosuite_api/.mokogitea/ISSUE_TEMPLATE/documentation.md b/mcp/servers/mokosuite_api/.mokogitea/ISSUE_TEMPLATE/documentation.md index ed4dabc..96d4fbc 100644 --- a/mcp/servers/mokosuite_api/.mokogitea/ISSUE_TEMPLATE/documentation.md +++ b/mcp/servers/mokosuite_api/.mokogitea/ISSUE_TEMPLATE/documentation.md @@ -42,7 +42,7 @@ Suggested text here ## Standards Alignment -- [ ] Follows MokoStandards documentation guidelines +- [ ] Follows MokoCli documentation guidelines - [ ] Uses en_US/en_GB localization - [ ] Includes proper SPDX headers where applicable diff --git a/mcp/servers/mokosuite_api/.mokogitea/ISSUE_TEMPLATE/feature_request.md b/mcp/servers/mokosuite_api/.mokogitea/ISSUE_TEMPLATE/feature_request.md index 7b76dc9..6161deb 100644 --- a/mcp/servers/mokosuite_api/.mokogitea/ISSUE_TEMPLATE/feature_request.md +++ b/mcp/servers/mokosuite_api/.mokogitea/ISSUE_TEMPLATE/feature_request.md @@ -37,7 +37,7 @@ If you have ideas about how this could be implemented, share them here: Add any other context, mockups, or screenshots about the feature request here. ## Relevant Standards -Does this relate to any standards in [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/MokoStandards)? +Does this relate to any standards in [MokoCli](https://git.mokoconsulting.tech/MokoConsulting/MokoCli)? - [ ] Accessibility (WCAG 2.1 AA) - [ ] Localization (en_US/en_GB) - [ ] Security best practices diff --git a/mcp/servers/mokosuite_api/.mokogitea/ISSUE_TEMPLATE/security.md b/mcp/servers/mokosuite_api/.mokogitea/ISSUE_TEMPLATE/security.md index f57b284..69bae34 100644 --- a/mcp/servers/mokosuite_api/.mokogitea/ISSUE_TEMPLATE/security.md +++ b/mcp/servers/mokosuite_api/.mokogitea/ISSUE_TEMPLATE/security.md @@ -35,7 +35,7 @@ Use this template only for: ## Standards Reference -Does this relate to security standards in [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/MokoStandards)? +Does this relate to security standards in [MokoCli](https://git.mokoconsulting.tech/MokoConsulting/MokoCli)? - [ ] SPDX license identifiers - [ ] Secret management - [ ] Dependency security diff --git a/mcp/servers/mokosuite_api/.mokogitea/auto-assign.yml b/mcp/servers/mokosuite_api/.mokogitea/auto-assign.yml index c6fdd55..132ac0f 100644 --- a/mcp/servers/mokosuite_api/.mokogitea/auto-assign.yml +++ b/mcp/servers/mokosuite_api/.mokogitea/auto-assign.yml @@ -3,8 +3,8 @@ # # FILE INFORMATION # DEFGROUP: GitHub.Workflow -# INGROUP: MokoStandards.Workflows.Shared -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCli.Workflows.Shared +# REPO: https://github.com/mokoconsulting-tech/MokoCli # PATH: /.github/workflows/auto-assign.yml # VERSION: 04.06.00 # BRIEF: Auto-assign jmiller to unassigned issues and PRs every 15 minutes diff --git a/mcp/servers/mokosuite_api/.mokogitea/auto-dev-issue.yml b/mcp/servers/mokosuite_api/.mokogitea/auto-dev-issue.yml index 76a99fe..1b3e9a3 100644 --- a/mcp/servers/mokosuite_api/.mokogitea/auto-dev-issue.yml +++ b/mcp/servers/mokosuite_api/.mokogitea/auto-dev-issue.yml @@ -6,8 +6,8 @@ # # FILE INFORMATION # DEFGROUP: GitHub.Workflow -# INGROUP: MokoStandards.Automation -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCli.Automation +# REPO: https://github.com/mokoconsulting-tech/MokoCli # PATH: /templates/workflows/shared/auto-dev-issue.yml.template # VERSION: 04.06.00 # BRIEF: Auto-create tracking issue with sub-issues for dev/rc branch workflow diff --git a/mcp/servers/mokosuite_api/.mokogitea/auto-release.yml b/mcp/servers/mokosuite_api/.mokogitea/auto-release.yml index 0f0035e..f514d8f 100644 --- a/mcp/servers/mokosuite_api/.mokogitea/auto-release.yml +++ b/mcp/servers/mokosuite_api/.mokogitea/auto-release.yml @@ -4,8 +4,8 @@ # # FILE INFORMATION # DEFGROUP: GitHub.Workflow -# INGROUP: MokoStandards.Release -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCli.Release +# REPO: https://github.com/mokoconsulting-tech/MokoCli # PATH: /templates/workflows/shared/auto-release.yml.template # VERSION: 04.06.00 # BRIEF: Generic build & release pipeline — version branch, platform version, badges, tag, release @@ -62,13 +62,13 @@ jobs: token: ${{ secrets.GH_PAT || github.token }} fetch-depth: 0 - - name: Setup MokoStandards tools + - name: Setup MokoCli tools env: GH_TOKEN: ${{ secrets.GH_PAT || github.token }} COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_PAT || github.token }}"}}' run: | git clone --depth 1 --branch version/04 --quiet \ - "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \ + "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoCli.git" \ /tmp/mokostandards cd /tmp/mokostandards composer install --no-dev --no-interaction --quiet diff --git a/mcp/servers/mokosuite_api/.mokogitea/cascade-dev.yml b/mcp/servers/mokosuite_api/.mokogitea/cascade-dev.yml index 4fe707a..52fc38f 100644 --- a/mcp/servers/mokosuite_api/.mokogitea/cascade-dev.yml +++ b/mcp/servers/mokosuite_api/.mokogitea/cascade-dev.yml @@ -4,8 +4,8 @@ # # FILE INFORMATION # DEFGROUP: Gitea.Workflow -# INGROUP: MokoStandards.Maintenance -# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoStandards-API +# INGROUP: MokoCli.Maintenance +# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoCli-API # PATH: /templates/workflows/cascade-dev.yml.template # VERSION: 02.00.00 # BRIEF: Forward-merge main → all open branches after every push to main diff --git a/mcp/servers/mokosuite_api/.mokogitea/changelog-validation.yml b/mcp/servers/mokosuite_api/.mokogitea/changelog-validation.yml index e2ec667..039868c 100644 --- a/mcp/servers/mokosuite_api/.mokogitea/changelog-validation.yml +++ b/mcp/servers/mokosuite_api/.mokogitea/changelog-validation.yml @@ -6,8 +6,8 @@ # # FILE INFORMATION # DEFGROUP: GitHub.Workflow.Template -# INGROUP: MokoStandards.CI -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCli.CI +# REPO: https://github.com/mokoconsulting-tech/MokoCli # PATH: /templates/workflows/shared/changelog-validation.yml.template # VERSION: 04.06.00 # BRIEF: Validates CHANGELOG.md format and version consistency diff --git a/mcp/servers/mokosuite_api/.mokogitea/codeql-analysis.yml b/mcp/servers/mokosuite_api/.mokogitea/codeql-analysis.yml index 3abfb02..3b33fa1 100644 --- a/mcp/servers/mokosuite_api/.mokogitea/codeql-analysis.yml +++ b/mcp/servers/mokosuite_api/.mokogitea/codeql-analysis.yml @@ -6,8 +6,8 @@ # # FILE INFORMATION # DEFGROUP: GitHub.Workflow.Template -# INGROUP: MokoStandards.Security -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCli.Security +# REPO: https://github.com/mokoconsulting-tech/MokoCli # PATH: /templates/workflows/generic/codeql-analysis.yml.template # VERSION: 04.05.00 # BRIEF: CodeQL security scanning workflow (generic — all repo types) diff --git a/mcp/servers/mokosuite_api/.mokogitea/deploy-demo.yml b/mcp/servers/mokosuite_api/.mokogitea/deploy-demo.yml index f7ac035..6c39238 100644 --- a/mcp/servers/mokosuite_api/.mokogitea/deploy-demo.yml +++ b/mcp/servers/mokosuite_api/.mokogitea/deploy-demo.yml @@ -19,8 +19,8 @@ # # FILE INFORMATION # DEFGROUP: GitHub.Workflow -# INGROUP: MokoStandards.Deploy -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCli.Deploy +# REPO: https://github.com/mokoconsulting-tech/MokoCli # PATH: /templates/workflows/shared/deploy-demo.yml.template # VERSION: 04.06.00 # BRIEF: SFTP deployment workflow for demo server — synced to all governed repos @@ -418,14 +418,14 @@ jobs: php-version: '8.1' tools: composer - - name: Setup MokoStandards deploy tools + - name: Setup MokoCli deploy tools if: steps.source.outputs.skip == 'false' && steps.remote.outputs.skip != 'true' env: GH_TOKEN: ${{ secrets.GH_PAT || github.token }} COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_PAT || github.token }}"}}' run: | git clone --depth 1 --branch version/04 --quiet \ - "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \ + "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoCli.git" \ /tmp/mokostandards cd /tmp/mokostandards composer install --no-dev --no-interaction --quiet @@ -629,7 +629,7 @@ jobs: fi fi - # ── Run deploy-sftp.php from MokoStandards ──────────────────────────── + # ── Run deploy-sftp.php from MokoCli ──────────────────────────── DEPLOY_ARGS=(--path . --src-dir "$SOURCE_DIR" --config /tmp/sftp-config.json) if [ "$USE_PASSPHRASE" = "true" ]; then DEPLOY_ARGS+=(--key-passphrase "$SFTP_PASSWORD") diff --git a/mcp/servers/mokosuite_api/.mokogitea/deploy-dev.yml b/mcp/servers/mokosuite_api/.mokogitea/deploy-dev.yml index ddd9a08..abe3598 100644 --- a/mcp/servers/mokosuite_api/.mokogitea/deploy-dev.yml +++ b/mcp/servers/mokosuite_api/.mokogitea/deploy-dev.yml @@ -19,8 +19,8 @@ # # FILE INFORMATION # DEFGROUP: GitHub.Workflow -# INGROUP: MokoStandards.Deploy -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCli.Deploy +# REPO: https://github.com/mokoconsulting-tech/MokoCli # PATH: /templates/workflows/shared/deploy-dev.yml.template # VERSION: 04.06.00 # BRIEF: SFTP deployment workflow for development server — synced to all governed repos @@ -418,14 +418,14 @@ jobs: php-version: '8.1' tools: composer - - name: Setup MokoStandards deploy tools + - name: Setup MokoCli deploy tools if: steps.source.outputs.skip == 'false' && steps.remote.outputs.skip != 'true' env: GH_TOKEN: ${{ secrets.GH_PAT || github.token }} COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_PAT || github.token }}"}}' run: | git clone --depth 1 --branch version/04 --quiet \ - "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \ + "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoCli.git" \ /tmp/mokostandards cd /tmp/mokostandards composer install --no-dev --no-interaction --quiet @@ -579,7 +579,7 @@ jobs: echo "*.min.js" >> "${SOURCE_DIR}/.ftpignore" echo "*.min.css" >> "${SOURCE_DIR}/.ftpignore" - # ── Run deploy-sftp.php from MokoStandards ──────────────────────────── + # ── Run deploy-sftp.php from MokoCli ──────────────────────────── DEPLOY_ARGS=(--path . --src-dir "$SOURCE_DIR" --config /tmp/sftp-config.json) if [ "$USE_PASSPHRASE" = "true" ]; then DEPLOY_ARGS+=(--key-passphrase "$SFTP_PASSWORD") diff --git a/mcp/servers/mokosuite_api/.mokogitea/enterprise-firewall-setup.yml b/mcp/servers/mokosuite_api/.mokogitea/enterprise-firewall-setup.yml index 1a533fb..23e0ec9 100644 --- a/mcp/servers/mokosuite_api/.mokogitea/enterprise-firewall-setup.yml +++ b/mcp/servers/mokosuite_api/.mokogitea/enterprise-firewall-setup.yml @@ -19,8 +19,8 @@ # FILE INFORMATION # DEFGROUP: GitHub.Workflow -# INGROUP: MokoStandards.Firewall -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCli.Firewall +# REPO: https://github.com/mokoconsulting-tech/MokoCli # PATH: /templates/workflows/shared/enterprise-firewall-setup.yml.template # VERSION: 04.06.00 # BRIEF: Enterprise firewall configuration — generates outbound allow-rules including SFTP deployment server diff --git a/mcp/servers/mokosuite_api/.mokogitea/gitleaks.yml b/mcp/servers/mokosuite_api/.mokogitea/gitleaks.yml index b29f881..f95b1ad 100644 --- a/mcp/servers/mokosuite_api/.mokogitea/gitleaks.yml +++ b/mcp/servers/mokosuite_api/.mokogitea/gitleaks.yml @@ -4,8 +4,8 @@ # # FILE INFORMATION # DEFGROUP: Gitea.Workflow -# INGROUP: MokoStandards.Security -# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoStandards-API +# INGROUP: MokoCli.Security +# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoCli-API # PATH: /templates/workflows/gitleaks.yml.template # VERSION: 01.00.00 # BRIEF: Secret scanning — detect leaked credentials, API keys, and tokens diff --git a/mcp/servers/mokosuite_api/.mokogitea/manifest.xml b/mcp/servers/mokosuite_api/.mokogitea/manifest.xml index e5a63dd..6c0bebc 100644 --- a/mcp/servers/mokosuite_api/.mokogitea/manifest.xml +++ b/mcp/servers/mokosuite_api/.mokogitea/manifest.xml @@ -1,6 +1,6 @@ diff --git a/mcp/servers/mokosuite_api/.mokogitea/mcp-auto-release.yml b/mcp/servers/mokosuite_api/.mokogitea/mcp-auto-release.yml index f067a94..921359d 100644 --- a/mcp/servers/mokosuite_api/.mokogitea/mcp-auto-release.yml +++ b/mcp/servers/mokosuite_api/.mokogitea/mcp-auto-release.yml @@ -87,13 +87,13 @@ jobs: done # ── Version ────────────────────────────────────────────────────── - - name: Setup MokoStandards tools + - name: Setup MokoCli tools env: GH_TOKEN: ${{ secrets.GH_PAT || github.token }} COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_PAT || github.token }}"}}' run: | git clone --depth 1 --branch version/04 --quiet \ - "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \ + "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoCli.git" \ /tmp/mokostandards cd /tmp/mokostandards composer install --no-dev --no-interaction --quiet diff --git a/mcp/servers/mokosuite_api/.mokogitea/repository-cleanup.yml b/mcp/servers/mokosuite_api/.mokogitea/repository-cleanup.yml index ac61c33..521b01c 100644 --- a/mcp/servers/mokosuite_api/.mokogitea/repository-cleanup.yml +++ b/mcp/servers/mokosuite_api/.mokogitea/repository-cleanup.yml @@ -6,8 +6,8 @@ # # FILE INFORMATION # DEFGROUP: GitHub.Workflow -# INGROUP: MokoStandards.Maintenance -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCli.Maintenance +# REPO: https://github.com/mokoconsulting-tech/MokoCli # PATH: /templates/workflows/shared/repository-cleanup.yml.template # VERSION: 04.06.00 # BRIEF: Recurring repository maintenance — labels, branches, workflows, logs, doc indexes @@ -220,7 +220,7 @@ jobs: config|F9D0C4|Configuration file changes build|FFA500|Build system changes automation|8B4513|Automated processes or scripts - mokostandards|B60205|MokoStandards compliance + mokostandards|B60205|MokoCli compliance needs-review|FBCA04|Awaiting code review work-in-progress|D93F0B|Work in progress, not ready for merge breaking-change|D73A4A|Breaking API or functionality change @@ -249,8 +249,8 @@ jobs: health: good|FBCA04|Health score 70-89 health: fair|FFA500|Health score 50-69 health: poor|FF6B6B|Health score below 50 - standards-update|B60205|MokoStandards sync update - standards-drift|FBCA04|Repository drifted from MokoStandards + standards-update|B60205|MokoCli sync update + standards-drift|FBCA04|Repository drifted from MokoCli sync-report|0075CA|Bulk sync run report sync-failure|D73A4A|Bulk sync failure requiring attention push-failure|D73A4A|File push failure requiring attention @@ -469,7 +469,7 @@ jobs: # Custom Workflows Place repo-specific workflows here. Files in this directory are: - - **Never overwritten** by MokoStandards bulk sync + - **Never overwritten** by MokoCli bulk sync - **Never deleted** by the repository-cleanup workflow - Safe for custom CI, notifications, or repo-specific automation diff --git a/mcp/servers/mokosuite_api/.mokogitea/standards-compliance.yml b/mcp/servers/mokosuite_api/.mokogitea/standards-compliance.yml index 4b22054..847663c 100644 --- a/mcp/servers/mokosuite_api/.mokogitea/standards-compliance.yml +++ b/mcp/servers/mokosuite_api/.mokogitea/standards-compliance.yml @@ -2,11 +2,11 @@ # SPDX-License-Identifier: GPL-3.0-or-later # FILE INFORMATION # DEFGROUP: GitHub.Workflow -# INGROUP: MokoStandards.Compliance -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCli.Compliance +# REPO: https://github.com/mokoconsulting-tech/MokoCli # PATH: /.github/workflows/standards-compliance.yml # VERSION: 04.06.00 -# BRIEF: MokoStandards compliance validation workflow +# BRIEF: MokoCli compliance validation workflow # NOTE: Validates repository structure, documentation, and coding standards name: Standards Compliance @@ -42,7 +42,7 @@ env: WORKFLOW_VERSION: "04.04.01" FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true -# MokoStandards Policy Compliance: +# MokoCli Policy Compliance: # - File formatting: Enforces organizational coding standards # - Reference: docs/policy/file-formatting.md @@ -252,7 +252,7 @@ jobs: echo "" >> $GITHUB_STEP_SUMMARY echo "### ❌ Validation Failed: LICENSE File Missing" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**Error:** LICENSE file is required for all MokoStandards-compliant repositories" >> $GITHUB_STEP_SUMMARY + echo "**Error:** LICENSE file is required for all MokoCli-compliant repositories" >> $GITHUB_STEP_SUMMARY echo "**Action Required:** Add LICENSE file with appropriate open-source license (GPL-3.0-or-later recommended)" >> $GITHUB_STEP_SUMMARY echo "" echo "❌ ERROR: LICENSE file not found - This is a critical requirement" @@ -323,11 +323,11 @@ jobs: [ ! -d "docs" ] && echo "- Create docs directory: \`mkdir docs && echo '# Documentation' > docs/README.md\`" >> $GITHUB_STEP_SUMMARY [ ! -d ".github" ] && echo "- Create .github directory: \`mkdir -p .github/workflows\`" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "📚 Reference: [MokoStandards Repository Structure](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/docs/policy/core-structure.md)" >> $GITHUB_STEP_SUMMARY + echo "📚 Reference: [MokoCli Repository Structure](https://github.com/mokoconsulting-tech/MokoCli/tree/main/docs/policy/core-structure.md)" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "### ❌ Validation Failed: Required Directories Missing" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**Status:** Repository structure does not meet MokoStandards requirements" >> $GITHUB_STEP_SUMMARY + echo "**Status:** Repository structure does not meet MokoCli requirements" >> $GITHUB_STEP_SUMMARY echo "**Missing:** $MISSING required director(y|ies)" >> $GITHUB_STEP_SUMMARY echo "**Compliance:** $PERCENT% ($PRESENT/$TOTAL directories present)" >> $GITHUB_STEP_SUMMARY echo "" @@ -384,17 +384,17 @@ jobs: echo "### 🔴 Critical Issues: $MISSING" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "**Remediation Steps:**" >> $GITHUB_STEP_SUMMARY - [ ! -f "README.md" ] && echo "- Create README.md: Use [template](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/templates/docs/required/README.md)" >> $GITHUB_STEP_SUMMARY + [ ! -f "README.md" ] && echo "- Create README.md: Use [template](https://github.com/mokoconsulting-tech/MokoCli/tree/main/templates/docs/required/README.md)" >> $GITHUB_STEP_SUMMARY [ ! -f "LICENSE" ] && echo "- Add LICENSE file: Choose from [OSI-approved licenses](https://opensource.org/licenses)" >> $GITHUB_STEP_SUMMARY - [ ! -f "CONTRIBUTING.md" ] && echo "- Create CONTRIBUTING.md: Use [template](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/templates/docs/required/CONTRIBUTING.md)" >> $GITHUB_STEP_SUMMARY - [ ! -f "SECURITY.md" ] && echo "- Create SECURITY.md: Use [template](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/templates/docs/required/SECURITY.md)" >> $GITHUB_STEP_SUMMARY - [ ! -f ".editorconfig" ] && echo "- Add .editorconfig: Use [template](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/templates/.editorconfig)" >> $GITHUB_STEP_SUMMARY + [ ! -f "CONTRIBUTING.md" ] && echo "- Create CONTRIBUTING.md: Use [template](https://github.com/mokoconsulting-tech/MokoCli/tree/main/templates/docs/required/CONTRIBUTING.md)" >> $GITHUB_STEP_SUMMARY + [ ! -f "SECURITY.md" ] && echo "- Create SECURITY.md: Use [template](https://github.com/mokoconsulting-tech/MokoCli/tree/main/templates/docs/required/SECURITY.md)" >> $GITHUB_STEP_SUMMARY + [ ! -f ".editorconfig" ] && echo "- Add .editorconfig: Use [template](https://github.com/mokoconsulting-tech/MokoCli/tree/main/templates/.editorconfig)" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "📚 Reference: [MokoStandards File Requirements](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/docs/policy/file-header-standards.md)" >> $GITHUB_STEP_SUMMARY + echo "📚 Reference: [MokoCli File Requirements](https://github.com/mokoconsulting-tech/MokoCli/tree/main/docs/policy/file-header-standards.md)" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "### ❌ Validation Failed: Required Files Missing" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**Status:** Repository files do not meet MokoStandards requirements" >> $GITHUB_STEP_SUMMARY + echo "**Status:** Repository files do not meet MokoCli requirements" >> $GITHUB_STEP_SUMMARY echo "**Missing:** $MISSING required file(s)" >> $GITHUB_STEP_SUMMARY echo "**Compliance:** $PERCENT% ($PRESENT/$TOTAL files present)" >> $GITHUB_STEP_SUMMARY echo "" @@ -437,7 +437,7 @@ jobs: echo "$TABS_IN_SPACES_FILES" >> $GITHUB_STEP_SUMMARY echo "\`\`\`" >> $GITHUB_STEP_SUMMARY echo "These languages require spaces (tabs will break): YAML, Python, Haskell, F#, CoffeeScript, Nim, JSON, RST" >> $GITHUB_STEP_SUMMARY - echo "All other files (including .md, .ps1, LICENSE, etc.) may use tabs per MokoStandards policy" >> $GITHUB_STEP_SUMMARY + echo "All other files (including .md, .ps1, LICENSE, etc.) may use tabs per MokoCli policy" >> $GITHUB_STEP_SUMMARY else echo "✅ No tabs found in files requiring spaces" >> $GITHUB_STEP_SUMMARY echo "Note: Tabs are allowed in most files (policy default). Only checked files requiring spaces." >> $GITHUB_STEP_SUMMARY @@ -483,7 +483,7 @@ jobs: echo "\`\`\`" >> $GITHUB_STEP_SUMMARY echo "$CRLF_FILES" >> $GITHUB_STEP_SUMMARY echo "\`\`\`" >> $GITHUB_STEP_SUMMARY - echo "MokoStandards requires LF line endings" >> $GITHUB_STEP_SUMMARY + echo "MokoCli requires LF line endings" >> $GITHUB_STEP_SUMMARY else echo "✅ Line endings are consistent (LF)" >> $GITHUB_STEP_SUMMARY fi @@ -504,13 +504,13 @@ jobs: tools: composer coverage: none - - name: Setup MokoStandards tools + - name: Setup MokoCli tools env: GH_TOKEN: ${{ secrets.GH_PAT || github.token }} COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_PAT || github.token }}"}}' run: | git clone --depth 1 --branch version/04 --quiet \ - "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \ + "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoCli.git" \ /tmp/mokostandards 2>/dev/null || true if [ -d "/tmp/mokostandards" ] && [ -f "/tmp/mokostandards/composer.json" ]; then cd /tmp/mokostandards @@ -524,7 +524,7 @@ jobs: echo "## 🔢 Version Consistency Validation" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - # Use MokoStandards tools (no Composer needed on the governed repo) + # Use MokoCli tools (no Composer needed on the governed repo) if [ -f "/tmp/mokostandards/api/validate/check_version_consistency.php" ]; then php /tmp/mokostandards/api/validate/check_version_consistency.php --path . --verbose 2>&1 | tee /tmp/version-check.log EXIT_CODE=${PIPESTATUS[0]} @@ -532,7 +532,7 @@ jobs: php api/validate/check_version_consistency.php --path . --verbose 2>&1 | tee /tmp/version-check.log EXIT_CODE=${PIPESTATUS[0]} else - echo "⏭️ MokoStandards tools not available — skipping version check" >> $GITHUB_STEP_SUMMARY + echo "⏭️ MokoCli tools not available — skipping version check" >> $GITHUB_STEP_SUMMARY exit 0 fi @@ -597,12 +597,12 @@ jobs: echo "⚠️ CodeQL workflow not found" >> $GITHUB_STEP_SUMMARY fi - # Check for MokoStandards-synced workflows + # Check for MokoCli-synced workflows for wf in deploy-dev.yml deploy-demo.yml deploy-rs.yml sync-version-on-merge.yml auto-release.yml standards-compliance.yml enterprise-firewall-setup.yml; do if [ -f "$WORKFLOWS_DIR/$wf" ]; then echo "✅ ${wf}" >> $GITHUB_STEP_SUMMARY else - echo "⚠️ ${wf} not found (synced from MokoStandards)" >> $GITHUB_STEP_SUMMARY + echo "⚠️ ${wf} not found (synced from MokoCli)" >> $GITHUB_STEP_SUMMARY fi done @@ -809,7 +809,7 @@ jobs: echo "" >> $GITHUB_STEP_SUMMARY echo "### ❌ Validation Failed: README.md Missing" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**Error:** README.md is required for all MokoStandards-compliant repositories" >> $GITHUB_STEP_SUMMARY + echo "**Error:** README.md is required for all MokoCli-compliant repositories" >> $GITHUB_STEP_SUMMARY echo "**Action Required:** Create README.md with project description, setup instructions, and usage examples" >> $GITHUB_STEP_SUMMARY echo "" echo "❌ ERROR: README.md not found - This is a critical requirement" @@ -915,7 +915,7 @@ jobs: echo "" >> $GITHUB_STEP_SUMMARY echo "### ❌ Validation Failed: CHANGELOG.md Missing" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**Error:** CHANGELOG.md is required for all MokoStandards-compliant repositories" >> $GITHUB_STEP_SUMMARY + echo "**Error:** CHANGELOG.md is required for all MokoCli-compliant repositories" >> $GITHUB_STEP_SUMMARY echo "**Action Required:** Create CHANGELOG.md following [Keep a Changelog](https://keepachangelog.com/) format" >> $GITHUB_STEP_SUMMARY echo "" echo "❌ ERROR: CHANGELOG.md not found - This is a critical requirement" @@ -1976,10 +1976,10 @@ jobs: if [ -f "composer.json" ]; then composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader else - echo "No composer.json — pulling MokoStandards tools" + echo "No composer.json — pulling MokoCli tools" if [ ! -d "/tmp/mokostandards" ]; then git clone --depth 1 --branch version/04 --quiet \ - "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \ + "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoCli.git" \ /tmp/mokostandards 2>/dev/null || true if [ -f "/tmp/mokostandards/composer.json" ]; then cd /tmp/mokostandards && composer install --no-dev --no-interaction --quiet 2>/dev/null || true @@ -2048,10 +2048,10 @@ jobs: if [ -f "composer.json" ]; then composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader else - echo "No composer.json — pulling MokoStandards tools" + echo "No composer.json — pulling MokoCli tools" if [ ! -d "/tmp/mokostandards" ]; then git clone --depth 1 --branch version/04 --quiet \ - "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \ + "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoCli.git" \ /tmp/mokostandards 2>/dev/null || true if [ -f "/tmp/mokostandards/composer.json" ]; then cd /tmp/mokostandards && composer install --no-dev --no-interaction --quiet 2>/dev/null || true @@ -2133,7 +2133,7 @@ jobs: # 1. Check .github/config.tf location (not root override files) echo "### Override Configuration Check" >> $GITHUB_STEP_SUMMARY - LEGACY_OVERRIDES=$(find . -maxdepth 1 -name "*override*.tf" -o -name "MokoStandards.override.tf" 2>/dev/null | wc -l || echo 0) + LEGACY_OVERRIDES=$(find . -maxdepth 1 -name "*override*.tf" -o -name "MokoCli.override.tf" 2>/dev/null | wc -l || echo 0) if [ "$LEGACY_OVERRIDES" -gt 0 ]; then echo "⚠️ Found legacy override files in root directory" >> $GITHUB_STEP_SUMMARY echo "**Expected Location**: .github/config.tf" >> $GITHUB_STEP_SUMMARY @@ -2299,7 +2299,7 @@ jobs: - name: Generate Compliance Report run: | set -x - echo "# 📊 MokoStandards Compliance Report" >> $GITHUB_STEP_SUMMARY + echo "# 📊 MokoCli Compliance Report" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY # Calculate overall status @@ -2486,7 +2486,7 @@ jobs: else echo "## 🎉 Excellent!" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "Your repository is **fully compliant** with MokoStandards!" >> $GITHUB_STEP_SUMMARY + echo "Your repository is **fully compliant** with MokoCli!" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "**Achievements:**" >> $GITHUB_STEP_SUMMARY echo "- ✅ All required directories and files present" >> $GITHUB_STEP_SUMMARY @@ -2501,12 +2501,12 @@ jobs: echo "---" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "📚 **Resources:**" >> $GITHUB_STEP_SUMMARY - echo "- [MokoStandards Documentation](https://github.com/mokoconsulting-tech/MokoStandards)" >> $GITHUB_STEP_SUMMARY - echo "- [Repository Structure Guide](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/docs/policy/core-structure.md)" >> $GITHUB_STEP_SUMMARY - echo "- [Documentation Standards](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/docs/policy/document-formatting.md)" >> $GITHUB_STEP_SUMMARY - echo "- [Coding Standards](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/docs/policy/coding-style-guide.md)" >> $GITHUB_STEP_SUMMARY + echo "- [MokoCli Documentation](https://github.com/mokoconsulting-tech/MokoCli)" >> $GITHUB_STEP_SUMMARY + echo "- [Repository Structure Guide](https://github.com/mokoconsulting-tech/MokoCli/tree/main/docs/policy/core-structure.md)" >> $GITHUB_STEP_SUMMARY + echo "- [Documentation Standards](https://github.com/mokoconsulting-tech/MokoCli/tree/main/docs/policy/document-formatting.md)" >> $GITHUB_STEP_SUMMARY + echo "- [Coding Standards](https://github.com/mokoconsulting-tech/MokoCli/tree/main/docs/policy/coding-style-guide.md)" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "_Generated by MokoStandards Compliance Workflow v${WORKFLOW_VERSION}_" >> $GITHUB_STEP_SUMMARY + echo "_Generated by MokoCli Compliance Workflow v${WORKFLOW_VERSION}_" >> $GITHUB_STEP_SUMMARY # Create tracking issue for non-compliance if on push if [ "$COMPLIANCE_PERCENT" -lt 100 ] && [ "${{ github.event_name }}" = "push" ]; then @@ -2530,9 +2530,9 @@ jobs: echo "### ✅ Full Standards Compliance Achieved" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "**Overall Compliance:** 100%" >> $GITHUB_STEP_SUMMARY - echo "**Status:** Repository meets all MokoStandards requirements" >> $GITHUB_STEP_SUMMARY + echo "**Status:** Repository meets all MokoCli requirements" >> $GITHUB_STEP_SUMMARY echo "" - echo "✅ SUCCESS: Repository is fully MokoStandards compliant" + echo "✅ SUCCESS: Repository is fully MokoCli compliant" - name: Create or reopen tracking issue for standards violations if: failure() diff --git a/mcp/servers/mokosuite_api/.mokogitea/sync-version-on-merge.yml b/mcp/servers/mokosuite_api/.mokogitea/sync-version-on-merge.yml index dbf32bd..093bf7e 100644 --- a/mcp/servers/mokosuite_api/.mokogitea/sync-version-on-merge.yml +++ b/mcp/servers/mokosuite_api/.mokogitea/sync-version-on-merge.yml @@ -6,8 +6,8 @@ # # FILE INFORMATION # DEFGROUP: GitHub.Workflow -# INGROUP: MokoStandards.Automation -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCli.Automation +# REPO: https://github.com/mokoconsulting-tech/MokoCli # PATH: /templates/workflows/shared/sync-version-on-merge.yml.template # VERSION: 04.06.00 # BRIEF: Auto-bump patch version on every push to main and propagate to all file headers @@ -53,13 +53,13 @@ jobs: php-version: '8.1' tools: composer - - name: Setup MokoStandards tools + - name: Setup MokoCli tools env: GH_TOKEN: ${{ secrets.GH_PAT || github.token }} COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_PAT || github.token }}"}}' run: | git clone --depth 1 --branch version/04 --quiet \ - "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \ + "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoCli.git" \ /tmp/mokostandards cd /tmp/mokostandards composer install --no-dev --no-interaction --quiet diff --git a/mcp/servers/mokosuite_api/.mokogitea/workflows/auto-assign.yml b/mcp/servers/mokosuite_api/.mokogitea/workflows/auto-assign.yml index c0f538f..ab7f573 100644 --- a/mcp/servers/mokosuite_api/.mokogitea/workflows/auto-assign.yml +++ b/mcp/servers/mokosuite_api/.mokogitea/workflows/auto-assign.yml @@ -3,8 +3,8 @@ # # FILE INFORMATION # DEFGROUP: GitHub.Workflow -# INGROUP: MokoStandards.Workflows.Shared -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCli.Workflows.Shared +# REPO: https://github.com/mokoconsulting-tech/MokoCli # PATH: /.mokogitea/workflows/auto-assign.yml # VERSION: 04.06.00 # BRIEF: Auto-assign jmiller to unassigned issues and PRs every 15 minutes diff --git a/mcp/servers/mokosuite_api/.mokogitea/workflows/auto-dev-issue.yml b/mcp/servers/mokosuite_api/.mokogitea/workflows/auto-dev-issue.yml index bdd7db7..a8774ab 100644 --- a/mcp/servers/mokosuite_api/.mokogitea/workflows/auto-dev-issue.yml +++ b/mcp/servers/mokosuite_api/.mokogitea/workflows/auto-dev-issue.yml @@ -6,8 +6,8 @@ # # FILE INFORMATION # DEFGROUP: GitHub.Workflow -# INGROUP: MokoStandards.Automation -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCli.Automation +# REPO: https://github.com/mokoconsulting-tech/MokoCli # PATH: /templates/workflows/shared/auto-dev-issue.yml.template # VERSION: 04.06.00 # BRIEF: Auto-create tracking issue with sub-issues for dev/rc branch workflow diff --git a/mcp/servers/mokosuite_api/.mokogitea/workflows/changelog-validation.yml b/mcp/servers/mokosuite_api/.mokogitea/workflows/changelog-validation.yml index 0601d2f..f104937 100644 --- a/mcp/servers/mokosuite_api/.mokogitea/workflows/changelog-validation.yml +++ b/mcp/servers/mokosuite_api/.mokogitea/workflows/changelog-validation.yml @@ -6,8 +6,8 @@ # # FILE INFORMATION # DEFGROUP: GitHub.Workflow.Template -# INGROUP: MokoStandards.CI -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCli.CI +# REPO: https://github.com/mokoconsulting-tech/MokoCli # PATH: /templates/workflows/shared/changelog-validation.yml.template # VERSION: 04.06.00 # BRIEF: Validates CHANGELOG.md format and version consistency diff --git a/mcp/servers/mokosuite_api/.mokogitea/workflows/codeql-analysis.yml b/mcp/servers/mokosuite_api/.mokogitea/workflows/codeql-analysis.yml index dd61fc3..0e4c735 100644 --- a/mcp/servers/mokosuite_api/.mokogitea/workflows/codeql-analysis.yml +++ b/mcp/servers/mokosuite_api/.mokogitea/workflows/codeql-analysis.yml @@ -6,8 +6,8 @@ # # FILE INFORMATION # DEFGROUP: GitHub.Workflow.Template -# INGROUP: MokoStandards.Security -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCli.Security +# REPO: https://github.com/mokoconsulting-tech/MokoCli # PATH: /templates/workflows/generic/codeql-analysis.yml.template # VERSION: 04.05.00 # BRIEF: CodeQL security scanning workflow (generic — all repo types) diff --git a/mcp/servers/mokosuite_api/.mokogitea/workflows/enterprise-firewall-setup.yml b/mcp/servers/mokosuite_api/.mokogitea/workflows/enterprise-firewall-setup.yml index 81866f2..af361ef 100644 --- a/mcp/servers/mokosuite_api/.mokogitea/workflows/enterprise-firewall-setup.yml +++ b/mcp/servers/mokosuite_api/.mokogitea/workflows/enterprise-firewall-setup.yml @@ -19,8 +19,8 @@ # FILE INFORMATION # DEFGROUP: GitHub.Workflow -# INGROUP: MokoStandards.Firewall -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCli.Firewall +# REPO: https://github.com/mokoconsulting-tech/MokoCli # PATH: /templates/workflows/shared/enterprise-firewall-setup.yml.template # VERSION: 04.06.00 # BRIEF: Enterprise firewall configuration — generates outbound allow-rules including SFTP deployment server diff --git a/mcp/servers/mokosuite_api/.mokogitea/workflows/mcp-auto-release.yml b/mcp/servers/mokosuite_api/.mokogitea/workflows/mcp-auto-release.yml index d3ef2ef..f4153ed 100644 --- a/mcp/servers/mokosuite_api/.mokogitea/workflows/mcp-auto-release.yml +++ b/mcp/servers/mokosuite_api/.mokogitea/workflows/mcp-auto-release.yml @@ -87,13 +87,13 @@ jobs: done # ── Version ────────────────────────────────────────────────────── - - name: Setup MokoStandards tools + - name: Setup MokoCli tools env: GH_TOKEN: ${{ secrets.GH_PAT || github.token }} COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_PAT || github.token }}"}}' run: | git clone --depth 1 --branch version/04 --quiet \ - "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \ + "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoCli.git" \ /tmp/mokostandards cd /tmp/mokostandards composer install --no-dev --no-interaction --quiet diff --git a/mcp/servers/mokosuite_api/.mokogitea/workflows/repository-cleanup.yml b/mcp/servers/mokosuite_api/.mokogitea/workflows/repository-cleanup.yml index bb90e00..0468b17 100644 --- a/mcp/servers/mokosuite_api/.mokogitea/workflows/repository-cleanup.yml +++ b/mcp/servers/mokosuite_api/.mokogitea/workflows/repository-cleanup.yml @@ -6,8 +6,8 @@ # # FILE INFORMATION # DEFGROUP: GitHub.Workflow -# INGROUP: MokoStandards.Maintenance -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCli.Maintenance +# REPO: https://github.com/mokoconsulting-tech/MokoCli # PATH: /templates/workflows/shared/repository-cleanup.yml.template # VERSION: 04.06.00 # BRIEF: Recurring repository maintenance — labels, branches, workflows, logs, doc indexes @@ -220,7 +220,7 @@ jobs: config|F9D0C4|Configuration file changes build|FFA500|Build system changes automation|8B4513|Automated processes or scripts - mokostandards|B60205|MokoStandards compliance + mokostandards|B60205|MokoCli compliance needs-review|FBCA04|Awaiting code review work-in-progress|D93F0B|Work in progress, not ready for merge breaking-change|D73A4A|Breaking API or functionality change @@ -249,8 +249,8 @@ jobs: health: good|FBCA04|Health score 70-89 health: fair|FFA500|Health score 50-69 health: poor|FF6B6B|Health score below 50 - standards-update|B60205|MokoStandards sync update - standards-drift|FBCA04|Repository drifted from MokoStandards + standards-update|B60205|MokoCli sync update + standards-drift|FBCA04|Repository drifted from MokoCli sync-report|0075CA|Bulk sync run report sync-failure|D73A4A|Bulk sync failure requiring attention push-failure|D73A4A|File push failure requiring attention @@ -469,7 +469,7 @@ jobs: # Custom Workflows Place repo-specific workflows here. Files in this directory are: - - **Never overwritten** by MokoStandards bulk sync + - **Never overwritten** by MokoCli bulk sync - **Never deleted** by the repository-cleanup workflow - Safe for custom CI, notifications, or repo-specific automation diff --git a/mcp/servers/mokosuite_api/.mokogitea/workflows/standards-compliance.yml b/mcp/servers/mokosuite_api/.mokogitea/workflows/standards-compliance.yml index 1927cb0..7774161 100644 --- a/mcp/servers/mokosuite_api/.mokogitea/workflows/standards-compliance.yml +++ b/mcp/servers/mokosuite_api/.mokogitea/workflows/standards-compliance.yml @@ -2,11 +2,11 @@ # SPDX-License-Identifier: GPL-3.0-or-later # FILE INFORMATION # DEFGROUP: GitHub.Workflow -# INGROUP: MokoStandards.Compliance -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCli.Compliance +# REPO: https://github.com/mokoconsulting-tech/MokoCli # PATH: /.mokogitea/workflows/standards-compliance.yml # VERSION: 04.06.00 -# BRIEF: MokoStandards compliance validation workflow +# BRIEF: MokoCli compliance validation workflow # NOTE: Validates repository structure, documentation, and coding standards name: "MCP: Standards Compliance" @@ -42,7 +42,7 @@ env: WORKFLOW_VERSION: "04.04.01" FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true -# MokoStandards Policy Compliance: +# MokoCli Policy Compliance: # - File formatting: Enforces organizational coding standards # - Reference: docs/policy/file-formatting.md @@ -252,7 +252,7 @@ jobs: echo "" >> $GITHUB_STEP_SUMMARY echo "### ❌ Validation Failed: LICENSE File Missing" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**Error:** LICENSE file is required for all MokoStandards-compliant repositories" >> $GITHUB_STEP_SUMMARY + echo "**Error:** LICENSE file is required for all MokoCli-compliant repositories" >> $GITHUB_STEP_SUMMARY echo "**Action Required:** Add LICENSE file with appropriate open-source license (GPL-3.0-or-later recommended)" >> $GITHUB_STEP_SUMMARY echo "" echo "❌ ERROR: LICENSE file not found - This is a critical requirement" @@ -323,11 +323,11 @@ jobs: [ ! -d "docs" ] && echo "- Create docs directory: \`mkdir docs && echo '# Documentation' > docs/README.md\`" >> $GITHUB_STEP_SUMMARY [ ! -d ".github" ] && echo "- Create .github directory: \`mkdir -p .github/workflows\`" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "📚 Reference: [MokoStandards Repository Structure](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/docs/policy/core-structure.md)" >> $GITHUB_STEP_SUMMARY + echo "📚 Reference: [MokoCli Repository Structure](https://github.com/mokoconsulting-tech/MokoCli/tree/main/docs/policy/core-structure.md)" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "### ❌ Validation Failed: Required Directories Missing" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**Status:** Repository structure does not meet MokoStandards requirements" >> $GITHUB_STEP_SUMMARY + echo "**Status:** Repository structure does not meet MokoCli requirements" >> $GITHUB_STEP_SUMMARY echo "**Missing:** $MISSING required director(y|ies)" >> $GITHUB_STEP_SUMMARY echo "**Compliance:** $PERCENT% ($PRESENT/$TOTAL directories present)" >> $GITHUB_STEP_SUMMARY echo "" @@ -384,17 +384,17 @@ jobs: echo "### 🔴 Critical Issues: $MISSING" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "**Remediation Steps:**" >> $GITHUB_STEP_SUMMARY - [ ! -f "README.md" ] && echo "- Create README.md: Use [template](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/templates/docs/required/README.md)" >> $GITHUB_STEP_SUMMARY + [ ! -f "README.md" ] && echo "- Create README.md: Use [template](https://github.com/mokoconsulting-tech/MokoCli/tree/main/templates/docs/required/README.md)" >> $GITHUB_STEP_SUMMARY [ ! -f "LICENSE" ] && echo "- Add LICENSE file: Choose from [OSI-approved licenses](https://opensource.org/licenses)" >> $GITHUB_STEP_SUMMARY - [ ! -f "CONTRIBUTING.md" ] && echo "- Create CONTRIBUTING.md: Use [template](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/templates/docs/required/CONTRIBUTING.md)" >> $GITHUB_STEP_SUMMARY - [ ! -f "SECURITY.md" ] && echo "- Create SECURITY.md: Use [template](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/templates/docs/required/SECURITY.md)" >> $GITHUB_STEP_SUMMARY - [ ! -f ".editorconfig" ] && echo "- Add .editorconfig: Use [template](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/templates/.editorconfig)" >> $GITHUB_STEP_SUMMARY + [ ! -f "CONTRIBUTING.md" ] && echo "- Create CONTRIBUTING.md: Use [template](https://github.com/mokoconsulting-tech/MokoCli/tree/main/templates/docs/required/CONTRIBUTING.md)" >> $GITHUB_STEP_SUMMARY + [ ! -f "SECURITY.md" ] && echo "- Create SECURITY.md: Use [template](https://github.com/mokoconsulting-tech/MokoCli/tree/main/templates/docs/required/SECURITY.md)" >> $GITHUB_STEP_SUMMARY + [ ! -f ".editorconfig" ] && echo "- Add .editorconfig: Use [template](https://github.com/mokoconsulting-tech/MokoCli/tree/main/templates/.editorconfig)" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "📚 Reference: [MokoStandards File Requirements](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/docs/policy/file-header-standards.md)" >> $GITHUB_STEP_SUMMARY + echo "📚 Reference: [MokoCli File Requirements](https://github.com/mokoconsulting-tech/MokoCli/tree/main/docs/policy/file-header-standards.md)" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "### ❌ Validation Failed: Required Files Missing" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**Status:** Repository files do not meet MokoStandards requirements" >> $GITHUB_STEP_SUMMARY + echo "**Status:** Repository files do not meet MokoCli requirements" >> $GITHUB_STEP_SUMMARY echo "**Missing:** $MISSING required file(s)" >> $GITHUB_STEP_SUMMARY echo "**Compliance:** $PERCENT% ($PRESENT/$TOTAL files present)" >> $GITHUB_STEP_SUMMARY echo "" @@ -437,7 +437,7 @@ jobs: echo "$TABS_IN_SPACES_FILES" >> $GITHUB_STEP_SUMMARY echo "\`\`\`" >> $GITHUB_STEP_SUMMARY echo "These languages require spaces (tabs will break): YAML, Python, Haskell, F#, CoffeeScript, Nim, JSON, RST" >> $GITHUB_STEP_SUMMARY - echo "All other files (including .md, .ps1, LICENSE, etc.) may use tabs per MokoStandards policy" >> $GITHUB_STEP_SUMMARY + echo "All other files (including .md, .ps1, LICENSE, etc.) may use tabs per MokoCli policy" >> $GITHUB_STEP_SUMMARY else echo "✅ No tabs found in files requiring spaces" >> $GITHUB_STEP_SUMMARY echo "Note: Tabs are allowed in most files (policy default). Only checked files requiring spaces." >> $GITHUB_STEP_SUMMARY @@ -483,7 +483,7 @@ jobs: echo "\`\`\`" >> $GITHUB_STEP_SUMMARY echo "$CRLF_FILES" >> $GITHUB_STEP_SUMMARY echo "\`\`\`" >> $GITHUB_STEP_SUMMARY - echo "MokoStandards requires LF line endings" >> $GITHUB_STEP_SUMMARY + echo "MokoCli requires LF line endings" >> $GITHUB_STEP_SUMMARY else echo "✅ Line endings are consistent (LF)" >> $GITHUB_STEP_SUMMARY fi @@ -504,13 +504,13 @@ jobs: tools: composer coverage: none - - name: Setup MokoStandards tools + - name: Setup MokoCli tools env: GH_TOKEN: ${{ secrets.GH_PAT || github.token }} COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_PAT || github.token }}"}}' run: | git clone --depth 1 --branch version/04 --quiet \ - "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \ + "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoCli.git" \ /tmp/mokostandards 2>/dev/null || true if [ -d "/tmp/mokostandards" ] && [ -f "/tmp/mokostandards/composer.json" ]; then cd /tmp/mokostandards @@ -524,7 +524,7 @@ jobs: echo "## 🔢 Version Consistency Validation" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - # Use MokoStandards tools (no Composer needed on the governed repo) + # Use MokoCli tools (no Composer needed on the governed repo) if [ -f "/tmp/mokostandards/api/validate/check_version_consistency.php" ]; then php /tmp/mokostandards/api/validate/check_version_consistency.php --path . --verbose 2>&1 | tee /tmp/version-check.log EXIT_CODE=${PIPESTATUS[0]} @@ -532,7 +532,7 @@ jobs: php api/validate/check_version_consistency.php --path . --verbose 2>&1 | tee /tmp/version-check.log EXIT_CODE=${PIPESTATUS[0]} else - echo "⏭️ MokoStandards tools not available — skipping version check" >> $GITHUB_STEP_SUMMARY + echo "⏭️ MokoCli tools not available — skipping version check" >> $GITHUB_STEP_SUMMARY exit 0 fi @@ -597,12 +597,12 @@ jobs: echo "⚠️ CodeQL workflow not found" >> $GITHUB_STEP_SUMMARY fi - # Check for MokoStandards-synced workflows + # Check for MokoCli-synced workflows for wf in deploy-dev.yml deploy-demo.yml deploy-rs.yml sync-version-on-merge.yml auto-release.yml standards-compliance.yml enterprise-firewall-setup.yml; do if [ -f "$WORKFLOWS_DIR/$wf" ]; then echo "✅ ${wf}" >> $GITHUB_STEP_SUMMARY else - echo "⚠️ ${wf} not found (synced from MokoStandards)" >> $GITHUB_STEP_SUMMARY + echo "⚠️ ${wf} not found (synced from MokoCli)" >> $GITHUB_STEP_SUMMARY fi done @@ -809,7 +809,7 @@ jobs: echo "" >> $GITHUB_STEP_SUMMARY echo "### ❌ Validation Failed: README.md Missing" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**Error:** README.md is required for all MokoStandards-compliant repositories" >> $GITHUB_STEP_SUMMARY + echo "**Error:** README.md is required for all MokoCli-compliant repositories" >> $GITHUB_STEP_SUMMARY echo "**Action Required:** Create README.md with project description, setup instructions, and usage examples" >> $GITHUB_STEP_SUMMARY echo "" echo "❌ ERROR: README.md not found - This is a critical requirement" @@ -915,7 +915,7 @@ jobs: echo "" >> $GITHUB_STEP_SUMMARY echo "### ❌ Validation Failed: CHANGELOG.md Missing" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**Error:** CHANGELOG.md is required for all MokoStandards-compliant repositories" >> $GITHUB_STEP_SUMMARY + echo "**Error:** CHANGELOG.md is required for all MokoCli-compliant repositories" >> $GITHUB_STEP_SUMMARY echo "**Action Required:** Create CHANGELOG.md following [Keep a Changelog](https://keepachangelog.com/) format" >> $GITHUB_STEP_SUMMARY echo "" echo "❌ ERROR: CHANGELOG.md not found - This is a critical requirement" @@ -1976,10 +1976,10 @@ jobs: if [ -f "composer.json" ]; then composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader else - echo "No composer.json — pulling MokoStandards tools" + echo "No composer.json — pulling MokoCli tools" if [ ! -d "/tmp/mokostandards" ]; then git clone --depth 1 --branch version/04 --quiet \ - "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \ + "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoCli.git" \ /tmp/mokostandards 2>/dev/null || true if [ -f "/tmp/mokostandards/composer.json" ]; then cd /tmp/mokostandards && composer install --no-dev --no-interaction --quiet 2>/dev/null || true @@ -2048,10 +2048,10 @@ jobs: if [ -f "composer.json" ]; then composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader else - echo "No composer.json — pulling MokoStandards tools" + echo "No composer.json — pulling MokoCli tools" if [ ! -d "/tmp/mokostandards" ]; then git clone --depth 1 --branch version/04 --quiet \ - "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \ + "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoCli.git" \ /tmp/mokostandards 2>/dev/null || true if [ -f "/tmp/mokostandards/composer.json" ]; then cd /tmp/mokostandards && composer install --no-dev --no-interaction --quiet 2>/dev/null || true @@ -2133,7 +2133,7 @@ jobs: # 1. Check .github/config.tf location (not root override files) echo "### Override Configuration Check" >> $GITHUB_STEP_SUMMARY - LEGACY_OVERRIDES=$(find . -maxdepth 1 -name "*override*.tf" -o -name "MokoStandards.override.tf" 2>/dev/null | wc -l || echo 0) + LEGACY_OVERRIDES=$(find . -maxdepth 1 -name "*override*.tf" -o -name "MokoCli.override.tf" 2>/dev/null | wc -l || echo 0) if [ "$LEGACY_OVERRIDES" -gt 0 ]; then echo "⚠️ Found legacy override files in root directory" >> $GITHUB_STEP_SUMMARY echo "**Expected Location**: .github/config.tf" >> $GITHUB_STEP_SUMMARY @@ -2299,7 +2299,7 @@ jobs: - name: Generate Compliance Report run: | set -x - echo "# 📊 MokoStandards Compliance Report" >> $GITHUB_STEP_SUMMARY + echo "# 📊 MokoCli Compliance Report" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY # Calculate overall status @@ -2486,7 +2486,7 @@ jobs: else echo "## 🎉 Excellent!" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "Your repository is **fully compliant** with MokoStandards!" >> $GITHUB_STEP_SUMMARY + echo "Your repository is **fully compliant** with MokoCli!" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "**Achievements:**" >> $GITHUB_STEP_SUMMARY echo "- ✅ All required directories and files present" >> $GITHUB_STEP_SUMMARY @@ -2501,12 +2501,12 @@ jobs: echo "---" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "📚 **Resources:**" >> $GITHUB_STEP_SUMMARY - echo "- [MokoStandards Documentation](https://github.com/mokoconsulting-tech/MokoStandards)" >> $GITHUB_STEP_SUMMARY - echo "- [Repository Structure Guide](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/docs/policy/core-structure.md)" >> $GITHUB_STEP_SUMMARY - echo "- [Documentation Standards](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/docs/policy/document-formatting.md)" >> $GITHUB_STEP_SUMMARY - echo "- [Coding Standards](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/docs/policy/coding-style-guide.md)" >> $GITHUB_STEP_SUMMARY + echo "- [MokoCli Documentation](https://github.com/mokoconsulting-tech/MokoCli)" >> $GITHUB_STEP_SUMMARY + echo "- [Repository Structure Guide](https://github.com/mokoconsulting-tech/MokoCli/tree/main/docs/policy/core-structure.md)" >> $GITHUB_STEP_SUMMARY + echo "- [Documentation Standards](https://github.com/mokoconsulting-tech/MokoCli/tree/main/docs/policy/document-formatting.md)" >> $GITHUB_STEP_SUMMARY + echo "- [Coding Standards](https://github.com/mokoconsulting-tech/MokoCli/tree/main/docs/policy/coding-style-guide.md)" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "_Generated by MokoStandards Compliance Workflow v${WORKFLOW_VERSION}_" >> $GITHUB_STEP_SUMMARY + echo "_Generated by MokoCli Compliance Workflow v${WORKFLOW_VERSION}_" >> $GITHUB_STEP_SUMMARY # Create tracking issue for non-compliance if on push if [ "$COMPLIANCE_PERCENT" -lt 100 ] && [ "${{ github.event_name }}" = "push" ]; then @@ -2530,9 +2530,9 @@ jobs: echo "### ✅ Full Standards Compliance Achieved" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "**Overall Compliance:** 100%" >> $GITHUB_STEP_SUMMARY - echo "**Status:** Repository meets all MokoStandards requirements" >> $GITHUB_STEP_SUMMARY + echo "**Status:** Repository meets all MokoCli requirements" >> $GITHUB_STEP_SUMMARY echo "" - echo "✅ SUCCESS: Repository is fully MokoStandards compliant" + echo "✅ SUCCESS: Repository is fully MokoCli compliant" - name: Create or reopen tracking issue for standards violations if: failure() diff --git a/mcp/servers/mokosuite_api/.mokogitea/workflows/sync-version-on-merge.yml b/mcp/servers/mokosuite_api/.mokogitea/workflows/sync-version-on-merge.yml index dbdcd6c..a3238bd 100644 --- a/mcp/servers/mokosuite_api/.mokogitea/workflows/sync-version-on-merge.yml +++ b/mcp/servers/mokosuite_api/.mokogitea/workflows/sync-version-on-merge.yml @@ -6,8 +6,8 @@ # # FILE INFORMATION # DEFGROUP: GitHub.Workflow -# INGROUP: MokoStandards.Automation -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCli.Automation +# REPO: https://github.com/mokoconsulting-tech/MokoCli # PATH: /templates/workflows/shared/sync-version-on-merge.yml.template # VERSION: 04.06.00 # BRIEF: Auto-bump patch version on every push to main and propagate to all file headers @@ -53,13 +53,13 @@ jobs: php-version: '8.1' tools: composer - - name: Setup MokoStandards tools + - name: Setup MokoCli tools env: GH_TOKEN: ${{ secrets.GH_PAT || github.token }} COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_PAT || github.token }}"}}' run: | git clone --depth 1 --branch version/04 --quiet \ - "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \ + "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoCli.git" \ /tmp/mokostandards cd /tmp/mokostandards composer install --no-dev --no-interaction --quiet diff --git a/mcp/servers/mokosuite_api/CHANGELOG.md b/mcp/servers/mokosuite_api/CHANGELOG.md index 6614242..8071575 100644 --- a/mcp/servers/mokosuite_api/CHANGELOG.md +++ b/mcp/servers/mokosuite_api/CHANGELOG.md @@ -13,7 +13,7 @@ # FILE INFORMATION DEFGROUP: INGROUP: Project.Documentation - REPO: mokoconsulting-tech/MokoStandards-Template-Generic + REPO: mokoconsulting-tech/MokoCli-Template-Generic VERSION: 0.1.0 PATH: ./CHANGELOG.md BRIEF: Version history and change log @@ -39,7 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Initial repository structure - Basic documentation templates -- MokoStandards-compliant README.md +- MokoCli-compliant README.md - LICENSE with GPL-3.0-or-later - CONTRIBUTING.md with contribution guidelines - CODE_OF_CONDUCT.md (Contributor Covenant v1.3.0) diff --git a/mcp/servers/mokosuite_api/CONTRIBUTING.md b/mcp/servers/mokosuite_api/CONTRIBUTING.md index b8c1d8b..1e8f5a5 100644 --- a/mcp/servers/mokosuite_api/CONTRIBUTING.md +++ b/mcp/servers/mokosuite_api/CONTRIBUTING.md @@ -13,13 +13,13 @@ # FILE INFORMATION DEFGROUP: INGROUP: Project.Documentation - REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-Template-Generic - VERSION: 09.29.01 + REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoCli-Template-Generic + VERSION: 09.29.02 PATH: ./CONTRIBUTING.md BRIEF: Contribution guidelines for the project --> -# Contributing to MokoStandards-Template-Generic +# Contributing to MokoCli-Template-Generic We appreciate your interest in contributing to this project! This document provides guidelines for contributing. diff --git a/mcp/servers/mokosuite_api/README.md b/mcp/servers/mokosuite_api/README.md index 91200e1..2ec82b4 100644 --- a/mcp/servers/mokosuite_api/README.md +++ b/mcp/servers/mokosuite_api/README.md @@ -79,7 +79,7 @@ joomla-api-mcp wraps the entire Joomla Web Services REST API into MCP tools that --- -> **[MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki)** -- central standards hub for all Moko Consulting projects. +> **[MokoCli](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki)** -- central standards hub for all Moko Consulting projects. --- @@ -101,4 +101,4 @@ This project is licensed under the GNU General Public License v3.0 or later -- s --- -*[Moko Consulting](https://mokoconsulting.tech) -- [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki/Home)* +*[Moko Consulting](https://mokoconsulting.tech) -- [MokoCli](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki/Home)* diff --git a/mcp/servers/mokosuite_api/SECURITY.md b/mcp/servers/mokosuite_api/SECURITY.md index 0a33957..c290e0c 100644 --- a/mcp/servers/mokosuite_api/SECURITY.md +++ b/mcp/servers/mokosuite_api/SECURITY.md @@ -23,7 +23,7 @@ DEFGROUP: [PROJECT_NAME] INGROUP: [PROJECT_NAME].Documentation REPO: [REPOSITORY_URL] PATH: /SECURITY.md -VERSION: 09.29.01 +VERSION: 09.29.02 BRIEF: Security vulnerability reporting and handling policy --> @@ -47,7 +47,7 @@ Only the current major version receives security updates. Users should upgrade t ## Reporting a Vulnerability Report security vulnerabilities via Gitea issue (preferred): -https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-Template-Generic/issues/new?template=security.yaml +https://git.mokoconsulting.tech/MokoConsulting/MokoCli-Template-Generic/issues/new?template=security.yaml Or email: hello@mokoconsulting.tech @@ -136,7 +136,7 @@ Advisories include: ## Security Best Practices -For repositories adopting MokoStandards: +For repositories adopting MokoCli: ### Required Controls @@ -194,7 +194,7 @@ See [Security Scanning Policy](docs/policy/security-scanning.md) for detailed re ## Compliance and Governance -This security policy is binding for all repositories governed by MokoStandards. Deviations require documented justification and approval from the Security Owner. +This security policy is binding for all repositories governed by MokoCli. Deviations require documented justification and approval from the Security Owner. Security policies are reviewed and updated at least annually or following significant security incidents. @@ -234,7 +234,7 @@ The following are explicitly out of scope: | Repository | [REPOSITORY_URL] | | Owner | [OWNER_NAME] | | Scope | Security vulnerability handling | -| Applies To | All repositories governed by MokoStandards | +| Applies To | All repositories governed by MokoCli | | Status | Active | | Effective | [YYYY-MM-DD] | diff --git a/mcp/servers/windows/.mokogitea/CLAUDE.md b/mcp/servers/windows/.mokogitea/CLAUDE.md index 88835f8..48b6a91 100644 --- a/mcp/servers/windows/.mokogitea/CLAUDE.md +++ b/mcp/servers/windows/.mokogitea/CLAUDE.md @@ -41,4 +41,4 @@ src/ - **Attribution**: `Authored-by: Moko Consulting` - **Workflow directory**: `.mokogitea/` (not `.gitea/` or `.github/`) - **Wiki**: documentation lives in the Gitea wiki, not `docs/` files -- **Standards**: [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki/Home) +- **Standards**: [MokoCli](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki/Home) diff --git a/mcp/servers/windows/.mokogitea/ISSUE_TEMPLATE/config.yml b/mcp/servers/windows/.mokogitea/ISSUE_TEMPLATE/config.yml index 7c403f1..14db946 100644 --- a/mcp/servers/windows/.mokogitea/ISSUE_TEMPLATE/config.yml +++ b/mcp/servers/windows/.mokogitea/ISSUE_TEMPLATE/config.yml @@ -7,7 +7,7 @@ contact_links: - name: 💬 Ask a Question url: https://mokoconsulting.tech/ about: Get help or ask questions through our website - - name: 📚 MokoStandards Documentation + - name: 📚 MokoCli Documentation url: https://git.mokoconsulting.tech/MokoConsulting/mokoplatform about: View our coding standards and best practices - name: 🔒 Report a Security Vulnerability diff --git a/mcp/servers/windows/.mokogitea/ISSUE_TEMPLATE/documentation.md b/mcp/servers/windows/.mokogitea/ISSUE_TEMPLATE/documentation.md index ed4dabc..96d4fbc 100644 --- a/mcp/servers/windows/.mokogitea/ISSUE_TEMPLATE/documentation.md +++ b/mcp/servers/windows/.mokogitea/ISSUE_TEMPLATE/documentation.md @@ -42,7 +42,7 @@ Suggested text here ## Standards Alignment -- [ ] Follows MokoStandards documentation guidelines +- [ ] Follows MokoCli documentation guidelines - [ ] Uses en_US/en_GB localization - [ ] Includes proper SPDX headers where applicable diff --git a/mcp/servers/windows/.mokogitea/ISSUE_TEMPLATE/feature_request.md b/mcp/servers/windows/.mokogitea/ISSUE_TEMPLATE/feature_request.md index 7b76dc9..6161deb 100644 --- a/mcp/servers/windows/.mokogitea/ISSUE_TEMPLATE/feature_request.md +++ b/mcp/servers/windows/.mokogitea/ISSUE_TEMPLATE/feature_request.md @@ -37,7 +37,7 @@ If you have ideas about how this could be implemented, share them here: Add any other context, mockups, or screenshots about the feature request here. ## Relevant Standards -Does this relate to any standards in [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/MokoStandards)? +Does this relate to any standards in [MokoCli](https://git.mokoconsulting.tech/MokoConsulting/MokoCli)? - [ ] Accessibility (WCAG 2.1 AA) - [ ] Localization (en_US/en_GB) - [ ] Security best practices diff --git a/mcp/servers/windows/.mokogitea/ISSUE_TEMPLATE/security.md b/mcp/servers/windows/.mokogitea/ISSUE_TEMPLATE/security.md index f57b284..69bae34 100644 --- a/mcp/servers/windows/.mokogitea/ISSUE_TEMPLATE/security.md +++ b/mcp/servers/windows/.mokogitea/ISSUE_TEMPLATE/security.md @@ -35,7 +35,7 @@ Use this template only for: ## Standards Reference -Does this relate to security standards in [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/MokoStandards)? +Does this relate to security standards in [MokoCli](https://git.mokoconsulting.tech/MokoConsulting/MokoCli)? - [ ] SPDX license identifiers - [ ] Secret management - [ ] Dependency security diff --git a/mcp/servers/windows/.mokogitea/manifest.xml b/mcp/servers/windows/.mokogitea/manifest.xml index a030851..9066fd5 100644 --- a/mcp/servers/windows/.mokogitea/manifest.xml +++ b/mcp/servers/windows/.mokogitea/manifest.xml @@ -1,6 +1,6 @@ diff --git a/mcp/servers/windows/.mokogitea/workflows/auto-assign.yml b/mcp/servers/windows/.mokogitea/workflows/auto-assign.yml index c0f538f..ab7f573 100644 --- a/mcp/servers/windows/.mokogitea/workflows/auto-assign.yml +++ b/mcp/servers/windows/.mokogitea/workflows/auto-assign.yml @@ -3,8 +3,8 @@ # # FILE INFORMATION # DEFGROUP: GitHub.Workflow -# INGROUP: MokoStandards.Workflows.Shared -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCli.Workflows.Shared +# REPO: https://github.com/mokoconsulting-tech/MokoCli # PATH: /.mokogitea/workflows/auto-assign.yml # VERSION: 04.06.00 # BRIEF: Auto-assign jmiller to unassigned issues and PRs every 15 minutes diff --git a/mcp/servers/windows/.mokogitea/workflows/auto-dev-issue.yml b/mcp/servers/windows/.mokogitea/workflows/auto-dev-issue.yml index bdd7db7..a8774ab 100644 --- a/mcp/servers/windows/.mokogitea/workflows/auto-dev-issue.yml +++ b/mcp/servers/windows/.mokogitea/workflows/auto-dev-issue.yml @@ -6,8 +6,8 @@ # # FILE INFORMATION # DEFGROUP: GitHub.Workflow -# INGROUP: MokoStandards.Automation -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCli.Automation +# REPO: https://github.com/mokoconsulting-tech/MokoCli # PATH: /templates/workflows/shared/auto-dev-issue.yml.template # VERSION: 04.06.00 # BRIEF: Auto-create tracking issue with sub-issues for dev/rc branch workflow diff --git a/mcp/servers/windows/.mokogitea/workflows/cascade-dev.yml b/mcp/servers/windows/.mokogitea/workflows/cascade-dev.yml index 12d5610..f595c92 100644 --- a/mcp/servers/windows/.mokogitea/workflows/cascade-dev.yml +++ b/mcp/servers/windows/.mokogitea/workflows/cascade-dev.yml @@ -4,8 +4,8 @@ # # FILE INFORMATION # DEFGROUP: Gitea.Workflow -# INGROUP: MokoStandards.Maintenance -# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoStandards-API +# INGROUP: MokoCli.Maintenance +# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoCli-API # PATH: /templates/workflows/cascade-dev.yml.template # VERSION: 02.00.00 # BRIEF: Forward-merge main → all open branches after every push to main diff --git a/mcp/servers/windows/.mokogitea/workflows/changelog-validation.yml b/mcp/servers/windows/.mokogitea/workflows/changelog-validation.yml index 0601d2f..f104937 100644 --- a/mcp/servers/windows/.mokogitea/workflows/changelog-validation.yml +++ b/mcp/servers/windows/.mokogitea/workflows/changelog-validation.yml @@ -6,8 +6,8 @@ # # FILE INFORMATION # DEFGROUP: GitHub.Workflow.Template -# INGROUP: MokoStandards.CI -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCli.CI +# REPO: https://github.com/mokoconsulting-tech/MokoCli # PATH: /templates/workflows/shared/changelog-validation.yml.template # VERSION: 04.06.00 # BRIEF: Validates CHANGELOG.md format and version consistency diff --git a/mcp/servers/windows/.mokogitea/workflows/cleanup.yml b/mcp/servers/windows/.mokogitea/workflows/cleanup.yml index ec100b1..b06157c 100644 --- a/mcp/servers/windows/.mokogitea/workflows/cleanup.yml +++ b/mcp/servers/windows/.mokogitea/workflows/cleanup.yml @@ -4,8 +4,8 @@ # # FILE INFORMATION # DEFGROUP: Gitea.Workflow -# INGROUP: MokoStandards.Maintenance -# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards +# INGROUP: MokoCli.Maintenance +# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoCli # PATH: /.gitea/workflows/cleanup.yml # VERSION: 01.00.00 # BRIEF: Scheduled cleanup — delete merged branches and old workflow runs diff --git a/mcp/servers/windows/.mokogitea/workflows/codeql-analysis.yml b/mcp/servers/windows/.mokogitea/workflows/codeql-analysis.yml index dd61fc3..0e4c735 100644 --- a/mcp/servers/windows/.mokogitea/workflows/codeql-analysis.yml +++ b/mcp/servers/windows/.mokogitea/workflows/codeql-analysis.yml @@ -6,8 +6,8 @@ # # FILE INFORMATION # DEFGROUP: GitHub.Workflow.Template -# INGROUP: MokoStandards.Security -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCli.Security +# REPO: https://github.com/mokoconsulting-tech/MokoCli # PATH: /templates/workflows/generic/codeql-analysis.yml.template # VERSION: 04.05.00 # BRIEF: CodeQL security scanning workflow (generic — all repo types) diff --git a/mcp/servers/windows/.mokogitea/workflows/deploy-manual.yml b/mcp/servers/windows/.mokogitea/workflows/deploy-manual.yml index 6908af1..62052b6 100644 --- a/mcp/servers/windows/.mokogitea/workflows/deploy-manual.yml +++ b/mcp/servers/windows/.mokogitea/workflows/deploy-manual.yml @@ -4,8 +4,8 @@ # # FILE INFORMATION # DEFGROUP: Gitea.Workflow -# INGROUP: MokoStandards.Deploy -# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API +# INGROUP: MokoCli.Deploy +# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoCli-API # PATH: /templates/workflows/joomla/deploy-manual.yml.template # VERSION: 04.07.00 # BRIEF: Manual SFTP deploy to dev server for Joomla repos @@ -40,7 +40,7 @@ jobs: run: | php -v && composer --version - - name: Setup MokoStandards tools + - name: Setup MokoCli tools env: GA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN || secrets.MOKOGITEA_TOKEN || github.token }} MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN || secrets.MOKOGITEA_TOKEN || github.token }} @@ -48,7 +48,7 @@ jobs: COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.MOKOGITEA_TOKEN || github.token }}"}}' run: | git clone --depth 1 --branch main --quiet \ - "https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoStandards-API.git" \ + "https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoCli-API.git" \ /tmp/mokostandards-api 2>/dev/null || true if [ -d "/tmp/mokostandards-api" ] && [ -f "/tmp/mokostandards-api/composer.json" ]; then cd /tmp/mokostandards-api && composer install --no-dev --no-interaction --quiet 2>/dev/null || true diff --git a/mcp/servers/windows/.mokogitea/workflows/enterprise-firewall-setup.yml b/mcp/servers/windows/.mokogitea/workflows/enterprise-firewall-setup.yml index 81866f2..af361ef 100644 --- a/mcp/servers/windows/.mokogitea/workflows/enterprise-firewall-setup.yml +++ b/mcp/servers/windows/.mokogitea/workflows/enterprise-firewall-setup.yml @@ -19,8 +19,8 @@ # FILE INFORMATION # DEFGROUP: GitHub.Workflow -# INGROUP: MokoStandards.Firewall -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCli.Firewall +# REPO: https://github.com/mokoconsulting-tech/MokoCli # PATH: /templates/workflows/shared/enterprise-firewall-setup.yml.template # VERSION: 04.06.00 # BRIEF: Enterprise firewall configuration — generates outbound allow-rules including SFTP deployment server diff --git a/mcp/servers/windows/.mokogitea/workflows/gitleaks.yml b/mcp/servers/windows/.mokogitea/workflows/gitleaks.yml index 0c07612..f6daf0c 100644 --- a/mcp/servers/windows/.mokogitea/workflows/gitleaks.yml +++ b/mcp/servers/windows/.mokogitea/workflows/gitleaks.yml @@ -4,8 +4,8 @@ # # FILE INFORMATION # DEFGROUP: Gitea.Workflow -# INGROUP: MokoStandards.Security -# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoStandards-API +# INGROUP: MokoCli.Security +# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoCli-API # PATH: /templates/workflows/gitleaks.yml.template # VERSION: 01.00.00 # BRIEF: Secret scanning — detect leaked credentials, API keys, and tokens diff --git a/mcp/servers/windows/.mokogitea/workflows/notify.yml b/mcp/servers/windows/.mokogitea/workflows/notify.yml index ce804b5..3153b25 100644 --- a/mcp/servers/windows/.mokogitea/workflows/notify.yml +++ b/mcp/servers/windows/.mokogitea/workflows/notify.yml @@ -4,8 +4,8 @@ # # FILE INFORMATION # DEFGROUP: Gitea.Workflow -# INGROUP: MokoStandards.Notifications -# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards +# INGROUP: MokoCli.Notifications +# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoCli # PATH: /.mokogitea/workflows/notify.yml # VERSION: 01.00.00 # BRIEF: Push notifications via ntfy on release success or workflow failure diff --git a/mcp/servers/windows/.mokogitea/workflows/pr-check.yml b/mcp/servers/windows/.mokogitea/workflows/pr-check.yml index 9290a89..f232f89 100644 --- a/mcp/servers/windows/.mokogitea/workflows/pr-check.yml +++ b/mcp/servers/windows/.mokogitea/workflows/pr-check.yml @@ -4,8 +4,8 @@ # # FILE INFORMATION # DEFGROUP: Gitea.Workflow -# INGROUP: MokoStandards.CI -# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoStandards-API +# INGROUP: MokoCli.CI +# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoCli-API # PATH: /templates/workflows/universal/pr-check.yml.template # VERSION: 05.00.00 # BRIEF: PR gate — branch policy + code validation before merge diff --git a/mcp/servers/windows/.mokogitea/workflows/repo-health.yml b/mcp/servers/windows/.mokogitea/workflows/repo-health.yml index 334a06e..d57b58f 100644 --- a/mcp/servers/windows/.mokogitea/workflows/repo-health.yml +++ b/mcp/servers/windows/.mokogitea/workflows/repo-health.yml @@ -7,8 +7,8 @@ # # FILE INFORMATION # DEFGROUP: Gitea.Workflow -# INGROUP: MokoStandards.Validation -# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoStandards-API +# INGROUP: MokoCli.Validation +# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoCli-API # PATH: /templates/workflows/joomla/repo_health.yml.template # VERSION: 04.06.00 # BRIEF: Enforces repository guardrails by validating release configuration, scripts governance, tooling availability, and core repository health artifacts. diff --git a/mcp/servers/windows/.mokogitea/workflows/repository-cleanup.yml b/mcp/servers/windows/.mokogitea/workflows/repository-cleanup.yml index bb90e00..0468b17 100644 --- a/mcp/servers/windows/.mokogitea/workflows/repository-cleanup.yml +++ b/mcp/servers/windows/.mokogitea/workflows/repository-cleanup.yml @@ -6,8 +6,8 @@ # # FILE INFORMATION # DEFGROUP: GitHub.Workflow -# INGROUP: MokoStandards.Maintenance -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCli.Maintenance +# REPO: https://github.com/mokoconsulting-tech/MokoCli # PATH: /templates/workflows/shared/repository-cleanup.yml.template # VERSION: 04.06.00 # BRIEF: Recurring repository maintenance — labels, branches, workflows, logs, doc indexes @@ -220,7 +220,7 @@ jobs: config|F9D0C4|Configuration file changes build|FFA500|Build system changes automation|8B4513|Automated processes or scripts - mokostandards|B60205|MokoStandards compliance + mokostandards|B60205|MokoCli compliance needs-review|FBCA04|Awaiting code review work-in-progress|D93F0B|Work in progress, not ready for merge breaking-change|D73A4A|Breaking API or functionality change @@ -249,8 +249,8 @@ jobs: health: good|FBCA04|Health score 70-89 health: fair|FFA500|Health score 50-69 health: poor|FF6B6B|Health score below 50 - standards-update|B60205|MokoStandards sync update - standards-drift|FBCA04|Repository drifted from MokoStandards + standards-update|B60205|MokoCli sync update + standards-drift|FBCA04|Repository drifted from MokoCli sync-report|0075CA|Bulk sync run report sync-failure|D73A4A|Bulk sync failure requiring attention push-failure|D73A4A|File push failure requiring attention @@ -469,7 +469,7 @@ jobs: # Custom Workflows Place repo-specific workflows here. Files in this directory are: - - **Never overwritten** by MokoStandards bulk sync + - **Never overwritten** by MokoCli bulk sync - **Never deleted** by the repository-cleanup workflow - Safe for custom CI, notifications, or repo-specific automation diff --git a/mcp/servers/windows/.mokogitea/workflows/security-audit.yml b/mcp/servers/windows/.mokogitea/workflows/security-audit.yml index ca671e5..71fd244 100644 --- a/mcp/servers/windows/.mokogitea/workflows/security-audit.yml +++ b/mcp/servers/windows/.mokogitea/workflows/security-audit.yml @@ -4,8 +4,8 @@ # # FILE INFORMATION # DEFGROUP: Gitea.Workflow -# INGROUP: MokoStandards.Security -# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards +# INGROUP: MokoCli.Security +# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoCli # PATH: /.mokogitea/workflows/security-audit.yml # VERSION: 01.00.00 # BRIEF: Dependency vulnerability scanning for composer and npm packages diff --git a/mcp/servers/windows/.mokogitea/workflows/standards-compliance.yml b/mcp/servers/windows/.mokogitea/workflows/standards-compliance.yml index 1927cb0..7774161 100644 --- a/mcp/servers/windows/.mokogitea/workflows/standards-compliance.yml +++ b/mcp/servers/windows/.mokogitea/workflows/standards-compliance.yml @@ -2,11 +2,11 @@ # SPDX-License-Identifier: GPL-3.0-or-later # FILE INFORMATION # DEFGROUP: GitHub.Workflow -# INGROUP: MokoStandards.Compliance -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCli.Compliance +# REPO: https://github.com/mokoconsulting-tech/MokoCli # PATH: /.mokogitea/workflows/standards-compliance.yml # VERSION: 04.06.00 -# BRIEF: MokoStandards compliance validation workflow +# BRIEF: MokoCli compliance validation workflow # NOTE: Validates repository structure, documentation, and coding standards name: "MCP: Standards Compliance" @@ -42,7 +42,7 @@ env: WORKFLOW_VERSION: "04.04.01" FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true -# MokoStandards Policy Compliance: +# MokoCli Policy Compliance: # - File formatting: Enforces organizational coding standards # - Reference: docs/policy/file-formatting.md @@ -252,7 +252,7 @@ jobs: echo "" >> $GITHUB_STEP_SUMMARY echo "### ❌ Validation Failed: LICENSE File Missing" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**Error:** LICENSE file is required for all MokoStandards-compliant repositories" >> $GITHUB_STEP_SUMMARY + echo "**Error:** LICENSE file is required for all MokoCli-compliant repositories" >> $GITHUB_STEP_SUMMARY echo "**Action Required:** Add LICENSE file with appropriate open-source license (GPL-3.0-or-later recommended)" >> $GITHUB_STEP_SUMMARY echo "" echo "❌ ERROR: LICENSE file not found - This is a critical requirement" @@ -323,11 +323,11 @@ jobs: [ ! -d "docs" ] && echo "- Create docs directory: \`mkdir docs && echo '# Documentation' > docs/README.md\`" >> $GITHUB_STEP_SUMMARY [ ! -d ".github" ] && echo "- Create .github directory: \`mkdir -p .github/workflows\`" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "📚 Reference: [MokoStandards Repository Structure](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/docs/policy/core-structure.md)" >> $GITHUB_STEP_SUMMARY + echo "📚 Reference: [MokoCli Repository Structure](https://github.com/mokoconsulting-tech/MokoCli/tree/main/docs/policy/core-structure.md)" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "### ❌ Validation Failed: Required Directories Missing" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**Status:** Repository structure does not meet MokoStandards requirements" >> $GITHUB_STEP_SUMMARY + echo "**Status:** Repository structure does not meet MokoCli requirements" >> $GITHUB_STEP_SUMMARY echo "**Missing:** $MISSING required director(y|ies)" >> $GITHUB_STEP_SUMMARY echo "**Compliance:** $PERCENT% ($PRESENT/$TOTAL directories present)" >> $GITHUB_STEP_SUMMARY echo "" @@ -384,17 +384,17 @@ jobs: echo "### 🔴 Critical Issues: $MISSING" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "**Remediation Steps:**" >> $GITHUB_STEP_SUMMARY - [ ! -f "README.md" ] && echo "- Create README.md: Use [template](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/templates/docs/required/README.md)" >> $GITHUB_STEP_SUMMARY + [ ! -f "README.md" ] && echo "- Create README.md: Use [template](https://github.com/mokoconsulting-tech/MokoCli/tree/main/templates/docs/required/README.md)" >> $GITHUB_STEP_SUMMARY [ ! -f "LICENSE" ] && echo "- Add LICENSE file: Choose from [OSI-approved licenses](https://opensource.org/licenses)" >> $GITHUB_STEP_SUMMARY - [ ! -f "CONTRIBUTING.md" ] && echo "- Create CONTRIBUTING.md: Use [template](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/templates/docs/required/CONTRIBUTING.md)" >> $GITHUB_STEP_SUMMARY - [ ! -f "SECURITY.md" ] && echo "- Create SECURITY.md: Use [template](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/templates/docs/required/SECURITY.md)" >> $GITHUB_STEP_SUMMARY - [ ! -f ".editorconfig" ] && echo "- Add .editorconfig: Use [template](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/templates/.editorconfig)" >> $GITHUB_STEP_SUMMARY + [ ! -f "CONTRIBUTING.md" ] && echo "- Create CONTRIBUTING.md: Use [template](https://github.com/mokoconsulting-tech/MokoCli/tree/main/templates/docs/required/CONTRIBUTING.md)" >> $GITHUB_STEP_SUMMARY + [ ! -f "SECURITY.md" ] && echo "- Create SECURITY.md: Use [template](https://github.com/mokoconsulting-tech/MokoCli/tree/main/templates/docs/required/SECURITY.md)" >> $GITHUB_STEP_SUMMARY + [ ! -f ".editorconfig" ] && echo "- Add .editorconfig: Use [template](https://github.com/mokoconsulting-tech/MokoCli/tree/main/templates/.editorconfig)" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "📚 Reference: [MokoStandards File Requirements](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/docs/policy/file-header-standards.md)" >> $GITHUB_STEP_SUMMARY + echo "📚 Reference: [MokoCli File Requirements](https://github.com/mokoconsulting-tech/MokoCli/tree/main/docs/policy/file-header-standards.md)" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "### ❌ Validation Failed: Required Files Missing" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**Status:** Repository files do not meet MokoStandards requirements" >> $GITHUB_STEP_SUMMARY + echo "**Status:** Repository files do not meet MokoCli requirements" >> $GITHUB_STEP_SUMMARY echo "**Missing:** $MISSING required file(s)" >> $GITHUB_STEP_SUMMARY echo "**Compliance:** $PERCENT% ($PRESENT/$TOTAL files present)" >> $GITHUB_STEP_SUMMARY echo "" @@ -437,7 +437,7 @@ jobs: echo "$TABS_IN_SPACES_FILES" >> $GITHUB_STEP_SUMMARY echo "\`\`\`" >> $GITHUB_STEP_SUMMARY echo "These languages require spaces (tabs will break): YAML, Python, Haskell, F#, CoffeeScript, Nim, JSON, RST" >> $GITHUB_STEP_SUMMARY - echo "All other files (including .md, .ps1, LICENSE, etc.) may use tabs per MokoStandards policy" >> $GITHUB_STEP_SUMMARY + echo "All other files (including .md, .ps1, LICENSE, etc.) may use tabs per MokoCli policy" >> $GITHUB_STEP_SUMMARY else echo "✅ No tabs found in files requiring spaces" >> $GITHUB_STEP_SUMMARY echo "Note: Tabs are allowed in most files (policy default). Only checked files requiring spaces." >> $GITHUB_STEP_SUMMARY @@ -483,7 +483,7 @@ jobs: echo "\`\`\`" >> $GITHUB_STEP_SUMMARY echo "$CRLF_FILES" >> $GITHUB_STEP_SUMMARY echo "\`\`\`" >> $GITHUB_STEP_SUMMARY - echo "MokoStandards requires LF line endings" >> $GITHUB_STEP_SUMMARY + echo "MokoCli requires LF line endings" >> $GITHUB_STEP_SUMMARY else echo "✅ Line endings are consistent (LF)" >> $GITHUB_STEP_SUMMARY fi @@ -504,13 +504,13 @@ jobs: tools: composer coverage: none - - name: Setup MokoStandards tools + - name: Setup MokoCli tools env: GH_TOKEN: ${{ secrets.GH_PAT || github.token }} COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_PAT || github.token }}"}}' run: | git clone --depth 1 --branch version/04 --quiet \ - "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \ + "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoCli.git" \ /tmp/mokostandards 2>/dev/null || true if [ -d "/tmp/mokostandards" ] && [ -f "/tmp/mokostandards/composer.json" ]; then cd /tmp/mokostandards @@ -524,7 +524,7 @@ jobs: echo "## 🔢 Version Consistency Validation" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - # Use MokoStandards tools (no Composer needed on the governed repo) + # Use MokoCli tools (no Composer needed on the governed repo) if [ -f "/tmp/mokostandards/api/validate/check_version_consistency.php" ]; then php /tmp/mokostandards/api/validate/check_version_consistency.php --path . --verbose 2>&1 | tee /tmp/version-check.log EXIT_CODE=${PIPESTATUS[0]} @@ -532,7 +532,7 @@ jobs: php api/validate/check_version_consistency.php --path . --verbose 2>&1 | tee /tmp/version-check.log EXIT_CODE=${PIPESTATUS[0]} else - echo "⏭️ MokoStandards tools not available — skipping version check" >> $GITHUB_STEP_SUMMARY + echo "⏭️ MokoCli tools not available — skipping version check" >> $GITHUB_STEP_SUMMARY exit 0 fi @@ -597,12 +597,12 @@ jobs: echo "⚠️ CodeQL workflow not found" >> $GITHUB_STEP_SUMMARY fi - # Check for MokoStandards-synced workflows + # Check for MokoCli-synced workflows for wf in deploy-dev.yml deploy-demo.yml deploy-rs.yml sync-version-on-merge.yml auto-release.yml standards-compliance.yml enterprise-firewall-setup.yml; do if [ -f "$WORKFLOWS_DIR/$wf" ]; then echo "✅ ${wf}" >> $GITHUB_STEP_SUMMARY else - echo "⚠️ ${wf} not found (synced from MokoStandards)" >> $GITHUB_STEP_SUMMARY + echo "⚠️ ${wf} not found (synced from MokoCli)" >> $GITHUB_STEP_SUMMARY fi done @@ -809,7 +809,7 @@ jobs: echo "" >> $GITHUB_STEP_SUMMARY echo "### ❌ Validation Failed: README.md Missing" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**Error:** README.md is required for all MokoStandards-compliant repositories" >> $GITHUB_STEP_SUMMARY + echo "**Error:** README.md is required for all MokoCli-compliant repositories" >> $GITHUB_STEP_SUMMARY echo "**Action Required:** Create README.md with project description, setup instructions, and usage examples" >> $GITHUB_STEP_SUMMARY echo "" echo "❌ ERROR: README.md not found - This is a critical requirement" @@ -915,7 +915,7 @@ jobs: echo "" >> $GITHUB_STEP_SUMMARY echo "### ❌ Validation Failed: CHANGELOG.md Missing" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**Error:** CHANGELOG.md is required for all MokoStandards-compliant repositories" >> $GITHUB_STEP_SUMMARY + echo "**Error:** CHANGELOG.md is required for all MokoCli-compliant repositories" >> $GITHUB_STEP_SUMMARY echo "**Action Required:** Create CHANGELOG.md following [Keep a Changelog](https://keepachangelog.com/) format" >> $GITHUB_STEP_SUMMARY echo "" echo "❌ ERROR: CHANGELOG.md not found - This is a critical requirement" @@ -1976,10 +1976,10 @@ jobs: if [ -f "composer.json" ]; then composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader else - echo "No composer.json — pulling MokoStandards tools" + echo "No composer.json — pulling MokoCli tools" if [ ! -d "/tmp/mokostandards" ]; then git clone --depth 1 --branch version/04 --quiet \ - "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \ + "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoCli.git" \ /tmp/mokostandards 2>/dev/null || true if [ -f "/tmp/mokostandards/composer.json" ]; then cd /tmp/mokostandards && composer install --no-dev --no-interaction --quiet 2>/dev/null || true @@ -2048,10 +2048,10 @@ jobs: if [ -f "composer.json" ]; then composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader else - echo "No composer.json — pulling MokoStandards tools" + echo "No composer.json — pulling MokoCli tools" if [ ! -d "/tmp/mokostandards" ]; then git clone --depth 1 --branch version/04 --quiet \ - "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \ + "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoCli.git" \ /tmp/mokostandards 2>/dev/null || true if [ -f "/tmp/mokostandards/composer.json" ]; then cd /tmp/mokostandards && composer install --no-dev --no-interaction --quiet 2>/dev/null || true @@ -2133,7 +2133,7 @@ jobs: # 1. Check .github/config.tf location (not root override files) echo "### Override Configuration Check" >> $GITHUB_STEP_SUMMARY - LEGACY_OVERRIDES=$(find . -maxdepth 1 -name "*override*.tf" -o -name "MokoStandards.override.tf" 2>/dev/null | wc -l || echo 0) + LEGACY_OVERRIDES=$(find . -maxdepth 1 -name "*override*.tf" -o -name "MokoCli.override.tf" 2>/dev/null | wc -l || echo 0) if [ "$LEGACY_OVERRIDES" -gt 0 ]; then echo "⚠️ Found legacy override files in root directory" >> $GITHUB_STEP_SUMMARY echo "**Expected Location**: .github/config.tf" >> $GITHUB_STEP_SUMMARY @@ -2299,7 +2299,7 @@ jobs: - name: Generate Compliance Report run: | set -x - echo "# 📊 MokoStandards Compliance Report" >> $GITHUB_STEP_SUMMARY + echo "# 📊 MokoCli Compliance Report" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY # Calculate overall status @@ -2486,7 +2486,7 @@ jobs: else echo "## 🎉 Excellent!" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "Your repository is **fully compliant** with MokoStandards!" >> $GITHUB_STEP_SUMMARY + echo "Your repository is **fully compliant** with MokoCli!" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "**Achievements:**" >> $GITHUB_STEP_SUMMARY echo "- ✅ All required directories and files present" >> $GITHUB_STEP_SUMMARY @@ -2501,12 +2501,12 @@ jobs: echo "---" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "📚 **Resources:**" >> $GITHUB_STEP_SUMMARY - echo "- [MokoStandards Documentation](https://github.com/mokoconsulting-tech/MokoStandards)" >> $GITHUB_STEP_SUMMARY - echo "- [Repository Structure Guide](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/docs/policy/core-structure.md)" >> $GITHUB_STEP_SUMMARY - echo "- [Documentation Standards](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/docs/policy/document-formatting.md)" >> $GITHUB_STEP_SUMMARY - echo "- [Coding Standards](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/docs/policy/coding-style-guide.md)" >> $GITHUB_STEP_SUMMARY + echo "- [MokoCli Documentation](https://github.com/mokoconsulting-tech/MokoCli)" >> $GITHUB_STEP_SUMMARY + echo "- [Repository Structure Guide](https://github.com/mokoconsulting-tech/MokoCli/tree/main/docs/policy/core-structure.md)" >> $GITHUB_STEP_SUMMARY + echo "- [Documentation Standards](https://github.com/mokoconsulting-tech/MokoCli/tree/main/docs/policy/document-formatting.md)" >> $GITHUB_STEP_SUMMARY + echo "- [Coding Standards](https://github.com/mokoconsulting-tech/MokoCli/tree/main/docs/policy/coding-style-guide.md)" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "_Generated by MokoStandards Compliance Workflow v${WORKFLOW_VERSION}_" >> $GITHUB_STEP_SUMMARY + echo "_Generated by MokoCli Compliance Workflow v${WORKFLOW_VERSION}_" >> $GITHUB_STEP_SUMMARY # Create tracking issue for non-compliance if on push if [ "$COMPLIANCE_PERCENT" -lt 100 ] && [ "${{ github.event_name }}" = "push" ]; then @@ -2530,9 +2530,9 @@ jobs: echo "### ✅ Full Standards Compliance Achieved" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "**Overall Compliance:** 100%" >> $GITHUB_STEP_SUMMARY - echo "**Status:** Repository meets all MokoStandards requirements" >> $GITHUB_STEP_SUMMARY + echo "**Status:** Repository meets all MokoCli requirements" >> $GITHUB_STEP_SUMMARY echo "" - echo "✅ SUCCESS: Repository is fully MokoStandards compliant" + echo "✅ SUCCESS: Repository is fully MokoCli compliant" - name: Create or reopen tracking issue for standards violations if: failure() diff --git a/mcp/servers/windows/.mokogitea/workflows/sync-version-on-merge.yml b/mcp/servers/windows/.mokogitea/workflows/sync-version-on-merge.yml index dbdcd6c..a3238bd 100644 --- a/mcp/servers/windows/.mokogitea/workflows/sync-version-on-merge.yml +++ b/mcp/servers/windows/.mokogitea/workflows/sync-version-on-merge.yml @@ -6,8 +6,8 @@ # # FILE INFORMATION # DEFGROUP: GitHub.Workflow -# INGROUP: MokoStandards.Automation -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCli.Automation +# REPO: https://github.com/mokoconsulting-tech/MokoCli # PATH: /templates/workflows/shared/sync-version-on-merge.yml.template # VERSION: 04.06.00 # BRIEF: Auto-bump patch version on every push to main and propagate to all file headers @@ -53,13 +53,13 @@ jobs: php-version: '8.1' tools: composer - - name: Setup MokoStandards tools + - name: Setup MokoCli tools env: GH_TOKEN: ${{ secrets.GH_PAT || github.token }} COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_PAT || github.token }}"}}' run: | git clone --depth 1 --branch version/04 --quiet \ - "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \ + "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoCli.git" \ /tmp/mokostandards cd /tmp/mokostandards composer install --no-dev --no-interaction --quiet diff --git a/mcp/servers/windows/README.md b/mcp/servers/windows/README.md index da2e99d..4b41e2e 100644 --- a/mcp/servers/windows/README.md +++ b/mcp/servers/windows/README.md @@ -2,7 +2,7 @@ ![Language](https://img.shields.io/badge/language-TypeScript-3178C6?style=flat-square&logo=typescript&logoColor=white) ![License](https://img.shields.io/badge/license-GPL--3.0--or--later-green?style=flat-square) ![Platform](https://img.shields.io/badge/platform-Node.js%20%7C%20MCP-339933?style=flat-square&logo=node.js&logoColor=white) ![Wiki](https://img.shields.io/badge/wiki-Template--MCP-blue?style=flat-square) -Template repository for creating MokoStandards-compliant Model Context Protocol (MCP) API servers. Provides the scaffolding, configuration patterns, and architecture conventions used by all Moko Consulting MCP servers, enabling AI assistants like Claude to interact with REST APIs through a standardized tool interface. +Template repository for creating MokoCli-compliant Model Context Protocol (MCP) API servers. Provides the scaffolding, configuration patterns, and architecture conventions used by all Moko Consulting MCP servers, enabling AI assistants like Claude to interact with REST APIs through a standardized tool interface. ## Features @@ -11,7 +11,7 @@ Template repository for creating MokoStandards-compliant Model Context Protocol - **REST API bridge architecture** -- standardized pattern for bridging any REST API as MCP tools, with typed request/response handling - **TypeScript-first** -- full TypeScript setup with `tsconfig.json`, strict mode, and ES module output - **Build tooling** -- Makefile with `build`, `dev`, `clean`, and `lint` targets; npm scripts for compilation and development -- **MokoStandards compliant** -- follows all Moko Consulting governance conventions: file headers, commit messages, `.gitattributes`, `.gitmessage`, PR/issue templates +- **MokoCli compliant** -- follows all Moko Consulting governance conventions: file headers, commit messages, `.gitattributes`, `.gitmessage`, PR/issue templates - **Example configuration** -- `config.example.json` demonstrates the connection configuration schema - **Documentation templates** -- wiki pages for API reference, architecture overview, and installation pre-generated @@ -77,4 +77,4 @@ This project is licensed under the GNU General Public License v3.0 or later -- s --- -*[Moko Consulting](https://mokoconsulting.tech) -- [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki/Home)* +*[Moko Consulting](https://mokoconsulting.tech) -- [MokoCli](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki/Home)* diff --git a/mcp/src/config.ts b/mcp/src/config.ts index b62052a..71b4ed5 100644 --- a/mcp/src/config.ts +++ b/mcp/src/config.ts @@ -6,10 +6,10 @@ * * FILE INFORMATION * DEFGROUP: mokostandards-mcp.Config - * INGROUP: MokoStandards-API + * INGROUP: MokoCli-API * REPO: https://git.mokoconsulting.tech/MokoConsulting/mokoplatform * PATH: /mcp/src/config.ts - * BRIEF: Configuration loader for MokoStandards MCP server + * BRIEF: Configuration loader for MokoCli MCP server */ import { readFile } from 'node:fs/promises'; @@ -30,7 +30,7 @@ export async function loadConfig(): Promise { const parsed = JSON.parse(raw) as Partial; if (!parsed.apiPath) { - throw new Error('apiPath is required — path to MokoStandards-API root'); + throw new Error('apiPath is required — path to MokoCli-API root'); } return { @@ -40,7 +40,7 @@ export async function loadConfig(): Promise { giteaToken: parsed.giteaToken, }; } catch (err) { - // Auto-detect: if running from within MokoStandards-API/mcp/dist/, resolve parent + // Auto-detect: if running from within MokoCli-API/mcp/dist/, resolve parent const scriptDir = dirname(fileURLToPath(import.meta.url)); const autoApiPath = resolve(scriptDir, '..', '..'); @@ -54,7 +54,7 @@ export async function loadConfig(): Promise { const message = err instanceof Error ? err.message : String(err); throw new Error( `Failed to load config from ${config_path}: ${message}\n` + - `Create ${config_path} with { "apiPath": "/path/to/MokoStandards-API" }`, + `Create ${config_path} with { "apiPath": "/path/to/MokoCli-API" }`, ); } } diff --git a/mcp/src/index.ts b/mcp/src/index.ts index ebc74fb..7e042d4 100644 --- a/mcp/src/index.ts +++ b/mcp/src/index.ts @@ -7,10 +7,10 @@ * * FILE INFORMATION * DEFGROUP: mokostandards-mcp.Server - * INGROUP: MokoStandards-API + * INGROUP: MokoCli-API * REPO: https://git.mokoconsulting.tech/MokoConsulting/mokoplatform * PATH: /mcp/src/index.ts - * BRIEF: MCP server entry point — exposes MokoStandards governance tools + * BRIEF: MCP server entry point — exposes MokoCli governance tools */ import { readFile, readdir } from 'node:fs/promises'; @@ -297,7 +297,7 @@ server.tool( server.tool( 'standards_list_repos', - 'List all repositories that have been synced with MokoStandards (from sync definitions)', + 'List all repositories that have been synced with MokoCli (from sync definitions)', {}, async () => { const syncDir = resolve(config.apiPath, 'definitions', 'sync'); @@ -343,25 +343,25 @@ server.tool( server.tool( 'standards_list_policies', - 'List available MokoStandards policy documents', + 'List available MokoCli policy documents', {}, async () => { const docsPath = config.standardsPath ? resolve(config.standardsPath, 'docs', 'policy') - : resolve(config.apiPath, '..', 'MokoStandards', 'docs', 'policy'); + : resolve(config.apiPath, '..', 'MokoCli', 'docs', 'policy'); try { const files = await readdir(docsPath); const docs = files.filter(f => f.endsWith('.md')).map(f => ` - ${f}`); return textResult(`Policy documents:\n${docs.join('\n')}`); } catch { - return textResult(`Could not list policies. Set standardsPath in config to the MokoStandards root.`); + return textResult(`Could not list policies. Set standardsPath in config to the MokoCli root.`); } }, ); server.tool( 'standards_read_policy', - 'Read a specific MokoStandards policy document', + 'Read a specific MokoCli policy document', { filename: z.string().describe('Policy filename (e.g. "core-structure.md", "file-header-standards.md")'), }, @@ -369,7 +369,7 @@ server.tool( const safe = basename(filename); const docsPath = config.standardsPath ? resolve(config.standardsPath, 'docs', 'policy') - : resolve(config.apiPath, '..', 'MokoStandards', 'docs', 'policy'); + : resolve(config.apiPath, '..', 'MokoCli', 'docs', 'policy'); try { const content = await readFile(resolve(docsPath, safe), 'utf-8'); return textResult(content); @@ -381,14 +381,14 @@ server.tool( server.tool( 'standards_read_guide', - 'Read a specific MokoStandards guide document', + 'Read a specific MokoCli guide document', { path: z.string().describe('Relative path within docs/guide/ (e.g. "validation/auto-detection.md")'), }, async ({ path }) => { const docsPath = config.standardsPath ? resolve(config.standardsPath, 'docs', 'guide') - : resolve(config.apiPath, '..', 'MokoStandards', 'docs', 'guide'); + : resolve(config.apiPath, '..', 'MokoCli', 'docs', 'guide'); try { const content = await readFile(resolve(docsPath, path), 'utf-8'); return textResult(content); @@ -402,7 +402,7 @@ server.tool( server.tool( 'standards_check_wiki', - 'Check wiki health for a repository — verifies Home page exists, has MokoStandards reference, and pages are indexed', + 'Check wiki health for a repository — verifies Home page exists, has MokoCli reference, and pages are indexed', { repo_path: z.string().describe('Path to the repository'), }, @@ -438,12 +438,12 @@ server.tool( server.tool( 'standards_info', - 'Get MokoStandards server info — API path, standards version, available tools', + 'Get MokoCli server info — API path, standards version, available tools', {}, async () => { let version = 'unknown'; try { - const readme = await readFile(resolve(config.apiPath, '..', 'MokoStandards', 'README.md'), 'utf-8'); + const readme = await readFile(resolve(config.apiPath, '..', 'MokoCli', 'README.md'), 'utf-8'); const match = readme.match(/VERSION:\s*([\d.]+)/); if (match) version = match[1]; } catch { /* ignore */ } @@ -463,7 +463,7 @@ server.tool( } catch { /* ignore */ } return textResult([ - `MokoStandards MCP Server`, + `MokoCli MCP Server`, ` Standards version: ${version}`, ` API path: ${config.apiPath}`, ` Standards path: ${config.standardsPath ?? 'auto-detect'}`, diff --git a/mcp/src/runner.ts b/mcp/src/runner.ts index 528a37d..c98f451 100644 --- a/mcp/src/runner.ts +++ b/mcp/src/runner.ts @@ -6,10 +6,10 @@ * * FILE INFORMATION * DEFGROUP: mokostandards-mcp.Runner - * INGROUP: MokoStandards-API + * INGROUP: MokoCli-API * REPO: https://git.mokoconsulting.tech/MokoConsulting/mokoplatform * PATH: /mcp/src/runner.ts - * BRIEF: PHP CLI command runner for MokoStandards tools — uses execFile (no shell injection) + * BRIEF: PHP CLI command runner for MokoCli tools — uses execFile (no shell injection) */ import { execFile as nodeExecFile } from 'node:child_process'; @@ -19,7 +19,7 @@ import type { StandardsConfig, ExecResult } from './types.js'; const TIMEOUT_MS = 60_000; /** - * Runs MokoStandards PHP CLI tools via execFile (safe, no shell). + * Runs MokoCli PHP CLI tools via execFile (safe, no shell). * All arguments are passed as array elements — never interpolated into a shell string. */ export class StandardsRunner { diff --git a/mcp/src/types.ts b/mcp/src/types.ts index 275273e..461a0d5 100644 --- a/mcp/src/types.ts +++ b/mcp/src/types.ts @@ -6,16 +6,16 @@ * * FILE INFORMATION * DEFGROUP: mokostandards-mcp.Types - * INGROUP: MokoStandards-API + * INGROUP: MokoCli-API * REPO: https://git.mokoconsulting.tech/MokoConsulting/mokoplatform * PATH: /mcp/src/types.ts - * BRIEF: TypeScript type definitions for MokoStandards MCP server + * BRIEF: TypeScript type definitions for MokoCli MCP server */ export interface StandardsConfig { - /** Path to MokoStandards-API root (contains cli/, validate/, definitions/) */ + /** Path to MokoCli-API root (contains cli/, validate/, definitions/) */ apiPath: string; - /** Path to MokoStandards root (contains docs/) */ + /** Path to MokoCli root (contains docs/) */ standardsPath?: string; /** Gitea API base URL */ giteaUrl?: string; diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 4f77b05..9bf9bce 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -457,277 +457,277 @@ parameters: path: lib/CliBase.php - - message: '#^Method MokoEnterprise\\AbstractProjectPlugin\:\:__construct\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\AbstractProjectPlugin\:\:__construct\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AbstractProjectPlugin.php - - message: '#^Method MokoEnterprise\\AbstractProjectPlugin\:\:checkReadiness\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\AbstractProjectPlugin\:\:checkReadiness\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AbstractProjectPlugin.php - - message: '#^Method MokoEnterprise\\AbstractProjectPlugin\:\:checkReadiness\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\AbstractProjectPlugin\:\:checkReadiness\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AbstractProjectPlugin.php - - message: '#^Method MokoEnterprise\\AbstractProjectPlugin\:\:collectMetrics\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\AbstractProjectPlugin\:\:collectMetrics\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AbstractProjectPlugin.php - - message: '#^Method MokoEnterprise\\AbstractProjectPlugin\:\:collectMetrics\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\AbstractProjectPlugin\:\:collectMetrics\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AbstractProjectPlugin.php - - message: '#^Method MokoEnterprise\\AbstractProjectPlugin\:\:findFiles\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\AbstractProjectPlugin\:\:findFiles\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AbstractProjectPlugin.php - - message: '#^Method MokoEnterprise\\AbstractProjectPlugin\:\:getBestPractices\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\AbstractProjectPlugin\:\:getBestPractices\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AbstractProjectPlugin.php - - message: '#^Method MokoEnterprise\\AbstractProjectPlugin\:\:getCommands\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\AbstractProjectPlugin\:\:getCommands\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AbstractProjectPlugin.php - - message: '#^Method MokoEnterprise\\AbstractProjectPlugin\:\:getConfigSchema\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\AbstractProjectPlugin\:\:getConfigSchema\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AbstractProjectPlugin.php - - message: '#^Method MokoEnterprise\\AbstractProjectPlugin\:\:getRecommendedFiles\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\AbstractProjectPlugin\:\:getRecommendedFiles\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AbstractProjectPlugin.php - - message: '#^Method MokoEnterprise\\AbstractProjectPlugin\:\:getRequiredFiles\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\AbstractProjectPlugin\:\:getRequiredFiles\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AbstractProjectPlugin.php - - message: '#^Method MokoEnterprise\\AbstractProjectPlugin\:\:healthCheck\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\AbstractProjectPlugin\:\:healthCheck\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AbstractProjectPlugin.php - - message: '#^Method MokoEnterprise\\AbstractProjectPlugin\:\:healthCheck\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\AbstractProjectPlugin\:\:healthCheck\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AbstractProjectPlugin.php - - message: '#^Method MokoEnterprise\\AbstractProjectPlugin\:\:initializeProject\(\) has parameter \$options with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\AbstractProjectPlugin\:\:initializeProject\(\) has parameter \$options with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AbstractProjectPlugin.php - - message: '#^Method MokoEnterprise\\AbstractProjectPlugin\:\:initializeProject\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\AbstractProjectPlugin\:\:initializeProject\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AbstractProjectPlugin.php - - message: '#^Method MokoEnterprise\\AbstractProjectPlugin\:\:log\(\) has parameter \$context with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\AbstractProjectPlugin\:\:log\(\) has parameter \$context with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AbstractProjectPlugin.php - - message: '#^Method MokoEnterprise\\AbstractProjectPlugin\:\:parseJsonFile\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\AbstractProjectPlugin\:\:parseJsonFile\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AbstractProjectPlugin.php - - message: '#^Method MokoEnterprise\\AbstractProjectPlugin\:\:recordMetric\(\) has parameter \$tags with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\AbstractProjectPlugin\:\:recordMetric\(\) has parameter \$tags with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AbstractProjectPlugin.php - - message: '#^Method MokoEnterprise\\AbstractProjectPlugin\:\:validateProject\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\AbstractProjectPlugin\:\:validateProject\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AbstractProjectPlugin.php - - message: '#^Method MokoEnterprise\\AbstractProjectPlugin\:\:validateProject\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\AbstractProjectPlugin\:\:validateProject\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AbstractProjectPlugin.php - - message: '#^Property MokoEnterprise\\AbstractProjectPlugin\:\:\$config type has no value type specified in iterable type array\.$#' + message: '#^Property MokoCli\\AbstractProjectPlugin\:\:\$config type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AbstractProjectPlugin.php - - message: '#^Constructor of class MokoEnterprise\\ApiClient has an unused parameter \$logger\.$#' + message: '#^Constructor of class MokoCli\\ApiClient has an unused parameter \$logger\.$#' identifier: constructor.unusedParameter count: 1 path: lib/Enterprise/ApiClient.php - - message: '#^Method MokoEnterprise\\ApiClient\:\:delete\(\) has parameter \$body with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\ApiClient\:\:delete\(\) has parameter \$body with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/ApiClient.php - - message: '#^Method MokoEnterprise\\AuditLogger\:\:logError\(\) has parameter \$data with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\AuditLogger\:\:logError\(\) has parameter \$data with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AuditLogger.php - - message: '#^Method MokoEnterprise\\AuditLogger\:\:logEvent\(\) has parameter \$data with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\AuditLogger\:\:logEvent\(\) has parameter \$data with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AuditLogger.php - - message: '#^Method MokoEnterprise\\AuditLogger\:\:logInfo\(\) has parameter \$data with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\AuditLogger\:\:logInfo\(\) has parameter \$data with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AuditLogger.php - - message: '#^Method MokoEnterprise\\AuditLogger\:\:logMessage\(\) has parameter \$data with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\AuditLogger\:\:logMessage\(\) has parameter \$data with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AuditLogger.php - - message: '#^Method MokoEnterprise\\AuditLogger\:\:logSecurityEvent\(\) has parameter \$data with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\AuditLogger\:\:logSecurityEvent\(\) has parameter \$data with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AuditLogger.php - - message: '#^Method MokoEnterprise\\AuditLogger\:\:logSystemEvent\(\) has parameter \$data with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\AuditLogger\:\:logSystemEvent\(\) has parameter \$data with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AuditLogger.php - - message: '#^Method MokoEnterprise\\AuditLogger\:\:logWarning\(\) has parameter \$data with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\AuditLogger\:\:logWarning\(\) has parameter \$data with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AuditLogger.php - - message: '#^Method MokoEnterprise\\AuditLogger\:\:startTransaction\(\) has parameter \$context with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\AuditLogger\:\:startTransaction\(\) has parameter \$context with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AuditLogger.php - - message: '#^Method MokoEnterprise\\AuditLogger\:\:writeLogEntry\(\) has parameter \$entry with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\AuditLogger\:\:writeLogEntry\(\) has parameter \$entry with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AuditLogger.php - - message: '#^Method MokoEnterprise\\AuditTransaction\:\:__construct\(\) has parameter \$context with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\AuditTransaction\:\:__construct\(\) has parameter \$context with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AuditLogger.php - - message: '#^Method MokoEnterprise\\AuditTransaction\:\:end\(\) has parameter \$result with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\AuditTransaction\:\:end\(\) has parameter \$result with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AuditLogger.php - - message: '#^Method MokoEnterprise\\AuditTransaction\:\:logEvent\(\) has parameter \$data with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\AuditTransaction\:\:logEvent\(\) has parameter \$data with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AuditLogger.php - - message: '#^Method MokoEnterprise\\AuditTransaction\:\:logSecurityEvent\(\) has parameter \$data with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\AuditTransaction\:\:logSecurityEvent\(\) has parameter \$data with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AuditLogger.php - - message: '#^Property MokoEnterprise\\AuditLogger\:\:\$retentionDays is never read, only written\.$#' + message: '#^Property MokoCli\\AuditLogger\:\:\$retentionDays is never read, only written\.$#' identifier: property.onlyWritten count: 1 path: lib/Enterprise/AuditLogger.php - - message: '#^Property MokoEnterprise\\AuditLogger\:\:\$transactionStack type has no value type specified in iterable type array\.$#' + message: '#^Property MokoCli\\AuditLogger\:\:\$transactionStack type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AuditLogger.php - - message: '#^Property MokoEnterprise\\AuditTransaction\:\:\$context type has no value type specified in iterable type array\.$#' + message: '#^Property MokoCli\\AuditTransaction\:\:\$context type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/AuditLogger.php - - message: '#^Property MokoEnterprise\\CLIApp\:\:\$arguments type has no value type specified in iterable type array\.$#' + message: '#^Property MokoCli\\CLIApp\:\:\$arguments type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/CliFramework.php - - message: '#^Property MokoEnterprise\\CLIApp\:\:\$options type has no value type specified in iterable type array\.$#' + message: '#^Property MokoCli\\CLIApp\:\:\$options type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/CliFramework.php - - message: '#^Method MokoEnterprise\\EnterpriseReadinessValidator\:\:getFailedChecks\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\EnterpriseReadinessValidator\:\:getFailedChecks\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/EnterpriseReadinessValidator.php - - message: '#^Method MokoEnterprise\\EnterpriseReadinessValidator\:\:getPassedChecks\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\EnterpriseReadinessValidator\:\:getPassedChecks\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/EnterpriseReadinessValidator.php - - message: '#^Method MokoEnterprise\\EnterpriseReadinessValidator\:\:getResults\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\EnterpriseReadinessValidator\:\:getResults\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/EnterpriseReadinessValidator.php - - message: '#^Method MokoEnterprise\\EnterpriseReadinessValidator\:\:validate\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\EnterpriseReadinessValidator\:\:validate\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/EnterpriseReadinessValidator.php - - message: '#^Property MokoEnterprise\\EnterpriseReadinessValidator\:\:\$results type has no value type specified in iterable type array\.$#' + message: '#^Property MokoCli\\EnterpriseReadinessValidator\:\:\$results type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/EnterpriseReadinessValidator.php @@ -739,31 +739,31 @@ parameters: path: lib/Enterprise/GitHubAdapter.php - - message: '#^Method MokoEnterprise\\MetricsTimer\:\:__construct\(\) has parameter \$labels with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\MetricsTimer\:\:__construct\(\) has parameter \$labels with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/MetricsCollector.php - - message: '#^Property MokoEnterprise\\MetricsCollector\:\:\$counters type has no value type specified in iterable type array\.$#' + message: '#^Property MokoCli\\MetricsCollector\:\:\$counters type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/MetricsCollector.php - - message: '#^Property MokoEnterprise\\MetricsCollector\:\:\$gauges type has no value type specified in iterable type array\.$#' + message: '#^Property MokoCli\\MetricsCollector\:\:\$gauges type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/MetricsCollector.php - - message: '#^Property MokoEnterprise\\MetricsCollector\:\:\$histograms type has no value type specified in iterable type array\.$#' + message: '#^Property MokoCli\\MetricsCollector\:\:\$histograms type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/MetricsCollector.php - - message: '#^Property MokoEnterprise\\MetricsTimer\:\:\$labels type has no value type specified in iterable type array\.$#' + message: '#^Property MokoCli\\MetricsTimer\:\:\$labels type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/MetricsCollector.php @@ -775,277 +775,277 @@ parameters: path: lib/Enterprise/MokoGiteaAdapter.php - - message: '#^Method MokoEnterprise\\MokoStandardsParser\:\:generate\(\) has parameter \$params with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\MokoCliParser\:\:generate\(\) has parameter \$params with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 - path: lib/Enterprise/MokoStandardsParser.php + path: lib/Enterprise/MokoCliParser.php - - message: '#^Method MokoEnterprise\\MokoStandardsParser\:\:parse\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\MokoCliParser\:\:parse\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 4 - path: lib/Enterprise/MokoStandardsParser.php + path: lib/Enterprise/MokoCliParser.php - - message: '#^Method MokoEnterprise\\MokoStandardsParser\:\:parseBuild\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\MokoCliParser\:\:parseBuild\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 - path: lib/Enterprise/MokoStandardsParser.php + path: lib/Enterprise/MokoCliParser.php - - message: '#^Method MokoEnterprise\\MokoStandardsParser\:\:parseDeploy\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\MokoCliParser\:\:parseDeploy\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 - path: lib/Enterprise/MokoStandardsParser.php + path: lib/Enterprise/MokoCliParser.php - - message: '#^Method MokoEnterprise\\MokoStandardsParser\:\:parseGovernance\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\MokoCliParser\:\:parseGovernance\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 - path: lib/Enterprise/MokoStandardsParser.php + path: lib/Enterprise/MokoCliParser.php - - message: '#^Method MokoEnterprise\\MokoStandardsParser\:\:parseIdentity\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\MokoCliParser\:\:parseIdentity\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 - path: lib/Enterprise/MokoStandardsParser.php + path: lib/Enterprise/MokoCliParser.php - - message: '#^Method MokoEnterprise\\MokoStandardsParser\:\:parseLegacy\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\MokoCliParser\:\:parseLegacy\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 - path: lib/Enterprise/MokoStandardsParser.php + path: lib/Enterprise/MokoCliParser.php - - message: '#^Method MokoEnterprise\\MokoStandardsParser\:\:parseOverrides\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\MokoCliParser\:\:parseOverrides\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 - path: lib/Enterprise/MokoStandardsParser.php + path: lib/Enterprise/MokoCliParser.php - - message: '#^Method MokoEnterprise\\MokoStandardsParser\:\:parseScripts\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\MokoCliParser\:\:parseScripts\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 - path: lib/Enterprise/MokoStandardsParser.php + path: lib/Enterprise/MokoCliParser.php - - message: '#^Method MokoEnterprise\\MokoStandardsParser\:\:tryParse\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\MokoCliParser\:\:tryParse\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 - path: lib/Enterprise/MokoStandardsParser.php + path: lib/Enterprise/MokoCliParser.php - - message: '#^Method MokoEnterprise\\PluginFactory\:\:__construct\(\) has parameter \$defaultConfig with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\PluginFactory\:\:__construct\(\) has parameter \$defaultConfig with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/PluginFactory.php - - message: '#^Method MokoEnterprise\\PluginFactory\:\:checkReadiness\(\) has parameter \$projectConfig with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\PluginFactory\:\:checkReadiness\(\) has parameter \$projectConfig with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/PluginFactory.php - - message: '#^Method MokoEnterprise\\PluginFactory\:\:checkReadiness\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\PluginFactory\:\:checkReadiness\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/PluginFactory.php - - message: '#^Method MokoEnterprise\\PluginFactory\:\:collectMetrics\(\) has parameter \$projectConfig with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\PluginFactory\:\:collectMetrics\(\) has parameter \$projectConfig with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/PluginFactory.php - - message: '#^Method MokoEnterprise\\PluginFactory\:\:collectMetrics\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\PluginFactory\:\:collectMetrics\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/PluginFactory.php - - message: '#^Method MokoEnterprise\\PluginFactory\:\:create\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\PluginFactory\:\:create\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/PluginFactory.php - - message: '#^Method MokoEnterprise\\PluginFactory\:\:createAll\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\PluginFactory\:\:createAll\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/PluginFactory.php - - message: '#^Method MokoEnterprise\\PluginFactory\:\:createAndValidate\(\) has parameter \$projectConfig with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\PluginFactory\:\:createAndValidate\(\) has parameter \$projectConfig with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/PluginFactory.php - - message: '#^Method MokoEnterprise\\PluginFactory\:\:createAndValidate\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\PluginFactory\:\:createAndValidate\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/PluginFactory.php - - message: '#^Method MokoEnterprise\\PluginFactory\:\:createForProject\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\PluginFactory\:\:createForProject\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/PluginFactory.php - - message: '#^Method MokoEnterprise\\PluginFactory\:\:createMultiple\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\PluginFactory\:\:createMultiple\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/PluginFactory.php - - message: '#^Method MokoEnterprise\\PluginFactory\:\:createMultiple\(\) has parameter \$projectTypes with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\PluginFactory\:\:createMultiple\(\) has parameter \$projectTypes with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/PluginFactory.php - - message: '#^Method MokoEnterprise\\PluginFactory\:\:getAvailablePlugins\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\PluginFactory\:\:getAvailablePlugins\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/PluginFactory.php - - message: '#^Method MokoEnterprise\\PluginFactory\:\:getDefaultConfig\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\PluginFactory\:\:getDefaultConfig\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/PluginFactory.php - - message: '#^Method MokoEnterprise\\PluginFactory\:\:getStatistics\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\PluginFactory\:\:getStatistics\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/PluginFactory.php - - message: '#^Method MokoEnterprise\\PluginFactory\:\:runHealthCheck\(\) has parameter \$projectConfig with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\PluginFactory\:\:runHealthCheck\(\) has parameter \$projectConfig with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/PluginFactory.php - - message: '#^Method MokoEnterprise\\PluginFactory\:\:runHealthCheck\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\PluginFactory\:\:runHealthCheck\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/PluginFactory.php - - message: '#^Method MokoEnterprise\\PluginFactory\:\:setDefaultConfig\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\PluginFactory\:\:setDefaultConfig\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/PluginFactory.php - - message: '#^Property MokoEnterprise\\PluginFactory\:\:\$defaultConfig type has no value type specified in iterable type array\.$#' + message: '#^Property MokoCli\\PluginFactory\:\:\$defaultConfig type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/PluginFactory.php - - message: '#^Method MokoEnterprise\\PluginRegistry\:\:findPluginsByFeature\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\PluginRegistry\:\:findPluginsByFeature\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/PluginRegistry.php - - message: '#^Method MokoEnterprise\\PluginRegistry\:\:getAllPlugins\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\PluginRegistry\:\:getAllPlugins\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/PluginRegistry.php - - message: '#^Method MokoEnterprise\\PluginRegistry\:\:getAllPluginsInfo\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\PluginRegistry\:\:getAllPluginsInfo\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/PluginRegistry.php - - message: '#^Method MokoEnterprise\\PluginRegistry\:\:getPlugin\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\PluginRegistry\:\:getPlugin\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/PluginRegistry.php - - message: '#^Method MokoEnterprise\\PluginRegistry\:\:getPluginInfo\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\PluginRegistry\:\:getPluginInfo\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/PluginRegistry.php - - message: '#^Method MokoEnterprise\\PluginRegistry\:\:getRegisteredTypes\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\PluginRegistry\:\:getRegisteredTypes\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/PluginRegistry.php - - message: '#^Method MokoEnterprise\\PluginRegistry\:\:getStatistics\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\PluginRegistry\:\:getStatistics\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/PluginRegistry.php - - message: '#^Method MokoEnterprise\\Plugins\\ApiPlugin\:\:collectMetrics\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\ApiPlugin\:\:collectMetrics\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/ApiPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\ApiPlugin\:\:collectMetrics\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\ApiPlugin\:\:collectMetrics\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/ApiPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\ApiPlugin\:\:getBestPractices\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\ApiPlugin\:\:getBestPractices\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/ApiPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\ApiPlugin\:\:getConfigSchema\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\ApiPlugin\:\:getConfigSchema\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/ApiPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\ApiPlugin\:\:getRecommendedFiles\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\ApiPlugin\:\:getRecommendedFiles\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/ApiPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\ApiPlugin\:\:getRequiredFiles\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\ApiPlugin\:\:getRequiredFiles\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/ApiPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\ApiPlugin\:\:healthCheck\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\ApiPlugin\:\:healthCheck\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/ApiPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\ApiPlugin\:\:healthCheck\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\ApiPlugin\:\:healthCheck\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/ApiPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\ApiPlugin\:\:validateProject\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\ApiPlugin\:\:validateProject\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/ApiPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\ApiPlugin\:\:validateProject\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\ApiPlugin\:\:validateProject\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/ApiPlugin.php @@ -1063,199 +1063,199 @@ parameters: path: lib/Enterprise/Plugins/ApiPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\DocumentationPlugin\:\:collectMetrics\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\DocumentationPlugin\:\:collectMetrics\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/DocumentationPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\DocumentationPlugin\:\:collectMetrics\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\DocumentationPlugin\:\:collectMetrics\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/DocumentationPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\DocumentationPlugin\:\:getBestPractices\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\DocumentationPlugin\:\:getBestPractices\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/DocumentationPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\DocumentationPlugin\:\:getConfigSchema\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\DocumentationPlugin\:\:getConfigSchema\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/DocumentationPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\DocumentationPlugin\:\:getRecommendedFiles\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\DocumentationPlugin\:\:getRecommendedFiles\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/DocumentationPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\DocumentationPlugin\:\:getRequiredFiles\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\DocumentationPlugin\:\:getRequiredFiles\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/DocumentationPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\DocumentationPlugin\:\:healthCheck\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\DocumentationPlugin\:\:healthCheck\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/DocumentationPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\DocumentationPlugin\:\:healthCheck\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\DocumentationPlugin\:\:healthCheck\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/DocumentationPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\DocumentationPlugin\:\:validateProject\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\DocumentationPlugin\:\:validateProject\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/DocumentationPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\DocumentationPlugin\:\:validateProject\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\DocumentationPlugin\:\:validateProject\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/DocumentationPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\DolibarrPlugin\:\:collectMetrics\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\DolibarrPlugin\:\:collectMetrics\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/DolibarrPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\DolibarrPlugin\:\:collectMetrics\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\DolibarrPlugin\:\:collectMetrics\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/DolibarrPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\DolibarrPlugin\:\:getBestPractices\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\DolibarrPlugin\:\:getBestPractices\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/DolibarrPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\DolibarrPlugin\:\:getConfigSchema\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\DolibarrPlugin\:\:getConfigSchema\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/DolibarrPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\DolibarrPlugin\:\:getRecommendedFiles\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\DolibarrPlugin\:\:getRecommendedFiles\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/DolibarrPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\DolibarrPlugin\:\:getRequiredFiles\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\DolibarrPlugin\:\:getRequiredFiles\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/DolibarrPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\DolibarrPlugin\:\:healthCheck\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\DolibarrPlugin\:\:healthCheck\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/DolibarrPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\DolibarrPlugin\:\:healthCheck\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\DolibarrPlugin\:\:healthCheck\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/DolibarrPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\DolibarrPlugin\:\:parseDescriptor\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\DolibarrPlugin\:\:parseDescriptor\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/DolibarrPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\DolibarrPlugin\:\:validateProject\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\DolibarrPlugin\:\:validateProject\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/DolibarrPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\DolibarrPlugin\:\:validateProject\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\DolibarrPlugin\:\:validateProject\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/DolibarrPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\GenericPlugin\:\:collectMetrics\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\GenericPlugin\:\:collectMetrics\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/GenericPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\GenericPlugin\:\:collectMetrics\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\GenericPlugin\:\:collectMetrics\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/GenericPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\GenericPlugin\:\:countByExtension\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\GenericPlugin\:\:countByExtension\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/GenericPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\GenericPlugin\:\:getBestPractices\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\GenericPlugin\:\:getBestPractices\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/GenericPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\GenericPlugin\:\:getConfigSchema\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\GenericPlugin\:\:getConfigSchema\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/GenericPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\GenericPlugin\:\:getDominantFileType\(\) has parameter \$extensions with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\GenericPlugin\:\:getDominantFileType\(\) has parameter \$extensions with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/GenericPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\GenericPlugin\:\:getRecommendedFiles\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\GenericPlugin\:\:getRecommendedFiles\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/GenericPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\GenericPlugin\:\:getRequiredFiles\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\GenericPlugin\:\:getRequiredFiles\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/GenericPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\GenericPlugin\:\:healthCheck\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\GenericPlugin\:\:healthCheck\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/GenericPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\GenericPlugin\:\:healthCheck\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\GenericPlugin\:\:healthCheck\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/GenericPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\GenericPlugin\:\:validateProject\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\GenericPlugin\:\:validateProject\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/GenericPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\GenericPlugin\:\:validateProject\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\GenericPlugin\:\:validateProject\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/GenericPlugin.php @@ -1267,187 +1267,187 @@ parameters: path: lib/Enterprise/Plugins/GenericPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\JoomlaPlugin\:\:collectMetrics\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\JoomlaPlugin\:\:collectMetrics\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/JoomlaPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\JoomlaPlugin\:\:collectMetrics\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\JoomlaPlugin\:\:collectMetrics\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/JoomlaPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\JoomlaPlugin\:\:getBestPractices\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\JoomlaPlugin\:\:getBestPractices\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/JoomlaPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\JoomlaPlugin\:\:getConfigSchema\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\JoomlaPlugin\:\:getConfigSchema\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/JoomlaPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\JoomlaPlugin\:\:getRecommendedFiles\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\JoomlaPlugin\:\:getRecommendedFiles\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/JoomlaPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\JoomlaPlugin\:\:getRequiredFiles\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\JoomlaPlugin\:\:getRequiredFiles\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/JoomlaPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\JoomlaPlugin\:\:healthCheck\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\JoomlaPlugin\:\:healthCheck\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/JoomlaPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\JoomlaPlugin\:\:healthCheck\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\JoomlaPlugin\:\:healthCheck\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/JoomlaPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\JoomlaPlugin\:\:parseManifest\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\JoomlaPlugin\:\:parseManifest\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/JoomlaPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\JoomlaPlugin\:\:validateProject\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\JoomlaPlugin\:\:validateProject\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/JoomlaPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\JoomlaPlugin\:\:validateProject\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\JoomlaPlugin\:\:validateProject\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/JoomlaPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\McpServerPlugin\:\:collectMetrics\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\McpServerPlugin\:\:collectMetrics\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/McpServerPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\McpServerPlugin\:\:collectMetrics\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\McpServerPlugin\:\:collectMetrics\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/McpServerPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\McpServerPlugin\:\:getBestPractices\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\McpServerPlugin\:\:getBestPractices\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/McpServerPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\McpServerPlugin\:\:getConfigSchema\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\McpServerPlugin\:\:getConfigSchema\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/McpServerPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\McpServerPlugin\:\:getRecommendedFiles\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\McpServerPlugin\:\:getRecommendedFiles\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/McpServerPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\McpServerPlugin\:\:getRequiredFiles\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\McpServerPlugin\:\:getRequiredFiles\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/McpServerPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\McpServerPlugin\:\:healthCheck\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\McpServerPlugin\:\:healthCheck\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/McpServerPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\McpServerPlugin\:\:healthCheck\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\McpServerPlugin\:\:healthCheck\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/McpServerPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\McpServerPlugin\:\:validateProject\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\McpServerPlugin\:\:validateProject\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/McpServerPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\McpServerPlugin\:\:validateProject\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\McpServerPlugin\:\:validateProject\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/McpServerPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\MobilePlugin\:\:collectMetrics\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\MobilePlugin\:\:collectMetrics\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/MobilePlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\MobilePlugin\:\:collectMetrics\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\MobilePlugin\:\:collectMetrics\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/MobilePlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\MobilePlugin\:\:getBestPractices\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\MobilePlugin\:\:getBestPractices\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/MobilePlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\MobilePlugin\:\:getConfigSchema\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\MobilePlugin\:\:getConfigSchema\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/MobilePlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\MobilePlugin\:\:getRecommendedFiles\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\MobilePlugin\:\:getRecommendedFiles\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/MobilePlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\MobilePlugin\:\:getRequiredFiles\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\MobilePlugin\:\:getRequiredFiles\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/MobilePlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\MobilePlugin\:\:healthCheck\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\MobilePlugin\:\:healthCheck\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/MobilePlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\MobilePlugin\:\:healthCheck\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\MobilePlugin\:\:healthCheck\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/MobilePlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\MobilePlugin\:\:validateProject\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\MobilePlugin\:\:validateProject\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/MobilePlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\MobilePlugin\:\:validateProject\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\MobilePlugin\:\:validateProject\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/MobilePlugin.php @@ -1459,97 +1459,97 @@ parameters: path: lib/Enterprise/Plugins/MobilePlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\NodeJsPlugin\:\:collectMetrics\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\NodeJsPlugin\:\:collectMetrics\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/NodeJsPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\NodeJsPlugin\:\:collectMetrics\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\NodeJsPlugin\:\:collectMetrics\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/NodeJsPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\NodeJsPlugin\:\:countDependencies\(\) has parameter \$packageData with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\NodeJsPlugin\:\:countDependencies\(\) has parameter \$packageData with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/NodeJsPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\NodeJsPlugin\:\:countScripts\(\) has parameter \$packageData with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\NodeJsPlugin\:\:countScripts\(\) has parameter \$packageData with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/NodeJsPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\NodeJsPlugin\:\:detectFramework\(\) has parameter \$packageData with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\NodeJsPlugin\:\:detectFramework\(\) has parameter \$packageData with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/NodeJsPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\NodeJsPlugin\:\:getBestPractices\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\NodeJsPlugin\:\:getBestPractices\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/NodeJsPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\NodeJsPlugin\:\:getConfigSchema\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\NodeJsPlugin\:\:getConfigSchema\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/NodeJsPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\NodeJsPlugin\:\:getNodeVersion\(\) has parameter \$packageData with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\NodeJsPlugin\:\:getNodeVersion\(\) has parameter \$packageData with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/NodeJsPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\NodeJsPlugin\:\:getRecommendedFiles\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\NodeJsPlugin\:\:getRecommendedFiles\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/NodeJsPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\NodeJsPlugin\:\:getRequiredFiles\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\NodeJsPlugin\:\:getRequiredFiles\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/NodeJsPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\NodeJsPlugin\:\:hasOldDependencies\(\) has parameter \$packageData with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\NodeJsPlugin\:\:hasOldDependencies\(\) has parameter \$packageData with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/NodeJsPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\NodeJsPlugin\:\:hasTests\(\) has parameter \$packageData with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\NodeJsPlugin\:\:hasTests\(\) has parameter \$packageData with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/NodeJsPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\NodeJsPlugin\:\:healthCheck\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\NodeJsPlugin\:\:healthCheck\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/NodeJsPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\NodeJsPlugin\:\:healthCheck\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\NodeJsPlugin\:\:healthCheck\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/NodeJsPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\NodeJsPlugin\:\:validateProject\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\NodeJsPlugin\:\:validateProject\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/NodeJsPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\NodeJsPlugin\:\:validateProject\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\NodeJsPlugin\:\:validateProject\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/NodeJsPlugin.php @@ -1561,67 +1561,67 @@ parameters: path: lib/Enterprise/Plugins/NodeJsPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\PythonPlugin\:\:collectMetrics\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\PythonPlugin\:\:collectMetrics\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/PythonPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\PythonPlugin\:\:collectMetrics\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\PythonPlugin\:\:collectMetrics\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/PythonPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\PythonPlugin\:\:getBestPractices\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\PythonPlugin\:\:getBestPractices\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/PythonPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\PythonPlugin\:\:getConfigSchema\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\PythonPlugin\:\:getConfigSchema\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/PythonPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\PythonPlugin\:\:getRecommendedFiles\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\PythonPlugin\:\:getRecommendedFiles\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/PythonPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\PythonPlugin\:\:getRequiredFiles\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\PythonPlugin\:\:getRequiredFiles\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/PythonPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\PythonPlugin\:\:healthCheck\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\PythonPlugin\:\:healthCheck\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/PythonPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\PythonPlugin\:\:healthCheck\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\PythonPlugin\:\:healthCheck\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/PythonPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\PythonPlugin\:\:parsePyprojectToml\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\PythonPlugin\:\:parsePyprojectToml\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/PythonPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\PythonPlugin\:\:validateProject\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\PythonPlugin\:\:validateProject\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/PythonPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\PythonPlugin\:\:validateProject\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\PythonPlugin\:\:validateProject\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/PythonPlugin.php @@ -1633,181 +1633,181 @@ parameters: path: lib/Enterprise/Plugins/PythonPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\TerraformPlugin\:\:collectMetrics\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\TerraformPlugin\:\:collectMetrics\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/TerraformPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\TerraformPlugin\:\:collectMetrics\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\TerraformPlugin\:\:collectMetrics\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/TerraformPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\TerraformPlugin\:\:detectProviders\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\TerraformPlugin\:\:detectProviders\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/TerraformPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\TerraformPlugin\:\:getBestPractices\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\TerraformPlugin\:\:getBestPractices\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/TerraformPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\TerraformPlugin\:\:getConfigSchema\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\TerraformPlugin\:\:getConfigSchema\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/TerraformPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\TerraformPlugin\:\:getRecommendedFiles\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\TerraformPlugin\:\:getRecommendedFiles\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/TerraformPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\TerraformPlugin\:\:getRequiredFiles\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\TerraformPlugin\:\:getRequiredFiles\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/TerraformPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\TerraformPlugin\:\:healthCheck\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\TerraformPlugin\:\:healthCheck\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/TerraformPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\TerraformPlugin\:\:healthCheck\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\TerraformPlugin\:\:healthCheck\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/TerraformPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\TerraformPlugin\:\:validateProject\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\TerraformPlugin\:\:validateProject\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/TerraformPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\TerraformPlugin\:\:validateProject\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\TerraformPlugin\:\:validateProject\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/TerraformPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\WordPressPlugin\:\:collectMetrics\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\WordPressPlugin\:\:collectMetrics\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/WordPressPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\WordPressPlugin\:\:collectMetrics\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\WordPressPlugin\:\:collectMetrics\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/WordPressPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\WordPressPlugin\:\:getBestPractices\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\WordPressPlugin\:\:getBestPractices\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/WordPressPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\WordPressPlugin\:\:getConfigSchema\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\WordPressPlugin\:\:getConfigSchema\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/WordPressPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\WordPressPlugin\:\:getRecommendedFiles\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\WordPressPlugin\:\:getRecommendedFiles\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/WordPressPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\WordPressPlugin\:\:getRequiredFiles\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\WordPressPlugin\:\:getRequiredFiles\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/WordPressPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\WordPressPlugin\:\:healthCheck\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\WordPressPlugin\:\:healthCheck\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/WordPressPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\WordPressPlugin\:\:healthCheck\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\WordPressPlugin\:\:healthCheck\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/WordPressPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\WordPressPlugin\:\:parseHeader\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\WordPressPlugin\:\:parseHeader\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/WordPressPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\WordPressPlugin\:\:validateProject\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\WordPressPlugin\:\:validateProject\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/WordPressPlugin.php - - message: '#^Method MokoEnterprise\\Plugins\\WordPressPlugin\:\:validateProject\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\WordPressPlugin\:\:validateProject\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/Plugins/WordPressPlugin.php - - message: '#^Method MokoEnterprise\\ProjectConfigValidator\:\:getResults\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\ProjectConfigValidator\:\:getResults\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/ProjectConfigValidator.php - - message: '#^Method MokoEnterprise\\ProjectConfigValidator\:\:validate\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\ProjectConfigValidator\:\:validate\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/ProjectConfigValidator.php - - message: '#^Method MokoEnterprise\\ProjectConfigValidator\:\:validateNodeJSFields\(\) has parameter \$fields with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\ProjectConfigValidator\:\:validateNodeJSFields\(\) has parameter \$fields with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/ProjectConfigValidator.php - - message: '#^Method MokoEnterprise\\ProjectConfigValidator\:\:validateProjectFields\(\) has parameter \$fields with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\ProjectConfigValidator\:\:validateProjectFields\(\) has parameter \$fields with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/ProjectConfigValidator.php - - message: '#^Method MokoEnterprise\\ProjectConfigValidator\:\:validatePythonFields\(\) has parameter \$fields with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\ProjectConfigValidator\:\:validatePythonFields\(\) has parameter \$fields with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/ProjectConfigValidator.php - - message: '#^Method MokoEnterprise\\ProjectConfigValidator\:\:validateRecommendedFiles\(\) has parameter \$files with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\ProjectConfigValidator\:\:validateRecommendedFiles\(\) has parameter \$files with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/ProjectConfigValidator.php - - message: '#^Method MokoEnterprise\\ProjectConfigValidator\:\:validateRequiredFiles\(\) has parameter \$files with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\ProjectConfigValidator\:\:validateRequiredFiles\(\) has parameter \$files with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/ProjectConfigValidator.php - - message: '#^Method MokoEnterprise\\ProjectConfigValidator\:\:validateWordPressFields\(\) has parameter \$fields with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\ProjectConfigValidator\:\:validateWordPressFields\(\) has parameter \$fields with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/ProjectConfigValidator.php @@ -1831,169 +1831,169 @@ parameters: path: lib/Enterprise/ProjectConfigValidator.php - - message: '#^Property MokoEnterprise\\ProjectConfigValidator\:\:\$validationResults type has no value type specified in iterable type array\.$#' + message: '#^Property MokoCli\\ProjectConfigValidator\:\:\$validationResults type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/ProjectConfigValidator.php - - message: '#^Method MokoEnterprise\\ProjectMetricsCollector\:\:collect\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\ProjectMetricsCollector\:\:collect\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/ProjectMetricsCollector.php - - message: '#^Method MokoEnterprise\\ProjectMetricsCollector\:\:getMetrics\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\ProjectMetricsCollector\:\:getMetrics\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/ProjectMetricsCollector.php - - message: '#^Property MokoEnterprise\\ProjectMetricsCollector\:\:\$collectedMetrics type has no value type specified in iterable type array\.$#' + message: '#^Property MokoCli\\ProjectMetricsCollector\:\:\$collectedMetrics type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/ProjectMetricsCollector.php - - message: '#^Method MokoEnterprise\\ProjectPluginInterface\:\:checkReadiness\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\ProjectPluginInterface\:\:checkReadiness\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/ProjectPluginInterface.php - - message: '#^Method MokoEnterprise\\ProjectPluginInterface\:\:checkReadiness\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\ProjectPluginInterface\:\:checkReadiness\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/ProjectPluginInterface.php - - message: '#^Method MokoEnterprise\\ProjectPluginInterface\:\:collectMetrics\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\ProjectPluginInterface\:\:collectMetrics\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/ProjectPluginInterface.php - - message: '#^Method MokoEnterprise\\ProjectPluginInterface\:\:collectMetrics\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\ProjectPluginInterface\:\:collectMetrics\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/ProjectPluginInterface.php - - message: '#^Method MokoEnterprise\\ProjectPluginInterface\:\:getBestPractices\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\ProjectPluginInterface\:\:getBestPractices\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/ProjectPluginInterface.php - - message: '#^Method MokoEnterprise\\ProjectPluginInterface\:\:getCommands\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\ProjectPluginInterface\:\:getCommands\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/ProjectPluginInterface.php - - message: '#^Method MokoEnterprise\\ProjectPluginInterface\:\:getConfigSchema\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\ProjectPluginInterface\:\:getConfigSchema\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/ProjectPluginInterface.php - - message: '#^Method MokoEnterprise\\ProjectPluginInterface\:\:getRecommendedFiles\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\ProjectPluginInterface\:\:getRecommendedFiles\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/ProjectPluginInterface.php - - message: '#^Method MokoEnterprise\\ProjectPluginInterface\:\:getRequiredFiles\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\ProjectPluginInterface\:\:getRequiredFiles\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/ProjectPluginInterface.php - - message: '#^Method MokoEnterprise\\ProjectPluginInterface\:\:healthCheck\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\ProjectPluginInterface\:\:healthCheck\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/ProjectPluginInterface.php - - message: '#^Method MokoEnterprise\\ProjectPluginInterface\:\:healthCheck\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\ProjectPluginInterface\:\:healthCheck\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/ProjectPluginInterface.php - - message: '#^Method MokoEnterprise\\ProjectPluginInterface\:\:initializeProject\(\) has parameter \$options with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\ProjectPluginInterface\:\:initializeProject\(\) has parameter \$options with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/ProjectPluginInterface.php - - message: '#^Method MokoEnterprise\\ProjectPluginInterface\:\:initializeProject\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\ProjectPluginInterface\:\:initializeProject\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/ProjectPluginInterface.php - - message: '#^Method MokoEnterprise\\ProjectPluginInterface\:\:validateProject\(\) has parameter \$config with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\ProjectPluginInterface\:\:validateProject\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/ProjectPluginInterface.php - - message: '#^Method MokoEnterprise\\ProjectPluginInterface\:\:validateProject\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\ProjectPluginInterface\:\:validateProject\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/ProjectPluginInterface.php - - message: '#^Method MokoEnterprise\\ProjectTypeDetector\:\:detect\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\ProjectTypeDetector\:\:detect\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/ProjectTypeDetector.php - - message: '#^Method MokoEnterprise\\ProjectTypeDetector\:\:fileExists\(\) has parameter \$contains with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\ProjectTypeDetector\:\:fileExists\(\) has parameter \$contains with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/ProjectTypeDetector.php - - message: '#^Method MokoEnterprise\\ProjectTypeDetector\:\:getAllScores\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\ProjectTypeDetector\:\:getAllScores\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/ProjectTypeDetector.php - - message: '#^Property MokoEnterprise\\ProjectTypeDetector\:\:\$detectionResults type has no value type specified in iterable type array\.$#' + message: '#^Property MokoCli\\ProjectTypeDetector\:\:\$detectionResults type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/ProjectTypeDetector.php - - message: '#^Constructor of class MokoEnterprise\\RepositoryHealthChecker has an unused parameter \$validator\.$#' + message: '#^Constructor of class MokoCli\\RepositoryHealthChecker has an unused parameter \$validator\.$#' identifier: constructor.unusedParameter count: 1 path: lib/Enterprise/RepositoryHealthChecker.php - - message: '#^Method MokoEnterprise\\RepositoryHealthChecker\:\:check\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\RepositoryHealthChecker\:\:check\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/RepositoryHealthChecker.php - - message: '#^Method MokoEnterprise\\RepositoryHealthChecker\:\:getFailedChecks\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\RepositoryHealthChecker\:\:getFailedChecks\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/RepositoryHealthChecker.php - - message: '#^Method MokoEnterprise\\RepositoryHealthChecker\:\:getPassedChecks\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\RepositoryHealthChecker\:\:getPassedChecks\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/RepositoryHealthChecker.php - - message: '#^Property MokoEnterprise\\RepositoryHealthChecker\:\:\$results type has no value type specified in iterable type array\.$#' + message: '#^Property MokoCli\\RepositoryHealthChecker\:\:\$results type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/RepositoryHealthChecker.php @@ -2005,109 +2005,109 @@ parameters: path: lib/Enterprise/RepositorySynchronizer.php - - message: '#^Method MokoEnterprise\\RepositorySynchronizer\:\:createSyncPR\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\RepositorySynchronizer\:\:createSyncPR\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/RepositorySynchronizer.php - - message: '#^Method MokoEnterprise\\RepositorySynchronizer\:\:detectPlatform\(\) has parameter \$repoInfo with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\RepositorySynchronizer\:\:detectPlatform\(\) has parameter \$repoInfo with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/RepositorySynchronizer.php - - message: '#^Method MokoEnterprise\\RepositorySynchronizer\:\:detectPlatformByHeuristics\(\) has parameter \$repoInfo with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\RepositorySynchronizer\:\:detectPlatformByHeuristics\(\) has parameter \$repoInfo with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/RepositorySynchronizer.php - - message: '#^Method MokoEnterprise\\RepositorySynchronizer\:\:ensureComposerEnterprise\(\) has parameter \$summary with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\RepositorySynchronizer\:\:ensureComposerEnterprise\(\) has parameter \$summary with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/RepositorySynchronizer.php - - message: '#^Method MokoEnterprise\\RepositorySynchronizer\:\:fetchModuleId\(\) is unused\.$#' + message: '#^Method MokoCli\\RepositorySynchronizer\:\:fetchModuleId\(\) is unused\.$#' identifier: method.unused count: 1 path: lib/Enterprise/RepositorySynchronizer.php - - message: '#^Method MokoEnterprise\\RepositorySynchronizer\:\:generateMokoStandardsXml\(\) has parameter \$repoInfo with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\RepositorySynchronizer\:\:generateMokoCliXml\(\) has parameter \$repoInfo with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/RepositorySynchronizer.php - - message: '#^Method MokoEnterprise\\RepositorySynchronizer\:\:generatePRBody\(\) has parameter \$summary with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\RepositorySynchronizer\:\:generatePRBody\(\) has parameter \$summary with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/RepositorySynchronizer.php - - message: '#^Method MokoEnterprise\\RepositorySynchronizer\:\:generateRepositoryDefinition\(\) has parameter \$repoInfo with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\RepositorySynchronizer\:\:generateRepositoryDefinition\(\) has parameter \$repoInfo with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/RepositorySynchronizer.php - - message: '#^Method MokoEnterprise\\RepositorySynchronizer\:\:generateRepositoryDefinition\(\) has parameter \$summary with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\RepositorySynchronizer\:\:generateRepositoryDefinition\(\) has parameter \$summary with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/RepositorySynchronizer.php - - message: '#^Method MokoEnterprise\\RepositorySynchronizer\:\:getRepositories\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\RepositorySynchronizer\:\:getRepositories\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/RepositorySynchronizer.php - - message: '#^Method MokoEnterprise\\RepositorySynchronizer\:\:getSharedWorkflows\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\RepositorySynchronizer\:\:getSharedWorkflows\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/RepositorySynchronizer.php - - message: '#^Method MokoEnterprise\\RepositorySynchronizer\:\:migrateMokoStandards\(\) has parameter \$repoInfo with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\RepositorySynchronizer\:\:migrateMokoCli\(\) has parameter \$repoInfo with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/RepositorySynchronizer.php - - message: '#^Method MokoEnterprise\\RepositorySynchronizer\:\:migrateMokoStandards\(\) has parameter \$summary with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\RepositorySynchronizer\:\:migrateMokoCli\(\) has parameter \$summary with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/RepositorySynchronizer.php - - message: '#^Method MokoEnterprise\\RepositorySynchronizer\:\:processTemplateContent\(\) has parameter \$repoInfo with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\RepositorySynchronizer\:\:processTemplateContent\(\) has parameter \$repoInfo with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/RepositorySynchronizer.php - - message: '#^Method MokoEnterprise\\RepositorySynchronizer\:\:syncFilesToBranch\(\) has parameter \$filesToSync with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\RepositorySynchronizer\:\:syncFilesToBranch\(\) has parameter \$filesToSync with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/RepositorySynchronizer.php - - message: '#^Method MokoEnterprise\\RepositorySynchronizer\:\:syncFilesToBranch\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\RepositorySynchronizer\:\:syncFilesToBranch\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/RepositorySynchronizer.php - - message: '#^Method MokoEnterprise\\RepositorySynchronizer\:\:synchronize\(\) has parameter \$options with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\RepositorySynchronizer\:\:synchronize\(\) has parameter \$options with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/RepositorySynchronizer.php - - message: '#^Method MokoEnterprise\\RepositorySynchronizer\:\:synchronize\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\RepositorySynchronizer\:\:synchronize\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/RepositorySynchronizer.php @@ -2131,67 +2131,67 @@ parameters: path: lib/Enterprise/RepositorySynchronizer.php - - message: '#^Property MokoEnterprise\\SecurityValidator\:\:\$findings type has no value type specified in iterable type array\.$#' + message: '#^Property MokoCli\\SecurityValidator\:\:\$findings type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/SecurityValidator.php - - message: '#^Property MokoEnterprise\\TransactionStep\:\:\$executeFunc has no type specified\.$#' + message: '#^Property MokoCli\\TransactionStep\:\:\$executeFunc has no type specified\.$#' identifier: missingType.property count: 1 path: lib/Enterprise/TransactionManager.php - - message: '#^Property MokoEnterprise\\TransactionStep\:\:\$result has no type specified\.$#' + message: '#^Property MokoCli\\TransactionStep\:\:\$result has no type specified\.$#' identifier: missingType.property count: 1 path: lib/Enterprise/TransactionManager.php - - message: '#^Property MokoEnterprise\\TransactionStep\:\:\$rollbackFunc has no type specified\.$#' + message: '#^Property MokoCli\\TransactionStep\:\:\$rollbackFunc has no type specified\.$#' identifier: missingType.property count: 1 path: lib/Enterprise/TransactionManager.php - - message: '#^Method MokoEnterprise\\ValidationResult\:\:__construct\(\) has parameter \$details with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\ValidationResult\:\:__construct\(\) has parameter \$details with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/UnifiedValidation.php - - message: '#^Property MokoEnterprise\\ValidationResult\:\:\$details type has no value type specified in iterable type array\.$#' + message: '#^Property MokoCli\\ValidationResult\:\:\$details type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/Enterprise/UnifiedValidation.php - - message: '#^Method MokoStandards\\Plugins\\Joomla\\UpdateXmlGenerator\:\:addUpdateEntry\(\) has parameter \$release with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\Joomla\\UpdateXmlGenerator\:\:addUpdateEntry\(\) has parameter \$release with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/plugins/Joomla/UpdateXmlGenerator.php - - message: '#^Method MokoStandards\\Plugins\\Joomla\\UpdateXmlGenerator\:\:extractFromManifest\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\Joomla\\UpdateXmlGenerator\:\:extractFromManifest\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/plugins/Joomla/UpdateXmlGenerator.php - - message: '#^Method MokoStandards\\Plugins\\Joomla\\UpdateXmlGenerator\:\:generate\(\) has parameter \$release with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\Joomla\\UpdateXmlGenerator\:\:generate\(\) has parameter \$release with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/plugins/Joomla/UpdateXmlGenerator.php - - message: '#^Method MokoStandards\\Plugins\\Joomla\\UpdateXmlGenerator\:\:update\(\) has parameter \$release with no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\Joomla\\UpdateXmlGenerator\:\:update\(\) has parameter \$release with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/plugins/Joomla/UpdateXmlGenerator.php - - message: '#^Method MokoStandards\\Plugins\\Joomla\\UpdateXmlGenerator\:\:validate\(\) return type has no value type specified in iterable type array\.$#' + message: '#^Method MokoCli\\Plugins\\Joomla\\UpdateXmlGenerator\:\:validate\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: lib/plugins/Joomla/UpdateXmlGenerator.php diff --git a/plugin_health_check.php b/plugin_health_check.php index eb5a27d..b371055 100755 --- a/plugin_health_check.php +++ b/plugin_health_check.php @@ -19,9 +19,9 @@ declare(strict_types=1); // Autoload dependencies require_once __DIR__ . '/../vendor/autoload.php'; -use MokoEnterprise\PluginFactory; -use MokoEnterprise\AuditLogger; -use MokoEnterprise\MetricsCollector; +use MokoCli\PluginFactory; +use MokoCli\AuditLogger; +use MokoCli\MetricsCollector; /** * Display usage information diff --git a/plugin_list.php b/plugin_list.php index 4f1adda..316331c 100755 --- a/plugin_list.php +++ b/plugin_list.php @@ -19,9 +19,9 @@ declare(strict_types=1); // Autoload dependencies require_once __DIR__ . '/../vendor/autoload.php'; -use MokoEnterprise\PluginFactory; -use MokoEnterprise\AuditLogger; -use MokoEnterprise\MetricsCollector; +use MokoCli\PluginFactory; +use MokoCli\AuditLogger; +use MokoCli\MetricsCollector; /** * Display usage information diff --git a/plugin_metrics.php b/plugin_metrics.php index ea22e60..4ac8bf3 100755 --- a/plugin_metrics.php +++ b/plugin_metrics.php @@ -19,9 +19,9 @@ declare(strict_types=1); // Autoload dependencies require_once __DIR__ . '/../vendor/autoload.php'; -use MokoEnterprise\PluginFactory; -use MokoEnterprise\AuditLogger; -use MokoEnterprise\MetricsCollector; +use MokoCli\PluginFactory; +use MokoCli\AuditLogger; +use MokoCli\MetricsCollector; /** * Display usage information diff --git a/plugin_readiness.php b/plugin_readiness.php index 33b06bd..b09487d 100755 --- a/plugin_readiness.php +++ b/plugin_readiness.php @@ -19,9 +19,9 @@ declare(strict_types=1); // Autoload dependencies require_once __DIR__ . '/../vendor/autoload.php'; -use MokoEnterprise\PluginFactory; -use MokoEnterprise\AuditLogger; -use MokoEnterprise\MetricsCollector; +use MokoCli\PluginFactory; +use MokoCli\AuditLogger; +use MokoCli\MetricsCollector; /** * Display usage information diff --git a/plugin_validate.php b/plugin_validate.php index 1f95f6f..308cebe 100755 --- a/plugin_validate.php +++ b/plugin_validate.php @@ -19,9 +19,9 @@ declare(strict_types=1); // Autoload dependencies require_once __DIR__ . '/../vendor/autoload.php'; -use MokoEnterprise\PluginFactory; -use MokoEnterprise\AuditLogger; -use MokoEnterprise\MetricsCollector; +use MokoCli\PluginFactory; +use MokoCli\AuditLogger; +use MokoCli\MetricsCollector; /** * Display usage information diff --git a/release/generate_dolibarr_version_txt.php b/release/generate_dolibarr_version_txt.php index 2164614..9c27c64 100644 --- a/release/generate_dolibarr_version_txt.php +++ b/release/generate_dolibarr_version_txt.php @@ -49,8 +49,8 @@ declare(strict_types=1); require_once __DIR__ . '/../vendor/autoload.php'; require_once __DIR__ . '/../lib/Enterprise/CliFramework.php'; -use MokoEnterprise\CliFramework; -use MokoEnterprise\{ApiClient, AuditLogger, Config}; +use MokoCli\CliFramework; +use MokoCli\{ApiClient, AuditLogger, Config}; class GenerateDolibarrVersionTxtCli extends CliFramework { @@ -305,7 +305,7 @@ class GenerateDolibarrVersionTxtCli extends CliFramework { $config = Config::load(); try { - $adapter = \MokoEnterprise\PlatformAdapterFactory::create($config); + $adapter = \MokoCli\PlatformAdapterFactory::create($config); $this->api = $adapter->getApiClient(); return true; } catch (\Exception $e) { diff --git a/release/generate_joomla_update_xml.php b/release/generate_joomla_update_xml.php index 12a5cb7..45a0bd3 100644 --- a/release/generate_joomla_update_xml.php +++ b/release/generate_joomla_update_xml.php @@ -48,9 +48,9 @@ declare(strict_types=1); require_once __DIR__ . '/../vendor/autoload.php'; require_once __DIR__ . '/../lib/Enterprise/CliFramework.php'; -use MokoEnterprise\CliFramework; -use MokoEnterprise\{ApiClient, AuditLogger, Config}; -use MokoStandards\Plugins\Joomla\UpdateXmlGenerator; +use MokoCli\CliFramework; +use MokoCli\{ApiClient, AuditLogger, Config}; +use MokoCli\Plugins\Joomla\UpdateXmlGenerator; class GenerateJoomlaUpdateXmlCli extends CliFramework { @@ -523,7 +523,7 @@ XML; { $config = Config::load(); try { - $adapter = \MokoEnterprise\PlatformAdapterFactory::create($config); + $adapter = \MokoCli\PlatformAdapterFactory::create($config); $this->api = $adapter->getApiClient(); return true; } catch (\Exception $e) { diff --git a/security/advisory_scan.php b/security/advisory_scan.php new file mode 100644 index 0000000..83299b7 --- /dev/null +++ b/security/advisory_scan.php @@ -0,0 +1,563 @@ +#!/usr/bin/env php + + * + * This file is part of a Moko Consulting project. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * FILE INFORMATION + * DEFGROUP: MokoPlatform.Security + * INGROUP: MokoPlatform.Scripts + * REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli + * PATH: /security/advisory_scan.php + * BRIEF: Cross-repo security advisory aggregator — scans org repos for known CVEs + */ + +declare(strict_types=1); + +require_once __DIR__ . '/../vendor/autoload.php'; + +use MokoCli\{ + ApiClient, + AuditLogger, + CheckpointManager, + CircuitBreakerOpen, + CliFramework, + Config, + GitPlatformAdapter, + MetricsCollector, + PlatformAdapterFactory, + RateLimitExceeded +}; + +/** + * Cross-Repo Security Advisory Aggregator + * + * Scans all repositories in an organization for known CVEs via `composer audit`, + * aggregates results into a single report, and optionally auto-creates issues + * for critical vulnerabilities. + * + * @see https://git.mokoconsulting.tech/MokoConsulting/mokocli/issues/150 + */ +class AdvisoryScan extends CliFramework +{ + public const VERSION = '01.00.00'; + + /** Minimum severity level for auto-creating issues. */ + private const SEVERITY_LEVELS = ['critical', 'high', 'medium', 'low']; + + private ApiClient $api; + private GitPlatformAdapter $adapter; + private AuditLogger $logger; + private CheckpointManager $checkpoints; + + /** Collected advisories keyed by repo name. */ + private array $advisories = []; + + /** Summary counters. */ + private int $reposScanned = 0; + private int $reposWithIssues = 0; + private int $totalAdvisories = 0; + private int $issuesCreated = 0; + + protected function configure(): void + { + $this->setDescription('Cross-repo security advisory aggregator'); + $this->addArgument('--org', 'Organization to scan', 'MokoConsulting'); + $this->addArgument('--repos', 'Comma-separated list of specific repos', ''); + $this->addArgument('--exclude', 'Comma-separated list of repos to exclude', ''); + $this->addArgument('--skip-archived', 'Skip archived repositories', true); + $this->addArgument('--severity', 'Minimum severity for issue creation (critical|high|medium|low)', 'high'); + $this->addArgument('--create-issues', 'Auto-create issues for vulnerabilities', false); + $this->addArgument('--resume', 'Resume from checkpoint', false); + $this->addArgument('--export', 'Export report to file (json|csv)', ''); + } + + protected function run(): int + { + $this->log("Security Advisory Scanner v" . self::VERSION, 'INFO'); + + if (!$this->initComponents()) { + return self::EXIT_FAILURE; + } + + $org = $this->getArgument('--org', 'MokoConsulting'); + $minSeverity = strtolower($this->getArgument('--severity', 'high')); + $createIssues = $this->getArgument('--create-issues', false); + $exportFormat = $this->getArgument('--export', ''); + + if (!in_array($minSeverity, self::SEVERITY_LEVELS, true)) { + $this->log("Invalid severity: {$minSeverity}. Use: " . implode(', ', self::SEVERITY_LEVELS), 'ERROR'); + return self::EXIT_USAGE; + } + + // ── Gather repos ───────────────────────────────────────────────── + + $repos = $this->gatherRepos($org); + if ($repos === null) { + return self::EXIT_FAILURE; + } + + $total = count($repos); + $this->log("Found {$total} repositories to scan", 'INFO'); + + // ── Resume support ─────────────────────────────────────────────── + + $completed = []; + if ($this->getArgument('--resume', false)) { + $checkpoint = $this->checkpoints->load('advisory_scan'); + if ($checkpoint) { + $completed = $checkpoint['completed'] ?? []; + $this->advisories = $checkpoint['advisories'] ?? []; + $this->log("Resuming — skipping " . count($completed) . " already-scanned repos", 'INFO'); + } + } + + // ── Scan each repo ─────────────────────────────────────────────── + + $this->section('Scanning repositories'); + + foreach ($repos as $i => $repo) { + $repoName = $repo['name']; + $this->progress($i + 1, $total, $repoName); + + if (in_array($repoName, $completed, true)) { + continue; + } + + try { + $this->scanRepo($org, $repoName); + $completed[] = $repoName; + + // Checkpoint after each repo + $this->checkpoints->save('advisory_scan', [ + 'completed' => $completed, + 'advisories' => $this->advisories, + ]); + } catch (RateLimitExceeded $e) { + $this->log("Rate limit hit — checkpoint saved, resume later with --resume", 'WARNING'); + break; + } catch (CircuitBreakerOpen $e) { + $this->log("API circuit breaker open — checkpoint saved", 'WARNING'); + break; + } catch (\Exception $e) { + $this->log("Failed to scan {$repoName}: {$e->getMessage()}", 'ERROR'); + } + } + + $this->progress($total, $total, '', true); + + // ── Aggregate & report ─────────────────────────────────────────── + + $this->section('Advisory Report'); + $this->printReport($minSeverity); + + // ── Auto-create issues ─────────────────────────────────────────── + + if ($createIssues) { + $this->section('Creating tracking issues'); + $this->createTrackingIssues($org, $minSeverity); + } + + // ── Export ─────────────────────────────────────────────────────── + + if ($exportFormat !== '') { + $this->exportReport($exportFormat); + } + + // ── JSON output ────────────────────────────────────────────────── + + if ($this->getArgument('--json', false)) { + $this->jsonOutput('ok', $this->buildReportData($minSeverity)); + return self::EXIT_SUCCESS; + } + + // ── Summary ────────────────────────────────────────────────────── + + $this->printSummary( + $this->reposScanned - $this->reposWithIssues, + $this->reposWithIssues, + $this->elapsed() + ); + + $this->log("Total advisories: {$this->totalAdvisories} across {$this->reposWithIssues} repos", 'INFO'); + if ($this->issuesCreated > 0) { + $this->log("Issues created: {$this->issuesCreated}", 'INFO'); + } + + // Clean checkpoint on full completion + if (count($completed) === $total) { + $this->checkpoints->clear('advisory_scan'); + } + + return $this->reposWithIssues > 0 ? self::EXIT_FAILURE : self::EXIT_SUCCESS; + } + + // ── Component initialisation ───────────────────────────────────────── + + private function initComponents(): bool + { + try { + $this->config = new Config(); + $this->api = new ApiClient($this->config); + $this->adapter = PlatformAdapterFactory::create($this->api, $this->config); + $this->logger = new AuditLogger(); + $this->checkpoints = new CheckpointManager(); + return true; + } catch (\Exception $e) { + $this->log("Failed to initialise: {$e->getMessage()}", 'ERROR'); + return false; + } + } + + // ── Repo gathering ─────────────────────────────────────────────────── + + private function gatherRepos(string $org): ?array + { + $specificRepos = array_filter(explode(',', $this->getArgument('--repos', ''))); + $excludeRepos = array_filter(explode(',', $this->getArgument('--exclude', ''))); + $skipArchived = $this->getArgument('--skip-archived', true); + + try { + $repos = $this->adapter->listOrgRepos($org, $skipArchived); + } catch (\Exception $e) { + $this->log("Failed to list repos: {$e->getMessage()}", 'ERROR'); + return null; + } + + // Filter to specific repos if requested + if (!empty($specificRepos)) { + $repos = array_filter($repos, fn($r) => in_array($r['name'], $specificRepos, true)); + } + + // Exclude repos + if (!empty($excludeRepos)) { + $repos = array_filter($repos, fn($r) => !in_array($r['name'], $excludeRepos, true)); + } + + return array_values($repos); + } + + // ── Per-repo scanning ──────────────────────────────────────────────── + + private function scanRepo(string $org, string $repoName): void + { + $this->reposScanned++; + + // Check if repo has a composer.lock file + try { + $lockData = $this->adapter->getFileContents($org, $repoName, 'composer.lock'); + } catch (\Exception $e) { + // No composer.lock — skip silently (not a Composer project) + return; + } + + // Download composer.json too (required by composer audit) + try { + $jsonData = $this->adapter->getFileContents($org, $repoName, 'composer.json'); + } catch (\Exception $e) { + return; + } + + // Write to temp directory and run composer audit + $tmpDir = sys_get_temp_dir() . '/moko_advisory_' . $repoName . '_' . getmypid(); + @mkdir($tmpDir, 0700, true); + + try { + file_put_contents($tmpDir . '/composer.lock', base64_decode($lockData['content'] ?? '')); + file_put_contents($tmpDir . '/composer.json', base64_decode($jsonData['content'] ?? '')); + + $result = $this->runComposerAudit($tmpDir); + if (!empty($result)) { + $this->advisories[$repoName] = $result; + $this->reposWithIssues++; + $this->totalAdvisories += count($result); + } + } finally { + // Cleanup temp files + @unlink($tmpDir . '/composer.lock'); + @unlink($tmpDir . '/composer.json'); + @rmdir($tmpDir); + } + } + + /** + * Run `composer audit --format=json` and parse the output. + * + * @return array + */ + private function runComposerAudit(string $dir): array + { + $cmd = sprintf( + 'composer audit --format=json --working-dir=%s --no-interaction 2>/dev/null', + escapeshellarg($dir) + ); + $output = shell_exec($cmd); + if ($output === null || $output === '') { + return []; + } + + $data = json_decode($output, true); + if (!is_array($data)) { + return []; + } + + $advisories = []; + + // composer audit JSON: { "advisories": { "vendor/package": [ { ... }, ... ] } } + foreach ($data['advisories'] ?? [] as $packageName => $packageAdvisories) { + foreach ($packageAdvisories as $advisory) { + $advisories[] = [ + 'advisoryId' => $advisory['advisoryId'] ?? '', + 'packageName' => $packageName, + 'cve' => $advisory['cve'] ?? '', + 'title' => $advisory['title'] ?? 'Unknown', + 'severity' => strtolower($advisory['severity'] ?? 'unknown'), + 'affectedVersions' => $advisory['affectedVersions'] ?? '', + 'link' => $advisory['link'] ?? '', + ]; + } + } + + return $advisories; + } + + // ── Reporting ──────────────────────────────────────────────────────── + + private function printReport(string $minSeverity): void + { + if (empty($this->advisories)) { + $this->log("No advisories found — all repos are clean", 'INFO'); + return; + } + + // Aggregate by severity + $bySeverity = array_fill_keys(self::SEVERITY_LEVELS, []); + foreach ($this->advisories as $repoName => $repoAdvisories) { + foreach ($repoAdvisories as $adv) { + $sev = $adv['severity'] ?: 'unknown'; + $bySeverity[$sev][] = array_merge($adv, ['repo' => $repoName]); + } + } + + foreach (self::SEVERITY_LEVELS as $severity) { + $items = $bySeverity[$severity] ?? []; + if (empty($items)) { + continue; + } + + $this->log(strtoupper($severity) . ': ' . count($items) . ' advisory(ies)', 'WARNING'); + + foreach ($items as $adv) { + $cveLabel = $adv['cve'] ?: $adv['advisoryId']; + $meetsThreshold = $this->severityMeetsThreshold($adv['severity'], $minSeverity); + $this->status( + !$meetsThreshold, + "{$adv['repo']}: {$adv['packageName']}", + "{$cveLabel} — {$adv['title']}" + ); + } + } + + // Show unknown-severity advisories if any + $unknowns = $bySeverity['unknown'] ?? []; + if (!empty($unknowns)) { + $this->log('UNKNOWN SEVERITY: ' . count($unknowns) . ' advisory(ies)', 'WARNING'); + foreach ($unknowns as $adv) { + $cveLabel = $adv['cve'] ?: $adv['advisoryId']; + $this->status(false, "{$adv['repo']}: {$adv['packageName']}", "{$cveLabel} — {$adv['title']}"); + } + } + } + + // ── Issue creation ─────────────────────────────────────────────────── + + private function createTrackingIssues(string $org, string $minSeverity): void + { + $dryRun = $this->getArgument('--dry-run', false); + + foreach ($this->advisories as $repoName => $repoAdvisories) { + // Filter to advisories meeting the severity threshold + $actionable = array_filter( + $repoAdvisories, + fn($a) => $this->severityMeetsThreshold($a['severity'], $minSeverity) + ); + + if (empty($actionable)) { + continue; + } + + $title = 'Security: ' . count($actionable) . ' CVE(s) found by composer audit'; + $body = $this->buildIssueBody($repoName, $actionable); + + if ($dryRun) { + $this->log("[dry-run] Would create issue in {$repoName}: {$title}", 'INFO'); + continue; + } + + // Check for existing open issue to avoid duplicates + try { + $existing = $this->adapter->listIssues($org, $repoName, [ + 'state' => 'open', + 'type' => 'issues', + ]); + + $duplicate = false; + foreach ($existing as $issue) { + if (str_starts_with($issue['title'] ?? '', 'Security:') && str_contains($issue['title'] ?? '', 'composer audit')) { + // Update existing issue instead + $this->adapter->addIssueComment($org, $repoName, (int) $issue['number'], $body); + $this->log("Updated existing issue #{$issue['number']} in {$repoName}", 'INFO'); + $this->issuesCreated++; + $duplicate = true; + break; + } + } + + if (!$duplicate) { + $this->adapter->createIssue($org, $repoName, $title, $body, [ + 'labels' => ['security'], + ]); + $this->log("Created issue in {$repoName}: {$title}", 'INFO'); + $this->issuesCreated++; + } + } catch (\Exception $e) { + $this->log("Failed to create issue in {$repoName}: {$e->getMessage()}", 'ERROR'); + } + } + } + + private function buildIssueBody(string $repoName, array $advisories): string + { + $date = date('Y-m-d H:i:s'); + $lines = [ + "## Security Advisory Report", + "", + "**Repository**: `{$repoName}`", + "**Scanned**: {$date}", + "**Tool**: `composer audit`", + "", + "### Vulnerabilities", + "", + "| Severity | Package | CVE | Description |", + "|----------|---------|-----|-------------|", + ]; + + foreach ($advisories as $adv) { + $cve = $adv['cve'] ?: $adv['advisoryId']; + $link = $adv['link'] ? "[{$cve}]({$adv['link']})" : $cve; + $lines[] = "| {$adv['severity']} | `{$adv['packageName']}` | {$link} | {$adv['title']} |"; + } + + $lines[] = ""; + $lines[] = "### Remediation"; + $lines[] = ""; + $lines[] = "Run `composer update` to update affected packages, or pin specific versions:"; + $lines[] = ""; + $lines[] = "```bash"; + $lines[] = "composer audit # verify current state"; + $lines[] = "composer update # update all dependencies"; + $lines[] = "```"; + $lines[] = ""; + $lines[] = "---"; + $lines[] = "*Auto-generated by `moko security:advisories`*"; + + return implode("\n", $lines); + } + + // ── Export ──────────────────────────────────────────────────────────── + + private function exportReport(string $format): void + { + $data = $this->buildReportData($this->getArgument('--severity', 'high')); + + $filename = 'advisory-report-' . date('Y-m-d-His'); + + switch (strtolower($format)) { + case 'json': + $path = $filename . '.json'; + file_put_contents($path, json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); + $this->log("Report exported to {$path}", 'INFO'); + break; + + case 'csv': + $path = $filename . '.csv'; + $fp = fopen($path, 'w'); + fputcsv($fp, ['Repository', 'Package', 'CVE', 'Severity', 'Title', 'Affected Versions', 'Link']); + foreach ($data['advisories'] as $adv) { + fputcsv($fp, [ + $adv['repo'], + $adv['packageName'], + $adv['cve'], + $adv['severity'], + $adv['title'], + $adv['affectedVersions'], + $adv['link'], + ]); + } + fclose($fp); + $this->log("Report exported to {$path}", 'INFO'); + break; + + default: + $this->log("Unsupported export format: {$format}. Use 'json' or 'csv'.", 'ERROR'); + } + } + + // ── Helpers ─────────────────────────────────────────────────────────── + + private function buildReportData(string $minSeverity): array + { + $flat = []; + foreach ($this->advisories as $repoName => $repoAdvisories) { + foreach ($repoAdvisories as $adv) { + $flat[] = array_merge($adv, ['repo' => $repoName]); + } + } + + // Sort: critical first, then high, etc. + usort($flat, function ($a, $b) { + $order = array_flip(self::SEVERITY_LEVELS); + $sa = $order[$a['severity']] ?? 99; + $sb = $order[$b['severity']] ?? 99; + return $sa <=> $sb; + }); + + return [ + 'summary' => [ + 'scannedAt' => date('c'), + 'reposScanned' => $this->reposScanned, + 'reposAffected' => $this->reposWithIssues, + 'totalAdvisories' => $this->totalAdvisories, + 'minSeverity' => $minSeverity, + 'issuesCreated' => $this->issuesCreated, + ], + 'advisories' => $flat, + ]; + } + + /** + * Check if a severity level meets or exceeds a threshold. + */ + private function severityMeetsThreshold(string $severity, string $threshold): bool + { + $order = array_flip(self::SEVERITY_LEVELS); + $sevIdx = $order[$severity] ?? 99; + $thrIdx = $order[$threshold] ?? 0; + return $sevIdx <= $thrIdx; + } +} + +$script = new AdvisoryScan('advisory_scan', 'Cross-repo security advisory aggregator'); +exit($script->execute()); diff --git a/templates/configs/.pylintrc b/templates/configs/.pylintrc index 6026be5..8479652 100644 --- a/templates/configs/.pylintrc +++ b/templates/configs/.pylintrc @@ -4,7 +4,7 @@ # # SPDX-License-Identifier: GPL-3.0-or-later -# Pylint configuration for MokoStandards projects +# Pylint configuration for MokoCli projects [MASTER] # Python code to execute, usually for sys.path manipulation diff --git a/templates/configs/composer.dolibarr.json b/templates/configs/composer.dolibarr.json index 20dc735..b4b0aba 100644 --- a/templates/configs/composer.dolibarr.json +++ b/templates/configs/composer.dolibarr.json @@ -34,7 +34,7 @@ "repositories": [ { "type": "vcs", - "url": "https://git.mokoconsulting.tech/mokoconsulting-tech/MokoStandards-API" + "url": "https://git.mokoconsulting.tech/mokoconsulting-tech/MokoCli-API" } ], "config": { diff --git a/templates/configs/composer.generic.json b/templates/configs/composer.generic.json index 445802d..f5be9d8 100644 --- a/templates/configs/composer.generic.json +++ b/templates/configs/composer.generic.json @@ -34,7 +34,7 @@ "repositories": [ { "type": "vcs", - "url": "https://git.mokoconsulting.tech/mokoconsulting-tech/MokoStandards-API" + "url": "https://git.mokoconsulting.tech/mokoconsulting-tech/MokoCli-API" } ], "config": { diff --git a/templates/configs/composer.joomla.json b/templates/configs/composer.joomla.json index 3ec119a..514d6cd 100644 --- a/templates/configs/composer.joomla.json +++ b/templates/configs/composer.joomla.json @@ -34,7 +34,7 @@ "repositories": [ { "type": "vcs", - "url": "https://git.mokoconsulting.tech/mokoconsulting-tech/MokoStandards-API" + "url": "https://git.mokoconsulting.tech/mokoconsulting-tech/MokoCli-API" } ], "config": { diff --git a/templates/configs/manifest.xml.template b/templates/configs/manifest.xml.template index 72dd4f6..8f17503 100644 --- a/templates/configs/manifest.xml.template +++ b/templates/configs/manifest.xml.template @@ -8,7 +8,7 @@ REPO: https://git.mokoconsulting.tech/MokoConsulting/mokoplatform PATH: /templates/configs/manifest.xml.template BRIEF: XML manifest template — synced to .mokogitea/manifest.xml in every governed repository - NOTE: This template is a reference only. The bulk sync generates XML via MokoStandardsParser::generate(). + NOTE: This template is a reference only. The bulk sync generates XML via MokoCliParser::generate(). mokoplatform Repository Manifest Auto-generated by mokoplatform bulk sync. diff --git a/templates/configs/mokostandards.xml.template b/templates/configs/mokostandards.xml.template index f9974ad..11f32e1 100644 --- a/templates/configs/mokostandards.xml.template +++ b/templates/configs/mokostandards.xml.template @@ -8,7 +8,7 @@ REPO: https://git.mokoconsulting.tech/MokoConsulting/mokoplatform PATH: /templates/configs/manifest.xml.template BRIEF: XML manifest template — synced to .mokogitea/manifest.xml in every governed repository - NOTE: This template is a reference only. The bulk sync generates XML via MokoStandardsParser::generate(). + NOTE: This template is a reference only. The bulk sync generates XML via MokoCliParser::generate(). mokoplatform Repository Manifest Auto-generated by mokoplatform bulk sync. diff --git a/templates/configs/phpstan.dolibarr.neon b/templates/configs/phpstan.dolibarr.neon index ef36b54..00ec81c 100644 --- a/templates/configs/phpstan.dolibarr.neon +++ b/templates/configs/phpstan.dolibarr.neon @@ -2,7 +2,7 @@ # SPDX-License-Identifier: GPL-3.0-or-later # # PHPStan configuration for Dolibarr module repositories. -# Extends the base MokoStandards config and adds Dolibarr class stubs +# Extends the base MokoCli config and adds Dolibarr class stubs # so PHPStan can resolve CommonObject, DoliDB, Conf, User, etc. # without requiring a full Dolibarr installation. diff --git a/templates/configs/phpstan.joomla.neon b/templates/configs/phpstan.joomla.neon index 3d4adca..9bb35ef 100644 --- a/templates/configs/phpstan.joomla.neon +++ b/templates/configs/phpstan.joomla.neon @@ -2,7 +2,7 @@ # SPDX-License-Identifier: GPL-3.0-or-later # # PHPStan configuration for Joomla extension repositories. -# Extends the base MokoStandards config and adds Joomla framework class stubs +# Extends the base MokoCli config and adds Joomla framework class stubs # so PHPStan can resolve Factory, CMSApplication, User, Table, etc. # without requiring a full Joomla installation. diff --git a/templates/configs/phpstan.neon b/templates/configs/phpstan.neon index 2ef9c15..1182786 100644 --- a/templates/configs/phpstan.neon +++ b/templates/configs/phpstan.neon @@ -4,7 +4,7 @@ # # SPDX-License-Identifier: GPL-3.0-or-later -# PHPStan configuration for MokoStandards projects +# PHPStan configuration for MokoCli projects parameters: level: 5 paths: diff --git a/templates/configs/pyproject.toml b/templates/configs/pyproject.toml index 97cbd3a..9747912 100644 --- a/templates/configs/pyproject.toml +++ b/templates/configs/pyproject.toml @@ -4,7 +4,7 @@ # # SPDX-License-Identifier: GPL-3.0-or-later -# Python project configuration for MokoStandards projects +# Python project configuration for MokoCli projects [tool.black] line-length = 100 diff --git a/templates/licenses/GPL-3.0 b/templates/licenses/GPL-3.0 index 1756213..1120bdf 100644 --- a/templates/licenses/GPL-3.0 +++ b/templates/licenses/GPL-3.0 @@ -11,9 +11,9 @@ You should have received a copy of the GNU General Public License (./LICENSE). # FILE INFORMATION - DEFGROUP: MokoStandards - INGROUP: MokoStandards.Documentation - REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoStandards/ + DEFGROUP: MokoCli + INGROUP: MokoCli.Documentation + REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoCli/ VERSION: 05.00.00 PATH: ./LICENSE BRIEF: Project license (GPL-3.0-or-later) diff --git a/templates/mokogitea/CODEOWNERS b/templates/mokogitea/CODEOWNERS index bb35912..f818f4a 100644 --- a/templates/mokogitea/CODEOWNERS +++ b/templates/mokogitea/CODEOWNERS @@ -2,13 +2,13 @@ # SPDX-License-Identifier: GPL-3.0-or-later # # CODEOWNERS — require approval from jmiller for protected paths -# Synced from MokoStandards. Do not edit manually. +# Synced from MokoCli. Do not edit manually. # # Changes to these paths require review from the listed owners before merge. # Combined with branch protection (require PR reviews), this prevents # unauthorized modifications to workflows, configs, and governance files. -# ── Synced workflows (managed by MokoStandards — do not edit manually) ──── +# ── Synced workflows (managed by MokoCli — do not edit manually) ──── /.github/workflows/deploy-dev.yml @jmiller /.github/workflows/deploy-demo.yml @jmiller /.github/workflows/deploy-manual.yml @jmiller diff --git a/templates/mokogitea/copilot-instructions.md.template b/templates/mokogitea/copilot-instructions.md.template index 48e325e..ea6d986 100644 --- a/templates/mokogitea/copilot-instructions.md.template +++ b/templates/mokogitea/copilot-instructions.md.template @@ -183,7 +183,7 @@ Run `composer install` after adding the dependency. See [package-installation.md ## PHP Script Pattern -All PHP scripts **must** extend `MokoStandards\Enterprise\CliFramework`. Never write standalone classes or extend the legacy `CliBase`. +All PHP scripts **must** extend `MokoCli\Enterprise\CliFramework`. Never write standalone classes or extend the legacy `CliBase`. ```php #!/usr/bin/env php @@ -194,7 +194,7 @@ declare(strict_types=1); require_once __DIR__ . '/vendor/autoload.php'; -use MokoStandards\Enterprise\CliFramework; +use MokoCli\Enterprise\CliFramework; class MyScript extends CliFramework { @@ -307,7 +307,7 @@ If your code change makes any existing doc sentence false or incomplete, fix the - Never use bare `catch (\Throwable $e) {}` without logging or re-throwing - Never hardcode version numbers in body text — update `README.md` and let automation propagate - Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows — always use `secrets.GH_TOKEN` -- Never extend `CliBase` in PHP scripts — extend `MokoStandards\Enterprise\CliFramework` +- Never extend `CliBase` in PHP scripts — extend `MokoCli\Enterprise\CliFramework` - Never call `$script->run()` as the entry point — call `$script->execute()` - Policy documents and guides must not be mixed diff --git a/templates/schemas/schemas/README.md b/templates/schemas/schemas/README.md index a489e74..b88bf6c 100644 --- a/templates/schemas/schemas/README.md +++ b/templates/schemas/schemas/README.md @@ -62,7 +62,7 @@ root = tree.getroot() getHealthConfig(); diff --git a/templates/scripts/common/CliBase.template.php b/templates/scripts/common/CliBase.template.php index e2027e1..7c5b611 100644 --- a/templates/scripts/common/CliBase.template.php +++ b/templates/scripts/common/CliBase.template.php @@ -12,7 +12,7 @@ * INGROUP: MokoPlatform.Templates * REPO: https://git.mokoconsulting.tech/MokoConsulting/mokoplatform * PATH: /templates/scripts/common/CliBase.template.php - * BRIEF: PHP CLI script template — extends MokoEnterprise\CliFramework + * BRIEF: PHP CLI script template — extends MokoCli\CliFramework * NOTE: Copy this file as a starting point for new PHP CLI scripts in governed repos. * Requires mokoconsulting/mokostandards installed via composer. * Replace MyScript / my_script / description with the real script name. @@ -25,7 +25,7 @@ declare(strict_types=1); // From a subdirectory two levels deep: __DIR__ . '/../../vendor/autoload.php' require_once __DIR__ . '/../vendor/autoload.php'; -use MokoEnterprise\CliFramework; +use MokoCli\CliFramework; /** * Template CLI script — replace this docblock and class name. diff --git a/templates/scripts/release/package_dolibarr.php b/templates/scripts/release/package_dolibarr.php index be812ab..bd1c357 100644 --- a/templates/scripts/release/package_dolibarr.php +++ b/templates/scripts/release/package_dolibarr.php @@ -22,7 +22,7 @@ declare(strict_types=1); // Deployed to bin/build_package.php in org repos — vendor/ is one level up (repo root) require_once __DIR__ . '/../vendor/autoload.php'; -use MokoEnterprise\CliFramework; +use MokoCli\CliFramework; /** * Builds a release-ready ZIP package from a Dolibarr module repository. diff --git a/templates/scripts/release/package_joomla.php b/templates/scripts/release/package_joomla.php index 137f089..5190a23 100644 --- a/templates/scripts/release/package_joomla.php +++ b/templates/scripts/release/package_joomla.php @@ -22,7 +22,7 @@ declare(strict_types=1); // Deployed to bin/build_package.php in org repos — vendor/ is one level up (repo root) require_once __DIR__ . '/../vendor/autoload.php'; -use MokoEnterprise\CliFramework; +use MokoCli\CliFramework; /** * Builds a release-ready ZIP package from a Joomla component repository. diff --git a/templates/scripts/validate/dolibarr_module.php b/templates/scripts/validate/dolibarr_module.php index 3278f85..8edcaa5 100644 --- a/templates/scripts/validate/dolibarr_module.php +++ b/templates/scripts/validate/dolibarr_module.php @@ -22,7 +22,7 @@ declare(strict_types=1); // Deployed to bin/validate_module.php in org repos — vendor/ is one level up (repo root) require_once __DIR__ . '/../vendor/autoload.php'; -use MokoEnterprise\CliFramework; +use MokoCli\CliFramework; /** * Validates a Dolibarr module repository against mokoplatform requirements. diff --git a/templates/scripts/validate/validate_manifest.php b/templates/scripts/validate/validate_manifest.php index 333344e..ab99c52 100644 --- a/templates/scripts/validate/validate_manifest.php +++ b/templates/scripts/validate/validate_manifest.php @@ -22,7 +22,7 @@ declare(strict_types=1); // Deployed to bin/validate_manifest.php in org repos — vendor/ is one level up (repo root) require_once __DIR__ . '/../vendor/autoload.php'; -use MokoEnterprise\CliFramework; +use MokoCli\CliFramework; /** * Validates a Joomla component XML manifest against mokoplatform requirements. diff --git a/templates/scripts/validate/validate_structure.php b/templates/scripts/validate/validate_structure.php index 3bc40bc..793de6d 100644 --- a/templates/scripts/validate/validate_structure.php +++ b/templates/scripts/validate/validate_structure.php @@ -22,7 +22,7 @@ declare(strict_types=1); // Deployed to bin/validate_structure.php in org repos — vendor/ is one level up (repo root) require_once __DIR__ . '/../vendor/autoload.php'; -use MokoEnterprise\CliFramework; +use MokoCli\CliFramework; /** * Validates a generic repository structure against mokoplatform requirements. diff --git a/templates/web/assets/css/app.css b/templates/web/assets/css/app.css index 489d323..879a0c7 100644 --- a/templates/web/assets/css/app.css +++ b/templates/web/assets/css/app.css @@ -1,12 +1,12 @@ /** - * MokoStandards Web Interface - Material Design 3 + * MokoCli Web Interface - Material Design 3 * * Copyright (C) 2026 Moko Consulting * SPDX-License-Identifier: GPL-3.0-or-later * * FILE INFORMATION - * DEFGROUP: MokoStandards.Templates.Web - * INGROUP: MokoStandards.Templates + * DEFGROUP: MokoCli.Templates.Web + * INGROUP: MokoCli.Templates * REPO: https://git.mokoconsulting.tech/MokoConsulting/mokoplatform * PATH: /templates/web/assets/css/app.css * BRIEF: Material Design 3 web interface stylesheet diff --git a/templates/web/index.php b/templates/web/index.php index 661ed34..d6f8764 100644 --- a/templates/web/index.php +++ b/templates/web/index.php @@ -19,7 +19,7 @@ declare(strict_types=1); // Load Composer autoloader require_once __DIR__ . '/../vendor/autoload.php'; -use MokoEnterprise\AuditLogger; +use MokoCli\AuditLogger; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\JsonResponse; diff --git a/tests/Enterprise/GitPlatformAdapterTest.php b/tests/Enterprise/GitPlatformAdapterTest.php index 2c5a0c7..d74164a 100644 --- a/tests/Enterprise/GitPlatformAdapterTest.php +++ b/tests/Enterprise/GitPlatformAdapterTest.php @@ -15,12 +15,12 @@ declare(strict_types=1); require_once __DIR__ . '/../../vendor/autoload.php'; -use MokoEnterprise\ApiClient; -use MokoEnterprise\Config; -use MokoEnterprise\GitPlatformAdapter; -use MokoEnterprise\GitHubAdapter; -use MokoEnterprise\MokoGiteaAdapter; -use MokoEnterprise\PlatformAdapterFactory; +use MokoCli\ApiClient; +use MokoCli\Config; +use MokoCli\GitPlatformAdapter; +use MokoCli\GitHubAdapter; +use MokoCli\MokoGiteaAdapter; +use MokoCli\PlatformAdapterFactory; echo "Testing GitPlatformAdapter Interface Compliance\n"; echo str_repeat('=', 60) . "\n\n"; diff --git a/tests/Unit/CliDispatchTest.php b/tests/Unit/CliDispatchTest.php index 0beecd9..226f3ca 100644 --- a/tests/Unit/CliDispatchTest.php +++ b/tests/Unit/CliDispatchTest.php @@ -6,7 +6,7 @@ declare(strict_types=1); -namespace MokoStandards\Tests\Unit; +namespace MokoCli\Tests\Unit; use PHPUnit\Framework\TestCase; @@ -34,7 +34,7 @@ class CliDispatchTest extends TestCase public function testHelpCommand(): void { $output = $this->runMoko('--help'); - $this->assertStringContainsString('MokoStandards CLI', $output); + $this->assertStringContainsString('MokoCli', $output); } public function testUnknownCommandExitsWithCode2(): void diff --git a/tests/Unit/CliFrameworkTest.php b/tests/Unit/CliFrameworkTest.php index f3ee849..36e553e 100644 --- a/tests/Unit/CliFrameworkTest.php +++ b/tests/Unit/CliFrameworkTest.php @@ -6,15 +6,15 @@ declare(strict_types=1); -namespace MokoStandards\Tests\Unit; +namespace MokoCli\Tests\Unit; -use MokoEnterprise\CliFramework; +use MokoCli\CliFramework; use PHPUnit\Framework\TestCase; /** * Unit tests for CliFramework base class. * - * @covers \MokoEnterprise\CliFramework + * @covers \MokoCli\CliFramework */ class CliFrameworkTest extends TestCase { diff --git a/tests/Unit/ConfigValidatorTest.php b/tests/Unit/ConfigValidatorTest.php index 797b713..12ee07d 100644 --- a/tests/Unit/ConfigValidatorTest.php +++ b/tests/Unit/ConfigValidatorTest.php @@ -6,9 +6,9 @@ declare(strict_types=1); -namespace MokoStandards\Tests\Unit; +namespace MokoCli\Tests\Unit; -use MokoEnterprise\ConfigValidator; +use MokoCli\ConfigValidator; use PHPUnit\Framework\TestCase; class ConfigValidatorTest extends TestCase diff --git a/tests/Unit/VersionBumpTest.php b/tests/Unit/VersionBumpTest.php index 722a368..7c1b770 100644 --- a/tests/Unit/VersionBumpTest.php +++ b/tests/Unit/VersionBumpTest.php @@ -6,7 +6,7 @@ declare(strict_types=1); -namespace MokoStandards\Tests\Unit; +namespace MokoCli\Tests\Unit; use PHPUnit\Framework\TestCase; @@ -63,7 +63,7 @@ class VersionBumpTest extends TestCase { file_put_contents( "{$this->tmpDir}/README.md", - "\nSome content\n" + "\nSome content\n" ); $this->execute(); diff --git a/tests/Unit/VersionReadTest.php b/tests/Unit/VersionReadTest.php index 6f36039..2df9355 100644 --- a/tests/Unit/VersionReadTest.php +++ b/tests/Unit/VersionReadTest.php @@ -6,7 +6,7 @@ declare(strict_types=1); -namespace MokoStandards\Tests\Unit; +namespace MokoCli\Tests\Unit; use PHPUnit\Framework\TestCase; @@ -34,7 +34,7 @@ class VersionReadTest extends TestCase { file_put_contents( "{$this->tmpDir}/README.md", - "# Test\n\n" + "# Test\n\n" ); $this->assertSame('02.03.04', trim($this->runScript())); @@ -68,7 +68,7 @@ class VersionReadTest extends TestCase { file_put_contents( "{$this->tmpDir}/README.md", - "\n" + "\n" ); mkdir("{$this->tmpDir}/src", 0755, true); file_put_contents( diff --git a/tests/test_circuit_breaker_handling.php b/tests/test_circuit_breaker_handling.php index 5f1991f..171efd5 100644 --- a/tests/test_circuit_breaker_handling.php +++ b/tests/test_circuit_breaker_handling.php @@ -22,7 +22,7 @@ declare(strict_types=1); require_once __DIR__ . '/../vendor/autoload.php'; -use MokoEnterprise\{ +use MokoCli\{ ApiClient, CircuitBreakerOpen, RateLimitExceeded diff --git a/tests/test_enterprise_libraries.php b/tests/test_enterprise_libraries.php index 7ed3a68..61c6597 100644 --- a/tests/test_enterprise_libraries.php +++ b/tests/test_enterprise_libraries.php @@ -18,13 +18,13 @@ declare(strict_types=1); require_once __DIR__ . '/../vendor/autoload.php'; -use MokoEnterprise\MetricsCollector; -use MokoEnterprise\SecurityValidator; -use MokoEnterprise\Transaction; -use MokoEnterprise\TransactionManager; -use MokoEnterprise\UnifiedValidator; -use MokoEnterprise\PathValidatorPlugin; -use MokoEnterprise\CliFramework; +use MokoCli\MetricsCollector; +use MokoCli\SecurityValidator; +use MokoCli\Transaction; +use MokoCli\TransactionManager; +use MokoCli\UnifiedValidator; +use MokoCli\PathValidatorPlugin; +use MokoCli\CliFramework; echo "Testing mokoplatform Enterprise Libraries\n"; echo str_repeat('=', 60) . "\n\n"; diff --git a/tmp_wiki_rename.py b/tmp_wiki_rename.py new file mode 100644 index 0000000..8d710d5 --- /dev/null +++ b/tmp_wiki_rename.py @@ -0,0 +1,37 @@ +import base64, re + +protected_pat = re.compile( + r'(com_mokowaashq|pkg_mokowaashq|plg_webservices_mokowaashq|' + r'com_mokowaasannounce|mod_mokowaasannounce|mokowaasannounce|' + r'mokowaashq|ModMokowaasannounceHelper|#__mokowaasannounce)', + re.IGNORECASE +) + +def apply_replacements(text): + parts = protected_pat.split(text) + result = [] + for i, part in enumerate(parts): + if i % 2 == 0: + part = part.replace('MokoWaaSHQ', 'MokoSuiteHQ') + part = part.replace('MokoWaaSBase', 'MokoSuiteBase') + part = part.replace('MokoWaaS', 'MokoSuite') + part = part.replace('mokowaas', 'mokosuite') + result.append(part) + return ''.join(result) + +pages = { + "Home": "IyBNb2tvU3VpdGVIUQoKQ2VudHJhbGl6ZWQgY29udHJvbCBwYW5lbCBmb3IgTW9rb1dhYVMgY2xpZW50IGluc3RhbGxhdGlvbnMgLS0gcmVjZWl2ZXMgaGVhcnRiZWF0cyBmcm9tIHJlbW90ZSBKb29tbGEgc2l0ZXMsIGRpc3BsYXlzIHN0YXR1cyBkYXNoYm9hcmQsIGFuZCBtYW5hZ2VzIHNpdGUgcmVnaXN0cmF0aW9ucwoKfCBGaWVsZCB8IFZhbHVlIHwKfC0tLXwtLS18CnwgKipUeXBlKiogfCBKb29tbGEgUGFja2FnZSAoY29tcG9uZW50ICsgd2Vic2VydmljZXMgcGx1Z2luKSB8CnwgKipWZXJzaW9uKiogfCAwMS4wMC4zNSB8CnwgKipKb29tbGEqKiB8IDUueCAvIDYueCB8CnwgKipQSFAqKiB8IDguMSsgfAp8ICoqTGljZW5zZSoqIHwgR1BMLTMuMC1vci1sYXRlciB8CnwgKipQbGF0Zm9ybSoqIHwgW01va29HaXRlYV0oaHR0cHM6Ly9naXQubW9rb2NvbnN1bHRpbmcudGVjaC9Nb2tvQ29uc3VsdGluZy9Nb2tvU3VpdGVIUSkgfAoKLS0tCgojIyBBcmNoaXRlY3R1cmUKCmBgYAorLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsKfCAgICAgICAgIE1va29XYWFTSFEgQ29udHJvbCBQYW5lbCAgICAgICAgICAgICB8CnwgICAgICAgICAoQ2VudHJhbCBKb29tbGEgU2l0ZSkgICAgICAgICAgICAgICAgfAp8ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwKfCAgY29tX21va293YWFzaHEgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICstIERhc2hib2FyZDogc2l0ZSBzdGF0dXMgb3ZlcnZpZXcgICAgICAgICAgfAp8ICArLSBTaXRlczogcmVnaXN0ZXIgJiBtYW5hZ2UgY2xpZW50IHNpdGVzICAgIHwKfCAgKy0gSGVhcnRiZWF0czogaGlzdG9yeSAmIGRpYWdub3N0aWNzICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfAp8ICBwbGdfd2Vic2VydmljZXNfbW9rb3dhYXNocSAgICAgICAgICAgICAgICAgIHwKfCAgKy0gUE9TVCAvYXBpL3YxL21va293YWFzaHEvaGVhcnRiZWF0ICAgICAgIHwKKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rCiAgICAgICAgIF4gICAgICAgICAgICBeICAgICAgICAgICAgXgogICAgICAgICB8IGhlYXJ0YmVhdCAgfCBoZWFydGJlYXQgIHwgaGVhcnRiZWF0CiAgICArLS0tLS0tLS0rICAgKy0tLS0tLS0tKyAgICstLS0tLS0tLSsKICAgIHxDbGllbnQgMXwgICB8Q2xpZW50IDJ8ICAgfENsaWVudCBOfAogICAgfCBKb29tbGEgfCAgIHwgSm9vbWxhIHwgICB8IEpvb21sYSB8CiAgICB8ICtXYWFTICB8ICAgfCArV2FhUyAgfCAgIHwgK1dhYVMgIHwKICAgICstLS0tLS0tLSsgICArLS0tLS0tLS0rICAgKy0tLS0tLS0tKwpgYGAKCnwgRXh0ZW5zaW9uIHwgUHVycG9zZSB8CnwtLS18LS0tfAp8IGBjb21fbW9rb3dhYXNocWAgfCBBZG1pbiBkYXNoYm9hcmQsIHNpdGUgQ1JVRCwgaGVhcnRiZWF0IGhpc3RvcnkgfAp8IGBwbGdfd2Vic2VydmljZXNfbW9rb3dhYXNocWAgfCBSRVNUIEFQSSByb3V0ZSBmb3IgaGVhcnRiZWF0IGluZ2VzdGlvbiB8CnwgYHBrZ19tb2tvd2Fhc2hxYCB8IEJ1bmRsZXMgYm90aCBmb3Igc2luZ2xlLWNsaWNrIGluc3RhbGwgfAoKLS0tCgojIyBSZXF1aXJlbWVudHMKCnwgUmVxdWlyZW1lbnQgfCBNaW5pbXVtIHwKfC0tLXwtLS18CnwgSm9vbWxhIHwgNS54IG9yIDYueCB8CnwgUEhQIHwgOC4xKyB8CnwgTXlTUUwgfCA4LjArIHwKCi0tLQoKPiBbTW9rb1N0YW5kYXJkc10oaHR0cHM6Ly9naXQubW9rb2NvbnN1bHRpbmcudGVjaC9Nb2tvQ29uc3VsdGluZy9tb2tvcGxhdGZvcm0vd2lraS9Ib21lKQoKLS0tCgoqUmVwbzogW01va29TdWl0ZUhRXShodHRwczovL2dpdC5tb2tvY29uc3VsdGluZy50ZWNoL01va29Db25zdWx0aW5nL01va29TdWl0ZUhRKSDCtyBbTW9rb1N0YW5kYXJkc10oaHR0cHM6Ly9naXQubW9rb2NvbnN1bHRpbmcudGVjaC9Nb2tvQ29uc3VsdGluZy9tb2tvcGxhdGZvcm0vd2lraS9Ib21lKSoKCnwgUmV2aXNpb24gfCBEYXRlIHwgQXV0aG9yIHwgRGVzY3JpcHRpb24gfAp8LS0tfC0tLXwtLS18LS0tfAp8IDIuMCB8IDIwMjYtMDYtMTkgfCBNb2tvIENvbnN1bHRpbmcgfCBSZXdyaXRlIGZyb20gY29kZSByZXNlYXJjaCAtLSBhcmNoaXRlY3R1cmUsIGhlYXJ0YmVhdCBmbG93IHwKfCAxLjEgfCAyMDI2LTA2LTE4IHwgTW9rbyBDb25zdWx0aW5nIHwgRml4IHJlcG8gbmFtZSwgVVJMcyB8CnwgMS4wIHwgMjAyNi0wNS0wOSB8IE1va28gQ29uc3VsdGluZyB8IEluaXRpYWwgdmVyc2lvbiB8Cg==", + "guides/Configuration": "W+KGkCBCYWNrIHRvIEhvbWVdKEhvbWUpCgojIENvbmZpZ3VyYXRpb24KCkNvbmZpZ3VyYXRpb24gaXMgc3BsaXQgYmV0d2VlbiB0aGUgaG9zdCBjb21wb25lbnQgKGFubm91bmNlbWVudCBtYW5hZ2VtZW50KSBhbmQgdGhlIHJlbW90ZSBtb2R1bGUgKGRpc3BsYXkgc2V0dGluZ3MpLgoKIyMgSG9zdCBDb21wb25lbnQgQ29uZmlndXJhdGlvbgoKVGhlIGNvbXBvbmVudCBpdHNlbGYgaGFzIG1pbmltYWwgY29uZmlndXJhdGlvbi4gTWFuYWdlIGFubm91bmNlbWVudHMgYXQgKipDb21wb25lbnRzID4gTW9rb1dhYVNCYXNlKiogaW4gdGhlIEpvb21sYSBhZG1pbi4KCiMjIyBBbm5vdW5jZW1lbnQgRmllbGRzCgpFYWNoIGFubm91bmNlbWVudCBoYXM6Cgp8IEZpZWxkIHwgVHlwZSB8IERlc2NyaXB0aW9uIHwKfC0tLS0tLS18LS0tLS0tfC0tLS0tLS0tLS0tLS18CnwgKipUaXRsZSoqIHwgVGV4dCB8IEFubm91bmNlbWVudCBoZWFkbGluZSB8CnwgKipNZXNzYWdlKiogfCBUZXh0YXJlYSB8IEZ1bGwgYW5ub3VuY2VtZW50IGNvbnRlbnQgKHN1cHBvcnRzIGxpbmUgYnJlYWtzKSB8CnwgKipTdGF0dXMqKiB8IFB1Ymxpc2hlZC9VbnB1Ymxpc2hlZCB8IE9ubHkgcHVibGlzaGVkIGFubm91bmNlbWVudHMgYXBwZWFyIGluIEFQSSB8CnwgKipPcmRlcmluZyoqIHwgSW50ZWdlciB8IEN1c3RvbSBzb3J0IG9yZGVyIChkcmFnLWFuZC1kcm9wIGluIGxpc3QgdmlldykgfAoKIyMjIFBlcm1pc3Npb25zCgpDb25maWd1cmUgdmlhICoqQ29tcG9uZW50cyA+IE1va29XYWFTQmFzZSA+IE9wdGlvbnMgPiBQZXJtaXNzaW9ucyoqOgoKLSAqKkNyZWF0ZSoqOiBXaGljaCB1c2VyIGdyb3VwcyBjYW4gY3JlYXRlIG5ldyBhbm5vdW5jZW1lbnRzCi0gKipFZGl0Kio6IFdoaWNoIHVzZXIgZ3JvdXBzIGNhbiBlZGl0IGV4aXN0aW5nIGFubm91bmNlbWVudHMKLSAqKkRlbGV0ZSoqOiBXaGljaCB1c2VyIGdyb3VwcyBjYW4gZGVsZXRlIGFubm91bmNlbWVudHMKLSAqKk1hbmFnZSoqOiBXaGljaCB1c2VyIGdyb3VwcyBjYW4gYWNjZXNzIHRoZSBjb21wb25lbnQKCiMjIyBBUEkgRW5kcG9pbnQKClRoZSBKU09OIEFQSSBpcyBhdXRvbWF0aWNhbGx5IGF2YWlsYWJsZSBhdDoKCmBgYApodHRwczovL3lvdXItaG9zdC1zaXRlLmNvbS9pbmRleC5waHA/b3B0aW9uPWNvbV9tb2tvd2Fhc2Fubm91bmNlJnZpZXc9YXBpJmZvcm1hdD1qc29uCmBgYAoKUXVlcnkgcGFyYW1ldGVyczoKCnwgUGFyYW1ldGVyIHwgVmFsdWVzIHwgRGVmYXVsdCB8IERlc2NyaXB0aW9uIHwKfC0tLS0tLS0tLS0tfC0tLS0tLS0tfC0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tfAp8IGBsaW1pdGAgfCBJbnRlZ2VyIHwgNSB8IE1heGltdW0gYW5ub3VuY2VtZW50cyB0byByZXR1cm4gfAp8IGBvcmRlcmluZ2AgfCBgY3JlYXRlZGAsIGBvcmRlcmluZ2AgfCBgY3JlYXRlZGAgfCBTb3J0IGZpZWxkIHwKfCBgZGlyZWN0aW9uYCB8IGBBU0NgLCBgREVTQ2AgfCBgREVTQ2AgfCBTb3J0IGRpcmVjdGlvbiB8CgojIyBSZW1vdGUgTW9kdWxlIENvbmZpZ3VyYXRpb24KCkNvbmZpZ3VyZSBlYWNoIG1vZHVsZSBpbnN0YW5jZSBhdCAqKkV4dGVuc2lvbnMgPiBNb2R1bGVzKiogb24gdGhlIHJlbW90ZSBzaXRlLgoKIyMjIEJhc2ljIFRhYgoKfCBQYXJhbWV0ZXIgfCBUeXBlIHwgRGVmYXVsdCB8IFJlcXVpcmVkIHwgRGVzY3JpcHRpb24gfAp8LS0tLS0tLS0tLS18LS0tLS0tfC0tLS0tLS0tLXwtLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS18CnwgKipIb3N0IFVSTCoqIChgaG9zdF91cmxgKSB8IFVSTCB8ICooZW1wdHkpKiB8IFllcyB8IEZ1bGwgVVJMIG9mIHRoZSBob3N0IHNpdGUgaW5jbHVkaW5nIHByb3RvY29sIChlLmcuLCBgaHR0cHM6Ly95b3VyLWhvc3Qtc2l0ZS5jb21gKSB8CnwgKipOdW1iZXIgb2YgQW5ub3VuY2VtZW50cyoqIChgY291bnRgKSB8IFRleHQvTnVtYmVyIHwgYDVgIHwgTm8gfCBIb3cgbWFueSBhbm5vdW5jZW1lbnRzIHRvIGRpc3BsYXkgfAp8ICoqT3JkZXJpbmcqKiAoYG9yZGVyaW5nYCkgfCBMaXN0IHwgYGNyZWF0ZWRgIHwgTm8gfCBTb3J0IGZpZWxkOiAiQnkgRGF0ZSAoTmV3ZXN0KSIgb3IgIkN1c3RvbSBPcmRlcmluZyIgfAp8ICoqRGlyZWN0aW9uKiogKGBkaXJlY3Rpb25gKSB8IExpc3QgfCBgREVTQ2AgfCBObyB8IFNvcnQgZGlyZWN0aW9uOiBEZXNjZW5kaW5nIG9yIEFzY2VuZGluZyB8CnwgKipTaG93IERhdGUqKiAoYHNob3dfZGF0ZWApIHwgUmFkaW8gKFllcy9ObykgfCBZZXMgfCBObyB8IFdoZXRoZXIgdG8gZGlzcGxheSB0aGUgY3JlYXRpb24gZGF0ZSB3aXRoIGVhY2ggYW5ub3VuY2VtZW50IHwKCiMjIyBBZHZhbmNlZCBUYWIKCnwgUGFyYW1ldGVyIHwgVHlwZSB8IERlZmF1bHQgfCBEZXNjcmlwdGlvbiB8CnwtLS0tLS0tLS0tLXwtLS0tLS18LS0tLS0tLS0tfC0tLS0tLS0tLS0tLS18CnwgKipBbHRlcm5hdGl2ZSBMYXlvdXQqKiAoYGxheW91dGApIHwgTW9kdWxlIExheW91dCB8ICooZGVmYXVsdCkqIHwgU2VsZWN0IGFuIGFsdGVybmF0aXZlIHRlbXBsYXRlIGxheW91dCB8CnwgKipNb2R1bGUgQ2xhc3MgU3VmZml4KiogKGBtb2R1bGVjbGFzc19zZnhgKSB8IFRleHQgfCAqKGVtcHR5KSogfCBDU1MgY2xhc3Mgc3VmZml4IGZvciBzdHlsaW5nIHwKfCAqKkNhY2hpbmcqKiAoYGNhY2hlYCkgfCBMaXN0IHwgVXNlIEdsb2JhbCB8IE1vZHVsZS1sZXZlbCBjYWNoZSB0b2dnbGUgfAp8ICoqQ2FjaGUgVGltZSoqIChgY2FjaGVfdGltZWApIHwgVGV4dCB8IGA5MDBgIHwgQ2FjaGUgZHVyYXRpb24gaW4gc2Vjb25kcyAoMTUgbWludXRlcykgfAoKIyMjIFN0YW5kYXJkIEpvb21sYSBNb2R1bGUgU2V0dGluZ3MKClRoZXNlIGFyZSBjb25maWd1cmVkIG9uIHRoZSBtb2R1bGUgZWRpdGluZyBwYWdlIGl0c2VsZjoKCnwgU2V0dGluZyB8IERlc2NyaXB0aW9uIHwKfC0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tfAp8ICoqVGl0bGUqKiB8IE1vZHVsZSB0aXRsZSBkaXNwbGF5ZWQgb24gdGhlIGZyb250ZW5kIHwKfCAqKlNob3cgVGl0bGUqKiB8IFdoZXRoZXIgdG8gZGlzcGxheSB0aGUgbW9kdWxlIHRpdGxlIHwKfCAqKlBvc2l0aW9uKiogfCBUZW1wbGF0ZSBwb3NpdGlvbiB3aGVyZSB0aGUgbW9kdWxlIGFwcGVhcnMgfAp8ICoqU3RhdHVzKiogfCBQdWJsaXNoZWQgb3IgVW5wdWJsaXNoZWQgfAp8ICoqQWNjZXNzKiogfCBXaGljaCBhY2Nlc3MgbGV2ZWxzIGNhbiBzZWUgdGhlIG1vZHVsZSB8CnwgKipNb2R1bGUgQXNzaWdubWVudCoqIHwgV2hpY2ggcGFnZXMgZGlzcGxheSB0aGUgbW9kdWxlIChBbGwsIE5vbmUsIHNwZWNpZmljIG1lbnUgaXRlbXMpIHwKCiMjIENhY2hpbmcgQmVoYXZpb3IKClRoZSBtb2R1bGUgaW1wbGVtZW50cyB0d28gbGV2ZWxzIG9mIGNhY2hpbmc6CgojIyMgMS4gSGVscGVyLUxldmVsIENhY2hlICgxNSBtaW51dGVzKQoKVGhlIGBoZWxwZXIucGhwYCBjYWNoZXMgdGhlIHJhdyBBUEkgcmVzcG9uc2UgdXNpbmcgSm9vbWxhJ3Mgb3V0cHV0IGNhY2hlOgoKYGBgcGhwCiRjYWNoZSA9IEpGYWN0b3J5OjpnZXRDYWNoZSgnbW9kX21va293YWFzYW5ub3VuY2UnLCAnb3V0cHV0Jyk7CmBgYAoKVGhlIGNhY2hlIGtleSBpcyBhbiBNRDUgaGFzaCBvZiB0aGUgZnVsbCBBUEkgVVJMLCBzbyBkaWZmZXJlbnQgY29uZmlndXJhdGlvbnMgKGRpZmZlcmVudCBsaW1pdCwgb3JkZXJpbmcsIGV0Yy4pIGFyZSBjYWNoZWQgc2VwYXJhdGVseS4KCiMjIyAyLiBNb2R1bGUtTGV2ZWwgQ2FjaGUgKGNvbmZpZ3VyYWJsZSkKClRoZSBKb29tbGEgbW9kdWxlIGZyYW1ld29yayBwcm92aWRlcyBhZGRpdGlvbmFsIGNhY2hpbmcgdmlhIHRoZSBBZHZhbmNlZCB0YWIgc2V0dGluZ3MuIFRoZSBkZWZhdWx0IGBjYWNoZV90aW1lYCBvZiA5MDAgc2Vjb25kcyAoMTUgbWludXRlcykgY29udHJvbHMgaG93IG9mdGVuIHRoZSBtb2R1bGUgb3V0cHV0IEhUTUwgaXMgcmVnZW5lcmF0ZWQuCgojIyMgQ2FjaGUgQ2xlYXJpbmcKClRvIGZvcmNlIGFuIGltbWVkaWF0ZSB1cGRhdGUgYWZ0ZXIgY2hhbmdpbmcgYW5ub3VuY2VtZW50cyBvbiB0aGUgaG9zdDoKCjEuIE9uIHRoZSByZW1vdGUgc2l0ZTogKipTeXN0ZW0gPiBDbGVhciBDYWNoZSoqCjIuIE9yIHdhaXQgZm9yIHRoZSBjYWNoZSB0byBleHBpcmUgbmF0dXJhbGx5ICgxNSBtaW51dGVzKQoKIyMgRXhhbXBsZSBDb25maWd1cmF0aW9uCgpGb3IgYSB0eXBpY2FsIHNldHVwIGRpc3BsYXlpbmcgdGhlIDMgbW9zdCByZWNlbnQgYW5ub3VuY2VtZW50cyB3aXRoIGRhdGVzOgoKfCBTZXR0aW5nIHwgVmFsdWUgfAp8LS0tLS0tLS0tfC0tLS0tLS18CnwgSG9zdCBVUkwgfCBgaHR0cHM6Ly9jZW50cmFsLmV4YW1wbGUuY29tYCB8CnwgTnVtYmVyIG9mIEFubm91bmNlbWVudHMgfCBgM2AgfAp8IE9yZGVyaW5nIHwgQnkgRGF0ZSAoTmV3ZXN0KSB8CnwgRGlyZWN0aW9uIHwgRGVzY2VuZGluZyB8CnwgU2hvdyBEYXRlIHwgWWVzIHwKfCBDYWNoZSBUaW1lIHwgYDkwMGAgfAoKLS0tCgoKLS0tCgoqUmVwbzogW01va29XYWFTQmFzZV0oaHR0cHM6Ly9naXQubW9rb2NvbnN1bHRpbmcudGVjaC9Nb2tvQ29uc3VsdGluZy9Nb2tvV2FhU0Jhc2UpIMK3IFtNb2tvU3RhbmRhcmRzXShodHRwczovL2dpdC5tb2tvY29uc3VsdGluZy50ZWNoL01va29Db25zdWx0aW5nL21va29wbGF0Zm9ybS93aWtpL0hvbWUpKgoKfCBSZXZpc2lvbiB8IERhdGUgfCBBdXRob3IgfCBEZXNjcmlwdGlvbiB8CnwtLS18LS0tfC0tLXwtLS18CnwgMS4wIHwgMjAyNi0wNS0wOSB8IE1va28gQ29uc3VsdGluZyB8IEluaXRpYWwgdmVyc2lvbiB8Cg==", + "guides/Contributing": "W+KGkCBCYWNrIHRvIEhvbWVdKEhvbWUpCgojIENvbnRyaWJ1dGluZyB0byBNb2tvIENvbnN1bHRpbmcgUHJvamVjdHMKClRoYW5rIHlvdSBmb3IgeW91ciBpbnRlcmVzdCBpbiBjb250cmlidXRpbmcuIEFsbCBNb2tvIENvbnN1bHRpbmcgcmVwb3NpdG9yaWVzIGZvbGxvdyB0aGlzIHVuaXZlcnNhbCB3b3JrZmxvdyBhbmQgdmVyc2lvbiBwb2xpY3kuCgojIyBCcmFuY2hpbmcgV29ya2Zsb3cKCmBgYApmZWF0dXJlLyog4pSA4pSAUFLilIDilIA+IGRldiDilIDilIBkcmFmdCBQUuKUgOKUgD4gKHJlbmFtZWQgdG8gcmMpIOKUgOKUgG1lcmdl4pSA4pSAPiBtYWluCmBgYAoKIyMjIFN0ZXAgYnkgc3RlcAoKMS4gKipDcmVhdGUgYSBmZWF0dXJlIGJyYW5jaCoqIGZyb20gYGRldmA6CiAgIGBgYGJhc2gKICAgZ2l0IGNoZWNrb3V0IGRldiAmJiBnaXQgcHVsbAogICBnaXQgY2hlY2tvdXQgLWIgZmVhdHVyZS9teS1jaGFuZ2UKICAgYGBgCgoyLiAqKldvcmsgYW5kIGNvbW1pdCoqIG9uIHlvdXIgZmVhdHVyZSBicmFuY2guIFB1c2ggdG8gb3JpZ2luLgoKMy4gKipPcGVuIGEgUFIqKjogYGZlYXR1cmUvbXktY2hhbmdlYCDihpIgYGRldmAuIEFmdGVyIHJldmlldyBhbmQgY2hlY2tzLCBtZXJnZSBpdC4KCjQuICoqV2hlbiByZWFkeSBmb3IgcmVsZWFzZSoqLCBvcGVuIGEgKipkcmFmdCBQUioqOiBgZGV2YCDihpIgYG1haW5gLgogICAtIFRoaXMgYXV0b21hdGljYWxseSByZW5hbWVzIHRoZSBzb3VyY2UgYnJhbmNoIHRvIGByY2AgKHJlbGVhc2UgY2FuZGlkYXRlKQogICAtIEFuIFJDIHByZS1yZWxlYXNlIGlzIGJ1aWx0IGFuZCB1cGxvYWRlZAoKNS4gKipBbHBoYSBhbmQgYmV0YSBicmFuY2hlcyoqIGFyZSBjcmVhdGVkIGJ5IG1hbnVhbGx5IHJlbmFtaW5nIHRoZSBicmFuY2ggYmVmb3JlIHRoZSBSQyBzdGFnZToKICAgLSBSZW5hbWUgYGRldmAgdG8gYGFscGhhYCBmb3IgZWFybHkgdGVzdGluZyDihpIgYWxwaGEgcHJlLXJlbGVhc2UgaXMgYnVpbHQKICAgLSBSZW5hbWUgYGFscGhhYCB0byBgYmV0YWAgZm9yIGZlYXR1cmUtY29tcGxldGUgdGVzdGluZyDihpIgYmV0YSBwcmUtcmVsZWFzZSBpcyBidWlsdAogICAtIFdoZW4gdGhlIGRyYWZ0IFBSIGlzIGNyZWF0ZWQsIHRoZSBicmFuY2ggaXMgcmVuYW1lZCB0byBgcmNgCgo2LiAqKk9uY2UgUFIgY2hlY2tzIHBhc3MqKiBvbiB0aGUgYHJjYCBicmFuY2gsIG1hcmsgdGhlIFBSIGFzIHJlYWR5IGFuZCBtZXJnZSB0byBgbWFpbmAuCgo3LiAqKk1lcmdpbmcgdG8gbWFpbioqIHRyaWdnZXJzIHRoZSBzdGFibGUgcmVsZWFzZSBwaXBlbGluZToKICAgLSBNaW5vciB2ZXJzaW9uIGJ1bXAgKGUuZy4sIGAwMi4wOS54eGAg4oaSIGAwMi4xMC4wMGApCiAgIC0gU3RhYmlsaXR5IHN1ZmZpeCBzdHJpcHBlZCAoY2xlYW4gdmVyc2lvbikKICAgLSBNb2tvR2l0ZWEgcmVsZWFzZSBjcmVhdGVkIHdpdGggWklQL3Rhci5neiBwYWNrYWdlcwogICAtIGB1cGRhdGVzLnhtbGAgdXBkYXRlZCAoSm9vbWxhIGV4dGVuc2lvbnMpCiAgIC0gYGRldmAgYnJhbmNoIHJlY3JlYXRlZCBmcm9tIGBtYWluYAoKIyMjIEJyYW5jaCBzdW1tYXJ5Cgp8IEJyYW5jaCB8IFB1cnBvc2UgfCBDcmVhdGVkIGJ5IHwKfC0tLS0tLS0tfC0tLS0tLS0tLXwtLS0tLS0tLS0tLXwKfCBgZmVhdHVyZS8qYCB8IE5ldyBmZWF0dXJlcyBhbmQgZml4ZXMgfCBEZXZlbG9wZXIgfAp8IGBkZXZgIHwgSW50ZWdyYXRpb24gYnJhbmNoIHwgQXV0by1yZWNyZWF0ZWQgYWZ0ZXIgcmVsZWFzZSB8CnwgYGFscGhhYCB8IEFscGhhIHByZS1yZWxlYXNlIHRlc3RpbmcgfCBNYW51YWwgcmVuYW1lIGZyb20gYGRldmAgfAp8IGBiZXRhYCB8IEJldGEgcHJlLXJlbGVhc2UgdGVzdGluZyB8IE1hbnVhbCByZW5hbWUgZnJvbSBgYWxwaGFgIHwKfCBgcmNgIHwgUmVsZWFzZSBjYW5kaWRhdGUgfCBBdXRvLXJlbmFtZWQgb24gZHJhZnQgUFIgdG8gbWFpbiB8CnwgYG1haW5gIHwgU3RhYmxlIHJlbGVhc2VzIHwgUHJvdGVjdGVkLCBtZXJnZSBvbmx5IHwKfCBgdmVyc2lvbi9YWC5ZWS5aWmAgfCBBcmNoaXZlZCByZWxlYXNlIHNuYXBzaG90cyB8IEF1dG8tY3JlYXRlZCBieSBDSSB8CgojIyMgUHJvdGVjdGVkIGJyYW5jaGVzCgp8IEJyYW5jaCB8IERpcmVjdCBwdXNoIHwgTWVyZ2UgdmlhIHwKfC0tLS0tLS0tfC0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLXwKfCBgbWFpbmAgfCBCbG9ja2VkIChDSSBib3Qgd2hpdGVsaXN0ZWQpIHwgUFIgbWVyZ2Ugb25seSB8CnwgYGRldmAgfCBCbG9ja2VkIChDSSBib3Qgd2hpdGVsaXN0ZWQpIHwgUFIgbWVyZ2UgZnJvbSBmZWF0dXJlLyogfAp8IGByY2AgfCBCbG9ja2VkIChDSSBib3Qgd2hpdGVsaXN0ZWQpIHwgQXV0by1jcmVhdGVkIG9uIGRyYWZ0IFBSIHwKfCBgYWxwaGFgIHwgQmxvY2tlZCAoQ0kgYm90IHdoaXRlbGlzdGVkKSB8IE1hbnVhbCByZW5hbWUgfAp8IGBiZXRhYCB8IEJsb2NrZWQgKENJIGJvdCB3aGl0ZWxpc3RlZCkgfCBNYW51YWwgcmVuYW1lIHwKfCBgZmVhdHVyZS8qYCB8IE9wZW4gfCBOL0EgKHNvdXJjZSBicmFuY2gpIHwKCiMjIFZlcnNpb24gUG9saWN5CgojIyMgRm9ybWF0CgpBbGwgdmVyc2lvbnMgdXNlIGBYWC5ZWS5aWmAg4oCUIHRocmVlIHR3by1kaWdpdCBzZWdtZW50cywgemVyby1wYWRkZWQ6CgotICoqWFgqKiDigJQgTWFqb3IgdmVyc2lvbiAoYnJlYWtpbmcgY2hhbmdlcykKLSAqKllZKiog4oCUIE1pbm9yIHZlcnNpb24gKG5ldyBmZWF0dXJlcywgYnVtcGVkIG9uIHJlbGVhc2UgdG8gbWFpbikKLSAqKlpaKiog4oCUIFBhdGNoIHZlcnNpb24gKGF1dG8taW5jcmVtZW50ZWQgb24gZXZlcnkgcHVzaCB0byBkZXYvZmVhdHVyZSBicmFuY2hlcykKClJvbGxvdmVyOiBwYXRjaCBgOTlgIOKGkiBgMDBgIGluY3JlbWVudHMgbWlub3I7IG1pbm9yIGA5OWAg4oaSIGAwMGAgaW5jcmVtZW50cyBtYWpvci4KCiMjIyBTdGFiaWxpdHkgc3VmZml4ZXMKCkVhY2ggYnJhbmNoIGFwcGVuZHMgYSBzdWZmaXggdG8gaW5kaWNhdGUgc3RhYmlsaXR5OgoKfCBCcmFuY2ggfCBTdWZmaXggfCBFeGFtcGxlIHwKfC0tLS0tLS0tfC0tLS0tLS0tfC0tLS0tLS0tLXwKfCBgbWFpbmAgfCAobm9uZSkgfCBgMDIuMDkuMDBgIHwKfCBgZGV2YCB8IGAtZGV2YCB8IGAwMi4wOS4wMS1kZXZgIHwKfCBgZmVhdHVyZS8qYCB8IGAtZGV2YCB8IGAwMi4wOS4wMS1kZXZgIHwKfCBgYWxwaGFgIHwgYC1hbHBoYWAgfCBgMDIuMDkuMDEtYWxwaGFgIHwKfCBgYmV0YWAgfCBgLWJldGFgIHwgYDAyLjA5LjAxLWJldGFgIHwKfCBgcmNgIHwgYC1yY2AgfCBgMDIuMDkuMDEtcmNgIHwKCiMjIENvZGUgU3RhbmRhcmRzCgotICoqUEhQKio6IFBTUi0xMiwgdGFicyBmb3IgaW5kZW50YXRpb24KLSAqKkNvcHlyaWdodCoqOiBhbGwgZmlsZXMgbXVzdCBpbmNsdWRlIHRoZSBNb2tvIENvbnN1bHRpbmcgY29weXJpZ2h0IGhlYWRlcgotICoqTGljZW5zZSoqOiBTUERYIGlkZW50aWZpZXIgYEdQTC0zLjAtb3ItbGF0ZXJgIChvciBhcyBzcGVjaWZpZWQgcGVyIHJlcG8pCi0gKipBdHRyaWJ1dGlvbioqOiB1c2UgYEF1dGhvcmVkLWJ5OiBNb2tvIENvbnN1bHRpbmdgIGluIGNvbW1pdHMsIG5vdCBpbmRpdmlkdWFsIG5hbWVzCgojIyBDb21taXQgTWVzc2FnZXMKClVzZSBjb252ZW50aW9uYWwgY29tbWl0IGZvcm1hdDoKCmBgYAp0eXBlKHNjb3BlKTogc2hvcnQgZGVzY3JpcHRpb24KCk9wdGlvbmFsIGJvZHkgd2l0aCBjb250ZXh0LgoKQXV0aG9yZWQtYnk6IE1va28gQ29uc3VsdGluZwpgYGAKClR5cGVzOiBgZmVhdGAsIGBmaXhgLCBgY2hvcmVgLCBgZG9jc2AsIGBzdHlsZWAsIGByZWZhY3RvcmAsIGB0ZXN0YCwgYGNpYAoKU3BlY2lhbCBmbGFncyBpbiBjb21taXQgbWVzc2FnZXM6Ci0gYFtza2lwIGNpXWAg4oCUIHNraXAgYWxsIENJIHdvcmtmbG93cwotIGBbc2tpcCBidW1wXWAg4oCUIHNraXAgYXV0byB2ZXJzaW9uIGJ1bXAgb25seQoKIyMgUmVwb3J0aW5nIElzc3VlcwoKVXNlIHRoZSByZXBvc2l0b3J5J3MgaXNzdWUgdHJhY2tlciB3aXRoIHRoZSBhcHByb3ByaWF0ZSB0ZW1wbGF0ZS4KCi0tLQoKKlJlcG86IFtNb2tvV2FhU0Jhc2VdKGh0dHBzOi8vZ2l0Lm1va29jb25zdWx0aW5nLnRlY2gvTW9rb0NvbnN1bHRpbmcvTW9rb1dhYVNCYXNlKSDCtyBbTW9rb1N0YW5kYXJkc10oaHR0cHM6Ly9naXQubW9rb2NvbnN1bHRpbmcudGVjaC9Nb2tvQ29uc3VsdGluZy9tb2tvcGxhdGZvcm0vd2lraS9Ib21lKSoKCnwgUmV2aXNpb24gfCBEYXRlIHwgQXV0aG9yIHwgRGVzY3JpcHRpb24gfAp8LS0tfC0tLXwtLS18LS0tfAp8IDEuMCB8IDIwMjYtMDYtMDYgfCBNb2tvIENvbnN1bHRpbmcgfCBJbml0aWFsIHZlcnNpb24gZnJvbSBUZW1wbGF0ZS1Kb29tbGEgfAo=", + "guides/Installation": "W+KGkCBCYWNrIHRvIEhvbWVdKEhvbWUpCgojIEluc3RhbGxhdGlvbgoKTW9rb1dhYVNCYXNlIHVzZXMgYSB0d28tcGFydCBpbnN0YWxsYXRpb246IHRoZSAqKmNvbXBvbmVudCoqIG9uIHRoZSBob3N0IHNpdGUgYW5kIHRoZSAqKm1vZHVsZSoqIG9uIHJlbW90ZSBzaXRlcy4KCiMjIFJlcXVpcmVtZW50cwoKfCBSZXF1aXJlbWVudCB8IE1pbmltdW0gfAp8LS0tfC0tLXwKfCAqKkpvb21sYSoqIHwgMy54IG9yIGxhdGVyIHwKfCAqKlBIUCoqIHwgNS42IG9yIGxhdGVyIHwKfCAqKk15U1FMKiogfCA1LjUgb3IgbGF0ZXIgKGhvc3Qgc2l0ZSBvbmx5KSB8CnwgKipOZXR3b3JrKiogfCBSZW1vdGUgc2l0ZXMgbXVzdCBiZSBhYmxlIHRvIHJlYWNoIHRoZSBob3N0IHNpdGUgdmlhIEhUVFAvSFRUUFMgfAoKIyMgUGFydCAxOiBIb3N0IFNpdGUgKENvbXBvbmVudCkKCkluc3RhbGwgdGhlIGNvbXBvbmVudCBvbiB0aGUgKipvbmUgY2VudHJhbCBzaXRlKiogd2hlcmUgYW5ub3VuY2VtZW50cyB3aWxsIGJlIG1hbmFnZWQuCgojIyMgUGFja2FnZSB0aGUgQ29tcG9uZW50CgpgYGBiYXNoCmNkIHNyYy8KemlwIC1yIGNvbV9tb2tvd2Fhc2Fubm91bmNlLnppcCBjb21fbW9rb3dhYXNhbm5vdW5jZS8KYGBgCgojIyMgSW5zdGFsbCB2aWEgSm9vbWxhIEFkbWluCgoxLiBMb2cgaW4gdG8gdGhlIEpvb21sYSBhZG1pbmlzdHJhdG9yIHBhbmVsCjIuIE5hdmlnYXRlIHRvICoqRXh0ZW5zaW9ucyA+IE1hbmFnZSA+IEluc3RhbGwqKgozLiBDbGljayAqKlVwbG9hZCBQYWNrYWdlIEZpbGUqKgo0LiBTZWxlY3QgYGNvbV9tb2tvd2Fhc2Fubm91bmNlLnppcGAgYW5kIGNsaWNrICoqVXBsb2FkICYgSW5zdGFsbCoqCgojIyMgVmVyaWZ5IEluc3RhbGxhdGlvbgoKMS4gR28gdG8gKipDb21wb25lbnRzKiogaW4gdGhlIGFkbWluIG1lbnUKMi4gQ2xpY2sgKipNb2tvV2FhU0Jhc2UqKiB0byBvcGVuIHRoZSBtYW5hZ2VtZW50IGludGVyZmFjZQozLiBUZXN0IHRoZSBBUEkgZW5kcG9pbnQgaW4geW91ciBicm93c2VyOgoKYGBgCmh0dHBzOi8veW91ci1ob3N0LXNpdGUuY29tL2luZGV4LnBocD9vcHRpb249Y29tX21va293YWFzYW5ub3VuY2Umdmlldz1hcGkmZm9ybWF0PWpzb24KYGBgCgpFeHBlY3RlZCByZXNwb25zZSAoZW1wdHkgYXQgZmlyc3QpOgoKYGBganNvbgp7CiAgInN1Y2Nlc3MiOiB0cnVlLAogICJjb3VudCI6IDAsCiAgImFubm91bmNlbWVudHMiOiBbXQp9CmBgYAoKU2F2ZSB0aGlzIFVSTCAtLSByZW1vdGUgbW9kdWxlcyB3aWxsIG5lZWQgaXQuCgojIyMgQ29uZmlndXJlIFBlcm1pc3Npb25zIChPcHRpb25hbCkKCjEuIEdvIHRvICoqQ29tcG9uZW50cyA+IE1va29XYWFTQmFzZSA+IE9wdGlvbnMgPiBQZXJtaXNzaW9ucyoqCjIuIENvbmZpZ3VyZSB3aGljaCB1c2VyIGdyb3VwcyBjYW4gY3JlYXRlLCBlZGl0LCBkZWxldGUsIGFuZCBtYW5hZ2UgYW5ub3VuY2VtZW50cwoKIyMgUGFydCAyOiBSZW1vdGUgU2l0ZXMgKE1vZHVsZSkKCkluc3RhbGwgdGhlIG1vZHVsZSBvbiAqKmVhY2ggc2l0ZSoqIHRoYXQgc2hvdWxkIGRpc3BsYXkgYW5ub3VuY2VtZW50cyBmcm9tIHRoZSBob3N0LgoKIyMjIFBhY2thZ2UgdGhlIE1vZHVsZQoKYGBgYmFzaApjZCBzcmMvCnppcCAtciBtb2RfbW9rb3dhYXNhbm5vdW5jZS56aXAgbW9kX21va293YWFzYW5ub3VuY2UvCmBgYAoKIyMjIEluc3RhbGwgdmlhIEpvb21sYSBBZG1pbgoKMS4gTG9nIGluIHRvIHRoZSByZW1vdGUgc2l0ZSdzIEpvb21sYSBhZG1pbgoyLiBOYXZpZ2F0ZSB0byAqKkV4dGVuc2lvbnMgPiBNYW5hZ2UgPiBJbnN0YWxsKioKMy4gVXBsb2FkIGBtb2RfbW9rb3dhYXNhbm5vdW5jZS56aXBgCgojIyMgQ3JlYXRlIGEgTW9kdWxlIEluc3RhbmNlCgoxLiBHbyB0byAqKkV4dGVuc2lvbnMgPiBNb2R1bGVzID4gTmV3KioKMi4gU2VsZWN0ICoqTW9rb1dhYVNCYXNlKioKMy4gQ29uZmlndXJlOgoKfCBTZXR0aW5nIHwgVmFsdWUgfAp8LS0tLS0tLS0tfC0tLS0tLS18CnwgKipUaXRsZSoqIHwgZS5nLiwgIkxhdGVzdCBBbm5vdW5jZW1lbnRzIiB8CnwgKipQb3NpdGlvbioqIHwgU2VsZWN0IGEgdGVtcGxhdGUgcG9zaXRpb24gfAp8ICoqU3RhdHVzKiogfCBQdWJsaXNoZWQgfAp8ICoqSG9zdCBVUkwqKiB8IGBodHRwczovL3lvdXItaG9zdC1zaXRlLmNvbWAgKHRoZSBzaXRlIHdoZXJlIHRoZSBjb21wb25lbnQgaXMgaW5zdGFsbGVkKSB8Cgo0LiBBZGp1c3QgZGlzcGxheSBvcHRpb25zIChzZWUgW0NvbmZpZ3VyYXRpb25dKENvbmZpZ3VyYXRpb24pKQo1LiBTZXQgbW9kdWxlIGFzc2lnbm1lbnQgKHdoaWNoIHBhZ2VzIHNob3cgdGhlIG1vZHVsZSkKNi4gQ2xpY2sgKipTYXZlICYgQ2xvc2UqKgoKIyMjIFZlcmlmeSB0aGUgTW9kdWxlCgoxLiBWaXNpdCB0aGUgcmVtb3RlIHNpdGUncyBmcm9udGVuZAoyLiBOYXZpZ2F0ZSB0byBhIHBhZ2Ugd2hlcmUgdGhlIG1vZHVsZSBpcyBhc3NpZ25lZAozLiBBbm5vdW5jZW1lbnRzIGZyb20gdGhlIGhvc3Qgc2hvdWxkIGFwcGVhcgoKIyMgQWx0ZXJuYXRpdmUgSW5zdGFsbGF0aW9uOiBEaXJlY3RvcnkgVXBsb2FkCgpJZiB5b3UgaGF2ZSBGVFAvU1NIIGFjY2VzczoKCjEuIFVwbG9hZCBgY29tX21va293YWFzYW5ub3VuY2UvYCB0byBgL2FkbWluaXN0cmF0b3IvY29tcG9uZW50cy9jb21fbW9rb3dhYXNhbm5vdW5jZS9gCjIuIFVwbG9hZCBgbW9kX21va293YWFzYW5ub3VuY2UvYCB0byBgL21vZHVsZXMvbW9kX21va293YWFzYW5ub3VuY2UvYAozLiBJbiBKb29tbGEgYWRtaW46ICoqRXh0ZW5zaW9ucyA+IE1hbmFnZSA+IERpc2NvdmVyID4gRGlzY292ZXIgPiBJbnN0YWxsKioKCiMjIENyZWF0aW5nIFlvdXIgRmlyc3QgQW5ub3VuY2VtZW50CgoxLiBPbiB0aGUgKipob3N0IHNpdGUqKiwgZ28gdG8gKipDb21wb25lbnRzID4gTW9rb1dhYVNCYXNlKioKMi4gQ2xpY2sgKipOZXcqKgozLiBFbnRlciBhIHRpdGxlIGFuZCBtZXNzYWdlCjQuIFNldCBzdGF0dXMgdG8gKipQdWJsaXNoZWQqKgo1LiBDbGljayAqKlNhdmUgJiBDbG9zZSoqCgpUaGUgYW5ub3VuY2VtZW50IHdpbGwgYXBwZWFyIG9uIHJlbW90ZSBzaXRlcyB3aXRoaW4gMTUgbWludXRlcyAodGhlIGRlZmF1bHQgY2FjaGUgZHVyYXRpb24pLgoKIyMgVW5pbnN0YWxsYXRpb24KCiMjIyBSZW1vdmUgdGhlIE1vZHVsZSAoUmVtb3RlIFNpdGVzKQoKMS4gKipFeHRlbnNpb25zID4gTWFuYWdlID4gTWFuYWdlKiogPiBzZWFyY2ggIk1va29XYWFTQmFzZSIgPiBzZWxlY3QgbW9kdWxlID4gKipVbmluc3RhbGwqKgoKIyMjIFJlbW92ZSB0aGUgQ29tcG9uZW50IChIb3N0IFNpdGUpCgoxLiAqKkV4dGVuc2lvbnMgPiBNYW5hZ2UgPiBNYW5hZ2UqKiA+IHNlYXJjaCAiTW9rb1dhYVNCYXNlIiA+IHNlbGVjdCBjb21wb25lbnQgPiAqKlVuaW5zdGFsbCoqCgpXYXJuaW5nOiBVbmluc3RhbGxpbmcgdGhlIGNvbXBvbmVudCBkZWxldGVzIHRoZSBgI19fbW9rb3dhYXNhbm5vdW5jZWAgZGF0YWJhc2UgdGFibGUgYW5kIGFsbCBhbm5vdW5jZW1lbnQgZGF0YS4gQmFjayB1cCBmaXJzdCBpZiBuZWVkZWQuCgojIyBUcm91Ymxlc2hvb3RpbmcKCnwgUHJvYmxlbSB8IFNvbHV0aW9uIHwKfC0tLS0tLS0tLXwtLS0tLS0tLS0tfAp8IENvbXBvbmVudCBub3QgYXBwZWFyaW5nIHwgQ2xlYXIgSm9vbWxhIGNhY2hlOyBjaGVjayB1c2VyIHBlcm1pc3Npb25zIHwKfCBNb2R1bGUgc2hvd3Mgbm8gYW5ub3VuY2VtZW50cyB8IFZlcmlmeSBIb3N0IFVSTCBpbmNsdWRlcyBwcm90b2NvbCAoYGh0dHBzOi8vYCk7IGNoZWNrIHRoYXQgYW5ub3VuY2VtZW50cyBhcmUgcHVibGlzaGVkIG9uIGhvc3QgfAp8IENvbm5lY3Rpb24gZXJyb3JzIHwgVmVyaWZ5IGhvc3QgaXMgcHVibGljbHkgYWNjZXNzaWJsZTsgY2hlY2sgZmlyZXdhbGwgcnVsZXM7IGVuc3VyZSBgYWxsb3dfdXJsX2ZvcGVuYCBvciBjVVJMIGlzIGVuYWJsZWQgfAp8IERhdGFiYXNlIGVycm9ycyAoaG9zdCkgfCBDaGVjayBNeVNRTCBpcyBydW5uaW5nOyB2ZXJpZnkgYENSRUFURSBUQUJMRWAgcGVybWlzc2lvbnMgfAoKLS0tCgoKLS0tCgoqUmVwbzogW01va29XYWFTQmFzZV0oaHR0cHM6Ly9naXQubW9rb2NvbnN1bHRpbmcudGVjaC9Nb2tvQ29uc3VsdGluZy9Nb2tvV2FhU0Jhc2UpIMK3IFtNb2tvU3RhbmRhcmRzXShodHRwczovL2dpdC5tb2tvY29uc3VsdGluZy50ZWNoL01va29Db25zdWx0aW5nL21va29wbGF0Zm9ybS93aWtpL0hvbWUpKgoKfCBSZXZpc2lvbiB8IERhdGUgfCBBdXRob3IgfCBEZXNjcmlwdGlvbiB8CnwtLS18LS0tfC0tLXwtLS18CnwgMS4wIHwgMjAyNi0wNS0wOSB8IE1va28gQ29uc3VsdGluZyB8IEluaXRpYWwgdmVyc2lvbiB8Cg==", + "reference/Architecture": "W+KGkCBCYWNrIHRvIEhvbWVdKEhvbWUpCgojIEFyY2hpdGVjdHVyZQoKTW9rb1dhYVNCYXNlIHVzZXMgYSBkaXN0cmlidXRlZCBjbGllbnQtc2VydmVyIGFyY2hpdGVjdHVyZSB3aGVyZSBvbmUgaG9zdCBzaXRlIG1hbmFnZXMgYW5ub3VuY2VtZW50cyBhbmQgYW55IG51bWJlciBvZiByZW1vdGUgc2l0ZXMgZmV0Y2ggYW5kIGRpc3BsYXkgdGhlbSB2aWEgYSBKU09OIEFQSS4KCiMjIFN5c3RlbSBEaWFncmFtCgpgYGAK4pSM4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSQCuKUgiAgICAgICAgIEhvc3QgSm9vbWxhIFNpdGUgICAgICAgICAgICAg4pSCCuKUgiAgKENlbnRyYWwgTWFuYWdlbWVudCkgICAgICAgICAgICAgICDilIIK4pSCICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICDilIIK4pSCICDilIzilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilJAgICAg4pSCCuKUgiAg4pSCICBjb21fbW9rb3dhYXNhbm5vdW5jZSAgICAgICDilIIgICAg4pSCCuKUgiAg4pSCICAoQWRtaW4gQ29tcG9uZW50KSAgICAgICAgICDilIIgICAg4pSCCuKUgiAg4pSCICAgICAgICAgICAgICAgICAgICAgICAgICAgICDilIIgICAg4pSCCuKUgiAg4pSCICAtIENSVUQgZm9yIGFubm91bmNlbWVudHMgICDilIIgICAg4pSCCuKUgiAg4pSCICAtIERhdGFiYXNlIHN0b3JhZ2UgICAgICAgICDilIIgICAg4pSCCuKUgiAg4pSCICAtIEpTT04gQVBJIGVuZHBvaW50ICAgICAgICDilIIgICAg4pSCCuKUgiAg4pSU4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSYICAgIOKUggrilJTilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilKzilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilJgKICAgICAgICAgICAgICAgIOKUgiAgICAgICAgICAgICAg4pSCCiAgICAgICAgICAgICAgIOKUgiAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgIOKUggogICAgIOKUjOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUtOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUrOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUkAogICAgIOKUgiAgICAgICAgICAgICAgICAgICDilIIgICAgICAgICAgICAgIOKUggogICAgIOKWvCAgICAgICAgICAgICAgICAgICDilrwgICAgICAgICAgICAgIOKWvArilIzilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilJAgICAgICAgIOKUjOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUkCAgIOKUjOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUkArilIIgUmVtb3RlIDEg4pSCICAgICAgICDilIIgUmVtb3RlIDIg4pSCICAg4pSCIFJlbW90ZSBOIOKUggrilIIgICAgICAgICAg4pSCICAgICAgICDilIIgICAgICAgICAg4pSCICAg4pSCICAgICAgICAgIOKUggrilIIgbW9kX2FubiAg4pSCICAgICAgICDilIIgbW9kX2FubiAg4pSCICAg4pSCIG1vZF9hbm4gIOKUggrilIIgKEZldGNoICAg4pSCICAgICAgICDilIIgKEZldGNoICAg4pSCICAg4pSCIChGZXRjaCAgIOKUggrilIIgJiBDYWNoZSAg4pSCICAgICAgICDilIIgJiBDYWNoZSAg4pSCICAg4pSCICYgQ2FjaGUgIOKUggrilIIgJiBEaXNwbGF54pSCICAgICAgICDilIIgJiBEaXNwbGF54pSCICAg4pSCICYgRGlzcGxheeKUggrilJTilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilJggICAgICAgIOKUlOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUmCAgIOKUlOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUmApgYGAKCiMjIEhvc3QgU2l0ZSBDb21wb25lbnRzCgpUaGUgaG9zdCBzaXRlIHJ1bnMgYGNvbV9tb2tvd2Fhc2Fubm91bmNlYCBhcyBhbiBhZG1pbi1vbmx5IGNvbXBvbmVudC4gTm8gbW9kdWxlIGlzIG5lZWRlZCBvbiB0aGUgaG9zdC4KCiMjIyBEaXJlY3RvcnkgU3RydWN0dXJlCgpgYGAKY29tX21va293YWFzYW5ub3VuY2UvCuKUnOKUgOKUgCBtb2tvd2Fhc2Fubm91bmNlLnhtbCAgICAgICAjIENvbXBvbmVudCBtYW5pZmVzdArilJzilIDilIAgYWRtaW4vCuKUgiAgIOKUnOKUgOKUgCBtb2tvd2Fhc2Fubm91bmNlLnBocCAgICMgQWRtaW4gZW50cnkgcG9pbnQK4pSCICAg4pSc4pSA4pSAIGNvbnRyb2xsZXIucGhwICAgICAgICAgIyBNYWluIGNvbnRyb2xsZXIK4pSCICAg4pSc4pSA4pSAIGNvbmZpZy54bWwgICAgICAgICAgICAgIyBDb21wb25lbnQgY29uZmlndXJhdGlvbgrilIIgICDilJzilIDilIAgY29udHJvbGxlcnMvCuKUgiAgIOKUgiAgIOKUlOKUgOKUgCBhbm5vdW5jZW1lbnQucGhwICAgIyBTaW5nbGUgYW5ub3VuY2VtZW50IGNvbnRyb2xsZXIK4pSCICAg4pSc4pSA4pSAIG1vZGVscy8K4pSCICAg4pSCICAg4pSc4pSA4pSAIGFubm91bmNlbWVudC5waHAgICAjIFNpbmdsZSBhbm5vdW5jZW1lbnQgbW9kZWwK4pSCICAg4pSCICAg4pSc4pSA4pSAIGFubm91bmNlbWVudHMucGhwICAjIExpc3QgbW9kZWwK4pSCICAg4pSCICAg4pSU4pSA4pSAIGZvcm1zLwrilIIgICDilIIgICAgICAgIOKUlOKUgOKUgCBhbm5vdW5jZW1lbnQueG1sICAjIEVkaXQgZm9ybSBkZWZpbml0aW9uCuKUgiAgIOKUnOKUgOKUgCB2aWV3cy8gICAgICAgICAgICAgICAgICMgQWRtaW4gdmlldyB0ZW1wbGF0ZXMK4pSCICAg4pSc4pSA4pSAIHRhYmxlcy8K4pSCICAg4pSCICAg4pSU4pSA4pSAIGFubm91bmNlbWVudC5waHAgICAjIERhdGFiYXNlIHRhYmxlIGNsYXNzCuKUgiAgIOKUnOKUgOKUgCBoZWxwZXJzLwrilIIgICDilIIgICDilJTilIDilIAgYW5ub3VuY2VtZW50cy5waHAgICMgU3VibWVudSBhbmQgcGVybWlzc2lvbiBoZWxwZXJzCuKUgiAgIOKUnOKUgOKUgCBzcWwvICAgICAgICAgICAgICAgICAgICMgSW5zdGFsbC91bmluc3RhbGwgU1FMIHNjcmlwdHMK4pSCICAg4pSU4pSA4pSAIGxhbmd1YWdlLwrilIIgICAgICAgIOKUlOKUgOKUgCBlbi1HQi8gICAgICAgICAgICAgIyBMYW5ndWFnZSBmaWxlcwrilJTilIDilIAgc2l0ZS8gICAgICAgICAgICAgICAgICAgICAgIyBTaXRlLXNpZGUgKEFQSSBlbmRwb2ludCkKYGBgCgojIyMgRGF0YWJhc2UgVGFibGUKClRoZSBjb21wb25lbnQgY3JlYXRlcyBhIHNpbmdsZSB0YWJsZSBgI19fbW9rb3dhYXNhbm5vdW5jZWAgd2l0aCBmaWVsZHMgZm9yIHRpdGxlLCBtZXNzYWdlLCBwdWJsaXNoZWQgc3RhdGUsIG9yZGVyaW5nLCBhbmQgdGltZXN0YW1wcy4KCiMjIyBKU09OIEFQSQoKVGhlIHNpdGUtc2lkZSB2aWV3IHByb3ZpZGVzIGEgcHVibGljIEpTT04gZW5kcG9pbnQ6CgpgYGAKR0VUIC9pbmRleC5waHA/b3B0aW9uPWNvbV9tb2tvd2Fhc2Fubm91bmNlJnZpZXc9YXBpJmZvcm1hdD1qc29uCiAgICAmb3JkZXJpbmc9Y3JlYXRlZCAgICAgIyBTb3J0IGZpZWxkIChjcmVhdGVkIG9yIG9yZGVyaW5nKQogICAgJmRpcmVjdGlvbj1ERVNDICAgICAgICMgU29ydCBkaXJlY3Rpb24gKEFTQyBvciBERVNDKQpgYGAKClJlc3BvbnNlIGZvcm1hdDoKCmBgYGpzb24KewogICJzdWNjZXNzIjogdHJ1ZSwKICAiY291bnQiOiAyLAogICJhbm5vdW5jZW1lbnRzIjogWwogICAgewogICAgICAiaWQiOiAxLAogICAgICAidGl0bGUiOiAiU2NoZWR1bGVkIE1haW50ZW5hbmNlIiwKICAgICAgIm1lc3NhZ2UiOiAiU2l0ZSB3aWxsIGJlIGRvd24gU2F0dXJkYXkgMi00IEFNL +iIsCiAgICAgICJjcmVhdGVkIjogIjIwMjYtMDUtMDEgMTI6MDA6MDAiLAogICAgICAib3JkZXJpbmciOiAxCiAgICB9CiAgXQp9CmBgYAoKIyMgUmVtb3RlIE1vZHVsZQoKUmVtb3RlIHNpdGVzIHJ1biBgbW9kX21va293YWFzYW5ub3VuY2VgLCB3aGljaCBmZXRjaGVzIGFubm91bmNlbWVudHMgZnJvbSB0aGUgaG9zdCBBUEkgYW5kIGRpc3BsYXlzIHRoZW0uCgojIyMgRGlyZWN0b3J5IFN0cnVjdHVyZQoKYGBgCm1vZF9tb2tvd2Fhc2Fubm91bmNlLwrilJzilIDilIAgbW9kX21va293YWFzYW5ub3VuY2UueG1sICAgIyBNb2R1bGUgbWFuaWZlc3QK4pSc4pSA4pSAIG1vZF9tb2tvd2Fhc2Fubm91bmNlLnBocCAgICMgRW50cnkgcG9pbnQK4pSc4pSA4pSAIGhlbHBlci5waHAgICAgICAgICAgICAgICAgIyBBUEkgZmV0Y2hpbmcgbG9naWMK4pSc4pSA4pSAIHRtcGwvCuKUgiAgIOKUlOKUgOKUgCBkZWZhdWx0LnBocCAgICAgICAgICAgICMgRGlzcGxheSB0ZW1wbGF0ZQrilJTilIDilIAgbGFuZ3VhZ2UvCiAgICDilJTilIDilIAgZW4tR0IvICAgICAgICAgICAgICAgICAjIExhbmd1YWdlIGZpbGVzCmBgYAoKIyMjIERhdGEgRmxvdwoKMS4gTW9kdWxlIGxvYWRzIGFuZCByZWFkcyBgaG9zdF91cmxgIHBhcmFtZXRlcgoyLiBgTW9kTW9rb3dhYXNhbm5vdW5jZUhlbHBlcjo6Z2V0QW5ub3VuY2VtZW50cygpYCBpcyBjYWxsZWQKMy4gSGVscGVyIGNoZWNrcyBKb29tbGEgY2FjaGUgZm9yIGEgY2FjaGVkIHJlc3BvbnNlIChrZXllZCBieSBBUEkgVVJMIGhhc2gpCjQuIElmIGNhY2hlIG1pc3M6IHNlbmRzIEhUVFAgR0VUIHRvIGhvc3QgQVBJIHZpYSBgSkh0dHBGYWN0b3J5OjpnZXRIdHRwKClgIHdpdGggMTAtc2Vjb25kIHRpbWVvdXQKNS4gVmFsaWRhdGVzIHJlc3BvbnNlIChIVFRQIDIwMCwgYHN1Y2Nlc3M6IHRydWVgKQo2LiBDYWNoZXMgcmVzdWx0IGZvciAxNSBtaW51dGVzICh2aWEgSm9vbWxhJ3Mgb3V0cHV0IGNhY2hlKQo3LiBSZXR1cm5zIGFycmF5IG9mIGFubm91bmNlbWVudCBvYmplY3RzIHRvIHRlbXBsYXRlIGZvciByZW5kZXJpbmcKCiMjIyBDYWNoaW5nCgpUaGUgbW9kdWxlIHVzZXMgSm9vbWxhJ3MgYnVpbHQtaW4gY2FjaGUgc3lzdGVtOgoKYGBgcGhwCiRjYWNoZSA9IEpGYWN0b3J5OjpnZXRDYWNoZSgnbW9kX21va293YWFzYW5ub3VuY2UnLCAnb3V0cHV0Jyk7CiRjYWNoZUtleSA9IG1kNSgkYXBpVXJsKTsKYGBgCgotIENhY2hlIGdyb3VwOiBgbW9kX21va293YWFzYW5ub3VuY2VgCi0gQ2FjaGUga2V5OiBNRDUgaGFzaCBvZiB0aGUgZnVsbCBBUEkgVVJMIChpbmNsdWRlcyBsaW1pdCwgb3JkZXJpbmcsIGRpcmVjdGlvbiBwYXJhbWV0ZXJzKQotIER1cmF0aW9uOiAxNSBtaW51dGVzIChKb29tbGEgZGVmYXVsdCBjYWNoZSBsaWZldGltZSkKLSBBZGRpdGlvbmFsIG1vZHVsZS1sZXZlbCBjYWNoZSBzZXR0aW5ncyBhdmFpbGFibGUgaW4gQWR2YW5jZWQgdGFiIChkZWZhdWx0OiA5MDAgc2Vjb25kcykKCiMjIyBFcnJvciBIYW5kbGluZwoKVGhlIGhlbHBlciBoYW5kbGVzIHNldmVyYWwgZmFpbHVyZSBtb2RlczoKCnwgQ29uZGl0aW9uIHwgQmVoYXZpb3IgfAp8LS0tLS0tLS0tLS18LS0tLS0tLS0tLXwKfCBFbXB0eSBob3N0IFVSTCB8IFdhcm5pbmcgbWVzc2FnZSwgcmV0dXJucyBlbXB0eSBhcnJheSB8CnwgSFRUUCBlcnJvciAobm9uLTIwMCkgfCBFcnJvciBtZXNzYWdlIHdpdGggc3RhdHVzIGNvZGUsIHJldHVybnMgZW1wdHkgYXJyYXkgfAp8IEludmFsaWQgSlNPTiByZXNwb25zZSB8IEVycm9yIG1lc3NhZ2UsIHJldHVybnMgZW1wdHkgYXJyYXkgfAp8IGBzdWNjZXNzOiBmYWxzZWAgaW4gcmVzcG9uc2UgfCBEaXNwbGF5cyBlcnJvciBmcm9tIEFQSSByZXNwb25zZSB8CnwgTmV0d29yay9jb25uZWN0aW9uIGZhaWx1cmUgfCBDYXRjaGVzIGV4Y2VwdGlvbiwgZGlzcGxheXMgZXJyb3IgbWVzc2FnZSB8CgpBbGwgZXJyb3JzIHVzZSBgSkZhY3Rvcnk6OmdldEFwcGxpY2F0aW9uKCktPmVucXVldWVNZXNzYWdlKClgIHRvIGRpc3BsYXkgdXNlci1mYWNpbmcgbWVzc2FnZXMgd2l0aG91dCBicmVha2luZyB0aGUgcGFnZS4KCiMjIFNlY3VyaXR5CgotICoqSG9zdCBzaWRlKio6IEpFWEVDIGNoZWNrcyBvbiBhbGwgZmlsZXMsIGlucHV0IGZpbHRlcmluZyB2aWEgSm9vbWxhJ3MgcXVlcnkgYnVpbGRlciwgcGVybWlzc2lvbiBjaGVja3MgdmlhIEFDTAotICoqTW9kdWxlIHNpZGUqKjogVVJMIHNhbml0aXphdGlvbiwgb3V0cHV0IGVzY2FwaW5nLCBIVFRQLW9ubHkgY29tbXVuaWNhdGlvbgotICoqQVBJKio6IFB1YmxpYyByZWFkLW9ubHkgZW5kcG9pbnQgKG5vIGF1dGhlbnRpY2F0aW9uIHJlcXVpcmVkIGZvciBmZXRjaGluZyBhbm5vdW5jZW1lbnRzKQoKLS0tCgoKLS0tCgoqUmVwbzogW01va29XYWFTQmFzZV0oaHR0cHM6Ly9naXQubW9rb2NvbnN1bHRpbmcudGVjaC9Nb2tvQ29uc3VsdGluZy9Nb2tvV2FhU0Jhc2UpIMK3IFtNb2tvU3RhbmRhcmRzXShodHRwczovL2dpdC5tb2tvY29uc3VsdGluZy50ZWNoL01va29Db25zdWx0aW5nL21va29wbGF0Zm9ybS93aWtpL0hvbWUpKgoKfCBSZXZpc2lvbiB8IERhdGUgfCBBdXRob3IgfCBEZXNjcmlwdGlvbiB8CnwtLS18LS0tfC0tLXwtLS18CnwgMS4wIHwgMjAyNi0wNS0wOSB8IE1va28gQ29uc3VsdGluZyB8IEluaXRpYWwgdmVyc2lvbiB8Cg==", + "reference/Security": "W+KGkCBCYWNrIHRvIEhvbWVdKEhvbWUpCgojIFNlY3VyaXR5IFBvbGljeQoKIyMgU3VwcG9ydGVkIFZlcnNpb25zCgpTZWN1cml0eSB1cGRhdGVzIGFyZSBwcm92aWRlZCBmb3IgdGhlIGZvbGxvd2luZyB2ZXJzaW9uczoKCnwgVmVyc2lvbiB8IFN1cHBvcnRlZCAgICAgICAgICB8CnwgLS0tLS0tLSB8IC0tLS0tLS0tLS0tLS0tLS0tLSB8CnwgMDEueC54ICB8IDp3aGl0ZV9jaGVja19tYXJrOiB8CnwgPCAwMS4wICB8IDp4OiAgICAgICAgICAgICAgICB8CgpPbmx5IHRoZSBjdXJyZW50IG1ham9yIHZlcnNpb24gcmVjZWl2ZXMgc2VjdXJpdHkgdXBkYXRlcy4KCiMjIFJlcG9ydGluZyBhIFZ1bG5lcmFiaWxpdHkKCiMjIyBXaGVyZSB0byBSZXBvcnQKCioqRE8gTk9UKiogY3JlYXRlIHB1YmxpYyBpc3N1ZXMgZm9yIHNlY3VyaXR5IHZ1bG5lcmFiaWxpdGllcy4KClJlcG9ydCBzZWN1cml0eSB2dWxuZXJhYmlsaXRpZXMgcHJpdmF0ZWx5IHRvOgoKKipFbWFpbCoqOiBgc2VjdXJpdHlAbW9rb2NvbnN1bHRpbmcudGVjaGAKCioqU3ViamVjdCBMaW5lKio6IGBbU0VDVVJJVFldIE1va29XYWFTQmFzZSAtIEJyaWVmIERlc2NyaXB0aW9uYAoKIyMjIFdoYXQgdG8gSW5jbHVkZQoKMS4gKipEZXNjcmlwdGlvbioqOiBDbGVhciBleHBsYW5hdGlvbiBvZiB0aGUgdnVsbmVyYWJpbGl0eQoyLiAqKkltcGFjdCoqOiBQb3RlbnRpYWwgc2VjdXJpdHkgaW1wYWN0IGFuZCBzZXZlcml0eSBhc3Nlc3NtZW50CjMuICoqQWZmZWN0ZWQgVmVyc2lvbnMqKjogV2hpY2ggdmVyc2lvbnMgYXJlIHZ1bG5lcmFibGUKNC4gKipSZXByb2R1Y3Rpb24gU3RlcHMqKjogRGV0YWlsZWQgc3RlcHMgdG8gcmVwcm9kdWNlIHRoZSBpc3N1ZQo1LiAqKlByb29mIG9mIENvbmNlcHQqKjogQ29kZSwgY29uZmlndXJhdGlvbiwgb3IgZGVtb25zdHJhdGlvbiAoaWYgYXBwbGljYWJsZSkKNi4gKipTdWdnZXN0ZWQgRml4Kio6IFByb3Bvc2VkIHJlbWVkaWF0aW9uIChpZiBrbm93bikKCiMjIyBSZXNwb25zZSBUaW1lbGluZQoKKiAqKkluaXRpYWwgUmVzcG9uc2UqKjogV2l0aGluIDMgYnVzaW5lc3MgZGF5cwoqICoqQXNzZXNzbWVudCBDb21wbGV0ZSoqOiBXaXRoaW4gNyBidXNpbmVzcyBkYXlzCiogKipGaXggVGltZWxpbmUqKjogRGVwZW5kcyBvbiBzZXZlcml0eSAoc2VlIGJlbG93KQoqICoqRGlzY2xvc3VyZSoqOiBDb29yZGluYXRlZCB3aXRoIHJlcG9ydGVyCgojIyBTZXZlcml0eSBDbGFzc2lmaWNhdGlvbgoKIyMjIENyaXRpY2FsCiogUmVtb3RlIGNvZGUgZXhlY3V0aW9uCiogQXV0aGVudGljYXRpb24gYnlwYXNzCiogRGF0YSBicmVhY2ggb3IgZXhwb3N1cmUgb2Ygc2Vuc2l0aXZlIGluZm9ybWF0aW9uCiogKipGaXggVGltZWxpbmUqKjogNyBkYXlzCgojIyMgSGlnaAoqIFByaXZpbGVnZSBlc2NhbGF0aW9uCiogU1FMIGluamVjdGlvbiBvciBjb21tYW5kIGluamVjdGlvbgoqIENyb3NzLXNpdGUgc2NyaXB0aW5nIChYU1MpIHdpdGggc2lnbmlmaWNhbnQgaW1wYWN0CiogKipGaXggVGltZWxpbmUqKjogMTQgZGF5cwoKIyMjIE1lZGl1bQoqIEluZm9ybWF0aW9uIGRpc2Nsb3N1cmUgKGxpbWl0ZWQgc2NvcGUpCiogRGVuaWFsIG9mIHNlcnZpY2UKKiBTZWN1cml0eSBtaXNjb25maWd1cmF0aW9ucyB3aXRoIG1vZGVyYXRlIGltcGFjdAoqICoqRml4IFRpbWVsaW5lKio6IDMwIGRheXMKCiMjIyBMb3cKKiBTZWN1cml0eSBiZXN0IHByYWN0aWNlIHZpb2xhdGlvbnMKKiBNaW5vciBpbmZvcm1hdGlvbiBsZWFrcwoqIElzc3VlcyByZXF1aXJpbmcgdXNlciBpbnRlcmFjdGlvbiBvciBjb21wbGV4IHByZWNvbmRpdGlvbnMKKiAqKkZpeCBUaW1lbGluZSoqOiA2MCBkYXlzIG9yIG5leHQgcmVsZWFzZQoKIyMgSm9vbWxhIEV4dGVuc2lvbiBTZWN1cml0eQoKKiBGb2xsb3cgSm9vbWxhIHNlY3VyaXR5IGJlc3QgcHJhY3RpY2VzCiogVmFsaWRhdGUgYW5kIHNhbml0aXplIGFsbCB1c2VyIGlucHV0CiogVXNlIEpvb21sYSdzIGRhdGFiYXNlIEFQSSB0byBwcmV2ZW50IFNRTCBpbmplY3Rpb24KKiBQcm9wZXJseSBlc2NhcGUgb3V0cHV0IHRvIHByZXZlbnQgWFNTCiogSW1wbGVtZW50IHByb3BlciBhY2Nlc3MgY29udHJvbCBjaGVja3MKKiBVc2UgSm9vbWxhJ3Mgc2Vzc2lvbiBhbmQgYXV0aGVudGljYXRpb24gQVBJcwoqIEtlZXAgSm9vbWxhIGFuZCBkZXBlbmRlbmNpZXMgdXAgdG8gZGF0ZQoKIyMgQ29udGFjdAoKKiAqKlNlY3VyaXR5IFRlYW0qKjogc2VjdXJpdHlAbW9rb2NvbnN1bHRpbmcudGVjaAoqICoqUHJpbWFyeSBDb250YWN0Kio6IGhlbGxvQG1va29jb25zdWx0aW5nLnRlY2gKCiMjIE91dCBvZiBTY29wZQoKKiBJc3N1ZXMgaW4gdGhpcmQtcGFydHkgZGVwZW5kZW5jaWVzIChyZXBvcnQgZGlyZWN0bHkgdG8gbWFpbnRhaW5lcnMpCiogU29jaWFsIGVuZ2luZWVyaW5nIGF0dGFja3MKKiBQaHlzaWNhbCBzZWN1cml0eSBpc3N1ZXMKKiBEZW5pYWwgb2Ygc2VydmljZSB2aWEgcmVzb3VyY2UgZXhoYXVzdGlvbiB3aXRob3V0IGFtcGxpZmljYXRpb24KKiBUaGVvcmV0aWNhbCB2dWxuZXJhYmlsaXRpZXMgd2l0aG91dCBwcm9vZiBvZiBleHBsb2l0YWJpbGl0eQoKLS0tCgoqUmVwbzogW01va29XYWFTQmFzZV0oaHR0cHM6Ly9naXQubW9rb2NvbnN1bHRpbmcudGVjaC9Nb2tvQ29uc3VsdGluZy9Nb2tvV2FhU0Jhc2UpIMK3IFtNb2tvU3RhbmRhcmRzXShodHRwczovL2dpdC5tb2tvY29uc3VsdGluZy50ZWNoL01va29Db25zdWx0aW5nL21va29wbGF0Zm9ybS93aWtpL0hvbWUpKgoKfCBSZXZpc2lvbiB8IERhdGUgfCBBdXRob3IgfCBEZXNjcmlwdGlvbiB8CnwtLS18LS0tfC0tLXwtLS18CnwgMS4wIHwgMjAyNi0wNi0wNiB8IE1va28gQ29uc3VsdGluZyB8IEluaXRpYWwgdmVyc2lvbiBmcm9tIFRlbXBsYXRlLUpvb21sYSB8Cg==" +} + +for page_name, b64 in pages.items(): + original = base64.b64decode(b64).decode('utf-8') + updated = apply_replacements(original) + new_b64 = base64.b64encode(updated.encode('utf-8')).decode('ascii') + changed = original != updated + print(f'PAGE:{page_name}|CHANGED:{changed}|B64:{new_b64}') diff --git a/tools/legal_doc_generator.html b/tools/legal_doc_generator.html index e3ec54c..ff9e295 100644 --- a/tools/legal_doc_generator.html +++ b/tools/legal_doc_generator.html @@ -769,7 +769,7 @@ content = generateTermsOfService(data) + '
' + generatePrivacyPolicy(data); } - content += ``; + content += ``; return content; } diff --git a/validate/auto_detect_platform.php b/validate/auto_detect_platform.php index 899d314..86dc735 100755 --- a/validate/auto_detect_platform.php +++ b/validate/auto_detect_platform.php @@ -21,7 +21,7 @@ declare(strict_types=1); require_once __DIR__ . '/../vendor/autoload.php'; require_once __DIR__ . '/../lib/Enterprise/CliFramework.php'; -use MokoEnterprise\{ +use MokoCli\{ CliFramework, ProjectTypeDetector, PluginFactory, diff --git a/validate/check_changelog.php b/validate/check_changelog.php index 6788d4a..dafde9c 100644 --- a/validate/check_changelog.php +++ b/validate/check_changelog.php @@ -19,7 +19,7 @@ declare(strict_types=1); require_once __DIR__ . '/../vendor/autoload.php'; -use MokoEnterprise\CliFramework; +use MokoCli\CliFramework; /** * Validates that CHANGELOG.md exists (in root, src/, or docs/) and follows Keep a Changelog format. diff --git a/validate/check_client_theme.php b/validate/check_client_theme.php index 7c7cb83..da31759 100644 --- a/validate/check_client_theme.php +++ b/validate/check_client_theme.php @@ -19,7 +19,7 @@ declare(strict_types=1); require_once __DIR__ . '/../vendor/autoload.php'; -use MokoEnterprise\{CliFramework, SourceResolver}; +use MokoCli\{CliFramework, SourceResolver}; /** * Validates client theme packages that deliver CSS, JS, and images diff --git a/validate/check_composer_deps.php b/validate/check_composer_deps.php index 8f0020c..c1904d0 100644 --- a/validate/check_composer_deps.php +++ b/validate/check_composer_deps.php @@ -42,9 +42,9 @@ if (!$repoName && !$allMode) { exit(2); } -$config = \MokoEnterprise\Config::load(); +$config = \MokoCli\Config::load(); try { - $_adapter = \MokoEnterprise\PlatformAdapterFactory::create($config); + $_adapter = \MokoCli\PlatformAdapterFactory::create($config); $_api = $_adapter->getApiClient(); } catch (\Exception $e) { fwrite(STDERR, "Platform init failed: " . $e->getMessage() . "\n"); diff --git a/validate/check_dolibarr_module.php b/validate/check_dolibarr_module.php index 2d5ba4b..caacf5e 100644 --- a/validate/check_dolibarr_module.php +++ b/validate/check_dolibarr_module.php @@ -19,7 +19,7 @@ declare(strict_types=1); require_once __DIR__ . '/../vendor/autoload.php'; -use MokoEnterprise\{CliFramework, SourceResolver}; +use MokoCli\{CliFramework, SourceResolver}; /** * Validates the required directory structure of a Dolibarr module repository. diff --git a/validate/check_enterprise_readiness.php b/validate/check_enterprise_readiness.php index 3b29577..4b9b950 100755 --- a/validate/check_enterprise_readiness.php +++ b/validate/check_enterprise_readiness.php @@ -20,7 +20,7 @@ declare(strict_types=1); require_once __DIR__ . '/../vendor/autoload.php'; -use MokoEnterprise\{ +use MokoCli\{ AuditLogger, CliFramework, SecurityValidator, @@ -55,7 +55,7 @@ class EnterpriseReadinessChecker extends CliFramework $this->logger = new AuditLogger('enterprise_readiness'); $this->securityValidator = new SecurityValidator(); - $metrics = new \MokoEnterprise\MetricsCollector(); + $metrics = new \MokoCli\MetricsCollector(); $this->pluginFactory = new PluginFactory($this->logger, $metrics); $this->log('Enterprise readiness checker initialized with plugin system'); diff --git a/validate/check_file_integrity.php b/validate/check_file_integrity.php index a4499b7..7bf54b0 100644 --- a/validate/check_file_integrity.php +++ b/validate/check_file_integrity.php @@ -12,7 +12,7 @@ * INGROUP: MokoPlatform * REPO: https://git.mokoconsulting.tech/MokoConsulting/mokoplatform * PATH: /validate/check_file_integrity.php - * VERSION: 09.29.01 + * VERSION: 09.29.02 * BRIEF: Compare deployed files on a remote server against the local repository to detect drift */ diff --git a/validate/check_joomla_manifest.php b/validate/check_joomla_manifest.php index 9a49fe4..f69936a 100644 --- a/validate/check_joomla_manifest.php +++ b/validate/check_joomla_manifest.php @@ -19,7 +19,7 @@ declare(strict_types=1); require_once __DIR__ . '/../vendor/autoload.php'; -use MokoEnterprise\CliFramework; +use MokoCli\CliFramework; /** * Validates that tracked XML files containing a Joomla element diff --git a/validate/check_language_structure.php b/validate/check_language_structure.php index 8dc715e..db98041 100644 --- a/validate/check_language_structure.php +++ b/validate/check_language_structure.php @@ -19,7 +19,7 @@ declare(strict_types=1); require_once __DIR__ . '/../vendor/autoload.php'; -use MokoEnterprise\CliFramework; +use MokoCli\CliFramework; /** * Validates that all tracked INI language files follow the KEY=value format. diff --git a/validate/check_license_headers.php b/validate/check_license_headers.php index a269892..10acdbc 100644 --- a/validate/check_license_headers.php +++ b/validate/check_license_headers.php @@ -19,7 +19,7 @@ declare(strict_types=1); require_once __DIR__ . '/../vendor/autoload.php'; -use MokoEnterprise\CliFramework; +use MokoCli\CliFramework; /** * Checks that tracked PHP, JS, CSS and Shell files contain an SPDX license identifier. diff --git a/validate/check_no_secrets.php b/validate/check_no_secrets.php index 4e6c666..b340fa1 100644 --- a/validate/check_no_secrets.php +++ b/validate/check_no_secrets.php @@ -19,7 +19,7 @@ declare(strict_types=1); require_once __DIR__ . '/../vendor/autoload.php'; -use MokoEnterprise\CliFramework; +use MokoCli\CliFramework; /** * Scans all tracked non-binary files for common secret patterns (advisory — always exits 0). diff --git a/validate/check_paths.php b/validate/check_paths.php index 4d9e737..edfb1da 100644 --- a/validate/check_paths.php +++ b/validate/check_paths.php @@ -19,7 +19,7 @@ declare(strict_types=1); require_once __DIR__ . '/../vendor/autoload.php'; -use MokoEnterprise\CliFramework; +use MokoCli\CliFramework; /** * Warns when backslash characters that look like Windows path separators appear diff --git a/validate/check_php_syntax.php b/validate/check_php_syntax.php index 72b673b..1416179 100644 --- a/validate/check_php_syntax.php +++ b/validate/check_php_syntax.php @@ -19,7 +19,7 @@ declare(strict_types=1); require_once __DIR__ . '/../vendor/autoload.php'; -use MokoEnterprise\CliFramework; +use MokoCli\CliFramework; /** * Runs `php -l` against all tracked *.php files and reports any syntax errors. diff --git a/validate/check_repo_health.php b/validate/check_repo_health.php index 73802be..f549068 100755 --- a/validate/check_repo_health.php +++ b/validate/check_repo_health.php @@ -31,7 +31,7 @@ declare(strict_types=1); require_once __DIR__ . '/../vendor/autoload.php'; -use MokoEnterprise\{AuditLogger, CliFramework, MetricsCollector, PluginFactory}; +use MokoCli\{AuditLogger, CliFramework, MetricsCollector, PluginFactory}; /** * Repository Health Checker @@ -67,7 +67,7 @@ class RepoHealthChecker extends CliFramework parent::initialize(); $this->logger = new AuditLogger('repo_health_checker'); $this->metrics = new MetricsCollector(); - $config = \MokoEnterprise\Config::load(); + $config = \MokoCli\Config::load(); $this->apiBaseUrl = rtrim($config->getString('gitea.url', 'https://git.mokoconsulting.tech'), '/') . '/api/v1'; } diff --git a/validate/check_structure.php b/validate/check_structure.php index 315a048..b802615 100644 --- a/validate/check_structure.php +++ b/validate/check_structure.php @@ -19,7 +19,7 @@ declare(strict_types=1); require_once __DIR__ . '/../vendor/autoload.php'; -use MokoEnterprise\CliFramework; +use MokoCli\CliFramework; /** * Validates that the required directories and files exist in the repository root. diff --git a/validate/check_tabs.php b/validate/check_tabs.php index 08a2d8d..87fbd54 100644 --- a/validate/check_tabs.php +++ b/validate/check_tabs.php @@ -19,7 +19,7 @@ declare(strict_types=1); require_once __DIR__ . '/../vendor/autoload.php'; -use MokoEnterprise\CliFramework; +use MokoCli\CliFramework; /** * Checks that none of the tracked PHP, JS, CSS, XML, YAML and Markdown files diff --git a/validate/check_version_consistency.php b/validate/check_version_consistency.php index 8380de8..510b1ec 100755 --- a/validate/check_version_consistency.php +++ b/validate/check_version_consistency.php @@ -20,7 +20,7 @@ declare(strict_types=1); require_once __DIR__ . '/../vendor/autoload.php'; -use MokoEnterprise\CliFramework; +use MokoCli\CliFramework; /** * Checks that the version recorded in composer.json matches VERSION headers @@ -79,7 +79,7 @@ class CheckVersionConsistency extends CliFramework $this->section('Checking critical files'); $criticalChecks = [ - 'README.md' => ['/VERSION:\s*(\d{2}\.\d{2}\.\d{2})/', '/MokoStandards-(\d{2}\.\d{2}\.\d{2})/'], + 'README.md' => ['/VERSION:\s*(\d{2}\.\d{2}\.\d{2})/', '/MokoCli-(\d{2}\.\d{2}\.\d{2})/'], 'CHANGELOG.md' => ['/VERSION:\s*(\d{2}\.\d{2}\.\d{2})/'], 'CONTRIBUTING.md' => ['/VERSION:\s*(\d{2}\.\d{2}\.\d{2})/'], ]; diff --git a/validate/check_wiki_health.php b/validate/check_wiki_health.php index 1a1a993..e86eff2 100644 --- a/validate/check_wiki_health.php +++ b/validate/check_wiki_health.php @@ -17,7 +17,7 @@ declare(strict_types=1); require_once __DIR__ . '/../vendor/autoload.php'; -use MokoEnterprise\CliFramework; +use MokoCli\CliFramework; /** * Wiki Health Checker diff --git a/validate/check_xml_wellformed.php b/validate/check_xml_wellformed.php index a323d03..317842d 100644 --- a/validate/check_xml_wellformed.php +++ b/validate/check_xml_wellformed.php @@ -19,7 +19,7 @@ declare(strict_types=1); require_once __DIR__ . '/../vendor/autoload.php'; -use MokoEnterprise\CliFramework; +use MokoCli\CliFramework; /** * Runs `xmllint --noout` against all tracked *.xml files and reports errors. diff --git a/validate/scan_drift.php b/validate/scan_drift.php index 0e0647a..e590a15 100755 --- a/validate/scan_drift.php +++ b/validate/scan_drift.php @@ -20,7 +20,7 @@ declare(strict_types=1); require_once __DIR__ . '/../vendor/autoload.php'; -use MokoEnterprise\{ +use MokoCli\{ ApiClient, AuditLogger, CliFramework, @@ -39,7 +39,7 @@ class DriftScanner extends CliFramework private ApiClient $apiClient; private MetricsCollector $metrics; - private \MokoEnterprise\GitPlatformAdapter $adapter; + private \MokoCli\GitPlatformAdapter $adapter; private array $driftResults = []; private array $templates = []; @@ -62,9 +62,9 @@ class DriftScanner extends CliFramework $this->metrics = new MetricsCollector(); // Initialize API client via platform adapter - $config = \MokoEnterprise\Config::load(); + $config = \MokoCli\Config::load(); try { - $this->adapter = \MokoEnterprise\PlatformAdapterFactory::create($config); + $this->adapter = \MokoCli\PlatformAdapterFactory::create($config); $this->apiClient = $this->adapter->getApiClient(); } catch (\Exception $e) { $this->error("Platform initialization failed: " . $e->getMessage());