Skip to content

ralph/feat/loop sandbox post merge#1579

Merged
Crunchyman-ralph merged 1 commit intonextfrom
ralph/feat/loop-sandbox-post-merge
Jan 15, 2026
Merged

ralph/feat/loop sandbox post merge#1579
Crunchyman-ralph merged 1 commit intonextfrom
ralph/feat/loop-sandbox-post-merge

Conversation

@Crunchyman-ralph
Copy link
Collaborator

@Crunchyman-ralph Crunchyman-ralph commented Jan 15, 2026

  • test(cli): fix and improve LoopCommand tests

What type of PR is this?

  • 🐛 Bug fix
  • ✨ Feature
  • 🔌 Integration
  • 📝 Docs
  • 🧹 Refactor
  • Other:

Description

  • test(cli): fix and improve LoopCommand tests

Related Issues

How to Test This

# Example commands or steps

Expected result:

Contributor Checklist

  • Created changeset: npm run changeset
  • Tests pass: npm test
  • Format check passes: npm run format-check (or npm run format to fix)
  • Addressed CodeRabbit comments (if any)
  • Linked related issues (if any)
  • Manually tested the changes

Changelog Entry


For Maintainers

  • PR title follows conventional commits
  • Target branch correct
  • Labels added
  • Milestone assigned (if applicable)

Summary by CodeRabbit

  • Tests
    • Enhanced sandbox authorization flow tests for the loop command, including success paths and error scenarios.
    • Added verification that the --sandbox option is displayed in help output.

✏️ Tip: You can customize this high-level summary in your review settings.

@changeset-bot
Copy link

changeset-bot bot commented Jan 15, 2026

⚠️ No Changeset found

Latest commit: 634e63d

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@Crunchyman-ralph Crunchyman-ralph changed the base branch from main to next January 15, 2026 13:49
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 15, 2026

📝 Walkthrough

Walkthrough

Updates test coverage for LoopCommand's sandbox authorization flow, adding tests for flag presence/absence, error handling, and interactive authentication scenarios with mocked ready states and error paths.

Changes

Cohort / File(s) Summary
Sandbox Authorization Test Coverage
apps/cli/src/commands/loop.command.spec.ts, apps/cli/tests/integration/commands/loop.command.test.ts
Enhanced unit tests for sandbox auth branches: renamed test for --sandbox flag presence, added test for flag omission, extended interactive auth test with mocked success return, introduced error handling tests (checkSandboxAuth errors and runInteractiveAuth failures triggering displayError). Added integration test verifying --sandbox option appears in help output.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • PR #1578: Modifies the same loop command tests, aligning sandbox auth mock return shapes and behavior paths (ready/error/interactive states).
  • PR #1576: Updates sandbox auth function return shapes (checkSandboxAuth and runInteractiveAuth) and error propagation that correspond directly to the new test error-handling branches added in this PR.

Suggested reviewers

  • eyaltoledano
🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The PR title references "loop sandbox post merge" but describes internal test refactoring, not a user-facing feature. The title is vague and uses abbreviations without context. Consider using a clearer title like "test(cli): fix and improve LoopCommand sandbox authorization tests" to better reflect the actual changes and make the commit history more readable.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings


📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between af49e8e and 634e63d.

📒 Files selected for processing (2)
  • apps/cli/src/commands/loop.command.spec.ts
  • apps/cli/tests/integration/commands/loop.command.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/cli/tests/integration/commands/loop.command.test.ts
🧰 Additional context used
📓 Path-based instructions (7)
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/test_workflow.mdc)

TypeScript test files must achieve minimum code coverage thresholds: 80% lines/functions and 70% branches globally, 90% for utilities, and 85% for middleware; new features must meet or exceed these thresholds

Files:

  • apps/cli/src/commands/loop.command.spec.ts
**/*.{js,ts}

📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)

**/*.{js,ts}: Import and use specific getters from config-manager.js (e.g., getMainProvider(), getLogLevel(), getMainMaxTokens()) to access configuration values needed for application logic
Use isApiKeySet(providerName, session) from config-manager.js to check if a provider's key is available before potentially attempting an AI call
Do not add direct console.log calls outside the logging utility - use the central log function instead
Ensure silent mode is disabled in a finally block to prevent it from staying enabled
Do not access the global silentMode variable directly - use the exported silent mode control functions instead
Do not duplicate task ID formatting logic across modules - centralize formatting utilities
Use ContextGatherer class from utils/contextGatherer.js for AI-powered commands that need project context, supporting tasks, files, custom text, and project tree context
Use FuzzyTaskSearch class from utils/fuzzyTaskSearch.js for automatic task relevance detection with configurable search parameters
Use fuzzy search to supplement user-provided task IDs and display discovered task IDs to users for transparency
Do not replace explicit user task selections with fuzzy results - fuzzy search should supplement, not replace user selections
Use readJSON and writeJSON utilities for all JSON file operations instead of raw fs.readFileSync or fs.writeFileSync
Include error handling for JSON file operations and validate JSON structure after reading
Use path.join() for cross-platform path construction and path.resolve() for absolute paths, validating paths before file operations
Support both .env files and MCP session environment for environment variable resolution with fallbacks for missing values
Prefer updating the core function to accept an outputFormat parameter and check outputFormat === 'json' before displaying UI elements

Files:

  • apps/cli/src/commands/loop.command.spec.ts
**/*.spec.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Place package and app test files in packages/<package-name>/src/<module>/<file>.spec.ts or apps/<app-name>/src/<module>/<file>.spec.ts alongside source files

Files:

  • apps/cli/src/commands/loop.command.spec.ts
**/*.{spec,test}.ts

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{spec,test}.ts: Always use .ts for TypeScript tests, never .js
NEVER use async/await in test functions unless testing actual asynchronous operations; use synchronous top-level imports instead of dynamic await import()

Files:

  • apps/cli/src/commands/loop.command.spec.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Import modules with .js extension even in TypeScript source files for ESM compatibility

Files:

  • apps/cli/src/commands/loop.command.spec.ts
apps/cli/**/*.{spec,test}.ts

📄 CodeRabbit inference engine (CLAUDE.md)

In unit tests for apps/cli, mock tm-core responses but use real Commander/chalk/inquirer/other npm packages to test display logic

Files:

  • apps/cli/src/commands/loop.command.spec.ts
apps/cli/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

CLI (@tm/cli) should be a thin presentation layer that calls tm-core methods and displays results; handle only CLI-specific concerns like argument parsing, output formatting, and user prompts

Files:

  • apps/cli/src/commands/loop.command.spec.ts
🧠 Learnings (17)
📓 Common learnings
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1178
File: packages/tm-core/src/subpath-exports.test.ts:6-9
Timestamp: 2025-09-03T12:45:30.724Z
Learning: The user Crunchyman-ralph prefers to avoid overly nitpicky or detailed suggestions in code reviews, especially for test coverage of minor import paths. Focus on more substantial issues rather than comprehensive coverage of all possible edge cases.
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : When testing CLI commands built with Commander.js: test command action handlers directly rather than mocking the entire Commander chain; create simplified test-specific implementations of command handlers; explicitly handle all options including defaults and shorthand flags; include null/undefined checks for optional parameters; use fixtures for consistent sample data.
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T22:09:45.455Z
Learning: Applies to apps/cli/**/*.{spec,test}.ts : In unit tests for apps/cli, mock tm-core responses but use real Commander/chalk/inquirer/other npm packages to test display logic
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1178
File: packages/tm-core/src/auth/config.ts:5-7
Timestamp: 2025-09-02T21:51:27.921Z
Learning: The user Crunchyman-ralph prefers not to use node: scheme imports (e.g., 'node:os', 'node:path') for Node.js core modules and considers suggestions to change bare imports to node: scheme as too nitpicky.
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1069
File: .changeset/fix-tag-complexity-detection.md:0-0
Timestamp: 2025-08-02T15:33:22.656Z
Learning: For changeset files (.changeset/*.md), Crunchyman-ralph prefers to ignore formatting nitpicks about blank lines between frontmatter and descriptions, as he doesn't mind having them and wants to avoid such comments in future reviews.
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1132
File: .github/workflows/weekly-metrics-discord.yml:81-93
Timestamp: 2025-08-13T22:10:46.958Z
Learning: Crunchyman-ralph ignores YAML formatting nitpicks about trailing spaces when there's no project-specific YAML formatter configured, preferring to focus on functionality over cosmetic formatting issues.
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1132
File: .github/workflows/weekly-metrics-discord.yml:81-93
Timestamp: 2025-08-13T22:10:46.958Z
Learning: Crunchyman-ralph ignores YAML formatting nitpicks about trailing spaces when there's no project-specific YAML formatter configured, preferring to focus on functionality over cosmetic formatting issues.
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1200
File: src/ai-providers/custom-sdk/grok-cli/language-model.js:96-100
Timestamp: 2025-09-19T16:06:42.182Z
Learning: The user Crunchyman-ralph prefers to keep environment variable names explicit (like GROK_CLI_API_KEY) rather than supporting multiple aliases, to avoid overlap and ensure clear separation between different CLI implementations.
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1105
File: scripts/modules/supported-models.json:242-254
Timestamp: 2025-08-08T11:33:15.297Z
Learning: Preference: In scripts/modules/supported-models.json, the "name" field is optional. For OpenAI entries (e.g., "gpt-5"), Crunchyman-ralph prefers omitting "name" when the id is explicit enough; avoid nitpicks requesting a "name" in such cases.
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1217
File: apps/cli/src/index.ts:16-21
Timestamp: 2025-09-18T16:35:35.147Z
Learning: The user Crunchyman-ralph considers suggestions to export types for better ergonomics (like exporting UpdateInfo type alongside related functions) as nitpicky and prefers not to implement such suggestions.
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : When testing CLI commands built with Commander.js: test command action handlers directly rather than mocking the entire Commander chain; create simplified test-specific implementations of command handlers; explicitly handle all options including defaults and shorthand flags; include null/undefined checks for optional parameters; use fixtures for consistent sample data.

Applied to files:

  • apps/cli/src/commands/loop.command.spec.ts
📚 Learning: 2025-11-24T22:09:45.455Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T22:09:45.455Z
Learning: Applies to apps/cli/**/*.{spec,test}.ts : In unit tests for apps/cli, mock tm-core responses but use real Commander/chalk/inquirer/other npm packages to test display logic

Applied to files:

  • apps/cli/src/commands/loop.command.spec.ts
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to tests/e2e/**/*.test.js : Locate end-to-end tests in `tests/e2e/` directory. Test complete workflows from a user perspective, focus on CLI commands as users would use them.

Applied to files:

  • apps/cli/src/commands/loop.command.spec.ts
📚 Learning: 2025-11-24T18:03:13.456Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/test_workflow.mdc:0-0
Timestamp: 2025-11-24T18:03:13.456Z
Learning: Applies to tests/e2e/**/*.test.ts : End-to-end tests must test complete user workflows across multiple API endpoints in sequence, verify state changes between workflow steps, use extended timeouts (30000ms), and validate final outcomes without mocking business logic

Applied to files:

  • apps/cli/src/commands/loop.command.spec.ts
📚 Learning: 2025-11-24T22:09:45.455Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T22:09:45.455Z
Learning: Applies to packages/tm-core/**/*.{spec,test}.ts : In unit tests for tm/core, mock only external I/O (Supabase, APIs, filesystem) and use real internal services

Applied to files:

  • apps/cli/src/commands/loop.command.spec.ts
📚 Learning: 2025-11-24T22:09:45.455Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T22:09:45.455Z
Learning: Applies to **/tests/integration/**/*.{spec,test}.ts : In integration tests, use real tm-core and mock only external boundaries (APIs, DB, filesystem)

Applied to files:

  • apps/cli/src/commands/loop.command.spec.ts
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : Do not import or instantiate real AI service clients. Create fully mocked versions that return predictable responses. Mock the entire module with controlled behavior.

Applied to files:

  • apps/cli/src/commands/loop.command.spec.ts
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : Never use asynchronous operations in tests. Always mock tests properly based on the way the tested functions are defined and used.

Applied to files:

  • apps/cli/src/commands/loop.command.spec.ts
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : Make async operations synchronous in tests. Mock async functions to return synchronous values when possible. Don't use real async/await or Promise resolution that might fail unpredictably.

Applied to files:

  • apps/cli/src/commands/loop.command.spec.ts
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : When testing console assertions: ensure assertion matches actual arguments passed; if code logs a single formatted string, assert against that single string using `expect.stringContaining` or exact match, not multiple arguments; verify exact behavior of the code being tested.

Applied to files:

  • apps/cli/src/commands/loop.command.spec.ts
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : For task file operations in tests: use test-specific file paths (e.g., 'test-tasks.json'); mock `readJSON` and `writeJSON` to avoid real file system interactions; verify file operations use correct paths; use different paths for each test; verify modifications on in-memory task objects passed to `writeJSON`.

Applied to files:

  • apps/cli/src/commands/loop.command.spec.ts
📚 Learning: 2025-11-24T18:03:13.456Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/test_workflow.mdc:0-0
Timestamp: 2025-11-24T18:03:13.456Z
Learning: Applies to **/*.test.ts : Unit tests must follow the describe/it pattern, use beforeEach for mock setup with jest.clearAllMocks(), include specific assertions with expect(), and test both success and error scenarios including edge cases

Applied to files:

  • apps/cli/src/commands/loop.command.spec.ts
📚 Learning: 2025-11-24T18:03:13.456Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/test_workflow.mdc:0-0
Timestamp: 2025-11-24T18:03:13.456Z
Learning: Use established mocking patterns from auth.test.ts as templates: mock bcrypt with proper TypeScript typing, mock Prisma client with transaction support, and always clear mocks between tests

Applied to files:

  • apps/cli/src/commands/loop.command.spec.ts
📚 Learning: 2025-11-24T22:09:45.455Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T22:09:45.455Z
Learning: Applies to apps/mcp/**/*.{spec,test}.ts : In unit tests for apps/mcp, mock tm-core responses but use real MCP framework to test response formatting

Applied to files:

  • apps/cli/src/commands/loop.command.spec.ts
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to **/*.test.{js,ts} : Follow the mock-first-then-import pattern for Jest mocking; use jest.spyOn() for spy functions; clear mocks between tests; verify mocks with the pattern described in `tests.mdc`

Applied to files:

  • apps/cli/src/commands/loop.command.spec.ts
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : When testing UI functions: mock console output and verify correct formatting; test conditional output logic; use `toContain()` or `toMatch()` rather than exact `toBe()` for strings with emojis or formatting; create separate tests for different behavior modes; test structure of formatted output rather than exact string matching.

Applied to files:

  • apps/cli/src/commands/loop.command.spec.ts
🧬 Code graph analysis (1)
apps/cli/src/commands/loop.command.spec.ts (1)
apps/cli/src/commands/loop.command.ts (1)
  • execute (55-126)
🔇 Additional comments (5)
apps/cli/src/commands/loop.command.spec.ts (5)

392-401: LGTM!

Test correctly verifies that sandbox auth is checked when the --sandbox flag is provided. The explicit mock setup on line 395 adds clarity for this specific test case.


403-411: LGTM - Previous bug fixed.

The test now correctly passes an empty options object ({}), which means the sandbox flag is not provided. This properly validates that checkSandboxAuth is not called when the flag is omitted.


413-423: LGTM!

Test correctly verifies the interactive authentication flow when sandbox is requested but not ready.


425-442: LGTM!

Test correctly verifies error handling when checkSandboxAuth returns an error. The pattern is consistent with other error handling tests in this file.


444-463: LGTM!

Test correctly verifies error handling when interactive authentication fails. This completes the coverage of the sandbox auth error paths.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@Crunchyman-ralph
Copy link
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 15, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@apps/cli/src/commands/loop.command.spec.ts`:
- Around line 403-411: The test 'should not check sandbox auth when --sandbox
flag is not provided' is passing sandbox: true which contradicts its intent;
update the call to (loopCommand as any).execute so it does not enable the
sandbox (e.g., pass { sandbox: false } or omit the sandbox property) so that
mockTmCore.loop.checkSandboxAuth is not expected to be called; keep references
to the existing execute binding and mockTmCore.loop.checkSandboxAuth assertion
unchanged.
🧹 Nitpick comments (8)
tests/unit/task-manager/tag-management.test.js (1)

116-124: Consider test placement: unit vs integration.

These tests perform real file system operations rather than mocking readJSON/writeJSON, which is appropriate for validating the atomic file locking behavior. However, per coding guidelines, unit tests in tests/unit/ should mock file operations and test in isolation.

Consider either:

  1. Moving these tests to an integration test directory (e.g., tests/integration/)
  2. Adding a comment explaining these are integration-style tests validating file I/O safety

This is a minor organizational concern—the tests themselves are well-written and provide valuable coverage for the concurrency safety features.

packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts (1)

69-106: Consider documenting the console.warn behavior.

The lock release warning only appears when DEBUG or TASKMASTER_DEBUG=true is set. This is reasonable for production noise reduction, but users debugging lock issues may miss this. Consider adding a note in the class-level JSDoc about enabling debug mode for lock diagnostics.

Also, the warning uses console.warn instead of a structured logger. Per coding guidelines, prefer using the central log function instead of direct console calls.

apps/cli/src/ui/display/tables.ts (1)

66-73: Edge case: optionalCols > 4 would use fallback ratios.

The fallback COLUMN_WIDTH_RATIOS[4] is used when optionalCols exceeds defined keys. Currently only 4 optional columns exist, so this is safe. However, if more optional columns are added in the future, this fallback may produce unexpected results.

Consider a defensive fallback
-	const ratios = COLUMN_WIDTH_RATIOS[optionalCols] || COLUMN_WIDTH_RATIOS[4];
+	const maxDefinedCols = Math.max(...Object.keys(COLUMN_WIDTH_RATIOS).map(Number));
+	const ratios = COLUMN_WIDTH_RATIOS[optionalCols] || COLUMN_WIDTH_RATIOS[maxDefinedCols];
scripts/modules/utils.js (1)

40-65: Consider the busy-wait CPU impact for longer backoff delays.

The busy-wait fallback (lines 61-64) will spin the CPU when SharedArrayBuffer is unavailable. With exponential backoff, the max wait is 100ms * 2^4 = 1600ms, which could cause noticeable CPU spikes.

For a file-locking utility that may be called frequently, consider using setTimeout with a sync wrapper pattern or documenting this limitation more prominently.

packages/tm-core/src/modules/storage/adapters/file-storage/file-storage.ts (1)

641-645: Silent fallback when copyFrom references unavailable tag in standard format.

When in standard format and options.copyFrom is set to something other than 'master' (or undefined), tasksToCopy will be an empty array without warning. This is technically correct since standard format only has master tasks, but the silent behavior could surprise callers.

Consider adding a warning or throwing when copyFrom references a tag that doesn't exist in standard format:

 				// Get tasks to copy (from master in this case)
 				let tasksToCopy: any[] = [];
-				if (options?.copyFrom === 'master' || !options?.copyFrom) {
+				if (!options?.copyFrom || options.copyFrom === 'master') {
 					tasksToCopy = JSON.parse(JSON.stringify(masterTasks));
+				} else {
+					// Standard format only has master; requested copyFrom tag doesn't exist
+					throw new TaskMasterError(
+						`Cannot copy from tag '${options.copyFrom}' - only 'master' exists in standard format`,
+						ERROR_CODES.VALIDATION_ERROR
+					);
 				}
packages/tm-core/src/modules/loop/services/loop.service.ts (1)

278-283: Consider adding a timeout to prevent indefinite hangs.

Unlike checkSandboxAuth which has a 30-second timeout, executeIteration has no timeout. While long iterations are expected, an indefinite hang (e.g., due to network issues or Claude becoming unresponsive) would require manual process termination.

Consider adding a configurable timeout (defaulting to a generous value like 30 minutes) to provide a safety net:

-		const result = spawnSync(command, args, {
+		const timeoutMs = 30 * 60 * 1000; // 30 minutes default
+		const result = spawnSync(command, args, {
 			cwd: this.projectRoot,
 			encoding: 'utf-8',
 			maxBuffer: 50 * 1024 * 1024, // 50MB buffer
-			stdio: ['inherit', 'pipe', 'pipe']
+			stdio: ['inherit', 'pipe', 'pipe'],
+			timeout: timeoutMs
 		});

This could also be exposed as a config option in LoopConfig for user control.

apps/cli/src/commands/list.command.ts (2)

71-78: Consider discriminated union for clearer type narrowing.

The tasks field uses a union type TaskWithBlocks[] | TaskWithTag[], which requires checking allTags to determine the actual type. A discriminated union would provide stronger type safety:

export type ListTasksResult = {
  total: number;
  filtered: number;
  storageType: Exclude<StorageType, 'auto'>;
} & (
  | { allTags: false; tag?: string; tasks: TaskWithBlocks[] }
  | { allTags: true; tasks: TaskWithTag[] }
);

This allows TypeScript to automatically narrow the tasks type based on allTags.


417-422: Type cast is safe but could be avoided.

The cast filterReadyTasks(enrichedTasks) as TaskWithTag[] is safe because enrichedTasks already includes tagName. However, you could avoid the cast by using a generic or intersection type in the filter function, or by filtering after assigning to tasksToAdd:

-				const tasksToAdd: TaskWithTag[] = options.ready
-					? (filterReadyTasks(enrichedTasks) as TaskWithTag[])
-					: enrichedTasks;
+				const tasksToAdd = options.ready
+					? filterReadyTasks(enrichedTasks)
+					: enrichedTasks;
 
-				allTaggedTasks.push(...tasksToAdd);
+				allTaggedTasks.push(...(tasksToAdd as TaskWithTag[]));

Or keep the cast as-is since it's demonstrably safe in this context.

- Fix sandbox auth tests to match implementation (sandbox flag is required)
- Add test for sandbox not being checked when flag is not provided
- Add test for sandbox auth error handling
- Add test for interactive auth failure
- Fix integration test to check --sandbox option instead of non-existent --json option
@Crunchyman-ralph Crunchyman-ralph force-pushed the ralph/feat/loop-sandbox-post-merge branch from af49e8e to 634e63d Compare January 15, 2026 15:02
@Crunchyman-ralph Crunchyman-ralph merged commit 68aac14 into next Jan 15, 2026
8 checks passed
@Crunchyman-ralph Crunchyman-ralph deleted the ralph/feat/loop-sandbox-post-merge branch January 15, 2026 15:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant