Skip to content

refactor+test+docs: multi-perspective improvements (QA, Developer, New Contributor)#150

Merged
patchloom-release[bot] merged 2 commits into
mainfrom
fix/multi-perspective-improvements-20260622
Jun 22, 2026
Merged

refactor+test+docs: multi-perspective improvements (QA, Developer, New Contributor)#150
patchloom-release[bot] merged 2 commits into
mainfrom
fix/multi-perspective-improvements-20260622

Conversation

@SebTardif

Copy link
Copy Markdown
Contributor

Initial cycle of /multi-perspective-improve.

Gate

Changes

All via

patchloom@0.0.4 check
npm run test && npm run test:coverage && npm run package

patchloom@0.0.4 test
npm run compile && npm run compile-tests && npm run test:unit

patchloom@0.0.4 compile
tsc -p ./

patchloom@0.0.4 compile-tests
tsc -p ./tsconfig.test.json

patchloom@0.0.4 test:unit
node --test ./out-test/test/unit/*.test.js

✔ buildBatchTemplate returns line-oriented format with four operations (1.021958ms)
✔ buildBatchTemplate ends with a newline (0.132708ms)
✔ parseBatchOperationCount counts non-empty lines (0.109375ms)
✔ parseBatchOperationCount returns 0 for empty input (0.053791ms)
✔ parseBatchOperationCount returns 0 for whitespace-only input (0.071834ms)
✔ parseBatchOperationCount ignores blank lines between operations (0.110917ms)
✔ parseBatchOperationCount counts a single operation (0.067167ms)
✔ buildBatchTemplate replace line has file and quoted arguments (0.1625ms)
✔ buildBatchTemplate doc.set line has file, selector, and quoted value (0.106416ms)
✔ buildBatchTemplate tidy.fix line has a file path (0.124917ms)
✔ buildBatchTemplate file.append line has file and quoted content (0.103917ms)
✔ resolvePatchloomStatusWithInputs prefers patchloom.path over PATH (1.391583ms)
✔ resolvePatchloomStatusWithInputs reports missing binary cleanly (0.211625ms)
✔ resolvePatchloomStatusWithInputs reports version execution failures (0.214417ms)
✔ findOnPath respects win32 PATH separators and command names (0.279583ms)
✔ parsePatchloomVersion extracts semantic versions from --version output (0.119375ms)
✔ comparePatchloomVersions follows semantic version ordering (0.108625ms)
✔ assessPatchloomCompatibility flags outdated CLI builds (0.085042ms)
✔ resolvePatchloomStatusWithInputs exposes compatibility diagnostics (0.101041ms)
✔ defaultWorkspaceFolderIndex prefers active folders and only auto-selects single roots (0.101458ms)
✔ defaultWorkspaceFolderIndex ignores out-of-range active indices (0.090208ms)
✔ describeWorkspaceEnvironment reports local environment for undefined remoteName (0.080083ms)
✔ describeWorkspaceEnvironment reports limited remote support (0.062792ms)
✔ describeWorkspaceEnvironment reports limited support for ssh-remote (0.592916ms)
✔ describeWorkspaceEnvironment reports limited support for dev-container (0.071792ms)
✔ describeWorkspaceEnvironment reports limited support for codespaces (0.046959ms)
✔ describeWorkspaceEnvironment reports unverified for unknown remote names (0.106833ms)
✔ resolveMcpTargets omits user config targets when disabled (0.789333ms)
✔ detectManagedInstallTarget maps supported platforms to release targets (0.088542ms)
✔ resolveManagedInstallPaths uses cargo-dist style archive names (0.082625ms)
✔ buildManagedInstallReleaseAssets builds archive and checksum urls with patchloom-v tag (0.140625ms)
✔ parseManagedInstallChecksumFile accepts common sha256 sidecar formats (0.180083ms)
✔ resolveManagedInstallChecksum returns the matching archive checksum (0.0755ms)
✔ verifyManagedInstallArchiveChecksum validates archive content against the checksum sidecar (0.314709ms)
✔ verifyManagedInstallArchiveChecksum rejects mismatched archive content (0.264583ms)
✔ parseManagedInstallChecksumFile rejects invalid lines (0.053083ms)
✔ assertTrustedManagedInstallDownloadUrl only accepts GitHub release download URLs (0.224125ms)
✔ managed install constants use a stable storage directory name (0.023958ms)
✔ resolveManagedInstallTransactionPaths keeps staged files separate from the live binary (0.090708ms)
✔ inspectManagedInstallStatus includes the last managed install failure for diagnostics (0.14575ms)
✔ clearManagedInstallStaging removes the entire staging directory (0.072416ms)
✔ promoteManagedInstallBinary replaces the live binary and clears stale backups (0.213541ms)
✔ promoteManagedInstallBinary restores the previous binary when replacement fails (0.262833ms)
✔ inspectManagedInstallStatus reports discovered managed binaries (0.076084ms)
✔ loadManagedInstallFailure reads persisted failure diagnostics from storage (0.073084ms)
✔ persistManagedInstallFailure and clearManagedInstallFailureRecord update the failure record file (0.092958ms)
✔ resolvePatchloomStatusWithInputs surfaces persisted managed install failures after reload (9.589292ms)
✔ normalizeReleaseVersion strips v and patchloom-v prefixes (0.125292ms)
✔ buildManagedInstallReleaseAssets normalizes patchloom-v prefixed versions (0.075917ms)
✔ resolvePatchloomStatusWithInputs falls back to a managed install when present (0.61525ms)
✔ configuredBinaryPathFromSetting trims whitespace and returns undefined for empty values (0.094708ms)
✔ describePatchloomSource maps all source types to labels (0.042041ms)
✔ describePatchloomCompatibility maps all compatibility levels to labels (0.042541ms)
✔ patchloomNeedsUpgrade returns true only for unsupported compatibility (0.036959ms)
✔ isTrustedManagedInstallDownloadUrl accepts valid GitHub release URLs (0.066083ms)
✔ isTrustedManagedInstallDownloadUrl rejects protocol-relative and non-HTTPS URLs (0.051916ms)
✔ isTrustedManagedInstallDownloadUrl handles query strings, fragments, and encoded paths (0.030458ms)
✔ isTrustedManagedInstallDownloadUrl rejects non-GitHub hosts (0.071583ms)
✔ isTrustedManagedInstallDownloadUrl rejects wrong repo path (0.030042ms)
✔ isTrustedManagedInstallDownloadUrl rejects malformed URLs (0.053834ms)
✔ isTrustedManagedInstallDownloadUrl respects custom repo parameter (0.039041ms)
✔ resolvePatchloomStatusWithInputs skips PATH and setting in untrusted workspaces (2.428167ms)
✔ resolvePatchloomStatusWithInputs reports restricted message when untrusted and no managed install (0.125084ms)
✔ resolvePatchloomStatusWithInputs allows setting and PATH in trusted workspaces (0.05675ms)
✔ findOnPath discovers a real executable in a temp directory (5.973417ms)
✔ findOnPath skips non-executable files (1.955708ms)
✔ findOnPath searches multiple PATH directories in order (3.777083ms)
✔ findOnPath returns undefined for empty PATH (0.151333ms)
✔ findOnPath deduplicates PATH entries (1.693166ms)
✔ resolvePatchloomStatusWithInputs discovers a real executable via PATH (2.079958ms)
✔ resolvePatchloomStatusWithInputs reports configured path that does not exist (0.69725ms)
✔ parsePatchloomVersion handles edge cases (0.158375ms)
✔ comparePatchloomVersions handles major, minor, and patch differences (0.097958ms)
✔ comparePatchloomVersions compares prerelease identifiers correctly (6.23725ms)
✔ comparePatchloomVersions ignores build metadata per SemVer 2.0 (0.096875ms)
✔ comparePatchloomVersions handles long prerelease chains (0.05925ms)
✔ assessPatchloomCompatibility correctly identifies supported versions (0.057334ms)
▶ downloadToFile with createDownloader over HTTP
✔ downloads content to the destination file (13.78025ms)
✔ follows redirects and delivers final content (3.734416ms)
✔ rejects after too many redirects (5.497125ms)
✔ rejects on HTTP error status (1.242167ms)
✔ creates parent directories for the destination (2.552834ms)
✔ downloadToFile with createDownloader over HTTP (27.367584ms)
▶ streamingSha256
✔ computes the same hash as the in-memory calculateSha256Hex (3.220375ms)
✔ produces correct SHA-256 for known input (1.171ms)
✔ handles empty files (1.011375ms)
✔ streamingSha256 (5.648042ms)
▶ performManagedInstall staging cleanup
✔ cleans up staging directory after download failure (2.632916ms)
✔ performManagedInstall staging cleanup (2.743958ms)
✔ formatError extracts message from Error instances (0.866792ms)
✔ formatError converts non-Error values to strings (0.073125ms)
✔ formatError falls back to String for Error with empty message (0.061667ms)
✔ formatCliOutput merges stderr and stdout into a single line (0.124958ms)
✔ formatCliOutput returns exit code when both streams are empty (0.07175ms)
✔ formatCliOutput normalizes CRLF line endings (0.063667ms)
✔ classifyAgentsFile returns missing when AGENTS.md does not exist (0.058916ms)
✔ classifyAgentsFile treats CRLF and trailing newline differences as up to date (0.050875ms)
✔ classifyAgentsFile detects real content drift (0.058042ms)
✔ buildStatusDetails includes workspace readiness context (0.262875ms)
✔ preferredStatusAction points missing binary users to settings (0.821ms)
✔ preferredStatusAction suggests install when binary missing with managed install available (0.073875ms)
✔ buildStatusDetails includes compatibility upgrade guidance (0.111792ms)
✔ buildStatusDetails surfaces managed install failure diagnostics (0.066833ms)
✔ preferredStatusAction points outdated CLI users to releases (0.046791ms)
✔ preferredStatusAction points ready workspaces without AGENTS to initialization (0.039125ms)
✔ preferredStatusAction points ready workspaces without MCP config to MCP setup (0.038917ms)
✔ preferredStatusAction returns nothing when workspace is already ready (0.038ms)
✔ preferredStatusAction returns nothing when workspace readiness is undefined (0.029875ms)
✔ buildPatchloomMcpEntry points at patchloom mcp-server (0.053333ms)
✔ inspectMcpTargets reports configured targets (0.918292ms)
✔ configureMcpTargets creates or updates only the selected target kinds (0.342666ms)
✔ generateAgentRules logs error to output channel on CLI failure (3.070667ms)
✔ promoteManagedInstallBinary moves a staged binary to the live path with real files (10.888791ms)
✔ promoteManagedInstallBinary replaces an existing binary and removes the backup (4.374583ms)
✔ promoteManagedInstallBinary rolls back on rename failure with real files (5.590875ms)
✔ clearManagedInstallStaging removes a real staging directory (2.640917ms)
✔ persistManagedInstallFailure and loadManagedInstallFailure round-trip through real files (2.823417ms)
✔ clearManagedInstallFailureRecord removes the failure file on disk (1.729166ms)
✔ inspectManagedInstallStatus detects a real binary on disk (1.417417ms)
✔ inspectManagedInstallStatus reports missing binary when file does not exist (0.554708ms)
✔ inspectManagedInstallStatus loads persisted failure from disk (1.502417ms)
✔ promoteManagedInstallBinary clears persisted failure on disk after success (2.920917ms)
✔ loadManagedInstallFailure returns undefined for corrupted JSON on disk (1.232709ms)
✔ loadManagedInstallFailure returns undefined for valid JSON with wrong shape (1.063167ms)
✔ fetchLatestReleaseVersion extracts version from GitHub API response (0.182708ms)
✔ fetchLatestReleaseVersion strips leading v from tag (0.06475ms)
✔ fetchLatestReleaseVersion throws on missing tag_name (0.048167ms)
✔ fetchLatestReleaseVersion throws on API failure (0.115667ms)
✔ extractManagedInstallArchive invokes tar with correct arguments for tar.xz (0.154541ms)
✔ extractManagedInstallArchive invokes tar for zip format on Windows (0.057416ms)
✔ performManagedInstall runs full pipeline with injected I/O (7.01625ms)
✔ performManagedInstall persists failure on checksum mismatch (2.095791ms)
✔ performManagedInstall throws for unsupported platform (0.092708ms)
✔ performManagedInstall fetches latest version when none specified (2.486209ms)
✔ configureMcpTargets writes VS Code mcp.json to a real temp workspace (9.551625ms)
✔ configureMcpTargets preserves existing servers in the config file (2.89925ms)
✔ configureMcpTargets creates both vscode and cursor configs (3.601583ms)
✔ inspectMcpTargets reads configured status from real files (2.524709ms)
✔ configureMcpTargets is idempotent on second call (2.221917ms)
✔ configureMcpTargets handles invalid JSON in existing file gracefully (2.765083ms)
✔ configureMcpTargets writes windsurf config with mcpServers key (2.275375ms)
✔ resolveMcpTargets omits workspace targets when no workspace is provided (0.138834ms)
✔ configureMcpTargets handles empty config file (2.385917ms)
✔ createPatchloomLog lazily creates channel on first log call (2.0175ms)
✔ logCommand appends command with arguments and cwd (0.130333ms)
✔ logResult appends stdout, stderr, and exit code (0.279708ms)
✔ logResult omits empty stdout and stderr (0.10575ms)
✔ show calls channel.show with preserveFocus (0.089125ms)
✔ dispose disposes channel and subsequent log creates a new one (0.087917ms)
✔ setPatchloomLog and getPatchloomLog round-trip module state (0.0715ms)
✔ logResult omits whitespace-only stdout and stderr (0.081666ms)
✔ logResult splits Windows-style CRLF line endings (0.10575ms)
✔ logResult handles multiline stderr (0.700083ms)
▶ patchloom CLI integration
✔ --version returns parseable version string (7.78675ms)
✔ --version output passes compatibility assessment (3.057916ms)
✔ resolvePatchloomStatusWithInputs discovers the real binary (2.687333ms)
✔ agent-rules produces markdown output (3.5975ms)
✔ doc set modifies a JSON file by selector (6.531667ms)
✔ doc set preserves YAML comments (6.293625ms)
✔ replace performs text substitution in a file (32.654ms)
✔ tidy fix ensures final newline (8.648375ms)
✔ search finds text across files (5.583042ms)
✔ doc get reads a value by selector (3.511709ms)
✔ batch applies multiple operations via stdin (7.301666ms)
✔ create makes a new file (3.574125ms)
✔ exit code 3 for search with no matches (6.028666ms)
✔ exit code 2 for replace --check with pending changes (4.654125ms)
✔ exit code 0 for tidy check on a clean file (5.840708ms)
✔ exit code 2 for tidy check on a file needing fixes (5.062333ms)
✔ agent-rules output classified as up_to_date after write (3.13475ms)
✔ agent-rules output classified as different after modification (2.687541ms)
✔ quick action preview flow: copy, apply to copy, compare (7.593459ms)
✔ buildStatusDetails renders real binary status correctly (2.522375ms)
✔ preferredStatusAction suggests Initialize Project for real ready status (2.288334ms)
✔ mcp-server starts and responds to JSON-RPC initialize (103.523833ms)
✔ doc delete removes a key from a JSON file (6.025ms)
✔ doc merge adds keys to a JSON file (4.392708ms)
✔ doc append adds an item to a JSON array (5.003791ms)
✔ md upsert-bullet adds a bullet under a heading (4.574041ms)
✔ md table-append adds a row to a markdown table (4.38475ms)
✔ undo restores files after an apply (11.644959ms)
✔ MCP config written for real binary is structurally valid (1.151292ms)
✔ patchloom CLI integration (272.991459ms)
▶ managed install end-to-end MCP
✔ managed install produces a runnable binary (310.735208ms)
✔ MCP server responds to initialize (100.954417ms)
✔ MCP server lists available tools (203.110875ms)
✔ MCP tools/call modifies a file on disk (204.877458ms)
✔ cleanup managed install temp directory (1.176291ms)
✔ managed install end-to-end MCP (821.095208ms)
▶ parsePatchloomVersion property-based tests
✔ never throws on arbitrary input (4.066541ms)
✔ always extracts the version from a well-formed semver string (0.62175ms)
✔ strips the leading v prefix from parsed versions (0.431625ms)
✔ parsePatchloomVersion property-based tests (5.940625ms)
▶ comparePatchloomVersions property-based tests
✔ is reflexive: compare(a, a) === 0 (0.64525ms)
✔ is antisymmetric: sign(compare(a, b)) === -sign(compare(b, a)) (0.647333ms)
✔ respects numeric ordering for major versions (0.453709ms)
✔ comparePatchloomVersions property-based tests (1.882542ms)
▶ formatError property-based tests
✔ never throws on arbitrary input (5.246041ms)
✔ returns the message for Error instances with non-empty messages (0.718417ms)
✔ formatError property-based tests (6.135583ms)
▶ formatCliOutput property-based tests
✔ always returns a non-empty string (1.198167ms)
✔ includes exit code when both streams are whitespace-only (0.374542ms)
✔ formatCliOutput property-based tests (1.737ms)
▶ parseManagedInstallChecksumFile property-based tests
✔ returns an array or throws a verification error on arbitrary input (0.935292ms)
✔ parses well-formed checksum lines into entries (8.015875ms)
✔ returns empty array for blank input (0.674166ms)
✔ parseManagedInstallChecksumFile property-based tests (9.746333ms)
✔ buildReplaceQuickAction builds a replace command for one file (2.149708ms)
✔ buildTidyQuickAction includes selected tidy flags (0.130208ms)
✔ buildDocSetQuickAction builds a doc set command (0.094542ms)
✔ retargetQuickAction swaps only the target path arguments (0.088541ms)
✔ withApplyFlag appends apply once (0.072167ms)
✔ isStructuredDocumentPath recognizes supported structured formats (0.115167ms)
✔ isStructuredDocumentPath handles uppercase extensions (0.077292ms)
✔ isStructuredDocumentPath rejects files without extensions (0.046125ms)
✔ isStructuredDocumentPath rejects dotfiles without basenames (0.069583ms)
✔ buildTidyQuickAction with a single fix omits unselected flags (0.106958ms)
✔ buildSearchQuickAction builds a search command without glob (0.69375ms)
✔ buildSearchQuickAction includes glob when provided (0.066917ms)
✔ buildCreateQuickAction builds a create command (0.052458ms)
✔ buildSearchQuickAction preserves spaces in pattern as a single arg (0.054125ms)
✔ buildDocGetQuickAction builds a doc get command (0.04975ms)
✔ resolveWorkspaceRelativePath accepts path inside workspace (0.096959ms)
✔ resolveWorkspaceRelativePath accepts nested subdirectory (0.030584ms)
✔ resolveWorkspaceRelativePath rejects traversal with .. (0.2235ms)
✔ resolveWorkspaceRelativePath rejects absolute path outside workspace (0.053875ms)
✔ resolveWorkspaceRelativePath rejects workspace root itself (0.04675ms)
✔ buildSearchQuickAction with empty pattern produces valid args (0.030333ms)
✔ buildSearchQuickAction with regex special characters (0.026792ms)
✔ buildCreateQuickAction with spaces in path (0.0295ms)
✔ buildDocGetQuickAction with deeply nested selector (0.028375ms)
✔ buildCreateQuickAction with unicode filename (0.028459ms)
✔ buildSearchQuickAction with unicode pattern (0.023667ms)
✔ buildDocDeleteQuickAction builds a doc delete command (0.040875ms)
✔ buildDocMergeQuickAction builds a doc merge command (0.032833ms)
✔ buildDocAppendQuickAction builds a doc append command (0.035875ms)
✔ buildMdTableAppendQuickAction builds a md table-append command (0.036125ms)
✔ buildMdUpsertBulletQuickAction builds a md upsert-bullet command (0.043667ms)
✔ buildMdReplaceSectionQuickAction builds a md replace-section command (0.036958ms)
✔ buildUndoQuickAction builds an undo command (0.040875ms)
✔ buildDocPrependQuickAction builds a doc prepend command (0.041ms)
✔ buildDocEnsureQuickAction builds a doc ensure command (0.041209ms)
✔ buildDocMoveQuickAction builds a doc move command (0.04825ms)
✔ buildMdInsertAfterHeadingQuickAction builds a md insert-after-heading command (0.051958ms)
✔ buildMdInsertBeforeHeadingQuickAction builds a md insert-before-heading command (0.042208ms)
✔ retargetQuickAction works with doc move command (0.030541ms)
✔ retargetQuickAction works with md insert-after-heading command (0.026125ms)
✔ isMarkdownPath recognizes markdown extensions (0.044542ms)
✔ isMarkdownPath handles uppercase extensions (0.025583ms)
✔ retargetQuickAction works with md commands (0.036125ms)
✔ buildPatchMergeQuickAction builds a patch merge command (0.038708ms)
✔ buildPatchMergeQuickAction includes allow-conflicts flag when enabled (0.032ms)
✔ retargetQuickAction works with patch merge command (0.045417ms)
✔ buildAppendQuickAction builds an append command (0.052334ms)
✔ parseInitializeResponse extracts server info from valid response (0.959584ms)
✔ parseInitializeResponse handles response without serverInfo (0.121ms)
✔ parseInitializeResponse detects JSON-RPC error response (0.069ms)
✔ parseInitializeResponse returns undefined for empty string (0.048792ms)
✔ parseInitializeResponse returns undefined for non-JSON lines (0.068375ms)
✔ parseInitializeResponse skips non-jsonrpc lines (0.062084ms)
✔ parseInitializeResponse handles multi-line output with blank lines (0.074958ms)
✔ verifyMcpServer returns success from injected spawn (0.202833ms)
✔ verifyMcpServer returns failure from injected spawn (0.137125ms)
✔ verifyMcpServer catches thrown errors from spawn (0.294042ms)
✔ verifyMcpServer catches non-Error thrown values (0.172167ms)
✔ buildStatusDetails shows per-editor MCP breakdown (0.296375ms)
✔ buildStatusDetails shows fallback when mcpTargets is undefined (0.11675ms)
✔ buildStatusDetails shows checkmark for configured targets (0.105458ms)
✔ buildStatusDetails shows X for unconfigured targets (0.081833ms)
ℹ tests 259
ℹ suites 10
ℹ pass 259
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 31139.790917

patchloom@0.0.4 test:coverage
node --test --experimental-test-coverage --test-coverage-lines=80 --test-coverage-exclude='out-test/src/extension*' --test-coverage-exclude='out-test/src/commands/showStatus*' --test-coverage-exclude='out-test/src/commands/configureMcp*' --test-coverage-exclude='out-test/src/commands/setupWorkspace*' --test-coverage-exclude='out-test/src/commands/batchApply*' --test-coverage-exclude='out-test/src/commands/quickActions*' --test-coverage-exclude='out-test/src/status/statusBar*' --test-coverage-exclude='out-test/test/unit/patchloomCli*' ./out-test/test/unit/*.test.js

✔ buildBatchTemplate returns line-oriented format with four operations (1.022083ms)
✔ buildBatchTemplate ends with a newline (0.064333ms)
✔ parseBatchOperationCount counts non-empty lines (0.064292ms)
✔ parseBatchOperationCount returns 0 for empty input (0.038917ms)
✔ parseBatchOperationCount returns 0 for whitespace-only input (0.074ms)
✔ parseBatchOperationCount ignores blank lines between operations (0.0705ms)
✔ parseBatchOperationCount counts a single operation (0.060959ms)
✔ buildBatchTemplate replace line has file and quoted arguments (0.131875ms)
✔ buildBatchTemplate doc.set line has file, selector, and quoted value (0.087959ms)
✔ buildBatchTemplate tidy.fix line has a file path (0.053083ms)
✔ buildBatchTemplate file.append line has file and quoted content (0.499917ms)
✔ resolvePatchloomStatusWithInputs prefers patchloom.path over PATH (1.599292ms)
✔ resolvePatchloomStatusWithInputs reports missing binary cleanly (0.252791ms)
✔ resolvePatchloomStatusWithInputs reports version execution failures (0.232458ms)
✔ findOnPath respects win32 PATH separators and command names (0.32875ms)
✔ parsePatchloomVersion extracts semantic versions from --version output (0.115042ms)
✔ comparePatchloomVersions follows semantic version ordering (0.101917ms)
✔ assessPatchloomCompatibility flags outdated CLI builds (0.07625ms)
✔ resolvePatchloomStatusWithInputs exposes compatibility diagnostics (0.097625ms)
✔ defaultWorkspaceFolderIndex prefers active folders and only auto-selects single roots (0.075375ms)
✔ defaultWorkspaceFolderIndex ignores out-of-range active indices (0.04325ms)
✔ describeWorkspaceEnvironment reports local environment for undefined remoteName (0.068917ms)
✔ describeWorkspaceEnvironment reports limited remote support (0.053208ms)
✔ describeWorkspaceEnvironment reports limited support for ssh-remote (0.036917ms)
✔ describeWorkspaceEnvironment reports limited support for dev-container (0.035875ms)
✔ describeWorkspaceEnvironment reports limited support for codespaces (0.0345ms)
✔ describeWorkspaceEnvironment reports unverified for unknown remote names (0.045375ms)
✔ resolveMcpTargets omits user config targets when disabled (0.844334ms)
✔ detectManagedInstallTarget maps supported platforms to release targets (0.11225ms)
✔ resolveManagedInstallPaths uses cargo-dist style archive names (0.106917ms)
✔ buildManagedInstallReleaseAssets builds archive and checksum urls with patchloom-v tag (0.145834ms)
✔ parseManagedInstallChecksumFile accepts common sha256 sidecar formats (0.200375ms)
✔ resolveManagedInstallChecksum returns the matching archive checksum (0.072417ms)
✔ verifyManagedInstallArchiveChecksum validates archive content against the checksum sidecar (0.401958ms)
✔ verifyManagedInstallArchiveChecksum rejects mismatched archive content (0.265333ms)
✔ parseManagedInstallChecksumFile rejects invalid lines (0.067542ms)
✔ assertTrustedManagedInstallDownloadUrl only accepts GitHub release download URLs (0.14525ms)
✔ managed install constants use a stable storage directory name (0.03325ms)
✔ resolveManagedInstallTransactionPaths keeps staged files separate from the live binary (0.124583ms)
✔ inspectManagedInstallStatus includes the last managed install failure for diagnostics (0.184834ms)
✔ clearManagedInstallStaging removes the entire staging directory (0.109208ms)
✔ promoteManagedInstallBinary replaces the live binary and clears stale backups (0.292ms)
✔ promoteManagedInstallBinary restores the previous binary when replacement fails (0.361375ms)
✔ inspectManagedInstallStatus reports discovered managed binaries (0.074166ms)
✔ loadManagedInstallFailure reads persisted failure diagnostics from storage (0.090041ms)
✔ persistManagedInstallFailure and clearManagedInstallFailureRecord update the failure record file (0.098417ms)
✔ resolvePatchloomStatusWithInputs surfaces persisted managed install failures after reload (11.760042ms)
✔ normalizeReleaseVersion strips v and patchloom-v prefixes (0.12875ms)
✔ buildManagedInstallReleaseAssets normalizes patchloom-v prefixed versions (0.157041ms)
✔ resolvePatchloomStatusWithInputs falls back to a managed install when present (2.3545ms)
✔ configuredBinaryPathFromSetting trims whitespace and returns undefined for empty values (0.126084ms)
✔ describePatchloomSource maps all source types to labels (0.035ms)
✔ describePatchloomCompatibility maps all compatibility levels to labels (0.042917ms)
✔ patchloomNeedsUpgrade returns true only for unsupported compatibility (0.036916ms)
✔ isTrustedManagedInstallDownloadUrl accepts valid GitHub release URLs (0.042583ms)
✔ isTrustedManagedInstallDownloadUrl rejects protocol-relative and non-HTTPS URLs (0.039667ms)
✔ isTrustedManagedInstallDownloadUrl handles query strings, fragments, and encoded paths (0.026792ms)
✔ isTrustedManagedInstallDownloadUrl rejects non-GitHub hosts (0.023083ms)
✔ isTrustedManagedInstallDownloadUrl rejects wrong repo path (0.021417ms)
✔ isTrustedManagedInstallDownloadUrl rejects malformed URLs (0.084958ms)
✔ isTrustedManagedInstallDownloadUrl respects custom repo parameter (0.09825ms)
✔ resolvePatchloomStatusWithInputs skips PATH and setting in untrusted workspaces (1.677583ms)
✔ resolvePatchloomStatusWithInputs reports restricted message when untrusted and no managed install (0.095125ms)
✔ resolvePatchloomStatusWithInputs allows setting and PATH in trusted workspaces (0.065166ms)
✔ findOnPath discovers a real executable in a temp directory (6.501125ms)
✔ findOnPath skips non-executable files (1.9015ms)
✔ findOnPath searches multiple PATH directories in order (3.388083ms)
✔ findOnPath returns undefined for empty PATH (0.135875ms)
✔ findOnPath deduplicates PATH entries (1.721917ms)
✔ resolvePatchloomStatusWithInputs discovers a real executable via PATH (2.197875ms)
✔ resolvePatchloomStatusWithInputs reports configured path that does not exist (0.67875ms)
✔ parsePatchloomVersion handles edge cases (0.260417ms)
✔ comparePatchloomVersions handles major, minor, and patch differences (0.141625ms)
✔ comparePatchloomVersions compares prerelease identifiers correctly (5.924458ms)
✔ comparePatchloomVersions ignores build metadata per SemVer 2.0 (0.082375ms)
✔ comparePatchloomVersions handles long prerelease chains (0.064833ms)
✔ assessPatchloomCompatibility correctly identifies supported versions (0.068667ms)
▶ downloadToFile with createDownloader over HTTP
✔ downloads content to the destination file (15.010792ms)
✔ follows redirects and delivers final content (4.054959ms)
✔ rejects after too many redirects (4.171583ms)
✔ rejects on HTTP error status (1.508708ms)
✔ creates parent directories for the destination (3.273166ms)
✔ downloadToFile with createDownloader over HTTP (28.71675ms)
▶ streamingSha256
✔ computes the same hash as the in-memory calculateSha256Hex (4.42175ms)
✔ produces correct SHA-256 for known input (2.551959ms)
✔ handles empty files (1.416667ms)
✔ streamingSha256 (8.757167ms)
▶ performManagedInstall staging cleanup
✔ cleans up staging directory after download failure (3.234417ms)
✔ performManagedInstall staging cleanup (3.37925ms)
✔ formatError extracts message from Error instances (1.52575ms)
✔ formatError converts non-Error values to strings (0.070209ms)
✔ formatError falls back to String for Error with empty message (0.042292ms)
✔ formatCliOutput merges stderr and stdout into a single line (0.132334ms)
✔ formatCliOutput returns exit code when both streams are empty (0.041916ms)
✔ formatCliOutput normalizes CRLF line endings (0.035708ms)
✔ classifyAgentsFile returns missing when AGENTS.md does not exist (0.056959ms)
✔ classifyAgentsFile treats CRLF and trailing newline differences as up to date (0.041125ms)
✔ classifyAgentsFile detects real content drift (0.077208ms)
✔ buildStatusDetails includes workspace readiness context (0.331834ms)
✔ preferredStatusAction points missing binary users to settings (0.93475ms)
✔ preferredStatusAction suggests install when binary missing with managed install available (0.124917ms)
✔ buildStatusDetails includes compatibility upgrade guidance (0.198375ms)
✔ buildStatusDetails surfaces managed install failure diagnostics (0.113542ms)
✔ preferredStatusAction points outdated CLI users to releases (0.079083ms)
✔ preferredStatusAction points ready workspaces without AGENTS to initialization (0.13775ms)
✔ preferredStatusAction points ready workspaces without MCP config to MCP setup (0.097792ms)
✔ preferredStatusAction returns nothing when workspace is already ready (0.050542ms)
✔ preferredStatusAction returns nothing when workspace readiness is undefined (0.051958ms)
✔ buildPatchloomMcpEntry points at patchloom mcp-server (0.091833ms)
✔ inspectMcpTargets reports configured targets (0.4135ms)
✔ configureMcpTargets creates or updates only the selected target kinds (0.262ms)
✔ generateAgentRules logs error to output channel on CLI failure (3.566667ms)
✔ promoteManagedInstallBinary moves a staged binary to the live path with real files (12.1115ms)
✔ promoteManagedInstallBinary replaces an existing binary and removes the backup (4.995375ms)
✔ promoteManagedInstallBinary rolls back on rename failure with real files (6.696959ms)
✔ clearManagedInstallStaging removes a real staging directory (2.709125ms)
✔ persistManagedInstallFailure and loadManagedInstallFailure round-trip through real files (2.936708ms)
✔ clearManagedInstallFailureRecord removes the failure file on disk (1.689084ms)
✔ inspectManagedInstallStatus detects a real binary on disk (2.40825ms)
✔ inspectManagedInstallStatus reports missing binary when file does not exist (0.708625ms)
✔ inspectManagedInstallStatus loads persisted failure from disk (1.504958ms)
✔ promoteManagedInstallBinary clears persisted failure on disk after success (3.318542ms)
✔ loadManagedInstallFailure returns undefined for corrupted JSON on disk (1.63575ms)
✔ loadManagedInstallFailure returns undefined for valid JSON with wrong shape (1.2515ms)
✔ fetchLatestReleaseVersion extracts version from GitHub API response (0.177875ms)
✔ fetchLatestReleaseVersion strips leading v from tag (0.076459ms)
✔ fetchLatestReleaseVersion throws on missing tag_name (0.060083ms)
✔ fetchLatestReleaseVersion throws on API failure (0.06425ms)
✔ extractManagedInstallArchive invokes tar with correct arguments for tar.xz (0.095708ms)
✔ extractManagedInstallArchive invokes tar for zip format on Windows (0.0555ms)
✔ performManagedInstall runs full pipeline with injected I/O (6.023583ms)
✔ performManagedInstall persists failure on checksum mismatch (3.931709ms)
✔ performManagedInstall throws for unsupported platform (0.120291ms)
✔ performManagedInstall fetches latest version when none specified (2.542708ms)
✔ configureMcpTargets writes VS Code mcp.json to a real temp workspace (10.296125ms)
✔ configureMcpTargets preserves existing servers in the config file (3.668708ms)
✔ configureMcpTargets creates both vscode and cursor configs (3.813541ms)
✔ inspectMcpTargets reads configured status from real files (2.765375ms)
✔ configureMcpTargets is idempotent on second call (2.350625ms)
✔ configureMcpTargets handles invalid JSON in existing file gracefully (2.859042ms)
✔ configureMcpTargets writes windsurf config with mcpServers key (2.554041ms)
✔ resolveMcpTargets omits workspace targets when no workspace is provided (0.123625ms)
✔ configureMcpTargets handles empty config file (3.812375ms)
✔ createPatchloomLog lazily creates channel on first log call (2.415916ms)
✔ logCommand appends command with arguments and cwd (0.14625ms)
✔ logResult appends stdout, stderr, and exit code (0.2105ms)
✔ logResult omits empty stdout and stderr (0.074541ms)
✔ show calls channel.show with preserveFocus (0.078667ms)
✔ dispose disposes channel and subsequent log creates a new one (0.280334ms)
✔ setPatchloomLog and getPatchloomLog round-trip module state (0.127583ms)
✔ logResult omits whitespace-only stdout and stderr (0.101875ms)
✔ logResult splits Windows-style CRLF line endings (0.123875ms)
✔ logResult handles multiline stderr (0.09875ms)
▶ patchloom CLI integration
✔ --version returns parseable version string (3.465042ms)
✔ --version output passes compatibility assessment (2.701042ms)
✔ resolvePatchloomStatusWithInputs discovers the real binary (3.206667ms)
✔ agent-rules produces markdown output (2.854208ms)
✔ doc set modifies a JSON file by selector (5.355458ms)
✔ doc set preserves YAML comments (5.750375ms)
✔ replace performs text substitution in a file (8.217625ms)
✔ tidy fix ensures final newline (8.201333ms)
✔ search finds text across files (6.313125ms)
✔ doc get reads a value by selector (3.355ms)
✔ batch applies multiple operations via stdin (6.157291ms)
✔ create makes a new file (3.756083ms)
✔ exit code 3 for search with no matches (4.896ms)
✔ exit code 2 for replace --check with pending changes (6.341791ms)
✔ exit code 0 for tidy check on a clean file (6.0845ms)
✔ exit code 2 for tidy check on a file needing fixes (7.454875ms)
✔ agent-rules output classified as up_to_date after write (3.116333ms)
✔ agent-rules output classified as different after modification (2.552792ms)
✔ quick action preview flow: copy, apply to copy, compare (7.260708ms)
✔ buildStatusDetails renders real binary status correctly (2.654583ms)
✔ preferredStatusAction suggests Initialize Project for real ready status (2.288459ms)
✔ mcp-server starts and responds to JSON-RPC initialize (103.6715ms)
✔ doc delete removes a key from a JSON file (6.111208ms)
✔ doc merge adds keys to a JSON file (4.443542ms)
✔ doc append adds an item to a JSON array (5.165583ms)
✔ md upsert-bullet adds a bullet under a heading (4.67825ms)
✔ md table-append adds a row to a markdown table (4.452375ms)
✔ undo restores files after an apply (10.986958ms)
✔ MCP config written for real binary is structurally valid (1.279334ms)
✔ patchloom CLI integration (244.093209ms)
▶ managed install end-to-end MCP
✔ managed install produces a runnable binary (391.714042ms)
✔ MCP server responds to initialize (101.312292ms)
✔ MCP server lists available tools (201.719209ms)
✔ MCP tools/call modifies a file on disk (202.935833ms)
✔ cleanup managed install temp directory (1.317667ms)
✔ managed install end-to-end MCP (899.268333ms)
▶ parsePatchloomVersion property-based tests
✔ never throws on arbitrary input (4.482667ms)
✔ always extracts the version from a well-formed semver string (1.083625ms)
✔ strips the leading v prefix from parsed versions (0.855542ms)
✔ parsePatchloomVersion property-based tests (7.412625ms)
▶ comparePatchloomVersions property-based tests
✔ is reflexive: compare(a, a) === 0 (1.080583ms)
✔ is antisymmetric: sign(compare(a, b)) === -sign(compare(b, a)) (1.247083ms)
✔ respects numeric ordering for major versions (0.748167ms)
✔ comparePatchloomVersions property-based tests (3.209167ms)
▶ formatError property-based tests
✔ never throws on arbitrary input (6.981459ms)
✔ returns the message for Error instances with non-empty messages (1.523375ms)
✔ formatError property-based tests (8.624459ms)
▶ formatCliOutput property-based tests
✔ always returns a non-empty string (1.180541ms)
✔ includes exit code when both streams are whitespace-only (0.560875ms)
✔ formatCliOutput property-based tests (1.8065ms)
▶ parseManagedInstallChecksumFile property-based tests
✔ returns an array or throws a verification error on arbitrary input (1.261833ms)
✔ parses well-formed checksum lines into entries (12.02825ms)
✔ returns empty array for blank input (0.994959ms)
✔ parseManagedInstallChecksumFile property-based tests (14.381042ms)
✔ buildReplaceQuickAction builds a replace command for one file (2.015083ms)
✔ buildTidyQuickAction includes selected tidy flags (0.21875ms)
✔ buildDocSetQuickAction builds a doc set command (0.121625ms)
✔ retargetQuickAction swaps only the target path arguments (0.093084ms)
✔ withApplyFlag appends apply once (0.069292ms)
✔ isStructuredDocumentPath recognizes supported structured formats (0.153708ms)
✔ isStructuredDocumentPath handles uppercase extensions (0.082041ms)
✔ isStructuredDocumentPath rejects files without extensions (0.052083ms)
✔ isStructuredDocumentPath rejects dotfiles without basenames (0.068666ms)
✔ buildTidyQuickAction with a single fix omits unselected flags (0.060042ms)
✔ buildSearchQuickAction builds a search command without glob (0.079875ms)
✔ buildSearchQuickAction includes glob when provided (0.053291ms)
✔ buildCreateQuickAction builds a create command (0.062167ms)
✔ buildSearchQuickAction preserves spaces in pattern as a single arg (0.05925ms)
✔ buildDocGetQuickAction builds a doc get command (0.057916ms)
✔ resolveWorkspaceRelativePath accepts path inside workspace (0.151833ms)
✔ resolveWorkspaceRelativePath accepts nested subdirectory (0.059125ms)
✔ resolveWorkspaceRelativePath rejects traversal with .. (0.291625ms)
✔ resolveWorkspaceRelativePath rejects absolute path outside workspace (0.072167ms)
✔ resolveWorkspaceRelativePath rejects workspace root itself (0.054875ms)
✔ buildSearchQuickAction with empty pattern produces valid args (0.042292ms)
✔ buildSearchQuickAction with regex special characters (0.037708ms)
✔ buildCreateQuickAction with spaces in path (0.043084ms)
✔ buildDocGetQuickAction with deeply nested selector (0.048333ms)
✔ buildCreateQuickAction with unicode filename (0.043583ms)
✔ buildSearchQuickAction with unicode pattern (0.034292ms)
✔ buildDocDeleteQuickAction builds a doc delete command (0.066042ms)
✔ buildDocMergeQuickAction builds a doc merge command (0.04925ms)
✔ buildDocAppendQuickAction builds a doc append command (0.050417ms)
✔ buildMdTableAppendQuickAction builds a md table-append command (0.046375ms)
✔ buildMdUpsertBulletQuickAction builds a md upsert-bullet command (0.045667ms)
✔ buildMdReplaceSectionQuickAction builds a md replace-section command (0.0795ms)
✔ buildUndoQuickAction builds an undo command (0.099625ms)
✔ buildDocPrependQuickAction builds a doc prepend command (0.070042ms)
✔ buildDocEnsureQuickAction builds a doc ensure command (0.065709ms)
✔ buildDocMoveQuickAction builds a doc move command (0.0655ms)
✔ buildMdInsertAfterHeadingQuickAction builds a md insert-after-heading command (0.066833ms)
✔ buildMdInsertBeforeHeadingQuickAction builds a md insert-before-heading command (0.041083ms)
✔ retargetQuickAction works with doc move command (0.033458ms)
✔ retargetQuickAction works with md insert-after-heading command (0.028292ms)
✔ isMarkdownPath recognizes markdown extensions (0.086833ms)
✔ isMarkdownPath handles uppercase extensions (0.057209ms)
✔ retargetQuickAction works with md commands (0.040459ms)
✔ buildPatchMergeQuickAction builds a patch merge command (0.134791ms)
✔ buildPatchMergeQuickAction includes allow-conflicts flag when enabled (0.059875ms)
✔ retargetQuickAction works with patch merge command (0.04225ms)
✔ buildAppendQuickAction builds an append command (0.052458ms)
✔ parseInitializeResponse extracts server info from valid response (1.088792ms)
✔ parseInitializeResponse handles response without serverInfo (0.093416ms)
✔ parseInitializeResponse detects JSON-RPC error response (0.060417ms)
✔ parseInitializeResponse returns undefined for empty string (0.048959ms)
✔ parseInitializeResponse returns undefined for non-JSON lines (0.076875ms)
✔ parseInitializeResponse skips non-jsonrpc lines (0.052291ms)
✔ parseInitializeResponse handles multi-line output with blank lines (0.079625ms)
✔ verifyMcpServer returns success from injected spawn (0.088333ms)
✔ verifyMcpServer returns failure from injected spawn (0.084875ms)
✔ verifyMcpServer catches thrown errors from spawn (0.15775ms)
✔ verifyMcpServer catches non-Error thrown values (0.563167ms)
✔ buildStatusDetails shows per-editor MCP breakdown (0.336417ms)
✔ buildStatusDetails shows fallback when mcpTargets is undefined (0.083375ms)
✔ buildStatusDetails shows checkmark for configured targets (0.075667ms)
✔ buildStatusDetails shows X for unconfigured targets (0.067916ms)
ℹ tests 259
ℹ suites 10
ℹ pass 259
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 30620.071458
ℹ start of coverage report
ℹ -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ℹ file | line % | branch % | funcs % | uncovered lines
ℹ -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ℹ out-test | | | |
ℹ src | | | |
ℹ binary | | | |
ℹ patchloom.js | 87.70 | 91.34 | 83.33 | 10-11 16 21-23 59-70 155-173 209-210 329-330 346-347 360-361
ℹ commands | | | |
ℹ initializeProject.js | 41.67 | 72.73 | 60.00 | 15-67 95-104
ℹ verifyMcp.js | 39.10 | 84.62 | 50.00 | 9-36 49-113 128-129
ℹ install | | | |
ℹ managed.js | 91.04 | 84.24 | 85.71 | 10-11 16 21-23 90-95 99-101 131-132 154-160 162-168 244-245 313-314 420-421 435-436 438-440 511-512 541-543 546-547 550-551
ℹ logging | | | |
ℹ outputChannel.js | 100.00 | 100.00 | 100.00 |
ℹ mcp | | | |
ℹ config.js | 94.61 | 79.63 | 80.00 | 10-11 16 21-23 164-166
ℹ status | | | |
ℹ details.js | 100.00 | 96.77 | 100.00 |
ℹ util.js | 91.67 | 90.91 | 100.00 | 13-14
ℹ workspace | | | |
ℹ readiness.js | 47.18 | 100.00 | 40.00 | 8-45 105-141
ℹ test | | | |
ℹ unit | | | |
ℹ batchApply.test.js | 100.00 | 94.74 | 100.00 |
ℹ binary.test.js | 98.76 | 91.13 | 92.98 | 10-11 16 21-23 382-383
ℹ binaryDiscovery.test.js | 94.23 | 71.43 | 88.57 | 10-11 16 21-23 100-101 124-125 144-145
ℹ downloadIntegration.test.js | 94.00 | 87.10 | 93.02 | 10-11 16 21-23 71-74 191-192
ℹ initializeProject.test.js | 98.15 | 78.57 | 86.96 | 10-11 16 21-23 339
ℹ managedLifecycle.test.js | 98.58 | 91.11 | 95.89 | 10-11 16 21-23
ℹ mcpConfig.test.js | 95.51 | 82.46 | 93.18 | 10-11 16 21-23 96-97 200-201 254-255
ℹ outputChannel.test.js | 97.99 | 97.62 | 68.97 | 99-101
ℹ propertyBased.test.js | 95.92 | 88.24 | 92.86 | 10-11 16 21-23
ℹ quickActions.test.js | 100.00 | 98.11 | 100.00 |
ℹ verifyMcp.test.js | 100.00 | 95.45 | 100.00 |
ℹ -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ℹ all files | 91.36 | 88.20 | 89.39 |
ℹ -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ℹ end of coverage report

patchloom@0.0.4 package
vsce package

Executing prepublish script 'npm run vscode:prepublish'...

patchloom@0.0.4 vscode:prepublish
npm run compile

patchloom@0.0.4 compile
tsc -p ./

INFO Files included in the VSIX:
patchloom-0.0.4.vsix
├─ [Content_Types].xml
├─ extension.vsixmanifest
└─ extension/
├─ LICENSE.txt [1.05 KB]
├─ changelog.md [9.34 KB]
├─ package.json [8.95 KB]
├─ readme.md [9.72 KB]
├─ images/
│ ├─ banner.png [113.9 KB]
│ ├─ icon-128.png [3.57 KB]
│ ├─ icon.png [63.07 KB]
│ ├─ logo-512.png [13.75 KB]
│ ├─ logo.svg [1.2 KB]
│ └─ setup-workspace-demo.gif [104.33 KB]
├─ out/
│ ├─ extension.js [4.82 KB]
│ ├─ extension.js.map [2.15 KB]
│ ├─ util.js [0.67 KB]
│ ├─ util.js.map [0.72 KB]
│ ├─ binary/ (2 files) [24 KB]
│ ├─ commands/ (18 files) [148.21 KB]
│ ├─ install/ (2 files) [42.04 KB]
│ ├─ logging/ (2 files) [3.15 KB]
│ ├─ mcp/ (4 files) [15.22 KB]
│ ├─ status/ (4 files) [12.15 KB]
│ └─ workspace/ (2 files) [9.28 KB]
└─ walkthrough/
├─ configure-mcp.md [0.61 KB]
├─ initialize.md [0.52 KB]
└─ install.md [0.63 KB]

=> Run vsce ls --tree to see all included files.

DONE Packaged: /Users/sebastientardif/patchloom-vscode/patchloom-0.0.4.vsix (53 files, 368.46 KB).

See patchloom-vscode-contrib for details.

…ady-check duplication across commands); increase managed install --version timeout for cold-start flakiness

- Developer: deduped 6+ copies of ready + upgrade notify logic.
- QA: 30s timeout for post-install --version in e2e (was 15s, cold binaries can exceed).

Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
…erspective)

- patchloomCli.test.ts count refreshed to reflect current e2e + unit.

Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
@patchloom-release patchloom-release Bot enabled auto-merge (squash) June 22, 2026 19:03
@patchloom-release patchloom-release Bot merged commit a20da2b into main Jun 22, 2026
19 of 20 checks passed
@patchloom-release patchloom-release Bot deleted the fix/multi-perspective-improvements-20260622 branch June 22, 2026 19:07
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