{"record":{"id":"fcbef06f5ccb8175","repo":"gastownhall/beads","slug":"worktree-comparison-target-observation-is-absent-o","errorCode":null,"errorMessage":"worktree comparison target observation is absent or invalid","messagePattern":"worktree comparison target observation is absent or invalid","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/worktreeremove/policy.go","lineNumber":205,"sourceCode":"\t}\n\tif facts.CommonDir != Matched {\n\t\treturn Plan{}, fmt.Errorf(\"target common git directory does not match repository\")\n\t}\n\tif facts.Status != Clean && facts.Status != Dirty {\n\t\treturn Plan{}, fmt.Errorf(\"worktree cleanliness observation is absent or invalid\")\n\t}\n\tif facts.ManagedIgnore != IgnoreAbsent && facts.ManagedIgnore != IgnoreManaged {\n\t\treturn Plan{}, fmt.Errorf(\"managed ignore observation is absent or invalid\")\n\t}\n\tif (facts.ManagedIgnore == IgnoreManaged) != (facts.ManagedIgnoreEntry != \"\") {\n\t\treturn Plan{}, fmt.Errorf(\"managed ignore cleanup identity is absent or invalid\")\n\t}\n\tif request.Mode != Force {\n\t\tif facts.Status != Clean {\n\t\t\treturn Plan{}, fmt.Errorf(\"worktree contains modified, untracked, or ignored files\")\n\t\t}\n\t\tif facts.Comparator != ComparatorAvailable && facts.Comparator != ComparatorMissing && facts.Comparator != ComparatorNotRequired {\n\t\t\treturn Plan{}, fmt.Errorf(\"worktree comparison target observation is absent or invalid\")\n\t\t}\n\t\tif facts.Comparator != ComparatorAvailable {\n\t\t\treturn Plan{}, fmt.Errorf(\"cannot verify unpushed commits: no comparison target is available\")\n\t\t}\n\t\tif facts.Containment != Contained && facts.Containment != NotContained && facts.Containment != ContainmentNotRequired {\n\t\t\treturn Plan{}, fmt.Errorf(\"worktree containment observation is absent or invalid\")\n\t\t}\n\t\tif facts.Containment != Contained {\n\t\t\treturn Plan{}, fmt.Errorf(\"worktree HEAD is not contained in the comparison target\")\n\t\t}\n\t} else if facts.Comparator != ComparatorNotRequired || facts.Containment != ContainmentNotRequired {\n\t\treturn Plan{}, fmt.Errorf(\"worktree force-mode comparison observations are inconsistent\")\n\t}\n\tplan := Plan{approved: true, mode: request.Mode, targetPath: facts.RegisteredPath}\n\tif facts.ManagedIgnore == IgnoreManaged {\n\t\tplan.managedIgnoreEntry = facts.ManagedIgnoreEntry\n\t}\n\treturn plan, nil","sourceCodeStart":187,"sourceCodeEnd":223,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/worktreeremove/policy.go#L187-L223","documentation":"Prepare rejects the request because mode is Normal but facts.Comparator holds an invalid value (not ComparatorAvailable, ComparatorMissing, or ComparatorNotRequired). The comparison-target observation is required in normal mode so the library can verify the worktree HEAD has been pushed; an absent observation fails closed.","triggerScenarios":"Calling Prepare with Mode: Normal and a zero-value or out-of-range Comparator, usually from an adapter that never resolved the upstream/comparison ref.","commonSituations":"Adapters that skip comparison resolution; tests omitting Comparator; enum drift after new ComparatorKind values.","solutions":["Populate facts.Comparator with ComparatorAvailable or ComparatorMissing from an actual upstream-ref check","Use ComparatorNotRequired only when the comparison is genuinely not applicable","In tests, set Comparator: worktreeremove.ComparatorAvailable alongside matching Containment"],"exampleFix":"// before\nfacts.Comparator = 0 // invalid zero value\n// after\nfacts.Comparator = worktreeremove.ComparatorAvailable // from upstream ref resolution","handlingStrategy":"validation","validationCode":"switch facts.Comparator {\ncase worktreeremove.ComparatorAvailable, worktreeremove.ComparatorMissing, worktreeremove.ComparatorNotRequired:\ndefault:\n\treturn fmt.Errorf(\"comparator not observed\")\n}","typeGuard":"func comparatorObserved(c worktreeremove.ComparatorKind) bool {\n\treturn c == worktreeremove.ComparatorAvailable || c == worktreeremove.ComparatorMissing || c == worktreeremove.ComparatorNotRequired\n}","tryCatchPattern":"plan, err := worktreeremove.Prepare(req, facts)\nif err != nil && strings.Contains(err.Error(), \"comparison target observation is absent\") {\n\treturn fmt.Errorf(\"adapter must resolve the comparison ref first: %w\", err)\n}","preventionTips":["Resolve the upstream/comparison ref in the adapter before Prepare","Validate all facts enums with a helper before calling Prepare","Pair Comparator with a matching Containment value in tests"],"tags":["worktree","git","validation"],"backgroundTag":"incomplete-observations","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}