Skip to content

feat: add pluggable friction stores - #75

Merged
jxom merged 27 commits into
wevm:mainfrom
Slokh:kartik/pluggable-stores
Aug 4, 2026
Merged

feat: add pluggable friction stores#75
jxom merged 27 commits into
wevm:mainfrom
Slokh:kartik/pluggable-stores

Conversation

@Slokh

@Slokh Slokh commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Add pluggable friction stores through Store.from, Store.file, and Store.postgres, plus the class-free Frog.create API for embedded consumers.

The CLI keeps file storage by default and selects PostgreSQL through FROG_DATABASE_URL.

@vercel

vercel Bot commented Aug 4, 2026

Copy link
Copy Markdown

@Slokh is attempting to deploy a commit to the Wevm Team on Vercel.

A member of the Team first needs to authorize it.

@pkg-pr-new

pkg-pr-new Bot commented Aug 4, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/frog@75

commit: ec4ce5a

@Slokh
Slokh marked this pull request as ready for review August 4, 2026 00:35
@Slokh
Slokh marked this pull request as draft August 4, 2026 00:48
@Slokh
Slokh marked this pull request as ready for review August 4, 2026 01:21
@jxom

jxom commented Aug 4, 2026

Copy link
Copy Markdown
Member

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread src/cli/commands/resolve.ts Outdated
Comment thread src/PostgresStore.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread src/FrictionLog.ts Outdated
Comment thread src/FrictionLog.ts Outdated
Comment thread src/FrictionLog.ts Outdated
Comment thread src/PostgresStore.ts Outdated
Comment thread src/cli/commands/list.ts Outdated
Comment thread src/Entry.ts Outdated
@jxom jxom changed the title Add pluggable friction stores feat: add pluggable friction stores Aug 4, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread src/cli/commands/log.ts Outdated
Comment thread src/cli/commands/resolve.ts Outdated
@socket-security

socket-security Bot commented Aug 4, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​testcontainers/​postgresql@​12.0.41001007895100
Addedpostgres@​3.4.99910010081100

View full report

@socket-security

socket-security Bot commented Aug 4, 2026

Copy link
Copy Markdown

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.

Action Severity Alert  (click "▶" to expand/collapse)
Warn High
Obfuscated code: npm @protobufjs/float is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: pnpm-lock.yamlnpm/@testcontainers/postgresql@12.0.4npm/@protobufjs/float@1.0.2

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@protobufjs/float@1.0.2. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
Obfuscated code: npm yargs is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: pnpm-lock.yamlnpm/@testcontainers/postgresql@12.0.4npm/yargs@17.7.3

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/yargs@17.7.3. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread src/Store.ts
Comment thread src/cli/Cli.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread src/cli/commands/list.ts Outdated
Comment thread src/Store.ts
Comment thread src/cli/commands/log.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread src/Entry.ts Outdated
Comment thread src/Store.ts Outdated
Comment thread src/Store.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread src/cli/commands/sync.ts
Comment thread src/Entry.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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')

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

Comment thread src/cli/commands/list.ts
const { root } = await context.resolve({ cwd: c.options.cwd })
const store = c.var.store ?? Store.file({ root })

if (c.options.since && store.name !== 'file')

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

@jxom
jxom merged commit 5225ab5 into wevm:main Aug 4, 2026
6 of 7 checks passed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread src/Store.ts
Comment on lines +101 to +103
records:
value.records ??
(async () => (await value.read()).map((entry) => ({ entry, occurrences: 1 }))),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

Comment thread src/Store.ts
Comment on lines +479 to +483
WHEN existing.dedupe_key LIKE 'title:%' AND NOT EXISTS (
SELECT 1
FROM ${table} AS duplicate
WHERE duplicate.namespace = ${namespace}
AND duplicate.dedupe_key = ${titleKey}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

Comment thread src/cli/commands/log.ts
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)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

Comment thread src/Store.ts
async migrate() {
if (schema !== undefined) await sql`CREATE SCHEMA IF NOT EXISTS ${sql(schema)}`
await sql`
CREATE TABLE IF NOT EXISTS ${table} (

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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 👍 / 👎.

Comment thread src/Store.test.ts
return writeFile(Store.toPath(id), contents, root)
}

test('behavior: from derives optional operations for a custom store', async () => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants