Skip to content

[2616 by GPT-5.6 Sol] Add support to Claude Sonnet 5.5 model, make it the canonical Sonnet model and retire the older Sonn - #2619

Merged
integry merged 2 commits into
mainfrom
2616/gpt-5.6-sol-add-support-to-claude-son-20260929-0822-ilv
Sep 29, 2026
Merged

integry merged 2 commits into
mainfrom
2616/gpt-5.6-sol-add-support-to-claude-son-20260929-0822-ilv

Conversation

@propr-dev

@propr-dev propr-dev Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

AI Implementation Summary

Closes #2616

Branch: 2616/gpt-5.6-sol-add-support-to-claude-son-20260929-0822-ilv
Commits: ✅ Changes committed (f80da63)


AI Processing Completed

Execution Details:

Summary:
Implemented GitHub issue #2616:

  • Added Claude Sonnet 5.5 with 1M context, pricing, label, aliases, and review budgeting.
  • Made sonnet resolve to Sonnet 5.5 while preserving explicit Sonnet 5 aliases.
  • Moved older Sonnet models behind the legacy-model fold.
  • Updated recommendations and Claude Code runtime pin to 2.1.284.
  • Updated documentation, changelog, dependencies, and licenses.
  • Added focused backend/frontend tests and visual preview evidence.

Validation passed: TypeScript builds, UI typecheck/lint, 89 focused tests, and Playwright preview capture.

Detailed Logs:

  • Conversation: 64 messages
  • Session: null

Log files stored at:

  • conversation: /tmp/claude-logs/issue-2616-2026-09-29T08-31-53-547Z-conversation.json
  • output: /tmp/claude-logs/issue-2616-2026-09-29T08-31-53-547Z-output.txt
Latest Conversation Messages

This PR was created automatically by ProPR after processing issue #2616.


💡 Need changes?

Comment on this PR to request refinements — the AI agent monitors comments and will update the implementation based on your feedback. Keep iterating until you're satisfied!


Visual preview

Claude Sonnet model catalog

Claude Sonnet model catalog

AI Agents configuration showing Claude Sonnet 5.5 in the current catalog and older Sonnet releases in the expanded legacy section.

Original unavailable: managed storage is unavailable or the upload has expired.

…, make it th

Implemented by ProPR AI using gpt-5.6-sol model.

Implementation completed successfully.
@propr-dev

propr-dev Bot commented Sep 29, 2026

Copy link
Copy Markdown
Contributor Author

CI failed: Full Test Suite Shard 2/4

Please investigate and fix this CI failure.

  • Check: Full Test Suite Shard 2/4
  • Result: failure
  • Commit: f80da63edf71 (f80da63edf71fceb6c29eebfb83d2114ef43501c)
  • Details: View CI failure

Failure evidence

.github:11
Process completed with exit code 1.

.github:19362
Process completed with exit code 1.

.github:2
Node.js 20 is deprecated. The following actions target Node.js 20 but are being forced to run on Node.js 24: actions/checkout@11d5960. For more information see: https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/

@propr-dev

propr-dev Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor Author

✅ Applied the requested follow-up changes in commit a7dc6fb

Summary of Changes

Fixed the Shard 2 CI failure.

  • Root cause: stale test expectations still resolved bare sonnet to Sonnet 5 instead of Sonnet 5.5.
  • Updated three assertions and centralized the canonical Sonnet test value in commentEventHandler.switch-use.test.ts.
  • The Node.js 20 deprecation notice was unrelated to the failure.
  • Verification: repository CI harness passed both affected suites, 2/2 files and all assertions.
  • git diff --check passed.

No visual preview was created because this is test-only and not user-visible.


🤖 Implementation Details

  • Model: GPT-5.6 Sol (high)
  • Requested By: @propr-dev[bot]
  • Time: 2m 48s
  • Tokens: 679,595 (676,447 in / 3,148 out)
  • Cost: $0.62

Undo Changes • View Task Execution


💡 ProPR Slash Commands
Command Description Example
/merge Merge target branch into this PR and resolve conflicts /merge
/review Request an AI code review /review or /review claude-sonnet
/fix Implement fixes for issues found by /review /fix or /fix address the null check issue
/switch Change the AI model for this PR /switch claude-opus
/use Override the model for a single follow-up run /use claude-sonnet
/ultrafix Loop review→fix cycles until score goal is met /ultrafix or /ultrafix goal=8 max=10

🤖 Generated by ProPR
Processing comment ID: 5886704736✓

@propr-dev

propr-dev Bot commented Sep 29, 2026

Copy link
Copy Markdown
Contributor Author

CI failed: Run Full Test Suite

Please investigate and fix this CI failure.

Failure evidence

.github:68
Process completed with exit code 1.

.github:66
Full test suite shards finished with result 'failure'.

.github:4
Node.js 20 is deprecated. The following actions target Node.js 20 but are being forced to run on Node.js 24: actions/checkout@11d5960, actions/download-artifact@018cc2c. For more information see: https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/

@github-actions

Copy link
Copy Markdown

Full Test Suite Results

Validation failed during: Test shard (shard 2).

  • Dependency install: success
  • Workspace build: success
  • Docs validation: success
  • Shard coverage verification: success
  • Hosted native Electron units: skipped (classifier decision: false)
  • Shard 1/4: passed in 367.0s on GitHub Actions 1000050603
  • Shard 2/4: failed during Test shard in 346.2s on GitHub Actions 1000050601
    • test/commentEventHandler.switch-use.test.ts: exit 1
  • Shard 3/4: passed in 262.2s on GitHub Actions 1000050600
  • Shard 4/4: passed in 318.4s on GitHub Actions 1000050602
View shard 2/4 output
...(truncated)

valid token is accepted
          ---
          duration_ms: 0.975265
          type: 'test'
          ...
        # Subtest: accepts a serialized job signed before userId was added
        ok 2 - accepts a serialized job signed before userId was added
          ---
          duration_ms: 0.748461
          type: 'test'
          ...
        # Subtest: missing SYSTEM_TASK_SECRET rejects
        ok 3 - missing SYSTEM_TASK_SECRET rejects
          ---
          duration_ms: 0.356647
          type: 'test'
          ...
        # Subtest: wrong secret rejects
        ok 4 - wrong secret rejects
          ---
          duration_ms: 0.412021
          type: 'test'
          ...
        # Subtest: empty auth token rejects
        ok 5 - empty auth token rejects
          ---
          duration_ms: 0.303198
          type: 'test'
          ...
        # Subtest: malformed (non-hex) auth token rejects
        ok 6 - malformed (non-hex) auth token rejects
          ---
          duration_ms: 0.262
          type: 'test'
          ...
        # Subtest: wrong-length hex token rejects before HMAC comparison
        ok 7 - wrong-length hex token rejects before HMAC comparison
          ---
          duration_ms: 0.259245
          type: 'test'
          ...
        # Subtest: tampered commitHash invalidates token
        ok 8 - tampered commitHash invalidates token
          ---
          duration_ms: 0.260788
          type: 'test'
          ...
        # Subtest: tampered targetCommentId invalidates token
        ok 9 - tampered targetCommentId invalidates token
          ---
          duration_ms: 0.339446
          type: 'test'
          ...
        # Subtest: tampered prBranch invalidates token
        ok 10 - tampered prBranch invalidates token
          ---
          duration_ms: 0.417701
          type: 'test'
          ...
        # Subtest: tampered requestingUser invalidates token
        ok 11 - tampered requestingUser invalidates token
          ---
          duration_ms: 0.309188
          type: 'test'
          ...
        # Subtest: tampered userId invalidates token
        ok 12 - tampered userId invalidates token
          ---
          duration_ms: 0.337251
          type: 'test'
          ...
        # Subtest: removing userId from a current token cannot downgrade it to legacy verification
        ok 13 - removing userId from a current token cannot downgrade it to legacy verification
          ---
          duration_ms: 0.382085
          type: 'test'
          ...
        1..13
    ok 2 - HMAC token verification
      ---
      duration_ms: 6.114572
      type: 'suite'
      ...
    # Subtest: Replay resistance (authTimestamp)
        # Subtest: missing authTimestamp rejects
        ok 1 - missing authTimestamp rejects
          ---
          duration_ms: 0.299741
          type: 'test'
          ...
        # Subtest: expired token (beyond AUTH_TOKEN_MAX_AGE_MS) rejects
        ok 2 - expired token (beyond AUTH_TOKEN_MAX_AGE_MS) rejects
          ---
          duration_ms: 0.252282
          type: 'test'
          ...
        # Subtest: recent token (within AUTH_TOKEN_MAX_AGE_MS) is accepted
        ok 3 - recent token (within AUTH_TOKEN_MAX_AGE_MS) is accepted
          ---
          duration_ms: 0.24537
          type: 'test'
          ...
        # Subtest: future-dated token (beyond clock-skew allowance) rejects
        ok 4 - future-dated token (beyond clock-skew allowance) rejects
          ---
          duration_ms: 0.231763
          type: 'test'
          ...
        # Subtest: token within clock-skew allowance is accepted
        ok 5 - token within clock-skew allowance is accepted
          ---
          duration_ms: 0.264465
          type: 'test'
          ...
        1..5
    ok 3 - Replay resistance (authTimestamp)
      ---
      duration_ms: 1.504104
      type: 'suite'
      ...
    # Subtest: Fork PR payload (headRepoOwner/headRepoName)
        # Subtest: payload without headRepoOwner/headRepoName keeps the non-fork canonical shape
        ok 1 - payload without headRepoOwner/headRepoName keeps the non-fork canonical shape
          ---
          duration_ms: 0.269554
          type: 'test'
          ...
        # Subtest: payload with headRepoOwner/headRepoName includes fork identity
        ok 2 - payload with headRepoOwner/headRepoName includes fork identity
          ---
          duration_ms: 0.21343
          type: 'test'
          ...
        # Subtest: token signed with headRepoOwner/headRepoName is valid
        ok 3 - token signed with headRepoOwner/headRepoName is valid
          ---
          duration_ms: 0.238356
          type: 'test'
          ...
        # Subtest: tampered headRepoOwner invalidates token
        ok 4 - tampered headRepoOwner invalidates token
          ---
          duration_ms: 0.260838
          type: 'test'
          ...
        # Subtest: tampered headRepoName invalidates token
        ok 5 - tampered headRepoName invalidates token
          ---
          duration_ms: 0.230411
          type: 'test'
          ...
        # Subtest: adding headRepoOwner/headRepoName after signing invalidates token
        ok 6 - adding headRepoOwner/headRepoName after signing invalidates token
          ---
          duration_ms: 0.28337
          type: 'test'
          ...
        # Subtest: removing headRepoOwner/headRepoName after signing invalidates token
        ok 7 - removing headRepoOwner/headRepoName after signing invalidates token
          ---
          duration_ms: 0.439393
          type: 'test'
          ...
        1..7
    ok 4 - Fork PR payload (headRepoOwner/headRepoName)
      ---
      duration_ms: 2.186862
      type: 'suite'
      ...
    # Subtest: Whitelist (fail-closed) — exercises getUserWhitelist()
        # Subtest: empty GITHUB_USER_WHITELIST returns empty array (fail-closed)
        ok 1 - empty GITHUB_USER_WHITELIST returns empty array (fail-closed)
          ---
          duration_ms: 0.742019
          type: 'test'
          ...
        # Subtest: configured whitelist returns expected users
        ok 2 - configured whitelist returns expected users
          ---
          duration_ms: 0.327383
          type: 'test'
          ...
        # Subtest: user in whitelist passes includes check
        ok 3 - user in whitelist passes includes check
          ---
          duration_ms: 0.37393
          type: 'test'
          ...
        # Subtest: whitelist check is case-sensitive
        ok 4 - whitelist check is case-sensitive
          ---
          duration_ms: 0.359363
          type: 'test'
          ...
        1..4
    ok 5 - Whitelist (fail-closed) — exercises getUserWhitelist()
      ---
      duration_ms: 2.050808
      type: 'suite'
      ...
    1..5
ok 1 - System Task Authorization
  ---
  duration_ms: 20.607211
  type: 'suite'
  ...
# [2026-09-29 08:38:02.503 +0000] �[32mINFO�[39m: �[36mSQLite database connection established successfully�[39m
#     filename: "/tmp/propr-test-suite-3qkl2W/140-systemTaskAuth.test.ts/propr.test.sqlite"
#     environment: "test"
# [2026-09-29 08:38:02.518 +0000] �[32mINFO�[39m: �[36mSQLite database connection closed�[39m
1..1
# tests 33
# suites 6
# pass 33
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 2153.302855
[140/150] passed test/systemTaskAuth.test.ts in 2.3s

[141/150] test/testSuiteRunner.test.mjs
TAP version 13
# Subtest: release test-suite runner
    # Subtest: prepares desktop runtime dependencies before clean desktop and full-suite tests
    ok 1 - prepares desktop runtime dependencies before clean desktop and full-suite tests
      ---
      duration_ms: 2.522461
      type: 'test'
      ...
    # Subtest: selects supported test files deterministically and excludes live E2E
    ok 2 - selects supported test files deterministically and excludes live E2E
      ---
      duration_ms: 7.573793
      type: 'test'
      ...
    # Subtest: enables module mocking without hiding leaked resources behind forced exit
    ok 3 - enables module mocking without hiding leaked resources behind forced exit
      ---
      duration_ms: 0.21911
      type: 'test'
      ...
    # Subtest: requires an explicit flush opt-in before Redis isolation is destructive
    ok 4 - requires an explicit flush opt-in before Redis isolation is destructive
      ---
      duration_ms: 0.15546
      type: 'test'
      ...
    # Subtest: waits for a timed-out process to close after escalating to SIGKILL
    ok 5 - waits for a timed-out process to close after escalating to SIGKILL
      ---
      duration_ms: 1058.006782
      type: 'test'
      ...
    # Subtest: discovers root and workspace tests while delegating native workspace runners
    ok 6 - discovers root and workspace tests while delegating native workspace runners
      ---
      duration_ms: 4.58531
      type: 'test'
      ...
    # Subtest: delegates native workspace runners by script instead of package name
    ok 7 - delegates native workspace runners by script instead of package name
      ---
      duration_ms: 0.226444
      type: 'test'
      ...
    # Subtest: partitions every discovered file and native workspace part into exactly one shard
    ok 8 - partitions every discovered file and native workspace part into exactly one shard
      ---
      duration_ms: 19.261452
      type: 'test'
      ...
    # Subtest: partitions the real repository suite completely across the CI shard count
    ok 9 - partitions the real repository suite completely across the CI shard count
      ---
      duration_ms: 42.294952
      type: 'test'
      ...
    # Subtest: runs each native workspace part through the package runner shard option
    ok 10 - runs each native workspace part through the package runner shard option
      ---
      duration_ms: 6.473253
      type: 'test'
      ...
    # Subtest: rejects invalid or partial shard configuration
    ok 11 - rejects invalid or partial shard configuration
      ---
      duration_ms: 1.112222
      type: 'test'
      ...
    # Subtest: rejects shards that would run nothing and conflicting shard sources
    ok 12 - rejects shards that would run nothing and conflicting shard sources
      ---
      duration_ms: 3.000655
      type: 'test'
      ...
    # Subtest: lists a shard manifest without running tests
    ok 13 - lists a shard manifest without running tests
      ---
      duration_ms: 65.861664
      type: 'test'
      ...
    # Subtest: verifies shard summaries cover the suite exactly once
    ok 14 - verifies shard summaries cover the suite exactly once
      ---
      duration_ms: 4.62246
      type: 'test'
      ...
    # Subtest: reports per-unit timing for later shard balancing
    ok 15 - reports per-unit timing for later shard balancing
      ---
      duration_ms: 0.564005
      type: 'test'
      ...
    # Subtest: warns about passing units that are close to the per-unit timeout
    ok 16 - warns about passing units that are close to the per-unit timeout
      ---
      duration_ms: 0.508893
      type: 'test'
      ...
    # Subtest: records the per-unit timeout every unit was measured against
    ok 17 - records the per-unit timeout every unit was measured against
      ---
      duration_ms: 430.960224
      type: 'test'
      ...
    # Subtest: hands every unit the desktop fsync opt-out unless the caller set it explicitly
    ok 18 - hands every unit the desktop fsync opt-out unless the caller set it explicitly
      ---
      duration_ms: 823.265855
      type: 'test'
      ...
    # Subtest: keeps the four-shard matrix complete and isolated on either route
    ok 19 - keeps the four-shard matrix complete and isolated on either route
      ---
      duration_ms: 0.697826
      type: 'test'
      ...
    # Subtest: serializes nightly validation without cancelling an active live run
    ok 20 - serializes nightly validation without cancelling an active live run
      ---
      duration_ms: 0.275296
      type: 'test'
      ...
    1..20
ok 1 - release test-suite runner
  ---
  duration_ms: 2474.224537
  type: 'suite'
  ...
1..1
# tests 20
# suites 1
# pass 20
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 2739.836189
[141/150] passed test/testSuiteRunner.test.mjs in 2.9s

[142/150] test/ultrafixLoopContinuation.test.ts
TAP version 13
# Subtest: Ultrafix loop continuation logic
    # Subtest: review-success-stop: explicitly clean review
        # Subtest: determineNextAction returns null when the review is valid and clean
        ok 1 - determineNextAction returns null when the review is valid and clean
          ---
          duration_ms: 5.617582
          type: 'test'
          ...
        # Subtest: determineNextAction returns fix when a passing review still has blockers
        ok 2 - determineNextAction returns fix when a passing review still has blockers
          ---
          duration_ms: 1.720519
          type: 'test'
          ...
        # Subtest: goal completion is persisted as a successful terminal state
        ok 3 - goal completion is persisted as a successful terminal state
          ---
          duration_ms: 2.166505
          type: 'test'
          ...
        1..3
    ok 1 - review-success-stop: explicitly clean review
      ---
      duration_ms: 10.537779
      type: 'suite'
      ...
    # Subtest: review-success-continue: score below goal
        # Subtest: clean review below goal stops without a fix and persists an unsuccessful completion
        ok 1 - clean review below goal stops without a fix and persists an unsuccessful completion
          ---
          duration_ms: 1.054483
          type: 'test'
          ...
        # Subtest: determineNextAction returns fix when score is below goal
        ok 2 - determineNextAction returns fix when score is below goal
          ---
          duration_ms: 4.249983
          type: 'test'
          ...
        # Subtest: determineNextAction returns fix when score is null
        ok 3 - determineNextAction returns fix when score is null
          ---
          duration_ms: 1.452328
          type: 'test'
          ...
        1..3
    ok 2 - review-success-continue: score below goal
      ---
      duration_ms: 7.402923
      type: 'suite'
      ...
    # Subtest: fix-completion: schedules review
        # Subtest: determineNextAction returns review after fix
        ok 1 - determineNextAction returns review after fix
          ---
          duration_ms: 2.542359
          type: 'test'
          ...
        # Subtest: recordAction increments cycleCount after fix
        ok 2 - recordAction increments cycleCount after fix
          ---
          duration_ms: 1.412241
          type: 'test'
          ...
        # Subtest: recordAction does not increment cycleCount after review
        ok 3 - recordAction does not increment cycleCount after review
          ---
          duration_ms: 1.332493
          type: 'test'
          ...
        1..3
    ok 3 - fix-completion: schedules review
      ---
      duration_ms: 5.802408
      type: 'suite'
      ...
    # Subtest: terminal conditions: state persisted
        # Subtest: failed terminal state is persisted when max cycles are reached
        ok 1 - failed terminal state is persisted when max cycles are reached
          ---
          duration_ms: 2.102895
          type: 'test'
          ...
        # Subtest: inactive loop returns null action
        ok 2 - inactive loop returns null action
          ---
          duration_ms: 1.874047
          type: 'test'
          ...
        1..2
    ok 4 - terminal conditions: state persisted
      ---
      duration_ms: 4.215097
      type: 'suite'
      ...
    # Subtest: label-based loop control
        # Subtest: loop stops when no active state exists
        ok 1 - loop stops when no active state exists
          ---
          duration_ms: 0.321401
          type: 'test'
          ...
        # Subtest: clearState removes loop state completely
        ok 2 - clearState removes loop state completely
          ---
          duration_ms: 0.40607
          type: 'test'
          ...
        1..2
    ok 5 - label-based loop control
      ---
      duration_ms: 0.884485
      type: 'suite'
      ...
    # Subtest: multi-cycle progression
        # Subtest: full cycle: review → fix → review with incrementing cycle count
        ok 1 - full cycle: review → fix → review with incrementing cycle count
          ---
          duration_ms: 7.286064
          type: 'test'
          ...
        # Subtest: stops at max cycles even if goal not met
        ok 2 - stops at max cycles even if goal not met
          ---
          duration_ms: 4.39107
          type: 'test'
          ...
        # Subtest: max cycle limit allows five review and five fix steps
        ok 3 - max cycle limit allows five review and five fix steps
          ---
          duration_ms: 1.753752
          type: 'test'
          ...
        1..3
    ok 6 - multi-cycle progression
      ---
      duration_ms: 13.738922
      type: 'suite'
      ...
    1..6
ok 1 - Ultrafix loop continuation logic
  ---
  duration_ms: 43.653621
  type: 'suite'
  ...
1..1
# tests 16
# suites 7
# pass 16
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 329.702222
[142/150] passed test/ultrafixLoopContinuation.test.ts in 0.5s

[143/150] test/ultrafixSettings.test.ts
TAP version 13
# Subtest: VALID_SETTING_KEYS includes new ultrafix keys
    # Subtest: should include pr_review_model
    ok 1 - should include pr_review_model
      ---
      duration_ms: 0.768548
      type: 'test'
      ...
    # Subtest: should include model_reasoning_level
    ok 2 - should include model_reasoning_level
      ---
      duration_ms: 0.11744
      type: 'test'
      ...
    # Subtest: should include ultrafix_rating_goal
    ok 3 - should include ultrafix_rating_goal
      ---
      duration_ms: 0.111348
      type: 'test'
      ...
    # Subtest: should include ultrafix_max_cycles
    ok 4 - should include ultrafix_max_cycles
      ---
      duration_ms: 0.100959
      type: 'test'
      ...
    # Subtest: should include ultrafix_pause_seconds
    ok 5 - should include ultrafix_pause_seconds
      ---
      duration_ms: 0.09618
      type: 'test'
      ...
    # Subtest: should include PR review context settings
    ok 6 - should include PR review context settings
      ---
      duration_ms: 0.136335
      type: 'test'
      ...
    # Subtest: should keep expected setting keys valid
    ok 7 - should keep expected setting keys valid
      ---
      duration_ms: 0.12779
      type: 'test'
      ...
    1..7
ok 1 - VALID_SETTING_KEYS includes new ultrafix keys
  ---
  duration_ms: 2.640321
  type: 'suite'
  ...
# Subtest: isValidSettingKey for new keys
    # Subtest: pr_review_model is valid
    ok 1 - pr_review_model is valid
      ---
      duration_ms: 0.248354
      type: 'test'
      ...
    # Subtest: model_reasoning_level is valid
    ok 2 - model_reasoning_level is valid
      ---
      duration_ms: 0.199673
      type: 'test'
      ...
    # Subtest: ultrafix_rating_goal is valid
    ok 3 - ultrafix_rating_goal is valid
      ---
      duration_ms: 0.22999
      type: 'test'
      ...
    # Subtest: ultrafix_max_cycles is valid
    ok 4 - ultrafix_max_cycles is valid
      ---
      duration_ms: 0.110206
      type: 'test'
      ...
    # Subtest: ultrafix_pause_seconds is valid
    ok 5 - ultrafix_pause_seconds is valid
      ---
      duration_ms: 0.085881
      type: 'test'
      ...
    # Subtest: unknown_key is not valid
    ok 6 - unknown_key is not valid
      ---
      duration_ms: 0.080571
      type: 'test'
      ...
    1..6
ok 2 - isValidSettingKey for new keys
  ---
  duration_ms: 1.30414
  type: 'suite'
  ...
# Subtest: parseSettingValue for pr_review_model
    # Subtest: should accept any string value
    ok 1 - should accept any string value
      ---
      duration_ms: 0.424354
      type: 'test'
      ...
    # Subtest: should accept empty string
    ok 2 - should accept empty string
      ---
      duration_ms: 0.091821
      type: 'test'
      ...
    1..2
ok 3 - parseSettingValue for pr_review_model
  ---
  duration_ms: 0.621924
  type: 'suite'
  ...
# Subtest: parseSettingValue for PR review context
    # Subtest: parses the enable switch
    ok 1 - parses the enable switch
      ---
      duration_ms: 0.137838
      type: 'test'
      ...
    # Subtest: accepts automatic and explicit context token limits
    ok 2 - accepts automatic and explicit context token limits
      ---
      duration_ms: 0.161452
      type: 'test'
      ...
    # Subtest: rejects context token limits below the supported explicit minimum
    ok 3 - rejects context token limits below the supported explicit minimum
      ---
      duration_ms: 0.398565
      type: 'test'
      ...
    # Subtest: accepts review context budget percentages in 10% increments
    ok 4 - accepts review context budget percentages in 10% increments
      ---
      duration_ms: 0.209461
      type: 'test'
      ...
    # Subtest: rejects unsupported review context budget percentages
    ok 5 - rejects unsupported review context budget percentages
      ---
      duration_ms: 0.223548
      type: 'test'
      ...
    1..5
ok 4 - parseSettingValue for PR review context
  ---
  duration_ms: 1.286277
  type: 'suite'
  ...
# Subtest: parseSettingValue for ultrafix_rating_goal
    # Subtest: should parse valid value 7
    ok 1 - should parse valid value 7
      ---
      duration_ms: 0.174577
      type: 'test'
      ...
    # Subtest: should accept minimum value 1
    ok 2 - should accept minimum value 1
      ---
      duration_ms: 0.089678
      type: 'test'
      ...
    # Subtest: should accept maximum value 10
    ok 3 - should accept maximum value 10
      ---
      duration_ms: 0.079409
      type: 'test'
      ...
    # Subtest: should reject value 0
    ok 4 - should reject value 0
      ---
      duration_ms: 0.113452
      type: 'test'
      ...
    # Subtest: should reject value 11
    ok 5 - should reject value 11
      ---
      duration_ms: 0.169497
      type: 'test'
      ...
    # Subtest: should reject non-numeric value
    ok 6 - should reject non-numeric value
      ---
      duration_ms: 0.125425
      type: 'test'
      ...
    # Subtest: should reject negative value
    ok 7 - should reject negative value
      ---
      duration_ms: 0.106038
      type: 'test'
      ...
    1..7
ok 5 - parseSettingValue for ultrafix_rating_goal
  ---
  duration_ms: 1.111419
  type: 'suite'
  ...
# Subtest: parseSettingValue for ultrafix_max_cycles
    # Subtest: should parse valid value 5
    ok 1 - should parse valid value 5
      ---
      duration_ms: 0.156072
      type: 'test'
      ...
    # Subtest: should accept minimum value 1
    ok 2 - should accept minimum value 1
      ---
      duration_ms: 0.150772
      type: 'test'
      ...
    # Subtest: should accept large values (no upper limit)
    ok 3 - should accept large values (no upper limit)
      ---
      duration_ms: 0.100077
      type: 'test'
      ...
    # Subtest: should reject value 0
    ok 4 - should reject value 0
      ---
      duration_ms: 0.134472
      type: 'test'
      ...
    # Subtest: should reject non-numeric value
    ok 5 - should reject non-numeric value
      ---
      duration_ms: 0.120065
      type: 'test'
      ...
    1..5
ok 6 - parseSettingValue for ultrafix_max_cycles
  ---
  duration_ms: 0.831225
  type: 'suite'
  ...
# Subtest: parseSettingValue for ultrafix_pause_seconds
    # Subtest: should parse valid value 60
    ok 1 - should parse valid value 60
      ---
      duration_ms: 0.177512
      type: 'test'
      ...
    # Subtest: should accept minimum value 0
    ok 2 - should accept minimum value 0
      ---
      duration_ms: 0.092172
      type: 'test'
      ...
    # Subtest: should accept large values (no upper limit)
    ok 3 - should accept large values (no upper limit)
      ---
      duration_ms: 0.086261
      type: 'test'
      ...
    # Subtest: should reject value -1
    ok 4 - should reject value -1
      ---
      duration_ms: 0.123632
      type: 'test'
      ...
    # Subtest: should reject non-numeric value
    ok 5 - should reject non-numeric value
      ---
      duration_ms: 0.120075
      type: 'test'
      ...
    1..5
ok 7 - parseSettingValue for ultrafix_pause_seconds
  ---
  duration_ms: 0.785981
  type: 'suite'
  ...
1..7
# tests 37
# suites 7
# pass 37
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 453.457098
[143/150] passed test/ultrafixSettings.test.ts in 0.6s

[144/150] test/validateRelayUrl.test.ts
TAP version 13
# Subtest: validateRelayUrl allows https and localhost http URLs
ok 1 - validateRelayUrl allows https and localhost http URLs
  ---
  duration_ms: 1.105148
  type: 'test'
  ...
# Subtest: validateRelayUrl rejects non-localhost http and non-http schemes
ok 2 - validateRelayUrl rejects non-localhost http and non-http schemes
  ---
  duration_ms: 0.272931
  type: 'test'
  ...
# Subtest: validateRelayUrl reports invalid URLs
ok 3 - validateRelayUrl reports invalid URLs
  ---
  duration_ms: 0.226344
  type: 'test'
  ...
1..3
# tests 3
# suites 0
# pass 3
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 254.944724
[144/150] passed test/validateRelayUrl.test.ts in 0.4s

[145/150] test/visualPreviewRelease.test.ts
TAP version 13
# [2026-09-29 08:38:09.132 +0000] �[32mINFO�[39m: �[36mSQLite database connection established successfully�[39m
#     filename: "/tmp/propr-test-suite-3qkl2W/145-visualPreviewRelease.test.ts/propr.test.sqlite"
#     environment: "test"
# Subtest: pr: pro GitHub plan / plus
ok 1 - pr: pro GitHub plan / plus
  ---
  duration_ms: 95.04869
  type: 'test'
  ...
# Subtest: follow-up: pro GitHub plan / plus
ok 2 - follow-up: pro GitHub plan / plus
  ---
  duration_ms: 65.677713
  type: 'test'
  ...
# Subtest: pr: pro GitHub plan / community
ok 3 - pr: pro GitHub plan / community
  ---
  duration_ms: 2.697658
  type: 'test'
  ...
# [2026-09-29 08:38:09.304 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "plus_required"
# [2026-09-29 08:38:09.311 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "plus_required"
# Subtest: follow-up: pro GitHub plan / community
ok 4 - follow-up: pro GitHub plan / community
  ---
  duration_ms: 6.59984
  type: 'test'
  ...
# [2026-09-29 08:38:09.313 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "unavailable"
# Subtest: pr: pro GitHub plan / offline
ok 5 - pr: pro GitHub plan / offline
  ---
  duration_ms: 1.991787
  type: 'test'
  ...
# [2026-09-29 08:38:09.315 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "unavailable"
# Subtest: follow-up: pro GitHub plan / offline
ok 6 - follow-up: pro GitHub plan / offline
  ---
  duration_ms: 1.982559
  type: 'test'
  ...
# Subtest: pr: pro GitHub plan / quota
ok 7 - pr: pro GitHub plan / quota
  ---
  duration_ms: 25.155526
  type: 'test'
  ...
# [2026-09-29 08:38:09.341 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "quota_exceeded"
# Subtest: follow-up: pro GitHub plan / quota
ok 8 - follow-up: pro GitHub plan / quota
  ---
  duration_ms: 23.588551
  type: 'test'
  ...
# [2026-09-29 08:38:09.364 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "quota_exceeded"
# Subtest: pr: pro GitHub plan / upload-expired
ok 9 - pr: pro GitHub plan / upload-expired
  ---
  duration_ms: 25.071564
  type: 'test'
  ...
# [2026-09-29 08:38:09.389 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "object_mismatch"
# Subtest: follow-up: pro GitHub plan / upload-expired
ok 10 - follow-up: pro GitHub plan / upload-expired
  ---
  duration_ms: 17.735879
  type: 'test'
  ...
# [2026-09-29 08:38:09.408 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "object_mismatch"
# Subtest: pr: pro GitHub plan / object-expired
ok 11 - pr: pro GitHub plan / object-expired
  ---
  duration_ms: 44.643171
  type: 'test'
  ...
# [2026-09-29 08:38:09.452 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "object_mismatch"
# Subtest: follow-up: pro GitHub plan / object-expired
ok 12 - follow-up: pro GitHub plan / object-expired
  ---
  duration_ms: 40.264722
  type: 'test'
  ...
# [2026-09-29 08:38:09.493 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "object_mismatch"
# Subtest: pr: pro GitHub plan / github-failed
ok 13 - pr: pro GitHub plan / github-failed
  ---
  duration_ms: 39.090109
  type: 'test'
  ...
# Subtest: follow-up: pro GitHub plan / github-failed
ok 14 - follow-up: pro GitHub plan / github-failed
  ---
  duration_ms: 37.617218
  type: 'test'
  ...
# Subtest: pr: pro GitHub plan / legacy
ok 15 - pr: pro GitHub plan / legacy
  ---
  duration_ms: 1.315673
  type: 'test'
  ...
# Subtest: follow-up: pro GitHub plan / legacy
ok 16 - follow-up: pro GitHub plan / legacy
  ---
  duration_ms: 1.195269
  type: 'test'
  ...
# Subtest: pr: free GitHub plan / plus
ok 17 - pr: free GitHub plan / plus
  ---
  duration_ms: 45.219269
  type: 'test'
  ...
# [2026-09-29 08:38:09.571 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "unavailable"
# [2026-09-29 08:38:09.572 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "unavailable"
# Subtest: follow-up: free GitHub plan / plus
ok 18 - follow-up: free GitHub plan / plus
  ---
  duration_ms: 36.925899
  type: 'test'
  ...
# Subtest: pr: free GitHub plan / community
ok 19 - pr: free GitHub plan / community
  ---
  duration_ms: 1.158408
  type: 'test'
  ...
# Subtest: follow-up: free GitHub plan / community
ok 20 - follow-up: free GitHub plan / community
  ---
  duration_ms: 1.136266
  type: 'test'
  ...
# Subtest: pr: free GitHub plan / offline
ok 21 - pr: free GitHub plan / offline
  ---
  duration_ms: 1.6139
  type: 'test'
  ...
# Subtest: follow-up: free GitHub plan / offline
ok 22 - follow-up: free GitHub plan / offline
  ---
  duration_ms: 1.46386
  type: 'test'
  ...
# Subtest: pr: free GitHub plan / quota
ok 23 - pr: free GitHub plan / quota
  ---
  duration_ms: 15.260196
  type: 'test'
  ...
# [2026-09-29 08:38:09.656 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "plus_required"
# [2026-09-29 08:38:09.657 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "plus_required"
# [2026-09-29 08:38:09.658 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "unavailable"
# [2026-09-29 08:38:09.660 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "unavailable"
# [2026-09-29 08:38:09.675 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "quota_exceeded"
# Subtest: follow-up: free GitHub plan / quota
ok 24 - follow-up: free GitHub plan / quota
  ---
  duration_ms: 19.817625
  type: 'test'
  ...
# [2026-09-29 08:38:09.695 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "quota_exceeded"
# Subtest: pr: free GitHub plan / upload-expired
ok 25 - pr: free GitHub plan / upload-expired
  ---
  duration_ms: 13.96225
  type: 'test'
  ...
# [2026-09-29 08:38:09.709 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "object_mismatch"
# Subtest: follow-up: free GitHub plan / upload-expired
ok 26 - follow-up: free GitHub plan / upload-expired
  ---
  duration_ms: 18.637133
  type: 'test'
  ...
# [2026-09-29 08:38:09.728 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "object_mismatch"
# Subtest: pr: free GitHub plan / object-expired
ok 27 - pr: free GitHub plan / object-expired
  ---
  duration_ms: 37.464497
  type: 'test'
  ...
# [2026-09-29 08:38:09.765 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "object_mismatch"
# Subtest: follow-up: free GitHub plan / object-expired
ok 28 - follow-up: free GitHub plan / object-expired
  ---
  duration_ms: 36.927635
  type: 'test'
  ...
# [2026-09-29 08:38:09.802 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "object_mismatch"
# Subtest: pr: free GitHub plan / github-failed
ok 29 - pr: free GitHub plan / github-failed
  ---
  duration_ms: 40.003984
  type: 'test'
  ...
# Subtest: follow-up: free GitHub plan / github-failed
ok 30 - follow-up: free GitHub plan / github-failed
  ---
  duration_ms: 37.788373
  type: 'test'
  ...
# Subtest: pr: free GitHub plan / legacy
ok 31 - pr: free GitHub plan / legacy
  ---
  duration_ms: 1.125216
  type: 'test'
  ...
# Subtest: follow-up: free GitHub plan / legacy
ok 32 - follow-up: free GitHub plan / legacy
  ---
  duration_ms: 1.089429
  type: 'test'
  ...
# Subtest: pr: unknown GitHub plan / plus
ok 33 - pr: unknown GitHub plan / plus
  ---
  duration_ms: 38.018233
  type: 'test'
  ...
# [2026-09-29 08:38:09.881 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "unavailable"
# [2026-09-29 08:38:09.883 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "unavailable"
# Subtest: follow-up: unknown GitHub plan / plus
ok 34 - follow-up: unknown GitHub plan / plus
  ---
  duration_ms: 39.653343
  type: 'test'
  ...
# Subtest: pr: unknown GitHub plan / community
ok 35 - pr: unknown GitHub plan / community
  ---
  duration_ms: 1.235942
  type: 'test'
  ...
# Subtest: follow-up: unknown GitHub plan / community
ok 36 - follow-up: unknown GitHub plan / community
  ---
  duration_ms: 1.5814
  type: 'test'
  ...
# Subtest: pr: unknown GitHub plan / offline
ok 37 - pr: unknown GitHub plan / offline
  ---
  duration_ms: 1.076835
  type: 'test'
  ...
# [2026-09-29 08:38:09.962 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "plus_required"
# Subtest: follow-up: unknown GitHub plan / offline
ok 38 - follow-up: unknown GitHub plan / offline
  ---
  duration_ms: 0.989091
  type: 'test'
  ...
# [2026-09-29 08:38:09.963 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "plus_required"
# [2026-09-29 08:38:09.964 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "unavailable"
# [2026-09-29 08:38:09.966 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "unavailable"
# Subtest: pr: unknown GitHub plan / quota
ok 39 - pr: unknown GitHub plan / quota
  ---
  duration_ms: 13.867109
  type: 'test'
  ...
# [2026-09-29 08:38:09.979 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "quota_exceeded"
# Subtest: follow-up: unknown GitHub plan / quota
ok 40 - follow-up: unknown GitHub plan / quota
  ---
  duration_ms: 14.993067
  type: 'test'
  ...
# [2026-09-29 08:38:09.994 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "quota_exceeded"
# Subtest: pr: unknown GitHub plan / upload-expired
ok 41 - pr: unknown GitHub plan / upload-expired
  ---
  duration_ms: 17.448001
  type: 'test'
  ...
# Subtest: follow-up: unknown GitHub plan / upload-expired
ok 42 - follow-up: unknown GitHub plan / upload-expired
  ---
  duration_ms: 14.073789
  type: 'test'
  ...
# [2026-09-29 08:38:10.012 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "object_mismatch"
# [2026-09-29 08:38:10.026 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "object_mismatch"
# Subtest: pr: unknown GitHub plan / object-expired
ok 43 - pr: unknown GitHub plan / object-expired
  ---
  duration_ms: 39.487265
  type: 'test'
  ...
# [2026-09-29 08:38:10.066 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "object_mismatch"
# Subtest: follow-up: unknown GitHub plan / object-expired
ok 44 - follow-up: unknown GitHub plan / object-expired
  ---
  duration_ms: 38.137525
  type: 'test'
  ...
# [2026-09-29 08:38:10.104 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "object_mismatch"
# Subtest: pr: unknown GitHub plan / github-failed
ok 45 - pr: unknown GitHub plan / github-failed
  ---
  duration_ms: 37.355433
  type: 'test'
  ...
# Subtest: follow-up: unknown GitHub plan / github-failed
ok 46 - follow-up: unknown GitHub plan / github-failed
  ---
  duration_ms: 36.996089
  type: 'test'
  ...
# Subtest: pr: unknown GitHub plan / legacy
ok 47 - pr: unknown GitHub plan / legacy
  ---
  duration_ms: 1.130185
  type: 'test'
  ...
# Subtest: follow-up: unknown GitHub plan / legacy
ok 48 - follow-up: unknown GitHub plan / legacy
  ---
  duration_ms: 1.124414
  type: 'test'
  ...
# Subtest: unknown and free GitHub-only collection conservatively excludes an oversized video
ok 49 - unknown and free GitHub-only collection conservatively excludes an oversized video
  ---
  duration_ms: 3.92773
  type: 'test'
  ...
# Subtest: issue completion and persisted task logs redact preview and staging paths
ok 50 - issue completion and persisted task logs redact preview and staging paths
  ---
  duration_ms: 33.004694
  type: 'test'
  ...
# [2026-09-29 08:38:10.179 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "unavailable"
# [2026-09-29 08:38:10.181 +0000] �[33mWARN�[39m: �[36mManaged preview original was not stored; continuing GitHub publication�[39m
#     code: "unavailable"
# [2026-09-29 08:38:10.189 +0000] �[32mINFO�[39m: �[36mCreated conversation log file�[39m
#     conversationPath: "/tmp/claude-logs/issue-2283-2026-09-29T08-38-10-186Z-conversation.json"
#     messageCount: 1
# [2026-09-29 08:38:10.189 +0000] �[32mINFO�[39m: �[36mCreated raw output log file�[39m
#     outputPath: "/tmp/claude-logs/issue-2283-2026-09-29T08-38-10-186Z-output.txt"
#     size: 189
# [2026-09-29 08:38:10.216 +0000] �[32mINFO�[39m: �[36mCreated conversation log file�[39m
#     conversationPath: "/tmp/claude-logs/issue-2283-2026-09-29T08-38-10-215Z-conversation.json"
#     messageCount: 1
# [2026-09-29 08:38:10.216 +0000] �[32mINFO�[39m: �[36mCreated raw output log file�[39m
#     outputPath: "/tmp/claude-logs/issue-2283-2026-09-29T08-38-10-215Z-output.txt"
#     size: 189
1..50
# tests 50
# suites 0
# pass 50
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 3107.252545
[145/150] passed test/visualPreviewRelease.test.ts in 3.2s

[146/150] test/webPushDeploymentContract.test.mjs
TAP version 13
# Subtest: legacy production Compose forwards every documented Web Push tuning variable
ok 1 - legacy production Compose forwards every documented Web Push tuning variable
  ---
  duration_ms: 1.241263
  type: 'test'
  ...
# Subtest: the reverse-proxy documentation includes every explicitly precached logo
ok 2 - the reverse-proxy documentation includes every explicitly precached logo
  ---
  duration_ms: 0.430987
  type: 'test'
  ...
1..2
# tests 2
# suites 0
# pass 2
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 240.255821
[146/150] passed test/webPushDeploymentContract.test.mjs in 0.4s

[147/150] test/worker.test.ts
TAP version 13
# Subtest: worker behavioral contracts
    # Subtest: label gating skips missing-primary and completed issues
    ok 1 - label gating skips missing-primary and completed issues
      ---
      duration_ms: 2.443663
      type: 'test'
      ...
    # Subtest: processing-label behavior adds the tag once and preserves an existing tag
    ok 2 - processing-label behavior adds the tag once and preserves an existing tag
      ---
      duration_ms: 3.91745
      type: 'test'
      ...
    # Subtest: authentication failures mark the task failed and remain observable
    ok 3 - authentication failures mark the task failed and remain observable
      ---
      duration_ms: 1.061827
      type: 'test'
      ...
    # Subtest: runtime processor dispatches every supported job type and rejects unknown jobs
    ok 4 - runtime processor dispatches every supported job type and rejects unknown jobs
      ---
      duration_ms: 0.623647
      type: 'test'
      ...
    # Subtest: worker construction attaches hooks before starting the paused worker
    ok 5 - worker construction attaches hooks before starting the paused worker
      ---
      duration_ms: 0.477503
      type: 'test'
      ...
    1..5
ok 1 - worker behavioral contracts
  ---
  duration_ms: 9.909994
  type: 'suite'
  ...
# [2026-09-29 08:38:12.782 +0000] �[33mWARN�[39m: �[36mIssue no longer has primary tag 'AI'. Skipping.�[39m
#     jobId: "job-1"
#     issueNumber: 42
# [2026-09-29 08:38:12.782 +0000] �[33mWARN�[39m: �[36mIssue already has 'AI-done' tag. Skipping.�[39m
#     jobId: "job-1"
#     issueNumber: 42
# [2026-09-29 08:38:12.789 +0000] �[32mINFO�[39m: �[36mSQLite database connection established successfully�[39m
#     filename: "/tmp/propr-test-suite-3qkl2W/147-worker.test.ts/propr.test.sqlite"
#     environment: "test"
# [2026-09-29 08:38:12.791 +0000] �[32mINFO�[39m: �[36mSQLite database connection closed�[39m
1..1
# tests 5
# suites 1
# pass 5
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 2175.614884
[147/150] passed test/worker.test.ts in 2.3s

[148/150] test/workerStateManagerRedisIntegration.test.ts
TAP version 13
# Subtest: Redis CAS rejects a stale metadata snapshot after terminalization
ok 1 - Redis CAS rejects a stale metadata snapshot after terminalization
  ---
  duration_ms: 21.93183
  type: 'test'
  ...
# [2026-09-29 08:38:13.776 +0000] �[32mINFO�[39m: �[36mSQLite database connection established successfully�[39m
#     filename: "/tmp/propr-test-suite-3qkl2W/148-workerStateManagerRedisIntegration.test.ts/propr.test.sqlite"
#     environment: "test"
# [2026-09-29 08:38:13.793 +0000] �[32mINFO�[39m: �[36mSQLite database connection closed�[39m
1..1
# tests 1
# suites 0
# pass 1
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 803.390034
[148/150] passed test/workerStateManagerRedisIntegration.test.ts in 0.9s

[149/150] test/worktreeLifecycle.integration.test.ts
TAP version 13
# Subtest: Worktree Lifecycle Integration Tests
    # Subtest: Worktree Structure Creation
        # Subtest: creates worktree with proper directory structure
        ok 1 - creates worktree with proper directory structure
          ---
          duration_ms: 212.157079
          type: 'test'
          ...
        # Subtest: .git file exists in worktree (not a directory)
        ok 2 - .git file exists in worktree (not a directory)
          ---
          duration_ms: 198.331368
          type: 'test'
          ...
        # Subtest: .git file contains valid gitdir reference
        ok 3 - .git file contains valid gitdir reference
          ---
          duration_ms: 192.134393
          type: 'test'
          ...
        # Subtest: worktree creates unique directories for different issues
        ok 4 - worktree creates unique directories for different issues
          ---
          duration_ms: 200.928787
          type: 'test'
          ...
        # Subtest: worktree includes model suffix when model name provided
        ok 5 - worktree includes model suffix when model name provided
          ---
          duration_ms: 203.799649
          type: 'test'
          ...
        1..5
    ok 1 - Worktree Structure Creation
      ---
      duration_ms: 1008.597426
      type: 'suite'
      ...
    # Subtest: Checkout Conflict Handling
        # Subtest: handles creating worktree when branch already exists locally
        ok 1 - handles creating worktree when branch already exists locally
          ---
          duration_ms: 250.687095
          type: 'test'
          ...
        # Subtest: handles creating worktree when directory already exists
        ok 2 - handles creating worktree when directory already exists
          ---
          duration_ms: 193.226267
          type: 'test'
          ...
        # Subtest: concurrent worktree creation for same issue with different models
        ok 3 - concurrent worktree creation for same issue with different models
          ---
          duration_ms: 216.247192
          type: 'test'
          ...
        # Subtest: worktree branch points to correct HEAD
        ok 4 - worktree branch points to correct HEAD
          ---
          duration_ms: 199.665985
          type: 'test'
          ...
        1..4
    ok 2 - Checkout Conflict Handling
      ---
      duration_ms: 860.520298
      type: 'suite'
      ...
    # Subtest: Worktree Cleanup
        # Subtest: worktree can be removed with git worktree remove
        ok 1 - worktree can be removed with git worktree remove
          ---
          duration_ms: 242.046525
          type: 'test'
          ...
        # Subtest: worktree directory can be cleaned via fs.remove
        ok 2 - worktree directory can be cleaned via fs.remove
          ---
          duration_ms: 190.240349
          type: 'test'
          ...
        # Subtest: associated branch can be deleted after worktree removal
        ok 3 - associated branch can be deleted after worktree removal
          ---
          duration_ms: 255.579047
          type: 'test'
          ...
        # Subtest: git worktree list reflects created and removed worktrees
        ok 4 - git worktree list reflects created and removed worktrees
          ---
          duration_ms: 256.209206
          type: 'test'
          ...
        1..4
    ok 3 - Worktree Cleanup
      ---
      duration_ms: 944.52022
      type: 'suite'
      ...
    # Subtest: Edge Cases
        # Subtest: handles special characters in issue title
        ok 1 - handles special characters in issue title
          ---
          duration_ms: 191.321684
          type: 'test'
          ...
        # Subtest: handles very long issue titles
        ok 2 - handles very long issue titles
          ---
          duration_ms: 189.384842
          type: 'test'
          ...
        # Subtest: worktree metadata exists in main repo .git/worktrees
        ok 3 - worktree metadata exists in main repo .git/worktrees
          ---
          duration_ms: 191.53333
          type: 'test'
          ...
        1..3
    ok 4 - Edge Cases
      ---
      duration_ms: 572.587566
      type: 'suite'
      ...
    # Subtest: Worktree Cleanup with Retention Strategies
        # Subtest: keep_on_failure strategy creates retention marker when success is false
        ok 1 - keep_on_failure strategy creates retention marker when success is false
          ---
          duration_ms: 194.286351
          type: 'test'
          ...
        # Subtest: keep_on_failure strategy removes worktree when success is true
        ok 2 - keep_on_failure strategy removes worktree when success is true
          ---
          duration_ms: 242.084341
          type: 'test'
          ...
        # Subtest: always_delete strategy removes worktree regardless of success
        ok 3 - always_delete strategy removes worktree regardless of success
          ---
          duration_ms: 243.531707
          type: 'test'
          ...
        # Subtest: keep_for_hours strategy creates marker and then removes worktree
        ok 4 - keep_for_hours strategy creates marker and then removes worktree
          ---
          duration_ms: 245.414601
          type: 'test'
          ...
        # Subtest: retention marker contains correct scheduled cleanup time
        ok 5 - retention marker contains correct scheduled cleanup time
          ---
          duration_ms: 192.210172
          type: 'test'
          ...
        1..5
    ok 5 - Worktree Cleanup with Retention Strategies
      ---
      duration_ms: 1117.98586
      type: 'suite'
      ...
    # Subtest: Expired Worktree Cleanup
        # Subtest: cleanupExpiredWorktrees removes worktrees past scheduled cleanup time
        ok 1 - cleanupExpiredWorktrees removes worktrees past scheduled cleanup time
          ---
          duration_ms: 193.40563
          type: 'test'
          ...
        # Subtest: cleanupExpiredWorktrees retains worktrees before scheduled cleanup time
        ok 2 - cleanupExpiredWorktrees retains worktrees before scheduled cleanup time
          ---
          duration_ms: 190.294575
          type: 'test'
          ...
        # Subtest: cleanupExpiredWorktrees handles multiple worktrees with mixed expiration
        ok 3 - cleanupExpiredWorktrees handles multiple worktrees with mixed expiration
          ---
          duration_ms: 202.015178
          type: 'test'
          ...
        # Subtest: cleanupExpiredWorktrees handles non-existent base path gracefully
        ok 4 - cleanupExpiredWorktrees handles non-existent base path gracefully
          ---
          duration_ms: 178.615995
          type: 'test'
          ...
        # Subtest: cleanupExpiredWorktrees handles corrupted retention info gracefully
        ok 5 - cleanupExpiredWorktrees handles corrupted retention info gracefully
          ---
          duration_ms: 191.153982
          type: 'test'
          ...
        1..5
    ok 6 - Expired Worktree Cleanup
      ---
      duration_ms: 955.851224
      type: 'suite'
      ...
    # Subtest: Safe Worktree Pruning
        # Subtest: detects and prunes stale metadata when worktree directory is missing
        ok 1 - detects and prunes stale metadata when worktree directory is missing
          ---
          duration_ms: 191.382888
          type: 'test'
          ...
        # Subtest: skips young stale entries that are below minimum age threshold
        ok 2 - skips young stale entries that are below minimum age threshold
          ---
          duration_ms: 189.570806
          type: 'test'
          ...
        # Subtest: handles non-existent .git/worktrees directory gracefully
        ok 3 - handles non-existent .git/worktrees directory gracefully
          ---
          duration_ms: 297.039837
          type: 'test'
          ...
        # Subtest: prunes entries without gitdir file when old enough
        ok 4 - prunes entries without gitdir file when old enough
          ---
          duration_ms: 190.828659
          type: 'test'
          ...
        # Subtest: skips entries without gitdir file when too young
        ok 5 - skips entries without gitdir file when too young
          ---
          duration_ms: 190.152558
          type: 'test'
          ...
        # Subtest: preserves valid worktree metadata for existing directories
        ok 6 - preserves valid worktree metadata for existing directories
          ---
          duration_ms: 189.590764
          type: 'test'
          ...
        # Subtest: handles mixed scenarios with valid, stale-old, and stale-young entries
        ok 7 - handles mixed scenarios with valid, stale-old, and stale-young entries
          ---
          duration_ms: 211.473177
          type: 'test'
          ...
        # Subtest: respects configurable minimum age threshold
        ok 8 - respects configurable minimum age threshold
          ---
          duration_ms: 191.368805
          type: 'test'
          ...
        1..8
    ok 7 - Safe Worktree Pruning
      ---
      duration_ms: 1651.950879
      type: 'suite'
      ...
    1..7
ok 1 - Worktree Lifecycle Integration Tests
  ---
  duration_ms: 7112.932411
  type: 'suite'
  ...
1..1
# tests 34
# suites 8
# pass 34
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 7524.529058
[149/150] passed test/worktreeLifecycle.integration.test.ts in 7.7s

[150/150] propr-ui#4/4 (workspace test script)

> propr-ui@0.0.1 test
> vitest run --shard=4/4


�[1m�[30m�[46m RUN �[49m�[39m�[22m �[36mv5.0.0 �[39m�[90m/home/runner/work/propr/propr/propr-ui�[39m

 �[32m✓�[39m src/hooks/useVoiceBriefing.test.tsx �[2m(�[22m�[2m29 tests�[22m�[2m)�[22m�[32m 191�[2mms�[22m�[39m
 �[32m✓�[39m src/desktop/DesktopExperience.management.test.tsx �[2m(�[22m�[2m19 tests�[22m�[2m)�[22m�[33m 1340�[2mms�[22m�[39m
   �[32m✓�[39m DesktopExperience profile management �[2m(19)�[22m
     �[33m�[2m✓�[22m�[39m switches instances and opens management from the compact connected selector�[33m 380�[2mms�[22m�[39m
 �[32m✓�[39m src/components/Dashboard.designRules.test.tsx �[2m(�[22m�[2m18 tests�[22m�[2m)�[22m�[33m 1106�[2mms�[22m�[39m
 �[32m✓�[39m src/pages/GoalsPage.test.tsx �[2m(�[22m�[2m55 tests�[22m�[2m)�[22m�[33m 5800�[2mms�[22m�[39m
   �[32m✓�[39m GoalsPage �[2m(55)�[22m
     �[33m�[2m✓�[22m�[39m reconciles the queue exactly once when the socket comes back�[33m 457�[2mms�[22m�[39m
     �[33m�[2m✓�[22m�[39m narrows the queue by every search keyword and mirrors the query in the URL�[33m 511�[2mms�[22m�[39m
 �[32m✓�[39m src/hooks/useLiveResource.test.tsx �[2m(�[22m�[2m18 tests�[22m�[2m)�[22m�[32m 99�[2mms�[22m�[39m
 �[32m✓�[39m src/pages/LoginPage.test.tsx �[2m(�[22m�[2m18 tests�[22m�[2m)�[22m�[33m 467�[2mms�[22m�[39m
 �[32m✓�[39m src/components/Dashboard.pushRefresh.test.tsx �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[33m 1688�[2mms�[22m�[39m
   �[32m✓�[39m Dashboard push-driven refreshes �[2m(10)�[22m
     �[33m�[2m✓�[22m�[39m removes a resumed task from attention on its progressed push�[33m 309�[2mms�[22m�[39m
     �[33m�[2m✓�[22m�[39m shows a plan issue that moved to review without waiting for a timer�[33m 383�[2mms�[22m�[39m
     �[33m�[2m✓�[22m�[39m regenerates the activity summary when a task stops for a human�[33m 356�[2mms�[22m�[39m
 �[32m✓�[39m src/api/proprApi.logout.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[33m 372�[2mms�[22m�[39m
�[90mstderr�[2m | src/contexts/NotificationCenterContext.test.tsx�[2m > �[22m�[2mNotificationCenterProvider�[2m > �[22m�[2mignores a previous account preference after identity changes
�[22m�[39mAn update to NotificationCenterProvider inside a test was not wrapped in act(...).

When testing, code that causes React state updates should be wrapped into act(...):

act(() => {
  /* fire events that update state */
});
/* assert on the output */

This ensures that you're testing the behavior the user would see in the browser. Learn more at https://react.dev/link/wrap-tests-with-act

 �[32m✓�[39m src/contexts/NotificationCenterContext.test.tsx �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[33m 306�[2mms�[22m�[39m
 �[32m✓�[39m src/pages/PlansPage.test.tsx �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[33m 628�[2mms�[22m�[39m
   �[32m✓�[39m PlansPage �[2m(6)�[22m
     �[33m�[2m✓�[22m�[39m renders repository filter counts and respects the repository query param�[33m 325�[2mms�[22m�[39m
 �[32m✓�[39m src/components/Dashboard.consistency.test.tsx �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[33m 713�[2mms�[22m�[39m
 �[32m✓�[39m src/components/TaskPlanner/PlanHistoryDialog.test.tsx �[2m(�[22m�[2m12 tests�[22m�[2m)�[22m�[33m 1501�[2mms�[22m�[39m
   �[32m✓�[39m PlanHistoryDialog �[2m(12)�[22m
     �[33m�[2m✓�[22m�[39m previews an earlier version and restores it�[33m 332�[2mms�[22m�[39m
 �[32m✓�[39m src/components/PreviewMedia.test.tsx �[2m(�[22m�[2m19 tests�[22m�[2m)�[22m�[33m 635�[2mms�[22m�[39m
�[90mstderr�[2m | src/components/TaskList.test.tsx�[2m > �[22m�[2mTaskList�[2m > �[22m�[2mshows loading until an initial empty read succeeds and never treats a failure as empty
�[22m�[39mError fetching tasks: Error: Tasks unavailable
    at �[90m/home/runner/work/propr/propr/propr-ui/�[39msrc/components/TaskList.test.tsx:196:50
    at /home/runner/work/propr/propr/node_modules/�[4m@testing-library/react�[24m/dist/act-compat.js:47:24
    at process.env.NODE_ENV.exports.act (/home/runner/work/propr/propr/node_modules/�[4mreact�[24m/cjs/react.development.js:814:22)
    at Proxy.<anonymous> (/home/runner/work/propr/propr/node_modules/�[4m@testing-library/react�[24m/dist/act-compat.js:46:25)
    at �[90m/home/runner/work/propr/propr/propr-ui/�[39msrc/components/TaskList.test.tsx:196:11
    at file:///home/runner/work/propr/propr/node_modules/�[4mvitest�[24m/dist/chunks/run.CQOUYP-x.js:2783:20

 �[32m✓�[39m src/components/TaskList.test.tsx �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[33m 539�[2mms�[22m�[39m
 �[32m✓�[39m src/api/proprApi.sharedReads.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 193�[2mms�[22m�[39m
 �[32m✓�[39m src/desktop/DesktopExperience.connect-prefill.test.tsx �[2m(�[22m�[2m26 tests�[22m�[2m)�[22m�[33m 2374�[2mms�[22m�[39m
   �[32m✓�[39m macos Add Instance Connect prefill �[2m(13)�[22m
     �[33m�[2m✓�[22m�[39m preserves the typed name and requires confirmation before probe, pairing, or persistence�[33m 357�[2mms�[22m�[39m
 �[32m✓�[39m src/voice/voiceCommands.test.ts �[2m(�[22m�[2m46 tests�[22m�[2m)�[22m�[32m 31�[2mms�[22m�[39m
 �[32m✓�[39m src/api/proprApi.status.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 25�[2mms�[22m�[39m
 �[32m✓�[39m src/hooks/shellLiveReads.test.tsx �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 212�[2mms�[22m�[39m
 �[32m✓�[39m src/voice/browserSpeech.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 17�[2mms�[22m�[39m
 �[32m✓�[39m src/pages/SettingsPage/AgentLoginModal.test.tsx �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[33m 802�[2mms�[22m�[39m
 �[32m✓�[39m src/hooks/usePlanRefinement.test.tsx �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 87�[2mms�[22m�[39m
 �[32m✓�[39m src/hooks/useHeaderStats.running.test.tsx �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 245�[2mms�[22m�[39m
 �[32m✓�[39m src/components/Inbox/NotificationActions.test.tsx �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[33m 312�[2mms�[22m�[39m
 �[32m✓�[39m src/components/Layout.logsGroup.test.tsx �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[33m 1050�[2mms�[22m�[39m
   �[32m✓�[39m Layout Logs navigation group �[2m(9)�[22m
     �[33m�[2m✓�[22m�[39m renders both log destinations inside one collapsible group�[33m 338�[2mms�[22m�[39m
 �[32m✓�[39m src/components/TaskPlanner/AuthenticatedAttachmentImage.test.tsx �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 199�[2mms�[22m�[39m
 �[32m✓�[39m src/components/RepositoryVisualPreviewControl.test.tsx �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[33m 372�[2mms�[22m�[39m
 �[32m✓�[39m src/pages/mcpLogsUtils.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 22�[2mms�[22m�[39m
 �[32m✓�[39m src/components/TaskList/TaskRows.desktop.test.tsx �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[33m 714�[2mms�[22m�[39m
   �[32m✓�[39m desktop task rows �[2m(5)�[22m
     �[33m�[2m✓�[22m�[39m retains named navigation and independent expansion on macos�[33m 399�[2mms�[22m�[39m
 �[32m✓�[39m src/components/TaskPlanner/AttachmentUploader.test.tsx �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 101�[2mms�[22m�[39m
 �[32m✓�[39m src/desktop/DesktopInstanceSelector.test.tsx �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 273�[2mms�[22m�[39m
 �[32m✓�[39m src/components/RepositoryIcon.test.tsx �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 50�[2mms�[22m�[39m
 �[32m✓�[39m src/components/TaskDetails/ActionBar.responsive.test.tsx �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[33m 445�[2mms�[22m�[39m
 �[32m✓�[39m src/components/Layout.test.tsx �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[33m 356�[2mms�[22m�[39m
   �[32m✓�[39m Layout sidebar counts �[2m(1)�[22m
     �[33m�[2m✓�[22m�[39m shows running goals separately from active tasks�[33m 351�[2mms�[22m�[39m
 �[32m✓�[39m src/utils/summaryBrowser.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 10�[2mms�[22m�[39m
 �[32m✓�[39m src/api/agentLoginApi.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 14�[2mms�[22m�[39m
 �[32m✓�[39m src/components/VisualPreviewGallery.test.tsx �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 295�[2mms�[22m�[39m
 �[32m✓�[39m src/api/summaryApi.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 12�[2mms�[22m�[39m
 �[32m✓�[39m src/components/ui/RepositoryChip.test.tsx �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 50�[2mms�[22m�[39m
 �[32m✓�[39m src/components/TaskList/lifecycleStatus.test.tsx �[2m(�[22m�[2m14 tests�[22m�[2m)�[22m�[33m 315�[2mms�[22m�[39m
 �[32m✓�[39m src/desktop/DesktopExperience.window-controls.test.tsx �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[33m 331�[2mms�[22m�[39m
   �[32m✓�[39m DesktopExperience Linux window controls �[2m(1)�[22m
     �[33m�[2m✓�[22m�[39m keeps native window actions outside the inert app and actionable while instance management is open�[33m 324�[2mms�[22m�[39m
 �[32m✓�[39m src/desktop.test.tsx �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
 �[32m✓�[39m src/components/GitHubAccountIdentity.test.tsx �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 55�[2mms�[22m�[39m
 �[32m✓�[39m src/components/Repositories/ModelContextSelector.test.tsx �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 205�[2mms�[22m�[39m
 �[32m✓�[39m src/components/taskStatusBreakdown.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 14�[2mms�[22m�[39m
 �[32m✓�[39m src/api/revertApi.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 11�[2mms�[22m�[39m
 �[32m✓�[39m src/pages/SettingsPage/modelSelectionHelpers.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m47 passed�[39m�[22m�[90m (47)�[39m
�[2m      Tests �[22m �[1m�[32m449 passed�[39m�[22m�[90m (449)�[39m
�[2m   Start at �[22m 08:38:22
�[2m   Duration �[22m 45.85s�[2m (environment 46%, tests 29%, import 10%, setup 9%, transform 5%)�[22m

�[2mEnvironment �[22m �[33mjsdom was created 47 times�[39m�[2m · 39.28s total, 46% of tracked time�[22m
�[2m            �[22m �[2mcreate it once per worker with �[22m�[33mpool: 'vmThreads'�[39m�[2m (keeps per-file isolation) or �[22m�[33misolate: false�[39m�[2m (shares it across files)�[22m
�[2m            �[22m �[2mlearn more: https://vitest.dev/guide/improving-performance#test-environments�[22m


> propr-ui@0.0.1 posttest
> npm run test:docker-context


> propr-ui@0.0.1 test:docker-context
> node --test scripts/docker-context-inputs.test.mjs

TAP version 13
# Subtest: focused UI selectors are forwarded only to Vitest
ok 1 - focused UI selectors are forwarded only to Vitest
  ---
  duration_ms: 1.080793
  type: 'test'
  ...
# Subtest: the UI Docker context contains its complete non-type external source import closure
ok 2 - the UI Docker context contains its complete non-type external source import closure
  ---
  duration_ms: 54.435165
  type: 'test'
  ...
1..2
# tests 2
# suites 0
# pass 2
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 125.701731
[150/150] passed propr-ui#4/4 (workspace test script) in 46.7s

### Shard 2/4: 149/150 passed in 346.2s

Assigned 150 of 598 discovered units.

| Duration | Status | Unit |
| ---: | --- | --- |
| 46.7s | passed | `propr-ui#4/4` (workspace) |
| 30.0s | passed | `apps/desktop/src/profile-store.crash-recovery.test.ts` |
| 12.9s | passed | `test/connectCliIntegration.test.ts` |
| 11.3s | passed | `apps/desktop/src/saved-accounts.test.ts` |
| 10.2s | passed | `packages/cli/src/projectOptions.cli.test.ts` |
| 8.0s | passed | `packages/core/test/eventPublisherBounds.test.ts` |
| 7.7s | passed | `test/worktreeLifecycle.integration.test.ts` |
| 7.1s | passed | `packages/api/test/mcpAccessLogDispatch.test.ts` |
| 6.4s | passed | `apps/desktop/scripts/desktop-native-menu.test.mjs` |
| 6.1s | passed | `apps/desktop/src/credential-service.test.ts` |
| 5.2s | passed | `packages/api/test/mcpIntegration.test.ts` |
| 4.9s | passed | `packages/api/test/notificationProjectionPublish.test.ts` |
| 4.8s | passed | `apps/desktop/scripts/macos-window-chrome.test.mjs` |
| 4.5s | passed | `test/partialExecution.test.ts` |
| 4.4s | passed | `packages/api/test/notificationBackgroundService.test.ts` |


1/150 test runs failed in shard 2/4 after 346.2s:
- test/commentEventHandler.switch-use.test.ts: exit 1

Details truncated; see the uploaded artifacts for complete failure rows and logs.

View Workflow
View uploaded artifacts

Fixed the Shard 2 CI failure.

- Root cause: stale test expectations still resolved bare `sonnet` to Sonnet 5 instead of Sonnet 5.5.
- Updated three assertions and centralized the canonical Sonnet test value in [commentEventHandler.switch-use.test.ts](/tmp/git-processor/worktrees/integry/propr/pr-2619-followup-2026-09-29T08-39-27/test/commentEventHandler.switch-use.test.ts:235).
- The Node.js 20 deprecation notice was unrelated to the failure.
- Verification: repository CI harness passed both affected suites, `2/2` files and all assertions.
- `git diff --check` passed.

No visual preview was created because this is test-only and not user-visible.

PR: #2619
Comment by: @propr-dev[bot] (ID: 5886704736)
Model: gpt-5.6-sol
@propr-dev

propr-dev Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor Author

ℹ️ Analyzed the follow-up request by @propr-dev[bot], @github-actions[bot]

Analysis Summary

Fixed the Shard 2 failure in commentEventHandler.switch-use.test.ts.

Root cause: three assertions still expected the old claude-sonnet-5 alias target. They now use the canonical claude-sonnet-5-5 value.

Validation:

  • Repository suite runner: 2/2 affected files passed
  • Focused test: 63/63 passed
  • Related model, pricing, and context tests: 38/38 passed
  • git diff --check: passed

The Node.js 20 deprecation notice was unrelated. No visual preview was needed because this is test-only.

No code changes were necessary based on the current state of the branch.


🤖 Analysis Details

  • Model: GPT-5.6 Sol (high)
  • Time: 2m 26s
  • Tokens: 466,879 (464,100 in / 2,779 out)
  • Cost: $0.46

View Task Execution


💡 ProPR Slash Commands
Command Description Example
/merge Merge target branch into this PR and resolve conflicts /merge
/review Request an AI code review /review or /review claude-sonnet
/fix Implement fixes for issues found by /review /fix or /fix address the null check issue
/switch Change the AI model for this PR /switch claude-opus
/use Override the model for a single follow-up run /use claude-sonnet
/ultrafix Loop review→fix cycles until score goal is met /ultrafix or /ultrafix goal=8 max=10

🤖 Generated by ProPR
Processing comment IDs: 5886722686✓, 5886723564✓

@integry

integry commented Sep 29, 2026

Copy link
Copy Markdown
Owner

/review

@propr-dev

propr-dev Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor Author

✅ AI Code Review Complete requested by @integry

Posted 1 review:

View Task Details

@propr-dev

propr-dev Bot commented Sep 29, 2026

Copy link
Copy Markdown
Contributor Author

🔍 AI Code Review — codex:gpt-6-astra

Overall Evaluation

Ready to merge within scope. The PR adds Sonnet 5.5, makes it the canonical Sonnet target, and moves older Sonnet models into the existing legacy fold.

✅ Compatible alias promotion — sonnet and claude-sonnet resolve to Sonnet 5.5 while explicit Sonnet 5 aliases remain unchanged.

✅ Consistent runtime configuration — The catalog’s minimum version, agent defaults, Docker build arguments, and locked Claude Code dependency consistently use 2.1.284.

✅ Focused regression coverage — Tests cover alias resolution, migration inclusion, pricing lookup, review context capacity, recommendations, and legacy-model visibility.

This assessment uses static review of the supplied code. The authoritative current-head checks report 30 passed, zero failed, and zero pending; the historical shard failure is superseded.

Merge blockers

No merge blockers.

Suggestions

These are optional follow-ups and are not sent to /fix.

No suggestions.

Score

The changes satisfy the stated objective with consistent configuration and focused tests. No merge-blocking regression was identified in the supplied diff and surrounding context.

Score: 9/10


🤖 Review Details

  • Model: GPT-6 Astra
  • Time: 18s
  • Tokens: 56,842 (56,513 in / 329 out)
  • Cost: $0.48

View Task


💡 Next step: Comment /fix to address every F# merge blocker, or name records explicitly, as in /fix F3 S5.
F# and S# IDs increment across review comments and remain permanent, so selectors such as /fix F3 F5 stay unambiguous across cycles. S# suggestions stay optional: they are implemented only when you name them, and they never relax a merge blocker.

🤖 Review by ProPR

@integry
integry merged commit 7f3482e into main Sep 29, 2026
44 checks passed
@integry
integry deleted the 2616/gpt-5.6-sol-add-support-to-claude-son-20260929-0822-ilv branch September 29, 2026 11:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add support to Claude Sonnet 5.5 model, make it the canonical Sonnet model and retire the older Sonn

1 participant