Commit Graph
618 Commits
Author SHA1 Message Date
QiuSW 151c426e54 test: isolate repeated auto-match scan regressions (#359) 2026-10-07 16:01:31 +08:00
QiuSW 95847a3f2d fix: resume bounded Shopee auto-match scans safely (#359) 2026-10-07 15:55:23 +08:00
QiuSW 6781b309d4 docs(#363): record production Web rollout and verification 2026-10-07 11:29:02 +08:00
QiuSW eb7cb6b5eb merge: default inner code list to 200 per page (#363) 2026-10-07 11:19:56 +08:00
QiuSW 845853c68a test(#363): verify page-local pagination and document default 2026-10-07 11:15:35 +08:00
QiuSW 955869b5f5 fix(#363): default inner code page size to 200 2026-10-07 11:09:26 +08:00
QiuSW 49de6f8045 merge: Android spec probe safety and truncated card handling (#361, #362) 2026-10-07 10:00:02 +08:00
QiuSW 279cb55847 docs: bind installed integrated Agent 0.9.69 (#362) 2026-10-06 18:03:31 +08:00
QiuSW 35119ea261 merge: retain #361 in #362 Android 0.9.69 installation build 2026-10-06 17:59:10 +08:00
QiuSW cb00194b0f docs: record independent spec card boundary (#362) 2026-10-06 17:57:41 +08:00
QiuSW 46b92dd6c5 docs: sync spec card dedup and prerequisite Wiki facts (#362) 2026-10-06 17:55:45 +08:00
QiuSW 1f5bab8192 fix(android): preserve independent cards under labelled groups (#362) 2026-10-06 17:54:50 +08:00
QiuSW 9a4495addd fix(android): deduplicate truncated same-card spec captions (#362) 2026-10-06 17:49:11 +08:00
QiuSW 75ab25658d docs: document spec probe diagnostics and safe verification (#361) 2026-10-06 17:19:19 +08:00
QiuSW a49dc696e9 fix(android): guard spec probe clicks and persist attempt diagnostics (#361) 2026-10-06 17:15:30 +08:00
QiuSWandClaude Opus 5.5 64f0e4941f merge: AGENTS worktree cleanup and SynapBus messaging rules
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 14:36:21 +08:00
QiuSWandClaude Opus 5.5 83af49b399 docs: require removing merged worktrees
One worktree per ticket under D:/OPC/goauto-worktrees/issue-<N>; runtime and release worktrees are excluded. After the branch is merged (and released if needed) the implementing agent removes it with git worktree remove after checking merged/clean/process/link state, never --force and never deleting branches.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 14:22:04 +08:00
QiuSWandClaude Opus 5.5 25d27b9194 docs: add SynapBus cross-project agent messaging rules
Document the local SynapBus service, per-tool identities (goauto, goauto_codex) and the #goauto channel, and the rule that agent messages are information, not authorization.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 14:22:00 +08:00
QiuSW e2a68b33ca docs(#358): record authorized production release 2026-10-06 11:27:34 +08:00
QiuSW e76de6fc08 merge(#358): fix SYB size-weight role recognition 2026-10-06 11:20:56 +08:00
QiuSW fb3efc929b docs(#358): record size-weight parsing contract 2026-10-06 11:18:02 +08:00
QiuSW a8233ecee1 fix(#358): recognize letter sizes with weight descriptions 2026-10-06 11:15:47 +08:00
QiuSW 955b34ad81 docs(#356): record online deployment and verification 2026-10-06 09:41:57 +08:00
QiuSW 0a79c83a95 merge(#356): support pasted purchase order filters 2026-10-06 09:33:41 +08:00
QiuSW b787473429 docs(#357): record authorized online migration and deployment 2026-10-05 18:16:19 +08:00
QiuSW 4567a24f05 merge(#357): add display-only SYB cancellation status 2026-10-05 17:59:23 +08:00
QiuSW 90e9fa7e79 docs(#357): document display-only cancellation status contract 2026-10-05 17:54:20 +08:00
QiuSW d6639a4a0d feat(#357): display SYB cancellation status without changing procurement 2026-10-05 17:51:07 +08:00
QiuSW 1858087a56 docs(#356): sync purchase order filter contract 2026-10-05 16:37:54 +08:00
QiuSW bb3990e432 feat(#356): support pasted purchase order filters 2026-10-05 16:33:38 +08:00
QiuSW e4d4a6fa79 docs(#355): record verified online release 2026-10-05 15:19:14 +08:00
QiuSW 1b4f7cd392 docs(#353): restore Chinese shop-filter contract 2026-10-05 15:07:58 +08:00
QiuSW ddc18f5370 merge(#353,#354,#355): integrate shop filter, pagination and list timeout 2026-10-05 15:02:12 +08:00
QiuSW 19060d2ce1 docs(#355): document list-only timeout budget 2026-10-05 14:52:09 +08:00
QiuSW a24c2068ef fix(#355): extend SYB product list timeout to 60 seconds 2026-10-05 14:50:22 +08:00
QiuSW 6752b149d8 feat(#353): filter SYB products by managed shops 2026-10-05 11:54:32 +08:00
QiuSW a38688cdd3 docs(#353): sync SYB shop filter contract 2026-10-05 11:51:55 +08:00
QiuSW c6c7fbe2d4 feat(#354): add top pagination to SYB products 2026-10-05 11:12:48 +08:00
QiuSW 1f3ce610b9 test(#352): verify additive source-time migration 2026-09-30 10:02:32 +08:00
QiuSW 31ff045e8c docs(#352): mirror SYB source-date API contract 2026-09-30 10:00:19 +08:00
QiuSW b4186a9228 docs(#352): mirror SYB source-time rules and architecture 2026-09-30 09:58:14 +08:00
QiuSW f9c48a018a fix(#352): filter SYB products by source stock created time 2026-09-30 09:46:57 +08:00
QiuSW bf06b2d500 Merge #348: distinguish absent reveal swipe targets 2026-09-29 18:03:52 +08:00
QiuSW fcb7dad878 docs: record reveal swipe result policy and version boundary (#348) 2026-09-29 17:52:32 +08:00
QiuSW 6550b9fd45 fix(android): skip reveal swipe without a scroll target (#348) 2026-09-29 17:43:46 +08:00
QiuSW 7a2c2d1eac merge: SYB excluded-product marking and recompute (#340) 2026-09-29 16:32:35 +08:00
QiuSW d01540b9fd fix(web): label SYB sync filter counts as hits (#340) 2026-09-29 16:31:54 +08:00
QiuSWandClaude Opus 5.5 ec010b42fc docs: SYB excluded-product marking and recompute contract (#340)
Mirrors of Wiki revisions Architecture-and-Code-Map 4bf8482e,
Business-Rules-and-Glossary c0b1a842, SYB-ERP-Interface-Contract 5979a142,
Android-Agent-API-Contract 92e9f856: filter hits are stored and marked
(first creation only), PDD isolation, 无需采购 stage position, purchaseType
list filter, recompute preview/execute with fingerprint and 409, hit vs
markedCount wording. SYB-ERP page also restores #343's unified-session
paragraph (was only in the mirror) and corrects the structure rule to #286's
single `-#` all-characters rule.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NTDbDcwbDw1TSAcE6wfh2F
2026-09-29 16:21:47 +08:00
QiuSWandClaude Opus 5.5 a56df9d908 fix(syb): #340 phase 4 — fingerprint includes rule evidence + MySQL IT
1. recomputeFingerprint now hashes a JSON-serialized (not naive string-
   concatenated, to avoid delimiter-collision) sorted list of
   {id, direction, ruleId, ruleKind, ruleKeyword} per planned change — the
   rule kind/keyword are exactly what gets written into
   excluded_rule_kind/excluded_rule_keyword, so a plan that affects the
   same ids/directions via a since-edited rule must now be rejected as
   stale, not silently accepted. New tests:
   TestRecomputeFingerprintChangesWhenRuleEvidenceChanges (edits the rule
   row directly between preview and execute, since the API has no edit
   endpoint, and asserts RECOMPUTE_PREVIEW_STALE with nothing written and
   no log row) and TestRecomputeFingerprintStableAcrossUnchangedPreviews
   (two previews of the same data yield the same fingerprint and execute
   succeeds).

2. New server/app/goauto/sybproductfilter/recompute_mysql_integration_test.go,
   gated on GOAUTO_IT_MYSQL_DSN (t.Skip when unset, so `go test` is
   unaffected normally). It creates a uniquely named throwaway database
   (zz_goauto_it_340_<ts>), migrates it, and drops it in t.Cleanup — never
   touches an existing database. Two real-MySQL, two-connection scenarios
   reproduce the exact race the phase-3 fix closes: connection A takes its
   REPEATABLE-READ snapshot via the planning step, connection B takes the
   row's FOR UPDATE lock and holds it (confirmed via a channel) while A's
   write phase is proven to actually block on that same lock (asserted via
   a wait window), B then inserts a purchase_task / active return_match
   and commits, and A is asserted to unblock, see it, and skip the row.
   Verified locally against the dev MySQL server (this session never
   printed the password: read via a shell one-liner into an env var,
   exported only for the go test invocation): both tests PASS with the
   phase-3 fix in place. Temporarily reverted purchaseTaskLockedQuery to a
   plain (non-locking) read (not committed) and reran —
   TestRecomputeConcurrentPurchaseTaskUnderRealMySQL correctly FAILED
   ("expected A to skip the row ... got {PDDToExcluded:1 SkippedHasTask:0}"),
   proving the test is meaningful; restored and diffed byte-identical
   against a backup before rerunning to confirm both tests pass again.
   Confirmed via `SHOW DATABASES LIKE 'zz_goauto_it_%'` (empty) that every
   throwaway database, across all these runs, was actually dropped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NTDbDcwbDw1TSAcE6wfh2F
2026-09-29 16:05:06 +08:00
QiuSWandClaude Opus 5.5 cd4bd6acb1 fix(syb): #340 phase 3 review — recheck reads must be locking, not plain
writeRecomputeChanges' purchase_task/return_match rechecks (added in the
previous phase 3 commit) used plain SELECT COUNT(*). On MySQL 8.4 under
REPEATABLE-READ, a plain read inside a transaction reuses the snapshot
taken at that transaction's first read (recomputeChanges' own SELECT), so
a purchase_task or return_match row committed by another connection AFTER
that snapshot was invisible to the recheck even after the syb_product row's
FOR UPDATE lock was granted — the row lock only serializes writers against
each other, it doesn't force a later plain read to see newer committed
data. Confirmed against a real local MySQL 8.4 server with two connections:
after the other transaction committed a task, plain COUNT(*) returned 0
while COUNT(*) ... FOR SHARE correctly returned 1. Every existing test
passed anyway because this package's tests run on SQLite, which has no
multi-connection snapshot isolation to reproduce the race at all.

Fix: both rechecks now use clause.Locking{Strength: "SHARE"} (a locking/
"current" read is enough since they only need to observe committed rows,
not lock them further). Split the three per-row queries (row FOR UPDATE,
purchase_task FOR SHARE, return_match FOR SHARE) into small query-builder
helpers (sybProductRowLockQuery / purchaseTaskLockedQuery /
returnMatchLockedQuery) so writeRecomputeChanges consumes them and a test
can independently assert their generated SQL.

New test: TestRecheckQueriesUseLockingReads opens a DryRun gorm session
against the MySQL dialector (mysql.New with SkipInitializeWithVersion,
DisableAutomaticPing — no real network connection is ever made) and pins
the exact SQL shape via db.ToSQL:
  SELECT * FROM `syb_product` WHERE id = 1 FOR UPDATE
  SELECT count(*) FROM `purchase_task` WHERE syb_product_id = 1 FOR SHARE
  SELECT count(*) FROM `return_match` WHERE syb_product_id = 1
    AND active_syb_product_id IS NOT NULL FOR SHARE
The test's own comment documents why SQLite cannot reproduce this race
(gorm's SQLite driver drops clause.Locking entirely; SQLite also has no
multi-connection REPEATABLE-READ snapshot semantics to begin with).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NTDbDcwbDw1TSAcE6wfh2F
2026-09-29 15:43:37 +08:00