2026-02-16 11:45:36 +00:00
|
|
|
version: "2"
|
|
|
|
|
|
|
|
|
|
linters:
|
|
|
|
|
default: all
|
|
|
|
|
disable:
|
|
|
|
|
# TODO: Tweak for current project needs
|
|
|
|
|
- containedctx
|
|
|
|
|
- cyclop
|
|
|
|
|
- depguard
|
|
|
|
|
- dupword
|
|
|
|
|
- err113
|
|
|
|
|
- exhaustruct
|
|
|
|
|
- funcorder
|
|
|
|
|
- gochecknoglobals
|
feat(seahorse): implement short-term memory engine (LCM) (#2285)
* feat(seahorse): implement short-term memory engine of seahorse
Add pkg/seahorse/ module implementing a SQLite-backed DAG-based summary
hierarchy for context management, ported from lossless-claw's LCM design:
- types.go + short_constants.go: core types (Message, Summary, Conversation,
ContextItem) and configuration constants (fanout, token targets, thresholds)
- migration.go: idempotent DB schema with FTS5 trigram tokenizer for CJK
- store.go: full SQLite CRUD (conversations, messages, summaries DAG,
context_items with ordinal gap numbering, FTS5 search)
- short_engine.go: Engine lifecycle (NewEngine, Ingest, Assemble, Compact),
session pattern filtering (ignore/stateless glob→regex compilation),
per-session mutex via sync.Map
- short_assembler.go: budget-aware context assembly with fresh tail protection
(32 messages), oldest-first eviction, summary XML formatting, RebuildContextItems
- short_compaction.go: leaf compaction (messages→summary) and condensed
compaction (summaries→higher-level summary), 3-level LLM escalation,
CompactUntilUnder for emergency overflow
- short_retrieval.go: lookupByID, FTS5/LIKE search, recursive expand with
token cap
- context_seahorse.go: agent.ContextManager adapter, registered as "seahorse",
provider↔seahorse message type conversion (ToolCalls, tool_result)
* fix(seahorse): correct 3 adapter bugs in context management
- TokenCount: use full message (Content+ToolCalls+Media) instead of Content-only
- Empty Content: rebuild Content from tool_result Parts when stored empty
- Duplicate summaries: summaries only in Summary field, not in History messages
- Grep: fix SearchResult.Snippet→Content for summaries
- Schema: fix FTS5 SQL uses VIRTUAL TABLE not TEMP TABLE
- TestFTS5SQLConstants: verify FTS5 SQL syntax correctness
- Test: fix flaky TestCompactLeaf
* fix(agent): ingest steering messages into seahorse SQLite
Steering messages were only persisted to session JSONL but not ingested
into seahorse SQLite, causing them to be missing from context assembly.
Added `ts.ingestMessage(turnCtx, al, pm)` call in the steering message
injection block alongside the existing JSONL persistence.
Test: TestSeahorseSteeringMessageIngested verifies steering messages
appear in seahorse SQLite DB after being processed.
* fix(seahorse): address 3 blocking bugs from code review
- Fix resequenceContextItemsTx scan error handling (store.go:850)
Changed `return err` to `return scanErr` to properly propagate scan errors
instead of returning nil (which silently corrupts data)
- Fix sql.NullString for INTEGER column (store.go:847)
Changed `mid` from sql.NullString to sql.NullInt64 since message_id
is INTEGER in schema. Removed unnecessary strconv.ParseInt call.
- Fix compactCondensed fallback deleting non-candidate items
Added ReplaceContextItemsWithSummary method for per-item deletion
when candidates are not contiguous in ordinal space.
Optimized to use range deletion when candidates are consecutive.
* fix(seahorse): pass Budget to Compact for correct condensed threshold
Issue #4 from PR review: When Budget was not passed to seahorse.Compact,
it defaulted to `tokensBefore * 0.75`, making `tokensBefore > budget`
always true and causing condensed compaction to trigger unnecessarily.
Changes:
- context_seahorse.go: Forward Budget from CompactRequest to CompactInput
- loop.go: Pass Budget (ContextWindow) in all 3 Compact calls
- Add test verifying condensed is skipped when tokens < threshold
- Fix lint issues in store.go and store_test.go
* fix(seahorse): add mutex for assembler lazy initialization
Issue #5 from PR review: The check-then-create pattern for e.assembler
was a data race when multiple goroutines called Assemble() concurrently:
if e.assembler == nil {
e.assembler = &Assembler{...}
}
Changes:
- Add assemblerMu sync.Mutex to Engine struct
- Add initAssemblerOnce() using double-checked locking (same pattern as initCompactionOnce)
- Add TestAssemblerLazyInitRace to verify thread-safety
* fix(seahorse): handle non-consecutive depths in selectShallowestCondensationCandidate
Issue #8 from PR review: the loop iterated depth 0, 1, 2... assuming
consecutive keys, but break when key was missing caused deeper depths
to never be checked.
Fix: collect all existing depth keys, sort, then iterate in order.
* fix(seahorse): wrap DeleteMessagesAfterID and appendContextItems in transactions
- DeleteMessagesAfterID: wrap all DELETE operations in a transaction for
atomicity, remove redundant manual FTS delete (handled by trigger)
- appendContextItems: use transaction to fix read-then-write race condition
- Add GetMaxOrdinalTx and resolveItemTokenCountTx for transaction-scoped queries
- Remove unused resolveItemTokenCount function
Fixes PR review issues 6 and 7.
* fix(seahorse): derive readable content from Parts and cap CompactUntilUnder iterations
- Derive readable content from MessageParts in AddMessageWithParts so
FTS5 indexing and summary formatting can access tool call information
- formatMessagesForSummary and truncateSummary now fall back to Parts
when Content is empty, fixing blank summaries for Part-based messages
- Add MaxCompactIterations (20) to prevent CompactUntilUnder infinite
loops; exceeded iterations are logged as warnings
2026-04-05 01:05:16 +00:00
|
|
|
- gosmopolitan # Project legitimately uses CJK text in tests (FTS5, token counting)
|
2026-02-16 11:45:36 +00:00
|
|
|
- godot
|
|
|
|
|
- intrange
|
|
|
|
|
- ireturn
|
|
|
|
|
- nlreturn
|
|
|
|
|
- noctx
|
|
|
|
|
- noinlineerr
|
|
|
|
|
- nonamedreturns
|
|
|
|
|
- tagliatelle
|
|
|
|
|
- testpackage
|
|
|
|
|
- varnamelen
|
|
|
|
|
- wrapcheck
|
|
|
|
|
- wsl
|
|
|
|
|
- wsl_v5
|
2026-02-16 15:13:35 +00:00
|
|
|
|
|
|
|
|
# TODO: Disabled, because they are failing at the moment, we should fix them and enable (step by step)
|
|
|
|
|
- contextcheck
|
|
|
|
|
- embeddedstructfieldcheck
|
|
|
|
|
- errcheck
|
|
|
|
|
- errchkjson
|
|
|
|
|
- errorlint
|
|
|
|
|
- exhaustive
|
|
|
|
|
- forbidigo
|
|
|
|
|
- forcetypeassert
|
|
|
|
|
- funlen
|
|
|
|
|
- gochecknoinits
|
|
|
|
|
- gocognit
|
|
|
|
|
- goconst
|
|
|
|
|
- gocritic
|
|
|
|
|
- gocyclo
|
|
|
|
|
- godox
|
|
|
|
|
- gosec
|
|
|
|
|
- ineffassign
|
|
|
|
|
- lll
|
|
|
|
|
- maintidx
|
|
|
|
|
- mnd
|
|
|
|
|
- modernize
|
|
|
|
|
- nestif
|
|
|
|
|
- nilnil
|
|
|
|
|
- paralleltest
|
|
|
|
|
- perfsprint
|
|
|
|
|
- revive
|
|
|
|
|
- staticcheck
|
|
|
|
|
- tagalign
|
|
|
|
|
- testifylint
|
|
|
|
|
- thelper
|
|
|
|
|
- unparam
|
|
|
|
|
- usestdlibvars
|
|
|
|
|
- usetesting
|
2026-02-16 11:45:36 +00:00
|
|
|
settings:
|
2026-04-01 04:21:21 +00:00
|
|
|
gomoddirectives:
|
|
|
|
|
replace-allow-list:
|
|
|
|
|
- github.com/bwmarrin/discordgo
|
2026-02-16 11:45:36 +00:00
|
|
|
errcheck:
|
|
|
|
|
check-type-assertions: true
|
|
|
|
|
check-blank: true
|
|
|
|
|
exhaustive:
|
|
|
|
|
default-signifies-exhaustive: true
|
|
|
|
|
funlen:
|
|
|
|
|
lines: 120
|
|
|
|
|
statements: 40
|
|
|
|
|
gocognit:
|
|
|
|
|
min-complexity: 25
|
|
|
|
|
gocyclo:
|
|
|
|
|
min-complexity: 20
|
|
|
|
|
govet:
|
|
|
|
|
enable-all: true
|
|
|
|
|
disable:
|
|
|
|
|
- fieldalignment
|
|
|
|
|
lll:
|
|
|
|
|
line-length: 120
|
|
|
|
|
tab-width: 4
|
|
|
|
|
misspell:
|
|
|
|
|
locale: US
|
|
|
|
|
mnd:
|
|
|
|
|
checks:
|
|
|
|
|
- argument
|
|
|
|
|
- assign
|
|
|
|
|
- case
|
|
|
|
|
- condition
|
|
|
|
|
- operation
|
|
|
|
|
- return
|
|
|
|
|
nakedret:
|
|
|
|
|
max-func-lines: 3
|
|
|
|
|
revive:
|
|
|
|
|
enable-all-rules: true
|
|
|
|
|
rules:
|
|
|
|
|
- name: add-constant
|
|
|
|
|
disabled: true
|
|
|
|
|
- name: argument-limit
|
|
|
|
|
arguments:
|
|
|
|
|
- 7
|
|
|
|
|
severity: warning
|
|
|
|
|
- name: banned-characters
|
|
|
|
|
disabled: true
|
|
|
|
|
- name: cognitive-complexity
|
|
|
|
|
disabled: true
|
|
|
|
|
- name: comment-spacings
|
|
|
|
|
arguments:
|
|
|
|
|
- nolint
|
|
|
|
|
severity: warning
|
|
|
|
|
- name: cyclomatic
|
|
|
|
|
disabled: true
|
|
|
|
|
- name: file-header
|
|
|
|
|
disabled: true
|
|
|
|
|
- name: function-result-limit
|
|
|
|
|
arguments:
|
|
|
|
|
- 3
|
|
|
|
|
severity: warning
|
|
|
|
|
- name: function-length
|
|
|
|
|
disabled: true
|
|
|
|
|
- name: line-length-limit
|
|
|
|
|
disabled: true
|
|
|
|
|
- name: max-public-structs
|
|
|
|
|
disabled: true
|
|
|
|
|
- name: modifies-value-receiver
|
|
|
|
|
disabled: true
|
|
|
|
|
- name: package-comments
|
|
|
|
|
disabled: true
|
|
|
|
|
- name: unused-receiver
|
|
|
|
|
disabled: true
|
|
|
|
|
exclusions:
|
|
|
|
|
generated: lax
|
|
|
|
|
rules:
|
|
|
|
|
- linters:
|
|
|
|
|
- lll
|
|
|
|
|
source: '^//go:generate '
|
|
|
|
|
- linters:
|
|
|
|
|
- funlen
|
|
|
|
|
- maintidx
|
|
|
|
|
- gocognit
|
|
|
|
|
- gocyclo
|
|
|
|
|
path: _test\.go$
|
2026-02-24 13:52:25 +00:00
|
|
|
- linters:
|
|
|
|
|
- nolintlint
|
|
|
|
|
path: 'pkg/tools/(i2c\.go|spi\.go)$'
|
2026-02-16 11:45:36 +00:00
|
|
|
|
|
|
|
|
issues:
|
|
|
|
|
max-issues-per-linter: 0
|
|
|
|
|
max-same-issues: 0
|
|
|
|
|
|
|
|
|
|
formatters:
|
|
|
|
|
enable:
|
2026-02-18 19:48:23 +00:00
|
|
|
- gci
|
|
|
|
|
- gofmt
|
|
|
|
|
- gofumpt
|
2026-02-16 11:45:36 +00:00
|
|
|
- goimports
|
2026-02-18 19:48:23 +00:00
|
|
|
- golines
|
2026-02-16 11:45:36 +00:00
|
|
|
settings:
|
|
|
|
|
gci:
|
|
|
|
|
sections:
|
|
|
|
|
- standard
|
|
|
|
|
- default
|
|
|
|
|
- localmodule
|
|
|
|
|
custom-order: true
|
|
|
|
|
gofmt:
|
2026-02-16 15:13:35 +00:00
|
|
|
simplify: true
|
2026-02-16 11:45:36 +00:00
|
|
|
rewrite-rules:
|
|
|
|
|
- pattern: "interface{}"
|
|
|
|
|
replacement: "any"
|
|
|
|
|
- pattern: "a[b:len(a)]"
|
|
|
|
|
replacement: "a[b:]"
|
2026-02-16 15:13:35 +00:00
|
|
|
golines:
|
|
|
|
|
max-len: 120
|