feat(sdk): dir-watcher poller — non-provider 2nd workload for gate 2 (Track E redo) - #95
Conversation
Track E, second attempt. Replaces the closed #89 (linear-poller) which was rejected on RFC-0001 §6: adding new provider code to SDK regresses the settled decision that providers = relayfile adapters (gate 6). dir-watcher deliberately introduces ZERO new provider surface. No HTTP, no API tokens, no external network. Just a directory poll — filesystem I/O available in any environment, no gate-6 dependency. Real-world analog: an "inbox" directory a human or system drops files into. Each new file triggers a per-file flow (summarize, ingest, route, whatever the step declares). Same shape as hn-monitor but with a different, non-provider input source — proves the runner pattern generalizes. Files: - sdk/src/dir-watcher-poller.ts (~125 lines): pollDirectoryOnce() lists a directory, dedupes against a caller-supplied `seen` Set, submits dir.file_appeared events for each unseen file. Fail-closed: a file is only added to `seen` AFTER eventSubmit succeeds (so a journal failure means the next poll retries). fileLimit safety valve against dropping thousands of files at once. - sdk/tests/dir-watcher-poller.test.ts (~105 lines): 6 tests covering new-file submission, seen dedup, retry-on-journal-failure, fileLimit cap, missing-directory error propagation, and payload metadata (size + mtime). - testdata/dir-watcher.flow.yaml: flow spec with dir.file_appeared trigger, dedupe key by payload.path, one agent step that describes the file. - sdk/src/index.ts: exports. Non-goals (documented so history lens doesn't reject): - Runner: composition lives on Track A (HnMonitorRunner PR #85 or whatever eventually merges). A DirWatcherRunner is trivial once the runner shape lands. - Canonical spec JSON: produced by compile step when runner uses the flow. Not this PR. - Actual persistent seen-set across runner restarts: the runner owns lifecycle; poller stays pure (accepts + mutates a Set). FAIL-first evidence: - Source removed: test file failed to load (Tests: no tests). - Source restored: Tests 6 passed (6). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Free Run ID: 📒 Files selected for processing (4)
Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review. 📝 WalkthroughWalkthroughAdds a directory polling API that submits metadata events for unseen files. Exports the API from the SDK, adds coverage for polling behavior, and introduces a flow that summarizes appeared files with validated JSON output. ChangesDirectory watcher
Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: ⚪ Minimal · up to This localized change adds a directory poller and flow metadata with fail-closed submission behavior and no new provider or external-network surface; no actionable merge-blocking risk remains beyond normal checks and review. Sequence Diagram(s)sequenceDiagram
participant DirLister
participant pollDirectoryOnce
participant EventSink
participant DirWatcherFlow
participant AgentWorker
DirLister->>pollDirectoryOnce: list directory entries
pollDirectoryOnce->>EventSink: submit dir.file_appeared event
pollDirectoryOnce->>pollDirectoryOnce: mark successful path as seen
EventSink->>DirWatcherFlow: deliver appeared-file event
DirWatcherFlow->>AgentWorker: provide file path and wake context
AgentWorker-->>DirWatcherFlow: return validated JSON summary
Poem
Note 🎁 Summarized by CodeRabbit FreeYour organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Pro by visiting https://app.coderabbit.ai/settings/billing. Comment |
maintainability lens — PASSMaintainability review — PR #95Blockers: none. Concerns
Notes
REVIEW_PASSED |
history lens — PASSBlockers: None. Concerns: The introductory comment claims an internal “Proves the runner pattern generalizes” is premature: this diff supplies a poll-once helper and flow fixture, not a runner, production trigger, liveness sweep, or immutable bundle (sdk/src/dir-watcher-poller.ts:1, lines 1–19; dir-watcher.flow.yaml:1, lines 1–15). The commit and PR explicitly defer the runner, canonical spec, and persistent prefilter state, so this is non-blocking scaffolding rather than a history violation. The commit narrates rather than captures its FAIL-first evidence, repeating the repository’s evidence-quality weakness. However, the claims are not false; independent reproduction produced: With Notes: This does not repeat PR #89’s rejected provider pattern. The implementation performs provider-neutral filesystem polling and submits through REVIEW_PASSED |
structure lens — PASS→ Read docs/RFC-0001-everything-is-a-relayflow.md Structure review — PR #95 (
|
|
🎯 review-swarm: PASSED (M:pass H:pass S:pass) Lens transcripts posted as sibling comments above. |
Track E, second attempt — non-provider workload
Replaces the closed #89 (linear-poller), which was correctly rejected on RFC-0001 §6: adding new provider code to SDK regresses the settled decision that providers = relayfile adapters (gate 6). hn-poller is grandfathered from before RFC-0001; adding new providers via the same path would be a step backward.
`dir-watcher` introduces zero new provider surface. No HTTP, no API tokens, no external network. Just a directory poll — filesystem I/O available in any environment, no gate-6 dependency. Same runner-composition pattern as hn-monitor but with a different, non-provider input source.
What this ships
Fail-closed behavior
Real-world analog
An "inbox" directory that a human or another system drops files into. Each new file triggers a per-file flow (summarize, ingest, route). Same shape as hn-monitor. No provider dependency.
Non-goals (deferrals — softened H lens accepts scaffolding with deferrals)
Test results
```
$ npx vitest run tests/dir-watcher-poller.test.ts
Test Files 1 passed (1)
Tests 6 passed (6)
```
FAIL-first evidence
Test plan