feat: add pluggable friction stores - #75
Conversation
|
@Slokh is attempting to deploy a commit to the Wevm Team on Vercel. A member of the Team first needs to authorize it. |
commit: |
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 566a4b7528
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7fbbda0336
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2a6581df7e
ℹ️ 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".
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
Warning Review the following alerts detected in dependencies. According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 69ce3b2bde
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 29c402a23e
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8fca846b18
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 74b1d55db6
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b70df9246d
ℹ️ 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".
| const store = c.var.store ?? Store.file({ root }) | ||
|
|
||
| const entries = await attempt(Store.read({ root })) | ||
| if (store.name !== 'file') |
There was a problem hiding this comment.
Require the publish store to match
--cwd
When an embedded caller injects Store.file({ root: A }) but invokes publish --cwd B, this check accepts the store and reads entries from A, while publisher.file derives Git provenance from B and writes issue links through Store.write(..., { root: B }). Publishing can therefore file A's friction as if it belonged to B, create a second entry in B, and leave A's original pending; reject the command unless store.root === root, as the sync path already does.
AGENTS.md reference: AGENTS.md:L53-L53
Useful? React with 👍 / 👎.
| const { root } = await context.resolve({ cwd: c.options.cwd }) | ||
| const store = c.var.store ?? Store.file({ root }) | ||
|
|
||
| if (c.options.since && store.name !== 'file') |
There was a problem hiding this comment.
Bind
--since filtering to the file store's root
When an embedded caller injects Store.file({ root: A }) and runs list --since <ref> --cwd B, this name-only check permits the option, but records are read from A while Git.changedSince inspects B. The output then selects A's entries using IDs changed in an unrelated repository, so require the injected file store's root to equal the resolved command root before applying --since.
AGENTS.md reference: AGENTS.md:L53-L53
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ec4ce5a61b
ℹ️ 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".
| records: | ||
| value.records ?? | ||
| (async () => (await value.read()).map((entry) => ({ entry, occurrences: 1 }))), |
There was a problem hiding this comment.
Preserve counts for adapters with atomic logging
When a Store.from adapter implements the optional atomic log operation but omits records—a supported combination—log can return an occurrence count such as 4 while this fallback makes an immediate Frog.logs() report 1. Although the CLI now hides fallback counts for non-tracking stores, Frog.logs() still exposes them unconditionally, which is fresh evidence that the earlier fabricated-count issue remains for embedded consumers; require occurrence-aware adapters to provide records, or retain and derive the authoritative count.
AGENTS.md reference: AGENTS.md:L77-L77
Useful? React with 👍 / 👎.
| WHEN existing.dedupe_key LIKE 'title:%' AND NOT EXISTS ( | ||
| SELECT 1 | ||
| FROM ${table} AS duplicate | ||
| WHERE duplicate.namespace = ${namespace} | ||
| AND duplicate.dedupe_key = ${titleKey} |
There was a problem hiding this comment.
Serialize colliding title rewrites
When two existing logged rows are concurrently rewritten to the same previously unused normalized title, both statements can evaluate this NOT EXISTS predicate before either new key is visible and choose the same titleKey; the unique (namespace, dedupe_key) constraint then rejects one update with a raw uniqueness error. The earlier sequential-collision fix only handles a key already visible to the predicate, so this two-writer race is fresh evidence that collision handling remains incomplete; lock the competing key or retry with the per-entry key.
Useful? React with 👍 / 👎.
| const { config, repo, root } = await context.resolve({ cwd: c.options.cwd }) | ||
| const store = c.var.store ?? Store.file({ root }) | ||
| const interactive = prompt.interactive() | ||
| if (store.name === 'file' && store.root !== undefined && store.root !== root) |
There was a problem hiding this comment.
Normalize roots before enforcing equality
When --cwd names a relative directory outside a Git worktree, such as --cwd ./scratch, context.resolve returns that raw relative path while the default Store.file({ root }) converts it to an absolute path; this guard therefore rejects the command's own internally created store with STORE_ROOT_MISMATCH, preventing frog log from working there. The new equality guard is fresh evidence beyond the earlier injected-root findings; normalize the resolved root before constructing or comparing the store.
AGENTS.md reference: AGENTS.md:L53-L53
Useful? React with 👍 / 👎.
| async migrate() { | ||
| if (schema !== undefined) await sql`CREATE SCHEMA IF NOT EXISTS ${sql(schema)}` | ||
| await sql` | ||
| CREATE TABLE IF NOT EXISTS ${table} ( |
There was a problem hiding this comment.
Serialize first-time PostgreSQL migrations
When multiple processes create Frog instances for the same previously empty schema and log concurrently, each instance automatically enters migrate() and can reach this CREATE TABLE before the other's uncommitted table is visible. PostgreSQL's IF NOT EXISTS does not interlock that initial catalog lookup, so one cold-start request can fail during concurrent relation creation; serialize migration with a database advisory lock or otherwise make this first-use race retryable.
Useful? React with 👍 / 👎.
| return writeFile(Store.toPath(id), contents, root) | ||
| } | ||
|
|
||
| test('behavior: from derives optional operations for a custom store', async () => { |
There was a problem hiding this comment.
Group Store.from coverage under its function suite
Wrap this newly added Store.from behavioral test in describe('from', ...); leaving it at the file top level violates the repository's explicit per-export test-suite convention and makes function-level test selection and reporting inconsistent with the rest of this module.
AGENTS.md reference: AGENTS.md:L89-L90
Useful? React with 👍 / 👎.
Add pluggable friction stores through
Store.from,Store.file, andStore.postgres, plus the class-freeFrog.createAPI for embedded consumers.The CLI keeps file storage by default and selects PostgreSQL through
FROG_DATABASE_URL.