You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
schemaVersion: requirement-record.v1revision: R1status: needs-designpriority: P2productOwner: "@PeterGuy326"technicalOwner: "@waterbro-8"userOutcome: "A mem maintainer changes local ingestion behaviour once, in one core, instead of twice: the qoder transcript connector and the future put --watch daemon share walk, cursor, change-detection and report code, so #110 does not write a second state layer."requirements:
- REQ-001
- REQ-002
- REQ-003acceptanceCriteria:
- AC-001
- AC-002
- AC-003parent: nulldependencies:
- "https://github.com/bytefolk/mem/pull/108 (must merge first)"supersedes: []lastDecisionAt: null
User problem and observable outcome
Adjudicated on #110 (R2, D-4): #110 and #103 share an ingestion core, not a write surface. The core already exists in working form inside #103's connector, and everything in it was earned through review on PR #108 — a cursor that must not advance under --dry-run, truncate/rewrite detection, atomic cursor writes, per-file degradation on a 409 instead of aborting the run, and a run summary.
Concrete duplication cost if this is not done: put --watch would re-implement the same cursor store, the same state-root layout (cliStateRoot(), server/cmd/mem/cmds_ingest.go:104-112), the same failure-classification table and the same report vocabulary, in a second file, with a second set of edge-case tests, and the two copies would drift. Observable outcome: one internal package owns local ingestion mechanics; both call sites are thin.
Requirements
REQ-001: Extract the local ingestion core — deterministic recursive walk, per-path cursor store (atomic rename write, truncate/rewrite reset), stat-gate-then-hash change decision, cycle report aggregation, closed failure-code classification, and the --dry-run / --limit semantics — out of server/cmd/mem/cmds_ingest.go + qoder_checkpoint.go into a reusable internal package, preserving behaviour exactly.
REQ-002: Point the qoder connector at the core with no observable behaviour change: same memories payload shape, same Idempotency-Key derivation, same stdout summary, same cursor file format and location (existing users' cursors must remain readable).
REQ-003: Make the report and failure vocabulary explicit and shared, so feat(sync): put --watch one-way directory watch (minimal tier, carved from Phase 2 sync drive) #110 consumes names instead of inventing them: counts scanned / ingested / deduped / unchanged / changed / local_gone / failed, and failure codes auth / plan_quota / provider_timeout / network / read_denied / upload_rejected / root_missing / state_corrupt.
AC-002: Core-level fixtures pin the edge cases that review found: --dry-run writes neither a cursor nor a request; a rewritten-shrunk file resets its cursor; a 409 degrades one file and continues the rest; a corrupt cursor degrades to state_corrupt without blocking the run.
Open decisions for the owner at kickoff: package location (server/internal/ingest vs server/cmd/mem internal file) — must stay CLI-side, since both sinks are CLI-driven and the server has no knowledge of local paths; and whether cursors key on absolute path or on a path-plus-device id (symlinked roots).
User problem and observable outcome
Adjudicated on #110 (R2, D-4): #110 and #103 share an ingestion core, not a write surface. The core already exists in working form inside
#103's connector, and everything in it was earned through review on PR #108 — a cursor that must not advance under--dry-run, truncate/rewrite detection, atomic cursor writes, per-file degradation on a 409 instead of aborting the run, and a run summary.Concrete duplication cost if this is not done:
put --watchwould re-implement the same cursor store, the same state-root layout (cliStateRoot(),server/cmd/mem/cmds_ingest.go:104-112), the same failure-classification table and the same report vocabulary, in a second file, with a second set of edge-case tests, and the two copies would drift. Observable outcome: one internal package owns local ingestion mechanics; both call sites are thin.Requirements
--dry-run/--limitsemantics — out ofserver/cmd/mem/cmds_ingest.go+qoder_checkpoint.gointo a reusable internal package, preserving behaviour exactly.Idempotency-Keyderivation, same stdout summary, same cursor file format and location (existing users' cursors must remain readable).scanned/ingested/deduped/unchanged/changed/local_gone/failed, and failure codesauth/plan_quota/provider_timeout/network/read_denied/upload_rejected/root_missing/state_corrupt.Acceptance criteria
--dry-runwrites neither a cursor nor a request; a rewritten-shrunk file resets its cursor; a 409 degrades one file and continues the rest; a corrupt cursor degrades tostate_corruptwithout blocking the run.Non-goals and forbidden shortcuts
--watchbehaviour here; no fsnotify or any new dependency; no server-side ledger; no change to the memory payload or the file upload path.AGENTS.mdstep 4 forbids.Lifecycle, status, priority, blockers, and open decisions
@waterbro-8; independent reviewer: aCODEOWNERSowner (not the author).server/internal/ingestvsserver/cmd/meminternal file) — must stay CLI-side, since both sinks are CLI-driven and the server has no knowledge of local paths; and whether cursors key on absolute path or on a path-plus-device id (symlinked roots).Evidence plan
server/cmd/mem/qoder_checkpoint.go:37-79andcmds_ingest.go:115-262, and feat(sync): put --watch one-way directory watch (minimal tier, carved from Phase 2 sync drive) #110's D-4 ruling on this issue names it.Decisions
Revision history
需要 maintainer 打标(本账号无 label 写权限):建议
type:maintenance、area:cli、priority:p2、evidence:e2-source、status:needs-triage。