feat: configure repository clone cache for #138#343
Conversation
📝 WalkthroughSummary by CodeRabbit
WalkthroughPR добавляет clone-cache: bare-mirror кэш под git-mirrors, переключает источник клонирования на mirror при его наличии, и изменяет шаблоны так, чтобы при тёплом кэше выполнять git pull --ff-only (иначе — git clone); дизайн, proposal, задачи, unit и e2e тесты обновлены. ChangesClone Cache Architecture and Implementation
Sequence Diagram(s)Диаграммы не сгенерированы. Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 6 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (6 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
scripts/e2e/clone-cache.sh (1)
204-223:⚠️ Potential issue | 🟠 Major | ⚡ Quick winДобавьте e2e-проверку, что кэш-артефакты не попадают в state-repo.
Сейчас сценарий подтверждает только reuse кэша, но не валидирует требование “cache artifacts remain ignored/untracked by state repo sync”. Это оставляет незакрытым acceptance criterion ABC-5.
As per coding guidelines, ".kanban/changes/ABC-5/tasks.md: extend
scripts/e2e/clone-cache.shto verify cache reuse across two clones and that cache artifacts are not tracked by the state repository."🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@scripts/e2e/clone-cache.sh` around lines 204 - 223, Add an e2e assertion after run_clone_case "second" "1" "$MIRROR_NAME" that locates the state repo used by the second clone (derive path from the clone workspace or variables used by run_clone_case), then assert that no cache artifact paths (e.g. entries matching "$MIRROR_PREFIX", "$MIRROR_NAME" or the cache directory pattern used by the clone logic) are present in the state repo's tracked files or git index; implement this by running git -C "$STATE_REPO" ls-files (or git -C "$STATE_REPO" status --porcelain) and failing with fail "cache artifacts found in state repo: $STATE_REPO" if any matching lines appear, using the existing FAIL/ fail helper so the test will fail when cache artifacts are tracked while keeping the existing MIRROR_NAME/FIRST_LOG checks intact and leaving the success echo for $REPO_URL.packages/lib/src/core/templates-entrypoint/tasks.ts (1)
151-157:⚠️ Potential issue | 🟠 Major | ⚡ Quick winCache не должен считаться "used", если refresh завершился ошибкой.
В текущем блоке после ошибки refresh (Line 151) всё равно активируются
CLONE_SOURCE_REPO="$CACHE_REPO_DIR"иCLONE_USED_CACHE=1(Lines 155-156). Это делает "warm-cache" недетерминированно устаревшим и расходится с AC о refresh-before-use.💡 Предлагаемое исправление
- if ! su - ${config.sshUser} -c "GIT_TERMINAL_PROMPT=0 git --git-dir '$CACHE_REPO_DIR' fetch --progress --prune '$AUTH_REPO_URL' ${cloneCacheRefreshRefspecs}"; then - echo "[clone-cache] mirror refresh failed for $REPO_URL" - fi - CLONE_CACHE_ARGS="--reference-if-able '$CACHE_REPO_DIR' --dissociate" - CLONE_SOURCE_REPO="$CACHE_REPO_DIR" - CLONE_USED_CACHE=1 - echo "[clone-cache] using mirror: $CACHE_REPO_DIR" + if ! su - ${config.sshUser} -c "GIT_TERMINAL_PROMPT=0 git --git-dir '$CACHE_REPO_DIR' fetch --progress --prune '$AUTH_REPO_URL' ${cloneCacheRefreshRefspecs}"; then + echo "[clone-cache] mirror refresh failed for $REPO_URL; fallback to auth clone source" + else + CLONE_CACHE_ARGS="--reference-if-able '$CACHE_REPO_DIR' --dissociate" + CLONE_SOURCE_REPO="$CACHE_REPO_DIR" + CLONE_USED_CACHE=1 + echo "[clone-cache] using mirror: $CACHE_REPO_DIR" + fi🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/lib/src/core/templates-entrypoint/tasks.ts` around lines 151 - 157, После неудачного выполнения команды `su - ${config.sshUser} -c "GIT_TERMINAL_PROMPT=0 git --git-dir '$CACHE_REPO_DIR' fetch ..."` текущее поведение всё равно присваивает CLONE_SOURCE_REPO="$CACHE_REPO_DIR" и CLONE_USED_CACHE=1; нужно изменить логику так, чтобы присвоения CLONE_CACHE_ARGS, CLONE_SOURCE_REPO и CLONE_USED_CACHE происходили только когда команда fetch прошла успешно (например, переместить эти присвоения в ветку else или проверить статус выполнения fetch и выставлять CLONE_USED_CACHE=1 только при успешном результате), оставляя при ошибке поведение без использования кэша.packages/app/src/lib/core/templates-entrypoint/tasks.ts (1)
151-157:⚠️ Potential issue | 🟠 Major | ⚡ Quick winНе переключайте clone source на cache после неуспешного refresh.
Сейчас при падении refresh (Line 151) всё равно устанавливаются
CLONE_SOURCE_REPO="$CACHE_REPO_DIR"иCLONE_USED_CACHE=1(Lines 155-156). Это нарушает контракт "cache is refreshed before it is used for a workspace" и может дать устаревший workspace.💡 Предлагаемое исправление
- if ! su - ${config.sshUser} -c "GIT_TERMINAL_PROMPT=0 git --git-dir '$CACHE_REPO_DIR' fetch --progress --prune '$AUTH_REPO_URL' ${cloneCacheRefreshRefspecs}"; then - echo "[clone-cache] mirror refresh failed for $REPO_URL" - fi - CLONE_CACHE_ARGS="--reference-if-able '$CACHE_REPO_DIR' --dissociate" - CLONE_SOURCE_REPO="$CACHE_REPO_DIR" - CLONE_USED_CACHE=1 - echo "[clone-cache] using mirror: $CACHE_REPO_DIR" + if ! su - ${config.sshUser} -c "GIT_TERMINAL_PROMPT=0 git --git-dir '$CACHE_REPO_DIR' fetch --progress --prune '$AUTH_REPO_URL' ${cloneCacheRefreshRefspecs}"; then + echo "[clone-cache] mirror refresh failed for $REPO_URL; fallback to auth clone source" + else + CLONE_CACHE_ARGS="--reference-if-able '$CACHE_REPO_DIR' --dissociate" + CLONE_SOURCE_REPO="$CACHE_REPO_DIR" + CLONE_USED_CACHE=1 + echo "[clone-cache] using mirror: $CACHE_REPO_DIR" + fi🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/app/src/lib/core/templates-entrypoint/tasks.ts` around lines 151 - 157, В блоке, где выполняется fetch к зеркалу (the if invoking su - ${config.sshUser} ... git fetch), не переключайте источник клонирования на $CACHE_REPO_DIR при неудаче: переменные CLONE_CACHE_ARGS, CLONE_SOURCE_REPO и CLONE_USED_CACHE должны быть установлены только если команда fetch прошла успешно; если fetch не успешен — ничего не менять и не печатать сообщение о «using mirror». Переместите присвоения CLONE_CACHE_ARGS="--reference-if-able '$CACHE_REPO_DIR' --dissociate", CLONE_SOURCE_REPO="$CACHE_REPO_DIR", CLONE_USED_CACHE=1 и echo "[clone-cache] using mirror: $CACHE_REPO_DIR" внутрь ветки успешного выполнения команды (the then branch of the if that checks the fetch) so зеркало используется только после успешного refresh.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.kanban/changes/ABC-5/tasks.md:
- Around line 26-27: The E2E acceptance test for the key scenario `bun run
e2e:clone-cache` was not executed because the controller was unreachable; run
that E2E in an environment where the controller is available (e.g., start the
controller via `docker compose up -d --build` or set
`DOCKER_GIT_API_URL`/`DOCKER_HOST` to point at a reachable controller), verify
the reuse-of-cache behavior and that no cache artifacts are tracked in the state
repo, capture and attach the test logs/output, then mark the checklist item as
completed and update the task notes to include the environment used and any
fixes if the test fails.
---
Outside diff comments:
In `@packages/app/src/lib/core/templates-entrypoint/tasks.ts`:
- Around line 151-157: В блоке, где выполняется fetch к зеркалу (the if invoking
su - ${config.sshUser} ... git fetch), не переключайте источник клонирования на
$CACHE_REPO_DIR при неудаче: переменные CLONE_CACHE_ARGS, CLONE_SOURCE_REPO и
CLONE_USED_CACHE должны быть установлены только если команда fetch прошла
успешно; если fetch не успешен — ничего не менять и не печатать сообщение о
«using mirror». Переместите присвоения CLONE_CACHE_ARGS="--reference-if-able
'$CACHE_REPO_DIR' --dissociate", CLONE_SOURCE_REPO="$CACHE_REPO_DIR",
CLONE_USED_CACHE=1 и echo "[clone-cache] using mirror: $CACHE_REPO_DIR" внутрь
ветки успешного выполнения команды (the then branch of the if that checks the
fetch) so зеркало используется только после успешного refresh.
In `@packages/lib/src/core/templates-entrypoint/tasks.ts`:
- Around line 151-157: После неудачного выполнения команды `su -
${config.sshUser} -c "GIT_TERMINAL_PROMPT=0 git --git-dir '$CACHE_REPO_DIR'
fetch ..."` текущее поведение всё равно присваивает
CLONE_SOURCE_REPO="$CACHE_REPO_DIR" и CLONE_USED_CACHE=1; нужно изменить логику
так, чтобы присвоения CLONE_CACHE_ARGS, CLONE_SOURCE_REPO и CLONE_USED_CACHE
происходили только когда команда fetch прошла успешно (например, переместить эти
присвоения в ветку else или проверить статус выполнения fetch и выставлять
CLONE_USED_CACHE=1 только при успешном результате), оставляя при ошибке
поведение без использования кэша.
In `@scripts/e2e/clone-cache.sh`:
- Around line 204-223: Add an e2e assertion after run_clone_case "second" "1"
"$MIRROR_NAME" that locates the state repo used by the second clone (derive path
from the clone workspace or variables used by run_clone_case), then assert that
no cache artifact paths (e.g. entries matching "$MIRROR_PREFIX", "$MIRROR_NAME"
or the cache directory pattern used by the clone logic) are present in the state
repo's tracked files or git index; implement this by running git -C
"$STATE_REPO" ls-files (or git -C "$STATE_REPO" status --porcelain) and failing
with fail "cache artifacts found in state repo: $STATE_REPO" if any matching
lines appear, using the existing FAIL/ fail helper so the test will fail when
cache artifacts are tracked while keeping the existing MIRROR_NAME/FIRST_LOG
checks intact and leaving the success echo for $REPO_URL.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: db5ddbef-9a55-4787-9a64-672389bff743
📒 Files selected for processing (7)
.kanban/changes/ABC-5/design.md.kanban/changes/ABC-5/proposal.md.kanban/changes/ABC-5/tasks.mdpackages/app/src/lib/core/templates-entrypoint/tasks.tspackages/lib/src/core/templates-entrypoint/tasks.tspackages/lib/tests/core/templates.test.tsscripts/e2e/clone-cache.sh
📜 Review details
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
- GitHub Check: E2E (OpenCode)
- GitHub Check: E2E (Runtime volumes + SSH)
- GitHub Check: Lint
- GitHub Check: E2E (Clone auto-open SSH)
- GitHub Check: E2E (Clone cache)
- GitHub Check: E2E (Browser command)
- GitHub Check: E2E (Local package CLI)
- GitHub Check: E2E (Login context)
- GitHub Check: Test
- GitHub Check: Final build (windows-latest)
- GitHub Check: Final build (macos-latest)
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{sh,bash,py,js,ts,jsx,tsx,go,java,rb,php}
📄 CodeRabbit inference engine (Custom checks)
Fail if changed files introduce command injection or unsafe shell/process execution with user-controlled input
Files:
scripts/e2e/clone-cache.shpackages/lib/tests/core/templates.test.tspackages/lib/src/core/templates-entrypoint/tasks.tspackages/app/src/lib/core/templates-entrypoint/tasks.ts
**/*.{py,js,ts,jsx,tsx,go,java,rb,php,sh,bash,c,cpp}
📄 CodeRabbit inference engine (Custom checks)
Fail if changed files introduce path traversal or writes outside intended project/container state directories
Files:
scripts/e2e/clone-cache.shpackages/lib/tests/core/templates.test.tspackages/lib/src/core/templates-entrypoint/tasks.tspackages/app/src/lib/core/templates-entrypoint/tasks.ts
**/*.{js,ts,jsx,tsx,py,java,go,rb,php,sh,bash,yml,yaml,json,env*,toml,cfg,config,dockerfile,dockerignore}
📄 CodeRabbit inference engine (Custom checks)
Fail if changed files expose credentials, tokens, private-keys, or PII in source, generated config, logs, or CI output
Files:
scripts/e2e/clone-cache.shpackages/lib/tests/core/templates.test.tspackages/lib/src/core/templates-entrypoint/tasks.tspackages/app/src/lib/core/templates-entrypoint/tasks.ts
**/*
⚙️ CodeRabbit configuration file
**/*: Ты строгий ревьюер SPEC DRIVEN DEVELOPMENT.Перед выводами изучи README.md, другие *.md файлы, linked issues,
PR description, PR comments/discussion и релевантную кодовую базу.Сверь изменения с исходным ТЗ/спекой и обсуждением. Флагай любой уход
от спеки, недокументированное изменение поведения, отсутствие тестов
для заявленного поведения и security-риск. Если спека не видна,
попроси автора добавить ее в issue или PR description.Проверь решение с точки зрения формальной верификации: какие инварианты,
предусловия и постусловия можно доказать математически, а где доказуемость
слабая. Оцени решение с точки зрения теории игр: устойчивы ли стимулы,
нет ли выгодного обхода правил, и какое решение было бы сильнее.
Files:
scripts/e2e/clone-cache.shpackages/lib/tests/core/templates.test.tspackages/lib/src/core/templates-entrypoint/tasks.tspackages/app/src/lib/core/templates-entrypoint/tasks.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Implement Functional Core, Imperative Shell (FCIS) pattern: CORE layer contains only pure functions with immutable data and mathematical operations; SHELL layer isolates all effects (IO, network, database). Strict dependency direction: SHELL → CORE (never reverse).
Never useany,unknown,eslint-disable,ts-ignore, orastype assertions (except in rigorously justified cases with documentation). Always use exhaustive union type analysis through.exhaustive()pattern matching.
All external dependencies must be wrapped through typed interfaces and injected via Effect-TS Layer pattern. Never call external services directly from CORE functions.
Use monadic composition with Effect-TS for all effects:Effect<Success, Error, Requirements>. Compose effects throughpipe()andEffect.flatMap(). Implement dependency injection via Layer pattern. Handle errors without try/catch blocks.
All functions must be pure in the CORE layer: no side effects (logging, console output, IO operations, mutations). Separate all side effects into the SHELL layer.
Use exhaustive pattern matching with Effect.Match instead of switch statements. Example:Match.value(item).pipe(Match.when(...), Match.exhaustive).
Document all functions with comprehensive TSDoc including:@pure(true/false),@effect(required services),@invariant(mathematical invariants),@precondition,@postcondition,@complexity(time and space),@throwsNever (errors must be typed in Effect).
Use functional comment markers for code clarity: CHANGE (brief description), WHY (mathematical/architectural justification), QUOTE(ТЗ) (requirement citation), REF (RTM or message ID), SOURCE (external source with quote), FORMAT THEOREM (∀x ∈ Domain: P(x) → Q(f(x))), PURITY (CORE|SHELL), EFFECT (Effect type signature), INVARIANT (mathematical invariant), COMPLEXITY (time/space).
Define all external service dependencies as Context.Tag classes with fully typed methods returning Effect types. Example: `class Da...
Files:
packages/lib/tests/core/templates.test.tspackages/lib/src/core/templates-entrypoint/tasks.tspackages/app/src/lib/core/templates-entrypoint/tasks.ts
**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.test.{ts,tsx}: Implement property-based testing using fast-check for mathematical properties and invariants. Example:fc.property(fc.array(messageArbitrary), (messages) => isChronologicallySorted(sortMessagesByTimestamp(messages))).
Mock external dependencies in unit tests using Effect's testing utilities. Run tests without Effect runtime for speed. Example:Effect.provide(MockService), Effect.runPromise.
Files:
packages/lib/tests/core/templates.test.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,js,jsx}: Forbidden constructs in CORE code:any,eslint-disable,ts-ignore,async/await, raw Promise chains (then/catch),Promise.all,try/catchfor logic control,console.*, switch statements (use Match with .exhaustive() instead)
All functions must use Effect-TS for composing effects:Effect<Success, Error, Requirements>. No direct async/await, Promise chains, or try/catch in product logic.
Functional comments must include: CHANGE, WHY, QUOTE(ТЗ) or n/a, REF, SOURCE or n/a, FORMAT THEOREM, PURITY (CORE|SHELL), EFFECT signature for SHELL functions, INVARIANT, and COMPLEXITY.
All data mutations must use immutable patterns (ReadonlyArray, readonly properties, Object.freeze); mutation in SHELL only when absolutely necessary and documented.
Files:
packages/lib/tests/core/templates.test.tspackages/lib/src/core/templates-entrypoint/tasks.tspackages/app/src/lib/core/templates-entrypoint/tasks.ts
**/*.{test,spec}.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Property-based tests (fast-check) must verify mathematical invariants; unit tests must use Effect test utilities without async/await.
Files:
packages/lib/tests/core/templates.test.ts
packages/app/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (README.md)
App layer (APP) should work only with API and not have direct access to LIB layer
Files:
packages/app/src/lib/core/templates-entrypoint/tasks.ts
🪛 LanguageTool
.kanban/changes/ABC-5/proposal.md
[style] ~19-~19: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...eckout logic in the target workspace. - Existing behavior refreshes the bare mirror with...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~33-~33: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...ics. - Do not merge work into main. - Do not cache secrets or auth material in r...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~34-~34: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...h material in repository cache paths. - Do not commit cache artifacts into the `.d...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~35-~35: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...o the .docker-git state repository. - Do not broaden mirror refresh to hosted fo...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
🔇 Additional comments (1)
packages/lib/tests/core/templates.test.ts (1)
309-351: LGTM!
0195026 to
67ed16e
Compare
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/lib/tests/core/templates.test.ts (1)
309-368: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick winНе хватает регрессий на cache-miss/tag/default-branch инварианты.
Новые кейсы покрывают только позитивные сценарии ветки/PR/issue. Они не доказывают три инварианта ABC-5: stale mirror не должен терять запрошенный ref, tag ref не должен уходить в
pullпо detached HEAD, а emptyREPO_REFдолжен следовать remote default branch, а неHEADmirror. Добавьте отдельные шаблонные тесты на эти случаи, иначе такой регресс пройдёт зелёным.As per coding guidelines, "Сверь изменения с исходным ТЗ/спекой и обсуждением. Флагай любой уход от спеки, недокументированное изменение поведения, отсутствие тестов для заявленного поведения и security-риск."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/lib/tests/core/templates.test.ts` around lines 309 - 368, The tests only cover positive branch/PR/issue paths and miss three invariants: on cache-miss a stale mirror must not drop the requested REPO_REF, tag refs must remain checked out as tags and not be converted into a detached-HEAD pull, and an empty REPO_REF should cause pulling the remote default branch (not mirror HEAD). Add focused unit tests using the existing helpers (renderEntrypoint, makeTemplateConfig, generatedTemplateConfigArbitrary) and assertion helpers (expectContainsAll/expect/expect(...).toContain) that: 1) simulate a cache-miss path and assert the entrypoint still references the requested '$REPO_REF' rather than only mirror HEAD, 2) create a tag ref input and assert the generated clone/pull lines preserve tag ref semantics (no detached HEAD pull/checkout fallback), and 3) render with REPO_REF empty and assert the pull uses a plain 'git pull --ff-only' against origin default branch (and echoes "[clone-cache] pulled default branch"); place these tests alongside the existing cases and mirror their style.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@packages/lib/tests/core/templates.test.ts`:
- Around line 309-368: The tests only cover positive branch/PR/issue paths and
miss three invariants: on cache-miss a stale mirror must not drop the requested
REPO_REF, tag refs must remain checked out as tags and not be converted into a
detached-HEAD pull, and an empty REPO_REF should cause pulling the remote
default branch (not mirror HEAD). Add focused unit tests using the existing
helpers (renderEntrypoint, makeTemplateConfig, generatedTemplateConfigArbitrary)
and assertion helpers (expectContainsAll/expect/expect(...).toContain) that: 1)
simulate a cache-miss path and assert the entrypoint still references the
requested '$REPO_REF' rather than only mirror HEAD, 2) create a tag ref input
and assert the generated clone/pull lines preserve tag ref semantics (no
detached HEAD pull/checkout fallback), and 3) render with REPO_REF empty and
assert the pull uses a plain 'git pull --ff-only' against origin default branch
(and echoes "[clone-cache] pulled default branch"); place these tests alongside
the existing cases and mirror their style.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 17489f3c-76c5-45fa-93a7-b7baa33f087f
📒 Files selected for processing (7)
.kanban/changes/ABC-5/design.md.kanban/changes/ABC-5/proposal.md.kanban/changes/ABC-5/tasks.mdpackages/app/src/lib/core/templates-entrypoint/tasks.tspackages/lib/src/core/templates-entrypoint/tasks.tspackages/lib/tests/core/templates.test.tsscripts/e2e/clone-cache.sh
📜 Review details
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: E2E (Login context)
- GitHub Check: E2E (Browser command)
- GitHub Check: E2E (Clone cache)
- GitHub Check: E2E (Runtime volumes + SSH)
- GitHub Check: E2E (Clone auto-open SSH)
- GitHub Check: E2E (OpenCode)
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{sh,bash,py,js,ts,jsx,tsx,go,java,rb,php}
📄 CodeRabbit inference engine (Custom checks)
Fail if changed files introduce command injection or unsafe shell/process execution with user-controlled input
Files:
scripts/e2e/clone-cache.shpackages/lib/tests/core/templates.test.tspackages/lib/src/core/templates-entrypoint/tasks.tspackages/app/src/lib/core/templates-entrypoint/tasks.ts
**/*.{py,js,ts,jsx,tsx,go,java,rb,php,sh,bash,c,cpp}
📄 CodeRabbit inference engine (Custom checks)
Fail if changed files introduce path traversal or writes outside intended project/container state directories
Files:
scripts/e2e/clone-cache.shpackages/lib/tests/core/templates.test.tspackages/lib/src/core/templates-entrypoint/tasks.tspackages/app/src/lib/core/templates-entrypoint/tasks.ts
**/*.{js,ts,jsx,tsx,py,java,go,rb,php,sh,bash,yml,yaml,json,env*,toml,cfg,config,dockerfile,dockerignore}
📄 CodeRabbit inference engine (Custom checks)
Fail if changed files expose credentials, tokens, private-keys, or PII in source, generated config, logs, or CI output
Files:
scripts/e2e/clone-cache.shpackages/lib/tests/core/templates.test.tspackages/lib/src/core/templates-entrypoint/tasks.tspackages/app/src/lib/core/templates-entrypoint/tasks.ts
**/*
⚙️ CodeRabbit configuration file
**/*: Ты строгий ревьюер SPEC DRIVEN DEVELOPMENT.Перед выводами изучи README.md, другие *.md файлы, linked issues,
PR description, PR comments/discussion и релевантную кодовую базу.Сверь изменения с исходным ТЗ/спекой и обсуждением. Флагай любой уход
от спеки, недокументированное изменение поведения, отсутствие тестов
для заявленного поведения и security-риск. Если спека не видна,
попроси автора добавить ее в issue или PR description.Проверь решение с точки зрения формальной верификации: какие инварианты,
предусловия и постусловия можно доказать математически, а где доказуемость
слабая. Оцени решение с точки зрения теории игр: устойчивы ли стимулы,
нет ли выгодного обхода правил, и какое решение было бы сильнее.
Files:
scripts/e2e/clone-cache.shpackages/lib/tests/core/templates.test.tspackages/lib/src/core/templates-entrypoint/tasks.tspackages/app/src/lib/core/templates-entrypoint/tasks.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Implement Functional Core, Imperative Shell (FCIS) pattern: CORE layer contains only pure functions with immutable data and mathematical operations; SHELL layer isolates all effects (IO, network, database). Strict dependency direction: SHELL → CORE (never reverse).
Never useany,unknown,eslint-disable,ts-ignore, orastype assertions (except in rigorously justified cases with documentation). Always use exhaustive union type analysis through.exhaustive()pattern matching.
All external dependencies must be wrapped through typed interfaces and injected via Effect-TS Layer pattern. Never call external services directly from CORE functions.
Use monadic composition with Effect-TS for all effects:Effect<Success, Error, Requirements>. Compose effects throughpipe()andEffect.flatMap(). Implement dependency injection via Layer pattern. Handle errors without try/catch blocks.
All functions must be pure in the CORE layer: no side effects (logging, console output, IO operations, mutations). Separate all side effects into the SHELL layer.
Use exhaustive pattern matching with Effect.Match instead of switch statements. Example:Match.value(item).pipe(Match.when(...), Match.exhaustive).
Document all functions with comprehensive TSDoc including:@pure(true/false),@effect(required services),@invariant(mathematical invariants),@precondition,@postcondition,@complexity(time and space),@throwsNever (errors must be typed in Effect).
Use functional comment markers for code clarity: CHANGE (brief description), WHY (mathematical/architectural justification), QUOTE(ТЗ) (requirement citation), REF (RTM or message ID), SOURCE (external source with quote), FORMAT THEOREM (∀x ∈ Domain: P(x) → Q(f(x))), PURITY (CORE|SHELL), EFFECT (Effect type signature), INVARIANT (mathematical invariant), COMPLEXITY (time/space).
Define all external service dependencies as Context.Tag classes with fully typed methods returning Effect types. Example: `class Da...
Files:
packages/lib/tests/core/templates.test.tspackages/lib/src/core/templates-entrypoint/tasks.tspackages/app/src/lib/core/templates-entrypoint/tasks.ts
**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.test.{ts,tsx}: Implement property-based testing using fast-check for mathematical properties and invariants. Example:fc.property(fc.array(messageArbitrary), (messages) => isChronologicallySorted(sortMessagesByTimestamp(messages))).
Mock external dependencies in unit tests using Effect's testing utilities. Run tests without Effect runtime for speed. Example:Effect.provide(MockService), Effect.runPromise.
Files:
packages/lib/tests/core/templates.test.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,js,jsx}: Forbidden constructs in CORE code:any,eslint-disable,ts-ignore,async/await, raw Promise chains (then/catch),Promise.all,try/catchfor logic control,console.*, switch statements (use Match with .exhaustive() instead)
All functions must use Effect-TS for composing effects:Effect<Success, Error, Requirements>. No direct async/await, Promise chains, or try/catch in product logic.
Functional comments must include: CHANGE, WHY, QUOTE(ТЗ) or n/a, REF, SOURCE or n/a, FORMAT THEOREM, PURITY (CORE|SHELL), EFFECT signature for SHELL functions, INVARIANT, and COMPLEXITY.
All data mutations must use immutable patterns (ReadonlyArray, readonly properties, Object.freeze); mutation in SHELL only when absolutely necessary and documented.
Files:
packages/lib/tests/core/templates.test.tspackages/lib/src/core/templates-entrypoint/tasks.tspackages/app/src/lib/core/templates-entrypoint/tasks.ts
**/*.{test,spec}.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Property-based tests (fast-check) must verify mathematical invariants; unit tests must use Effect test utilities without async/await.
Files:
packages/lib/tests/core/templates.test.ts
packages/app/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (README.md)
App layer (APP) should work only with API and not have direct access to LIB layer
Files:
packages/app/src/lib/core/templates-entrypoint/tasks.ts
🪛 LanguageTool
.kanban/changes/ABC-5/proposal.md
[style] ~19-~19: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...eckout logic in the target workspace. - Existing behavior refreshes the bare mirror with...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~33-~33: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...ics. - Do not merge work into main. - Do not cache secrets or auth material in r...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~34-~34: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...h material in repository cache paths. - Do not commit cache artifacts into the `.d...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~35-~35: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...o the .docker-git state repository. - Do not broaden mirror refresh to hosted fo...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
🔇 Additional comments (3)
.kanban/changes/ABC-5/tasks.md (1)
26-27: Неподтверждённый e2e-сценарий уже отмечен в предыдущем ревью.Этот риск уже был поднят ранее и остаётся актуальным до прогона
bun run e2e:clone-cacheв окружении с доступным controller.Also applies to: 50-50
packages/lib/src/core/templates-entrypoint/tasks.ts (1)
151-156: Здесь продублирован тот же дефект warm-cache ref-resolution, что и в app-шаблоне.Fallback из stale mirror может потерять запрошенный ref, теговый checkout упирается в detached HEAD, а empty
REPO_REFзависит от staleHEADmirror.Also applies to: 187-217
packages/app/src/lib/core/templates-entrypoint/tasks.ts (1)
151-156: 🏗️ Heavy liftWarm-cache больше не гарантирует запрошенный ref/default branch — нужен явный resolve и корректная логика для tag/detached HEAD
packages/app/src/lib/core/templates-entrypoint/tasks.ts(151–156): refresh делает толькоgit --git-dir '$CACHE_REPO_DIR' fetch ...в bare-зеркало;git fetchне обновляет symbolic-refHEADbare-репозитория, поэтому дальнейший checkout по умолчанию (например, при пустомREPO_REF/когда не используется--branch) может зависеть от устаревшегоHEADв кэше, а не от current default-branch удалённого$AUTH_REPO_URL.packages/app/src/lib/core/templates-entrypoint/tasks.ts(187–217): для кейсаREPO_REFкак tag проверьте последовательностьgit pull --ff-only origin '$REPO_REF'послеgit clone --branch '$REPO_REF' ...;git pullпри detached HEAD может привести к неожиданной семантике (обновление/слияние не в локальную ветку) и оставаться в detached состоянии — для детерминизма нужно явноcheckout/создать локальную ветку из тега и выполнятьpullуже от неё.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.kanban/changes/ABC-5/proposal.md:
- Line 57: В файле содержащем строку "Remote CI note: GitHub `E2E (Clone cache)`
was still pending at archive time" обновите текст, чтобы явно зафиксировать, что
по PR `#343` все E2E ещё в состоянии pending и потому merge блокируется;
перечислите текущие зависающие чекы (`E2E (Clone cache)`, `E2E (OpenCode)`, `E2E
(Login context)`, `E2E (Runtime volumes + SSH)`, `E2E (Clone auto-open SSH)`) и
добавьте короткую пометку/строку о том, что мердж разрешён только после
успешного завершения всех этих E2E.
In @.kanban/changes/ABC-5/tasks.md:
- Line 53: PR `#343` shows E2E (Clone cache) as SUCCESS while E2E (Login context)
and E2E (OpenCode) are still IN_PROGRESS; do not merge yet — wait until those
two checks finish and report SUCCESS. Monitor the PR checks for "E2E (Login
context)" and "E2E (OpenCode)" and only merge when all three E2E checks are
green; if you need immediate enforcement, enable/confirm branch protection rules
that require all E2E checks before merging to main.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 70202598-186d-43d5-bb06-743a48ce12e3
📒 Files selected for processing (3)
.kanban/changes/ABC-5/design.md.kanban/changes/ABC-5/proposal.md.kanban/changes/ABC-5/tasks.md
📜 Review details
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: E2E (OpenCode)
- GitHub Check: E2E (Runtime volumes + SSH)
- GitHub Check: E2E (Clone auto-open SSH)
- GitHub Check: E2E (Clone cache)
- GitHub Check: E2E (Login context)
- GitHub Check: E2E (Browser command)
🔇 Additional comments (5)
.kanban/changes/ABC-5/design.md (2)
89-95: Отметьте ограничение верификации e2e в локальной среде.Документация корректно фиксирует, что локальный e2e заблокирован ограничениями окружения (DOCKER_HOST discovery) и что GitHub E2E job является authoritative signal. Это разумное признание ограничений среды разработки.
94-94: ⚡ Quick winПроверьте утверждение о scope ошибок lint в Archive Verification Notes (стр. 94)
Утверждение, что lint-ошибки “полного репозитория” находятся вне ABC-5 diff, требует подтверждения: при попытке прогнатьbun run eslintлокально командаbunотсутствует, поэтому проверить попадание/непопадание ошибок в изменённые ABC-5 файлы не удалось.Приложить к строке 94 вывод/ссылку на CI eslint, показывающую, что изменённые файлы ABC-5 (
packages/lib/src/core/templates-entrypoint/tasks.ts,packages/app/src/lib/core/templates-entrypoint/tasks.ts,packages/lib/src/core/templates/docker-compose.ts,packages/app/src/lib/core/templates/docker-compose.tsиpackages/lib/tests/core/templates.test.ts) проходят lint без ошибок, а проблемные файлы действительно соответствуют указанным исключениям..kanban/changes/ABC-5/proposal.md (1)
49-56: Документация архивного статуса соответствует требованиям.Секция Archive Status корректно документирует ссылки на коммиты, PR, и финальное поведение. Описание warm-cache behavior (использование refreshed bare mirror + authenticated origin + branch-aware
git pull --ff-only) согласуется с design.md..kanban/changes/ABC-5/tasks.md (2)
58-62: LGTM!
49-49: ⚡ Quick winУточните, блокирует ли
bun run lintmerge в CI при ошибках на файлах вне ABC-5.
В PR#343bun run lintпадает из‑за существующих нарушенийmax-lines/max-lines-per-functionвне scope, при этом scoped lint для изменённых файлов прошёл (стр. 47–48, стр. 49). Нужно подтвердить поведение CI/branch protection: какие lint-check’и считаются required и блокируют ли merge при таких failures. Запрос настроек branch protection дляmainпо API вернул 403, поэтому автоматически проверить required-check’и не удалось.
| - Archive baseline commit after rebase: `67ed16e docs(spec): archive ABC-5 clone cache work` | ||
| - Final behavior: warm-cache clones use the refreshed bare mirror as the local clone source, then restore the authenticated origin and run branch-aware `git pull --ff-only` for normal branch/default branch flows. | ||
| - E2E note: `bun run e2e:clone-cache` is updated but could not run in the local review environment because the host CLI cannot auto-discover the controller when `DOCKER_HOST=tcp://host.docker.internal:2375` and `DOCKER_GIT_API_URL` is unset. | ||
| - Remote CI note: GitHub `E2E (Clone cache)` was still pending at archive time; other remote build/type/test/e2e checks had passed except the repository-wide `Lint` job, which failed on unrelated pre-existing `max-lines` violations outside ABC-5 files. |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Проверка статуса GitHub E2E workflow для PR `#343`
echo "Checking GitHub E2E workflow status for PR `#343`..."
# Получаем информацию о PR и его checks
gh pr view 343 --json statusCheckRollup --jq '.statusCheckRollup[] | select(.name | contains("E2E")) | {name: .name, status: .status, conclusion: .conclusion}'
echo ""
echo "Full PR status:"
gh pr checks 343Repository: ProverCoderAI/docker-git
Length of output: 2788
Блокировка merge: E2E ещё не завершён (PR #343)
В .kanban/changes/ABC-5/proposal.md (стр. 57) сказано, что E2E (Clone cache) был “still pending at archive time”, и сейчас по PR #343 E2E проверки всё ещё в состоянии pending — в том числе: E2E (Clone cache), E2E (OpenCode), E2E (Login context), E2E (Runtime volumes + SSH), E2E (Clone auto-open SSH). Merge стоит делать только после успешного завершения всех E2E.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.kanban/changes/ABC-5/proposal.md at line 57, В файле содержащем строку
"Remote CI note: GitHub `E2E (Clone cache)` was still pending at archive time"
обновите текст, чтобы явно зафиксировать, что по PR `#343` все E2E ещё в состоянии
pending и потому merge блокируется; перечислите текущие зависающие чекы (`E2E
(Clone cache)`, `E2E (OpenCode)`, `E2E (Login context)`, `E2E (Runtime volumes +
SSH)`, `E2E (Clone auto-open SSH)`) и добавьте короткую пометку/строку о том,
что мердж разрешён только после успешного завершения всех этих E2E.
| - [x] `bun run build` | ||
| - [x] Local git repro for warm-cache branch path: bare mirror refresh, clone from mirror, restore origin, `git pull --ff-only origin <branch>`. | ||
| - [ ] `bun run e2e:clone-cache` blocked by local Docker/controller discovery: `DOCKER_HOST=tcp://host.docker.internal:2375` with no reachable `DOCKER_GIT_API_URL`. | ||
| - [ ] GitHub `E2E (Clone cache)` pending at archive time. |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Проверяем текущий статус E2E check для PR `#343`
gh pr view 343 --json statusCheckRollup --jq '.statusCheckRollup[] | select(.context | contains("E2E") or contains("Clone cache")) | {context: .context, state: .state, conclusion: .conclusion}'Repository: ProverCoderAI/docker-git
Length of output: 111
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# 1) Печатаем тип/наличие statusCheckRollup
gh pr view 343 --json statusCheckRollup --jq '{
statusCheckRollup_type: (.statusCheckRollup | type),
statusCheckRollup_is_null: (.statusCheckRollup == null)
}'
# 2) Достаём только контексты, где context не null и содержит E2E/Clone cache
gh pr view 343 --json statusCheckRollup --jq '
(.statusCheckRollup // [])
| map(select((.context? // "") | test("E2E|Clone cache")))
| map({context: .context, state: .state, conclusion: .conclusion})
'Repository: ProverCoderAI/docker-git
Length of output: 140
🏁 Script executed:
#!/bin/bash
set -euo pipefail
gh pr view 343 --json statusCheckRollup --jq '
(.statusCheckRollup // [])
| map({context: .context, state: .state, conclusion: .conclusion})
| sort_by(.context)
| .[0:200]
'Repository: ProverCoderAI/docker-git
Length of output: 1071
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Покажем структуру одного элемента statusCheckRollup (первые 1-3 штуки)
gh pr view 343 --json statusCheckRollup --jq '
(.statusCheckRollup // [])
| [.[0], .[1], .[2]]
'Repository: ProverCoderAI/docker-git
Length of output: 964
🏁 Script executed:
#!/bin/bash
set -euo pipefail
gh pr view 343 --json statusCheckRollup --jq '
(.statusCheckRollup // [])
| map({
name: .name,
workflowName: .workflowName,
status: .status,
conclusion: .conclusion,
detailsUrl: .detailsUrl
})
| sort_by(.name)
'Repository: ProverCoderAI/docker-git
Length of output: 3700
Подождите завершения всех E2E check’ов перед merge (Clone cache уже SUCCESS)
E2E (Clone cache) для PR #343 сейчас завершён с SUCCESS. При этом E2E (Login context) и E2E (OpenCode) ещё IN_PROGRESS, поэтому merge в main стоит отложить до их успешного завершения.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.kanban/changes/ABC-5/tasks.md at line 53, PR `#343` shows E2E (Clone cache)
as SUCCESS while E2E (Login context) and E2E (OpenCode) are still IN_PROGRESS;
do not merge yet — wait until those two checks finish and report SUCCESS.
Monitor the PR checks for "E2E (Login context)" and "E2E (OpenCode)" and only
merge when all three E2E checks are green; if you need immediate enforcement,
enable/confirm branch protection rules that require all E2E checks before
merging to main.
Summary
Implements ABC-5 / GitHub #138 repository clone cache behavior. Warm-cache clones use the refreshed shared bare mirror as the local clone source, restore the authenticated origin, and run branch-aware
git pull --ff-onlyfor normal/default branch flows.Closes #138
Verification
bun run --filter @effect-template/lib test -- tests/core/templates.test.tsbun run --filter @effect-template/lib testbun run --filter @prover-coder-ai/docker-git testbun run typecheckpackages/app/src/lib/core/templates-entrypoint/tasks.tspackages/lib/src/core/templates-entrypoint/tasks.tsbun run buildCI / Notes
Lintpreviously failed on unrelated existingmax-lines/max-lines-per-functionviolations outside ABC-5 changed files. ABC-5 scoped lint passed.bun run e2e:clone-cacheis updated but was blocked in the local environment because the host CLI cannot auto-discover the controller whenDOCKER_HOST=tcp://host.docker.internal:2375andDOCKER_GIT_API_URLis unset.