v5 data platform, Phase 6: two-step add-tool — identify in chat, research in the background - #38
Conversation
…he background The chat now only identifies. identify_tools writes pending_tools rows owned by the caller and renders an editable, selectable intake table; research_tool and propose_listing are gone, and create_tool is MCP-only and writes a Postgres draft. Research selected (N) starts researchBatch on the Workflow SDK: two steps per item (4 searches, then 4 fetches and link verification), a 240s abort, retryable vs fatal errors, and confidence computed in code. Admins review on /admin/intake and approve from /admin/intake/[id], behind the low-confidence gate. The 100-a-day limit counts a ledger (research_requests) under an advisory lock, so Research again costs again and concurrent presses cannot overshoot. Each item carries the request that owns it, so two runs never both pay for it. The daily cron fails abandoned research, expires identified items after 14 days and deletes discarded ones after 30. Migrations 0005 (pending_tools) and 0006 (research ledger). E2E scenario 5 stubs the model at the provider boundary and runs everything else for real. Gate: lint 0 errors, 163 files / 2131 tests, 68 Playwright, spec:coverage 0 undocumented, build green with every /admin route still Partial Prerender. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DNV63U6ERy45Gj2TThBfyC
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2a7901d98d
ℹ️ 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".
| if (row.status !== "researched" || row.duplicateResolution === "add_unit") { | ||
| throw new Refusal("not_editable"); | ||
| } |
There was a problem hiding this comment.
Block approval while a duplicate remains unresolved
When an admin edits the name or brand of an already researched item, updatePendingTool reruns duplicate detection and can attach a new match while clearing duplicateResolution to null, without changing the researched status. This condition rejects only add_unit, so the still-enabled approval path can immediately create a second catalogue tool without the required duplicate decision; also reject rows that have either duplicate ID with no resolution.
AGENTS.md reference: v5/AGENTS.md:L328-L339
Useful? React with 👍 / 👎.
| "actionCreateAnyway": "No, create a new tool", | ||
| "actionOpenDraft": "Open draft in Notion" | ||
| "actionOpenDraft": "Open draft in Notion", | ||
| "status": { |
There was a problem hiding this comment.
Update every locale alongside the new intake strings
This commit adds the new intake table, status, error, and admin-review copy only to en.json; none of the other 11 locale files changed, so users selecting those supported locales receive English throughout the new workflow via the fallback instead of localized UI. Add the corresponding keys to all message files as required by the repository convention.
AGENTS.md reference: AGENTS.md:L77-L85
Useful? React with 👍 / 👎.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DNV63U6ERy45Gj2TThBfyC
Stacked on #37 (Phase 5). Implements §5.4 of the data-platform spec; as-built details are in the 2026-09-23 amendment.
What changes
identify_tools(tools.add) createspending_toolsrows owned by the caller, attaches the turn's photos, runs the duplicate check (normalized name+brand, thenpg_trgm), and rendersIntakeTableCard: select all/some/none, inline edit viaPATCH /api/pending-tools/[id], and a required choice for each duplicate.research_toolandpropose_listingare removed.create_toolis MCP-only and writes a Postgres draft, which removes the last request-path Notion write.POST /api/pending-tools/researchchecks ownership (ortools.approve) and the limits (25 per request, 100 per person per day, counted from an append-only ledger under an advisory lock), then startsresearchBatchon the Workflow SDK:maxRetries = 2.Promise.allSettled./admin/intakepolls while research runs, and offers Retry, Discard and duplicate resolution for leftover items./admin/intake/[id]offers Approve, Approve as draft, Add unit, Research again and Discard, with the low-confidence gate ("I've checked this" + note). Approval is one transaction; it is audited (pending.approved,tool.published) and invalidates the catalogue.identifieditems after 14 days, deletes discarded items after 30 days, and releases their photos to the orphan sweep.pending_toolsis included in the backup.0005_pending_tools.sqland0006_research_ledger.sql.Tests
@workflow/vitesttest.e2e/intake.spec.ts) stubs the Anthropic API at the provider boundary. Everything else runs for real, including the workflow on the local world./tools/[id]and all/adminroutes are Partial Prerender).Before production
copyToPublic(turning a pending photo into a public blob) needs one manual check on a preview deploy.🤖 Generated with Claude Code
https://claude.ai/code/session_01DNV63U6ERy45Gj2TThBfyC