package walking_skeleton_test import ( "errors" "testing" "git.cin.su/m/Assistant/contracts/authority" "git.cin.su/m/Assistant/contracts/identity" situationcontract "git.cin.su/m/Assistant/contracts/situation" workcontract "git.cin.su/m/Assistant/contracts/work" situation "git.cin.su/m/Assistant/modules/situation/domain" work "git.cin.su/m/Assistant/modules/work/domain" "git.cin.su/m/Assistant/platform/ids" ) func TestWS001FocusIsolationPreventsWrongProjectMutation(t *testing.T) { actor := identity.ActorID(ids.ID("actor")) scope := authority.ScopeID(ids.ID("scope")) project := situationcontract.ProjectID(ids.ID("same-repository")) goalA := workcontract.GoalID(ids.ID("goal-a")) goalB := workcontract.GoalID(ids.ID("goal-b")) bindings := []situationcontract.FocusBinding{ {ID: situationcontract.FocusBindingID(ids.ID("focus-a")), ActorID: actor, SessionID: situationcontract.SessionID(ids.ID("session-a")), Workspace: situationcontract.WorkspaceID(ids.ID("worktree-a")), ProjectID: project, GoalID: goalA, ScopeID: scope, Active: true}, {ID: situationcontract.FocusBindingID(ids.ID("focus-b")), ActorID: actor, SessionID: situationcontract.SessionID(ids.ID("session-b")), Workspace: situationcontract.WorkspaceID(ids.ID("worktree-b")), ProjectID: project, GoalID: goalB, ScopeID: scope, Active: true}, } resolver := situation.NewResolver(bindings) store := work.NewStore([]work.Task{ {ID: workcontract.TaskID(ids.ID("task-a")), GoalID: goalA, ScopeID: scope, Revision: 1}, {ID: workcontract.TaskID(ids.ID("task-b")), GoalID: goalB, ScopeID: scope, Revision: 1}, }) // The identical phrase is intentionally not supplied to resolution: runtime // session/workspace bindings, including two worktrees of one repository, // are the only project-selection inputs. focusA, err := resolver.Resolve(situationcontract.RuntimeBinding{SessionID: bindings[0].SessionID, Workspace: bindings[0].Workspace}) if err != nil { t.Fatal(err) } focusB, err := resolver.Resolve(situationcontract.RuntimeBinding{SessionID: bindings[1].SessionID, Workspace: bindings[1].Workspace}) if err != nil { t.Fatal(err) } if focusA.GoalID == focusB.GoalID { t.Fatal("two worktrees resolved to the same goal") } wrongTarget := workcontract.TaskTarget{TaskID: workcontract.TaskID(ids.ID("task-b")), GoalID: goalB, ScopeID: scope, Revision: 1} if err := situation.ValidateTaskTarget(focusA, wrongTarget); !errors.Is(err, situation.ErrTargetMismatch) { t.Fatalf("wrong cognition target error = %v, want ErrTargetMismatch", err) } targetA := workcontract.TaskTarget{TaskID: workcontract.TaskID(ids.ID("task-a")), GoalID: goalA, ScopeID: scope, Revision: 1} if err := situation.ValidateTaskTarget(focusA, targetA); err != nil { t.Fatal(err) } committed, err := store.Commit(targetA) if err != nil { t.Fatal(err) } if committed.Revision != 2 { t.Fatalf("revision = %d, want 2", committed.Revision) } if _, err := store.Commit(targetA); !errors.Is(err, work.ErrRevisionConflict) { t.Fatalf("stale revision error = %v, want ErrRevisionConflict", err) } if _, err := store.Commit(wrongTarget); err != nil { t.Fatalf("other context must retain its original revision: %v", err) } } func TestWS001RejectsStaleAndAmbiguousFocusWithoutMutation(t *testing.T) { runtime := situationcontract.RuntimeBinding{SessionID: situationcontract.SessionID(ids.ID("session")), Workspace: situationcontract.WorkspaceID(ids.ID("workspace"))} stale := situation.NewResolver([]situationcontract.FocusBinding{{SessionID: runtime.SessionID, Workspace: runtime.Workspace, Active: false}}) if _, err := stale.Resolve(runtime); !errors.Is(err, situation.ErrStaleFocus) { t.Fatalf("stale error = %v, want ErrStaleFocus", err) } ambiguous := situation.NewResolver([]situationcontract.FocusBinding{ {ID: situationcontract.FocusBindingID(ids.ID("one")), SessionID: runtime.SessionID, Workspace: runtime.Workspace, Active: true}, {ID: situationcontract.FocusBindingID(ids.ID("two")), SessionID: runtime.SessionID, Workspace: runtime.Workspace, Active: true}, }) if _, err := ambiguous.Resolve(runtime); !errors.Is(err, situation.ErrAmbiguousFocus) { t.Fatalf("ambiguity error = %v, want ErrAmbiguousFocus", err) } }