Workflow builder v0.2.0: SQLite tracking, sub-agent loops, check-work tiering#49
Conversation
… tiering Three new best practices for workflow design: - Pattern 3: Never loop over collections in orchestrator — spawn sub-agents per item - Pattern 3: Check-work tiering — cheap model checks if work exists, expensive model acts - Pattern 4: Split contextual state (markdown) vs tracking state (SQLite), ban JSON - Pattern 4: Schema versioning mechanism with per-workflow db-setup.md Contact steward migrated from processed.md to processed.db with schema versioning, legacy migration path, and automatic initialization for new installs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- schema_meta: Add PRIMARY KEY + CHECK constraint to prevent duplicate rows - Cleanup window: 90 days → 120 days to avoid race with 90-day scan window - SKILL.md: Pattern 4 no longer says inline SQL — schema lives in db-setup.md Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
SQLite has a built-in integer for version tracking in the database header. No extra table, no constraints, no duplicate row risks. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cae6baf8b1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
workflows/contact-steward/AGENT.md
Outdated
| Not in database and saved contact on platform? Check for enrichment (new messages | ||
| with contact-relevant info). If no new info, skip. e. Not a saved contact? |
There was a problem hiding this comment.
Add path for tracked contacts with new messages
Step 5 makes enrichment conditional on Not in database and saved contact, which leaves a gap for contacts that are already in processed.db and then receive new messages: they do not match the skip branch (no new messages), the retry branch (status error), or the enrichment branch (not in database). In that common case, the workflow has no explicit action and can miss enrichment updates after the first run.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Good catch. Fixed in bffd52e — step 5d no longer requires "not in database". Enrichment check now applies to all saved contacts with new messages regardless of DB state.
There was a problem hiding this comment.
Incorrect — the merged code handles this at step 5b: "If found, not an error, and no new messages since last_checked → skip." Contacts with new messages fall through to step 5d (enrichment check). The bot was reading an intermediate diff revision, not the final merged code.
| ## Target Schema (Current: Version 1) | ||
|
|
||
| ```sql | ||
| CREATE TABLE IF NOT EXISTS schema_meta (version INTEGER NOT NULL); |
There was a problem hiding this comment.
Seed schema_meta version on initial schema creation
The target schema creates schema_meta but does not insert an initial version row. Since runtime logic checks schema_meta.version to decide whether setup/migration is needed, fresh databases can return an empty result and never reach a stable "version matches" state. Add an idempotent seed insert for version 1 during initialization.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Stale — db-setup.md and schema_meta table were both removed. Schema is now inline in AGENT.md, versioning uses PRAGMA user_version (no extra tables).
There was a problem hiding this comment.
Incorrect — db-setup.md and the schema_meta table don't exist in the merged code. The final version uses PRAGMA user_version instead (set during creation at step 1 of the setup flow). Bot was commenting on an intermediate revision that was replaced before merge.
The LLM needs the schema in context to write queries — a separate file just adds a read with no savings. Schema, setup, and migration all live in AGENT.md now. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Step 5d previously required "not in database AND saved contact" — so contacts already in processed.db with new messages since last_checked had no explicit path. Now enrichment check applies to all saved contacts regardless of DB state. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
| - **user_version lower than current** → apply any needed ALTER TABLE changes for the new | ||
| version, then update user_version | ||
| - **`processed.md` exists (legacy)** → create the database, migrate entries from the | ||
| markdown file into the processed table, archive as `processed.md.migrated` |
There was a problem hiding this comment.
Platform files still reference processed.md not processed.db
High Severity
The AGENT.md migrates tracking state from processed.md to processed.db (SQLite), but the platform-specific files that the agent reads each run still reference processed.md. Specifically, platforms/whatsapp.md (lines 168, 210), platforms/imessage.md (line 199), and platforms/quo.md (line 120) all instruct the agent to "check processed.md" or "log in processed.md". Since these are instructions for an LLM agent, the conflicting references will cause the agent to look for or write to the wrong state file during platform scanning.
Additional Locations (1)
There was a problem hiding this comment.
Good catch — fixed in #51. All 4 stale processed.md references updated to processed.db.
Platform scanner flows still referenced `processed.md` after PR #49 migrated tracking state to `processed.db` (SQLite). Updated all 4 references across whatsapp.md, imessage.md, and quo.md. Caught by Cursor Bugbot. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>


Summary
db-setup.md.processed.mdtoprocessed.dbwith automatic initialization, legacy migration path, and schema upgrade detection.Test plan
processed.mdin contact-steward🤖 Generated with Claude Code