QwenPaw stores rewritten JSON session snapshots under workspace-scoped sessions directories, with a second one-level subdirectory namespace for console sessions. Moving it behind a concrete provider keeps those raw ID shapes explicit while continuing to use the shared file-source mechanics where they fit.
The provider preserves workspace project hints, root and console source lookup, hidden/deeper layout rejection, symlinked workspace discovery, content-hash fingerprinting, and force-replace parse semantics for rewritten session files.
fix(parser): prune qwenpaw source traversal
QwenPaw legacy discovery only walks valid workspace directories, the sessions directory, and one real non-hidden namespace below sessions. The provider migration reused the generic recursive JSONL walker, which preserved emitted source filtering but still allowed traversal and event classification through deeper or symlinked session namespaces.
Add a shared traversal predicate to the JSONL source helper so providers can keep discovery and changed-path classification aligned when their source layouts are narrower than an unbounded recursive scan.
test(parser): opt qwenpaw into provider shadow
QwenPaw now has a concrete facade provider on this branch, so its migration mode should enter shadow comparison instead of remaining legacy-only and additive.
Earlier provider opt-ins stay inherited and later branches own their modes.
Validation: go test -tags "fts5" ./internal/parser -run TestProviderMigrationModes -count=1; go test -tags "fts5" ./internal/parser -count=1; go vet ./...; git diff --check
test(sync): compare qwenpaw shadow parity
QwenPaw is shadow-compared on this branch, so add source-level migration coverage that compares provider observation with ParseQwenPawSession.
The test covers both root session files and console subdirectory session files so the path-derived workspace/session IDs and planned data-version behavior stay visible during review.
Validation: go test -tags "fts5" ./internal/parser ./internal/sync -run 'TestObserveProviderSourceMatchesQwenPawLegacyParser|TestQwenPawProvider|TestParseQwenPaw|TestSyncSingleSession_QwenPaw|TestWriteBatchQwenPaw' -count=1; go test -tags "fts5" ./internal/parser ./internal/sync -count=1; go fmt ./...; go vet ./...; git diff --check; ./custom-gcl run --config .golangci.nilaway.yml ./internal/parser/... ./internal/sync/...
refactor(parser): fold qwenpaw into provider
Move QwenPaw parse and source-lookup ownership onto the concrete
qwenPawProvider and delete the package-level legacy entrypoints
(DiscoverQwenPawSessions, FindQwenPawSourceFile, ParseQwenPawSession)
plus their unexported discovery/traversal helpers.
ParseQwenPawSession becomes the provider parseSession method, and the
rawID resolution from FindQwenPawSourceFile moves onto the provider as
sourceFileForRawID with its traversal guard. The provider's existing
JSONLSourceSet already reproduces workspace/sessions/console discovery,
symlink handling, and hidden-subdir pruning, so the legacy
DiscoverQwenPawSessions free function is dropped entirely.
Route QwenPaw sync classification and processing through the
provider-neutral runtime by removing its legacy engine dispatch: the
classifyOnePath workspace/sessions block, the processFile case arm, and
the processQwenPaw method. The provider's SourcesForChangedPath and
forceReplace-on-parse capability preserve changed-path remapping and the
full-rewrite write semantics the legacy path provided.
Make QwenPaw provider-authoritative in the migration manifest, drop its
AgentDef DiscoverFunc/FindSourceFunc hooks, remove it from the pending
shim scan list, and replace the shadow-baseline test with provider API
coverage plus a guard that the legacy symbols stay gone.
To preserve single-session resync parity, FindSource now resolves a
DB-stored file_path that points outside any configured QWENPAW_DIR by
synthesizing a source from the path's implicit
<root>/<workspace>/sessions/ layout, recovering the workspace as
ProjectHint so a reparse keeps the canonical qwenpaw:<workspace>:<stem>
ID instead of orphaning it under an empty workspace.
fix(parser): thread ctx through qwenpaw source lookups
QwenPaw now has a concrete provider facade for its workspace-scoped JSON session snapshots under sessions/ and the one-level console-style sessions subdirectory.
The provider preserves workspace project hints, root and subdirectory raw-ID lookup, hidden/deeper layout rejection, symlinked workspace discovery, content-hash fingerprinting, changed-path classification for rewritten JSON files, and force-replace parse semantics for full session snapshot rewrites. Discovery and live changed-path classification now share the same pruned traversal policy so QwenPaw does not rely on an unbounded recursive root scan or follow symlinked session namespaces below sessions/.