diff --git a/.agents/_TOC.md b/.agents/_TOC.md index cb993b72..4be0656b 100644 --- a/.agents/_TOC.md +++ b/.agents/_TOC.md @@ -1,24 +1,23 @@ # Table of Contents 1. [Quick Reference Card](quick-reference-card.md) -2. [Project overview](project-overview.md) -3. [JVM project requirements](jvm-project.md) — language, build, and review checklist shared by all JVM repos -4. [Coding guidelines](coding-guidelines.md) -5. [Documentation & comments](documentation-guidelines.md) -6. [Documentation tasks](documentation-tasks.md) -7. [Running builds](running-builds.md) -8. [Version policy](version-policy.md) -9. [Project structure expectations](project-structure-expectations.md) -10. [Testing](testing.md) -11. [Safety rules](safety-rules.md) -12. [Advanced safety rules](advanced-safety-rules.md) -13. [Refactoring guidelines](refactoring-guidelines.md) -14. [Common tasks](common-tasks.md) -15. [Team memory](memory/MEMORY.md) -16. [Task plans](tasks/README.md) -17. [Java to Kotlin conversion](skills/java-to-kotlin/SKILL.md) -18. [Dependency update](skills/dependency-update/SKILL.md) -19. [Documentation review](skills/review-docs/SKILL.md) -20. [Pre-PR checklist](skills/pre-pr/SKILL.md) -21. [Kotlin code review](skills/kotlin-review/SKILL.md) -22. [Dependency audit](skills/dependency-audit/SKILL.md) +2. [JVM project requirements](jvm-project.md) — language, build, and review checklist shared by all JVM repos +3. [Coding guidelines](coding-guidelines.md) +4. [Documentation & comments](documentation-guidelines.md) +5. [Documentation tasks](documentation-tasks.md) +6. [Running builds](running-builds.md) +7. [Version policy](version-policy.md) +8. [Project structure expectations](project-structure-expectations.md) +9. [Testing](testing.md) +10. [Safety rules](safety-rules.md) +11. [Advanced safety rules](advanced-safety-rules.md) +12. [Refactoring guidelines](refactoring-guidelines.md) +13. [Common tasks](common-tasks.md) +14. [Team memory](memory/MEMORY.md) +15. [Task plans](tasks/README.md) +16. [Java to Kotlin conversion](skills/java-to-kotlin/SKILL.md) +17. [Dependency update](skills/dependency-update/SKILL.md) +18. [Documentation review](skills/review-docs/SKILL.md) +19. [Pre-PR checklist](skills/pre-pr/SKILL.md) +20. [Kotlin code review](skills/kotlin-review/SKILL.md) +21. [Dependency audit](skills/dependency-audit/SKILL.md) diff --git a/.agents/project-overview.md b/.agents/project-overview.md deleted file mode 100644 index dfac73f0..00000000 --- a/.agents/project-overview.md +++ /dev/null @@ -1,7 +0,0 @@ -# 🛠️ Project overview - -- **Languages**: Kotlin (primary), Java (secondary). -- **Build tool**: Gradle with Kotlin DSL. -- **Static analysis**: detekt, ErrorProne, Checkstyle, PMD. -- **Testing**: JUnit 5, Kotest Assertions, Codecov. -- **Tools used**: Gradle plugins, IntelliJ IDEA Platform, KSP, KotlinPoet, Dokka. diff --git a/.agents/scripts/pre-pr-gate.sh b/.agents/scripts/pre-pr-gate.sh index cb80b312..88de51c2 100755 --- a/.agents/scripts/pre-pr-gate.sh +++ b/.agents/scripts/pre-pr-gate.sh @@ -9,6 +9,8 @@ # set -eu +command -v jq >/dev/null 2>&1 || exit 0 + input=$(cat) tool=$(printf '%s' "$input" | jq -r '.tool_name // empty') [ "$tool" != "Bash" ] && exit 0 diff --git a/.agents/scripts/protect-version-file.sh b/.agents/scripts/protect-version-file.sh index cd0fbdd6..2184468c 100755 --- a/.agents/scripts/protect-version-file.sh +++ b/.agents/scripts/protect-version-file.sh @@ -12,6 +12,8 @@ # set -eu +command -v jq >/dev/null 2>&1 || exit 0 + input=$(cat) file=$(printf '%s' "$input" | jq -r '.tool_input.file_path // empty') command=$(printf '%s' "$input" | jq -r '.tool_input.command // empty') diff --git a/.agents/scripts/publish-version-gate.sh b/.agents/scripts/publish-version-gate.sh index 466f0a80..996bd256 100755 --- a/.agents/scripts/publish-version-gate.sh +++ b/.agents/scripts/publish-version-gate.sh @@ -17,6 +17,8 @@ # set -eu +command -v jq >/dev/null 2>&1 || exit 0 + input=$(cat) tool=$(printf '%s' "$input" | jq -r '.tool_name // empty') [ "$tool" != "Bash" ] && exit 0 diff --git a/.agents/scripts/sanitize-source-code.sh b/.agents/scripts/sanitize-source-code.sh index 821bf897..f74c867a 100755 --- a/.agents/scripts/sanitize-source-code.sh +++ b/.agents/scripts/sanitize-source-code.sh @@ -11,6 +11,8 @@ # set -eu +command -v jq >/dev/null 2>&1 || exit 0 + input=$(cat) file=$(printf '%s' "$input" | jq -r '.tool_input.file_path // empty') command=$(printf '%s' "$input" | jq -r '.tool_input.command // empty') diff --git a/.agents/skills/check-links/SKILL.md b/.agents/skills/check-links/SKILL.md index 5571e13f..a4c61a0c 100644 --- a/.agents/skills/check-links/SKILL.md +++ b/.agents/skills/check-links/SKILL.md @@ -78,15 +78,17 @@ version matches what the CI workflow uses, so behavior is identical. Execute the steps in order. On the first failure, stop, write a `FAIL` sentinel (step 8), and report the failure with the next action. -### 0. Detect site root +### 0. Detect site root and work directory -Before any other step, determine `SITE_DIR` — the directory that contains the -Hugo config file: +Before any other step, determine `SITE_DIR` (the Hugo site root) and `WORK_DIR` +(the directory where `npm ci` / `hugo` commands run — mirrors `.github/workflows/check-links.yml`): ```bash SITE_DIR="" for dir in docs site; do - for cfg in hugo.toml hugo.yaml; do + for cfg in hugo.toml hugo.yaml \ + config/hugo.toml config/hugo.yaml \ + config/_default/hugo.toml config/_default/hugo.yaml; do if [ -f "$dir/$cfg" ]; then SITE_DIR="$dir" break 2 @@ -97,9 +99,18 @@ if [ -z "$SITE_DIR" ]; then echo "ERROR: No Hugo config found under docs/ or site/." >&2 exit 1 fi + +if [ -f "${SITE_DIR}/_preview/package-lock.json" ]; then + WORK_DIR="${SITE_DIR}/_preview" +elif [ -f "${SITE_DIR}/package-lock.json" ]; then + WORK_DIR="${SITE_DIR}" +else + echo "ERROR: No package-lock.json found under ${SITE_DIR}/_preview/ or ${SITE_DIR}/." >&2 + exit 1 +fi ``` -Use `$SITE_DIR` everywhere a directory path is needed in the steps below. +Use `$SITE_DIR` for content paths and `$WORK_DIR` for build/serve operations in the steps below. ### 1. Scope check @@ -160,7 +171,7 @@ explicitly ask, decline and exit cleanly. ### 3. Install Hugo deps -Run `( cd ${SITE_DIR}/_preview && npm ci )`. We deliberately use `npm ci` +Run `( cd ${WORK_DIR} && npm ci )`. We deliberately use `npm ci` (matching the CI workflow's `Install Dependencies` step in `check-links.yml`) rather than `npm install`: @@ -172,18 +183,13 @@ rather than `npm install`: fails fast with a clear error rather than silently healing the lockfile — a divergence we want to surface, not paper over. -The helper script `${SITE_DIR}/_script/install-dependencies` exists for -interactive use but does a relative `cd _preview` and therefore only works -when invoked from `${SITE_DIR}/` — calling it from the repo root (the skill's -default CWD) would fail with "No such file or directory: _preview". - ### 4. Build the site -Run `( cd ${SITE_DIR}/_preview && hugo -e development )`. -This emits `${SITE_DIR}/_preview/public/**/*.html`. The `-e development` flag -matches what CI uses in `check-links.yml` so the two builds render identical -HTML. (The helper `${SITE_DIR}/_script/hugo-build` exists for interactive use -but defaults to `production`; we invoke `hugo` directly to keep the env in +Run `( cd ${WORK_DIR} && hugo -e development )`. +This emits `${WORK_DIR}/public/**/*.html`. The `-e development` flag matches +what CI uses in `check-links.yml` so the two builds render identical HTML. +(The helper `${SITE_DIR}/_script/hugo-build` exists for interactive use but +defaults to `production`; we invoke `hugo` directly to keep the env in lock-step with CI.) ### 5. Start the Hugo server in the background @@ -200,7 +206,7 @@ stale process does not hold port `1414`: pkill -F /tmp/check-links.hugo.pid 2>/dev/null || true rm -f /tmp/check-links.hugo.pid -( cd ${SITE_DIR}/_preview && nohup hugo server --environment development --port 1414 \ +( cd ${WORK_DIR} && nohup hugo server --environment development --port 1414 \ > /tmp/check-links.hugo.out 2>&1 & echo $! > /tmp/check-links.hugo.pid ) sleep 5 @@ -223,7 +229,7 @@ Port `1414` is chosen to avoid clashing with a developer's local `hugo server` ```bash --config lychee.toml --timeout 60 \ --base-url http://localhost:1414/ \ - "${SITE_DIR}/_preview/public/**/*.html" + "${WORK_DIR}/public/**/*.html" ``` Capture exit code. Any non-zero exit means at least one broken link. @@ -233,7 +239,7 @@ Capture exit code. Any non-zero exit means at least one broken link. Group the broken URLs from Lychee's output by source page. To reverse-map an HTML path to its Markdown source: -`${SITE_DIR}/_preview/public/docs/
//index.html` +`${WORK_DIR}/public/docs/
//index.html` ↔ `${SITE_DIR}/content/docs/
/.md` (or `/_index.md`). Report in this shape: @@ -293,10 +299,9 @@ HEAD advance (commit, amend, rebase) invalidates the cache automatically. reader does not mistake them for unrelated side-effects: - `.agents/skills/check-links/.cache/lychee/` — auto-downloaded Lychee binary, when the system Lychee was unavailable. - - `${SITE_DIR}/_preview/node_modules/` — installed by `npm ci` in step 3. - - `${SITE_DIR}/_preview/public/` — Hugo's rendered HTML (the corpus Lychee - scans). - - `${SITE_DIR}/_preview/resources/` — Hugo's asset-pipeline cache. + - `${WORK_DIR}/node_modules/` — installed by `npm ci` in step 3. + - `${WORK_DIR}/public/` — Hugo's rendered HTML (the corpus Lychee scans). + - `${WORK_DIR}/resources/` — Hugo's asset-pipeline cache. - `.lycheecache` at the repo root — Lychee's per-URL result cache (honoured for `max_cache_age = "3d"` per `lychee.toml`). - `/tmp/check-links.hugo.{pid,out}` — server PID file and log, both diff --git a/.agents/skills/pre-pr/SKILL.md b/.agents/skills/pre-pr/SKILL.md index 2c81dfde..e656b0b4 100644 --- a/.agents/skills/pre-pr/SKILL.md +++ b/.agents/skills/pre-pr/SKILL.md @@ -2,9 +2,11 @@ name: pre-pr description: > Run the pre-PR checklist for this repo: apply the version gate only when - the repository has a root `version.gradle.kts`, run the configured - build/check command per `.agents/running-builds.md`, and invoke the - configured reviewers (`kotlin-review`, `review-docs`, `dependency-audit`, + the repository has a root `version.gradle.kts`, run a scope-dependent + build/check command per `.agents/running-builds.md` (docs-only → `dokka`; + code/deps → `build`; proto → `clean build`; no documented command → skipped), + and invoke the relevant reviewers (`kotlin-review`, `review-docs`, + `dependency-audit`, `check-links`) against the branch diff. On success, write a sentinel file at `.git/pre-pr.ok` so the `gh pr create` hook can verify the checklist ran for the current HEAD. Use before opening a PR, or when CI rejected a diff --git a/.github/workflows/check-links.yml b/.github/workflows/check-links.yml index 7a51f8f1..3fa235be 100644 --- a/.github/workflows/check-links.yml +++ b/.github/workflows/check-links.yml @@ -36,7 +36,12 @@ jobs: uses: actions/checkout@v4 # Detect the Hugo site root (`docs/` or `site/`) by looking for a Hugo - # config file. Outputs `present=true|false` and `site_dir=docs|site`. + # config file. Hugo config may live directly in the site root or in a + # `config/` or `config/_default/` subdirectory (both layouts are valid). + # Outputs `present=true|false` and `work_dir` (the directory where + # `npm ci` / `hugo` commands should run — either `$dir/_preview` for + # repos that use a separate preview sub-tree, or `$dir` for repos whose + # Node/Hugo setup lives at the site root). # When neither directory has a Hugo config, the job short-circuits to a # success so that this shared workflow stays green on repos that do not # host a Hugo site at all. @@ -44,15 +49,21 @@ jobs: id: docs run: | for dir in docs site; do - for cfg in hugo.toml hugo.yaml; do + for cfg in hugo.toml hugo.yaml \ + config/hugo.toml config/hugo.yaml \ + config/_default/hugo.toml config/_default/hugo.yaml; do if [ -f "$dir/$cfg" ]; then - echo "site_dir=$dir" >> "$GITHUB_OUTPUT" if [ -f "$dir/_preview/package-lock.json" ]; then + echo "work_dir=$dir/_preview" >> "$GITHUB_OUTPUT" echo "present=true" >> "$GITHUB_OUTPUT" - echo "::notice::Hugo site found under $dir/" + echo "::notice::Hugo site found under $dir/ (work_dir: $dir/_preview)" + elif [ -f "$dir/package-lock.json" ]; then + echo "work_dir=$dir" >> "$GITHUB_OUTPUT" + echo "present=true" >> "$GITHUB_OUTPUT" + echo "::notice::Hugo site found under $dir/ (work_dir: $dir)" else echo "present=false" >> "$GITHUB_OUTPUT" - echo "::notice::Hugo config found in $dir/ but $dir/_preview/package-lock.json is missing — skipping link check." + echo "::notice::Hugo config found in $dir/ but no package-lock.json found — skipping link check." fi exit 0 fi @@ -78,7 +89,7 @@ jobs: with: node-version: '26' cache: 'npm' - cache-dependency-path: ${{ steps.docs.outputs.site_dir }}/_preview/package-lock.json + cache-dependency-path: ${{ steps.docs.outputs.work_dir }}/package-lock.json # `HUGO_CACHEDIR=/tmp/hugo_cache` (set in `env:` above) makes Hugo # actually write to the path this step restores from. The key hashes @@ -95,12 +106,12 @@ jobs: - name: Install Dependencies if: steps.docs.outputs.present == 'true' - working-directory: ${{ steps.docs.outputs.site_dir }}/_preview + working-directory: ${{ steps.docs.outputs.work_dir }} run: npm ci - name: Build docs preview site if: steps.docs.outputs.present == 'true' - working-directory: ${{ steps.docs.outputs.site_dir }}/_preview + working-directory: ${{ steps.docs.outputs.work_dir }} run: hugo -e development # Cache Lychee results to avoid hitting rate limits. @@ -183,7 +194,7 @@ jobs: # Lychee step is visible — change one, change the other. - name: Start Hugo server if: steps.docs.outputs.present == 'true' - working-directory: ${{ steps.docs.outputs.site_dir }}/_preview + working-directory: ${{ steps.docs.outputs.work_dir }} run: | nohup hugo server \ --environment development \ @@ -202,4 +213,4 @@ jobs: run: | ./lychee/lychee --config lychee.toml --timeout 60 \ --base-url http://localhost:1313/ \ - '${{ steps.docs.outputs.site_dir }}/_preview/public/**/*.html' + '${{ steps.docs.outputs.work_dir }}/public/**/*.html' diff --git a/.idea/live-templates/README.md b/.idea/live-templates/README.md index 66713b34..95006673 100644 --- a/.idea/live-templates/README.md +++ b/.idea/live-templates/README.md @@ -5,12 +5,12 @@ This directory contains two live template groups: 1. `Spine.xml`: shortcuts for the repeated patterns used in the framework. 2. `User.xml`: a single shortcut to generate TODO comments. -### Instlallation +### Installation Live templates are not picked up by IDEA automatically. They should be added manually. In order to add these templates, perform the following steps: -1. Copy `*.xml` files from this directory to `templates` directory in the IntelliJ IDEA +1. Copy `*.xml` files from this directory to `templates` directory in the IntelliJ IDEA [settings folder][settings_folder]. 2. Restart IntelliJ IDEA: `File -> Invalidate Caches -> Just restart`. 3. Go to `Preferences -> Editor -> Live Templates`. @@ -23,5 +23,5 @@ In order to add these templates, perform the following steps: 1. Open the corresponding template: `Preferences -> Editor -> Live Templates -> User.todo`. 2. Click on `Edit variables`. 3. Set `USER` variable to your domain email address without `@teamdev.com` ending. For example, - for `jack.sparrow@teamdev.com` use the follwoing expression `"jack.sparrow"`. + for `jack.sparrow@teamdev.com` use the following expression `"jack.sparrow"`. 4. Verify that the template generates expected comments: `// TODO:2022-11-03:jack.sparrow: <...>`. diff --git a/.idea/live-templates/User.xml b/.idea/live-templates/User.xml index cc156507..958e2ea9 100644 --- a/.idea/live-templates/User.xml +++ b/.idea/live-templates/User.xml @@ -1,7 +1,7 @@