Skip to content

#213 Add run directory scanning and refactor ProjectScanner - #221

Merged
williamthorsen merged 7 commits into
mainfrom
213
Mar 7, 2026
Merged

#213 Add run directory scanning and refactor ProjectScanner#221
williamthorsen merged 7 commits into
mainfrom
213

Conversation

@williamthorsen

@williamthorsen williamthorsen commented Mar 7, 2026

Copy link
Copy Markdown
Owner

Closes #213

What

Adds run directory scanning infrastructure to run-core — a scanner (discoverRunDirectories), validator (validateRunDirectory), and CLI tool for checking and archiving invalid runs. Refactors factory's ProjectScanner to delegate to these new shared scanners and introduces a central configuration module.

Why

The directory scanning and validation logic was embedded in the factory app's ProjectScanner, making it unavailable for reuse. Extracting it into run-core enables both the factory app and a standalone CLI to scan, validate, and manage run directories with consistent behavior.

Details

Features

  • discoverRunDirectories in run-core/scanners scans a base path and returns discovered run directory entries
  • validateRunDirectory checks whether a discovered directory contains a valid run-index.json
  • CLI tool (run-core/cli.ts) for checking run directories and archiving invalid ones
  • Central FactoryConfig module in factory to manage environment-driven configuration (FACTORY_LOG_INVALID_RUNS)

Refactoring

  • ProjectScanner now delegates to run-core scanners instead of performing its own readdir/stat/parse logic, significantly reducing its complexity
  • Extracted isEnoent type guard into shared type-guards module in run-core

Fixes

  • Added error logging to scanner for per-entry archive handling failures

Tests

  • Added comprehensive tests for run-directory-scanner (238 lines) and run-directory-validator (161 lines)
  • Simplified project-scanner tests to mock the scanner module rather than low-level fs operations, reducing from ~450 to ~140 lines

Move the isEnoent type guard from run-data-parser.ts into a dedicated type-guards module and export it from the package root. This eliminates the duplicate implementation in Factory and provides a single shared source.
Add validateRunDirectory in scanners module that wraps parseRunData and returns a discriminated union (valid/invalid) instead of throwing. Covers all error categories: missing files, corrupt JSON, invalid schema, and missing companion log.
Add discoverRunDirectories that walks the project/ticket/run hierarchy for both layout patterns (with and without tickets/ subdirectory). Skips hidden directories and -interactive run directories.
Add factoryConfig object loaded from environment variables. Initial option: logInvalidRuns (FACTORY_LOG_INVALID_RUNS env var, defaults to false) to control whether invalid-run warnings are logged during project scanning.
Replace ProjectScanner's inline directory-walking and validation logic with shared discoverRunDirectories and validateRunDirectory from run-core/scanners. Reduce type-guards.ts to a re-export from run-core. Invalid-run warnings are suppressed by default; set FACTORY_LOG_INVALID_RUNS=true to re-enable them.
Add codeassembly-runs binary with two commands: check (list invalid run directories, exit 1 if any found) and archive (list then prompt to move invalid directories to tickets-archived/). Supports --path to override the base projects directory.
…ling

Replace silent error swallowing in run-directory-scanner with console.warn
messages that identify the failing path and error. The base-path catch, three
readdir catch handlers, and isDirectory now all log before returning fallback
values. isDirectory additionally distinguishes ENOENT (silent) from other
errors (warned). The CLI archive loop wraps each mkdir/rename in a per-entry
try/catch so a single failure no longer aborts the batch, and the summary
reports both succeeded and failed counts.
@williamthorsen williamthorsen self-assigned this Mar 7, 2026
@williamthorsen williamthorsen added scope:factory feature Added or improved external functionality scope:run-core labels Mar 7, 2026
@williamthorsen williamthorsen changed the title #213 * | feat: Add run directory scanning and refactor ProjectScanner #213: Add run directory scanning and refactor ProjectScanner Mar 7, 2026
@williamthorsen williamthorsen changed the title #213: Add run directory scanning and refactor ProjectScanner #213 Add run directory scanning and refactor ProjectScanner Mar 7, 2026
@williamthorsen
williamthorsen marked this pull request as ready for review March 7, 2026 15:04
@williamthorsen
williamthorsen merged commit 52e07b6 into main Mar 7, 2026
1 check passed
@williamthorsen
williamthorsen deleted the 213 branch March 7, 2026 15:05
williamthorsen added a commit that referenced this pull request May 4, 2026
agents-v0.2.0
- #525 fix: Extract Jira-style ticket IDs from author-prefixed branches (#528)
- #452 feat: Have reviewers write findings incrementally for interruption resilience (#523)
- feat: Prevent agents from using interactive prompts
- #506 feat: Pre-load reviewer context for unfamiliar third-party APIs (#517)
- #511 internal: Migrate work-types to a JSON SSOT with schema validation (#516)
- #430 feat: Add preferences.yaml schema and normalize default_remote (#509)
- #497 feat: Show pros and cons in a list instead of inline (#503)
- #501 fix: Default merge-pr to remote-only branch deletion via tristate flag (#504)
- #494 feat: Resolve merge-pr scope and type via a tested script (#502)
- #491 feat: Canonicalize finding icons; switch Suggestion to ☝️ (#500)
- #496 feat: Mark skips and successes in install/uninstall output (#499)
- #462 feat: Add advisability dimension to /assess-ticket (#498)
- #382 feat: Add merge-pr skill family and rename merge config section (#495)
- #490 feat: Codify design priorities: correctness over convenience (#493)
- #489 feat: Reframe `## What` guidance around outside-reader audience (#492)
- #486 feat: Surface recommendation-gradient format at point of use (#488)
- #484 feat: Adopt plural tickets_created and drop counts (#487)
- #473 feat: Adopt cost-aware three-lane disposition for findings and follow-ups (#485)
- #476 feat: Add recommendation gradient to clarifying questions (#483)
- #478 feat: Persist deferred findings from /wrap-up sessions (#482)
- #474 refactor: Rename parse/resolve_prefix to title_format names (#481)
- #464 feat: Render ticket reference consistently in artifact headings (#479)
- #466 feat: Render commit, ticket, PR, and merge titles from declarative templates (#475)
- #471 fix: Make subagent guidance refs apply on Rovo Dev (#472)
- tooling: Exclude Playwright MCP files from linting
- #467 feat: Add update-jira-ticket skill to prevent INVALID_INPUT failures (#470)
- #461 feat: Append `Closes` line to PRs and expose `ticket_ref` (#465)
- #460 feat: Have /design-and-plan evaluate tickets on their merits (#463)
- #456 feat: Have Rovo Dev present choices as numbered text (#457)
- feat: Refine agent collaboration
- #446 feat: Require outcome-first framing in commit titles (#454)
- #448 fix: Have orchestrated-coder write change-summary incrementally (#453)
- #443 tooling: Automate replacement of dashed separator comments with headings or region folds (#451)
- #441 feat: Add provenance markers to generated files (#447)
- #442 fix: Prevent backtick over-escape in agent-authored GitHub bodies (#445)
- #437 fix: Eliminate relative Markdown links in installed guidance (#439)
- #426 feat: Make devlogs ticket-scoped and add linking frontmatter (#434)
- feat: If changes made, offer to run /create-pr after wrap-up
- feat: Improve question style in collaborative mode
- #416 feat: Add `generate label-map` CLI command with JSON Schema and readyup check (#420)
- docs: Record mistake writing long-running test
- #414 feat: Adopt release-notes voice in commit/change-summary skills (#417)
- feat: Instruct agents to follow best practices and prefer CLI tools
- #409 feat: Rationalize PR creation skills with platform-specific delegates (#411)
- #381 feat: Add GitHub label application to create-ticket skill (#410)
- #407 feat: Add project guidelines reading to 9 subagent definitions (#408)
- #384 feat: Improve outcome-first guidance across change-summary & commit skills (#406)
- #404 fix: Add documentation coverage convention to plan-producing skills (#405)
- feat: Improve guidance on writing What section of change summary
- fix: Prevent agents from categorizing trivial flaws as warnings
- #400 fix: Replace hardcoded artifact paths with placeholder in examples (#401)
- feat: Instruct agents to prefer git -C
- #388 fix: Filter stale entries from manifest on partial uninstall (#399)
- #386 tests: Add tests for describe-change.sh and installScripts (#398)
- #392 fix: List at-risk files in symlink safety error message (#397)
- #390 fix: Escalate test gaps for pipeline-authored code to F-level (#396)
- #391 fix: Resolve script paths at install time via template variable (#395)
- #393 fix: Add bin wrappers to eliminate pnpm install warnings (#394)
- #377 feat: Add guidance file install, uninstall, and status support (#389)
- docs: Add README
- #383 feat: Allow commit prefixes to be configured for user and for repo (#387)
- #379 feat: Require tests with code changes across orchestration pipeline (#380)
- #376 tooling: Migrate to nmr script runner (#378)
- #374 feat: Prompt for next steps after non-baseline assessment verdicts (#375)
- #372 feat: Skip complexity assessment when progress is complete (#373)
- fix: Ticket assessment checkboxes are not displayed in terminal
- #370 feat: Add complexity classification to assess-ticket and as standalone skill (#371)
- #135 feat: Add severity to legacy findings (#369)
- #363 fix: Rewrite relative Markdown paths to absolute during skill install (#368)
- #366 feat: Add PROJECT.md staleness check and agent launchers (#367)
- #364 feat: Add people-report skill (#365)
- #306 feat: Add shared complexity rubric and quick-fix pass to wrap-up (#362)
- fix: Gate next-steps presentation on reading reference file
- #360 fix: Replace plugin code-simplifier with standalone reviewer (#361)
- #357 feat: Add assess-ticket skill and extract shared ticket resolution (#359)
- #345 feat: Add staleness and relevancy check to design-and-plan skill (#356)
- #330 feat: Add numbered options and context-clearing to next-steps prompts (#355)
- #351 fix: Fix next-steps-after-plan over-recommending refinement (#354)
- #350 fix: Fix broken _data/ relative paths in skill files (#352)
- #348 feat: Add update-project-guidance skill (#349)
- #346 fix: Replace symlinks before writing generated files
- #346 fix: Install _data support files and filter dotfiles (#347)
- fix: Agents misunderstand session-context fallbacks
- #328 feat: Add ticket compliance checking to review-change skill (#331)
- #320 feat: Add next-steps resumption prompt to plan-producing skills (#329)
- #321 refactor: Remove stale get-session-context references from reviewers (#327)
- #319 refactor: Rename get-branch-context to get-session-context, centralize artifact resolution (#322)
- #315 feat: Add plan provenance to save-plan and refinedBy field (#317)
- #313 fix: Replace 24-hour active-run heuristic (#314)
- refactor: Clarify logic for finding agent preferences
- #290 feat: Show waiting-for-input state in factory visualization (#292)
- #282 fix: Clean up PR and review output conventions (#285)
- #281 feat: Add variable naming conventions (#284)
- refactor: Use short form of SHA in plan provenance metadata
- #280 fix: Remove ticket ID from condense-branch commit format
- #280 fix: Improve adherence to commit conventions (#283)
- #264 fix: Guard against zero parsed steps in high-trust plan conversion (#278)
- #266 feat: Add bb-pr-inline-comment skill (#276)
- feat: Add recommended next-step guidance to design-and-plan skill
- #267 docs: Document optional fields in artifact-conventions
- #267 feat: Wire up usage metrics for savings analysis (#275)
- #263 feat: Use plan provenance and trust level when calibrating orchestration effort (#265)
- fix: Prevent coder subagent from ignoring commit conventions
- tooling: Fix lint in package.json files
- fix: Coder ignores git-commit instructions on title content
- fix: Incorrect path to _data directory in skill definitions
- fix: PR body extracted from branch summary includes frontmatter
- #231 feat: Add design-and-plan skill for interactive design + planning (#234)
- #217 feat: Create find-orchestration-savings skill to identify token waste (#232)
- #105 feat: Add artifact-write safeguards to subagent prompts (#229)
- #223 feat: Create sprite-loading infrastructure for catwalk (#228)
- refactor: Discourage reliance on indirect sources
- #199 feat: Replace orchestration mode system with effort system (#206)
- #197 feat: Make review fan-out mode-aware and remove lite mode (#203)
- #169 feat: Replace timestamp prefixes with sequential counters on run artifacts (#170)
- #163 fix: Resolve artifact base directory from preferences instead of hardcoding project path (#168)
- #157 feat: Add /refine-plan skill for plan review and refinement (#159)
- #155 fix: Fix silent logging failure when MCP is unavailable to orchestrate engine (#158)
- #152 fix: Fix inconsistent artifact logging (#154)
- feat: Emit run_failed event when complete_run receives failed status (#150)
- #141 fix: Fix wrap-up skill action menu and summary narrative (#146)
- #121 fix: Restore platform-specific skill handling and prompts.yml generation (#144)
- #139 feat: Add --mode=lite to orchestrate-dev skill (#143)
- CODY-113 refactor: Deduplicate finding scheme from reviewer agents into shared skill (#134)
- CODY-87 feat: Migrate orchestrator to MCP and v3 events (#133)
- fix: Fix review-cycle doc gaps in Phase 4a entry and Phase 4b flow control
- fix: Address review findings for mode system and two-threshold model
- feat: Add mode system and two-threshold model to orchestrate-dev
- CODY-71 feat: Refine wrap-up: numbered findings, action menu
- CODY-71 feat: Add post-session wrap-up skill (#95)
- CODY-73 feat: Add rich summary sections to orchestrated run output (#88)
- CODY-65 feat: Update run-index.json incrementally during parallel review (#69)

factory-v0.2.0
- deps: Upgrade all deps to latest minor version
- #443 tooling: Automate replacement of dashed separator comments with headings or region folds (#451)
- #427 feat: Add `pick-demo-runs` script to rank archived runs (#436)
- #402 tooling: Add readyup and default kit (#403)
- deps: Upgrade all deps to latest minor version
- #376 tooling: Migrate to nmr script runner (#378)
- deps: Upgrade all deps to latest minor version & patch vuln
- deps: Upgrade all deps to latest minor version
- deps: Upgrade to Vite 8
- #76 feat: Enable playback of completed orchestrated runs (#344)
- #335 feat: Use slot-based positioning for orchestrator (#340)
- #311 feat: Animate office transitions (#336)
- #310 feat: Replace geometric placeholders with tileset rendering (#332)
- #318 tests: Require explicit method selection in silencedConsole (#326)
- #303 internal: Create 3-zone adapter for office visualization (#309)
- #299 feat: Shared logical scene state for visualizations (#304)
- #297 feat: Add ?format=html param to artifact content endpoint (#300)
- #293 spike: Design facility visualization with office prototype (#296)
- #290 feat: Show waiting-for-input state in factory visualization (#292)
- deps: Upgrade all deps to latest minor version
- #287 feat: Add three-zone factory-floor visualization (#291)
- #274 feat: Redesign orchestrator sprite (#286)
- #270 tests: Add edge-case tests for input deferral, playback, rebuild (#273)
- #259 feat: Add progressive artifact reveal to catwalk demo replay (#272)
- #260 feat: Expand block-robot sprites and improve palette contrast (#268)
- #239 fix: Fix catwalk layout geometry, actor rendering, and artifact positioning (#262)
- deps: Require Node 24+
- deps: Upgrade shared linting configs to latest version
- #247 feat: Generate HTML preview page for sprite sheets (#254)
- #236 fix: Subagent sprites are not centered on station x position (#250)
- #235 feat: Generate block-robot pixel art sprites (#249)
- #187 refactor: Move FlowDiagram to visualizations/flow/ (#244)
- tooling: Fix lint in package.json files
- #237 fix: Fix canvas not scaling up on viewport resize (#243)
- #238 fix: Guard against negative orchestrator station index (#242)
- #184 feat: Add chute animations, carried artifacts, and code badge (#241)
- #233 feat: Pulse scale instead of opacity; extract opacity constants (#240)
- refactor: Use preferences cascade for project base path
- #223 feat: Create sprite-loading infrastructure for catwalk (#228)
- #183 feat: Add animated state transitions to catwalk actors (#225)
- #213 feat: Add run directory scanning and refactor ProjectScanner (#221)
- #210 test: Add catwalk differ boundary tests for agent (#212)
- #182 feat: Implement catwalk config differ (#211)
- #207 fix: Skip interactive run directories in project scanner (#208)
- #199 feat: Replace orchestration mode system with effort system (#206)
- #181 feat: Integrate CatwalkScene with config-driven actor management (#201)
- #180 util: Implement static catwalk actors (#195)
- #179 util: Define CatwalkSceneConfig types and implement run-to-catwalk mapper (#192)
- #178 util: Implement catwalk layout engine (#191)
- #177 util: Add shared artifact color constants and catwalk dimension/timing constants (#190)
- #176 feat: Scaffold catwalk visualization with empty scene (#189)
- #171 feat: Gracefully handle invalid log files in orchestrated-run directories (#174)
- #148 feat: Propagate failure reason from run_failed event to CanonicalRunStatus (#167)
- tests: Add shared visualization mocks and status prop forwarding tests (#149)
- #10 tests: Silence console noise in test output (#147)
- #137 feat: Persist visualization mode in query string parameter (#142)
- #136 fix: Fix diagram view crash on undefined reviewers (#138)
- CODY-100 feat: Implement review-cycle visualization and iteration tracking (#129)
- CODY-116 fix: Fix canvas scaling to be width-driven with FitContainer (#125)
- CODY-99 feat: Add custom edge components with packet animation (#118)
- CODY-98 feat: Create custom node components for flow diagram (#112)
- CODY-97 feat: Add React Flow foundation and visualization switcher (#109)
- refactor: Migrate imports to @codeassembly/run-core (#104)
- CODY-94 fix: Handle newer parallelReview schema shapes in scene mapper (#102)
- CODY-79 feat: Show tooltip on hover over artifact boxes (#91)
- feat: Rebrand to "Code Assembly Factory"
- fix: Left-align labels, align upper reviewers, reposition artifacts
- fix: Fix orchestrator start position and approach distance
- CODY-63 feat: Add demo playback mode with event-sourced run replay (#81)
- CODY-60 feat: Render individual artifact boxes with configurable layout (#77)
- refactor: Fix lint surfaced by dependency upgrades
- CODY-67 feat: Move station labels to platform (#70)
- CODY-65 feat: Update run-index.json incrementally during parallel review (#69)
- CODY-59 feat: Improve representational quality of gates (#64)
- fix: Guard against stale setFacing from cancelled walk
- feat: Add directional sprite facing for approaching orchestrator
- CODY-42 feat: Position orchestrator to left of delegatee (#56)
- CODY-26 feat: Add resting animations for idle agents (#54)
- CODY-49 fix: Sync RunList selection with URL params and RunSelector dropdowns (#51)
- CODY-39 feat: Improve run listing readability in sidebar (#50)
- fix: Propagate null-safety to shared phase-inference module
- refactor: Simplify walk chain, deduplicate error handler, and clean up minor noise
- fix: Address review findings for artifact indicator
- feat: Add agent spawning, artifact indicator, and hand-off
- refactor: Simplify onDismissRun prop and clarify partial comment
- fix: Address review findings for settings persistence
- fix: Resolve lint errors in settings route test and hook
- feat: Update App and RunList for status-aware dismissal API
- feat: Rewrite useDismissedRuns hook with server persistence
- feat: Add fetchSettings and patchSettings client API functions
- feat: Register settings route and fix type compatibility
- feat: Add settings REST endpoints (GET/PATCH /api/settings)
- feat: Add SettingsStore service for persisting user settings
- feat: Add shared types and Zod schema for user settings
- fix: Position orchestrator at inferred current phase
- refactor: Consolidate phase-active checks to delegate to isPhasePresentInData
- feat: Show agents at stations before phase data is written
- CODY-41 fix: Correct structural element positioning in the factory scene (#44)
- MAC-35 feat: Add Zod schema validation for run-index.json (#43)
- CODY-34 fix: Accept null phases and criticality in status-adapter (#37)
- CODY-24 feat: Add orchestrator walk transitions along assembly line (#33)
- CODY-28 feat: Auto-refresh projects list with file watching (#32)
- refactor: Remove redundant ternary in camera bounds calculation
- feat: Add multi-level platforms and orchestrator positioning
- CODY-20 feat: Add RunList component with clickable run list in sidebar (#29)
- feat: Show project, ticket, run, status, duration in status  bar
- feat: Persist selected project, ticket, and run in URL
- CODY-7 feat: Add agent movement and status-driven animation transitions (#14)
- CODY-3 fix: Accept no-reason phase decisions in run-index validator (#13)
- fix: Load ImageSource data before engine start
- feat: Add sprite infrastructure and basic animations
- CODY-5 feat: Implement role-type architecture and all-phase agent mapping (#8)
- CODY-3 feat: Support run-index.json (v2) in status adapter (#4)
- fix: Skip missing status.json gracefully and extract shared isEnoent helper
- deps: Use exact version numbers in package.json
- refactor: Extract shared test fixtures and simplify buildGates
- tests: Add test coverage for game actors, FactoryScene, GameCanvas, and mappers
- fix: Fix StationActor graphics, GameCanvas race condition, and poll cleanup
- fix: Add onInitialize lifecycle hook to FactoryScene
- fix: Prevent isLoading flicker during poll cycles
- refactor: Add comment explaining type-narrowing aliases in useRunStatus
- tests: Strengthen error recovery assertions in useRunStatus test
- fix: Fix intervalRef leak on run switch, add missing test coverage
- tests: Add polling behavior tests for useRunStatus hook
- refactor: Remove dead typeof guards, redundant test assertions
- fix: Add route tests, fix ENOENT handling, and harden routes
- refactor: Simplify scanProject with early returns
- fix: Remove dead guard, improve project-scanner coverage
- fix: Fix duplicate tickets & stat check in project scanner
- fix: Reject null phase entries in status-adapter validation
- refactor: Simplify status-adapter validation helpers
- fix: Harden status-adapter type guard and validation

mcp-v0.2.0
- deps: Upgrade all deps to latest minor version
- #443 tooling: Automate replacement of dashed separator comments with headings or region folds (#451)
- deps: Upgrade all deps to latest version
- #376 tooling: Migrate to nmr script runner (#378)
- deps: Upgrade all deps to latest minor version
- tooling: Fix lint in package.json files
- fix: Exclude __tests__/ from staleness check to match compile scope
- refactor: Use preferences cascade for project base path
- #210 test: Add catwalk differ boundary tests for agent (#212)
- #199 feat: Replace orchestration mode system with effort system (#206)
- #163 fix: Resolve artifact base directory from preferences instead of hardcoding project path (#168)
- #160 feat: Warn when compiled output is stale if using development MCP code (#166)
- #152 fix: Fix inconsistent artifact logging (#154)
- #131: Verify end-to-end MCP integration (#151)
- feat: Emit run_failed event when complete_run receives failed status (#150)
- CODY-87 feat: Migrate orchestrator to MCP and v3 events (#133)

run-core-v0.2.0
- deps: Upgrade all deps to latest minor version
- #443 tooling: Automate replacement of dashed separator comments with headings or region folds (#451)
- #427 feat: Add `pick-demo-runs` script to rank archived runs (#436)
- #393 fix: Add bin wrappers to eliminate pnpm install warnings (#394)
- #376 tooling: Migrate to nmr script runner (#378)
- #76 feat: Enable playback of completed orchestrated runs (#344)
- #290 feat: Show waiting-for-input state in factory visualization (#292)
- tooling: Fix lint in package.json files
- fix: Add prepare script to fix bin linking in worktrees
- refactor: Use preferences cascade for project base path
- #217 feat: Create find-orchestration-savings skill to identify token waste (#232)
- #213 feat: Add run directory scanning and refactor ProjectScanner (#221)
- #199 feat: Replace orchestration mode system with effort system (#206)
- #171 feat: Gracefully handle invalid log files in orchestrated-run directories (#174)
- #148 feat: Propagate failure reason from run_failed event to CanonicalRunStatus (#167)
- #136 fix: Fix diagram view crash on undefined reviewers (#138)
- CODY-97 feat: Add React Flow foundation and visualization switcher (#109)
- refactor: Migrate imports to @codeassembly/run-core (#104)
- CODY-85 feat: Create @codeassembly/mcp server with run-data tools (#96)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature Added or improved external functionality scope:factory scope:run-core

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Create standalone utility to archive invalid run directories

1 participant