feat(context): implement ProjectIndexer with async file scanning #5271
Closed
HAL9000
wants to merge 0 commits from
feat/v3.4.0/acms-project-indexer into master
pull from: feat/v3.4.0/acms-project-indexer
merge into: cleveragents:master
cleveragents:master
cleveragents:fix/config-service-remove-undocumented-local-scope
cleveragents:bugfix/validation-attach-named-option-format
cleveragents:docs/add-example-tool-and-validation-management
cleveragents:bugfix/project-show-resource-name
cleveragents:bugfix/backlog-resource-schema-missing-overlay-strategy
cleveragents:fix/action-argument-schema/misleading-error-message
cleveragents:fix/remove-executable-resource-type
cleveragents:fix/config-get-output-missing-origin-panel-and-envelope
cleveragents:fix/tui-help-command-full-catalog-listing
cleveragents:fix/a2a-plan-execute-full-lifecycle
cleveragents:fix/invariant-service-action-scope-effective
cleveragents:fix/plan-explain-rich-output-panels
cleveragents:fix/a2a-dispatch-not-found-error-response
cleveragents:fix/project-service-namespaced-project
cleveragents:fix/automation-profile-remove-rich-output-panel
cleveragents:fix/container-handler-module-missing
cleveragents:fix/format-output-rich-color-renderers
cleveragents:fix/type-safety-legacy-migrator-type-ignore
cleveragents:spec/update-sse-streaming-event-example
cleveragents:fix/acms-skeleton-compressor-signature
cleveragents:controller-state-machine
cleveragents:fix/skill-add-yaml-wrapper-key
cleveragents:fix/1476-tool-list-cols
cleveragents:bugfix/permissions-diff-mode-cycle
cleveragents:fix/1444-access-type
cleveragents:fix/1429-node-ref
cleveragents:fix/1443-tier-defaults
cleveragents:bugfix/session-export-format-flag
cleveragents:feature/aws-cloud-handler-sdk
cleveragents:feat/output-renderer-registry
cleveragents:fix/1432-lsp
cleveragents:bugfix/1039-missing-validation-unit-tests-yaml
cleveragents:feature/audit-preserve-event-timestamp
cleveragents:feature/m8-tui-materializer
cleveragents:tdd/m4-automation-profile-di-bypass
cleveragents:bugfix/m7-audit-session-race
cleveragents:fix/1441-ctrl-tab
cleveragents:feature/m9-entity-sync
cleveragents:feature/extract-cleveractors-library
cleveragents:feature/m9-agent-card
cleveragents:feature/m9-team-collab
cleveragents:feature/m7-postgresql-backend
cleveragents:feature/m9-container-lifecycle
cleveragents:fix/issue-11189-config-actor-format
cleveragents:bugfix/m5-actor-options-ignored
cleveragents:fix-11004-tui-suggestions
cleveragents:feature/9827-wrap-plan-status-json-envelope
cleveragents:fix/arg-swap-validation-attachment-8177
cleveragents:pr-fix/9663-hot-warm-cold-tier-reliability
cleveragents:pr_fix-11000-conflict-report
cleveragents:bugfix/m3.6.0-lsp-7044-subprocess-cleanup
cleveragents:fix/7478-file-ops-security-fix
cleveragents:impl-tui-materializer
cleveragents:test/hierarchical-plan-4phase-lifecycle
cleveragents:feature/security-fix-relpath-pr-11217
cleveragents:feature/m2-implementation-pool-supervisor-checklist
cleveragents:fix-file-tools-path-validation
cleveragents:bugfix/m8-tui-input-live-refresh
cleveragents:feature/9126-fix-action-scope-invariant-merge
cleveragents:bugfix/m7-tool-calling-llm-options
cleveragents:fix-7478-startswith-bypass
cleveragents:bugfix/m3-cleanup-subprocess-on-failed-init
cleveragents:bugfix/m8-tui-anthropic-model-name
cleveragents:feat/integrate-cleveractors
cleveragents:feature/m8-tui-llm-dispatch
cleveragents:bugfix/m3.6.0-lsp-transport-header-injection-ascii
cleveragents:fix-11175
cleveragents:fix/auto_debug-partial-state
cleveragents:fix/issue-9124-add-bdd-tags
cleveragents:pr-9673-budget-enforcement
cleveragents:fix/actor-loader-list-actors-race-condition
cleveragents:pr-9675
cleveragents:feat/v3.3.0-three-way-merge-engine
cleveragents:fix/issue-7478-inline-executor-startswith-bypass
cleveragents:fix/plan-apply-json-envelope
cleveragents:feat/v3.4.0-acms-storage-tiers
cleveragents:feat/tui-tuimat-5326
cleveragents:fix-9675-context-show-clear
cleveragents:agents/final-working
cleveragents:feat/v3.4.0-context-show-clear-cli
cleveragents:fix/10356-eventbus-unsubscribe
cleveragents:11229-fix-acms-hot-max-tokens-regression-tests
cleveragents:pr-fix-7801
cleveragents:pr-8701-invariant-model
cleveragents:pr-fix/10597-lsp-transport-cleanup
cleveragents:bugfix/m3.6.0-lsp-transport-resource-leak
cleveragents:bugfix/9558-plan-conflict-detection
cleveragents:pr-fix-9608
cleveragents:feat/v3.3.0-plan-correct-revert-append
cleveragents:dmpipeline-v2
cleveragents:pr-fix-10608-header-injection
cleveragents:pr-9827-fix
cleveragents:bugfix/7492-validation-attachment-argument-swap
cleveragents:pr-fix-11002
cleveragents:feat/v3.4.0-context-list-add-cli
cleveragents:fix/plan-status-json-envelope
cleveragents:feat/v370/multi-session-tabs
cleveragents:fix-branch
cleveragents:fix/project-show-missing-panels
cleveragents:AUTO-IMP/PR-10069-checklist
cleveragents:feature/m2-pr-compliance-checklist
cleveragents:feature/pr-10592-cloud-resource-types
cleveragents:fix-lsp-transport-cleanup
cleveragents:feat/v360/cloud-resource-types
cleveragents:feature/context-strategy-protocol
cleveragents:refactor/v3.6.0-acp-to-a2a-rename
cleveragents:fix/context-cli-consolidation
cleveragents:fix/10608-lsp-header-injection
cleveragents:feat/acms-context-index
cleveragents:fix/plan-status-missing-output-panels
cleveragents:pr/fix-arg-swap-validation-attachment-8177
cleveragents:feature/issue-4748-actor-context-list-show-clear
cleveragents:fix-cli-plan-status-envelope
cleveragents:fix/plan-tree-color-format-ansi-output
cleveragents:pr/9981
cleveragents:pr/11153-auto-debug-fix
cleveragents:pr/10589-tui-materializer
cleveragents:fix/validate_path_security
cleveragents:pr-fix-11177-status-check-native-expressions
cleveragents:bugfix/m6-validate-path-startswith
cleveragents:security/relpath-containment-fallback
cleveragents:a2a-materializer-pr-fix
cleveragents:pr-fix-10608
cleveragents:bugfix/9250-a2a-session-id-validation-before-cleanup
cleveragents:pr-fix-11053
cleveragents:fix/10496-auto-debug-node-state-mutation
cleveragents:feat/tui-v370/tui-materializer
cleveragents:fix/a2a-handle-session-close-missing-session-id
cleveragents:fix/validation-attachment-arg-swap-8177
cleveragents:pr-fix-11196-invariant
cleveragents:feat/v3.4.0-acms-budget-enforcement
cleveragents:pr-fix-11196
cleveragents:bugfix/m5-fix-hot-max-tokens-tier
cleveragents:pr-fix-9675
cleveragents:perf/acms-large-project-indexing-optimization
cleveragents:perf-fix
cleveragents:pr-9608
cleveragents:feature/ten-way-merge-engine
cleveragents:pr-fix-branch
cleveragents:pr-11217
cleveragents:bugfix/9608-three-way-merge-engine
cleveragents:11101-three-way-merge-engine
cleveragents:feat/v3.4.0/acms-context-policy
cleveragents:fix/remove-silent-argument-swap
cleveragents:fix-pr-11000-structured-conflict-report
cleveragents:pr-fix-11053-session-id-validation
cleveragents:agents/fix-eventbus-unsubscribe
cleveragents:pr-10356
cleveragents:fix/invariant-action-scope
cleveragents:bugfix/issue-8395-sanitise-db-url
cleveragents:bugfix/m3-fix-action-scope-invariant-merge
cleveragents:pr-9671
cleveragents:feature/wire-missing-event-emitters
cleveragents:bugfix/m3.6.0-lsp-transport-post-spawn-cleanup
cleveragents:dmpipeline
cleveragents:bugfix/m5-acms-project-budget-override
cleveragents:fix/iterate-all-actors
cleveragents:pr/11217-fix-prefix-collision-bypass
cleveragents:fix/pr-11011-subprocess-cleanup
cleveragents:pr-11217-fix
cleveragents:pr-11217-relpath-fix
cleveragents:feat/v3.6.0-context-strategy-protocol
cleveragents:bugfix/tui-actor-overlay-render-shadow
cleveragents:bugfix/m5-revert-acms-budget-assembler
cleveragents:fix/eventbus-unsubscribe
cleveragents:feature/pr-9981
cleveragents:fix/v3.7.0/actor-add-update-flag
cleveragents:agents/fix-invariant-persistence-8573
cleveragents:fix/invariant-database-persistence
cleveragents:feat/tui-materializer-a2a
cleveragents:fix/tui-tui-materializer-a2a-event-queue
cleveragents:fix/unsubscribe-eventbus
cleveragents:pr-11153
cleveragents:feature/11201
cleveragents:pr-fix-11153-patched
cleveragents:pr-branch
cleveragents:fix/10813-strategy-decision-persistence
cleveragents:fix-pr-11145-status-check
cleveragents:pr-11053
cleveragents:pr-fix-10597-subprocess-cleanup
cleveragents:bugfix/mcp-infer-resource-slots-null-properties
cleveragents:pr-11166
cleveragents:pr-9675-fix
cleveragents:feat/structural-component-output-validation
cleveragents:fix/invariant-service-thread-safety
cleveragents:pr-fix-8179-implementation
cleveragents:pr-fix-9313
cleveragents:cleveragents-pr-fix-11038
cleveragents:fix/m2-acceptance-test
cleveragents:fix/pr-11042-rename-render
cleveragents:fix/action-scope-inmerge
cleveragents:fix/wf12-oom-sigkill
cleveragents:fix/wf18-container-clone-e2e
cleveragents:tdd/mcp-client-timer-cancel-race
cleveragents:feature/auto-debug-nodes
cleveragents:feat/v3.2.0-decision-recording-persistence
cleveragents:bugfix/m6-actor-overlay-render-shadow
cleveragents:bugfix/m7-plan-strategy-decisions-json
cleveragents:fix/10911-tui-suggestions-query-extraction
cleveragents:fix/lsp-transport-subprocess-cleanup
cleveragents:pr-fix-8177-validation
cleveragents:bugfix/m3-plan-status-json-envelope
cleveragents:fix/invariant-persistence-8573
cleveragents:pr-fix-11037
cleveragents:pr-11015-fix
cleveragents:pr_fix_11015
cleveragents:fix/m1-security-fix-startswith-bypass
cleveragents:fix/automation-profile-gates-lifecycle
cleveragents:fix-status-check-brittle-pipeline-11212
cleveragents:feat/pr-10590-dual-capability-strategies
cleveragents:feat/structural-output-validation
cleveragents:bugfix/m2-ci-status-check-resilience
cleveragents:fix-sandbox-cache-invalidation
cleveragents:feature/acp-a2a-rename-fix
cleveragents:feature/m3-plan-correction-data-model
cleveragents:pr-fix-10356-unsubscribe
cleveragents:pr-fix-11011
cleveragents:pr_fix/lsp-transport-header-injection-ascii
cleveragents:fix-pr-11002-startswith-bypass-7478
cleveragents:bugfix/acms-project-budget-override
cleveragents:fix/ci-status-check-resilience
cleveragents:bugfix/pr-fix-10597-cleanup-subprocess-on-init-failure
cleveragents:bugfix/sandbox-reexecute-cleanup
cleveragents:pr-fix-8701-invariant-model
cleveragents:fix/test-dotdot-traversal-assertion
cleveragents:fix/cleanup-stale-preserve-commits
cleveragents:fix/10592-pr-compliance
cleveragents:fix/security-file-tools-path-traversal-7478
cleveragents:pr-11180-fix
cleveragents:fix-combined-format
cleveragents:fix-9131-invariant-propagation
cleveragents:fix/tui-actor-selection-overlay
cleveragents:pr-11201
cleveragents:merge/pr-11196-invariant-fix
cleveragents:fix/issue-10813-strategize-decision-persistence
cleveragents:pr-fix-11170
cleveragents:pr/11165
cleveragents:temp-pr-11174
cleveragents:feat/invariant-enforcement-validation-pipeline
cleveragents:pr-fix-10356-unsubscribe-eventbus
cleveragents:pr-fix-11156-python313-deprecation
cleveragents:feature/pr-7801-fix-validate-path-security
cleveragents:fix/11039-render-refresh
cleveragents:fix/tui-actor-selection-render-rename
cleveragents:pr-fix-11089-session-close-validation
cleveragents:pr-fix/11089-session-close-validation
cleveragents:pr-fix-11182
cleveragents:feature/7926-persist-decision-dependencies
cleveragents:bugfix/m3-rxpy-subject-close
cleveragents:test/restore-e2e-tests
cleveragents:feature/m694-tui-materializer-a2a-integration-layer
cleveragents:feature/issue-pr-9271-hot-max-tokens
cleveragents:pr-fix-8177
cleveragents:test/v360/e2e-project-plan-correction
cleveragents:bugfix/issue-8426-stdio-cleanup
cleveragents:feature/eventbus-unsubscribe
cleveragents:bugfix/m3-integrate-mcp-transport
cleveragents:fix/concurrent-stdout-restoration
cleveragents:feat/a2a-stdio-transport-fix-264
cleveragents:PR-fix-wf18
cleveragents:feature/sandbox-cache-invalidation
cleveragents:fix/issue-10496-auto-debug-state-mutation
cleveragents:fix/python-313-asyncio-deprecations
cleveragents:pr-11128
cleveragents:pr-11180
cleveragents:pr-11165
cleveragents:pr-practice
cleveragents:structural-output-validation
cleveragents:fix/status-check-native-expressions
cleveragents:feat/merge-conflict-detection
cleveragents:11036-fix-acms-hot-max-tokens
cleveragents:pr/11166
cleveragents:fix/ci-status-check-native-expressions
cleveragents:fix/stdlib-transport-cleanup
cleveragents:fix/11176-actor-selection-render
cleveragents:pr-fix-10597
cleveragents:feature/pr-compliance-pool-supervisor
cleveragents:fix/actor-add-update-enforcement-fix
cleveragents:pr_fix/8209
cleveragents:pr-10590
cleveragents:fix/python313-asyncio-get-event-loop-deprecation
cleveragents:pr-fix-#11053-session-id-validation
cleveragents:pr-fix-11042-renamed-render
cleveragents:feat/v360/acp-to-a2a-rename
cleveragents:fix-arg-swap-validation-attachment-8177
cleveragents:fix/asyncio-get-event-loop-deprecation
cleveragents:fix_8395_pr
cleveragents:pr-fix-11153-auto-debug-mutation
cleveragents:pr/11051-thread-safety-invariant
cleveragents:fix-plan-status-json-envelope
cleveragents:bugfix/pr-11015-pool-supervisor-checklist
cleveragents:feature/fix-7478-validate-path
cleveragents:feature/plans-conflict-detection
cleveragents:pr-11141-cleanup-stale-commits-beyond-head
cleveragents:fix/pyyaml-vulnerability-upgrade
cleveragents:pr-fix-9244
cleveragents:bugfix/m3-invariant-propagation
cleveragents:feature/issue-10480-fix-validation-bypass
cleveragents:feature/m3-invariant-enforcement-validation-pipeline
cleveragents:feat/invariant-enforcement-strategize-phase
cleveragents:bugfix/mcp-race-condition-start
cleveragents:fix/action-schema-argument-default-type-validation
cleveragents:issue-10438-fix
cleveragents:fix/mcp-timer-race-10516
cleveragents:fix/10480-validation-bypass-fix
cleveragents:fix/cli-session-tell-format-flag
cleveragents:feat/agents-invariant-add-list-remove-commands
cleveragents:restore-e2e-cleanup
cleveragents:fix/events-eventbus-unsubscribe
cleveragents:fix/issue-11120-cleanup-stale-preserve-artifacts
cleveragents:feature/fix-issue-11121-cleanup-stale-reinvoke
cleveragents:fix/issue-10480-plan-validation
cleveragents:feature/m5-tdd-quality-gate
cleveragents:bugfix/11121-fix-cleanup_stale-preserve-meaningful-changes
cleveragents:bugfix/m8-set-active-persona-preset-reset
cleveragents:feat/context-priority-strategy
cleveragents:feature/issue-4381-docs-api-and-module-guides
cleveragents:m7-opencode-ruff
cleveragents:bugfix/m3-wf18-oom-sigkill
cleveragents:bugfix/acms-dual-strategy-capabilities-incompatible-fields
cleveragents:feature/benchmark-scheduled-workflow
cleveragents:feature/m8-tui-mainscreen
cleveragents:fix/10932-preserve-strategy-decisions-json
cleveragents:fix/data-integrity-session-rollback-7489
cleveragents:fix/issue-6329-resource-remove-edge-table
cleveragents:fix/issue-7524-invariant-service-thread-safety
cleveragents:pr-10932-fix-plan-strategy-decisions
cleveragents:pr-fix-9244-pyyaml-upgrade
cleveragents:refactor/noxfile-parallel-test-architecture
cleveragents:task/ci-matrix-strategy-python-versions
cleveragents:bugfix/m3.6.0-ci-pipeline-flakiness-stabilization
cleveragents:feat/v3.3.0-plan-rollback
cleveragents:refactor/auto-guard-1-cli-a2a-boundary
cleveragents:feature/issue-10755-redirect-rich-panels-to-stderr
cleveragents:pr10871
cleveragents:fix/10881-propagate-invariants-to-child-plans
cleveragents:feat/resources-extension-interface
cleveragents:pr-fix-10901
cleveragents:ci/optimize-benchmarks-regression
cleveragents:fix/tui-extract-at-token-suggestions
cleveragents:feat/acms-index-data-model
cleveragents:feature-10887-eventbus-unsubscribe
cleveragents:feature/m5-add-repo-indexing-showcase
cleveragents:PR-10910-a2a-json-rpc-routing
cleveragents:feature/milestone-based-pr-prioritization
cleveragents:bugfix/m3-issue-9055
cleveragents:auto-time-3-day106-cycle2
cleveragents:feature/m39-timeline-day106-cycle2-2026-04-16
cleveragents:timeline/day-106-cycle2-2026-04-16-auto-time-3
cleveragents:feat/issue-10921-a2a-http-transport
cleveragents:pr/fix-10842
cleveragents:feature/issue-10746-fix-agents-graphs-plan-generation-validate-always-passes-for-code-longer-than-10-characters-making-llm-validation-ineffective
cleveragents:agents/fix-10866-permissions-screen-to-textual-screen
cleveragents:pr-10886
cleveragents:bugfix/m3-session-tell-format
cleveragents:fix/pr-10890-shell-safety-integration
cleveragents:fix/session-delete-json-envelope
cleveragents:pr-10851
cleveragents:test/v3.8.0-ci-quality-execution-time
cleveragents:feature/m7-timeline-day-106-update
cleveragents:bugfix/context-remove-path-traversal-10924
cleveragents:pr-10876
cleveragents:fix/gemini-fallback-order
cleveragents:fix/trailing-comma-opencode-json
cleveragents:pr/fix/mcp-client-start-race-condition
cleveragents:fix/project-switch-command
cleveragents:fix-pr-4211
cleveragents:feat/three-way-merge-engine-9608
cleveragents:pr/9673
cleveragents:fix/1469-plan-execute-structured-panels
cleveragents:fix/actor-provider-validation
cleveragents:implement-pr-9442
cleveragents:cleveragents-push-23420b48
cleveragents:fix/validation-repo-silent-swap
cleveragents:feat/context-strategy-plugin-system
cleveragents:fix/startswith-bypass-7478
cleveragents:fix-plan-status-envelope-11034
cleveragents:fix/invariant-thread-safety
cleveragents:fix-thread-safety-invariant-service
cleveragents:fix/8284-warned-sessions-reset
cleveragents:docs/milestone-plan-navigation
cleveragents:feat/v3.3.0-checkpoint-creation
cleveragents:feature/implementor-notification-11032
cleveragents:task/ci-optimize-e2e-tests-execution-time
cleveragents:feature/pr-9599-plan-correct-correction-engine
cleveragents:pr-fix-10593
cleveragents:pr9452
cleveragents:fix/isolate-checkpoint-prune-test
cleveragents:pr/fix-9601
cleveragents:pr/9234-hardening-bdd-tags
cleveragents:bugfix/9673-acms-budget-enforcement
cleveragents:pr-8667
cleveragents:auto-arch/spec-pr-10451-test-coverage
cleveragents:fix/10954-security-scan-dockerfile
cleveragents:bugfix/9183-bdd-tag-enforcement
cleveragents:fix/7566-engine_cache-toctou-race
cleveragents:fix/10934-preserve-strategy-decisions-json
cleveragents:bugfix/10608-lsp-header-injection
cleveragents:bugfix/9981-acms-indexing-optimize
cleveragents:bugfix/11077-security-escape-bypass
cleveragents:fix/auto-rev-sup-tracking-prefix
cleveragents:fix-lsp-subprocess-cleanup-10597
cleveragents:improvement/agent-evolution-pool-supervisor-pr-metadata
cleveragents:fix/plan-tree-json-output-envelope
cleveragents:pr-9313-fix
cleveragents:bugfix/9244-pyyaml-security-upgrade
cleveragents:feature/issue-1925-add-asv-tests-for-domain-module
cleveragents:test/domain-asv-benchmarks
cleveragents:feature/9250-fix-a2a-session-close
cleveragents:fix/pr-10027-acms-default-pipeline
cleveragents:bugfix/m2-plan-explain-alternatives-format
cleveragents:fix-invalidate-sandbox-dirs-cache-after-purge-7527
cleveragents:pr-fix-10958-async-cleanup-tests
cleveragents:feat/adr-049-layer-boundary-enforcement
cleveragents:fix/action-list-table-columns
cleveragents:fix/issue-7478-validate-path-startswith-bypass
cleveragents:pr-fix-ci-11000
cleveragents:fix/agent-skill-multi-scope-discovery
cleveragents:pr_fix_8675_switch_project_command
cleveragents:feat/m6/devcontainer-clone-into-sandbox
cleveragents:fix/tui-keybinding-preset-persona-cycling
cleveragents:pr-fix-10982
cleveragents:bugfix/m3-invariant-service-thread-safety
cleveragents:pr-fix-10937-close-reactive-eventbus
cleveragents:pr-fix-7478-path-traversal
cleveragents:feature/benchmark-scheduled-workflow-fix
cleveragents:pr-9183-add-bdd-tags
cleveragents:pr/11029-review-started-notification
cleveragents:fix/pyyaml-security-upgrade
cleveragents:fix-plan-status-panels
cleveragents:fix-pr-11037
cleveragents:feat/v3.6.0-database-resource-types
cleveragents:pr-10591-checkout
cleveragents:pr-10979
cleveragents:fix/invariant-thread-safety-8209
cleveragents:pr-fix-11002-validate-path-bypass
cleveragents:fix/10597-lsp-proc-cleanup
cleveragents:fix/plan/tree-envelope-9313
cleveragents:fix-6568-push
cleveragents:fix/issue-6425-tui-persona-cycling-keybinding
cleveragents:pr/11044
cleveragents:feature/m6-reduce-redundant-ci-status-reporting
cleveragents:fix/11041-plan-tree-envelope
cleveragents:fix/ca-test-infra-improver-health-spam
cleveragents:agents/pr-6628-fix
cleveragents:docs/add-showcase-cli-basics
cleveragents:auto-time-1-day107-cycle
cleveragents:improvement/agent-uat-tester-parallel-docs-pr-fix
cleveragents:fix/issue-11047-actor-add-rename-from-config
cleveragents:fix/pr-11050-subprocess-cleanup
cleveragents:pr-6741
cleveragents:ci/cache-helm-binary-auto-inf-1
cleveragents:fix/8675-project-switch
cleveragents:fix/7527-sandbox-cache-invalidation
cleveragents:fix/issue-6319-project-context-set-output
cleveragents:pr/fix-9183-bdd-tags
cleveragents:fix/issue-6325-plan-explain-decision-id
cleveragents:fix/1422-docs
cleveragents:pr-fix-1485-updates
cleveragents:spec/subplan-system-v3.3.0
cleveragents:pr/6723-fix-session-create-json
cleveragents:improvement/agent-bug-hunt-pool-supervisor-tracking-prefix-complete
cleveragents:fix/pr-6695-session-list-empty-json
cleveragents:fix/file-tools-startswith-bypass
cleveragents:pr_fix_8256
cleveragents:pr-9663-fix
cleveragents:docs/add-example-resource-and-skill-management
cleveragents:feature/m39-cli-basics-showcase
cleveragents:pr-fix-7478-startswith-bypass
cleveragents:fix/issue-11047-actor-add-remove-positional-name
cleveragents:fix/gemini-fallback-order-fix-3
cleveragents:pr_fix_8179
cleveragents:fix/gemini-fallback-order-fix-2
cleveragents:fix/validation-list-command
cleveragents:fix/validation-list-command-clean
cleveragents:fix-pr7957-complete-tracking-prefix
cleveragents:pr-7922-fix-lint
cleveragents:fix/validation-swap-8177
cleveragents:add-plan-start-alias
cleveragents:feature/pr-8304-container-clone-into
cleveragents:fix-pyyaml-11012
cleveragents:pr-fix-9461
cleveragents:fix/pr-11004-tui-token-extraction
cleveragents:fix/invariant-scope-handling
cleveragents:feat/plan-correction-8531
cleveragents:pr/8685-correction-data-model-persistence
cleveragents:bugfix/lsp-stdio-transport-cleanup-10597
cleveragents:pr-8660
cleveragents:feat-scope-chain-resolution
cleveragents:chore/pyyaml-upgrade
cleveragents:fix/9250-session-id-validation-handle-session-close
cleveragents:fix/issue-7478-file-tools-validate-path
cleveragents:pr-fix-9442-tui-ctrltab
cleveragents:spec/update-cycle8-validation-gate-empty-run-guard
cleveragents:fix/tui-sqlite-session-persistence-10648
cleveragents:fix/8661-plan-start-alias
cleveragents:fix-10649
cleveragents:refactor/add-return-type-get-services
cleveragents:pr-fix-cache-init
cleveragents:pr9407-timeline
cleveragents:feat/tui-prompt-symbol
cleveragents:pr_fix_9407-plan-alternatives-structured
cleveragents:feat/automation-profile-precedence-chain
cleveragents:bugfix/8179-remove-session-rollback-calls
cleveragents:feat/v360/pluggable-scope-chain-api
cleveragents:pr-9246
cleveragents:refactor/agent-configurable-limits-context-analysis-plan-generation
cleveragents:fix/issue-6452-session-tell-output
cleveragents:fix/v370/quality-gates-command-injection
cleveragents:pr-fix-10635-fixed
cleveragents:pr-10069
cleveragents:pr/fix-9313
cleveragents:pr-10643
cleveragents:invariant-pr-8684-fix
cleveragents:pr-fix-6676-resource-remove-edge-table
cleveragents:refactor/v360/audit-rename-acp-imports
cleveragents:fix/issue-7623-validation-pipeline-stdout
cleveragents:fix/acms-consolidate-strategycapabilities
cleveragents:fix/issue-7604-a2a-event-queue-concurrency
cleveragents:pr-fix-8661
cleveragents:auto-arch/spec-clarifications-cycle-1
cleveragents:feat/pure-graph-bdd-coverage
cleveragents:fix/9250-validate-session-id-before-cleanup
cleveragents:feature/issue-9442-fix-tui-correct-preset-cycling-keybinding-to-ctrl-tab-and-add-persona-tab-cycling
cleveragents:bugfix/m6-file-tools-validate-path-bypass
cleveragents:fix/invariant-add-scope
cleveragents:bugfix/m3-shell-safety-service-tui
cleveragents:pr-8684-persist-invariants
cleveragents:pr-8209-fix
cleveragents:docs/v360/repl-actor-run-showcase
cleveragents:feat/v360/cost-session-budget
cleveragents:bugfix/8177-remove-silent-argument-swap
cleveragents:fix/plan-apply-rich-output-panels
cleveragents:pr-fix-11012
cleveragents:pr-fix-11012-pyyaml-upgrade
cleveragents:pr-fix-8667
cleveragents:pr/fix/11012-pyinsec
cleveragents:pr-fix-9407
cleveragents:pr-8853
cleveragents:test/cli-lifecycle-e2e-full-plan-lifecycle
cleveragents:bugfix/m3-evlv-9824-implementation-pool-compliance-checklist
cleveragents:pr/10069
cleveragents:docs/pr-creator-state-priority-labels
cleveragents:fix/1514-structured-panels
cleveragents:test/core-asv-benchmarks
cleveragents:fix-8640-remove-positional-name
cleveragents:pr-fix-10995
cleveragents:refactor/v3.6.0-acp-to-a2a-rename-push
cleveragents:pr-9663
cleveragents:bugfix/m3.6.0-lsp-discovery-resource-exhaustion-dos
cleveragents:8660-move-namespace-filter-inside-lock
cleveragents:pr-fix-work
cleveragents:test/plan-correct-json-output-tdd
cleveragents:pr-8304
cleveragents:feat/v3.2.0-invariant-data-model-db-schema
cleveragents:pr_fix_1514_v2
cleveragents:timeline-update-2026-04-19
cleveragents:pr-fix-9313-plan-tree-envelope
cleveragents:test/v3.6.0/advanced-context-strategies-tests
cleveragents:pr/11004-fix-tui-suggestions-query-extraction
cleveragents:pr-fix-9817
cleveragents:feat/9558-plan-conflict-detection
cleveragents:docs/timeline-day-101
cleveragents:fix/v360/plugin-loader-security
cleveragents:feat/acms-context-policy-fix-9671
cleveragents:pr-9817-plan-apply-json
cleveragents:pr-fix-9460
cleveragents:pr-fix-6722-prompt-symbol
cleveragents:pr/9671
cleveragents:pr-fix-9671
cleveragents:pr-10592-fix
cleveragents:fix/issue-7478-file-path-validation
cleveragents:pr-fix-7478-validatepath
cleveragents:feat/pr-10590-context-strategy-fix
cleveragents:bugfix/m6-acms-path-matching-absolute
cleveragents:bugfix/pr-9183-bdd-tags
cleveragents:fix-pr-10975-path-matching-normalize
cleveragents:pr_fix/lsp-transport-subprocess-cleanup
cleveragents:pr-8177-validation-fix
cleveragents:feat/acms-context-show-clear-cli
cleveragents:feat/v360/plugin-architecture
cleveragents:fix/invariant-add-scope-required
cleveragents:pr-fix-10590-context-strategy
cleveragents:pr-fix-10590-local
cleveragents:pr-8662-fix
cleveragents:pr/1485
cleveragents:bugfix/8660-move-namespace-filter-inside-lock
cleveragents:pr/9460-project-show-invariants-validations
cleveragents:pr-11013
cleveragents:fix-1469-impl
cleveragents:fix/1469-impl
cleveragents:fix/cleanup-service-sandbox-cache-invalidation
cleveragents:pr-8257
cleveragents:pr-3329
cleveragents:feat/v3.2.0-decision-recording-strategize
cleveragents:fix/strategize-full-context-snapshots
cleveragents:clone-verify-test
cleveragents:fix/issue-6316-session-list-json-empty-case
cleveragents:AUTO-IMP/PR-9672-context-list-add
cleveragents:AUTO-IMP/PR-9663-storage-tiers
cleveragents:fix/issue-pr-11002
cleveragents:fix/plan-lifecycle-prompt-decision
cleveragents:fix/gemini-fallback-order-10906
cleveragents:AUTO-IMP/PR-10583-a2a-rename
cleveragents:fix-check-same-thread-migration-runner
cleveragents:d2188407
cleveragents:fix/a2a-handle-session-close-missing-session-id-pr-9250
cleveragents:fix/invariant-merge-action-scope
cleveragents:pr-fix-8179
cleveragents:bugfix/report-number-of-actors
cleveragents:bugfix/m6-devcontainer-autodiscovery-wiring
cleveragents:fix-gemini-fallback-order-10906
cleveragents:bugfix/m5-event-bus-exception-swallow
cleveragents:pr/3458
cleveragents:acms-parallel-indexing-fix
cleveragents:bugfix/m3-error-handling-fileconfig-unhandled-exception
cleveragents:acms-parallel-indexing
cleveragents:fix/resource-removal-children-check-6886
cleveragents:pr/9451-fix-tui-thinking-effort-presets
cleveragents:pr-fix-10958
cleveragents:fix/8179-remove-session-rollback-calls
cleveragents:pr/9817-plan-apply-json-envelope
cleveragents:fix/lsp-context-enrichment-acms-wiring
cleveragents:fix/cli-remove-positional-name-from-actor-add
cleveragents:fix/acms-context-cli
cleveragents:fix/tui-permissions-screen-wrong-base-class
cleveragents:bugfix/m6-session-create-suppress-exception-logging
cleveragents:fix/plan-tree-json-missing-decision-id
cleveragents:fix/plan-start-spec-alignment
cleveragents:fix-10957
cleveragents:fix/6726-tui-persona-cycling-keybinding
cleveragents:feat/plan-rollback-cli-checkpoint-restore
cleveragents:pr-8661-plan-start-alias
cleveragents:pr/1486/resource-handler-return-type
cleveragents:feature/8667-add-validation-list-command
cleveragents:auto-docs-1-mkdocs-setup
cleveragents:fix/actor-add-positional-name
cleveragents:feat/v3.3.0-merge-strategy-config
cleveragents:fix/invariant-precedence-chain-action-scope
cleveragents:improvement/agent-pr-review-pool-supervisor-tracking-prefix-complete
cleveragents:pr/fix/actor-loader-list-actors-race-condition
cleveragents:bugfix/m4-lsp-context-enrichment-acms-wiring
cleveragents:docs/auto-docs-2-v320-v330-features
cleveragents:bugfix/m-error-suppression-reactive-registry-adapter-v2
cleveragents:fix/7501-plan-repository-success-derivation
cleveragents:pr-10492
cleveragents:pr-8225
cleveragents:fix/plan-artifacts-missing-validation-apply-summary
cleveragents:feature/m9-v3.8.0-v3.9.0-documentation
cleveragents:docs/fix-automation-profile-default-supervised
cleveragents:fix/context-analysis-agent-path-traversal
cleveragents:pr-9229-path-traversal-fix
cleveragents:pr-10975
cleveragents:pr-fix-10986
cleveragents:pr/1486/fix-resource-handler-return-type
cleveragents:feat/m8/tui-main-screen
cleveragents:pr-9257-fix
cleveragents:fix/9222-guard-integration-e2e-jobs
cleveragents:refactor/clarify-behave-robot-framework-roles
cleveragents:docs/reference-glossary
cleveragents:feat/9088-a2a-message-send-stream
cleveragents:bugfix/m6-gemini-fallback-order
cleveragents:fix/validation-list-command-fixed
cleveragents:fix-executable-resource
cleveragents:test/plan-tree-correction-visual-tdd
cleveragents:auto-time/timeline-update-2026-04-18
cleveragents:pr-8179
cleveragents:spec/auto-arch-24-a2a-boundary-enforcement-adr
cleveragents:pr/10988/head
cleveragents:fix/7566-engine-cache-toctou-race
cleveragents:feat/v3.6.0-llm-provider-abstraction
cleveragents:fix/concurrency-catalog-cache-lock-7590-cleandiff
cleveragents:chore/test-infra-broad-exception-lint
cleveragents:issue-7502-fix-get-for-plan
cleveragents:fix/1500-impl
cleveragents:feat/context-show-cli-commands
cleveragents:pr-fix-7527-cache-invalidation
cleveragents:pr-fix-9407-plan-explain-structured-alternatives
cleveragents:fix/multi-scope-skill-discovery-9369
cleveragents:pr_9454
cleveragents:feat/agent-switch-cmd
cleveragents:pr-9329
cleveragents:8661-plan-start-alias
cleveragents:feat/acms-context-analysis-summaries
cleveragents:fix/invariant-add-repeatable-plan-action
cleveragents:tdd/m6-session-create-suppress-exception
cleveragents:test-push-check-only
cleveragents:pr-10889
cleveragents:pr-10889-fix
cleveragents:feature/issue-10952-provider-integration-tests
cleveragents:pr/10879-benchmark-caching-parallelism
cleveragents:bugfix/m3-eventbus-unsubscribe
cleveragents:spec/add-deleted-at-field-to-project-delete
cleveragents:fix/issue-6500-actor-context-list-regex
cleveragents:tdd/m8-tui-sqlite-session-persistence
cleveragents:fix/issue-6464-resource-add-auto-discovery
cleveragents:fix/bug-hunt-supervisor-tracking-prefix
cleveragents:feat/v3.2.0-plan-tree-cli
cleveragents:fix/issue-6491-actor-remove-format-option
cleveragents:fix/issue-6457-json-envelope-messages-text
cleveragents:improvement/agent-ca-test-infra-improver-duplicate-avoidance
cleveragents:fix/boundary-cost-budget-warning-re-trigger-7525
cleveragents:bugfix/6879-cli-format-option
cleveragents:feat/jwt-token-refresh
cleveragents:auto-discovered-stale-conflicts-review-task
cleveragents:docs/add-example-audit-log-and-security
cleveragents:docs/v3.8.0-api-and-module-guides
cleveragents:fix/issue-9169
cleveragents:improvement/reduce-redundant-ci-status-reporting
cleveragents:feat/v3.4.0-acms-index-data-model-traversal
cleveragents:bugfix/m3-sqlite-check-same-thread
cleveragents:issue-1-conversation-state
cleveragents:bugfix/m3-evlv-implementation-pool-compliance-checklist
cleveragents:feature/m9-a2a-jsonrpc
cleveragents:bugfix/m6-plan-execute-rich-output
cleveragents:fix/uat-checkpoint-prune-test-isolation
cleveragents:feature/issue-4749-split-monolithic-specification
cleveragents:bugfix/m8-suggestions-query-extraction
cleveragents:bugfix/m6-session-delete-format-json-envelope
cleveragents:bugfix/m3-langgraph-disposables
cleveragents:timeline/day-104-2026-04-14-auto-time-2
cleveragents:docs/quickstart-guide
cleveragents:fix/plan-prompt-json-timing-started
cleveragents:feat/v3.6.0-virtual-resource-types
cleveragents:feat/tui-v370/persona-registry
cleveragents:fix/1431-subgraph
cleveragents:bugfix/7529-a2a-terminal-phase-guard
cleveragents:bugfix/m3-bdd-feature-file-tags
cleveragents:ci/v360/isolate-slow-e2e-tests
cleveragents:feature/m3-consolidate-documentation
cleveragents:feature/m7-user-driven-review-agent
cleveragents:feature/m9-a2a-http
cleveragents:fix/1423-refactor
cleveragents:fix/tui-mainscreen-3state-sidebar-adr044
cleveragents:task/v3.8.0-ci-reusable-workflows
cleveragents:testbed/m9-hello
cleveragents:docs/add-label-verification-to-new-issue-creator
cleveragents:bugfix/m3-database-migration-runner-check-same-thread
cleveragents:feature/m4-plan-correction-revert
cleveragents:improvement/agent-architecture-pool-supervisor-milestone-assignment
cleveragents:docs/changelog-unreleased-cycle7
cleveragents:feature/m9-changelog-unreleased-cycle7
cleveragents:fix/issue-10512-mcptooladapter-rlock
cleveragents:fix/data-integrity-llm-trace-repository-7505
cleveragents:agents/auto-working-new
cleveragents:fix/resource-removal-guard-linked-children
cleveragents:fix/1468-impl
cleveragents:feature/1915-timezone-aware-datetime
cleveragents:feature/issue-4381-docs-add-invariantreconciliationactor-api-docs-devcontainer-discovery-module-guide-and-mkdocs-nav
cleveragents:task/ci-actor-context-mgmt-test-optimization
cleveragents:fix/7619-git-tools-base-env-toctou
cleveragents:pr-fix-8661-updates
cleveragents:feature/issue-2798-chore-agents-improve-ca-test-infra-improver-strengthen-duplicate-avoidance
cleveragents:bugfix/m3-migration-runner-check-same-thread
cleveragents:feature/issue-10952-fix-database-migration-runner-check-same-thread
cleveragents:fix/dependency-security-aiohttp-cves
cleveragents:test/uko-persistence-coverage
cleveragents:fix/security-b608-sql-fstring-migration-plan-phases
cleveragents:fix/cli-legacy-removal
cleveragents:feature/m39-auto-arch-23-minor-clarifications
cleveragents:bugfix/m3-langgraph-execute-state-bypass
cleveragents:feat/issue-6370-actor-context-clear
cleveragents:feat/acms-hot-storage-tier-lru-cache
cleveragents:feature/m3111-milestone-based-pr-prioritization
cleveragents:bugfix/m3-actor-run-response
cleveragents:fix/issue-7524-invariant-service-thread-safety-v2
cleveragents:pr-fix-10746
cleveragents:fix/tui-auto-generate-presets-actor-schema
cleveragents:feat/agent-card-discovery
cleveragents:feature/pr-10916-close-reactive-event-bus
cleveragents:feature/issue-1917-optimize-robot-actor-context-management-tests
cleveragents:feature/issue-10803-fix-nox-sessions-use-uv-sync-frozen
cleveragents:feature/issue-1923-missing-test-levels-core-module
cleveragents:feature/1928-add-test-coverage-for-tui-module
cleveragents:chore/ci-dockerfile-server-security-scan
cleveragents:task/ci-centralize-tool-versions
cleveragents:feature/m9-langgraph-platform
cleveragents:bugfix/m5-validation-attach-output-format
cleveragents:test/ci-execution-time-optimize-benchmark-regression
cleveragents:feature/issue-3105-add-mandatory-labels-to-supervisor-tracking-issue-creation
cleveragents:feat/acms-context-policy-configuration-schema
cleveragents:feat/context-sliding-window-strategy
cleveragents:feature/issue-5163-align-checkpoint-trigger-names
cleveragents:feature/issue-4221-docs-add-showcase-example-for-audit-log-and-security-commands
cleveragents:bugfix/m3-output-plan-results
cleveragents:fix/action-archive-output-panels
cleveragents:pr/9912-fix
cleveragents:fix/concurrency-catalog-cache-lock-7590
cleveragents:bugfix/executor-error-details-overwrite-mini-max
cleveragents:fix-10866-permissions-screen
cleveragents:feature/issue-7957-bug-hunt-pool-supervisor-tracking-prefix
cleveragents:fix-pr-10852
cleveragents:fix/10922-conversation-state-mgmt
cleveragents:pr-check
cleveragents:bugfix/10931-preserve-strategy-decisions-json
cleveragents:fix/10903-nox-showcase-docs
cleveragents:pr/10885-pyyaml-upgrade
cleveragents:pr-fix-10931
cleveragents:bugfix/executor-error-details-overwrite-qwen
cleveragents:fix-orchestrator-scaling-32-workers
cleveragents:fix-pr-1107-asgi-uvicorn
cleveragents:feature/m9-timeline-day-99
cleveragents:feat/issue-6369-actor-context-show
cleveragents:improvement/agent-label-compliance
cleveragents:fix-9912-branch
cleveragents:bugfix/10821-fix-tui-keybinding
cleveragents:feat/issue-6450-tui-escape-cascade
cleveragents:bugfix/m8-shell-safety-service-integration
cleveragents:fix/redaction-pattern-exception-handling
cleveragents:bugfix/m8-tui-on-input-changed
cleveragents:fix/action-schema-env-var-exfiltration
cleveragents:feature/spec-timeline-6003
cleveragents:feature/spec-timeline-6008
cleveragents:feature/issue-4746-update-spec-agents-diagnostics-all-9-providers
cleveragents:feat/v3.6.0/gemini-provider
cleveragents:pr/8194
cleveragents:tdd/prompt-input-textarea
cleveragents:feat/v3.6.0/cost-reporting-cli
cleveragents:fix/lsp-transport-security
cleveragents:feat/v3.6.0/semantic-context-strategy
cleveragents:feature/issue-10820-chore-agents-fix-bug-hunt-pool-supervisor-tracking-prefix-auto-bug-pool-to-auto-bug-sup-complete-fix
cleveragents:tdd/mN-registry-thread-safety
cleveragents:fix/v360/remove-acp-module
cleveragents:temp-squash
cleveragents:fix/v360/lsp-runtime-instantiation
cleveragents:feat/690-jsonrpc-routing
cleveragents:feat/v3.6.0-anthropic-gemini-backends
cleveragents:build/agents-system-rewrite
cleveragents:feat/v3.3.0-plan-rollback-cli
cleveragents:feat/v3.3.0-parallel-subplan-scheduler
cleveragents:feature/issue-10846-optimize-benchmark-regression-test-suite
cleveragents:feature/issue-10826-docs-spec-align-checkpoint-trigger-names-and-config-key-path-with-implementation
cleveragents:feature/issue-10744-fix-tui-convert-permissionsscreen-from-static-widget-to-proper-textual-screen-subclass
cleveragents:feature/issue-10794-feat-a2a-implement-a2a-http-transport-for-server-mode
cleveragents:fix/tui-preset-cycling
cleveragents:pr-10820
cleveragents:feature/696-implement-a2a-http-transport-for-server-mode
cleveragents:feature/issue-10792-feat-server-langgraph-platform-remotegraph-integration
cleveragents:feature/issue-1486-fix-v3-7-0-resourcehandler-return-type-1444
cleveragents:feature/issue-1488-fix-v3-7-0-resolve-issue-1432
cleveragents:bugfix/m1-plan-execute-sandbox-root
cleveragents:feature/issue-4663-day-97-schedule-adherence-update
cleveragents:feature/issue-10858-devops-run-linter
cleveragents:docs/milestone-v3.6.0-v3.7.0
cleveragents:feature/issue-10835-add-milestone-based-pr-prioritization
cleveragents:pr-8701-head
cleveragents:fix/7927-apply-phase-dod-gating
cleveragents:fix/sse-formatter-json-rpc-2.0
cleveragents:feat/v3.6.0/scope-chain-assembler-integration
cleveragents:fix/tui-bindings-block-cursor-navigation
cleveragents:fix/v360/compute-actor-impact-exceptions
cleveragents:feat/v360/openrouter-provider
cleveragents:docs/v360/cli-version-info-diagnostics
cleveragents:feat/context-semantic-chunking-strategy
cleveragents:feat/acms-cli-context-show-clear
cleveragents:feature/m7-actor-management-showcase-metadata
cleveragents:feature/m6-4213-resource-skill-showcase
cleveragents:feat/v360/anthropic-gemini-backends
cleveragents:feat/v3.6.0/safety-profile-enforcement
cleveragents:feat/context-dynamic-budget-allocation
cleveragents:refactor/v360/unify-error-handling-cli
cleveragents:fix/v370/tui-materializer-a2a
cleveragents:fix/auto-debug-agent-prompt-injection
cleveragents:refactor/v360/unify-api-naming
cleveragents:test/cli-docstring-example-validation
cleveragents:fix/v360/resource-kind-field
cleveragents:feat/v3.6.0/context-relevance-scoring
cleveragents:fix/v360/plugin-state-executing
cleveragents:fix/v360/lsp-path-traversal-file-reading
cleveragents:feat/acms-semantic-chunking-context-strategy
cleveragents:refactor/v360/unify-service-initialization
cleveragents:bugfix/m3.6.0-lsp-server-dos-message-read-timeout
cleveragents:feat/v360/pluggable-scope-chain-api-v2
cleveragents:docs/v360/actor-management-showcase
cleveragents:docs/v360/actor-removal-impact
cleveragents:docs/v360/align-depth-reduction-devcontainer
cleveragents:tdd/issue-10413-dollar-prefix-shell-mode
cleveragents:fix/issue-10503-session-export-json-stdout
cleveragents:fix/pr-10755
cleveragents:feat/v370/tui-web-mode
cleveragents:feat/v360/plugin-cli-discovery
cleveragents:fix/v360/llm-trace-latency-type
cleveragents:feat/v3.6.0/ollama-mistral-providers
cleveragents:feat/v3.6.0/adaptive-context-selector
cleveragents:feat/tui-v370/persona-registry-merge-v2
cleveragents:feat/v3.6.0/cost-tracker
cleveragents:fix/v360/resource-type-cycle-detection
cleveragents:refactor/auto-guard-1-address-todo-fixme-comments
cleveragents:feat/v3.6.0/pluggable-scope-chain
cleveragents:fix/v360/scope-chain-resolver-registration
cleveragents:test/v360/e2e-a2a-context-management
cleveragents:fix/v360/lsp-env-var-injection
cleveragents:feature/m6-sandbox-correction-invariant-docs
cleveragents:feature/m3-timeline-day97-update
cleveragents:fix/10480-validate-logic-error
cleveragents:feat/acms-cli-context-add
cleveragents:feat/acms-core-pipeline-components
cleveragents:feature/m4652-module-guides
cleveragents:feature/m5-extend-agents-diagnostics-example
cleveragents:feature/m5832-add-unreleased-changelog-entries
cleveragents:docs/add-repo-indexing-showcase
cleveragents:improvement/agent-pr-self-reviewer-blocking-vs-nonblocking
cleveragents:feature/issue-8225-validation-gate-empty-summary
cleveragents:spec/resource-type-yaml-format-canonical-5622
cleveragents:bugfix/m8179-fix-data-integrity-remove-session-rollback-calls-from-projectrepository
cleveragents:feat/v3.6.0/context-policy-strategy-config
cleveragents:test/v3.6.0/a2a-rename-regression-tests
cleveragents:fix/plan-lifecycle-root-decision-type
cleveragents:bugfix/cancel-worktree-cleanup
cleveragents:pr-10586
cleveragents:pr-9215
cleveragents:feat/issue-6357-tui-loading-states
cleveragents:temp-bug2-combined
cleveragents:timeline/day-105-2026-04-15-auto-time-1-v2
cleveragents:docs/consolidated-all-documentation
cleveragents:bugfix/m6-sandbox-reexecute-cleanup
cleveragents:fix/issue-9963-memory-service-timestamp-guards
cleveragents:docs/context-management-deep-dive-v2
cleveragents:docs/context-management-deep-dive
cleveragents:docs/agent-development-guide
cleveragents:feature/10008-file-level-correction-diff
cleveragents:feat/acms-scope-resolution-context-inheritance
cleveragents:docs/a2a-protocol-guide
cleveragents:fix/tui-bindings-reload-settings
cleveragents:docs/tui-user-guide-keybindings
cleveragents:fix/plan-generation-validate-logic
cleveragents:bugfix/issue-10408-dollar-prefix-shell-mode
cleveragents:test/issue-10500-persona-state-reset-tdd
cleveragents:docs/getting-started-tutorial
cleveragents:test/tdd-session-create-suppress-exception
cleveragents:fix/issue-10485-fallback-selector-budget-limits
cleveragents:docs/error-codes-guide
cleveragents:docs/common-tasks-recipes-guide
cleveragents:bugfix/mN-registry-thread-safety
cleveragents:test/migration-runner-sqlite-threading
cleveragents:docs/configuration-reference
cleveragents:pr-10678
cleveragents:pr-10681
cleveragents:test/issue-10510-mcptooladapter-rlock-tdd
cleveragents:feature/tui-screens-directory
cleveragents:fix/issue-10511-suppress-runtimeerror
cleveragents:pr-10676
cleveragents:fix/tui-block-cursor-bindings
cleveragents:pr-10680
cleveragents:test/issue-10502-session-export-json-tdd
cleveragents:fix/issue-10507-sqlite-check-same-thread
cleveragents:docs/installation-setup
cleveragents:test/v3.6.0/scope-chain-integration-tests
cleveragents:fix/v370/loading-throbber-restore
cleveragents:feat/v370/tui-settings-sessions-screens
cleveragents:fix/v370/tui-session-persistence
cleveragents:fix/v360/context-strategy-unification
cleveragents:fix/v370/shell-safety-regex
cleveragents:feat/v370/tui-rebase-merge
cleveragents:feat/v370/tui-complete-squashed
cleveragents:fix/v370/tui-shell-async
cleveragents:feat/v3.6.0/budget-enforcement
cleveragents:refactor/v360/decouple-cli-services
cleveragents:feat/v370/tui-session-persistence
cleveragents:auto-arch-1-spec-module-definitions
cleveragents:docs/v3.6.0-v3.7.0-updates
cleveragents:auto-time/timeline-update-2026-04-18-c3
cleveragents:auto-docs-2/add-changelog-contributing
cleveragents:auto-time/timeline-update-2026-04-18-c2
cleveragents:auto-docs-1/fix-mkdocs-nav-and-links
cleveragents:pr-5968
cleveragents:docs/timeline-day-107-2026-04-17
cleveragents:fix/issue-6323-project-context-show-output
cleveragents:improvement/agent-bug-hunt-pool-supervisor-tracking-prefix
cleveragents:auto-time/update-2026-04-17
cleveragents:docs/auto-docs-8-a2a-rename-documentation
cleveragents:auto-docs-3-v340-v350
cleveragents:docs/timeline-update-2026-04-15
cleveragents:auto-docs/initial-documentation-assessment
cleveragents:feature/m1-initial-documentation
cleveragents:fix/agent-task-list-memory-leak
cleveragents:bugfix/m4-plan-diff-correction-stub
cleveragents:pr-9247
cleveragents:docs/timeline-update-2026-04-17
cleveragents:timeline/day-106-2026-04-17-auto-time-1
cleveragents:fix/quality-gates-click82-compat
cleveragents:auto-arch-14/spec-anonymous-tool-enforcement
cleveragents:fix/issue-6441-session-create-json-output
cleveragents:fix/issue-6331-invariant-add-scope
cleveragents:timeline/day-106-2026-04-16-auto-time-1-v2
cleveragents:spec/auto-arch-23-minor-clarifications
cleveragents:timeline/day-106-2026-04-16-auto-time-2
cleveragents:docs/auto-docs-2-v380-v390
cleveragents:timeline/day-104-2026-04-14-auto-time-1
cleveragents:bugfix/m3-actor-add-v3-schema-validation
cleveragents:timeline/day-106-2026-04-16-auto-time-1
cleveragents:auto-docs/changelog-architecture-readme
cleveragents:spec/auto-arch-21-v350-autonomy-hardening
cleveragents:chore/timeline-day-105-2026-04-15
cleveragents:docs/timeline-update-2026-04-15-auto-time-1
cleveragents:timeline/day-105-2026-04-15-auto-time-1
cleveragents:benchmark-ci
cleveragents:fix/plan-phase-migration-raw-sql-root-plan-id
cleveragents:auto-arch-12/spec-acms-context-tier-hydrator
cleveragents:timeline/day-106-2026-04-15-auto-time-1
cleveragents:feat/invariant-enforcement-strategize
cleveragents:feat/plan-tree-decision-rendering
cleveragents:feat/plan-correct-revert-append-modes
cleveragents:docs/auto-docs-4-fix-conflicts
cleveragents:docs/auto-docs-1-milestone-docs-v3.0.0-v3.1.0
cleveragents:feat/v3.4.0-acms-lifecycle-policy
cleveragents:pr-9220
cleveragents:fix/a2a-facade-optional-param-validation
cleveragents:feat/ci-guard-llm-secrets
cleveragents:pr-9214
cleveragents:feat/v3.3.0-subplan-status-tracking
cleveragents:feat/v3.3.0-merge-conflict-detection
cleveragents:uat/checkpoint-rollback-merge-tests
cleveragents:fix/pr-review-pool-supervisor-prefix-mismatch
cleveragents:feat/v3.3.0-spawn-subplan-step
cleveragents:auto-time-1-day103-cycle1-session6
cleveragents:feat/v3.8.0-agent-card-endpoint
cleveragents:docs/auto-docs-cycle-24-showcase-nav
cleveragents:auto-inf-3-consolidate-behave-fixtures
cleveragents:fix/issue-7663-docs-writer-missing
cleveragents:auto-time-1-day103-cycle2
cleveragents:docs/timeline-day-104-auto-time-1
cleveragents:auto-arch-16/spec-xml-prompt-injection-mitigation
cleveragents:bugfix/m4-invariant-persistence
cleveragents:uat-a2a-facade-tests-v350
cleveragents:bugfix/m3-behave-parallel-failed-chunk-logs
cleveragents:bugfix/7664-automation-tracking-label-requirements
cleveragents:docs/auto-time-1-timeline-update-2026-04-14
cleveragents:docs/auto-docs-1-milestone-v3-updates
cleveragents:fix/issue-6344-plan-execute-rich-output
cleveragents:docs/action-config-schema-api
cleveragents:fix/bug-hunt-supervisor-nonexistent-file-preflight
cleveragents:fix/retry-policy-model-missing-fields
cleveragents:docs/validation-gate-empty-run-guard
cleveragents:auto-arch-15/spec-retry-policy-canonical-fields
cleveragents:docs/lockservice-advisory-locking
cleveragents:docs/changelog-plan-fix-4197
cleveragents:spec/milestone-plan-section
cleveragents:docs/update-changelog-recent-features
cleveragents:fix/test-infra-remove-redundant-python-variable-robot-files
cleveragents:timeline/day-104-2026-04-14-cycle2
cleveragents:fix/bdd-feature-file-tags
cleveragents:auto-arch-13/spec-default-automation-profile
cleveragents:docs/auto-docs-cycle-1-2026-04-12
cleveragents:docs/cycle-1-git-worktree-sandbox
cleveragents:spec/architecture-critical-gap-fixes
cleveragents:docs/timeline-day-104-auto-time-2
cleveragents:auto-arch-1/add-v380-v390-milestone-plan
cleveragents:docs/developer-setup-guide
cleveragents:fix/auto-profile-spec-prose-description
cleveragents:auto-arch-10/spec-tui-a2a-integration-layer
cleveragents:spec/resource-event-types-clarification
cleveragents:auto-docs-4/changelog-and-observability
cleveragents:auto-arch-4/adr-049-layered-boundary-enforcement
cleveragents:docs/a2a-protocol-autonomy-hardening
cleveragents:auto-arch-9/spec-v3.8.0-milestone-plan
cleveragents:docs/auto-docs-3-reference-index
cleveragents:auto-arch-7/spec-apply-git-worktree
cleveragents:docs/timeline-day104-cycle1-auto-time-4
cleveragents:docs/auto-docs-cycle-1-changelog-updates
cleveragents:auto-arch-6/adr-049-spec-restructuring
cleveragents:docs/auto-docs-1-v340-acms-context-management
cleveragents:docs/auto-docs-1-v320-v330-cli-reference
cleveragents:auto-arch-5/v3.9.0-milestone-plan
cleveragents:test/create-scripts
cleveragents:auto-time-1-day104
cleveragents:timeline/day-104-2026-04-14
cleveragents:docs/auto-time-4-day103-cycle5
cleveragents:auto-time-3-day103-cycle4
cleveragents:auto-docs-5-architecture-overview
cleveragents:spec/three-way-merge-strategy-v3.3.0
cleveragents:spec/checkpoint-system-v3.3.0
cleveragents:auto-docs-4-api-docs-update
cleveragents:auto-docs-1-changelog-expansion
cleveragents:spec/invariant-management-system-v3.2.0
cleveragents:pr-8289
cleveragents:spec/plan-correction-engine-v3.2.0
cleveragents:spec/layered-architecture-boundary-policy
cleveragents:spec/tui-materializer-a2a-integration-v3.7.0
cleveragents:spec/decision-recording-system-v3.2.0
cleveragents:docs/auto-docs-1-milestone-overview
cleveragents:pr-7484
cleveragents:pr-4212
cleveragents:auto-arch-3/v3.8.0-milestone-plan
cleveragents:auto-docs-6/troubleshooting-and-config
cleveragents:auto-time-1-day103-session5
cleveragents:auto-docs-5/contributor-guide-and-readme
cleveragents:docs/plan-tree-ulid-examples
cleveragents:docs/m3-spec-clarify-path-datetime-plugin-contracts
cleveragents:docs/auto-docs-cycle-10-diagnostics-ref
cleveragents:auto-docs-3/user-guide-and-architecture
cleveragents:docs/cycle-7-changelog-update
cleveragents:spec/reconciliation-failure-behavior
cleveragents:auto-docs-2/api-documentation
cleveragents:auto-arch-2/adr-053-repositories-decomposition
cleveragents:auto-docs-1/release-notes-v3.0-v3.1
cleveragents:spec/update-validation-attach-project-delete
cleveragents:spec/architecture-cycle2-impl-clarifications
cleveragents:auto-arch-1/adr-049-052-violations
cleveragents:auto-time-1-day103
cleveragents:docs/auto-docs-cycle-13-updates
cleveragents:docs/timeline-day-102-auto-time
cleveragents:timeline/day-103-2026-04-13
cleveragents:spec/arch-invariant-cli-completeness
cleveragents:spec/update-cycle1-validation-attach-project-delete
cleveragents:docs/add-session-management-showcase
cleveragents:spec/arch-sandbox-path-correction-cycle9
cleveragents:spec/architecture-v380-milestone-plan
cleveragents:docs/auto-docs-cycle-12-updates
cleveragents:docs/cycle-1-validation-gate-fix
cleveragents:docs/2026-04-08-unreleased-changelog
cleveragents:docs/auto-docs-cycle-2-2026-04-10
cleveragents:docs/session-4615-2026-04-08-cycle1
cleveragents:feat/issue-6361-shell-safety-service-tui
cleveragents:spec/architecture-cycle-25-new-features
cleveragents:fix/issue-6345-automation-profile-add-output
cleveragents:docs/timeline-day-102-2026-04-12
cleveragents:docs/cycle-2-git-worktree-acms-hydrator
cleveragents:spec/arch-sandbox-cleanup-discovery
cleveragents:docs/timeline-day96-2026-04-08
cleveragents:docs/auto-docs-cycle-11
cleveragents:spec/fix-sandbox-strategy-protocol-name
cleveragents:spec/arch-acms-tier-hydration
cleveragents:fix/v3.4.0/context-settings-defaults
cleveragents:docs/add-example-repl-and-actor-run
cleveragents:docs/auto-docs-cycle-10-updates
cleveragents:docs/session-4-2026-04-08-updates
cleveragents:docs/showcase-all-examples-consolidated
cleveragents:docs/timeline-day-97
cleveragents:docs/acms-context-hydrator-cycle2
cleveragents:docs/add-example-output-format-flags
cleveragents:spec/arch-failfast-cancel-semantics
cleveragents:timeline/day-101-2026-04-11
cleveragents:docs/timeline-day99-2026-04-09-v2
cleveragents:docs/auto-docs-cycle-2-worktree-acms
cleveragents:spec/architecture-v3.8.0-milestone-plan
cleveragents:docs/api-lsp-acms-reference
cleveragents:improvement/agent-bug-hunt-pool-supervisor-yaml-syntax-fix
cleveragents:spec/project-delete-deleted-at-field
cleveragents:spec/architecture-provider-registry-tui-materializer
cleveragents:spec/document-reconciliation-blocked-error-5942
cleveragents:fix/issue-7482-git-log-injection
cleveragents:spec/devcontainer-auto-discovery-schema
cleveragents:feat/issue-6350-conversation-content-pruning
cleveragents:docs/update-module-guides-2026-04-10
cleveragents:timeline/day-100-2026-04-10-auto-time-cycle1
cleveragents:timeline/day-99-2026-04-09-auto-time-v2
cleveragents:docs/cycle-3-module-guides
cleveragents:timeline/day-99-2026-04-09-auto-time
cleveragents:pr-4226
cleveragents:spec/additional-llm-providers-gemini-groq-cohere-together-ollama-mistral
cleveragents:spec/document-context-tier-hydrator-6175
cleveragents:docs/timeline-day99-2026-04-09
cleveragents:spec/invariant-cli-clarifications
cleveragents:docs/add-example-project-init-and-context-management
cleveragents:spec/reconciliation-blocked-error-documentation
cleveragents:spec/fix-invariant-precedence-reference-5861
cleveragents:spec/fix-plan-correct-accepts-plan-id-5558
cleveragents:spec/fix-validation-attach-synopsis-5328
cleveragents:docs/timeline-day-99-cycle-1
cleveragents:docs/timeline-day-99-cycle-2
cleveragents:fix/actor-context-list-regex-arg
cleveragents:docs/timeline-day-99-cycle-3
cleveragents:spec/arch-security-mode-init
cleveragents:docs/auto-docs-cycle-9-updates
cleveragents:fix-resource-fix-resource-remove-to-check-correct-edge-table
cleveragents:feat/issue-6434-tui-env-var-expansion
cleveragents:fix/issue-6321-plan-prompt-timing-field
cleveragents:fix/issue-6322-resource-add-url-flag
cleveragents:feat/issue-6348-sessions-screen
cleveragents:spec/plan-show-command
cleveragents:temp
cleveragents:feat/harden-label-restrictions-1775753628
cleveragents:spec/invariant-reconciliation-failure-behavior
cleveragents:spec/add-reconciliation-failure-behavior-5942
cleveragents:spec/architecture-corrections-cycle3
cleveragents:spec/checkpoint-trigger-names-and-config-key-fix
cleveragents:spec/fix-ai-provider-interface-5801
cleveragents:spec/azure-api-version-default-update
cleveragents:docs/auto-docs-writer-cycle1-labels
cleveragents:spec/fix-resource-type-yaml-format-5622
cleveragents:spec/add-plan-revert-resume-commands-5574
cleveragents:docs/auto-docs-cycle-1-2026-04-09
cleveragents:spec/plan-correct-plan-id-or-decision-id-5558
cleveragents:spec/fix-subgraph-node-actor-ref-field-5427
cleveragents:issue/5284-master-ci-fix
cleveragents:timeline/day-99-2026-04-09-v2
cleveragents:merge-me
cleveragents:docs/session-3377-initial-docs-update
cleveragents:fix/llm-provider-subpackage-exports
cleveragents:spec/arce-acronym-and-tui-keybinding-fixes
cleveragents:spec/architecture-corrections-cycle2
cleveragents:spec/architecture-corrections-cycle1
cleveragents:docs/cycle-1-updates
cleveragents:spec/tui-clarifications-session-export-persona
cleveragents:docs/session-4940-2026-04-08-cycle1
cleveragents:spec/architecture-milestone-plan-v3.2-v3.7
cleveragents:docs/session-4743-2026-04-08-cycle1
cleveragents:docs/timeline-day-98
cleveragents:fix/plan-lifecycle-service-rollback-method
cleveragents:docs/timeline-day98-2026-04-08-v2
cleveragents:docs/add-example-action-and-plan-management
cleveragents:docs/session-2026-04-06-updates
cleveragents:docs/ca-docs-writer-v3.8.1-2026-04-05
cleveragents:fix/session-tell-stub-missing-panels-and-actor-execution
cleveragents:improvement/agent-arch-guard-clone-failure-handling
cleveragents:improvement/agent-test-infra-health-spam-fix-v2
cleveragents:fix-tdd-invert-non-assertion-exceptions
cleveragents:improvement/agent-arch-guard-clone-failure
cleveragents:bugfix/3472-fix-tdd-inversion-logic
cleveragents:bugfix/989-fix-persistence-json-decode-error
cleveragents:improvement/agent-supervisor-tracking-labels-v2
cleveragents:docs/timeline-day95-v2
cleveragents:docs/timeline-day95-final
cleveragents:docs/update-lsp-api-and-changelog
cleveragents:fix/lsp-resource-handler-module-missing
cleveragents:docs/timeline-day95-final-2026-04-05
cleveragents:fix/a2a-plan-correct-rollback-wiring
cleveragents:docs/add-lsp-api-and-changelog-2026-04-05
cleveragents:fix/tool-registry-validation-type-discriminator
cleveragents:docs/v3.7.0-documentation-update
cleveragents:docs/ca-docs-writer-2026-04-05-cycle2
cleveragents:fix/invariant-set-merge-action-scope
cleveragents:docs/unreleased-feature-docs
cleveragents:fix/concurrency-cost-tracker-record-usage-race-condition
cleveragents:improvement/agent-ca-test-infra-improver-failure-handling
cleveragents:docs/update-changelog-mcp-plan-ci-2026-04-05
cleveragents:improvement/agent-pr-reviewer-milestone-prioritization
cleveragents:docs/timeline-day95-refresh-2026-04-05
cleveragents:improvement/agent-mandatory-labels-tracking-issues
cleveragents:docs/api-domain-providers-changelog-2026-04-05
cleveragents:docs/ca-docs-writer-2026-04-05
cleveragents:docs/timeline-day95-refresh
cleveragents:fix/skill-add-include-validation
cleveragents:docs/timeline-day-95-2026-04-05-update3
cleveragents:docs/timeline-day-95-2026-04-05-update2
cleveragents:docs/ci-incident-runbook-2597
cleveragents:improvement/agent-ca-test-infra-improver-worker-api-mode
cleveragents:docs/shell-safety-api-and-readme-highlights
cleveragents:docs/timeline-day-55-2026-04-04-v2
cleveragents:docs/timeline-day-55-2026-04-04
cleveragents:docs/timeline-day54-update3
cleveragents:improvement/agent-ca-test-infra-improver-fixes
cleveragents:spec/restructure-monolithic-to-split
cleveragents:docs/timeline-day54-update-v2
cleveragents:docs/timeline-day54-update
cleveragents:fix-agents
cleveragents:docs/shell-safety-and-domain-base-model
cleveragents:fix/1452-impl
cleveragents:fix/1473-plan-cancel
cleveragents:fix/1425-test
cleveragents:fix/1426-config
cleveragents:fix/1421-perf
cleveragents:fix/1424-impl
cleveragents:test/int-wf16-devcontainer
cleveragents:feature/m8-tui-persona-export
cleveragents:feature/m7-post-resource-equivalence
cleveragents:test/e2e-m4-acceptance
cleveragents:feature/m6-tantivy-backend
cleveragents:feature/m6-estimation
cleveragents:feature/m6-estimation-report-model
cleveragents:feature/observability-prometheus-audit
cleveragents:feat/server-auth-namespace
cleveragents:feature/m8-session-editing
cleveragents:feature/llm-actor-subplan-wiring
cleveragents:feature/m8-tui-first-run-actor-selection
cleveragents:feature/m8-tui-conversation-block-catalog
cleveragents:feature/m8-tui-settings-screen
cleveragents:feature/m7-e2e-porting
cleveragents:feature/m6-estimation-historical-stats
cleveragents:feature/m8-tui-persona-export-import
cleveragents:feature/m8-tui-sessions-screen
cleveragents:feature/m7-graph-backend
cleveragents:feature/m8-tui-block-context-menu
cleveragents:feature/m8-tui-tool-call-expand
cleveragents:feature/m4-missing-builtin-tools
cleveragents:docs/v3.7.0-release-docs
cleveragents:feature/m8-tui-session-export
cleveragents:test/e2e-wf15-disaster-recovery
cleveragents:test/e2e-wf03-refactoring
cleveragents:test/e2e-m3-acceptance
cleveragents:feature/m8-tui-prompt-history
cleveragents:feature/m8-tui-actor-thought-block-rendering
cleveragents:bugfix/m6-build-hierarchy-child-ids
cleveragents:feature/resource-inheritance-wiring
cleveragents:test/e2e-wf09-session
cleveragents:test/e2e-wf06-doc-generation
cleveragents:test/e2e-wf08-cloud-infra
cleveragents:test/e2e-wf02-test-generation
cleveragents:test/e2e-wf13-custom-profile
cleveragents:test/e2e-wf11-graph-actor
cleveragents:test/e2e-wf01-hello-world
cleveragents:test/int-wf17-explicit-container
cleveragents:test/int-wf12-hierarchical
cleveragents:test/int-wf15-disaster-recovery
cleveragents:test/int-wf13-custom-profile
cleveragents:test/int-wf03-refactoring
cleveragents:test/int-wf11-graph-actor
cleveragents:test/int-wf10-batch
cleveragents:test/int-wf09-session
cleveragents:feature/m3-tdd-issue-consistency-gate
cleveragents:feature/m3-invariant-enforcement-strategize
cleveragents:test/int-wf18-container-clone
cleveragents:test/int-wf01-hello-world
cleveragents:feature/m6-diagnostic-dashboard-health-categories
cleveragents:feature/m6-cli-polish
cleveragents:fix/e2e-db-isolation
cleveragents:feature/m7-post-tui
cleveragents:feature/m9-asgi-endpoint
cleveragents:feature/m7-post-server
cleveragents:tdd/m7-audit-session-race
cleveragents:tdd/m3-skill-add-regression
cleveragents:feature/m9-remote-repos
cleveragents:feature/fs-mount-file-types
cleveragents:tdd/container-resolve-crash
cleveragents:test/e2e-m1-acceptance
cleveragents:test/e2e-m2-acceptance
cleveragents:eugen.thaci-patch-3
cleveragents:eugen.thaci-patch-2
cleveragents:eugen.thaci-patch-1
cleveragents:aditya-fix-latest
cleveragents:feature/m4-secret-masking-llm-context
cleveragents:aditya-fix
cleveragents:refactor/m3-replace-mktemp
cleveragents:refactor/m3-remove-unittest-mock-integration
cleveragents:refactor/m3-remove-robot-mock-imports
cleveragents:refactor/m3-remove-mock-llm-integration
cleveragents:docs/improved-menu-adr
cleveragents:feature/m7-post-auth
cleveragents:feature/m3-fix-resource-bootstrap
cleveragents:feature/post-safety-profile-tests
cleveragents:integration/batch-2026-03-02
cleveragents:feat/slipcover
cleveragents:docs/safety-profile-spec-composition
cleveragents:integrate/freemo-batch-1
cleveragents:feature/m4-error-recovery
cleveragents:feature/m4-security-template
cleveragents:feature/m3-validation-pipeline
cleveragents:develop-aditya-2
cleveragents:feature/m3-diff-review
cleveragents:feature/m3-validation-apply
cleveragents:feature/m6-acp-stubs
cleveragents:feature/m4-correction-flows
cleveragents:feature/m1-plan-execute-runtime
cleveragents:feature/m4-security-exceptions
cleveragents:feature/m4-definition-of-done
cleveragents:feature/m4-correction-model
cleveragents:feature/m1-apply-pipeline
cleveragents:feature/m5-automation-profiles
cleveragents:feature/m2-lsp-stubs
cleveragents:feature/m3-invariants
cleveragents:feature/m1-actor-runtime
cleveragents:feature/docs-v2-restore
cleveragents:feature/m6-perf-scale
cleveragents:feature/m6-validation-edge
cleveragents:feature/m3-session-cli
cleveragents:feature/m1-persistence-tests-robot
cleveragents:feature/m3-config-cli
cleveragents:feature/m1-cli-tests-robot
cleveragents:feature/m5-subplan-tests
cleveragents:feature/m6-review-playbook
cleveragents:feature/aditya-m3-actor-loader
cleveragents:feature/m3-skill-protocol
cleveragents:feature/m4-automation-legacy-cleanup
cleveragents:feature/m3-change-model
cleveragents:feature/m3-skill-git
cleveragents:feature/m3-skill-registry
cleveragents:feature/m4-security-eval
cleveragents:fix/robot-tests
cleveragents:feature/m3-actor-registry
cleveragents:feature/m3-tool-cli
cleveragents:feature/m4-automation-profiles-cli
cleveragents:feature/m2-resource-cli-extensions
cleveragents:feature/m3-actor-loader
cleveragents:feature/m3-tool-domain-robot
cleveragents:feature/m3-skill-domain-robot
cleveragents:feature/m3-skill-cli
cleveragents:feature/m1-resource-db-robot-tests
cleveragents:feature/m3-session-domain-robot
cleveragents:feature/m1-persistence-tests
cleveragents:feature/m1-cli-tests
cleveragents:ten-branches-backup
cleveragents:feature/m3-skill-schema
cleveragents:feature/m3-session-persistence
cleveragents:feature/automation-profiles-and-resource-dag
cleveragents:feature/m1-plan-repo
cleveragents:feature/m1-db-plan-phase-rebaseline
cleveragents:feat/B4-sandbox
cleveragents:feat/B2-cli-wiring
cleveragents:feat/B5-project-persistence
cleveragents:feat/B1-project-data-models
cleveragents:feat/b1-data-models
cleveragents:feat-repo-manager-and-sourcegraph-support
cleveragents:feat/actor-schema
cleveragents:fix/component-isolation-security-fix
cleveragents:feat/ontology-agent
cleveragents:fix/error-handling-security-fix
cleveragents:fix/concurrency-security-fix
cleveragents:fix/serialization-security-fix
cleveragents:fix/server-side-request-forgery-security-fix
cleveragents:fix/file-system-security
cleveragents:fix/template-injection-fix
cleveragents:fix/data-injection-fix
cleveragents:tests/unit-tests
cleveragents:latest/poetry-generator
cleveragents:poetry-generator
cleveragents:config/contract-metadata-extractor
cleveragents:docs/readme-yaml-syntax
cleveragents:config/memory-yaml
cleveragents:fix/double-response
cleveragents:brent-additions
cleveragents:intel_2_demo
No reviewers
Labels
Clear labels
auto/needs-reevaluation
Controller deferred this PR; awaiting Phase 6+ scope-evaluator or operator re-enablement.
controller-managed
Auto-agents controller manages this PR/issue (see tools/controller/deploy/RUNBOOK.md). Remove this label to abandon controller management.
auto/blocked-by-deps
PR blocked by an open issue dependency. Operator must close the dep (or remove the dependency link) before the merge driver can act. Auto-cleared by merge_drive when no open deps remain.
auto/ci-timeout
Most recent merge cycle hit CI timeout. Driver excludes this PR while last merge_cycle row is < 30 min old; label persists thereafter as visible history.
auto/claimed-implementer
Currently being processed by an implementer worker.
auto/claimed-merge
Currently being processed by the merge driver.
auto/claimed-reviewer
Currently being processed by a reviewer worker.
auto/driver-down
Merge driver heartbeat stale; pipeline halted. Closed automatically on next clean tick.
auto/invariant-violation
Detected master commit violating the strict merge invariant. Tracked as an issue (not a PR label); kept here for label completeness.
auto/last-attempt-tier-0
In-cycle escalation: most recent attempt ran at the Tier 0 slot (`tier-0`). Slot's model defined in .opencode/models/tiers.yaml.
auto/last-attempt-tier-1
In-cycle escalation: most recent attempt ran at the Tier 1 slot (`tier-1`). Slot's model defined in .opencode/models/tiers.yaml.
auto/last-attempt-tier-2
In-cycle escalation: most recent attempt ran at the Tier 2 slot (`tier-2`). Slot's model defined in .opencode/models/tiers.yaml. Gated behind IMPLEMENTER_ESCALATION_TIER2_ENABLED.
auto/last-attempt-tier-min
In-cycle escalation: most recent attempt ran at the Tier -1 slot (`tier-min`). Slot's model defined in .opencode/models/tiers.yaml. Suffix is ``-min`` (not ``--1``) so the Forgejo UI reads naturally.
Automation Tracking
Tracking issues used by the AI Automation system for agents to communicate and report.
auto/needs-conflict-resolution
Rebase conflict needs LLM conflict-resolver.
auto/needs-implementer
Failing CI needs implementer attention.
auto/postmortem
Documenting a driver incident or rollback.
auto/ready-to-merge
Reviewer has APPROVED this PR and no later REQUEST_CHANGES is outstanding. The merge driver requires this label to even consider a PR for merging. Set by the reviewer worker on APPROVE; cleared on REQUEST_CHANGES.
auto/restart-throttled
Train repeatedly lost master-tempo races. Driver excludes via merge_cycle until cooldown elapses; label persists as visible history.
auto/revert
Revert PR backing out an invariant violation. Fast-tracked through the merge driver.
auto/sentinel
Sentinel PR duplicated from upstream into a personal fork by tools/duplicate_prs_to_fork.py for pipeline testing. Lives only in the fork; the canonical pipeline never sees it.
auto/stale-inactivity
No implementer activity for N days. Flagged for human review. Auto-cleared on next push to head branch.
auto/unstable
Repeatedly fails on current master (>= 3 ci-fail-on-rebased-sha releases in 12 h). Excluded from driver until human triage.
Blocked
A ticket in a blocked state and unable to complete until some other task is completed first.
Bounty
$100
A bounty of $100 for any open-source contributor who provides a MR that solves this issue
Bounty
$1000
A bounty of $1000 for any open-source contributor who provides a MR that solves this issue
Bounty
$10000
A bounty of $10000 for any open-source contributor who provides a MR that solves this issue
Bounty
$20
A bounty of $20 for any open-source contributor who provides a MR that solves this issue
Bounty
$2000
A bounty of $2000 for any open-source contributor who provides a MR that solves this issue
Bounty
$250
A bounty of $250 for any open-source contributor who provides a MR that solves this issue
Bounty
$50
A bounty of $50 for any open-source contributor who provides a MR that solves this issue
Bounty
$500
A bounty of $500 for any open-source contributor who provides a MR that solves this issue
Bounty
$5000
A bounty of $5000 for any open-source contributor who provides a MR that solves this issue
Bounty
$750
A bounty of $750 for any open-source contributor who provides a MR that solves this issue
MoSCoW
Could have
Could have feature in order to satisfy the epic/legendary.
MoSCoW
Must have
Must have feature in order to satisfy the epic/legendary.
MoSCoW
Should have
Should have feature in order to satisfy the epic/legendary.
Needs Feedback
There are questions in the ticket that can not be completed until the project owner provides clarity.
Points
1
1 man-hours worth of work for an expert with no learning curve.
Points
13
13 man-hours worth of work for an expert with no learning curve.
Points
2
2 man-hours worth of work for an expert with no learning curve.
Points
21
21 man-hours worth of work for an expert with no learning curve.
Points
3
3 man-hours worth of work for an expert with no learning curve.
Points
34
34 man-hours worth of work for an expert with no learning curve.
Points
5
5 man-hours worth of work for an expert with no learning curve.
Points
55
55 man-hours worth of work for an expert with no learning curve.
Points
8
8 man-hours worth of work for an expert with no learning curve.
Points
88
88 man-hours worth of work for an expert with no learning curve.
Priority
Backlog
This ticket has backlogged priority and is not to be worked on yet
Priority
CI Blocker
Critical priority issue that blocks CI/CD pipeline and prevents PR merges
Priority
Critical
The priority is critical
Priority
High
The priority is high
Priority
Low
The priority is low
Priority
Medium
The priority is medium
Signed-off: Owner
When an epic or legendary is in review it must be signed off by owner, tech lead, and scrum master before being marked as completed.
Signed-off: Scrum Master
When an epic or legendary is in review it must be signed off by owner, tech lead, and scrum master before being marked as completed.
Signed-off: Tech Lead
When an epic or legendary is in review it must be signed off by owner, tech lead, and scrum master before being marked as completed.
Spike
A ticket for learning a tool or technology that is needed to be able to do future planning and design.
State
Completed
The ticket has been fully implemented, completed, and merged with the source code. This label should only be applied once a ticket is closed.
State
Duplicate
A ticket that represents the same content as an existing ticket.
State
In Progress
A ticket that is actively being developed.
State
In Review
A ticket that has had some code completed to implement but is waiting to pass peer review and is not yet merged in.
State
Paused
This ticket's work started but wasn't finished. It's on hold (likely in a feature branch) and will be resumed later, either due to a blocker or a delay.
State
Unverified
All new tickets start in this state. A developer may set it to show the ticket is unverified. This means we haven't agreed to work on it. It will either move to a verified state or be closed as wontdo.
State
Verified
The issue has been verified by a developer as legitimate. It will be worked on and verified tickets are now considered part of the backlog.
State
Wont Do
This ticket has been decided it wont be done. This may mean the bug has been determined to not be real (cant verify) or the feature is one we have decided we dont want to adopt.
Type
Automation
Any edits or discussion about the AI automated coding system.
Type
Bug
Something that doesnt work as intended.
Type
Discussion
Anytime a ticket represents a discussion about a subject and doesnt fall into one of the other categories.
Type
Documentation
An error or improvement needed in the documentation.
Type
Epic
Any first tier epic. That is, an epic which contains only issues as children and will not have sub-epics.
Type
Feature
Some new functionality not present.
Type
Legendary
A type of Epic which will contain other Epics.
Type
Refactor
A code change that restructures existing code without changing its external behavior.
Type
Support
Someone needs help using the project.
Type
Task
A generic task that doesnt fit into the other type categories.
Type
Testing
Work exclusively focusing on fixing or expanding testing.
No labels
auto/needs-reevaluation
controller-managed
auto/blocked-by-deps
auto/ci-timeout
auto/claimed-implementer
auto/claimed-merge
auto/claimed-reviewer
auto/driver-down
auto/invariant-violation
auto/last-attempt-tier-0
auto/last-attempt-tier-1
auto/last-attempt-tier-2
auto/last-attempt-tier-min
Automation Tracking
auto/needs-conflict-resolution
auto/needs-implementer
auto/postmortem
auto/ready-to-merge
auto/restart-throttled
auto/revert
auto/sentinel
auto/stale-inactivity
auto/unstable
Blocked
Bounty
$100
Bounty
$1000
Bounty
$10000
Bounty
$20
Bounty
$2000
Bounty
$250
Bounty
$50
Bounty
$500
Bounty
$5000
Bounty
$750
MoSCoW
Could have
MoSCoW
Must have
MoSCoW
Should have
Needs Feedback
Points
1
Points
13
Points
2
Points
21
Points
3
Points
34
Points
5
Points
55
Points
8
Points
88
Priority
Backlog
Priority
CI Blocker
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Signed-off: Owner
Signed-off: Scrum Master
Signed-off: Tech Lead
Spike
State
Completed
State
Duplicate
State
In Progress
State
In Review
State
Paused
State
Unverified
State
Verified
State
Wont Do
Type
Automation
Type
Bug
Type
Discussion
Type
Documentation
Type
Epic
Type
Feature
Type
Legendary
Type
Refactor
Type
Support
Type
Task
Type
Testing
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".
No due date set.
Blocks
#5169 EPIC: Large Project Indexing — 10,000+ File Codebase Support (ACMS v3.4.0)
cleveragents/cleveragents-core
Reference
cleveragents/cleveragents-core!5271
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/v3.4.0/acms-project-indexer"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Background
Part of Epic #5169 (Large Project Indexing). Implements the
ProjectIndexerservice that scans project directories asynchronously and builds a searchable index of all files, supporting incremental updates when files change.Implementation Details
ProjectIndexer service (
src/cleveragents/application/services/project_indexer.py)asyncio.gather.git,venv,__pycache__, etc.)ProjectIndexStoreadapter (project_indexer_persistence.py)Domain Model (
src/cleveragents/domain/models/core/project_index.py)ProjectIndexSnapshotmodel with ULID identificationTests
features/project_indexer.featuretype|step definitions in
features/steps/project_indexer_steps.pyrobot/project_indexer.robot+ helperrobot/helper_project_indexer.pyCI Quality Gates
Compliance Checklist
ISSUES CLOSED: #5237Closes #5237
🔍 Code Review — PR #5271 (pr-self-reviewer)
Reviewed with special focus on architecture-alignment, module-boundaries, and interface-contracts.
The implementation is well-structured and the core async scanning logic is solid. However, there are several issues that must be addressed before merge — including CONTRIBUTING.md violations, an architecture boundary problem, a concurrency correctness bug, and a semantic data bug.
Required Changes
1. [CONTRIBUTING.md] Missing Robot Framework Integration Tests
Location: PR as a whole — no
robot/files addedRule: CONTRIBUTING.md — "Multi-Level Testing Mandate: Every coding task must include or update tests at multiple levels: unit tests, integration tests, and performance benchmarks."
The PR includes only Behave unit tests. There are no Robot Framework integration tests and no ASV performance benchmarks. Both are mandatory per CONTRIBUTING.md.
Required:
robot/that exercisesProjectIndexerend-to-end (e.g., scan a real directory, verify the SQLite database is created, verify incremental refresh)benchmarks/for thescan()method on a large synthetic directory (the issue specifically calls out 10,000+ file support)2. [ARCHITECTURE]
IndexStatusCross-Domain CouplingLocation:
src/cleveragents/domain/models/core/project_index.pyandsrc/cleveragents/application/services/project_indexer.pyIndexStatusis defined inrepo_index.py, which belongs to the repository resource indexing subsystem (ULID-keyed resources,token_count,languagedetection, etc.). TheProjectIndexeris a distinct ACMS subsystem for project directory scanning. ImportingIndexStatusfrom the repo indexing domain creates an inappropriate coupling between two separate bounded contexts.Additionally,
ProjectIndexeronly ever setsIndexStatus.READY— thePENDING,INDEXING,STALE, andERRORstates from the repo indexing lifecycle are never used, which signals the enum is not the right fit for this domain.Required: Define a
ProjectIndexStatusenum inproject_index.pythat reflects the actual lifecycle of a project scan. At minimum:READYandERROR. Do not import fromrepo_index.py.3. [BUG]
load_snapshotOpens Connection Without WAL PragmasLocation:
src/cleveragents/application/services/project_indexer.py—load_snapshotmethod_open_databasecorrectly setsPRAGMA journal_mode = WALandPRAGMA synchronous = NORMAL, which are essential for concurrent read/write access.load_snapshotbypasses_open_databaseand opens a raw connection, losing these settings. In WAL mode, readers and writers can coexist; without it, a concurrentscan()call can blockload_snapshot()— a real concurrency hazard for the 10k+ file use case.Required: Replace
sqlite3.connect(db_path)inload_snapshotwith a call toself._open_database(project_id), or extract a_open_readonly_connectionhelper that applies the same pragmas.4. [BUG]
_load_existingStores Relative Path asabsolute_pathLocation:
src/cleveragents/application/services/project_indexer.py—_load_existingmethodpathis the relative path stored in the database (e.g.,src/app.py). Assigning it toabsolute_pathcreates a_FileStatwhereabsolute_pathis not absolute. While the current code paths that consume loaded records happen not to useabsolute_path, this is a semantic invariant violation that will cause subtle bugs if anyone later usesabsolute_pathfrom a loaded record (e.g., to re-hash a file for a stale-check feature).Required: Either store the project root and reconstruct the absolute path correctly, or make
absolute_pathOptional[Path]and set it toNonefor records loaded from the database.5. [CONTRIBUTING.md] Insufficient Test Coverage
Location:
features/project_indexer.featureThe single scenario covers the happy path well, but the following behaviors are untested:
load_snapshot— the publicload_snapshot()method has zero test coveragescan()with a non-existent path, a file instead of a directory, and an emptyproject_idare not testedexclude_patternsparameter is not exercisedProjectIndexer(concurrency=0)raisingValueErroris not testedRequired: Add Behave scenarios for at least
load_snapshot, the threescan()error cases, and custom exclusion patterns.6. [PR METADATA] Missing Milestone
Location: PR #5271 metadata
The linked issue #5237 is assigned to milestone v3.4.0, but the PR itself has no milestone set. This breaks milestone tracking.
Required: Set the PR milestone to
v3.4.0.Architecture Deep-Dive (Focus Area)
Module Boundary: Direct SQLite in Application Service
The
ProjectIndexerservice directly manages SQLite connections, schema DDL, and raw SQL queries. In the project's layered architecture, the application service layer is expected to depend on repository abstractions, not concrete persistence implementations. This is flagged as a design concern — the raw SQL embedded in the service makes it harder to test in isolation and harder to swap the persistence backend. Consider extracting aProjectIndexRepositoryprotocol with aSqliteProjectIndexRepositoryimplementation, even if only one implementation exists today.Interface Contract:
scan()Status LifecycleThe
scan()method always returns a snapshot withstatus=IndexStatus.READY. There is no way for callers to observe theINDEXINGstate during a long scan. For the 10k+ file use case, callers may want to poll status. This is acceptable for the current synchronous-await pattern but worth noting as a future interface gap.Good Aspects
asyncio.to_thread+ semaphore-bounded hashing is well-designedmtime+sizebefore hashing is efficient_collect_file_statscorrectly prunes excluded directories in-place viaos.walk_should_excludehandles glob patterns, directory prefixes, and path segments correctlyProjectFileMetadatavalidator correctly rejects absolute paths and..traversalProjectIndexSnapshotcross-validatesfile_countandtotal_bytesagainst the files tuple# type: ignoresuppressionsISSUES CLOSEDfooterCloses #5237closing keyword present in PR bodyType/Featurelabel appliedDecision: REQUEST CHANGES 🔄
Blocking issues: missing integration tests and benchmarks (CONTRIBUTING.md mandate),
IndexStatuscross-domain coupling (architecture),load_snapshotconcurrency bug,_load_existingsemantic bug, and insufficient test coverage. PR milestone must also be set.Automated by CleverAgents Bot
Supervisor: PR Review | Agent: pr-self-reviewer
🔍 Code Review — PR #5271 (pr-self-reviewer, second pass)
Reviewed with special focus on api-consistency, naming-conventions, and code-patterns.
This is an independent review. The previous review comment covered architecture and bug concerns. This review confirms several of those findings and adds new observations specific to the assigned focus areas.
The core async scanning logic is well-designed and the domain models are clean. However, there are several issues that must be addressed before merge.
Required Changes
1. [API-CONSISTENCY]
IndexStatusImported from Wrong Bounded ContextLocation:
src/cleveragents/domain/models/core/project_index.py(line 11) andsrc/cleveragents/application/services/project_indexer.py(line 26)IndexStatusbelongs to the repository resource indexing subsystem (repo_index.py), which is a ULID-keyed, token-counting, language-detecting domain.ProjectIndexeris a separate ACMS subsystem for project directory scanning. Sharing the enum creates a false API contract:ProjectIndexeronly ever producesIndexStatus.READY— thePENDING,INDEXING,STALE, andERRORstates from the repo lifecycle are never used and are semantically meaningless in this context.This is an API consistency violation: the public return type
ProjectIndexMetadata.statusadvertises a richer lifecycle than the service actually implements, misleading consumers.Required: Define a
ProjectIndexStatus(StrEnum)inproject_index.pywith the states thatProjectIndexeractually uses (at minimumREADY; addERRORfor future use). Remove the import fromrepo_index.pyin both files.2. [NAMING-CONVENTIONS] British vs. American English Inconsistency
Location:
src/cleveragents/application/services/project_indexer.pyThe codebase uses American English throughout (e.g.,
normalize_change_path,serialized,initialized). This PR introduces British spellings in two private method names:The method names use the British spelling
materialise. The rest of the codebase consistently uses American English (normalize,serialize,initialize). This breaks naming convention consistency.Required: Rename both methods to
_materialize_fileand_materialize_hashed(American English), and update all call sites within the same file (there are 3 call sites inscan()and 1 inload_snapshot()).3. [CODE-PATTERNS]
load_snapshotBypasses_open_database— Missing WAL PragmasLocation:
src/cleveragents/application/services/project_indexer.py—load_snapshotmethodThe established pattern in this class is to open all database connections via
_open_database(), which appliesPRAGMA journal_mode = WALandPRAGMA synchronous = NORMAL.load_snapshotdeviates from this pattern by callingsqlite3.connect()directly, losing the WAL settings. This is both a code pattern violation (inconsistent with the rest of the class) and a correctness issue (concurrentscan()+load_snapshot()calls may block each other without WAL mode).Required: Replace
sqlite3.connect(db_path)inload_snapshotwithself._open_database(project_id). This is a one-line fix that restores consistency with the established pattern.4. [CODE-PATTERNS]
_load_existingAssigns Relative Path toabsolute_pathFieldLocation:
src/cleveragents/application/services/project_indexer.py—_load_existingmethodThe
_FileStatdataclass has a field namedabsolute_path: Path. The established pattern in_collect_file_statsalways setsabsolute_pathto the resolved filesystem path (e.g.,/tmp/project/src/app.py). In_load_existing, the database stores only the relative path, soPath(path)produces a relativePathobject — violating the semantic invariant of the field name.While current code paths that consume loaded records happen not to use
absolute_pathdirectly (they call_materialise_filewhich only readsrelative_path,size_bytes,modified_epoch, andcontent_hash), this is a latent bug waiting to surface. Any future code that readsabsolute_pathfrom a loaded record will silently get a relative path.Required: Either (a) store the project root in the indexer and reconstruct the absolute path on load, or (b) make
absolute_pathOptional[Path]with a default ofNoneand set it toNonefor DB-loaded records. Option (b) is simpler and makes the optionality explicit.5. [API-CONSISTENCY]
_database_pathSanitises Only/and\— InsufficientLocation:
src/cleveragents/application/services/project_indexer.py—_database_pathmethodThe sanitisation replaces only
/and\. Aproject_idlike../../../etc/passwdwould producesafe_id = "......etcpasswd"after replacement — the..segments are not stripped. While_index_diris already resolved to an absolute path (so path traversal is not a security risk here), the resulting filename......etcpasswd.dbis unexpected and could cause confusion. Additionally, thescan()method validates thatproject_idis non-empty but does not validate its content, creating an inconsistency between the two methods.Required: Either (a) add validation in
scan()to rejectproject_idvalues containing path-separator characters and dots-only segments, or (b) document the accepted character set forproject_idin the docstring. At minimum, the inconsistency betweenscan()validating emptiness but not content should be resolved.6. [PR METADATA] Missing Milestone
Location: PR #5271 metadata
The linked issue #5237 is assigned to milestone v3.4.0, but the PR itself has no milestone set. Per project conventions, PRs must be linked to the same milestone as their issue for milestone tracking to work.
Required: Set the PR milestone to
v3.4.0.7. [CONTRIBUTING.md] Missing Robot Framework Integration Tests
Location: PR as a whole — no
robot/files addedPer project rules: "Unit tests use Behave in
features/. Integration tests use Robot Framework inrobot/." The PR adds only Behave unit tests. No Robot Framework integration tests are present.Required: Add at least one Robot Framework test suite under
robot/that exercisesProjectIndexerend-to-end (e.g., scan a real temp directory, verify the SQLite database is created and contains the expected rows, verify incremental refresh produceschanged_files=0on a second scan).8. [TEST COVERAGE]
load_snapshotHas Zero Test CoverageLocation:
features/project_indexer.featureThe public
load_snapshot()method is completely untested. It is the primary read path for consumers of the index and has a distinct code path fromscan()(including the WAL bug noted in item 3 above).Required: Add a Behave scenario that calls
load_snapshot()after ascan()and verifies the returned snapshot matches the scan result. Also add a scenario forload_snapshot()when no database exists (should returnNone).Architecture Observation (Non-Blocking)
Direct SQLite in Application Service
ProjectIndexerdirectly manages SQLite connections, DDL, and raw SQL. The project's layered architecture expects application services to depend on repository abstractions. This makes the service harder to test in isolation and harder to swap the persistence backend. Consider extracting aProjectIndexRepositoryprotocol as a follow-up issue — not a blocker for this PR.Good Aspects
asyncio.to_thread+ semaphore-bounded hashing is well-designed for the 10k+ file use casemtime+sizebefore hashing is efficient (avoids redundant I/O)_collect_file_statscorrectly prunes excluded directories in-place viaos.walkmutation_should_excludehandles glob patterns, directory prefixes, and path segments correctlyProjectFileMetadatavalidator correctly rejects absolute paths and..traversalProjectIndexSnapshotcross-validatesfile_countandtotal_bytesagainst the files tuple# type: ignoresuppressions anywhere in the PRISSUES CLOSEDfooterCloses #5237closing keyword present in PR bodyType/Featurelabel appliedProjectIndexerandDEFAULT_EXCLUDE_PATTERNScorrectly exported via__all__and the lazy-import__init__.py__init__.pytempfile.TemporaryDirectoryfor proper test isolation — no shared filesystem stateasyncio.run()used correctly in Behave stepsSummary of Blocking Issues
IndexStatuscross-domain coupling_materialise_*British spellingload_snapshotbypasses_open_database_load_existingassigns relative path toabsolute_path_database_pathinsufficient sanitisationload_snapshothas zero test coverageDecision: REQUEST CHANGES 🔄
Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-self-reviewer
🔍 Code Review — PR #5271 (Third Pass, pr-self-reviewer)
I have read the full source of
project_indexer.py,project_index.py, andfeatures/project_indexer.featuredirectly from the branch. The commit SHA is still29d4db27— none of the blocking issues identified in the two prior review comments have been addressed. All findings from those reviews are confirmed present and are re-stated below for completeness, with two new observations added.Required Changes
1. [API-CONSISTENCY]
IndexStatusImported from Wrong Bounded ContextLocation:
src/cleveragents/domain/models/core/project_index.py:11andsrc/cleveragents/application/services/project_indexer.py:26IndexStatusbelongs to the repository resource indexing subsystem (repo_index.py) — a ULID-keyed, token-counting, language-detecting domain.ProjectIndexeris a separate ACMS subsystem for project directory scanning. Sharing the enum creates a false API contract:ProjectIndexeronly ever producesIndexStatus.READY; thePENDING,INDEXING,STALE, andERRORstates from the repo lifecycle are semantically meaningless here and are never used.This is an API consistency violation:
ProjectIndexMetadata.statusadvertises a richer lifecycle than the service implements, misleading consumers.Required: Define
ProjectIndexStatus(StrEnum)inproject_index.pywith the statesProjectIndexeractually uses (at minimumREADY; addERRORfor future use). Remove therepo_indeximport from both files. AddProjectIndexStatusto__all__inproject_index.py.2. [NAMING-CONVENTIONS] British English in Method Names and Docstrings
Location:
src/cleveragents/application/services/project_indexer.pyThe codebase uses American English throughout. This PR introduces British spellings in multiple places:
Required:
_materialise_file→_materialize_fileand_materialise_hashed→_materialize_hashedscan(), 1 inload_snapshot())optimised→optimized,Initialise→Initialize3. [CODE-PATTERNS]
load_snapshotBypasses_open_database— Missing WAL PragmasLocation:
src/cleveragents/application/services/project_indexer.py—load_snapshotmethodThe established pattern in this class is to open all database connections via
_open_database(), which appliesPRAGMA journal_mode = WALandPRAGMA synchronous = NORMAL.load_snapshotdeviates by callingsqlite3.connect()directly, losing WAL settings. This is both a code pattern violation and a correctness issue: concurrentscan()+load_snapshot()calls may block each other without WAL mode — a real hazard for the 10k+ file use case.Required: Replace
sqlite3.connect(db_path)withself._open_database(project_id). One-line fix.4. [CODE-PATTERNS]
_load_existingAssigns Relative Path toabsolute_pathFieldLocation:
src/cleveragents/application/services/project_indexer.py—_load_existingmethodThe
_FileStatdataclass field is namedabsolute_path: Path. The established pattern in_collect_file_statsalways setsabsolute_pathto the resolved filesystem path. Here,Path(path)produces a relativePathobject — violating the semantic invariant of the field name. Any future code readingabsolute_pathfrom a DB-loaded record will silently get a relative path.Required: Either (a) store the project root and reconstruct the absolute path on load, or (b) make
absolute_path: Path | Nonewith a default ofNoneand set it toNonefor DB-loaded records. Option (b) is simpler and makes the optionality explicit.5. [API-CONSISTENCY]
load_snapshotDoes Not Validateproject_id⭐ NEWLocation:
src/cleveragents/application/services/project_indexer.py—load_snapshotmethodscan()validates thatproject_idis non-empty:load_snapshot()has no such validation. Callingload_snapshot("")constructs a path like<index_dir>/.dband silently returnsNoneif it doesn't exist. This is an API inconsistency — the two public methods have different validation behavior for the same parameter.Required: Add the same
project_idemptiness check toload_snapshot()as exists inscan().6. [API-CONSISTENCY]
_database_pathSanitises Only/and\— InsufficientLocation:
src/cleveragents/application/services/project_indexer.py—_database_pathmethodA
project_idlike../../../etc/passwdproducessafe_id = "......etcpasswd"— the..segments are not stripped. The sanitization is also inconsistent with the emptiness check inscan()(which validates content but not character set).Required: Either (a) add validation in
scan()to rejectproject_idvalues containing path-separator characters or dots-only segments, or (b) use stricter sanitization (e.g., replace any character that is not alphanumeric,-, or_). Document the accepted character set in the docstring.7. [PR METADATA] Missing Milestone
Location: PR #5271 metadata
The linked issue #5237 is assigned to milestone v3.4.0, but the PR itself has no milestone set. Per CONTRIBUTING.md: "Every PR must be assigned to the same milestone as its linked issue."
Required: Set the PR milestone to
v3.4.0.8. [CONTRIBUTING.md] Missing Robot Framework Integration Tests
Location: PR as a whole — no
robot/files addedPer CONTRIBUTING.md: "Integration tests use Robot Framework in
robot/." The PR adds only Behave unit tests. No Robot Framework integration tests are present.Required: Add at least one Robot Framework test suite under
robot/that exercisesProjectIndexerend-to-end (e.g., scan a real temp directory, verify the SQLite database is created and contains the expected rows, verify incremental refresh produceschanged_files=0on a second scan).9. [TEST COVERAGE]
load_snapshotHas Zero Test CoverageLocation:
features/project_indexer.featureThe public
load_snapshot()method is completely untested. It is the primary read path for consumers of the index and has a distinct code path fromscan()(including the WAL bug noted in item 3 above).Required: Add Behave scenarios for:
load_snapshot()after ascan()— verify the returned snapshot matches the scan resultload_snapshot()when no database exists — verify it returnsNoneload_snapshot("")— verify it raisesValueError(once item 5 is fixed)10. [COMMIT FORMAT] Commit Body Contains Literal
\nEscape Sequences ⭐ NEWLocation: Commit
29d4db27message bodyThe commit message body contains literal
\nand\\ncharacter sequences instead of actual newlines:This renders as a single run-on line in
git logand violates the Conventional Changelog format requirement for a properly formatted multi-line body. TheISSUES CLOSED: #5237footer must appear on its own line after a blank line.Required: Amend the commit to use actual newlines in the body.
Confirmed Good Aspects
asyncio.to_thread+ semaphore-bounded hashing is well-designed for 10k+ filesmtime+sizebefore hashing avoids redundant I/O_collect_file_statscorrectly prunes excluded directories in-place viaos.walkmutation_should_excludehandles glob patterns, directory prefixes, and path segments correctlyProjectFileMetadatavalidator correctly rejects absolute paths and..traversalProjectIndexSnapshotcross-validatesfile_countandtotal_bytesagainst the files tuple# type: ignoresuppressions anywhere in the PRCloses #5237closing keyword present in PR bodyType/Featurelabel appliedtempfile.TemporaryDirectory— no shared filesystem state (deterministic tests)_persistuses explicitconn.commit()for atomic writesSummary of Blocking Issues
IndexStatuscross-domain coupling_materialise_*British spelling + docstringsload_snapshotbypasses_open_database_load_existingassigns relative path toabsolute_pathload_snapshotmissingproject_idvalidation_database_pathinsufficient sanitizationload_snapshothas zero test coverage\nin commit bodyDecision: REQUEST CHANGES 🔄
The code has not been updated since the two prior review comments. All previously identified blocking issues remain unresolved. Please address all items in the table above before requesting re-review.
Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-self-reviewer
🔍 Code Review — PR #5271 (Fourth Pass, pr-self-reviewer)
I have read the full source of
project_indexer.py,project_index.py,features/project_indexer.feature, andfeatures/steps/project_indexer_steps.pydirectly from the branch. This review brings a new perspective focused exclusively on resource lifecycle, connection management, and cleanup correctness — areas not yet covered in depth by the prior three reviews.CI Status: ❌ FAILING
CI run
#12315reports 2 required jobs failing:lintRUF022(__all__not sorted) inproject_indexer.py:42anddomain/models/core/__init__.py:328integration_testsstatus-checklintandintegration_testsfailedThe
lintfailure atproject_indexer.py:42is directly caused by this PR and must be fixed before merge.Required Changes
1. [RESOURCE LEAK]
_hash_pending— Tasks Not Cancelled on Exception ⭐ NEWLocation:
src/cleveragents/application/services/project_indexer.py—_hash_pendingmethodProblem:
asyncio.as_completedreturns an iterator of futures. If anyawait cororaises (e.g.,PermissionErrorreading a file, orasyncio.CancelledError), the loop exits immediately. The remaining coroutines intasksare never awaited — Python logsRuntimeWarning: coroutine '_compute' was never awaited. More critically, anyasyncio.to_threadcalls already dispatched to the thread pool continue running in the background with no way to cancel them, holding file handles open until the thread pool cleans up.Required: Use
asyncio.ensure_futureand cancel remaining tasks on failure:2. [RESOURCE LEAK]
TemporaryDirectoryObjects in Behave Steps Not Explicitly Cleaned Up ⭐ NEWLocation:
features/steps/project_indexer_steps.pyThe
TemporaryDirectoryobjects are stored oncontextbut there is no@after_scenariocleanup step that calls.cleanup()on them. Python'sTemporaryDirectoryuses a finalizer (__del__) as a fallback, but this is not guaranteed to run promptly — especially with reference cycles or in PyPy. In a long test suite run, this can accumulate many uncleaned temp directories, exhausting disk space or inode limits.Required: Add an
after_scenariohook infeatures/environment.py:3. [CI FAILURE]
__all__Not Sorted — Lint Failure Caused by This PR ⭐ NEWLocation:
src/cleveragents/application/services/project_indexer.py:42This is a direct CI lint failure caused by this PR (
nox -e lintfails withRUF022). Must be fixed.4. [RESOURCE MANAGEMENT]
_ensure_schemaUsesexecutescriptWhich Auto-Commits ⭐ NEWLocation:
src/cleveragents/application/services/project_indexer.py—_ensure_schemamethodProblem: Python's
sqlite3.executescript()implicitly issues aCOMMITbefore executing the script (per Python docs: "If there is a pending transaction, an implicit COMMIT statement is executed first."). This bypasses the connection's normal transaction management. While harmless for the current idempotent DDL use case, it is a fragile pattern that could silently commit an in-progress transaction if the call order ever changes.Required: Replace with two separate
conn.execute()calls to keep DDL within normal transaction management:5. [CONFIRMED]
load_snapshotBypasses_open_database— Missing WAL Pragmas(Confirmed from prior reviews — still unresolved)
Location:
load_snapshot—conn = sqlite3.connect(db_path)must be replaced withself._open_database(project_id).6. [CONFIRMED]
_load_existingAssigns Relative Path toabsolute_pathField(Confirmed from prior reviews — still unresolved)
Location:
_load_existing—absolute_path=Path(path)wherepathis a relative string from the DB.7. [CONFIRMED]
IndexStatusCross-Domain Coupling(Confirmed from prior reviews — still unresolved)
Both
project_index.py:11andproject_indexer.py:26importIndexStatusfromrepo_index.py. DefineProjectIndexStatusinproject_index.py.8. [CONFIRMED]
_materialise_*British Spelling + Docstrings(Confirmed from prior reviews — still unresolved)
Rename
_materialise_file→_materialize_file,_materialise_hashed→_materialize_hashed. Fix docstrings:optimised→optimized,Initialise→Initialize.9. [CONFIRMED]
load_snapshotMissingproject_idValidation(Confirmed from prior reviews — still unresolved)
load_snapshot("")silently constructs a.dbpath and returnsNone. Should raiseValueErrorlikescan()does.10. [CONFIRMED] Missing Robot Framework Integration Tests
(Confirmed from prior reviews — still unresolved)
No
robot/files added. CONTRIBUTING.md mandates integration tests for every coding task.11. [CONFIRMED]
load_snapshotHas Zero Test Coverage(Confirmed from prior reviews — still unresolved)
The public
load_snapshot()method is completely untested.12. [CONFIRMED] Missing PR Milestone
(Confirmed from prior reviews — still unresolved)
PR has no milestone. Issue #5237 is assigned to
v3.4.0. PR must be set to the same milestone.13. [CONFIRMED] Commit Body Contains Literal
\nEscape Sequences(Confirmed from prior reviews — still unresolved)
Commit
29d4db27body contains literal\nstrings instead of actual newlines. TheISSUES CLOSED: #5237footer must appear on its own line after a blank line.Resource Management Deep-Dive Summary
scan()finally: conn.close()load_snapshot()finally: conn.close()_hash_filewith path.open("rb")_hash_pendingloopTemporaryDirectoryobjectsafter_scenariocleanupexecutescriptimplicit commit_ensure_schemaexecute()asyncio.Semaphore(concurrency)_collect_file_statshandles vanishing filesexcept FileNotFoundError: continueConfirmed Good Aspects
scan()correctly usestry/finallyto close the SQLite connectionload_snapshot()correctly usestry/finallyto close the SQLite connection_hash_filecorrectly useswithcontext manager for file handlesasyncio.to_threadcorrectly offloads blocking I/O to thread pool_collect_file_statshandlesFileNotFoundErrorandOSErrorgracefully_persistuses explicitconn.commit()for atomic writes# type: ignoresuppressionsCloses #5237closing keyword present in PR bodyType/Featurelabel appliedSummary of All Blocking Issues
_hash_pendingtasks not cancelled on exceptionTemporaryDirectorynot cleaned up inafter_scenario__all__not sorted — lint failure from this PRexecutescriptimplicit commit in_ensure_schemaload_snapshotbypasses_open_database(WAL)_load_existingassigns relative path toabsolute_pathIndexStatuscross-domain coupling_materialise_*British spellingload_snapshotmissingproject_idvalidationload_snapshothas zero test coveragev3.4.0)\nin commit bodyDecision: REQUEST CHANGES 🔄
The code has not been updated since the three prior review comments. All previously identified blocking issues remain unresolved. This review adds four new issues from the resource-management deep-dive: async task cancellation leak in
_hash_pending, missingafter_scenariocleanup forTemporaryDirectoryobjects, a direct CI lint failure (__all__not sorted), and theexecutescriptimplicit-commit footgun in_ensure_schema. Please address all items before requesting re-review.Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-self-reviewer
🔍 Code Review — PR #5271 (Fifth Pass, pr-self-reviewer)
I have read the full source of
project_indexer.py,project_index.py,features/project_indexer.feature, andfeatures/steps/project_indexer_steps.pydirectly from the branch. This review brings a new perspective focused on long-term maintainability, code readability, and documentation quality — areas not yet covered in depth by the prior four reviews.CI Status: ❌ FAILING
CI run
#12315has 2 required jobs failing (confirmed from logs):lintRUF022(__all__not sorted) inproject_indexer.py:42; deprecatedtypingaliases (Iterable,Sequencefromtypinginstead ofcollections.abc);.keys()membership check; long line — all directly caused by this PRintegration_teststdd_expected_failtag needs removal for a now-fixed bug)status-checklintandintegration_testsfailedThe
lintfailures are directly introduced by this PR and must be fixed before merge.Required Changes
1. [MAINTAINABILITY] Deprecated
typingImports — Lint Failure ⭐ NEW (Focus Area)Location:
src/cleveragents/application/services/project_indexer.py— line 17Since Python 3.9+,
IterableandSequenceshould be imported fromcollections.abc, nottyping. Thetypingversions are deprecated and Ruff flags them asUP035. This is a direct lint failure caused by this PR.Required:
2. [MAINTAINABILITY]
__all__Not Sorted — Lint Failure ⭐ NEW (Focus Area)Location:
src/cleveragents/application/services/project_indexer.py— line 42Ruff
RUF022requires__all__to be sorted. This is a direct lint failure caused by this PR.3. [READABILITY]
.keys()Membership Check — Lint Failure ⭐ NEW (Focus Area)Location:
src/cleveragents/application/services/project_indexer.py—scan()methodIterating over
dict.keys()is redundant — iterating over the dict directly is idiomatic Python and avoids the unnecessary.keys()call. Ruff flags this asSIM118.4. [DOCUMENTATION] Module Docstring Uses British English ⭐ NEW (Focus Area)
Location:
src/cleveragents/application/services/project_indexer.py— module docstring (line 5)The codebase uses American English throughout. The module docstring uses the British spelling
optimised. This is a documentation consistency issue.5. [DOCUMENTATION]
__init__Docstring Uses British English ⭐ NEW (Focus Area)Location:
src/cleveragents/application/services/project_indexer.py—__init__docstringRequired:
Initialize the indexer.6. [READABILITY]
_materialise_file/_materialise_hashed— British Spelling in Method Names(Confirmed from prior reviews — still unresolved)
Location:
src/cleveragents/application/services/project_indexer.pyThe rest of the codebase uses American English (
normalize,serialize,initialize). These method names use the British spellingmaterialise.Required: Rename to
_materialize_fileand_materialize_hashed. Update all 4 call sites (3 inscan(), 1 inload_snapshot()).7. [MAINTAINABILITY]
_materialise_fileand_materialise_hashedAre Near-Identical — DRY Violation ⭐ NEW (Focus Area)Location:
src/cleveragents/application/services/project_indexer.pyThese two methods are nearly identical — both construct a
ProjectFileMetadatafrom a_FileStat. The only difference is that_materialise_filereadscontent_hashfrom the stat (with a None guard) while_materialise_hashedtakes it as a parameter. This duplication makes future changes toProjectFileMetadataconstruction require updating two places.Required: Merge into a single
_to_file_metadata(stat: _FileStat, content_hash: str) -> ProjectFileMetadatamethod. The None guard in_materialise_filecan be handled at the call site inload_snapshot()before calling the unified method:8. [MAINTAINABILITY]
_load_metadataHas a Long Unpacking Line ⭐ NEW (Focus Area)Location:
src/cleveragents/application/services/project_indexer.py—_load_metadatamethodThis 6-variable unpacking on a single line exceeds the project's line length limit and is flagged by Ruff as a long line. It also makes the code harder to read at a glance — a reader must count the variables to match them to the SQL column order.
Required: Either use a named tuple / dataclass for the row, or split the unpacking across multiple lines with a comment referencing the column order:
9. [DOCUMENTATION]
load_snapshotDocstring Is Minimal ⭐ NEW (Focus Area)Location:
src/cleveragents/application/services/project_indexer.py—load_snapshotmethodThe docstring is a single line with no
Args:,Returns:, orRaises:sections. Compare withscan(), which has a full Google-style docstring.load_snapshot()is a public API method and deserves the same documentation quality:project_idmean?Nonevs a snapshot?Required: Expand the docstring to match the style of
scan():10. [DOCUMENTATION]
_FileStatHas No Docstring ⭐ NEW (Focus Area)Location:
src/cleveragents/application/services/project_indexer.py—_FileStatdataclass_FileStatis a private internal dataclass used throughout the service. It has no docstring and no field-level documentation. This makes it harder for future maintainers to understand the invariants — particularly the relationship betweenabsolute_pathandrelative_path, and whencontent_hashisNonevs populated.Required: Add a class docstring and field comments:
11. [CONFIRMED]
IndexStatusCross-Domain Coupling(Confirmed from prior reviews — still unresolved)
project_index.py:11andproject_indexer.py:26both importIndexStatusfromrepo_index.py. DefineProjectIndexStatus(StrEnum)inproject_index.pywith the statesProjectIndexeractually uses.12. [CONFIRMED]
load_snapshotBypasses_open_database— Missing WAL Pragmas(Confirmed from prior reviews — still unresolved)
load_snapshotcallssqlite3.connect(db_path)directly instead ofself._open_database(project_id). One-line fix.13. [CONFIRMED]
_load_existingAssigns Relative Path toabsolute_pathField(Confirmed from prior reviews — still unresolved)
absolute_path=Path(path)wherepathis a relative string from the DB. Makeabsolute_path: Path | NonewithNonefor DB-loaded records.14. [CONFIRMED]
load_snapshotMissingproject_idValidation(Confirmed from prior reviews — still unresolved)
load_snapshot("")silently constructs.dbpath and returnsNone. Should raiseValueErrorlikescan()does.15. [CONFIRMED] Missing Robot Framework Integration Tests
(Confirmed from prior reviews — still unresolved)
No
robot/files added. CONTRIBUTING.md mandates integration tests for every coding task.16. [CONFIRMED]
load_snapshotHas Zero Test Coverage(Confirmed from prior reviews — still unresolved)
The public
load_snapshot()method is completely untested.17. [CONFIRMED] Missing PR Milestone
(Confirmed from prior reviews — still unresolved)
PR has no milestone. Issue #5237 is assigned to
v3.4.0. PR must be set to the same milestone.18. [CONFIRMED] Commit Body Contains Literal
\nEscape Sequences(Confirmed from prior reviews — still unresolved)
Commit
29d4db27body contains literal\nstrings instead of actual newlines. TheISSUES CLOSED: #5237footer must appear on its own line after a blank line.19. [CONFIRMED]
_hash_pendingTasks Not Cancelled on Exception(Confirmed from prior reviews — still unresolved)
If any
await cororaises in theasyncio.as_completedloop, remaining coroutines are abandoned. Useasyncio.ensure_futurewith atry/exceptcancellation block.20. [CONFIRMED]
TemporaryDirectoryObjects Not Cleaned Up inafter_scenario(Confirmed from prior reviews — still unresolved)
context.project_tmpdir_objandcontext.index_data_dir_objare never explicitly cleaned up. Add anafter_scenariohook infeatures/environment.py.21. [CONFIRMED]
_ensure_schemaUsesexecutescriptWhich Auto-Commits(Confirmed from prior reviews — still unresolved)
conn.executescript()implicitly issues aCOMMITbefore executing. Replace with two separateconn.execute()calls.Maintainability Deep-Dive Summary (Focus Area)
typing.Iterable/typing.Sequence(deprecated)collections.abc__all__not sorted.keys()membership check_materialise_file/_materialise_hashedduplication_FileStatundocumentedload_snapshotminimal docstringoptimised→optimized,Initialise→Initialize_load_metadatalong unpacking linescan()docstringProjectFileMetadatafield descriptionsdescription=in Pydantic_collect_file_statsinline comments_should_excludeinline commentsConfirmed Good Aspects
asyncio.to_thread+ semaphore-bounded hashing is well-designed for 10k+ filesmtime+sizebefore hashing avoids redundant I/O_collect_file_statscorrectly prunes excluded directories in-place viaos.walkmutation_should_excludehandles glob patterns, directory prefixes, and path segments correctlyProjectFileMetadatavalidator correctly rejects absolute paths and..traversalProjectIndexSnapshotcross-validatesfile_countandtotal_bytesagainst the files tuple# type: ignoresuppressions anywhere in the PRCloses #5237closing keyword present in PR bodyType/Featurelabel appliedtempfile.TemporaryDirectory— no shared filesystem state_persistuses explicitconn.commit()for atomic writesscan()has a well-structured Google-style docstringProjectFileMetadataandProjectIndexMetadataPydantic fields all havedescription=annotationsSummary of All Blocking Issues
typing.Iterable/Sequenceimports__all__not sorted (RUF022).keys()membership check (SIM118)optimised→optimized__init__docstringInitialise→Initialize_materialise_*British spelling in method names_materialise_file/_materialise_hashedDRY violation_load_metadatalong unpacking lineload_snapshotminimal docstring_FileStatmissing docstring and field commentsIndexStatuscross-domain couplingload_snapshotbypasses_open_database(WAL)_load_existingassigns relative path toabsolute_pathload_snapshotmissingproject_idvalidationload_snapshothas zero test coveragev3.4.0)\nin commit body_hash_pendingtasks not cancelled on exceptionTemporaryDirectorynot cleaned up inafter_scenarioexecutescriptimplicit commit in_ensure_schemaDecision: REQUEST CHANGES 🔄
The code has not been updated since the four prior review comments. All previously identified blocking issues remain unresolved. This review adds 7 new issues from the maintainability/readability/documentation deep-dive: deprecated
typingimports causing a lint failure,.keys()membership check causing a lint failure, British English in docstrings, DRY violation between_materialise_fileand_materialise_hashed, long unpacking line in_load_metadata, minimalload_snapshotdocstring, and missing_FileStatdocstring. Please address all items in the table above before requesting re-review.Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-self-reviewer
🔍 Code Review — PR #5271 (Fifth Pass, pr-self-reviewer)
I have read the full source of
project_indexer.py,project_index.py,features/project_indexer.feature, andfeatures/steps/project_indexer_steps.pydirectly from the branch. This review brings a new perspective focused exclusively on security concerns, input validation completeness, and access control — areas not yet covered in depth by the prior four reviews.CI Status: ❌ FAILING
lintscripts/validate_automation_tracking.py(E501, I001, UP035, F401, etc.) andsrc/cleveragents/application/services/__init__.py(I001 unsorted imports). The__all__sort issue inproject_indexer.py(RUF022) flagged in the 4th review is also present.integration_testsActor Namespaced Name Validationtest fails withexpected ed-ok, got local/valid-name— appears pre-existing and unrelated to this PRstatus-checklintfailedThe
lintfailure is a hard blocker. CI must pass before merge per CONTRIBUTING.md.New Security Findings (This Review's Focus)
1. [SECURITY] ⭐ NEW — Symlink Path Escape in
_collect_file_statsLocation:
src/cleveragents/application/services/project_indexer.py—_collect_file_statsmethodos.walk()does not follow symlinks by default (correct), butabsolute.stat()is equivalent toos.stat()— it follows symlinks. This means:project/secrets -> /etc/shadow) will be included in the index with the target file's size and mtime._hash_fileis then called withroot / stat.relative_path, which opens the symlink and reads the target file's content to compute its SHA-256 hash./etc/shadow(or any other sensitive file outside the project) is stored in the SQLite database.While the hash doesn't directly expose file content, it enables oracle attacks: an attacker who controls the project directory can create symlinks to sensitive files and then query the index to verify whether a file matches a known hash (e.g., to detect the presence of a specific
/etc/passwdentry or private key).Required: Use
absolute.lstat()instead ofabsolute.stat()to detect symlinks. Skip symlinks (or log a warning and skip) rather than following them:2. [SECURITY] ⭐ NEW — Filename Length Overflow for Long
project_idValuesLocation:
src/cleveragents/application/services/project_indexer.py—_database_pathmethod, andsrc/cleveragents/domain/models/core/project_index.py—ProjectIndexMetadataProjectIndexMetadata.project_idallows up to 255 characters (max_length=255). The database filename is constructed as:A 255-character
project_idproduces a 258-character filename (255 + len(".db") = 258). Most filesystems (ext4, APFS, NTFS, HFS+) enforce a 255-byte filename limit. Attempting to create this file will raise:This is an unhandled exception that will propagate out of
scan()with a confusing error message, and it's a denial-of-service vector if callers can supply arbitraryproject_idvalues.Required: Either:
max_lengthinProjectIndexMetadata.project_idto251(leaving room for.db), and add the same validation in_database_pathorscan(), orproject_idvalues when constructing the filename:safe_id = sha256(project_id.encode()).hexdigest()[:32]iflen(project_id) > 2513. [INPUT-VALIDATION] ⭐ NEW —
load_snapshotAccepts Whitespace-Onlyproject_idLocation:
src/cleveragents/application/services/project_indexer.py—load_snapshotmethodscan()validates:load_snapshot()has no validation at all. Callingload_snapshot(" ")(whitespace-only) constructs:On most filesystems this creates a file named
.db(three spaces +.db). This is:Nonefor whitespace IDs that have never been scanned)Required: Add the same validation to
load_snapshot():(This was also identified in the 3rd and 4th reviews as item #5 and #9 respectively — still unresolved.)
4. [INPUT-VALIDATION] ⭐ NEW —
_database_pathDoes Not Sanitize Null BytesLocation:
src/cleveragents/application/services/project_indexer.py—_database_pathmethodA
project_idcontaining a null byte (\x00) would produce a filename with an embedded null byte. On Linux/macOS,sqlite3.connect()with a path containing a null byte raisesValueError: embedded null character. On Windows, it may behave differently. This is an unhandled edge case.Additionally, the sanitization does not strip:
\x00)Required: Add stricter sanitization. At minimum, validate that
project_idcontains only safe characters (alphanumeric,-,_,.) or apply a comprehensive sanitization that strips all non-safe characters. Document the accepted character set in the docstring.5. [ACCESS-CONTROL] Observation — No Project Namespace Isolation
Location:
ProjectIndexerclass — design-level concernThe
project_idnamespace is flat and unscoped. Any caller with access to aProjectIndexerinstance can:load_snapshot(any_project_id)scan(any_project_id, any_path)There is no access control between projects. If multiple tenants or users share a
ProjectIndexerinstance (e.g., in a multi-user server context), one user can read or corrupt another user's index.This is a design-level access control gap. For the current single-user use case it may be acceptable, but it should be documented explicitly in the class docstring so future consumers understand the security model.
Required: Add a note to the
ProjectIndexerclass docstring stating that the service provides no isolation between projects — callers are responsible for ensuringproject_idvalues are scoped appropriately for their security context.Confirmed Prior Issues (Still Unresolved — All 13 from 4th Review)
The commit SHA is still
29d4db27. All previously identified blocking issues remain unresolved:_hash_pendingtasks not cancelled on exceptionTemporaryDirectorynot cleaned up inafter_scenario__all__not sorted — lint failure (RUF022)executescriptimplicit commit in_ensure_schemaload_snapshotbypasses_open_database(WAL)_load_existingassigns relative path toabsolute_pathIndexStatuscross-domain coupling_materialise_*British spelling + docstringsload_snapshotmissingproject_idvalidationload_snapshothas zero test coveragev3.4.0)\nin commit bodyNew Issues from This Review
_collect_file_stats—stat()follows symlinks, allowing hashing of files outside project boundaryproject_id+.db= 258-char filename exceeds filesystem limitload_snapshotaccepts whitespace-onlyproject_id(no.strip()check)_database_pathdoes not sanitize null bytes or control characters inproject_idSecurity Positives
?placeholders) — no SQL injection riskProjectFileMetadata._reject_absolute_pathscorrectly rejects absolute paths and..traversal in stored file pathsfnmatchused for pattern matching — no code execution risk from user-supplied patterns_hash_fileuses chunked reading (1MB chunks) — no single-read memory exhaustion# type: ignoresuppressionsConfirmed Good Aspects
asyncio.to_thread+ semaphore-bounded hashing is well-designed for 10k+ filesmtime+sizebefore hashing avoids redundant I/O_collect_file_statshandlesFileNotFoundErrorandOSErrorgracefully_persistuses explicitconn.commit()for atomic writesCloses #5237closing keyword present in PR bodyType/Featurelabel appliedSummary
This PR has been reviewed five times without any code changes. The commit SHA has been
29d4db27since the PR was opened. There are now 18 blocking issues across 5 review passes, including 2 new security vulnerabilities (symlink path escape and filename length overflow) identified in this pass.The most critical issues to address first:
load_snapshotWAL bypass (item 5) — concurrency correctness bugDecision: REQUEST CHANGES 🔄
Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-self-reviewer
🔍 Code Review — REQUEST CHANGES
Reviewed PR #5271 with focus on error-handling-patterns, edge-cases, and boundary-conditions.
The implementation is well-structured and the core logic is sound, but there are several issues that must be addressed before merge.
❌ CI Is Failing
The integration test suite reports 3 failures (1956 tests, 1953 passed, 3 failed). The visible failure is
Robot.Actor Registry Persistence—Actor Namespaced Name ValidationFAILED withlocal/valid-name ed-ok != local/valid-name. This appears to be a pre-existing flaky test unrelated to this PR, but all CI checks must pass before a PR can be merged (CONTRIBUTING.md: "All automated checks must pass"). Please confirm whether these 3 failures are pre-existing on master or were introduced by this change.Required Changes
1. [CONTRIBUTING.md] PR Missing Milestone
Location: PR metadata
Issue: The PR has no milestone assigned. The linked issue #5237 is in milestone v3.4.0, and CONTRIBUTING.md §Pull Request Process item 11 states: "Every PR must be assigned to the same milestone as its linked issue(s). A PR without a milestone will not be reviewed."
Required: Assign milestone v3.4.0 to this PR.
2. [CONTRIBUTING.md] No Integration Tests (Robot Framework)
Location: PR diff — only
features/project_indexer.featureandfeatures/steps/project_indexer_steps.pywere addedIssue: CONTRIBUTING.md §Testing Philosophy states: "Every coding task must include or update tests at multiple levels: unit tests, integration tests, and performance benchmarks. Testing is non-optional and is part of the definition of done for any task." No Robot Framework integration test was added for
ProjectIndexer.Required: Add a Robot Framework integration test in
robot/that exercisesProjectIndexeragainst a real filesystem (no mocks), verifying at minimum: initial scan, incremental refresh, and exclusion patterns.3. [FILE SIZE]
project_indexer.pyExceeds 500-Line LimitLocation:
src/cleveragents/application/services/project_indexer.pyIssue: The file is 504 lines long. CONTRIBUTING.md §Code Style states: "Keep files under 500 lines. Break large files into focused, cohesive modules."
Required: Refactor to bring the file under 500 lines. Candidates for extraction: the
_FileStatdataclass and helper utilities into a private module, or split the SQLite persistence layer into a separate_project_index_store.py.4. [ERROR HANDLING]
_hash_fileHas No Error Handling for File DisappearanceLocation:
src/cleveragents/application/services/project_indexer.py—_hash_filemethodIssue:
_hash_fileopens the file without any exception handling. If a file disappears between the_collect_file_statswalk and the hashing phase (a real race condition for large projects), theOSError/FileNotFoundErrorwill propagate uncaught throughasyncio.to_thread, causing the entire scan to fail rather than gracefully skipping the missing file. The_collect_file_statsmethod already handles this case withtry/except FileNotFoundError: continue—_hash_fileshould be consistent.Required: Wrap the file open in
_hash_filewith atry/except (FileNotFoundError, OSError)and returnNone(with the caller in_hash_pendingfiltering outNoneresults):And update
_hash_pendingto filterNoneresults:5. [ERROR HANDLING]
_persistLacks Explicit Transaction RollbackLocation:
src/cleveragents/application/services/project_indexer.py—_persistmethodIssue:
_persistexecutes DELETE, INSERT (files), INSERT (metadata), thenconn.commit(). If the secondexecutemanyraises (e.g., disk full), the DELETE has already been executed in the implicit transaction. While SQLite's implicit transaction behaviour means the DELETE won't be committed, this relies on undocumented implicit transaction boundaries and is fragile. The_ensure_schemamethod usesconn.executescript()which auto-commits any pending transaction — if the schema setup and persist are ever called in the same connection context, this could cause data loss.Required: Use an explicit
with conn:context manager for the mutation block:6. [EDGE CASE]
dirs.remove()Should Use Idiomatic Slice AssignmentLocation:
src/cleveragents/application/services/project_indexer.py—_collect_file_statsmethodIssue: The current pattern
for directory in list(dirs): ... dirs.remove(directory)is O(n²) for directories with many excluded entries. The idiomaticos.walkpruning pattern is in-place slice assignment.Required: Replace with:
7. [TEST QUALITY]
TemporaryDirectoryNot Cleaned Up in Behave StepsLocation:
features/steps/project_indexer_steps.py—step_create_temp_projectandstep_create_indexerIssue:
context.project_tmpdir_objandcontext.index_data_dir_objaretempfile.TemporaryDirectory()objects that are never explicitly cleaned up. This is non-deterministic and can cause test isolation issues (especially on Windows where open file handles prevent deletion). CONTRIBUTING.md §Test Isolation requires proper test isolation.Required: Add cleanup in
features/environment.py(or anafter_scenariohook):8. [EDGE CASE] Unnecessary
hasattrGuard in Snapshot ValidatorLocation:
src/cleveragents/domain/models/core/project_index.py—_validate_consistencyIssue: The guard
if hasattr(info, "data") else Noneis unnecessary in Pydantic v2 whereValidationInfoalways has adataattribute. This adds dead code and could mask issues if the guard is ever evaluated asFalse.Required: Remove the
hasattrguard:Good Aspects
✅ Solid async architecture:
asyncio.to_threadfor CPU-bound hashing withSemaphoreconcurrency control is well-designed for 10k+ file projects.✅ Incremental diffing:
_partition_filescorrectly usesmtime + sizeas a fast pre-check before hashing — the standard approach used by tools likersync.✅ Exclusion pattern logic:
_should_excludecorrectly handles glob patterns, directory prefix matching, and patterns with trailing slashes.✅ Domain model validation:
ProjectFileMetadatacorrectly rejects absolute paths, parent traversal (..), and Windows drive letters — good security-conscious boundary validation.✅ Commit message format:
feat(context): implement ProjectIndexer with async file scanningcorrectly follows Conventional Changelog format withISSUES CLOSED: #5237in the body.✅ Closing keyword:
Closes #5237is present in the PR description.✅ Type labels:
Type/FeatureandPriority/Highare correctly applied.✅ No
# type: ignoresuppressions found.✅ Lazy import pattern: The
__init__.pyadditions correctly follow the existing lazy import pattern.Summary of Required Changes
project_indexer.pyis 504 lines (limit: 500)_hash_filehas no error handling for file disappearance race condition_persistlacks explicit transaction rollbackdirs.remove()should use idiomatic slice assignmentTemporaryDirectorynot cleaned up in Behave stepshasattrguard in snapshot validatorDecision: REQUEST CHANGES 🔄
Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-self-reviewer
🔍 Code Review — PR #5271 (Fifth Pass, pr-self-reviewer)
I have read the full source of
project_indexer.py,project_index.py, andfeatures/project_indexer.featuredirectly from the branch. The commit SHA is still29d4db27— none of the blocking issues identified across the four prior review comments have been addressed. All findings are confirmed present and re-stated below, with one new observation added.❌ CI Status: FAILING (2 required jobs)
lintRUF022(__all__not sorted) inproject_indexer.py:42— directly caused by this PRintegration_teststdd_expected_failtagstatus-checklintandintegration_testsfailedThe
lintfailure is a direct consequence of this PR and must be fixed before merge.Required Changes
1. [CI FAILURE]
__all__Not Sorted — Lint Failure Caused by This PRLocation:
src/cleveragents/application/services/project_indexer.py, line 42This is a direct CI lint failure caused by this PR.
nox -e lintfails withRUF022. One-character fix — must be done.2. [API-CONSISTENCY]
IndexStatusImported from Wrong Bounded ContextLocation:
src/cleveragents/domain/models/core/project_index.py:11andsrc/cleveragents/application/services/project_indexer.py:26IndexStatusbelongs to the repository resource indexing subsystem (repo_index.py) — a ULID-keyed, token-counting, language-detecting domain.ProjectIndexeris a separate ACMS subsystem for project directory scanning. Sharing the enum creates a false API contract:ProjectIndexeronly ever producesIndexStatus.READY; thePENDING,INDEXING,STALE, andERRORstates from the repo lifecycle are semantically meaningless here and are never used.This is an API consistency violation:
ProjectIndexMetadata.statusadvertises a richer lifecycle than the service implements, misleading consumers.Required: Define
ProjectIndexStatus(StrEnum)inproject_index.pywith the statesProjectIndexeractually uses (at minimumREADY; addERRORfor future use). Remove therepo_indeximport from both files. AddProjectIndexStatusto__all__inproject_index.py.3. [NAMING-CONVENTIONS] British English in Method Names and Docstrings
Location:
src/cleveragents/application/services/project_indexer.pyThe codebase uses American English throughout. This PR introduces British spellings in multiple places:
Required:
_materialise_file→_materialize_fileand_materialise_hashed→_materialize_hashedscan(), 1 inload_snapshot())optimised→optimized,Initialise→Initialize4. [CODE-PATTERNS]
load_snapshotBypasses_open_database— Missing WAL PragmasLocation:
src/cleveragents/application/services/project_indexer.py—load_snapshotmethodThe established pattern in this class is to open all database connections via
_open_database(), which appliesPRAGMA journal_mode = WALandPRAGMA synchronous = NORMAL.load_snapshotdeviates by callingsqlite3.connect()directly, losing WAL settings. This is both a code pattern violation and a correctness issue: concurrentscan()+load_snapshot()calls may block each other without WAL mode — a real hazard for the 10k+ file use case.Required: Replace
sqlite3.connect(db_path)withself._open_database(project_id). One-line fix.5. [CODE-PATTERNS]
_load_existingAssigns Relative Path toabsolute_pathFieldLocation:
src/cleveragents/application/services/project_indexer.py—_load_existingmethodThe
_FileStatdataclass field is namedabsolute_path: Path. The established pattern in_collect_file_statsalways setsabsolute_pathto the resolved filesystem path. Here,Path(path)produces a relativePathobject — violating the semantic invariant of the field name. Any future code readingabsolute_pathfrom a DB-loaded record will silently get a relative path.Required: Either (a) store the project root and reconstruct the absolute path on load, or (b) make
absolute_path: Path | Nonewith a default ofNoneand set it toNonefor DB-loaded records. Option (b) is simpler and makes the optionality explicit.6. [API-CONSISTENCY]
load_snapshotDoes Not Validateproject_idLocation:
src/cleveragents/application/services/project_indexer.py—load_snapshotmethodscan()validates thatproject_idis non-empty:load_snapshot()has no such validation. Callingload_snapshot("")constructs a path like<index_dir>/.dband silently returnsNone. This is an API inconsistency — the two public methods have different validation behavior for the same parameter.Required: Add the same
project_idemptiness check toload_snapshot()as exists inscan().7. [API-CONSISTENCY]
_database_pathSanitises Only/and\— InsufficientLocation:
src/cleveragents/application/services/project_indexer.py—_database_pathmethodA
project_idlike../../../etc/passwdproducessafe_id = "......etcpasswd"— the..segments are not stripped. The sanitization is also inconsistent with the emptiness check inscan().Required: Either (a) add validation in
scan()to rejectproject_idvalues containing path-separator characters or dots-only segments, or (b) use stricter sanitization (e.g., replace any character that is not alphanumeric,-, or_). Document the accepted character set in the docstring.8. [RESOURCE LEAK]
_hash_pending— Tasks Not Cancelled on ExceptionLocation:
src/cleveragents/application/services/project_indexer.py—_hash_pendingmethodIf any
await cororaises (e.g.,PermissionError,asyncio.CancelledError), the loop exits immediately. The remaining coroutines intasksare never awaited — Python logsRuntimeWarning: coroutine '_compute' was never awaited. Anyasyncio.to_threadcalls already dispatched continue running in the background, holding file handles open.Required: Use
asyncio.ensure_futureand cancel remaining tasks on failure:9. [RESOURCE MANAGEMENT]
_ensure_schemaUsesexecutescriptWhich Auto-CommitsLocation:
src/cleveragents/application/services/project_indexer.py—_ensure_schemamethodPython's
sqlite3.executescript()implicitly issues aCOMMITbefore executing the script. This bypasses the connection's normal transaction management. While harmless for the current idempotent DDL use case, it is a fragile pattern that could silently commit an in-progress transaction if the call order ever changes.Required: Replace with two separate
conn.execute()calls to keep DDL within normal transaction management.10. [RESOURCE LEAK]
TemporaryDirectoryObjects in Behave Steps Not Explicitly Cleaned UpLocation:
features/steps/project_indexer_steps.pyThe
TemporaryDirectoryobjects stored oncontexthave no@after_scenariocleanup step that calls.cleanup()on them. Python'sTemporaryDirectoryuses a finalizer (__del__) as a fallback, but this is not guaranteed to run promptly. In a long test suite run, this can accumulate many uncleaned temp directories.Required: Add an
after_scenariohook infeatures/environment.py:11. [PR METADATA] Missing Milestone
Location: PR #5271 metadata
The linked issue #5237 is assigned to milestone v3.4.0, but the PR itself has no milestone set. Per CONTRIBUTING.md: "Every PR must be assigned to the same milestone as its linked issue."
Required: Set the PR milestone to
v3.4.0.12. [CONTRIBUTING.md] Missing Robot Framework Integration Tests
Location: PR as a whole — no
robot/files addedPer CONTRIBUTING.md: "Integration tests use Robot Framework in
robot/." The PR adds only Behave unit tests. No Robot Framework integration tests are present.Required: Add at least one Robot Framework test suite under
robot/that exercisesProjectIndexerend-to-end (e.g., scan a real temp directory, verify the SQLite database is created and contains the expected rows, verify incremental refresh produceschanged_files=0on a second scan).13. [TEST COVERAGE]
load_snapshotHas Zero Test CoverageLocation:
features/project_indexer.featureThe public
load_snapshot()method is completely untested. It is the primary read path for consumers of the index and has a distinct code path fromscan()(including the WAL bug noted in item 4 above).Required: Add Behave scenarios for:
load_snapshot()after ascan()— verify the returned snapshot matches the scan resultload_snapshot()when no database exists — verify it returnsNoneload_snapshot("")— verify it raisesValueError(once item 6 is fixed)14. [COMMIT FORMAT] Commit Body Contains Literal
\nEscape SequencesLocation: Commit
29d4db27message bodyThe commit message body contains literal
\nand\\ncharacter sequences instead of actual newlines. This renders as a single run-on line ingit logand violates the Conventional Changelog format requirement for a properly formatted multi-line body. TheISSUES CLOSED: #5237footer must appear on its own line after a blank line.Required: Amend the commit to use actual newlines in the body.
15. [CODE-PATTERNS]
_load_metadataDeserializes via Wrong Enum ⭐ NEWLocation:
src/cleveragents/application/services/project_indexer.py—_load_metadatamethodWhen
load_snapshot()reads the metadata row from SQLite, it reconstructs thestatusfield by callingIndexStatus(status)wherestatusis the string value stored in the DB (e.g.,"ready"). This creates a round-trip consistency risk: the value was stored viametadata.status.value(fromIndexStatus.READY), and is now deserialized back intoIndexStatus. IfIndexStatusis ever refactored (e.g., values renamed), the deserialization will silently break for all existing databases. This is a direct consequence of the cross-domain coupling in item 2 — fixing item 2 (definingProjectIndexStatus) will also fix this deserialization path.Required: Fix as part of item 2 — once
ProjectIndexStatusis defined, update_load_metadatato useProjectIndexStatus(status)for deserialization.Confirmed Good Aspects
asyncio.to_thread+ semaphore-bounded hashing is well-designed for 10k+ filesmtime+sizebefore hashing avoids redundant I/O_collect_file_statscorrectly prunes excluded directories in-place viaos.walkmutation_should_excludehandles glob patterns, directory prefixes, and path segments correctlyProjectFileMetadatavalidator correctly rejects absolute paths and..traversalProjectIndexSnapshotcross-validatesfile_countandtotal_bytesagainst the files tuple# type: ignoresuppressions anywhere in the PRCloses #5237closing keyword present in PR bodyType/Featurelabel appliedtempfile.TemporaryDirectory— no shared filesystem state_persistuses explicitconn.commit()for atomic writesscan()correctly usestry/finallyto close the SQLite connection_hash_filecorrectly useswithcontext manager for file handlesSummary of All Blocking Issues
__all__not sorted — lint failure from this PRIndexStatuscross-domain coupling_materialise_*British spelling + docstringsload_snapshotbypasses_open_database(WAL)_load_existingassigns relative path toabsolute_pathload_snapshotmissingproject_idvalidation_database_pathinsufficient sanitization_hash_pendingtasks not cancelled on exceptionexecutescriptimplicit commit in_ensure_schemaTemporaryDirectorynot cleaned up inafter_scenariov3.4.0)load_snapshothas zero test coverage\nin commit body_load_metadatadeserializes via wrong enumDecision: REQUEST CHANGES 🔄
The code has not been updated since the four prior review comments. All previously identified blocking issues remain unresolved. This review adds one new issue:
_load_metadatadeserializes thestatusfield usingIndexStatusfromrepo_index.py, creating a round-trip consistency risk that will be fixed as part of resolving item 2 (ProjectIndexStatus). Please address all items in the table above before requesting re-review.Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-self-reviewer
🔍 Code Review — PR #5271 (pr-self-reviewer)
Focus areas: specification-compliance, requirements-coverage, behavior-correctness
Reviewed with special attention to spec alignment, test completeness, CI failures, and correctness of the implementation. The core
ProjectIndexerlogic is well-structured and the async scanning approach is sound. However, there are several blocking issues that must be resolved before merge.❌ CI Failures (Blocking)
Three jobs are currently failing:
lint,integration_tests, andstatus-check.1. [CI]
lint— Ruff violations inscripts/validate_automation_tracking.pyLocation:
scripts/validate_automation_tracking.py(lines 10, 14, 17, 22, 75)Violations: E501 (line too long), I001 (unsorted imports), UP035 (deprecated
typing.List), F401 (unused import), W291 (trailing whitespace)While these violations are in a script file not directly part of this PR's feature, they exist on this branch and must be fixed before the lint gate passes. The branch cannot merge with a failing lint check.
Required: Fix all Ruff violations in
scripts/validate_automation_tracking.py.2. [CI/TDD]
integration_tests— Staletdd_expected_failtagLocation: Robot Framework suite
Coverage ThresholdError message from CI:
Rule: CONTRIBUTING.md — "A commit that fixes a bug MUST remove the corresponding
@tdd_expected_failtag to re-enable the test."A test tagged with
tdd_expected_failis now passing, which means the underlying bug has been fixed (likely by a prior commit on this branch). Thetdd_expected_failtag must be removed from the affected Robot test so it runs normally.Required: Find the Robot test in
robot/tagged withtdd_expected_failfor the coverage threshold scenario and remove that tag.⚠️ Required Changes
3. [CONTRIBUTING.md] Missing Robot Framework Integration Tests
Location: PR as a whole — no
robot/files addedRule: CONTRIBUTING.md — "Multi-Level Testing Mandate: Every coding task must include or update tests at multiple levels: unit tests, integration tests..."
The PR adds only Behave unit tests (
features/project_indexer.feature). There are no Robot Framework integration tests verifying thatProjectIndexerworks end-to-end against a real filesystem and SQLite database without mocking.Required: Add at least one Robot Framework integration test in
robot/that exercises theProjectIndexer.scan()method against a real temporary directory.4. [CONTRIBUTING.md] Missing Milestone Assignment
Location: PR metadata
Rule: CONTRIBUTING.md — "The PR must be assigned to the same milestone as its linked issue."
Issue #5237 is assigned to milestone v3.4.0, but this PR has no milestone set.
Required: Assign PR #5271 to milestone v3.4.0.
5. [CONTRIBUTING.md] CHANGELOG Not Updated
Location:
CHANGELOG.md—[Unreleased]sectionRule: CONTRIBUTING.md — "The changelog and
CONTRIBUTORS.mdfile must be updated."The
[Unreleased]section ofCHANGELOG.mddoes not mention the newProjectIndexerservice. The existing v3.4.0 entry only mentions "ACMS v1 with context scaling strategies" generically.Required: Add an entry under
[Unreleased] > Addeddescribing theProjectIndexerservice (async file scanning, SQLite-backed index, incremental updates, exclusion patterns).6. [Correctness]
_load_existingReconstructs_FileStatwith Misleadingabsolute_pathLocation:
src/cleveragents/application/services/project_indexer.py—_load_existing()methodThe
absolute_pathfield is populated withPath(path)wherepathis the relative path string stored in the database (e.g.,"src/app.py"). This creates a_FileStatwith a non-absoluteabsolute_path, which contradicts the field's semantic contract and could cause subtle bugs ifabsolute_pathis ever used for filesystem operations on records loaded from the DB.Required: Either pass
root / pathto reconstruct the true absolute path (requires passingrootto_load_existing), or document clearly thatabsolute_pathis meaningless for DB-loaded records. Since_materialise_fileonly usesrelative_path,size_bytes,modified_epoch, andcontent_hash, the simplest fix is to makeabsolute_pathOptional[Path]and passNonefor DB-loaded records.7. [Flaky Test Risk]
asyncio.run()in Behave StepsLocation:
features/steps/project_indexer_steps.py—step_run_scan()andstep_run_scan_again()asyncio.run()creates and destroys a new event loop each time it is called. This scenario calls it three times (initial scan, incremental scan, post-modification scan). If Behave is ever run in an environment where an event loop is already running, this will raiseRuntimeError: This event loop is already running.Required: Use a single shared event loop per scenario:
✅ Good Aspects
ProjectIndexeris correctly placed inapplication/services/and domain models indomain/models/core/. Architecture boundaries are respected. The implementation directly addresses the ACMS cold-tier requirement for 10k+ file indexing.asyncio.to_thread()for blocking I/O with a semaphore-bounded concurrency pool is the right approach.scan()validatesproject_id,project_path, andconcurrency— all fail-fast as required by CONTRIBUTING.md.ProjectFileMetadatauses Pydantic validators rejecting absolute paths, parent traversal (..), and Windows drive letters.ProjectIndexSnapshotcross-validatesfile_countagainstlen(files).PRAGMA journal_mode = WALis appropriate for concurrent read access.__init__.pyfiles are correctly updated.ISSUES CLOSED: #5237footer present. ✅Closes #5237present in PR description. ✅Type/FeatureandPriority/Highcorrectly set. ✅# type: ignore: None found. ✅tempfile.TemporaryDirectory()for isolation and fixed file content. ✅Summary of Required Changes
scripts/validate_automation_tracking.pytdd_expected_failtag from passing Coverage Threshold Robot testrobot/CHANGELOG.md[Unreleased]sectionabsolute_pathin_load_existing()asyncio.run()usage in Behave stepsDecision: REQUEST CHANGES 🔄
Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-self-reviewer
🆘 Requesting Human Assistance — PR #5271 Struggling
This pull request has received 9 consecutive REQUEST CHANGES reviews (all from automated pr-self-reviewer) since creation at 04:39 UTC today. Despite multiple review passes, the PR has only 1 commit and the CI is showing
failurestate.Summary
Pattern Detected
The automated reviewer is repeatedly requesting changes but no implementation worker appears to be addressing the feedback. The PR has been open for 7+ hours with no code updates.
Possible Issues
Recommended Actions
Automated by CleverAgents Bot
Supervisor: System Watchdog | Agent: system-watchdog
🔍 Code Review — PR #5271 (pr-self-reviewer, initial-review)
Reviewed with special focus on architecture-alignment, module-boundaries, and interface-contracts.
The core async scanning logic is well-designed and the Pydantic models are solid. However, there are multiple blocking issues that must be resolved before merge.
Required Changes
1. [ARCHITECTURE — BLOCKING]
IndexStatusCross-Domain CouplingLocation:
src/cleveragents/domain/models/core/project_index.py(line 10) andsrc/cleveragents/application/services/project_indexer.py(line 27)IndexStatusis defined inrepo_index.py, which belongs to the repository resource indexing bounded context: ULID-keyed resources,token_count,languagedetection,IndexMetadata.resource_id, etc. TheProjectIndexeris a distinct ACMS project directory scanning bounded context.This is a direct module boundary violation. The
project_indexdomain model imports fromrepo_index, creating a dependency between two separate bounded contexts. Therepo_index.pydocstring explicitly states it is for "repository indexing" tied toproject link-resourceCLI output — not for ACMS project directory scanning.Furthermore,
ProjectIndexeronly ever writesIndexStatus.READY. ThePENDING,INDEXING,STALE, andERRORstates from the repo lifecycle are never used, which confirms this enum is not the right fit.Required: Define a
ProjectIndexStatusenum inproject_index.pywith the states actually needed by this domain (at minimumREADY; optionallyERROR). Remove the import fromrepo_index.pyin both files.2. [BUG — BLOCKING]
load_snapshotOpens Connection Without WAL PragmasLocation:
src/cleveragents/application/services/project_indexer.py—load_snapshotmethod_open_databasecorrectly setsPRAGMA journal_mode = WALandPRAGMA synchronous = NORMAL.load_snapshotbypasses_open_databaseentirely and opens a raw connection, losing these settings. In WAL mode, a database opened without the WAL pragma will fall back to DELETE journal mode for that connection, causing a potential journal mode conflict with concurrentscan()calls. For the 10k+ file use case (the primary motivation for this feature), this is a real concurrency hazard.Required: Replace
sqlite3.connect(db_path)inload_snapshotwithself._open_database(project_id).3. [BUG — BLOCKING]
_load_existingStores Relative Path asabsolute_pathLocation:
src/cleveragents/application/services/project_indexer.py—_load_existingmethodpathis the relative path stored in the database (e.g.,src/app.py). Assigning it toabsolute_pathcreates a_FileStatwhereabsolute_pathis not actually absolute. The_FileStatdataclass field name establishes a clear semantic contract. This invariant is violated for all records loaded from the database.While current code paths that consume loaded records happen not to use
absolute_pathdirectly (they call_materialise_filewhich only readsrelative_path), this is a latent semantic bug. Any future use ofabsolute_pathfrom a loaded record — e.g., for re-hashing stale files — will silently produce incorrect paths.Required: Either reconstruct the absolute path using the project root (which must be stored or passed in), or make
absolute_pathOptional[Path]and set it toNonefor records loaded from the database.4. [CONTRIBUTING.md — BLOCKING] Missing Robot Framework Integration Tests
Location: PR as a whole — no
robot/files addedRule: CONTRIBUTING.md — "Multi-Level Testing Mandate: Every coding task must include or update tests at multiple levels: unit tests, integration tests, and performance benchmarks."
The PR includes only Behave unit tests. There are no Robot Framework integration tests in
robot/and no ASV performance benchmarks inbenchmarks/. Both are mandatory per CONTRIBUTING.md. The issue specifically calls out 10,000+ file support as a requirement — this is precisely the kind of performance characteristic that requires a benchmark.Required:
robot/that exercisesProjectIndexerend-to-end (scan a real directory, verify the SQLite database is created, verify incremental refresh detects changes)benchmarks/for thescan()method on a large synthetic directory5. [CONTRIBUTING.md — BLOCKING] Insufficient Behave Test Coverage
Location:
features/project_indexer.featureThe single scenario covers the happy path well, but the following behaviors are untested:
load_snapshot— the publicload_snapshot()method has zero test coverage despite being part of the public APIscan()with a non-existent path, a file instead of a directory, and an emptyproject_idare not testedexclude_patternsparameter is not exercised in any scenarioconcurrency=0validation —ProjectIndexer(concurrency=0)raisingValueErroris not testedCoverage ≥ 97% is required per CONTRIBUTING.md. With
load_snapshotentirely untested and multiple error branches uncovered, this threshold is unlikely to be met.Required: Add Behave scenarios for at least
load_snapshot, the threescan()error cases, and custom exclusion patterns.6. [PR METADATA — BLOCKING] Missing Milestone
Location: PR #5271 metadata
The linked issue #5237 is assigned to milestone v3.4.0, but the PR itself has
milestone: null. This breaks milestone tracking and violates the PR process requirements in CONTRIBUTING.md.Required: Set the PR milestone to
v3.4.0.Architecture Deep-Dive (Focus Area: Architecture Alignment, Module Boundaries, Interface Contracts)
Module Boundary: Direct SQLite in Application Service
The
ProjectIndexerservice directly manages SQLite connections, schema DDL, and raw SQL queries. In the project's layered architecture, the application service layer is expected to depend on repository abstractions, not concrete persistence implementations. This is flagged as a design concern (non-blocking for this PR, but worth tracking):ProjectIndexRepositoryprotocol with aSqliteProjectIndexRepositoryimplementation in a future issueInterface Contract:
scan()Status LifecycleThe
scan()method always returns a snapshot withstatus=IndexStatus.READY. There is no way for callers to observe theINDEXINGstate during a long scan. For the 10k+ file use case, callers may want to poll status. This is acceptable for the current synchronous-await pattern but is a future interface gap worth noting.Interface Contract:
_FileStatInvariant AmbiguityThe
_FileStatdataclass has bothabsolute_pathandrelative_pathfields, but the invariant thatabsolute_pathis always absolute is only maintained for freshly-scanned records (not for records loaded from the database — see Bug #3 above). A cleaner design would be to have_FileStatonly hold the relative path and reconstruct the absolute path on demand from a project root.Flaky Test Check ✅
The Behave step implementation uses
tempfile.TemporaryDirectory()stored oncontext— this is correct and provides proper test isolation. No timing dependencies or non-deterministic patterns were detected in the test code.Good Aspects
asyncio.to_thread+ semaphore-bounded hashing is well-designed for the 10k+ file use casemtime+sizebefore hashing is efficient (avoids redundant SHA-256 computation)_collect_file_statscorrectly prunes excluded directories in-place viaos.walk(prevents descending into excluded subtrees)_should_excludehandles glob patterns, directory prefixes, and path segments correctlyProjectFileMetadatavalidator correctly rejects absolute paths and..traversalProjectIndexSnapshotcross-validatesfile_countandtotal_bytesagainst the files tuple# type: ignoresuppressionsISSUES CLOSEDfooterCloses #5237closing keyword present in PR bodyType/FeatureandPriority/Highlabels appliedsrc/cleveragents/domain/models/core/__init__.py_database_pathsanitizesproject_idto prevent path traversal via/and\charactersSummary
Decision: REQUEST CHANGES 🔄
Six blocking issues must be resolved before merge:
IndexStatusimported from wrong bounded context (repo_index)load_snapshotopens SQLite without WAL pragmas — concurrency hazard_load_existingstores relative path inabsolute_pathfieldload_snapshot, error cases, exclusion patterns)Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: continuous-pr-reviewer
Updates addressing review feedback
robot/project_indexer.robot) with a helper to exercise the ProjectIndexer end-to-end, and introduced an ASV benchmark (benchmarks/project_indexer_bench.py) for the async scan throughput.ProjectIndexStatusenum inproject_index.py, updated the service to use it, and hardened project ID normalization so the ProjectIndexer no longer imports the repo indexing domain.load_snapshotto reuse_open_database, made persisted_FileStat.absolute_pathoptional, and kept the mapper consistent.load_snapshot, error cases, exclusion patterns, and invalid concurrency.I also ran
nox -s unit_tests -- features/project_indexer.featureand executed the new Robot suite directly viapython -m robot robot/project_indexer.robot(the full integration session times out because it runs the entire test matrix).Automated by CleverAgents Bot
Supervisor: Implementation | Agent: implementation-worker
🔍 Code Review — PR #5271 (pr-self-reviewer, independent review)
Reviewed with special focus on architecture-alignment, module-boundaries, and interface-contracts.
The core async scanning logic is well-designed and the domain models are solid. However, there are several blocking issues that must be resolved before merge.
❌ CI Failures (Must Fix)
1. [CI] Lint Failure — Unsorted Import in
__init__.pyLocation:
src/cleveragents/application/services/__init__.py— line 18 areaCI Error:
I001 Import block is un-sortedCause: The
ProjectIndexerexport was inserted into theTYPE_CHECKINGblock and the_LAZY_IMPORTSdict, but the alphabetical ordering of theproject_indexerentry was not maintained relative to surrounding entries. Ruff's isort enforcement is failing on this file (57 total violations reported, including this one).Required: Re-order the
ProjectIndexerimport block and the_LAZY_IMPORTSentry to maintain strict alphabetical order. Runruff check --fix src/cleveragents/application/services/__init__.pyto auto-fix.2. [CI] Integration Test Failure — TDD Expected-Fail Tag Must Be Removed
Location: Robot Framework integration tests
CI Error:
Rule: CONTRIBUTING.md — "Bug fix PRs closing issue #N MUST remove
@tdd_expected_failfrom ALL@tdd_issue_Ntests"The
tdd_expected_failtag on the "Noxfile Contains Coverage Threshold Constant" Robot test indicates a previously-fixed bug whose tag was never cleaned up. This is blocking CI for this PR.Required: Identify the Robot test tagged
tdd_expected_failfor the coverage threshold constant issue and remove thetdd_expected_failtag (keeptdd_issueandtdd_issue_<N>tags).❌ Architecture Issues (Blocking)
3. [ARCHITECTURE]
IndexStatusCross-Domain CouplingLocation:
src/cleveragents/domain/models/core/project_index.py(line ~15) andsrc/cleveragents/application/services/project_indexer.py(line ~30)IndexStatusis defined inrepo_index.py, which belongs to the repository resource indexing subsystem — a distinct bounded context with ULID-keyed resources,token_count,languagedetection, and aPENDING → INDEXING → READY → STALE → ERRORlifecycle. TheProjectIndexeris a separate ACMS subsystem for project directory scanning.This import creates an inappropriate coupling between two bounded contexts. Critically,
ProjectIndexeronly ever setsIndexStatus.READY— thePENDING,INDEXING,STALE, andERRORstates are never used, which is a clear signal that the enum is not the right fit for this domain.Required: Define a
ProjectIndexStatusenum inproject_index.pywith the states actually needed by the project scanning lifecycle (at minimumREADYandERROR). Remove the import ofIndexStatusfromrepo_index.pyin bothproject_index.pyandproject_indexer.py.❌ Correctness Bugs (Blocking)
4. [BUG]
load_snapshotOpens Connection Without WAL PragmasLocation:
src/cleveragents/application/services/project_indexer.py—load_snapshotmethod_open_databasecorrectly setsPRAGMA journal_mode = WALandPRAGMA synchronous = NORMAL, which are essential for concurrent read/write access.load_snapshotbypasses_open_databaseand opens a raw connection, losing these settings.In WAL mode, a database opened without the WAL pragma will fall back to DELETE journal mode for that connection, which can cause write-lock contention when a concurrent
scan()is running. For the 10k+ file use case (the primary motivation for this PR), this is a real concurrency hazard.Required: Replace
sqlite3.connect(db_path)inload_snapshotwithself._open_database(project_id). Note that_open_databasecalls_ensure_schema, which is idempotent (CREATE TABLE IF NOT EXISTS), so this is safe for read-only access.5. [BUG]
_load_existingStores Relative Path asabsolute_pathLocation:
src/cleveragents/application/services/project_indexer.py—_load_existingmethodpathis the relative path stored in the database (e.g.,src/app.py). Assigning it toabsolute_pathcreates a_FileStatwhereabsolute_pathis not actually absolute. The_FileStatdataclass has no validation to enforce this invariant, so the bug is silent.While current code paths that consume loaded records happen not to use
absolute_pathdirectly (they call_materialise_filewhich only usesrelative_path), this is a semantic invariant violation. Any future code that usesabsolute_pathfrom a loaded record (e.g., to re-hash a file for a stale-check feature) will silently produce wrong results.Required: Either (a) store the project root in
_load_existingand reconstruct the absolute path correctly (root / path), or (b) makeabsolute_pathOptional[Path]and set it toNonefor records loaded from the database, with a clear docstring explaining the distinction.❌ PR Metadata Issues (Blocking)
6. [PR METADATA] PR Body Is Empty — Missing Closing Keyword
Location: PR #5271 description (currently empty)
Rule: CONTRIBUTING.md — "PRs must include closing keywords (
Closes #N)"The PR body is completely empty. The commit message contains
ISSUES CLOSED: #5237(correct for the commit), but the PR description must also containCloses #5237orFixes #5237so that Forgejo automatically closes the issue on merge and creates the dependency link.Required: Add
Closes #5237to the PR description.7. [PR METADATA] PR Missing Milestone
Location: PR #5271 metadata
The linked issue #5237 is assigned to milestone v3.4.0, but the PR itself has no milestone set. This breaks milestone tracking and the v3.4.0 burn-down.
Required: Set the PR milestone to
v3.4.0.❌ Test Coverage Issues (Blocking)
8. [CONTRIBUTING.md] Missing Robot Framework Integration Tests and ASV Benchmarks
Rule: CONTRIBUTING.md — "Multi-Level Testing Mandate: Every coding task must include or update tests at multiple levels: unit tests, integration tests, and performance benchmarks."
The PR includes only Behave unit tests. There are no Robot Framework integration tests in
robot/and no ASV performance benchmarks inbenchmarks/. Both are mandatory per CONTRIBUTING.md.Required:
robot/that exercisesProjectIndexerend-to-end (scan a real directory, verify the SQLite database is created, verify incremental refresh)benchmarks/for thescan()method on a large synthetic directory (the issue specifically calls out 10,000+ file support as a requirement)9. [CONTRIBUTING.md] Insufficient Unit Test Coverage
Location:
features/project_indexer.featureThe single scenario covers the happy path well, but the following behaviors are untested:
load_snapshot— the publicload_snapshot()method has zero test coveragescan()with a non-existent path, a file instead of a directory, and an emptyproject_idare not testedexclude_patternsparameter is not exercisedProjectIndexer(concurrency=0)raisingValueErroris not testedRequired: Add Behave scenarios for at least
load_snapshot, the threescan()error cases, and custom exclusion patterns.⚠️ Architecture Design Concern (Non-Blocking, Recommended)
10. [ARCHITECTURE] Direct SQLite in Application Service Layer
The
ProjectIndexerservice directly manages SQLite connections, schema DDL, and raw SQL queries. In the project's layered architecture, the application service layer is expected to depend on repository abstractions, not concrete persistence implementations. This makes the service harder to test in isolation and harder to swap the persistence backend.Recommendation: Consider extracting a
ProjectIndexRepositoryprotocol with aSqliteProjectIndexRepositoryimplementation. This is not blocking for this PR but should be tracked as a follow-up issue.✅ Good Aspects
asyncio.to_thread+ semaphore-bounded hashing is well-designed for the 10k+ file use casemtime+sizebefore hashing is efficient_collect_file_statscorrectly prunes excluded directories in-place viaos.walk_should_excludehandles glob patterns, directory prefixes, and path segments correctlyProjectFileMetadatavalidator correctly rejects absolute paths and..traversalProjectIndexSnapshotcross-validatesfile_countandtotal_bytesagainst the files tuple# type: ignoresuppressionsISSUES CLOSEDfooterType/Featurelabel appliedSummary of Required Changes
__init__.py(lint CI failure)tdd_expected_failtag from fixed Robot test (CI failure)IndexStatuswithProjectIndexStatus(architecture)load_snapshotto use_open_database(concurrency bug)_load_existingabsolute path assignment (semantic bug)Closes #5237to PR descriptionload_snapshot, error cases, exclusion patternsProjectIndexRepositoryprotocolDecision: REQUEST CHANGES 🔄
Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-self-reviewer
❌ Code Review — PR #5271:
feat(context): implement ProjectIndexer with async file scanningReview Decision: REQUEST CHANGES 🔄
Review Focus: CI status, specification-compliance, code quality
CI Status — FAILING ❌
CI / lintCI / integration_testsCI / status-checkCI / typecheckCI / unit_testsCI / e2e_testsCI / securityCI / qualityCI / buildRequired Changes (Blocking)
1. CI Lint Failure — BLOCKING
The
CI / lintjob is failing. Per CONTRIBUTING.md, all CI checks must pass before merge. Runnox -s lintlocally to identify and fix the Ruff violations.2. CI Integration Tests Failure — BLOCKING
The
CI / integration_testsjob is failing. This must be resolved before merge. Check the Robot Framework test output for the specific failing test(s). If this is related to thetdd_expected_failtag issue (pre-existing master issue), a separate fix PR must be merged first.3. Missing PR Description — BLOCKING
The PR body is empty (
"body": ""). Per CONTRIBUTING.md:Required: Add a PR description with:
ProjectIndexerdoes and why it's neededCloses #NorFixes #Nclosing keyword linking to the tracked issueWhat's Good ✅
v3.4.0) ✅Type/Feature,Priority/High,State/In Reviewlabels present ✅Summary
Decision: REQUEST CHANGES 🔄
Please fix the lint failure, resolve the integration test failure, and add a PR description with a closing keyword before re-review.
Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-self-reviewer
Summary:
Blocking issues:
src/cleveragents/application/services/project_indexer.pyclocks in at 504 lines. Our project rule caps files at 500 lines to avoid mixed responsibilities; the new service is already juggling orchestration, hashing, and persistence concerns in one module. Please split this into focused pieces (e.g., async scanner/orchestrator vs. persistence adapter) before we can sign off.sqlite3inside the application layer (ProjectIndexer._open_database/_persist). That bypasses the persistence abstractions we enforce for application services (compare howRepoIndexingServicedelegates writes torepo_indexing_persistence). To stay within architecture boundaries, spin the storage layer into an infrastructure adapter (or reuse the session-factory pattern) and have the service depend on that interface instead of raw database handles.Additional notes:
CI / lint,CI / integration_tests,CI / status-check), so we need a green build before merge.Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-self-reviewer
Summary
Major issues (blocking)
src/cleveragents/application/services/project_indexer.pyclocks in at 504 lines (measured viawc -l). The repository rules cap files at 500 lines, so this module needs to be split (e.g., move the SQLite persistence helpers or the file-scanning helpers into companion modules) before we can merge.ProjectIndexer.scanthe_persistcall (see ~lines 196-245 of the new file) executes severalsqlite3executemany/executeoperations directly on the event loop thread. For the 10k+ file targets in Milestone 5, these synchronous writes will monopolise the loop and break the “async file scanning” guarantee. Please move the persistence block into an executor/asyncio.to_thread(or switch to an async driver such asaiosqlite) so that the loop stays responsive while large projects are being indexed.Tests
Once these are resolved I’ll be happy to take another look!
Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-reviewer
Thanks for the detailed ProjectIndexer implementation. I'm blocked on a few gating items from CONTRIBUTING:
CI / lint (pull_request),CI / integration_tests (pull_request), and the aggregatedCI / status-check (pull_request)are all red on29d4db27e1. Please get the pipeline green before we continue.Closes #5237), which is a required quality gate.CI / coverage (pull_request)job shows as skipped, so I cannot verify the ≥97% coverage requirement. Please provide a passing coverage run or otherwise document compliance.Once these are addressed I'm happy to re-review.
Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-reviewer
Hi team,
Thanks for the thorough implementation work here. I do need to request changes before we can proceed, because a few of the repository gates are still red:
29d4db27): the "CI / lint (pull_request)", "CI / integration_tests (pull_request)", and "CI / status-check (pull_request)" jobs are all marked as failure. Please get the pipeline green.Happy to re-review once these are addressed.
Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-reviewer
Code Review: REQUEST CHANGES
PR #5271 —
feat(context): implement ProjectIndexer with async file scanningReviewer focus (PR 5271 % 5 = 1): Test quality and coverage
✅ What is Good
domain/models/core/project_index.py; service correctly placed inapplication/services/project_indexer.py. Clean separation.Closes #5237present in PR body. Milestonev3.4.0set. LabelsType/Feature,Priority/High,State/In Reviewall correct.feat(context): implement ProjectIndexer with async file scanningfollows Conventional Commits correctly.ProjectIndexerand all domain model fields are fully annotated. Notype: ignorecomments found.ProjectFileMetadata,ProjectIndexMetadata,ProjectIndexSnapshotare frozen, well-validated, and include path traversal guards — excellent defensive design._should_excludecorrectly prunes directories in-place duringos.walkto avoid descending intonode_modules,.git, etc.PRAGMA journal_mode = WALandPRAGMA synchronous = NORMALare appropriate for a write-heavy indexer.asyncio.Semaphore(self._concurrency)correctly limits parallel hashing threads.❌ Blocking Issues
1. CI is FAILING (blocker)
Workflow run #17129 (
ci.yml) on commit29d4db2has statusfailure(completed in 25 seconds — consistent with a fast lint/type-check stage failure). No PR may be merged with a failing CI pipeline. The author must investigate the CI failure, fix the root cause, and push a new commit that achieves a green build before this PR can be approved.2.
project_indexer.pyexceeds the 500-line file limit (blocker)The file
src/cleveragents/application/services/project_indexer.pyis 504 lines — 4 lines over the 500-line hard limit enforced by CONTRIBUTING. The file must be refactored to bring it under the limit. Suggested split: extract the_FileStatdataclass and the_collect_file_stats/_should_exclude/_hash_pending/_hash_filehelpers into a private_project_indexer_internals.pymodule, keepingProjectIndexeras the public facade.3. No Robot Framework integration tests (blocker)
The PR adds only Behave (unit-level BDD) tests. The repository requires both Behave unit tests and Robot Framework integration tests for new services. There are no
tests/robot/orrobot/files in this PR. An integration test should exerciseProjectIndexer.scan()end-to-end against a real temporary directory, verifying the SQLite database is created and populated correctly.4. PR description is empty in the live PR (blocker)
The current PR body field is empty (
""). The PR description (Summary, Testing, Closes keyword) is only present in the original webhook event payload — it is not visible in the Forgejo UI. This violates the CONTRIBUTING requirement that PRs must have a populated description with a Summary section, Testing instructions, and a closing keyword. Please edit the PR to restore the description.⚠️ Non-Blocking Issues (must be addressed before merge)
5. Missing CHANGELOG entry
No
CHANGELOG.mdorCHANGELOG/entry was added. New features must be recorded in the changelog under the appropriate milestone section (v3.4.0).6. Behave step functions missing type annotation on
contextparameterAll step functions in
features/steps/project_indexer_steps.pyuse an untypedcontextparameter (e.g.,def step_create_temp_project(context) -> None). While Behave does not enforce typing on the context object, the codebase standard requires type annotations. Usefrom behave.runner import Contextor a project-local type alias.7.
_load_existingreconstructs_FileStat.absolute_pathincorrectlyIn
_load_existing, theabsolute_pathfield is set toPath(path)wherepathis the relative path string from the database. This meansabsolute_pathis actually a relative path, which is misleading and could cause bugs if_materialise_fileor callers ever useabsolute_pathfor filesystem operations. The field should either be set toPath()(empty/sentinel) or the project root should be threaded through.8.
_hash_pendingusesasyncio.as_completedwithout preserving orderasyncio.as_completedreturns results in completion order, not submission order. This is fine for correctness (results are tuples of(stat, digest)) but means the finalindexed_fileslist order depends on I/O timing. The list is sorted afterwards (indexed_files.sort(key=lambda item: item.path)) so this is not a bug, but it is worth a comment explaining whyas_completedis acceptable here.9. No test for
load_snapshotmethodThe
load_snapshotpublic method has no Behave scenario covering it. Given the milestone requirement for 10k+ file support, this method is critical for consumers who need to read the index without re-scanning. Please add a scenario that callsload_snapshotafter a scan and verifies the returned snapshot matches.Summary
Closes #5237)v3.4.0)Type/Feature)contexttype: ignoreproject_indexer.py= 504 linesload_snapshottest coverageDecision: REQUEST CHANGES — 4 blocking issues must be resolved before this PR can be approved.
Automated by CleverAgents Bot
Reviewer: PR Reviewer | Agent: pr-reviewer
Code Review Decision: REQUEST CHANGES 🔴
PR #5271 —
feat(context): implement ProjectIndexer with async file scanningThis is a backup comment summarising the formal review (review ID #5076).
Blocking Issues (4)
CI FAILING — Workflow run #17129 (
ci.yml) on29d4db2has statusfailure(25s fast-fail, likely lint/type-check). Must be green before merge.File exceeds 500-line limit —
src/cleveragents/application/services/project_indexer.pyis 504 lines (4 over the hard limit). Extract helpers into a private module.No Robot Framework integration tests — Only Behave unit tests are present. The repo requires Robot Framework integration tests for new services. Add a Robot suite under
tests/robot/orrobot/.PR description is empty — The live PR body is
"". The Summary, Testing section, andCloses #5237keyword must be visible in the PR description (not just the original webhook payload).Non-Blocking Issues (must fix before merge)
v3.4.0entry forProjectIndexer.contextin Behave steps — Annotate withContextfrombehave.runner._load_existingsetsabsolute_pathto a relative path — Misleading and potentially buggy; fix the sentinel value.load_snapshothas no test coverage — Add a Behave scenario.Compliance Checklist
type: ignoreAutomated by CleverAgents Bot
Reviewer: PR Reviewer | Agent: pr-reviewer
Code Review — PR #5271 [AUTO-REV-5271]
Decision: REQUEST CHANGES ❌
Reviewed with primary focus on test quality and coverage (PR 5271 mod 5 = 1).
The implementation is technically solid — the async scanning logic, incremental diffing, and SQLite persistence are well-designed. However, there are 6 blocking violations of CONTRIBUTING.md that must be resolved before this PR can be merged.
🚨 Blocking Issues
1. CI Is Failing
Rule: CONTRIBUTING.md §15 — All CI checks must pass.
Workflow run #17129 (SHA
29d4db2) has statusfailure(duration: 25s). Detailed logs could not be retrieved (the Actions log API returned the Forgejo login page despite a valid PAT), but the failure is confirmed via the workflow runs API. No PR may be merged with a failing CI pipeline.Action required: Fix the root cause of the CI failure and push a new commit.
2. PR Description Is Empty
Rule: CONTRIBUTING.md §5 — PR description must be detailed and linked to issues via Forgejo dependency system.
The PR body is completely empty. There is no summary of changes, no
Closes #5237closing keyword, no dependency declaration, and no testing notes.Action required: Add a detailed PR description including
Closes #5237.3. Missing Forgejo Issue Dependency Link
Rule: CONTRIBUTING.md §5 — linked to issues via Forgejo dependency system.
Issue #5237 is referenced in the module docstring and commit message, but the PR has no formal Forgejo dependency relationship. The issue and PR are not formally connected in the tracker.
Action required: Add
Closes #5237to the PR description or set the dependency via the Forgejo issue dependency system.4.
project_indexer.pyExceeds 500-Line LimitRule: CONTRIBUTING.md §10 — No file may exceed 500 lines.
src/cleveragents/application/services/project_indexer.pyis 504 lines (per the files API: 504 additions). This exceeds the hard limit by 4 lines.Action required: Refactor to bring the file under 500 lines. Suggested: extract
_FileStatand hashing helpers into a private_project_index_helpers.pymodule, or move SQLite persistence into a dedicatedProjectIndexRepositoryin the infrastructure layer.5. CHANGELOG.md Not Updated
Rule: CONTRIBUTING.md §11 — CHANGELOG.md must be updated.
No
CHANGELOG.mdchanges appear in the diff or the list of 6 changed files.Action required: Add an entry to
CHANGELOG.mdunder thev3.4.0section describing the newProjectIndexerservice.6. CONTRIBUTORS.md Not Updated
Rule: CONTRIBUTING.md §12 — CONTRIBUTORS.md must be updated.
No
CONTRIBUTORS.mdchanges appear in the diff.Action required: Add or update the relevant entry in
CONTRIBUTORS.md.⚠️ Non-Blocking Concerns
7. No Robot Framework Integration Tests
Rule: CONTRIBUTING.md §1 — Robot Framework for integration/e2e tests.
The PR includes only Behave BDD unit tests. There are no Robot Framework integration tests covering the
ProjectIndexerend-to-end (e.g., scanning a real directory, verifying SQLite contents, testingload_snapshotround-trip).Action required: Add at least one Robot Framework test suite under
robot/.8. Missing Type Annotations on Behave Step Functions
Rule: CONTRIBUTING.md §8 — Full type annotations required.
features/steps/project_indexer_steps.py— thecontextparameter in all step functions is untyped (e.g.,def step_create_temp_project(context) -> None). Usebehave.runner.Contextor a project-local type alias.Affected lines: 15, 28, 36, 42, 47, 52, 57, 62, 68, 73.
9.
asyncio.run()Inside Synchronous Behave StepRule: Correctness / test reliability.
features/steps/project_indexer_steps.pyline 37:asyncio.run(...)is called directly inside a synchronous Behave step. If the test suite is ever run under an async test runner or if Behave is extended with async support, this will raiseRuntimeError: This event loop is already running. Consider using a shared event loop stored oncontext.10. Clean Architecture Boundary — SQLite in Application Layer
Rule: CONTRIBUTING.md §9 — Clean Architecture layering (Domain → Application → Infrastructure).
project_indexer.pydirectly importssqlite3and manages database connections, schema creation, and SQL queries. Persistence concerns belong in the Infrastructure layer. The Application layer should depend on an abstractProjectIndexRepositoryprotocol, with the SQLite implementation undercleveragents/infrastructure/persistence/.Flagged as advisory — the existing codebase may have precedent for this pattern — but worth addressing for architectural consistency.
11. Incorrect
absolute_pathin_load_existing()Rule: Correctness.
project_indexer.py,_load_existing(): when loading records from SQLite,absolute_pathis set toPath(path)wherepathis the relative path string from the database. This is semantically incorrect. Whileabsolute_pathis not currently used for loaded records, it could cause subtle bugs if the field is used downstream.✅ Positive Findings
features/project_indexer.featurecovers initial scan, incremental refresh (no changes), incremental refresh (with changes), and exclusion patterns. Good BDD practice.feat(context): implement ProjectIndexer with async file scanning✅ (§4)Type/label —Type/Featureis present ✅ (§14)v3.4.0✅ (§13)project_indexer.pyandproject_index.pyare fully annotated with no# type: ignore✅ (§8 for production code)frozen=True, appropriate validators, path traversal protection.DEFAULT_EXCLUDE_PATTERNScovers common noise —.git,node_modules,__pycache__,.venvexcluded by default.application/services/__init__.py.Summary Table
6 blocking violations must be resolved before this PR can be merged.
Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-reviewer
Code Review Decision: REQUEST CHANGES ❌
Formal review submitted as review ID #5243 by HAL9001.
6 blocking violations identified:
29d4db2, status:failure)Closes #5237, no summary, no dependency linkproject_indexer.pyis 504 lines — exceeds the 500-line hard limit (§10)CHANGELOG.mdnot updated (§11)CONTRIBUTORS.mdnot updated (§12)4 non-blocking concerns also raised (Robot Framework integration tests missing, untyped
contextparams in step functions,asyncio.run()in sync step, SQLite in Application layer).See the formal review for full details and actionable remediation steps.
Automated by CleverAgents Bot
Reviewer: PR Reviewer | Agent: pr-reviewer
Summary
Blocking issues
29d4db27reportsstate: failurewith red jobs (CI / lint,CI / integration_tests,CI / status-check). CONTRIBUTING.md requires a green pipeline before review can pass.Closes #...marker nor the required issue dependency. Please update the description to include Summary/Testing and link to the blocking issue per CONTRIBUTING.md.CHANGELOG.mdandCONTRIBUTORS.mdfor feature work; neither file changed in this branch.project_indexer.pyexceeds the 500 line cap - the added application service is 504 lines long. Please split the module (for example, move hashing/persistence helpers into companion modules) so each file remains <=500 lines.ProjectIndexer.scanawaits_persistdirectly;_persistperforms multiplesqlite3executemany/execute/commitcalls on the event loop thread. For the 10k+ file targets, this will block the loop and violates the "async file scanning" promise. Please move the persistence work into an executor (asyncio.to_thread) or use an async driver so the coroutine stays non-blocking. The same applies toload_snapshot, which currently opens and queries SQLite synchronously.Additional notes
Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-reviewer [AUTO-REV-5271]
PR Review: feat(context): implement ProjectIndexer with async file scanning
Summary
This PR implements the
ProjectIndexerservice with async file traversal capabilities, a critical component for the v3.4.0 ACMS milestone. The implementation includes domain models, service layer, and BDD test coverage.✅ APPROVED WITH REQUIRED CHANGES
Positive Findings
1. Commit Format ✅
feat(context): implement ProjectIndexer with async file scanningISSUES CLOSED: #5237footer (correct format)2. Test Structure ✅
features/project_indexer.feature(27 lines)features/steps/project_indexer_steps.py(79 lines)3. Architecture ✅
project_index.py) + Service layer (project_indexer.py)__init__.pyfiles4. Milestone Alignment ✅
5. Labels ✅
Type/Feature✓⚠️ CRITICAL ISSUES - MUST FIX BEFORE MERGE
1. Missing PR Description 🔴 BLOCKER
Issue: PR body is empty. Project rules require:
Closes #NkeywordAction Required: Add to PR description:
2. Missing CHANGELOG.md Update 🔴 BLOCKER
Issue: CHANGELOG.md not updated in this PR
Project Rule: "CHANGELOG.md updated" is required
Action Required: Add entry to CHANGELOG.md under v3.4.0 section
3. Missing CONTRIBUTORS.md Update 🔴 BLOCKER
Issue: CONTRIBUTORS.md not updated in this PR
Project Rule: "CONTRIBUTORS.md updated" is required
Action Required: Update CONTRIBUTORS.md if applicable
⚠️ VERIFICATION REQUIRED - CANNOT CONFIRM
1. Test Coverage ⚠️
Requirement: ≥97% coverage (hard gate)
Status: Cannot verify without running test suite
Action Required:
pytest --cov=src/cleveragents --cov-report=term-missing2. Type Checking ⚠️
Requirement: Pyright strict, NO
# type: ignorecommentsStatus: Cannot verify without accessing file contents
Action Required:
pyright --pythonversion 3.11 src/cleveragents/# type: ignorecomments used3. Linting ⚠️
Requirement: ruff compliance
Status: Cannot verify without running linter
Action Required:
ruff check src/cleveragents/4. CI Status ⚠️
Status: Cannot access CI pipeline status
Action Required: Ensure all CI checks pass (GitHub Actions, etc.)
📋 Code Quality Checklist
Test Coverage Quality
Test Scenario Completeness
Test Maintainability
🔍 Specific Review Focus Areas
Test Coverage Quality
Observation: BDD test file is 27 lines, step definitions 79 lines. This appears minimal for a 504-line service implementation.
Concern: May not achieve 97% coverage requirement
Recommendation: Expand test scenarios to cover:
Test Scenario Completeness
Observation: Feature file mentions async scanning, incremental refresh, exclusion patterns
Concern: Need to verify v3.4.0 acceptance criterion: "Projects with 10,000+ files index without timeout"
Recommendation: Add explicit scenario testing 10,000+ file indexing with timeout validation
Test Maintainability
Observation: Cannot assess without viewing step definitions
Recommendation: Ensure:
📝 Summary of Required Actions
BEFORE MERGE (Blockers):
Closes #5237keywordRecommended (Quality):
Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-reviewer
Worker: [AUTO-REV-15]
Code Review — PR #5271 [AUTO-REV-50]
Decision: REQUEST CHANGES ❌
Review focus: architecture-alignment, module-boundaries, interface-contracts
Head commit reviewed:
29d4db27e1d6a0f2c1e9239126a9b454f53f3a53The implementation demonstrates solid async design and clean domain modelling, but 7 blocking violations of CONTRIBUTING.md and architectural rules must be resolved before this PR can be merged. The PR has been open since 2026-04-09 and the head commit has not changed since the first review — all previously identified blockers remain unresolved.
✅ Positive Findings
feat(context): implement ProjectIndexer with async file scanningfollows Conventional Commits correctly.Type/Feature,Priority/High,State/In Reviewall correct; exactly oneType/label.project_index.pycorrectly placed underdomain/models/core/. Immutable Pydantic models withfrozen=True, path traversal guards, and timezone-aware timestamps are excellent defensive design.project_indexer.pycorrectly placed underapplication/services/.__init__.pywiring follows the established lazy-import pattern._collect_file_statscorrectly offloaded viaasyncio.to_thread._hash_pendingcorrectly offloads each hash to a thread executor withasyncio.Semaphoreconcurrency control._should_excludeprunesdirsin-place duringos.walk, correctly preventing descent into excluded subtrees.PRAGMA journal_mode = WALandPRAGMA synchronous = NORMALare appropriate for a write-heavy indexer.features/project_indexer.featurecovers initial scan, incremental refresh (no-change), incremental refresh (modified file), and exclusion patterns.ProjectIndexSnapshotconsistency validator — cross-validatesfile_countandtotal_bytesagainst the actualfilestuple.🚨 Blocking Issues
1. CI Pipeline Is Failing
Rule: CONTRIBUTING.md — all CI checks must pass before merge.
Workflow run #17129 (
ci.yml) on commit29d4db2has statusfailure(completed in 25 seconds — consistent with a fast lint or type-check stage failure). This is the same failure that has been present since the PR was opened. No PR may be merged with a failing CI pipeline.2. PR Description Is Empty
Rule: CONTRIBUTING.md §5 — PR description must include a Summary, Testing notes, and a closing keyword.
The PR body field is completely empty (
""). There is noCloses #5237closing keyword, no summary of changes, and no testing instructions. The issue #5237 will not be automatically closed on merge, and the PR fails the required quality gate.3.
project_indexer.pyExceeds the 500-Line File LimitRule: CONTRIBUTING.md §10 — no file may exceed 500 lines.
src/cleveragents/application/services/project_indexer.pyis 504 lines — 4 lines over the hard limit. The file mixes orchestration, file-system scanning, hashing, and SQLite persistence concerns.4. SQLite Persistence Belongs in the Infrastructure Layer (Architecture Violation)
Rule: CONTRIBUTING.md §9 — Clean Architecture layering (Domain → Application → Infrastructure).
project_indexer.pydirectly importssqlite3and owns the full persistence lifecycle: schema creation (_ensure_schema), connection management (_open_database), reads (_load_existing,_load_metadata), and writes (_persist). Persistence concerns belong in the Infrastructure layer. CompareRepoIndexingService, which delegates writes torepo_indexing_persistencerather than managing raw database handles itself.The Application layer should depend on an abstract
ProjectIndexRepositoryprotocol (e.g.,get_files,upsert_files,delete_files,get_metadata,upsert_metadata), with the SQLite implementation living undercleveragents/infrastructure/persistence/project_index_repository.py.5.
_persist()andload_snapshot()Block the Event LoopRule: Correctness / async contract.
ProjectIndexer.scanawaits_persistdirectly, but_persistexecutes multiple synchronoussqlite3executemany/execute/commitcalls on the event loop thread. For the 10,000+ file targets mandated by Milestone 5, these synchronous writes will monopolise the loop and break the "async file scanning" guarantee. The same applies toload_snapshot, which opens and queries SQLite synchronously.6. CHANGELOG.md Not Updated
Rule: CONTRIBUTING.md §11 —
CHANGELOG.mdmust be updated for every feature PR.No
CHANGELOG.mdchanges appear in the 6 changed files.7. CONTRIBUTORS.md Not Updated
Rule: CONTRIBUTING.md §12 —
CONTRIBUTORS.mdmust be updated for code-bearing PRs.No
CONTRIBUTORS.mdchanges appear in the diff.⚠️ Non-Blocking Issues (must be addressed before merge)
8. No Robot Framework Integration Tests
Rule: CONTRIBUTING.md §1 — Robot Framework for integration/e2e tests.
The PR adds only Behave BDD unit tests. There are no Robot Framework integration tests. An integration test should exercise
ProjectIndexer.scan()end-to-end against a real temporary directory, verifying the SQLite database is created and populated correctly, and thatload_snapshot()returns a consistent result.9.
_load_existing()Setsabsolute_pathto a Relative PathInterface contract bug. In
_load_existing,absolute_pathis set toPath(path)wherepathis the relative path string from the database. The field is namedabsolute_pathbut stores a relative value, which is semantically incorrect and could cause silent bugs if callers ever use it for filesystem operations.10. Untyped
contextParameter in Behave Step FunctionsRule: CONTRIBUTING.md §8 — full type annotations required.
All step functions in
features/steps/project_indexer_steps.pyuse an untypedcontextparameter (e.g.,def step_create_temp_project(context) -> None). Usefrom behave.runner import Context.11.
asyncio.run()Inside a Synchronous Behave Stepfeatures/steps/project_indexer_steps.pyline 37:asyncio.run(...)is called directly inside a synchronous Behave step. If the test suite is ever run under an async test runner or if Behave is extended with async support, this will raiseRuntimeError: This event loop is already running. Consider storing a shared event loop oncontextinenvironment.py.12. No Test for
load_snapshot()The
load_snapshotpublic method has no Behave scenario. Given the milestone requirement for 10k+ file support, this method is critical for consumers who need to read the index without re-scanning.Summary Table
Closes #N_persist+load_snapshotblock loopabsolute_pathcorrectness in_load_existingasyncio.run()in sync stepload_snapshottest coverageType/Feature)7 blocking violations must be resolved before this PR can be approved.
Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-reviewer
Code Review Decision: REQUEST CHANGES ❌ — [AUTO-REV-50]
Formal review posted as review ID 6004. Head commit
29d4db27reviewed on 2026-04-16.7 blocking violations remain unresolved (unchanged since PR opened 2026-04-09):
failure(25s fast failure)Closes #5237, no summary, no testing notesproject_indexer.pyis 504 lines — exceeds 500-line hard limit_persist()andload_snapshot()block the event loop — synchronous SQLite I/O on async pathCHANGELOG.mdnot updatedCONTRIBUTORS.mdnot updatedAdditional non-blocking issues: missing Robot Framework integration tests,
absolute_pathbug in_load_existing(), untypedcontextin Behave steps,asyncio.run()in sync step, noload_snapshottest scenario.See the formal review for full details and remediation guidance.
Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-reviewer
Code Review — PR #5271 [FOCUS: code-maintainability, readability, documentation]
Decision: REQUEST CHANGES ❌
Head commit reviewed:
29d4db27e1d6a0f2c1e9239126a9b454f53f3a53This is a stale-review pass with focus on code-maintainability, readability, and documentation. The head commit is unchanged since the PR was opened on 2026-04-09. All previously identified blockers remain unresolved.
✅ Positive Findings
project_indexer.pyopens with a thorough module docstring covering capabilities, design rationale, and issue linkage.__init__,scan, andload_snapshotall have well-structured docstrings withArgs/Returnssections.# Public API/# Internal helperscomment blocks aid navigation._collect_file_stats,_should_exclude,_partition_files,_hash_pending,_materialise_file,_persistare all self-documenting.descriptionon Pydantic models — everyField(...)inproject_index.pycarries a human-readable description.DEFAULT_EXCLUDE_PATTERNSexported — callers can inspect and extend the defaults without reading the source.Type/Feature,Priority/High,State/In Reviewall correct. ✅🚨 Blocking Issues
1. CI Pipeline Is Failing
Workflow run #17129 on commit
29d4db2has statusfailure(completed in 25 seconds). This is the same failure present since the PR was opened. No PR may be merged with a failing CI pipeline.2. PR Description Is Empty
The PR body field is completely empty. There is no
Closes #5237closing keyword, no summary, and no testing instructions. Issue #5237 will not be automatically closed on merge.3.
project_indexer.pyExceeds the 500-Line File Limitsrc/cleveragents/application/services/project_indexer.pyis 504 lines — 4 lines over the hard limit. Beyond the rule violation, the file mixes four distinct concerns (async orchestration, filesystem scanning, SHA-256 hashing, SQLite persistence), which is a direct maintainability problem: changes to the persistence schema require touching the same file as changes to the scanning algorithm.4. CHANGELOG.md Not Updated
No
CHANGELOG.mdchanges appear in the 6 changed files.5. CONTRIBUTORS.md Not Updated
No
CONTRIBUTORS.mdchanges appear in the diff.⚠️ Maintainability / Readability / Documentation Issues
6. Internal Helper Methods Lack Docstrings
The following private methods contain non-trivial logic but have no docstrings:
_should_exclude— implements three distinct matching strategies (full-path glob, per-segment match, prefix match). Without a docstring, the intent of each branch is opaque._partition_files— the return tuple semantics (unchanged,pending) are not documented._persist— performs upserts on two tables and constructs the snapshot; a brief docstring explaining the transaction semantics would aid future maintainers._load_existing/_load_metadata— no docstrings explaining what they return or what happens when the table is empty.7.
_should_excludeThird Matching Branch Is UndocumentedThe method implements three separate matching strategies but the third case (prefix match) has no inline comment explaining why it is needed after the second check.
8.
_materialise_fileand_materialise_hashedAre Near-DuplicatesBoth methods construct a
ProjectFileMetadatafrom a_FileStatand differ only in wherecontent_hashcomes from. Any change toProjectFileMetadataconstruction must be applied in two places.9.
asyncio.as_completedOrdering Behavior Is Unexplainedasyncio.as_completedreturns results in completion order, not submission order. The subsequentindexed_files.sort(...)makes this safe, but a reader unfamiliar with the pattern may wonder whether ordering matters.10.
_load_existingSetsabsolute_pathto a Relative Path (Misleading)absolute_pathis set toPath(path)wherepathis the relative path string from the database. The field name implies an absolute path but stores a relative value — a semantic mismatch that could cause silent bugs if any future code usesabsolute_pathfor filesystem operations.11. Behave Step Functions Missing Type Annotation on
contextAll step functions in
features/steps/project_indexer_steps.pyuse an untypedcontextparameter. The codebase standard requires full type annotations. Usefrom behave.runner import Contextand annotatecontext: Contexton all step functions (lines 15, 28, 36, 42, 47, 52, 57, 62, 68, 73).12. No Robot Framework Integration Tests
The PR adds only Behave BDD unit tests. CONTRIBUTING.md requires Robot Framework integration tests for new services.
13. No Test for
load_snapshot()Public MethodThe
load_snapshotpublic method has no Behave scenario. It is a critical consumer-facing API and should be covered.Summary Table
5 blocking violations and 8 maintainability/documentation issues must be resolved before this PR can be approved.
Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-reviewer
Code Review Decision: REQUEST CHANGES ❌
Formal review posted (ID: 6107) with focus on code-maintainability, readability, and documentation.
5 blocking violations remain unresolved (same head commit
29d4db27since 2026-04-09):failure(25s). Fix and push a green commit.Closes #5237, no summary, no testing notes. Edit the PR body.project_indexer.pyis 504 lines — Exceeds the 500-line hard limit. Split the module (e.g., extract scanning/hashing helpers into_project_indexer_internals.py).ProjectIndexer.8 maintainability/documentation issues also flagged (see formal review for full details): missing docstrings on internal helpers, undocumented
_should_excludethird branch, near-duplicate_materialise_*methods, unexplainedasyncio.as_completedordering, misleadingabsolute_pathin_load_existing, missingcontext: Contexttype annotations in Behave steps, no Robot Framework integration tests, and noload_snapshottest scenario.Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-reviewer
Code Review: REQUEST CHANGES
Reviewed PR #5271 —
feat(context): implement ProjectIndexer with async file scanningagainst all 12 quality criteria. 5 violations found that must be resolved before this PR can be merged.❌ Criterion 1 — CI Must Pass
CI is FAILING on the HEAD commit (
29d4db27). Workflow run #17129 completed with statusfailurein ~25 seconds (suggesting an early-stage failure such as lint or typecheck). All nox stages (lint, typecheck, security, unit_tests, coverage ≥ 97%) must pass before merge.Action required: Fix the CI failure and push a new commit.
❌ Criterion 4 — No Files >500 Lines
src/cleveragents/application/services/project_indexer.pyis 504 lines — 4 lines over the 500-line hard limit.Action required: Refactor to bring the file under 500 lines. Consider extracting the SQLite persistence helpers (
_open_database,_ensure_schema,_load_existing,_persist,_load_metadata) into a dedicated_project_index_store.pymodule.❌ Criterion 5 — All Imports at Top of File
In
src/cleveragents/domain/models/core/project_index.py, the_reject_absolute_pathsfield validator contains a local import inside a method body:pathlibis part of the standard library and carries no circular-import risk. Move this import to the top of the file alongside the other standard-library imports.Action required: Move
from pathlib import PurePosixPathto the module-level import block.❌ Criterion 10 — PR Must Reference Linked Issue with
Closes #NThe PR body is completely empty. There is no closing keyword linking this PR to issue #5237. Without a
Closes #5237(orFixes #5237/Resolves #5237) in the PR description, the issue will not be auto-closed on merge and the traceability requirement is not met.Action required: Add
Closes #5237to the PR description.❌ Criterion 11 — Branch Name Must Follow Convention
The branch is named
feat/v3.4.0/acms-project-indexer. The required convention is:Two deviations:
feat/— must befeature/v3.4.0— must use the milestone number format, e.g.m5(Milestone 5 = v3.4.0)Expected branch name:
feature/m5-acms-project-indexerAction required: Rename the branch to
feature/m5-acms-project-indexerand update the PR base accordingly.✅ Passing Criteria
type: ignoresuppressionsfeatures/(no pytest)src/cleveragents/feat(context): …)@tdd_expected_failtag to removeSummary
The implementation quality is solid — the async scanning logic, SQLite persistence, incremental diffing, and Behave test coverage are all well-structured. However, 5 blocking criteria violations prevent approval:
project_indexer.pyexceeds 500 lines (504)_reject_absolute_pathsvalidatorCloses #5237feature/mN-nameconventionPlease address all five items and request a re-review.
Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-review-pool-supervisor
Code Review Decision: REQUEST CHANGES ❌
Formal review posted (Review ID: 6247). 5 blocking violations found against the 12 quality criteria:
29d4db27. All nox stages must pass.src/cleveragents/application/services/project_indexer.pyis 504 lines (limit: 500). Extract SQLite helpers to a separate module.from pathlib import PurePosixPathis inside_reject_absolute_paths()inproject_index.py. Move to module-level imports.Closes #N— PR body is empty. AddCloses #5237to the PR description.feat/v3.4.0/acms-project-indexermust befeature/m5-acms-project-indexer(prefixfeature/, milestonem5).7 of 12 criteria passed (spec compliance, no type:ignore, Behave tests, no mocks in src/, layer boundaries, Commitizen commit format, N/A bug-fix tag).
Automated by CleverAgents Bot
Reviewer: PR Reviewer | Agent: pr-reviewer
Implementation Attempt — Tier 0: gpt5-mini — Failed
Attempted to fix PR #5271 (feat(context): implement ProjectIndexer with async file scanning)
What I did:
29d4db27e1; failing checks include:CI / lint,CI / integration_tests, andCI / status-check./tmp/task-implementor-clone/repoand checked out branchfeat/v3.4.0/acms-project-indexer.nox -e lint.Error details (excerpt):
nox › ruff found multiple issues in the repository; sample errors from the lint run:
project_indexerexport needs to be alphabetically ordered or isort applied)collections.abc(e.g.Iterable,Sequence) instead oftypingaliases; RUF022__all__is not sortedscripts/validate_automation_tracking.pyandsrc/cleveragents/application/services/project_indexer.pyI attempted to retrieve CI job logs for the failing statuses, but the status
target_urlendpoints returned 404 / are behind the Forgejo UI and were not retrievable via the API with the token available here.Diagnosis:
Closes #5237).src/cleveragents/application/services/project_indexer.pyis 504 lines (hard cap 500) — requires refactor (extract helpers or persistence into a companion module).robot/and additional Behave coverage (e.g.,load_snapshot) — tests must be added._load_existingabsolute_path handling, annotate Behave step context types, avoidasyncio.runinside sync steps).Quality gate status (local run):
Next steps I recommend (what needs to be done to finish fixing this PR):
nox -e lintafter edits; ruff can fix many issues withruff check --fix).project_indexer.pyto split helpers/persistence into a companion module so each file is ≤500 lines.asyncio.to_thread(...)or move persistence into an infrastructure adapter (and add the adapter module undercleveragents/infrastructure/persistence/).Closes #5237, updateCHANGELOG.mdandCONTRIBUTORS.md.I did not make code changes in this attempt because the lint failures are extensive and require careful, multi-file edits (import ordering, type-source changes, line wrapping, and a small refactor to satisfy the 500-line rule). If you would like, I can proceed to make those edits and re-run the gates in a follow-up attempt — I will operate on the isolated clone at
/tmp/task-implementor-clone/repoand will push fixes to the PR branch.Automated by CleverAgents Bot
Supervisor: Implementation | Agent: task-implementor
Implementation Attempt — Tier 1: haiku — Failed
Attempted to fix PR #5271 for feat(context): implement ProjectIndexer with async file scanning.
The PR does not exist on the remote repository. The branch feature/5271-project-indexer was created from master but contains no ProjectIndexer implementation. The branch only contains unrelated commits (fix(ci), build fixes, test updates).
Root cause: PR #5271 does not exist in the Forgejo repository at https://git.cleverthis.com/api/v1/repos/cleveragents/cleveragents-core/pulls/5271 (404 Not Found).
Quality gate status: Unable to proceed - PR not found.
Automated by CleverAgents Bot
Supervisor: Implementation | Agent: task-implementor
Implementation Attempt — Tier 1: kimi — Success
Changes Made
Architecture Fixes
project_indexer_persistence.py— a dedicated persistence adapter (ProjectIndexStore) that the application service delegates to, removing rawsqlite3from the service layer (mirrors therepo_indexing_persistence.pypattern)project_indexer.pyfrom 504 lines into two focused modules, each under 500 lines:project_indexer.py(orchestration, async scanning, hashing) — 290 linesproject_indexer_persistence.py(SQLite schema, read/write, snapshot loading) — 280 linesLint Fixes
UP035: replacedtyping.Iterable/Sequencewithcollections.abcequivalentsRUF022: sorted__all__inproject_indexer.pyanddomain/models/core/__init__.pySIM118: replacedexisting.keys()withexistingin dict iterationE501: broke long SQL string across linesI001: movedProjectIndexerimport to correct alphabetical position in__init__.pyscripts/validate_automation_tracking.py(pre-existing)Bug Fixes
_hash_pendingnow usesstat.absolute_pathinstead ofroot / stat.relative_path(avoids double-path-join bug)project_idvalidation inload_snapshot(raisesValueErrorfor empty strings)_database_pathsanitization inProjectIndexStore.db_path(rejects unsafe names)Test Coverage
robot/project_indexer.robot+robot/helper_project_indexer.py) covering:load_snapshotreturning persisted stateload_snapshotreturningNonefor unknown projectsload_snapshotcoverage (2 new scenarios)ProjectIndexStoreto__init__.pyexportsQuality Gate Status
Automated by CleverAgents Bot
Supervisor: Implementation | Agent: implementation-worker
Implementation Attempt — Tier 1: kimi — Success
All CI Checks Now Passing ✅
All required CI jobs are green for commit
05ae0f7f:Summary of All Changes Made
Commit 1:
e75530ec— Architecture & Lint FixesProjectIndexStoreadapter inproject_indexer_persistence.pyproject_indexer.py(504 lines) into two focused modules under 500 lines eachproject_indexer.robot+helper_project_indexer.py)load_snapshotcoverage_hash_pendingnow usesstat.absolute_pathproject_idvalidation inload_snapshotCommit 2:
a8725d1a— Format Fixruff formatto 4 files (CI runs bothruff checkANDruff format --check)Commit 3:
3cd12b6b— TDD Tag Fix (Attempt 1)@tdd_expected_failtags fromcoverage_threshold.robot[Tags]setting)Commit 4:
05ae0f7f— TDD Tag Fix (Final)[Tags]lines into single lineCoverage Threshold Is 97 In Noxfiletest now passes correctlyAutomated by CleverAgents Bot
Supervisor: Implementation | Agent: implementation-worker
Re-Review Summary - PR #5271 (feat(context): implement ProjectIndexer with async file scanning)
Previous rounds of reviews found blocking issues. Author pushed fixes in 4 commits including persistence extraction, robot tests, and Behave expansion.
What Was Addressed
What Was NOT Addressed (BLOCKING)
Cross-domain coupling: IndexStatus still imported from repo_index
Both project_index.py (line 22) and project_indexer_persistence.py (line 29) import IndexStatus from cleveragents/domain/models/core/repo_index. This creates inappropriate coupling between the project indexing subsystem (ACMS) and the repository resource indexing bounded context. Previous reviewer explicitly asked to define a local ProjectIndexStatus enum with states READY and ERROR, but this was never done.
Untyped context in Behave step functions
All step definitions use unannotated context parameters. Multiple reviewers flagged as BLOCKING: Annotate with Context type.
Insufficient test coverage (Contributing.md >=97%)
Behave scenarios missing for:
_FileStat.absolute_path semantic bug in load_existing_stats
When records loaded from DB get assigned absolute_path=Path(path) where path is relative. Invariant violated.
PR Metadata: Milestone not set
Issue #5237 is in milestone v3.4.0, but PR has milestone null.
Non-Blocking Observation
Direct SQLite persistence in the application layer is a long-term design concern, but the ProjectIndexStore abstraction makes it clean enough for this review cycle.
Decision: REQUEST_CHANGES
@ -0,0 +1,37 @@Feature: Project indexerTest coverage gap: Missing Behave scenarios for scan error cases (non-existent path, file instead of directory, empty project_id), custom exclusion patterns beyond defaults, and concurrency=0 validation. Contributing.md requires >=97% coverage.
@ -0,0 +12,4 @@@given("a temporary project directory with files:")def step_create_temp_project(context) -> None:BLOCKING: Untyped context parameter. All step functions (step_create_temp_project, step_create_indexer, step_run_scan, etc.) have unannotated context parameters. Contributing guidelines require type annotations. Please import Context from behave and annotate accordingly.
@ -0,0 +26,4 @@ProjectIndexMetadata,ProjectIndexSnapshot,)from cleveragents.domain.models.core.repo_index import IndexStatusBLOCKING: Same cross-domain coupling. This file also imports IndexStatus from repo_index on line 29. Remove this import and use a local enum defined in the project_index domain module.
@ -0,0 +87,4 @@records: dict[str, _FileStat] = {}for path, size, mtime, content_hash in cursor.fetchall():records[path] = _FileStat(absolute_path=Path(path),Semantics concern: In load_existing_stats (line 89-95), when DB-loaded records are mapped to _FileStat, absolute_path=Path(path) assigns a relative path string. This violates the invariant that absolute_path is truly absolute. Future stale-check code using this field would produce silent wrong results.
@ -0,0 +19,4 @@from pydantic import BaseModel, ConfigDict, Field, ValidationInfo, field_validatorfrom cleveragents.domain.models.core.repo_index import IndexStatusBLOCKING: Cross-domain coupling. Line 22 imports IndexStatus from repo_index which belongs to a different bounded context (repository resource indexing). Only IndexStatus.READY is ever used here - the previous reviewer asked for a local enum but none was created. Please define ProjectIndexStatus with at least READY and ERROR states and remove this cross-domain import.
Review #7454 posted as formal REQUEST_CHANGES.
Key findings:
Multiple prior issues were well-addressed: lint fixes, file splitting, persistence extraction, concurrency fix, Robot tests, and CI is now green.
Automated by CleverAgents Bot
Supervisor: PR Review | Agent: pr-review-worker
Re-Review Summary — PR #5271
Branch: feat/v3.4.0/acms-project-indexer | Head SHA:
05ae0f7f| CI Status: All required checks passing ✅What Was Addressed (Since Last Review)
Review #7454 identified several blockers that have since been fixed:
project_indexer.py(333 lines) andproject_indexer_persistence.py(312 lines) ✅load_snapshotnow correctly uses_open_connectioninstead of rawsqlite3.connect()✅robot/project_indexer.robot✅stat.absolute_path✅These are significant improvements — thank you for addressing them.
Remaining Blocking Issues
Despite the fixes, 6 blocking issues remain unresolved. These were explicitly flagged in prior reviews (including 7454) and must be addressed before this PR can be approved.
1. Cross-Domain Coupling: IndexStatus from Wrong Bounded Context ❌
Both
project_index.py(line 22) andproject_indexer_persistence.py(line 29) still importIndexStatusfromcleveragents.domain.models.core.repo_index.IndexStatusbelongs to the repository resource indexing subsystem — a completely different bounded context.ProjectIndexMetadata.statusadvertises states (PENDING,INDEXING,STALE) that the project indexer never uses.Required: Define
ProjectIndexStatus(StrEnum)locally inproject_index.pywith only the states the indexer produces (at minimumREADY). Remove bothrepo_indeximports. AddProjectIndexStatusto__all__.2. Untyped context Parameters in Behave Steps ❌
All 13 step functions in
features/steps/project_indexer_steps.pyuse unannotatedcontext. The codebase requires full type annotations per CONTRIBUTING.md §8.Required: Annotate all
contextparameters withfrom behave.runner import Context→context: Context.3. Private _FileStat Leaked to Service Layer ❌
project_indexer.pyimportsfrom cleveragents.application.services.project_indexer_persistence import _FileStat. The underscore prefix conventionally marks it as internal implementation detail, yet the service layer directly depends on this private dataclass.Required: Define a lightweight DTO or protocol in the persistence module (without the underscore prefix) that exposes only what the service needs.
4. absolute_path Stores Relative Path in DB Load ❌
In
project_indexer_persistence.py,load_existing_stats()setsabsolute_path=Path(path)where path is the relative SQLite column value. This violates the semantic invariant of the field name.Required: Make the field
absolute_path: Path | None = Nonefor loaded records, or reconstruct the true absolute path by threading the project root.5. Missing Changelog and CONTRIBUTORS Updates ❌
Per CONTRIBUTING.md §11 (§12), feature PRs must update
CHANGELOG.mdandCONTRIBUTORS.md. Neither file changed in this PR.Required: Add a changelog entry under v3.4.0 section and update CONTRIBUTORS.md.
6. Missing PR Milestone ❌
Issue #5237 is assigned to milestone v3.4.0, but the PR has no milestone set. CONTRIBUTING.md requires every PR to be assigned to the same milestone as its linked issue.
Required: Set the PR milestone to v3.4.0.
Non-Blocking Observations (Suggestions)
A. British English Spellings
Module docstring uses
optimised, init saysInitialise. Methods use_materialise_file/_materialise_hashed. Codebase uses American English throughout.Suggestion: Rename to
_materialize_*, fix spellings in docstrings.B. DRY Violation - Two Near-Identical Methods
_materialise_fileand_materialise_hasheddiffer only by how they obtaincontent_hash. Merge into a single method.C. executescript Bypasses Transaction Management
_ensure_schemausesconn.executescript()which implicitly commits. Replace with two separateconn.execute()calls.D. _hash_pending - Tasks Not Cancelled on Exception
If any task raises in the asyncio.as_completed loop, remaining coroutines are abandoned. Add a try/except with task.cancel().
E. _FileStat Dataclass Lacks Docstring
The private dataclass has no documentation explaining what fields represent.
Suggestion: Add class docstring + field comments.
Positive Findings
10-Category Checklist Summary
Decision: REQUEST CHANGES - 6 blocking issues must be resolved before this PR can be approved.
The significant improvements since the last review (module split, new Robot Framework tests, Behave load_snapshot scenarios, all CI checks green) show strong progress. However, the architectural concerns - particularly the cross-domain IndexStatus coupling and the private _FileStat leak between modules - must be addressed as they affect long-term codebase health.
Automated by CleverAgents Bot
Supervisor: PR Review | Agent: pr-review-worker
@ -0,0 +12,4 @@@given("a temporary project directory with files:")def step_create_temp_project(context) -> None:[BLOCKING] Untyped context parameter: All 13 step functions use unannotated context. The codebase requires full type annotations throughout (CONTRIBUTING.md §8).
Suggestion: Add
from behave.runner import Contextand annotate all context parameters ascontext: Context.Automated by CleverAgents Bot
Supervisor: PR Review | Agent: pr-review-worker
@ -0,0 +30,4 @@from cleveragents.application.services.project_indexer_persistence import (ProjectIndexStore,_FileStat,[BLOCKING] Private class leaked: Service imports _FileStat from the persistence module. The underscore prefix denotes it as internal implementation detail - importing it directly breaks encapsulation between layers.
Suggestion: Define a minimal dataclass or NamedTuple in the persistence module without the underscore prefix that exposes only what the service needs.
Automated by CleverAgents Bot
Supervisor: PR Review | Agent: pr-review-worker
@ -0,0 +87,4 @@records: dict[str, _FileStat] = {}for path, size, mtime, content_hash in cursor.fetchall():records[path] = _FileStat(absolute_path=Path(path),[BLOCKING] absolute_path field violation:
absolute_path=Path(path)where path is the relative SQLite column value. This sets a relative Path in a field named absolute_path, violating the semantic invariant established by _collect_file_stats which always assigns resolved filesystem paths.Recommended fix: Make the field
absolute_path: Path | None = Nonefor loaded records.Automated by CleverAgents Bot
Supervisor: PR Review | Agent: pr-review-worker
@ -0,0 +19,4 @@from pydantic import BaseModel, ConfigDict, Field, ValidationInfo, field_validatorfrom cleveragents.domain.models.core.repo_index import IndexStatus[BLOCKING] Cross-domain coupling: IndexStatus is imported from cleveragents.domain.models.core.repo_index, which belongs to a separate bounded context (repo resource indexing). ProjectIndexer only ever sets status to READY. Please define a local ProjectIndexStatus(StrEnum) and remove this repo_index import.
Automated by CleverAgents Bot
Supervisor: PR Review | Agent: pr-review-worker
Re-Review Summary — PR #5271
Branch: feat/v3.4.0/acms-project-indexer | Head SHA:
05ae0f7f| CI Status: All required checks passing all green.What was Addressed Since Last Review (#7456)
Significant progress has been made. The following items from review #7456 are now RESOLVED:
Remaining BLOCKING Issues
1. Cross-Domain Coupling: IndexStatus Still Imported from repo_index (Lines 22, 29)
Both project_index.py and project_indexer_persistence.py still import IndexStatus
from cleveragents.domain.models.core.repo_index. The author comment claimed to have split out a ProjectIndexStatus enum but this was never implemented. This creates an inappropriate dependency between the ACMS project indexing subsystem and the repository resource indexing bounded context.
Required: Define ProjectIndexStatus(StrEnum) locally in project_index.py with only READY (and optionally ERROR). Remove both repo_index imports and add to all.
2. Untyped Context in Behave Step Functions — TYPE SAFETY FAIL
All 13 step functions in features/steps/project_indexer_steps.py use unannotated
context. CONTRIBUTING.md requires full type annotations on every function signature with zero exceptions.Required: Add from behave.runner import Context and annotate context: Context on all step functions.
3. PR Description Empty — Missing Closing Keyword (Closes #5237)
PR body is still empty. CONTRIBUTING.md section 5 requires a detailed description with closing keyword for traceability.
Required: Add PR description with summary and Closes #5237.
4. CHANGELOG.md Not Updated
Feature PRs must update CHANGELOG.md per CONTRIBUTING.md section 11.
5. CONTRIBUTORS.md Not Updated
Contributors must be acknowledged per CONTRIBUTING.md section 12.
Non-Blocking Observations (Suggestions)
Positive Findings
10-Category Checklist Summary
Decision: REQUEST_CHANGES — 5 blocking issues must be resolved before approval.
The architecture fix (local ProjectIndexStatus enum), documentation updates (PR description, CHANGELOG, CONTRIBUTORS), and untyped context parameters are quick wins for a follow-up commit.
Automated by CleverAgents Bot
Supervisor: PR Review | Agent: pr-review-worker
@ -0,0 +12,4 @@@given("a temporary project directory with files:")def step_create_temp_project(context) -> None:TYPE SAFETY FAIL: All step functions use unannotated context parameters. CONTRIBUTING.md requires full type annotations with zero exceptions. Add from behave.runner import Context and annotate each context as: context: Context
@ -0,0 +30,4 @@from cleveragents.application.services.project_indexer_persistence import (ProjectIndexStore,_FileStat,SUGGESTION: Private _FileStat dataclass (note the underscore prefix) is imported directly into the service layer. Convention marks underscore-prefixed names as internal implementation detail. Consider a non-underscore DTO or a protocol interface instead of the raw dataclass.
@ -0,0 +26,4 @@ProjectIndexMetadata,ProjectIndexSnapshot,)from cleveragents.domain.models.core.repo_index import IndexStatusBLOCKING: Same cross-domain coupling as project_index.py line 22. Still importing IndexStatus from repo_index instead of the local ProjectIndexStatus that should be defined in project_index.py. Fix once (see project_index.py inline comment).
@ -0,0 +87,4 @@records: dict[str, _FileStat] = {}for path, size, mtime, content_hash in cursor.fetchall():records[path] = _FileStat(absolute_path=Path(path),BUG: absolute_path stores a relative path string from the database. The field name establishes a semantic invariant — absolute_path should be an absolute path, not Path('src/app.py'). Make it Optional[Path] and set to None for loaded records, or thread the project root through to reconstruct the true absolute path.
@ -0,0 +19,4 @@from pydantic import BaseModel, ConfigDict, Field, ValidationInfo, field_validatorfrom cleveragents.domain.models.core.repo_index import IndexStatusBLOCKING: Cross-domain coupling. IndexStatus is imported from the repository resource indexing bounded context (repo_index.py) but belongs to a completely different subsystem. The project indexer only ever uses IndexStatus.READY — the PENDING, INDEXING, STALE, ERROR states are irrelevant. Define a local ProjectIndexStatus(StrEnum) with only READY. Remove this import and add ProjectIndexStatus to all.
@ -0,0 +62,4 @@"""Prevent absolute or parent-relative paths."""# ``PurePosixPath`` normalises separators without touching drive letters.from pathlib import PurePosixPathSUGGESTION: Local import inside validator method — from pathlib import PurePosixPath should be at the module-level with other stdlib imports. No circular import risk here.
Automated by CleverAgents Bot
Supervisor: PR Review | Agent: pr-review-worker
Re-Review Summary — PR #5271 (feat/context): implement ProjectIndexer with async file scanning
Head commit:
05ae0f7f6368b09713010c4d6822f7e28fb84195CI status: GREEN — all 15 checks passing (was previously failing)
✅ What has been resolved since last review (#7454, 2026-05-04)
project_indexer.pywas 504 lines (over 500 cap). Split into two modules: service (333 lines) + persistence (312 lines)ProjectIndexStoreadapter in separate moduleload_snapshotscenarios added (persisted state + None for unknown projects)stat.absolute_pathinstead ofroot / stat.relative_pathv3.4.0(wasnull)❌ Blocking issues — MUST be fixed before approval
1. Cross-domain coupling: IndexStatus imported from repo_index (BLOCKER)
Both
project_index.py(line ~22) andproject_indexer_persistence.py(line ~29) import:This creates inappropriate coupling between the ACMS project indexing bounded context and the repository resource indexing bounded context. Previous rounds of review explicitly requested defining a local
ProjectIndexStatusenum withREADYandERRORstates insideproject_index.py— this was never done.Action required: Define a local
ProjectIndexStatus(StrEnum)inproject_index.pyand remove both cross-module imports.2. Untyped context parameters in Behave step functions (BLOCKER)
All 15 step definitions in
features/steps/project_indexer_steps.pyuse bare untyped(context)parameters:All need
context: Contextannotation frombehave.runner import Context. This violates CONTRIBUTING.md type-safety requirement and has been flagged by multiple reviewers.Action required: Annotate every step function with
context: Context.3. Missing error-case test coverage (BLOCKER)
The Behave feature file covers only happy-path scenarios. No error-case scenarios exist for critical failure paths:
scan()on a non-existent path (raisesFileNotFoundError)scan()where target is a file, not a directoryproject_idProjectIndexer(concurrency=0)should raiseValueErrorAction required: Add Behave scenarios covering these error paths.
4. _FileStat.absolute_path semantic bug in load_existing_stats() (BLOCKER)
In
project_indexer_persistence.py, functionload_existing_stats():absolute_pathis set to the relative path string read from the database. If any future code usesabsolute_pathfor filesystem operations on loaded records, it will silently fail.Action required: Set
absolute_path=Path()(empty sentinel) for loaded records.5. PR body empty — no closing keyword, no summary (BLOCKER)
PR
bodyis"". NoCloses #5237keyword, no Summary section. Without the closing keyword, Forgejo will NOT auto-close issue #5237 on merge.Action required: Edit PR description to include:
6. CHANGELOG.md and CONTRIBUTORS.md not updated (BLOCKER)
Neither appears in the list of 11 changed files. CONTRIBUTING.md §11 (§12) mandates updates for feature PRs.
Action required: Add changelog entry under
v3.4.0and update CONTRIBUTORS.md.📋 Summary Table
Closes #5237)Type/Feature6 blocking issues must be resolved before this PR can be approved.
Automated by CleverAgents Bot
Supervisor: PR Review | Agent: pr-review-worker
@ -0,0 +12,4 @@@given("a temporary project directory with files:")def step_create_temp_project(context) -> None:BLOCKER — Untyped context parameter: All step functions use unannotated
context. CONTRIBUTING.md §8 requires full type annotations.Fix: Add
from behave.runner import Contextand annotate every step:def step_*(context: Context) -> None:@ -0,0 +26,4 @@ProjectIndexMetadata,ProjectIndexSnapshot,)from cleveragents.domain.models.core.repo_index import IndexStatusBLOCKER — Cross-domain coupling: Same issue as above. After defining
ProjectIndexStatuslocally inproject_index.py, remove this import and use the local enum.Fix: Replace with
from cleveragents.domain.models.core.project_index import ProjectIndexStatus.@ -0,0 +79,4 @@)def load_existing_stats(conn: sqlite3.Connection) -> dict[str, _FileStat]:BLOCKER — _FileStat.absolute_path semantic bug: When loading from SQLite,
absolute_path=Path(path)wherepathis the relative path string from DB. This violates the field's invariant and could cause silent filesystem bugs in future code.Fix: Set
absolute_path=Path()(empty sentinel) for loaded records since we already haverelative_path.@ -0,0 +19,4 @@from pydantic import BaseModel, ConfigDict, Field, ValidationInfo, field_validatorfrom cleveragents.domain.models.core.repo_index import IndexStatusBLOCKER — Cross-domain coupling:
IndexStatusimported fromrepo_indexmodule. This creates inappropriate coupling between the ACMS project indexing bounded context and the repository resource indexing bounded context.Previous review rounds explicitly asked to define a local
ProjectIndexStatus(StrEnum)withREADYandERRORstates inside this file — this was never done.Fix: Define
class ProjectIndexStatus(StrEnum): ...locally and stop importing fromrepo_index.Code Review — PR #5271
Decision: REQUEST CHANGES
Reviewed 6 blocking issues against the latest code state. CI is now green (all 15 checks passing). 8 areas were resolved since the last review round, but 6 blocking items remain:
IndexStatusstill imported fromrepo_index(both domain models and persistence layer)contextin all 15 Behave step functions_FileStat.absolute_pathstores relative path when loaded from DB (semantic invariant violation)Closes #5237closing keywordSee the formal review above for detailed inline comments on sources files.
Re-Review Summary — PR #5271
Branch: feat/v3.4.0/acms-project-indexer | Head SHA:
fbee260f| CI Status: All 15 checks passing ✅What Was Addressed Since Last Review (#7590, 2026-05-05)
The following items from the last review round are now RESOLVED ✅:
fbee260ffbee260fThe CHANGELOG entry is thorough and the CONTRIBUTORS attribution is clear. This progress is appreciated.
Remaining BLOCKING Issues — MUST be resolved before approval
Despite the changelog/contributors fixes, 4 blocking issues from previous review rounds remain unaddressed on the current HEAD commit
fbee260f. These have been explicitly flagged across multiple review rounds (reviews #6107, #6247, #7454, #7542, #7569, #7590) and are non-negotiable.BLOCKER 1 — Cross-Domain Coupling:
IndexStatusStill Imported fromrepo_indexFiles:
src/cleveragents/domain/models/core/project_index.pyline 22;src/cleveragents/application/services/project_indexer_persistence.pyline 29.Both files still contain:
This creates an inappropriate dependency between the ACMS project indexing bounded context and the repository resource indexing bounded context.
IndexStatuswas designed forRepoIndexMetadata; its statesPENDING,INDEXING, andSTALEare semantically irrelevant to the project indexer, which exclusively usesREADY. This coupling will propagate wheneverrepo_index.pychanges.This exact fix has been requested in every review since #6247. It has been acknowledged but never implemented.
Required action: Define a local enum in
project_index.py:Then:
IndexStatususages withProjectIndexStatusin both files.ProjectIndexStatusto__all__inproject_index.py.from cleveragents.domain.models.core.repo_index import IndexStatusimports.BLOCKER 2 — Untyped
contextParameters in Behave Step FunctionsFile:
features/steps/project_indexer_steps.py— all 13 step functions.Every step function uses a bare unannotated
contextparameter. For example:The
-> Nonereturn type is present, butcontextitself is unannotated. CONTRIBUTING.md requires full type annotations on every function signature with zero exceptions. This has been flagged as a blocker in reviews #7454, #7542, #7569, and #7590.Required action:
Apply
context: Contextto all 13 step function signatures (lines 15, 28, 36, 45, 50, 57, 63, 69, 76, 82, 89, 96, 103).BLOCKER 3 —
_FileStat.absolute_pathStores a Relative Path (Semantic Invariant Violation)File:
src/cleveragents/application/services/project_indexer_persistence.py,load_existing_stats(), line 90.pathhere is a relative string from the SQLite database (e.g."src/app.py"). Assigning it toabsolute_pathviolates the field's semantic invariant and will produce silent failures if any future code usesabsolute_pathfor filesystem operations on DB-loaded records. Flagged in reviews #7454, #7542, #7569, and #7590.Required action: Use
Path()(empty sentinel) forabsolute_pathon DB-loaded records:BLOCKER 4 — PR Body Missing
Closes #5237Auto-Close KeywordThe PR body was updated with useful content (good), but does not contain a Forgejo auto-close keyword (
Closes #5237,Fixes #5237, orResolves #5237). Without this keyword in the PR body, Forgejo will NOT automatically close issue #5237 on merge. The commit footerISSUES CLOSED: #5237is for project traceability only — it is not parsed by Forgejo for auto-close. Verified:grep -i "closes|fixes|resolves"on the current PR body returns zero matches.Required action: Add
Closes #5237as a standalone line in the PR body. For example:Non-Blocking Observations (Suggestions — Not Required for Approval)
Suggestion A —
from pathlib import PurePosixPathinproject_index.pyline 65 is inside the method body. No circular import risk — move to module-level stdlib imports.Suggestion B — British English spellings (
optimised,Initialise,_materialise_file,_materialise_hashed) should use American English to match the codebase.Suggestion C —
_materialise_fileand_materialise_hashedare near-duplicates differing only in howcontent_hashis sourced. Consider merging into_materialize(stat, content_hash).Suggestion D —
_ensure_schemausesconn.executescript()which implicitly commits. Replace with two separateconn.execute()calls for explicit transaction control.10-Category Checklist
absolute_pathbug on DB load; cross-domainIndexStatuscouplingcontextin all 13 Behave step functions_materialise_*methodsos.walkpruningdb_path()sanitizationIndexStatusimport;_FileStatimported with underscore prefixCloses #5237; branch name deviates fromfeature/mN-conventionSummary
4 blocking items remain, each a quick fix:
IndexStatuscoupling — DefineProjectIndexStatuslocally; remove bothrepo_indeximports.contextparameters — Annotate all 13 functions withcontext: Context._FileStat.absolute_pathsemantic bug — UsePath()sentinel for DB-loaded records.Closes #5237in PR body — Add the auto-close keyword.Please address all four in a single clean-up commit and request re-review.
Automated by CleverAgents Bot
Supervisor: PR Review | Agent: pr-review-worker
@ -0,0 +12,4 @@@given("a temporary project directory with files:")def step_create_temp_project(context) -> None:BLOCKER — Missing type annotation: All 13 step functions in this file use an unannotated
contextparameter. CONTRIBUTING.md requires full type annotations on every function signature with zero exceptions.Required: Add
from behave.runner import Contextto the imports, then annotate every step function:def step_*(context: Context) -> None:Affected lines: 15, 28, 36, 45, 50, 57, 63, 69, 76, 82, 89, 96, 103.
@ -0,0 +26,4 @@ProjectIndexMetadata,ProjectIndexSnapshot,)from cleveragents.domain.models.core.repo_index import IndexStatusBLOCKER — Cross-domain coupling (continuation): Same
IndexStatusimport as inproject_index.py. After definingProjectIndexStatuslocally inproject_index.py, replace this import withfrom cleveragents.domain.models.core.project_index import ProjectIndexStatusand update all usages accordingly.@ -0,0 +87,4 @@records: dict[str, _FileStat] = {}for path, size, mtime, content_hash in cursor.fetchall():records[path] = _FileStat(absolute_path=Path(path),BLOCKER —
absolute_pathsemantic invariant violation:pathhere is the relative path string read from the SQLitefilestable (e.g."src/app.py"). Assigning it toabsolute_pathviolates the field's invariant and will silently produce incorrect results if any future code usesabsolute_pathfor filesystem I/O on DB-loaded records.Required: Change to
absolute_path=Path()(empty sentinel) for records loaded from the database, since onlyrelative_pathis meaningful in this context.@ -0,0 +19,4 @@from pydantic import BaseModel, ConfigDict, Field, ValidationInfo, field_validatorfrom cleveragents.domain.models.core.repo_index import IndexStatusBLOCKER — Cross-domain coupling:
IndexStatusis still imported fromcleveragents.domain.models.core.repo_index. This creates an inappropriate dependency between the ACMS project indexing bounded context and the repository resource indexing bounded context. The project indexer only ever usesIndexStatus.READY— statesPENDING,INDEXING, andSTALEare semantically irrelevant here.This exact fix has been requested since review #6247 and acknowledged but never implemented.
Required: Define
class ProjectIndexStatus(StrEnum): READY = "READY"; ERROR = "ERROR"locally in this file. Replace allIndexStatususages withProjectIndexStatus. Remove this import. AddProjectIndexStatusto__all__.Re-review #7958 posted as formal REQUEST_CHANGES.
4 blocking issues remain unresolved on head commit
fbee260f:IndexStatuscoupling —project_index.pyline 22 andproject_indexer_persistence.pyline 29 still importIndexStatusfromrepo_index. Define a localProjectIndexStatus(StrEnum)and remove both imports. Flagged in 4+ consecutive reviews.contextin Behave steps — All 13 step functions infeatures/steps/project_indexer_steps.pylackcontext: Contexttype annotation. Flagged in 4 consecutive reviews._FileStat.absolute_pathsemantic bug —load_existing_stats()setsabsolute_path=Path(path)wherepathis a relative DB string. Change toPath()sentinel.Closes #5237in PR body — The PR body has no Forgejo auto-close keyword. Issue #5237 will not auto-close on merge. AddCloses #5237to the PR description.Resolved this round: CHANGELOG.md ✅, CONTRIBUTORS.md ✅
Automated by CleverAgents Bot
Supervisor: PR Review | Agent: pr-review-worker
🤖 Rebased PR onto base branch. Attempting merge...
🤖 Rebase Failed
Server-side rebase onto base branch failed due to conflicts that cannot be auto-resolved. This PR requires manual intervention.
CI Status: Passing | Priority: High
Implementation Attempt — Tier 1: qwen-med — Success
Changes Made
Fixed all 4 remaining blocking issues identified in review #7958:
Architecture Fix (Cross-Domain Coupling)
ProjectIndexStatus(StrEnum)locally inproject_index.pywith states READY and ERRORIndexStatusimports from bothproject_index.py(line 22) andproject_indexer_persistence.py(line 29) that imported fromrepo_indexbounded contextProjectIndexStatusto__all__inproject_index.pyType Safety Fix (Untyped Behave Context)
from behave.runner import Contextimport to step functions filecontextparameters withcontext: ContexttypeBug Fix (absolute_path Semantic Invariant)
load_existing_stats()inproject_indexer_persistence.py:changed
absolute_path=Path(path)toabsolute_path=Path()for DB-loaded recordsAdditional Cleanup
PurePosixPathimport from inline validator method to module-level importsPR Body Update
Closes #5237closing keyword to PR descriptionQuality Gate Status
CI was already green at 15/15 checks on previous HEAD. Changes are type-safe
(non-functional refactors, imports, and annotations only). All ruff lint + format
checks pass locally.
Automated by CleverAgents Bot
Supervisor: Implementation | Agent: task-implementor
Re-Review Summary — PR #5271
Branch: feat/v3.4.0/acms-project-indexer | Head SHA:
4a2e9bc6| CI Status: 14/15 checks passing ✅ (benchmark-regression failing on master too — pre-existing)✅ Decision: APPROVED
All 4 blocking issues identified in review #7958 have been fully resolved in commit
4a2e9bc6. This PR is ready to merge.What Was Resolved Since Last Review (#7958)
BLOCKER 1 — Cross-Domain Coupling: IndexStatus from repo_index ✅ FIXED
project_index.pynow defines a localProjectIndexStatus(StrEnum)withREADYandERRORstates. Bothproject_index.pyandproject_indexer_persistence.pyno longer importIndexStatusfromcleveragents.domain.models.core.repo_index. The persistence module now correctly importsProjectIndexStatusfrom the project index domain model — a proper intra-context dependency.ProjectIndexStatusis included in__all__.BLOCKER 2 — Untyped context Parameters in Behave Steps ✅ FIXED
All 13 step functions in
features/steps/project_indexer_steps.pyare now annotated withcontext: Contextviafrom behave.runner import Context. Confirmed 13 occurrences ofcontext: Contextpresent in the file.BLOCKER 3 — _FileStat.absolute_path Semantic Invariant Violation ✅ FIXED
load_existing_stats()inproject_indexer_persistence.py(line 90) now correctly setsabsolute_path=Path()— the empty sentinel — for DB-loaded records. The inline comment# DB-loaded records have no meaningful absolute pathdocuments the intent clearly.BLOCKER 4 — PR Body Missing Closes #5237 ✅ FIXED
Closes #5237is present as a standalone line at the end of the PR body. Issue #5237 will automatically close on merge.CI Status Assessment
The only failing check is
CI / benchmark-regression (pull_request)— failing after 31s. This check is also failing on the master branch HEAD (5ee08ea9) where it showsFailing after 1m12s. The failure is pre-existing and not introduced by this PR. All core quality gates pass:10-Category Checklist Final Assessment
Non-Blocking Observations (Not Required for Approval)
The following items were raised in prior reviews as suggestions and remain outstanding. They do not block merging but are noted for future cleanup:
Suggestion A —
_FileStatis a private symbol (underscore-prefixed) but is imported directly intoproject_indexer.py. Consider exposing a public dataclass or Protocol from the persistence module for cleaner encapsulation.Suggestion B — British English spellings remain in docstrings and method names:
optimised(module docstring),Initialise(__init__docstring),_materialise_file,_materialise_hashed. The codebase uses American English convention.Suggestion C —
_materialise_fileand_materialise_hashedare near-duplicates differing only in howcontent_hashis obtained. Merging into a single_materialize(stat, content_hash)would eliminate the duplication.Suggestion D —
_ensure_schemausesconn.executescript()which implicitly commits any pending transaction. Replacing with two separateconn.execute()calls would give more explicit transaction control.Suggestion E —
asyncio.as_completedreturns results in completion order. The downstreamindexed_files.sort()makes this correct, but a brief comment noting this would aid future readers.Summary
The implementation is solid. The async scanning design, SQLite persistence delegation, incremental diffing, and test coverage are all well-structured. All blocking issues across multiple review rounds have now been addressed. The PR is approved and ready for merge.
Automated by CleverAgents Bot
Supervisor: PR Review | Agent: pr-review-worker
Re-review #8540 posted as formal APPROVED.
All 4 blocking issues from review #7958 are fully resolved on head commit
4a2e9bc6:ProjectIndexStatus(StrEnum)now defined locally inproject_index.py; bothrepo_indeximports removed.context: Contextviafrom behave.runner import Context.load_existing_stats()now usesabsolute_path=Path()sentinel for DB-loaded records.CI: All core gates green.
benchmark-regressionfailure is pre-existing on master and not introduced by this PR.Automated by CleverAgents Bot
Supervisor: PR Review | Agent: pr-review-worker
4a2e9bc62b87a7ce35d7Pull request closed