Sync MCP surface to SPEC §7 process model
Rename list_children/read_output/kill/send_message_to to their SPEC §7 process_id-shaped names; drop report_to_parent (direction inferred by send_message) and policy_check (replaced by per-project trust gating). Add the SPEC's missing tools: start_process, restart_process, close_process, rename_process, select_process, get_process_status, get_project_status, get_process_raw_output, search_output, get_process_ports, whoami, help. Process model now distinguishes agent/terminal/command kinds with opaque p_<6hex> IDs. Command entries are session-persistent so they survive PTY exit and can be Restart'd. Status enum gains starting and stopped. screen_version, port detection, and bracketed-paste send_input land alongside. Trust gating (internal/trust) replaces the regex policy: command-preset spawns return needs_trust on first use; the user confirms in a status-line modal and the grant persists to \$XDG_DATA_HOME/patterm/projects/<key>/trust.json. Tests cover send_message direction inference (parent↔child, sibling rejection, nil caller paths) and trust grant persistence across reopen.
This commit is contained in:
61
internal/trust/trust_test.go
Normal file
61
internal/trust/trust_test.go
Normal file
@@ -0,0 +1,61 @@
|
||||
package trust
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestStoreGrantPersists(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
t.Setenv("XDG_DATA_HOME", dir)
|
||||
|
||||
s1, err := Open("projkey")
|
||||
if err != nil {
|
||||
t.Fatalf("open: %v", err)
|
||||
}
|
||||
if s1.IsTrusted("vitest") {
|
||||
t.Fatalf("fresh store should not trust anything")
|
||||
}
|
||||
if err := s1.Grant("vitest"); err != nil {
|
||||
t.Fatalf("grant: %v", err)
|
||||
}
|
||||
if !s1.IsTrusted("vitest") {
|
||||
t.Fatalf("grant didn't take effect")
|
||||
}
|
||||
|
||||
// Re-open and confirm persistence.
|
||||
s2, err := Open("projkey")
|
||||
if err != nil {
|
||||
t.Fatalf("reopen: %v", err)
|
||||
}
|
||||
if !s2.IsTrusted("vitest") {
|
||||
t.Fatalf("grant did not persist across reopen")
|
||||
}
|
||||
if s2.IsTrusted("bun-dev") {
|
||||
t.Fatalf("unrelated preset should not be trusted")
|
||||
}
|
||||
|
||||
// Verify the file exists at the expected path.
|
||||
if _, err := os.Stat(s2.Path()); err != nil {
|
||||
t.Fatalf("stat trust.json: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreRevokeWithoutGrantIsNoop(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
t.Setenv("XDG_DATA_HOME", dir)
|
||||
|
||||
s, err := Open("projkey")
|
||||
if err != nil {
|
||||
t.Fatalf("open: %v", err)
|
||||
}
|
||||
if err := s.Revoke("never-granted"); err != nil {
|
||||
t.Fatalf("revoke noop should succeed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreOpenRequiresProjectKey(t *testing.T) {
|
||||
if _, err := Open(""); err == nil {
|
||||
t.Fatalf("open with empty project key should fail")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user