diff --git a/ingestion/internal/api/handler.go b/ingestion/internal/api/handler.go index 3a8b75b..7156151 100644 --- a/ingestion/internal/api/handler.go +++ b/ingestion/internal/api/handler.go @@ -51,12 +51,13 @@ type queryRequest struct { } type writeRequest struct { - Content string `json:"content"` - Filename string `json:"filename,omitempty"` - Type string `json:"type,omitempty"` - Domain string `json:"domain,omitempty"` - Wing string `json:"wing,omitempty"` - Hall string `json:"hall,omitempty"` + Content string `json:"content"` + Filename string `json:"filename,omitempty"` + Type string `json:"type,omitempty"` + Domain string `json:"domain,omitempty"` + Wing string `json:"wing,omitempty"` + Hall string `json:"hall,omitempty"` + SourceType string `json:"source_type,omitempty"` // "external" opts a hall=facts entry out of the internal default } type ingestRequest struct { @@ -166,8 +167,16 @@ func writeHallNote(brainDir string, opts WriteNoteOptions) (string, error) { if opts.Domain != "" { fmt.Fprintf(&fm, "domain: %s\n", opts.Domain) } - if opts.SourceType != "" { - fmt.Fprintf(&fm, "source_type: %s\n", opts.SourceType) + sourceType := opts.SourceType + if sourceType == "" && opts.Hall == "facts" { + // Most hall=facts entries are first-party (an eval/benchmark the + // writer ran itself), not external claims — default to internal and + // require an explicit source_type: external opt-out for the rare + // citation-needing entry (brain-gardener#7). + sourceType = "internal" + } + if sourceType != "" { + fmt.Fprintf(&fm, "source_type: %s\n", sourceType) } fm.WriteString("---\n") @@ -232,12 +241,13 @@ func (h *Handler) Write(w http.ResponseWriter, r *http.Request) { return } relPath, err := WriteNote(h.brainDir, WriteNoteOptions{ - Content: req.Content, - Filename: req.Filename, - Type: req.Type, - Domain: req.Domain, - Wing: req.Wing, - Hall: req.Hall, + Content: req.Content, + Filename: req.Filename, + Type: req.Type, + Domain: req.Domain, + Wing: req.Wing, + Hall: req.Hall, + SourceType: req.SourceType, }) if err != nil { h.logger.Error("write failed", "err", err) diff --git a/ingestion/internal/api/handler_test.go b/ingestion/internal/api/handler_test.go index 3573942..b0b1917 100644 --- a/ingestion/internal/api/handler_test.go +++ b/ingestion/internal/api/handler_test.go @@ -137,7 +137,7 @@ func TestWriteNote_HallRouteIncludesSourceTypeWhenSet(t *testing.T) { assert.Contains(t, string(got), "wing: claude-sessions") } -func TestWriteNote_HallRouteOmitsSourceTypeWhenUnset(t *testing.T) { +func TestWriteNote_HallFactsDefaultsSourceTypeInternalWhenUnset(t *testing.T) { dir := t.TempDir() rel, err := api.WriteNote(dir, api.WriteNoteOptions{ @@ -147,6 +147,40 @@ func TestWriteNote_HallRouteOmitsSourceTypeWhenUnset(t *testing.T) { }) require.NoError(t, err) + got, err := os.ReadFile(filepath.Join(dir, filepath.FromSlash(rel))) + require.NoError(t, err) + // Most hall=facts entries are first-party (an eval/benchmark the agent ran + // itself), not external claims — default to internal, require explicit + // opt-out for the rare case that does need a citation (brain-gardener#7). + assert.Contains(t, string(got), "source_type: internal") +} + +func TestWriteNote_HallFactsPreservesExplicitExternalSourceType(t *testing.T) { + dir := t.TempDir() + + rel, err := api.WriteNote(dir, api.WriteNoteOptions{ + Content: "vendor pricing claim, needs a citation.\n", + Wing: "agentsquad", + Hall: "facts", + SourceType: "external", + }) + require.NoError(t, err) + + got, err := os.ReadFile(filepath.Join(dir, filepath.FromSlash(rel))) + require.NoError(t, err) + assert.Contains(t, string(got), "source_type: external") +} + +func TestWriteNote_HallRouteOmitsSourceTypeForNonFactsHalls(t *testing.T) { + dir := t.TempDir() + + rel, err := api.WriteNote(dir, api.WriteNoteOptions{ + Content: "a decision record.\n", + Wing: "agentsquad", + Hall: "decisions", + }) + require.NoError(t, err) + got, err := os.ReadFile(filepath.Join(dir, filepath.FromSlash(rel))) require.NoError(t, err) assert.NotContains(t, string(got), "source_type")