Skip to content

refactor(ingest): extract the shared local ingestion core (#111) - #217

Merged
waterbro-8 merged 4 commits into
mainfrom
refactor/111-shared-ingest-core
Sep 18, 2026
Merged

waterbro-8 merged 4 commits into
mainfrom
refactor/111-shared-ingest-core

Conversation

@waterbro-8

Copy link
Copy Markdown
Collaborator

Refs #111

Requirement and scope

Re-lands #147 onto current main as an organization branch. #129/#147 were closed under the 2026-09-03 fork-workflow decision, not as a judgment that the extraction was wrong. Blocker PR #108 is already merged.

Preserves qoder behaviour: same memories payload shape, same Idempotency-Key derivation for a canonical absolute root, same stdout summary, same cursor file format/location. Adds the OS-backed cursor lock from the #147 follow-up so concurrent writers do not share a .tmp name.

Changes

Validation ledger

ID Criterion Command Status
V1 Qoder tests with import-path changes go test ./cmd/mem -run Ingest NOT VERIFIED locally — host Go 1.22, module requires 1.25
V2 Core fixtures: dry-run, shrink-reset, 409 degrade, corrupt cursor go test ./internal/ingest NOT VERIFIED locally — same toolchain gap
V3 git diff --check local PASS
V4 No cobra/stdout in the core package source review of server/internal/ingest PASS

Independent review still required. No merge or issue close.

Original extraction: @waterbro-8. Cursor lock follow-up: @sun-970 / liyuanyang. Canonical-path identity follow-up: 勒布朗-詹姆斯.

@waterbro-8

Copy link
Copy Markdown
Collaborator Author

CI is green. I cannot approve or merge: I am the author. Needs @PeterGuy326 or @Bindy-lbb. Sequencing: land before any put --watch (#110).

@waterbro-8

Copy link
Copy Markdown
Collaborator Author

请评审合入(作者是我,不能自批)。

server/internal/ingest 抽出 walk/cursor/report,qoder 变薄封装,带 OS cursor lock。应在 put --watch#110)之前落地。CI 已绿。

需要 @PeterGuy326@Bindy-lbb 批准。

@PeterGuy326 PeterGuy326 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

REQUEST CHANGES: the current head 74e31a2 is not approvable yet. On macOS 14 arm64 with Go 1.25.9, the PR body V1 command go test ./cmd/mem -run Ingest -count=1 fails in TestIngestQoderPostsAndCheckpoints, TestIngestQoder409ConflictDegradesPerFile, TestIngestQoderLimitCheckpoint, and TestIngestQoderRelativeRootKeepsProjectSplit. The same command passes on the declared base 1b27aac, so this is a PR regression: the canonical /private/var versus /var path identity and checkpoint expectations are inconsistent. Please make the path contract platform-stable, rerun the documented macOS/Linux/Windows checks, and request re-review.

@PeterGuy326 PeterGuy326 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

APPROVE

独立复核当前 head dfae2c8

  • 原评审指出的 macOS canonical /private/var 与 fixture /var 不一致已修复:Qoder fixture 现在通过 ingest.CanonicalRoot 返回与实现相同的 source/cursor identity;业务实现未被放宽。
  • 当前 head 的 required CI 全绿,包含 Go、PostgreSQL integration、HTTP/CLI/MCP lifecycle、跨 Node 版本 wrapper、Windows audit、CodeQL 与安全基线;Go job 已通过 ingest 回归套件。
  • 已核对当前 diff、测试调用路径和 git diff --check 结论,没有新增 blocking finding。

LGTM。

@PeterGuy326
PeterGuy326 force-pushed the refactor/111-shared-ingest-core branch from dfae2c8 to 70bce9c Compare September 18, 2026 03:20
waterbro-8 and others added 4 commits September 18, 2026 11:43
`put --watch` (#110) would otherwise re-implement the same cursor store,
state-root layout, failure classification and report vocabulary that PR
drift. Move walk, cursor, change gate, `--dry-run` / `--limit` semantics,
per-file degradation and report aggregation into `server/internal/ingest`
and leave the connector as a thin call site that supplies the Qoder
parser, the memory payload and the HTTP upload.

Behaviour is preserved at the bytes level, not just by assertion:
memories request bodies, `Idempotency-Key` derivation, stdout summary,
stderr conflict warning, exit status and cursor file format and location
are identical before and after extraction on a shared fixture tree. The
PR #108 test suite passes with import-path changes only.

Refs #111
The connector used --root exactly as spelled, so the walk, the project/session
split and the cursor key disagreed whenever the root was relative or reached
through a symlink. Two working directories each holding sessions/p.jsonl shared
one cursor, and the second run saw an up-to-date checkpoint and posted nothing.
Canonicalize the root once and derive every identity from it.

Checkpoint saves staged through one shared <cursor>.tmp, so a second run could
fail on the name or rewind a cursor a faster run had already committed. Each
save now gets its own staging file and never moves a cursor backwards.

Failures now reach the classifier intact: the upload adapter keeps the typed API
error and the command maps exit codes at its own boundary, and the transport
check no longer runs ahead of the local-file checks that a syscall.Errno also
satisfies, so an unreadable source reports read_denied or root_missing instead of
network. A cycle that aborts while reading records the code it died on.
Add per-cursor advisory lock (flock on Unix, fcntl on AIX, LockFileEx on
Windows) that covers the read/merge/write sequence in SaveCursor. This
prevents concurrent ingest processes from regressing a cursor's LastLine
or colliding on a shared staging path.

The lock sidecar (<cursor>.json.lock) remains on disk after release; the
OS releases the advisory lock when the descriptor or owning process exits.

Refs #111
Refs #139
@PeterGuy326
PeterGuy326 force-pushed the refactor/111-shared-ingest-core branch from 70bce9c to 2041c3c Compare September 18, 2026 03:43

@PeterGuy326 PeterGuy326 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed current head 2041c3c. Required CI is green, including Go and PostgreSQL integration; the ingest fixture now uses the same canonical path normalization as production on macOS. No remaining blocker found.

@sun-970 sun-970 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review — Approve

Scope: #111 extract the shared local ingestion core.

Analysis

  1. Canonical path identity ✅ — ingest.CanonicalRoot resolves symlinks and relative paths to absolute canonical paths. Qoder fixture now uses the same normalization as production, fixing the macOS /private/var vs /var inconsistency that PeterGuy326 flagged.

  2. Cursor locking ✅ — New cursorLock provides advisory locking on cursor sidecars with platform-specific implementations (Unix, Windows, AIX). Lock file deliberately persists after release to avoid inode races.

  3. Backward compatibility ✅ — Cursor file format and location under ~/.mem/ingest/qoder unchanged for roots already given as canonical absolute paths. Relative or symlinked roots get new cursor keys (documented behavior change).

  4. Test coverage ✅ — Ingest tests cover upload errors, read failures, exit code mapping, relative root checkpoint separation, and project split. PeterGuy326 verified CI green on the latest head including macOS ingest regression suite.

  5. CI ✅ — Green across all required checks.

No blocking issues found.

@Bindy-lbb Bindy-lbb left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Independently reviewed current head 2041c3c. Checked the shared ingest core, Qoder connector, canonical-root identity, cursor persistence/locking across supported OS paths, error classification, and the added regression coverage. git diff --check is clean and all reported required CI checks are green, including Go and PostgreSQL integration. No blocking findings.

@waterbro-8
waterbro-8 merged commit f72e294 into main Sep 18, 2026
21 checks passed
@waterbro-8
waterbro-8 deleted the refactor/111-shared-ingest-core branch September 18, 2026 07:01
waterbro-8 added a commit that referenced this pull request Sep 18, 2026
…est (#139)

#217 already moved the OS lock into server/internal/ingest. Port the
remaining #191 review items onto that package: non-blocking flock /
LockFileEx, a 5s give-up, and a subprocess test that a contended lock
returns instead of blocking forever.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants