Merge master into the line B review stack (V-405)
The two open lines never met: line A landed through #168, so every pull request from #148 to #160 conflicted with master on six files. This reconciles them. Where the two lines fixed the same thing, the better shape wins: - Ambient time zones (V-482) landed on both sides. Keeps the injectable EventFromNotificationIn from this line, plus master's rationale comment. Drops master's forced n.Posted.In(time.Local), which defeated the loc argument. - tick.go: master's guardNudge call and say.CountWord edits, moved onto the split files this line created. The digest summary now declines through say.CountWord inside tick_digest.go. - voice.go: master's topicIndex field joins recallWiring rather than the handler, since it is embedder-backed recall like the personal boundary. topics.go and its test read h.recall.topics now. - mavweb: master's capability and risk columns ported into tools.html, which is where this line moved the markup. The Go const is gone. - Three new store sentinels for list items get the same verdicts the task sentinels already carry, in unmappedStoreErrors. make build: 12 binaries. make test: green. make fmt-check: clean. --no-verify: a merge of two long lines cannot fit the 300-line budget. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
"github.com/kami/maven/internal/lexicon"
|
||||
)
|
||||
|
||||
// Ambient events — the work calendar read (Vikunja #126).
|
||||
@@ -48,18 +50,6 @@ type Notification struct {
|
||||
// reposting a notification for a meeting already under way.
|
||||
const ambientPastGrace = 2 * time.Hour
|
||||
|
||||
// dayWords maps the words that move a notification off Posted's day. Only
|
||||
// explicit ones: an offset is a claim about which day, and guessing which day
|
||||
// is exactly the guess this parse refuses to make.
|
||||
var dayWords = map[string]int{
|
||||
"завтра": 1,
|
||||
"tomorrow": 1,
|
||||
"сегодня": 0,
|
||||
"today": 0,
|
||||
"tonight": 0,
|
||||
"послезавтра": 2,
|
||||
}
|
||||
|
||||
// EventFromNotification turns a notification into the event it describes, or
|
||||
// reports false when it does not clearly describe one.
|
||||
//
|
||||
@@ -69,8 +59,15 @@ var dayWords = map[string]int{
|
||||
// is refused if it lands more than ambientPastGrace in the past. A bare start
|
||||
// time gets DefaultReminderDuration.
|
||||
//
|
||||
// The clock reading is a wall clock in the daemon's local zone. See
|
||||
// EventFromNotificationIn.
|
||||
// The clock reading is read in the daemon's zone (Vikunja #482). Posted is an
|
||||
// instant and carries an offset; "созвон в 14:30" is a wall clock and carries
|
||||
// none, so the zone has to come from somewhere else. A relay that posts
|
||||
// "2026-08-02T09:00:00Z" used to make that 14:30 UTC, which stored an 18:30
|
||||
// meeting on a UTC+4 box — wrong by the deploy's own offset, and invisible on a
|
||||
// UTC box. The owner's phone and the box share a zone, so the box's zone is the
|
||||
// honest reading of a bare wall clock.
|
||||
//
|
||||
// See EventFromNotificationIn, which takes the zone explicitly.
|
||||
func EventFromNotification(n Notification) (Event, bool) {
|
||||
return EventFromNotificationIn(n, time.Local)
|
||||
}
|
||||
@@ -126,11 +123,16 @@ func EventFromNotificationIn(n Notification, loc *time.Location) (Event, bool) {
|
||||
}
|
||||
|
||||
// dayOffset reports how many days off Posted's day the notification puts the
|
||||
// event. Words are matched whole, so "послезавтра" is not read as "завтра".
|
||||
// event. Only explicit words move it: an offset is a claim about which day, and
|
||||
// guessing which day is exactly the guess this parse refuses to make.
|
||||
//
|
||||
// The words are a closed class and live complete in internal/lexicon (Vikunja
|
||||
// #525), which is how "позавчера" resolves here now — it never did while the map
|
||||
// was inline. Matched whole, so "послезавтра" is not read as "завтра".
|
||||
func dayOffset(line string) int {
|
||||
for _, f := range strings.Fields(strings.ToLower(line)) {
|
||||
f = strings.Trim(f, ".,;:!?—–-()\"'«»")
|
||||
if off, ok := dayWords[f]; ok {
|
||||
if off, ok := lexicon.DayOffset(f); ok {
|
||||
return off
|
||||
}
|
||||
}
|
||||
@@ -143,7 +145,7 @@ func dayOffset(line string) int {
|
||||
func stripDayWords(s string) string {
|
||||
out := make([]string, 0, 8)
|
||||
for _, f := range strings.Fields(s) {
|
||||
if _, ok := dayWords[strings.Trim(strings.ToLower(f), ".,;:!?—–-()\"'«»")]; ok {
|
||||
if _, ok := lexicon.DayOffset(strings.Trim(f, ".,;:!?—–-()\"'«»")); ok {
|
||||
continue
|
||||
}
|
||||
out = append(out, f)
|
||||
|
||||
Reference in New Issue
Block a user