Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Codev.Tests/AgentProfileCatalogTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ await File.WriteAllTextAsync(Path.Combine(directory, "writer.md"), """
Assert.Equal(6, writer.MaxSteps);
Assert.Equal(AgentToolPermission.Allow, AgentProfilePolicy.PermissionFor(writer, "read_file", resource: "docs/guide.md"));
Assert.Equal(AgentToolPermission.Deny, AgentProfilePolicy.PermissionFor(writer, "read_file", resource: "docs/private/key.md"));
Assert.Equal(AgentToolPermission.Deny, AgentProfilePolicy.PermissionFor(writer, "read_file", resource: "docs/../docs/private/key.md"));
Assert.Equal(AgentToolPermission.Ask, AgentProfilePolicy.PermissionFor(writer, "read_file", resource: "README.md"));
Assert.Equal(AgentToolPermission.Ask, AgentProfilePolicy.PermissionFor(writer, "read_file", resource: "docs/../README.md"));
Assert.Equal(AgentToolPermission.Ask, AgentProfilePolicy.PermissionFor(writer, "read_file", resource: "../docs/guide.md"));
Expand All @@ -319,14 +320,15 @@ await File.WriteAllTextAsync(Path.Combine(directory, "writer.md"), """
Assert.Equal(AgentToolPermission.Allow, AgentProfilePolicy.PermissionFor(writer, "search_files"));
Assert.True(AgentProfilePolicy.CanExposeReadPath(writer, "docs/guide.md"));
Assert.False(AgentProfilePolicy.CanExposeReadPath(writer, "docs/private/key.md"));
Assert.False(AgentProfilePolicy.CanExposeReadPath(writer, "docs/../docs/private/key.md"));
Assert.False(AgentProfilePolicy.CanExposeReadPath(writer, "README.md"));
Assert.False(AgentProfilePolicy.CanExposeReadPath(writer, "docs/../README.md"));
Assert.False(AgentProfilePolicy.CanExposeReadPath(writer, "../docs/guide.md"));
Assert.False(AgentProfilePolicy.CanExposeReadPath(writer, "/docs/guide.md"));
Assert.False(AgentProfilePolicy.CanExposeReadPath(writer, "C:/docs/guide.md"));
Assert.True(AgentProfilePolicy.CanExposeReadPath(writer, "docs/../docs/guide.md"));
Assert.Equal(["docs/guide.md"], AgentProfilePolicy.FilterReadablePaths(writer,
["docs/guide.md", "docs/private/key.md", "README.md", "docs/../README.md", "../docs/guide.md"]));
["docs/guide.md", "docs/private/key.md", "docs/../docs/private/key.md", "README.md", "docs/../README.md", "../docs/guide.md"]));
Assert.Empty(loaded.Warnings);
}

Expand Down
2 changes: 2 additions & 0 deletions Codev.Tests/CodeTaskToolExecutorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ public async Task OpenCode_scoped_read_rules_filter_list_search_and_direct_file_
var search = GetUntrustedContent(await ExecuteAsync(executor, "search_files", """{"query":"needle"}"""));
var allowedRead = await ExecuteAsync(executor, "read_file", """{"relative_path":"docs/guide.md"}""");
var deniedRead = await ExecuteAsync(executor, "read_file", """{"relative_path":"docs/private/secret.md"}""");
var traversalDeniedRead = await ExecuteAsync(executor, "read_file", """{"relative_path":"docs/../docs/private/secret.md"}""");
var unmatchedRead = await ExecuteAsync(executor, "read_file", """{"relative_path":"README.md"}""");

Assert.Contains(Path.Combine("docs", "guide.md"), listing, StringComparison.Ordinal);
Expand All @@ -135,6 +136,7 @@ public async Task OpenCode_scoped_read_rules_filter_list_search_and_direct_file_
Assert.DoesNotContain("private needle", search, StringComparison.Ordinal);
Assert.Contains("public needle", allowedRead, StringComparison.Ordinal);
Assert.Contains("Denied by the selected agent profile", deniedRead, StringComparison.Ordinal);
Assert.Contains("Denied by the selected agent profile", traversalDeniedRead, StringComparison.Ordinal);
Assert.Contains("Rejected by the selected agent profile", unmatchedRead, StringComparison.Ordinal);

var semanticExecutor = new CodeTaskToolExecutor(new WorkspaceFileService(_root), _conversation,
Expand Down
2 changes: 1 addition & 1 deletion DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ X-items are from section 7. Items in phase 1 to 3 do not depend on the Avalonia
|---|---|---|---|---|
| D1 | Slash commands and file-based commands | S | none | Core · Avalonia implemented; project commands require trust; manual QA remains; The shared-core implementation remains in place |
| D2 | Skills | M | D1 | Later · Avalonia discovers Codev and OpenCode/Claude/Agents-compatible user and trusted-project skill folders. It accepts OpenCode `name`, `license`, `compatibility`, and nested `metadata` frontmatter, validates the declared name against the directory, and keeps Codev's bounded prompt-only behavior. Project Codev skills win same-name conflicts, followed by OpenCode, Claude, and Agents folders; Codev user skills win over shared user folders. Code task loaders re-read the original file and recheck trust. The portable suite now passes 822 tests with one opt-in live-model test skipped; manual UI checks remain |
| D3 | Agent definition files | M | B4 | Core · Avalonia supports built-in Build/Plan primary agents switchable during Code tasks, Markdown profiles, a validated user profile editor, prompt/tool policies with wildcard matching, edit-path and command allow/deny globs, and model/temperature/step settings. It imports legacy and current V2 OpenCode Markdown profiles from the standard user and trusted-project folders, maps ordered wildcard, shell-command, read-path, and edit-path permissions without overriding Codev's project policy, and warns when a model preference is unsupported. Scoped read rules are checked for direct reads and filter list/search results before they reach the model; relative file candidates are normalized lexically before matching, and rooted or escaping paths cannot inherit a narrower directory allow; they also constrain automatically attached source excerpts, relevance-preflight candidate paths, and optional repo-map entries. An explicit empty filtered selection stays empty instead of falling back to unrestricted automatic context. Resource-scoped V2 `glob`/`grep` rules now map to bounded path-glob and regex-search tools, with requested patterns checked against ordered permission rules and read-path scope still filtering returned files. Path-scoped edit `ask` rules now reach per-proposal approval outside Auto while matching denies remain hard blocks; the shared Auto/project policy still governs asks in Auto. Resource-scoped V2 `task`/`subagent` rules now target specific installed profiles through isolated child worktrees; target denies are hard blocks, asks follow the Auto/project policy, and only root profiles with explicit task permission may delegate. Resource-scoped V2 skill rules filter each discovered skill by OpenCode skill-ID patterns, with deny hiding skills and ask checked when loading; resource-scoped custom-tool rules remain unsupported and are rejected with a warning. Headless UI tests reject invalid profile Markdown, save valid Markdown through the real store and verify reload, select a saved profile in the real picker while verifying active-conversation persistence and label updates, and switch Build/Plan from the picker and Ctrl+Shift+A in both directions. Persisted profile references use validated display names (including spaces); profile filenames remain short slugs. Portable tests assert Plan schemas omit edit, shell, MCP, delegation, and background operations for both Ollama and OpenAI; executor tests reject Plan edits and commands before project review or command approval. A Windows x64 preview smoke verified that a multi-word `Smoke QA` selection remains visible after restart. Current-source Windows/.NET 10 recheck on PR head `3ce4814` passed all 30 `AgentProfileCatalogTests` and `Code_task_profile_picker_selects_a_saved_profile_on_the_active_conversation` (1/1), including OpenCode-format frontmatter import and picker selection/persistence. Other native profile-editor checks remain; The shared policy engine remains in place |
| D3 | Agent definition files | M | B4 | Core · Avalonia supports built-in Build/Plan primary agents switchable during Code tasks, Markdown profiles, a validated user profile editor, prompt/tool policies with wildcard matching, edit-path and command allow/deny globs, and model/temperature/step settings. It imports legacy and current V2 OpenCode Markdown profiles from the standard user and trusted-project folders, maps ordered wildcard, shell-command, read-path, and edit-path permissions without overriding Codev's project policy, and warns when a model preference is unsupported. Scoped read rules are checked for direct reads and filter list/search results before they reach the model; relative file candidates are normalized lexically before matching, and rooted or escaping paths cannot inherit a narrower directory allow. Regression tests verify that traversal normalizing into a nested explicit Deny remains denied by both the matcher and direct-read executor. Scoped rules also constrain automatically attached source excerpts, relevance-preflight candidate paths, and optional repo-map entries. An explicit empty filtered selection stays empty instead of falling back to unrestricted automatic context. Resource-scoped V2 `glob`/`grep` rules now map to bounded path-glob and regex-search tools, with requested patterns checked against ordered permission rules and read-path scope still filtering returned files. Path-scoped edit `ask` rules now reach per-proposal approval outside Auto while matching denies remain hard blocks; the shared Auto/project policy still governs asks in Auto. Resource-scoped V2 `task`/`subagent` rules now target specific installed profiles through isolated child worktrees; target denies are hard blocks, asks follow the Auto/project policy, and only root profiles with explicit task permission may delegate. Resource-scoped V2 skill rules filter each discovered skill by OpenCode skill-ID patterns, with deny hiding skills and ask checked when loading; resource-scoped custom-tool rules remain unsupported and are rejected with a warning. Headless UI tests reject invalid profile Markdown, save valid Markdown through the real store and verify reload, select a saved profile in the real picker while verifying active-conversation persistence and label updates, and switch Build/Plan from the picker and Ctrl+Shift+A in both directions. Persisted profile references use validated display names (including spaces); profile filenames remain short slugs. Portable tests assert Plan schemas omit edit, shell, MCP, delegation, and background operations for both Ollama and OpenAI; executor tests reject Plan edits and commands before project review or command approval. A Windows x64 preview smoke verified that a multi-word `Smoke QA` selection remains visible after restart. Current-source Windows/.NET 10 recheck on PR head `3ce4814` passed all 30 `AgentProfileCatalogTests` and `Code_task_profile_picker_selects_a_saved_profile_on_the_active_conversation` (1/1), including OpenCode-format frontmatter import and picker selection/persistence. Other native profile-editor checks remain; The shared policy engine remains in place |
| D4 | Hooks (formatter first) | M | B1 | Avalonia formatter hook implemented · general hooks remain Later; manual UI/security review pending |
| D5 | Subagents with child sessions | L | D3, section 3 worktrees | Later · Avalonia implements isolated child conversations, Orchestrator delegation, child diff review/merge, and missing-worktree recovery. Codev-managed file operations and Git history are isolated in per-child worktrees; shell commands still run with the user's account permissions and can affect paths or services outside the worktree. Child UI/status and delegation output disclose this boundary. Parallel worktree mutation is serialized, and creation/recovery disable checkout hooks, fsmonitor, and configured smudge/process filters; child merge suppresses hooks and refuses external merge drivers or checkout filters only when they apply to reviewed files (or when a changed `.gitattributes` could affect them). Git LFS/custom-filter files are consequently unexpanded during child checkout and this is reported to the user. Smudge filters are disabled with an empty command so checkout does not launch a replacement executable from PATH. Regression tests cover helper suppression, concurrency, atomic permission-policy inheritance, recovery, parent-stop scoping, and stopping one selected child without canceling siblings. Child mode and eligible rules are persisted in one update, so interruption cannot leave Auto active without inherited exact denies. **Current-checkout validation (2026-10-07, code head `415a171`):** the live Qwen3.6 `Live_orchestrator_starts_two_read_only_children_in_parallel_worktrees` test passed in 49 seconds, verifying two overlapping Ask children in distinct managed worktrees, exact fixture reads/results, and a clean parent Git tree. The two stop-scope regression tests passed 2/2, and the full Avalonia Release suite passed 56 tests with 12 opt-in live tests skipped. At PR #10 head `af41fc9` on 2026-10-08, focused local Windows .NET 10 Release runs passed all 11 `GitChildWorktreeManagerTests` and four `ChildDelegationTests`; the opt-in live Orchestrator/Qwen3.6 test was skipped because `CODEV_OLLAMA_LIVE_TESTS` was unset. Full OS-level shell confinement remains dependent on B7; packaged UI stop/cancel controls, native interaction with review/merge/recovery, and independent security review remain release gaps. D5's workflow is implemented ahead of phase 5; the remaining safety and manual-verification work is not complete. |
| D6 | MCP client | L | B1 | Core · Avalonia implemented for Ollama and OpenAI Code tasks (stdio and auto-detected Streamable HTTP with legacy SSE fallback, user settings, tool/prompt/resource/resource-template discovery and calls, untrusted results, per-project permissions); diagnostics persist per conversation. On 2026-10-01, the focused MCP suite passed 49/49 on Windows Release, including a cross-origin redirect regression proving custom environment-backed secret headers reach only the configured endpoint. The mock OAuth/PKCE integration covers browser callback, token exchange, authenticated MCP call, persistence, and refresh. Opt-in native-vault OAuth smoke now passes with Windows Credential Manager, Linux Secret Service, and macOS Keychain (CI [#36849825001](https://github.com/jay23606/codev/actions/runs/36849825001)); four-RID package/launch validation passed in [#36849824882](https://github.com/jay23606/codev/actions/runs/36849824882). Latest Avalonia UI plus portable CI passed on all three OSes in [#36853446126](https://github.com/jay23606/codev/actions/runs/36853446126), with four-RID packaging and launch in [#36853446114](https://github.com/jay23606/codev/actions/runs/36853446114). Live provider sign-in, native interactive macOS/Linux UI smoke, and independent security review remain; external server configuration and an optional global connection-history view remain future work; The shared-core implementation remains in place |
Expand Down
Loading