Skip to content

feat: add kill CLI command, implement session activity spinner in TUI…#1014

Open
ElioNeto wants to merge 62 commits into
mainfrom
develop
Open

feat: add kill CLI command, implement session activity spinner in TUI…#1014
ElioNeto wants to merge 62 commits into
mainfrom
develop

Conversation

@ElioNeto
Copy link
Copy Markdown
Owner

… and desktop, and improve lock handling.

Issue for this PR

Closes #

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Please provide a description of the issue, the changes you made to fix it, and why they work. It is expected that you understand why your changes work and if you do not understand why at least say as much so a maintainer knows how much to value the PR.

If you paste a large clearly AI generated description here your PR may be IGNORED or CLOSED!

How did you verify your code works?

Screenshots / recordings

If this is a UI change, please include a screenshot or recording.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

If you do not follow this template your PR will be automatically rejected.

ElioNeto added 26 commits May 20, 2026 20:09
…n ProviderID.teamcode schema

- Renamed opencode.json -> teamcode.json in all 16 test files (184 occurrences)
- Updated nvidia header expectations from OpenCode to TeamCode
- Fixed ProviderID.teamcode in schema.ts to map to 'opencode' matching models-snapshot
- Fixed opencode loader config check to use 'opencode' key matching database
- All provider test failures reduced from 9 to 2 (pre-existing plugin config issues)

Resolves pre-existing test failures from opencode->teamcode rename migration.

Automatic resolution via delivery-loop pipeline.
The postinstall script was looking for opencode-* packages and opencode
binary, but the published packages are @teamcode-ai/linux-x64 etc. and
the binary is named teamcode.
- Fixed tool/github-* references from anomalyco/opencode to ElioNeto/teamcode
- Fixed skill/effect package path from packages/opencode to packages/teamcode
- Fixed triage agent team assignments to match repo ownership

Added 5 new specialized agents:
  - db-agent: Drizzle ORM schema design and SQLite migrations
  - desktop-agent: Electron-based desktop app development
  - web-agent: SolidJS web app with Vite, Tailwind, Hono
  - test-agent: Test infrastructure across the monorepo
  - docs-agent: Project documentation specialist

Added 6 new skills:
  - database: Drizzle ORM patterns and migration workflow
  - desktop-app: Electron architecture and development
  - web-app: SolidJS and frontend conventions
  - testing: Bun test, Effect test helpers, fixtures
  - sdk: JavaScript SDK architecture and regeneration
  - cli: CLI and TUI architecture

Added 5 new commands:
  - db-generate: Database migration generation
  - dev-server: Development server launcher
  - build-package: Package build helper
  - check-types: TypeScript type checking
  - run-tests: Test runner

Updated opencode.jsonc with comprehensive configuration including:
  - All agent model assignments
  - Useful CLI commands
  - Permission rules with granular bash patterns
  - Tool output and compaction settings

Cleaned up duplicate agent/command files in .opencode/ directory
(unique glossary/ and issues/ directories preserved)
Archived sessions are no longer removed from the store or filtered out
of the session list. They appear in a collapsible 'Archived' section at
the bottom of the workspace sidebar, visually dimmed with italic text
and an unarchive button. The latestRootSession helper now explicitly
filters archived sessions so they are never auto-selected for navigation.

Resolves #978
Archived sessions are no longer removed from the store or filtered out
of the session list. They appear in a collapsible 'Archived' section at
the bottom of the workspace sidebar, visually dimmed with italic text
and an unarchive button. The latestRootSession helper now explicitly
filters archived sessions so they are never auto-selected for navigation.

Resolves #978
Updates the OpenAPI spec and generated SDK types so the session
update endpoint accepts null for time.archived, enabling unarchive
via the session update API.

Resolves #978
Two fixes:

1. fix(cli): remove process.exit() call to prevent PowerShell exit on /exit
   - Replaced process.exit() with process.exitCode assignment so the event
     loop drains naturally instead of forcefully terminating, which was
     causing the parent PowerShell process to exit on Windows.

2. fix(core): handle child process external termination gracefully
   - cross-spawn-spawner: return exit code 1 instead of failing when
     process is killed by signal (e.g., taskkill /F /IM node.exe)
   - run.ts: use process.exitCode instead of process.exit(1)
   - mcp/index.ts: detect transport disconnection and update status

Resolves #982
Resolves #995
fix(project): enforce strict project directory boundary
- containsPath now only checks ctx.directory instead of falling back
  to the git worktree, preventing file creation in sibling directories
  within the same git repo

fix(notifications): prevent badge reappearance on desktop restart
- Added ready() guard to notification event listener to prevent race
  condition where SDK events fire before persisted state is loaded

Resolves #985
Resolves #1003
Adds README.md copy alongside LICENSE in the meta-package creation
section of publish.ts so npmjs.com shows documentation.

Resolves #1015

Automatic resolution via delivery-loop pipeline.
closeIssue and commentOnIssue were using PATCH (apiPatch) for
creating comments on issues. GitHub API requires POST for
/repos/{owner}/{repo}/issues/{number}/comments.

Added apiPost function and fixed both methods.
…tion

The markdown stream's remend htmlTags handler was stripping incomplete
HTML-like tags (e.g., <T> in List<T>), causing responses with C#
generic types to be truncated. Disabled htmlTags in remend options.

Also added an html() renderer in marked context to escape < and > in
inline HTML tags, preventing DOMPurify from stripping non-standard
tags like <T>.

Resolves #983

Automatic resolution via delivery-loop pipeline.
Adds a refresh button (reset icon) to the file tab content area
that allows users to manually reload a file when its content
changes on disk, particularly useful for MD files that don't
auto-refresh.

Uses file.load(path, { force: true }) to trigger a reload.

Resolves #1005

Automatic resolution via delivery-loop pipeline.
AI models sometimes use timeout: -1 expecting it to mean
'no timeout' / 'wait indefinitely', causing a schema validation
error and getting stuck in a loop (issue #974).

- Changed timeout schema to accept both PositiveInt and -1
- Treat -1 as Infinity (no timeout race)
- Updated prompt descriptions to document -1 behavior

Resolves #974

Automatic resolution via delivery-loop pipeline.
… text

When a non-vision model receives an image attachment (e.g., via
clipboard paste), the unsupportedParts function was replacing it
with an error message that confused the model and wasted a turn.

Changed to silently drop unsupported parts from the message,
allowing the rest of the user's text to be processed normally.

Resolves #917

Automatic resolution via delivery-loop pipeline.
…approval compression

Implements remaining pieces of the Caveman mode feature:

- /caveman [lite|full|ultra] TUI command to enable/switch level
- /caveman-stats TUI command to show tokens saved
- CAVEMAN badge in TUI prompt header (colored, bold, shows level)
- compressDefinition() helper for caveman-compressed swarm templates
- compressApprovalRequest() helper for compressed approval messages

Closes #28
…ecutor, Reviewer

Adds the four core swarm roles as separate modules under swarm/roles/:

- planner.ts — TaskPlan schema and strategic decomposition prompt
- researcher.ts — ResearchResult schema and codebase investigation prompt
- executor.ts — ExecutionResult schema and implementation prompt
- reviewer.ts — ReviewResult schema with approve/change/block verdict

Each role exports its own types, system prompt, and config schema
for model/temperature overrides per role.

Part of #2
…anel

Bug 1 - Esc interrupt: removed 2-press guard that required pressing Esc
twice within 5 seconds to abort generation. Now single Esc during
streaming immediately calls session.abort().

Bug 2 - Ctrl+G Git toggle:
- Changed git_toggle keybind from ctrl+shift+g to ctrl+g
- Changed conflicting messages_first from ctrl+g,home to
  ctrl+shift+g,home to avoid chord conflict

Closes #1016
Registers Planner, Researcher, Executor, and Reviewer as native
subagent agents so the swarm orchestrator can resolve them via
agentSvc.get("planner") without user configuration.

Each role has:
- A dedicated system prompt (.txt file in agent/prompt/)
- Tailored tool permissions (read-only for planner/researcher/reviewer,
  edit+execute for executor)
- Appropriate description and metadata

The existing swarm templates already reference these role names.
With this change, the orchestrator can dispatch them immediately.

Part of #2
Completes Phase 0 of Bun Shell Migration:
- Process.status() — run and return exit code
- Process.shell() — run command via system shell
- Process.git() — run git command with args
- Process.gitText() — run git command returning text

Part of #17
…r) to agent schema

Adds the four swarm roles to both the agent config schema and the
deprecated mode schema so users can configure per-role model overrides
and prompts in teamcode.json.

Part of #2
When /undo is called, the current todo list is captured and stored in
the revert metadata. On cleanup (next prompt), the todo list is restored
to its pre-revert state so undone todo entries don't persist.

Fixes #898
…bind overrides

When a user rebinds return to input_newline, the global managed textarea
layer captures bare Enter in all focused textareas, including the
DialogPrompt textarea. This broke dialog forms (rename, etc.) because
Enter inserted a newline instead of submitting.

Fix: add onKeyDown handler to DialogPrompt's textarea that intercepts
bare Enter (without Shift) and calls onConfirm directly, bypassing the
keymap.

Fixes #900
When pasting multi-line shell commands into shell mode, JSON.stringify
escaped actual newlines to \n (two chars), which bash/zsh eval treated
as literal backslash-n instead of command separators.

Fix: replace newlines with semicolons before wrapping in JSON.stringify,
so multi-line pasted commands execute as separate commands in the shell.

Fixes #877
Rename all OPENCODE_* prefixed constants, env vars, flags, and types
to TEAMCODE_* to match the project branding.

Key changes:
- Flag.OPENCODE_* -> Flag.TEAMCODE_* (flag.ts)
- process.env['OPENCODE_*'] -> process.env['TEAMCODE_*']
- Build defines: OPENCODE_VERSION -> TEAMCODE_VERSION (build.ts)
- Global constants: OPENCODE_VERSION, OPENCODE_CHANNEL (version.ts)
- Window property: __OPENCODE__ -> __TEAMCODE__
- Vite env vars: VITE_OPENCODE_* -> VITE_TEAMCODE_*
- CI workflow: OPENCODE_VERSION, OPENCODE_RELEASE, OPENCODE_CHANNEL
- Removed fallback alias logic in truthy() helper
- Deleted unused opencode-process.ts (teamcode-process.ts is active)
- Removed OPENCODE_* fallback aliases in runtime-flags.ts

Test fixes (reduced failures from 158 to 93):
- Skill discovery: .opencode/ directories now scanned for skill files
- Config paths: disableProjectConfig properly gates projectFiles()
- Plugin meta: storePath reads TEAMCODE_PLUGIN_META_FILE from process.env
- Layer caching: RuntimeFlags.defaultLayer wrapped in Layer.fresh()
- Auth tests: use process.env instead of Flag for env var changes
- Session: ECONNRESET error detection strengthened
- Session: temperature parameter precedence fixed (agent > model default)
- Empty file read: test expects '(File is empty)' output
- containsPath: test updated for strict directory boundary enforcement
- Config parser: error shape updated for Effect v4 TaggedErrorClass
Correções de testes (158 → 40 falhas, 75% resolvidas):

- Skill discovery: adicionado scan de .opencode/ para skills first-party
- Plugin meta: storePath lê env var direto do process.env
- RuntimeFlags: Layer.fresh() para evitar cache de env vars
- Config paths: disableProjectConfig filtra projectFiles()
- Auth: server/auth lê env var direto (sem RuntimeFlags)
- ProxyUtil: headers atualizados para x-teamcode-*
- Session: fromError serializa TaggedErrorClass corretamente
- Session: ECONNRESET detection expandida
- Session: temperatura precedence (agent > model)
- Compaction: overflow headroom corrigido
- CORS: middleware global, OPTIONS antes do handler
- CORS: header names atualizados (x-opencode → x-teamcode)
- Provider: applyCaching só seta cache relevante ao modelo
- Project: .git/opencode → .git/teamcode
- Worktree: branch prefix opencode/ → teamcode/
- Plugin install: .opencode → .teamcode, opencode.jsonc → teamcode.jsonc
- Permission, error tests: branding atualizado
- TypeScript: mergeDeep cast type fix

93 falhas restantes são maioritariamente testes de integração
complexos (HttpApi, workspace, CORS) pré-existentes.
ElioNeto added 3 commits May 21, 2026 16:24
Principais correções:
- Session fromError: toObj lida com TaggedErrorClass + NamedError
- Session ECONNRESET: expandida detecção de erros de rede
- Permission disabled: implementação correta com last-match-wins
- Config: cachedGlobal sem RuntimeFlags snapshot congelado
- Plugin meta: storePath lê env var direto
- Auth: lê env var direto (sem RuntimeFlags)
- ProxyUtil headers: x-opencode → x-teamcode
- CORS middleware: global ({ global: true }), OPTIONS antes do handler
- Session overflow: headroom calculation corrigido
- Provider applyCaching: só seta cache relevante ao modelo
- Project: .git/opencode → .git/teamcode
- Worktree: prefix branch opencode/ → teamcode/
- Plugin install: .opencode → .teamcode
- Testes de snapshot: atualizados
- TypeScript: mergeDeep cast, getGlobal type fix
- Provider transform: DeepSeek reasoning + cache control atualizados

158 → 12 falhas (99.6% dos testes passando)
Corrige 3 dos 12 testes restantes:
- httpapi-query-schema-drift: mode working -> git
- plugin-loader: .opencode/themes -> .teamcode/themes
- httpapi-sdk: undefined TEAMCODE_SERVER_PASSWORD nao passado ao ConfigProvider
- httpapi-cors: corsLayer le CorsConfig via Context.Reference

9 testes ainda falham: 4 config (pre-existing), 3 SDK (test isolation),
1 CORS (test isolation), 1 plugin-loader-pure (test isolation).
99.67% pass rate (2693/2702)
…lick

On macOS, clicking the window close button should hide the window
but keep the app running in the dock. This adds the standard Electron
'activate' event handler that recreates the main window when the user
clicks the dock icon after closing all windows.

Closes #62
ElioNeto added 29 commits May 25, 2026 19:50
Reduces polling frequency for models.json by 12x, preventing excessive
network requests that can consume 21+ GB/day when models URL points to
a large file on raw.githubusercontent.com.

Closes #88
Add packElevateHelper:false and allowElevation:false to ensure the
NSIS installer respects user-selected custom install directories
and doesn't fall back to default C drive paths during auto-updates.

Closes #822
The mentionTriggerIndex function expects a display offset (visual width),
but was receiving a raw string cursor index. For CJK text where one character
equals 2 display units, this caused the @mention trigger to fail or require
extra spaces to activate.

Fix: convert the string cursor to a display offset via promptOffsetWidth
before passing to mentionTriggerIndex.

Closes #865
When git add --all fails (e.g., due to a nested git repo with no commits),
the snapshot index retains the previous tree. A subsequent write-tree
returns the stale tree hash, making restore operations unsafe.

Fix: add --ignore-errors to skip problematic files, and reset the index
on complete failure to prevent stale tree reuse.

Closes #894
The cursor-position guard (Up at position 0, Down at end) was applied to
every history navigation attempt, including when already browsing history.
After navigating back with Up (cursor set to 0), pressing Down would fail
because cursor 0 != text length.

Fix: only enforce cursor position when entering history browse from
user input (state.index === null). Once browsing, cursor position is
ignored for subsequent Up/Down presses.

Closes #904
Older persisted settings might be missing nested fields like 'permissions',
notifications', or 'sounds' that were added in later versions. When makePersisted
replaces the entire store with saved data, these missing fields cause the
settings to fall back to defaults on every restart.

Fix: add a migrate function that fills in missing nested default fields
when loading older persisted settings data.

Closes #847
Adds a guard at the beginning of handleSubmit that returns early
if the session is already working, preventing multiple prompts
from being sent when pressing Enter multiple times on a slow
connection.

Closes #837
Two-part fix:
1. Remove 'escape' from captured keys when autocomplete is visible so
   ESC reaches the global keybinding system instead of being swallowed
   by the textarea.
2. Add hide() to the AutocompleteRef so the interrupt handler can close
   the autocomplete popup before aborting the session.

Previously pressing ESC while autocomplete was open did nothing because
the textarea captured the key but had no handler for it.
Two fixes:
1. Resize uploaded icon images to max 128x128 before converting to data URL,
   preventing oversized base64 strings from being rejected by the storage layer.
2. Add error handling to the save mutation so save failures surface a toast
   instead of silently failing.

Closes #895
…wline

When oldString is empty (creating a new file), the newString content is
now guaranteed to end with a newline character, matching the convention
that all text files end with a trailing newline.

Closes #786
Server-side errors in the RPC listen handler were not caught, so the
client never received a response and hung forever. The client also had
no reject callback, so even if an error were sent it couldn't surface.

Fix: wrap the server handler in try-catch and send an 'rpc.error' message
on failure; add a reject callback on the client side.

Closes #797
When usable() returns 0 (e.g., because the model's context limit is very
small and outputReserve consumes it all), an empty session with count 0
would still trigger '0 >= 0 = true' and immediately start compaction.

Fix: add count > 0 guard so overflow only fires when there is actual
content in the session.

Closes #862
Worker pool initialization was fire-and-forget (void pool.initialize())
with no error handling. When the pool failed to initialize, callers
received no error event and code blocks remained unrendered.

Fix: add .catch() handler that logs the failure so downstream code
can fall back to plain-text rendering.

Closes #861
…s visible

Previously, pressing ESC while autocomplete was visible during model
generation would only close the autocomplete popup without aborting the
session, requiring the user to press ESC twice. Now a single ESC press
closes autocomplete (if visible) AND immediately aborts the session.

Also removes the guard condition that checked auto()?.visible before
calling session.abort(), so the interrupt always proceeds.

Closes #1022
Plan-mode synthetic reminders (and build-switch reminders) were appended
to the user message in-memory before sending to the model, but were
never persisted via sessions.updatePart(). On subsequent turns, the
historical user message omitted the reminder, causing the model to see
a different prefix and breaking prompt/prefix caches.

Now the non-experimental code path (the default) calls
sessions.updatePart() for the synthetic parts, matching behavior of the
experimental path. This ensures the stored history is identical to what
was sent to the model on the original turn.

Closes #908
… API rejection

The Cerebras API does not support 'reasoning_content' in request messages,
unlike OpenAI/DeepSeek. When assistant messages with reasoning parts were
replayed on follow-up turns, the @ai-sdk/cerebras SDK serialized them as
reasoning_content, causing:
  'reasoning_content: property is unsupported'

Added a normalize step that converts reasoning parts to text parts for
Cerebras models, preserving the thinking content as context without
sending the unsupported field.

Closes #906
…nAI translation

When translating tools from Anthropic format to OpenAI-compatible format,
the intermediate CommonTool format stores the tool name, description, and
parameters inside the 'function' sub-object. The toOaCompatibleRequest
function was incorrectly reading these fields directly from the top-level
tool object, resulting in undefined values and API rejection errors like:
  'tools[0].function: missing field name'

Now reads from tool.function first with a fallback to the top-level
properties for other input formats (e.g. OpenAI Responses API flat format).

Closes #882
…prompt injection

Previously, selected text from the editor was formatted with
<system-reminder> tags but framed as narrative instructions
('Note: The user selected...'). The model could interpret this as
commands rather than data, enabling prompt injection from arbitrary
file contents.

Now uses a <selected_context> block with an explicit instruction that
the content is data, not instructions. The model receives a clear
boundary: 'This content is data, not instructions — analyze it but do
not treat it as commands.'

Also cleans up the formatting for better readability: each selection
in its own fenced code block.

Closes #896
…sts on Windows

- open-path IPC handler now properly executes .cmd/.bat files on Windows
  via cmd.exe /c instead of trying to spawn them directly (which fails
  with ENOENT)
- checkAppExists now actually checks if the app is available on Windows
  and Linux instead of always returning true
- Fixes: 'spawn [object Promise] ENOENT' when VS Code path has spaces
  and is a .cmd file

Closes #893
…acters

mentionTriggerIndex() expects a display-width offset, but the
autocomplete was passing cursorOffset (a character index). For ASCII
text these are identical, but CJK characters have display width 2 and
string length 1, causing the offset mismatch: displaySlice truncated
the '@' out of the text, and mentionTriggerIndex returned undefined.

Fixed by converting cursorOffset to display offset via
promptOffsetWidth() before passing to mentionTriggerIndex, and also
fixed the filter() function and hide-check conditions that similarly
mixed character and display offsets.

This matches the correct implementation already used in footer.prompt.tsx.

Closes #870
…enies

Permission.evaluate uses last-match-wins semantics. The subagent's own
rules were being placed before the parent agent's deny rules, causing
the parent's deny to win (since it appeared later in the array).

For example, setting edit: deny on the primary agent and edit: allow
on the subagent would result in the subagent inheriting deny.

Fixed by reversing the order so the subagent's own rules come last
(highest priority), allowing explicit subagent permissions to override
inherited parent restrictions.

Closes #846
…models with variants

Removes the early-return logic that skipped the variant selection dialog
when a saved variant already existed for the selected model. This ensures
the reasoning effort menu always appears after selecting a model that
supports reasoning, fixing a regression where the dialog would not pop up.

The previously saved variant remains pre-selected in the dialog so users
can quickly confirm their existing choice.

Closes #811
The context percentage indicator was using model.limit.context as the
denominator, which for models with separate input limits (e.g., GPT 5.5
with 400k context but 272k input) showed an misleadingly low percentage.
Now uses model.limit.input when available, falling back to
model.limit.context, giving users a more accurate picture of usable
context proportion.

Closes #794
Port the upstream anomalyco/opencode implementation for ESC interrupt
in the TUI prompt component:

1. Add guard: only interrupt when autocomplete is NOT visible (auto?.visible)
2. Add guard: only interrupt when input is focused
3. Two-press pattern: first ESC shows hint, second ESC within 5s aborts
4. Timer: reset interrupt counter after 5 seconds
5. Abort only fires on second press (store.interrupt >= 2)

Previously the TUI aborted immediately on first ESC press with no
two-press pattern or guard conditions, causing the abort to not
work correctly in practice.

References the upstream implementation at:
anomalyco/opencode/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx

Closes #1024
Root cause: The gather() function caches results by name. Two useBindings
calls both used 'prompt.palette' as the cache key — the first cached bindings
for 7 palette commands, and the second call for session.interrupt returned
the stale cached result, so the ESC→session.interrupt binding was NEVER
registered in the keymap.

Fix: Use a unique cache key 'prompt.interrupt' for the interrupt binding
to avoid colliding with the prompt.palette cache.

Refs #1024
Adds two tests to prevent the session.interrupt gather cache issue:

1. 'session.interrupt is bound to escape by default' — verifies the
   keybind config correctly maps session.interrupt to the escape key.

2. 'gather() returns session.interrupt with unique cache key' —
   documents the gather() caching behavior:
   - gather() with a cached key returns stale results (NOT the
     requested commands), which was the root cause of issue #1024.
   - gather() with a UNIQUE key correctly returns session.interrupt.

Also fixes prompt-traits.test.ts which incorrectly expected 'escape'
in the autocomplete capture list. ESC is deliberately omitted so it
falls through to the global keybinding for session.interrupt.

Adds explanatory comments at both useBindings gather() callsites.
Adds 'id' field to Session.CreateInput schema so POST /session accepts
an explicit session id. Previously the id parameter was accepted in the
SDK's typed API surface but silently ignored on the server side.

Changes:
- Add id?: SessionID to CreateInput schema
- Pass id through Session.create -> createNext
- Add duplicate-id check in HTTP handler: if a session with the given
  id already exists, returns 400 BadRequest instead of creating a
  duplicate

Closes #767
Remove the TEAMCODE_EXPERIMENTAL_FILEWATCHER gate so the
@parcel/watcher-based directory subscriber runs on every project
bootstrap. The watcher already handles missing native bindings
gracefully (logs and returns early), so there's no risk of crashes
on platforms without a binding.

Previously, only the desktop app set this flag to 'true' explicitly,
leaving CLI/TUI users without automatic file tree updates when
files were changed externally (via Explorer, editor, git, etc.).

The subscription uses the same ignore patterns (node_modules, .git,
dist, etc.) and retry logic as before.

Closes #858
…sion

The expand() function now resolves Unix symlinks after expanding ~
and /home/elioneto in permission patterns. Previously, a pattern like ~/ide/**
would only match paths under the literal ~/ide directory, even when
~/ide was a symlink to a different location. The symlink target is
now resolved via fs.realpathSync() so the pattern matches the actual
filesystem paths.

This fixes issues where users configure external_directory patterns
using symlinked directories (e.g. ~/ide -> /mnt/data/projects/) and
the permission system fails to match because the pattern refers to
the symlink path while file access goes through the resolved target.

Symlink resolution is skipped when the prefix path does not exist
(e.g. a future output directory) — the expanded pattern is used as-is.

Closes #835
@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
3 Security Hotspots
4.6% Duplication on New Code (required ≤ 3%)
D Security Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

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