| name | concave-parity |
| description | Skill: concave-parity |
| metadata | {"skiller":{"source":".agents/rules/concave-parity.mdc"}} |
Concave Parity
Contract
When the user asks for Concave parity, treat Convex behavior as the source of
truth for kitcn runtime contracts.
Do not hand-wave with "compatible enough."
Do not normalize a parity shift into "just how Concave works" if kitcn
already has a shim for it. Name the shift, point at the shim, and state the
delete condition.
If upstream Concave reaches parity, delete the bandaid. Do not keep fallback
sludge around for nostalgia.
Hard Rules
- Every Concave-specific workaround must be listed here with file locations.
- Every new Concave workaround needs a removal trigger.
- If you touch a listed bandaid, re-check whether upstream parity makes it
deletable right now.
- If the shift only affects repo tooling or scenarios, say that explicitly.
- If the shift is only observed and not patched, keep it in the watchlist, not
the bandaid section.
Active Bandaids
1. Local dev site-side 3211 proxy
Convex local dev shape in this repo:
- backend on
127.0.0.1:3210
- site URL on
127.0.0.1:3211
- frontend app on
localhost:3005 in prepared scenarios
Concave alpha.14 fixed the backend default to 3210, but it still does not
expose the site side on 3211.
kitcn workaround:
- start a local site proxy on
3211
- inject
CONVEX_SITE_URL=http://127.0.0.1:3211
- inject
SITE_URL from .env.local
Code locations:
packages/kitcn/src/cli/commands/dev.ts
resolveConcaveLocalDevContract(...)
resolveConcaveLocalSiteUrl(...)
startLocalSiteProxy(...)
packages/kitcn/src/cli/commands/dev.test.ts
tooling/scenarios.ts
DEFAULT_SCENARIO_READY_URL
readScenarioSiteUrl(...)
tooling/scaffold-utils.ts
- local env patching for
3005
Why it exists:
- prepared apps and auth wiring already assume the Convex-style split
- upstream still only exposes the backend side
Delete when:
- Concave local dev natively supports the same backend/site split contract, or
- kitcn no longer needs to emulate Convex local URLs for prepared apps
2. Startup retry loop for dev migration/backfill hooks
Convex dev startup usually accepts kitcn migration/backfill hooks
cleanly on first call.
Concave alpha.14 fixed concave run for internal runtime functions, but
startup can still race readiness.
kitcn workaround:
- Concave-only retry loop
- backoff:
1s, 2s, 4s
- show retry count only while retrying
Code locations:
packages/kitcn/src/cli/commands/dev.ts
runDevStartupRetryLoop(...)
- startup
migration up and aggregateBackfill kickoff callers
packages/kitcn/src/cli/commands/dev.test.ts
- related notes:
docs/solutions/integration-issues/concave-internal-runtime-calls-20260322.md
docs/solutions/integration-issues/concave-local-dev-auth-cycle-20260319.md
Why it exists:
- immediate
concave run calls can still hit ECONNREFUSED before local dev
is ready
Delete when:
- Concave local dev exposes a reliable readiness signal integrated into the CLI,
or
- startup hooks become reliably callable with no transient failures
3. Vite scenario backend/frontend split
Prepared Vite scenarios in this repo are supposed to prove:
- frontend on
3005
- backend on the kitcn local contract
Concave alpha.14 still auto-detects and starts Vite itself, which steals
frontend ownership and lands on 5173.
kitcn workaround:
- run backend dev with
--frontend no
- run the prepared Vite frontend separately
Code locations:
tooling/scenarios.ts
buildBackendOnlyDevCommand(...)
resolveScenarioDevCommands(...)
tooling/scenarios.test.ts
- related note:
docs/solutions/integration-issues/scenario-vite-dev-split-and-react18-runtime-20260322.md
Why it exists:
- scenario proof should validate the prepared app contract, not Concave's
auto-detected default frontend behavior
Delete when:
- Concave backend-only dev becomes unnecessary for prepared Vite scenarios, or
- Concave frontend auto-detection respects the prepared dev command/port with
no special handling
4. Generated auth runtime fallback for empty Concave internals
Convex-generated _generated/api.js exposes internal refs for generated auth
runtime calls.
Concave alpha.14 still leaves prepared auth apps with:
export const internal = {};
That breaks generated auth runtime access like authFunctions.findOne even
though the actual function paths are known.
kitcn workaround:
- synthesize generated auth internal refs from their function path names
- use
createGeneratedFunctionReference(...) instead of trusting Concave's
empty internal object
Code locations:
packages/kitcn/src/auth/generated-contract.ts
packages/kitcn/src/auth/generated-contract.test.ts
- related note:
docs/solutions/integration-issues/concave-alpha14-generated-auth-and-run-output-20260323.md
Why it exists:
- Concave local codegen/runtime shape is still missing generated auth internal
refs that Convex-generated output exposes
Delete when:
- Concave-generated
_generated/api.js includes generated auth internal refs,
and
- prepared auth scenarios no longer need synthesized fallback references
5. Concave run output JSON fallback parsing
Convex-style machine output is clean JSON when kitcn shells out to a
backend run command and expects structured results.
Concave alpha.14 now prints a human preamble before the JSON body, for example:
Running ...
Args: ...
URL: ...
Success
- pretty JSON
kitcn workaround:
- parse a trailing JSON block after the preamble
- keep the existing one-line JSON path for Convex and any future clean output
Code locations:
packages/kitcn/src/cli/backend-core.ts
packages/kitcn/src/cli/commands/migrate.test.ts
- related note:
docs/solutions/integration-issues/concave-alpha14-generated-auth-and-run-output-20260323.md
Why it exists:
- alpha.14 made
concave run human-friendlier but less machine-clean for the
startup migration and aggregate flows kitcn shells out to
Delete when:
concave run exposes clean JSON output by default or under a stable flag we
can rely on, and
parseBackendRunJson(...) no longer needs the trailing-block fallback
6. Manual static JWKS export command
Convex has an env CLI seam, so kitcn env push can fetch and sync static
JWKS.
Concave still has no equivalent upstream env command surface. That means auth
runtime parity exists, but env-management parity does not.
kitcn workaround:
- expose
kitcn auth jwks
- expose
kitcn auth jwks --rotate
- print a manual
JWKS=... payload instead of inventing fake env passthrough
Code locations:
packages/kitcn/src/cli/commands/auth.ts
packages/kitcn/src/cli/commands/auth.test.ts
packages/kitcn/src/cli/cli.ts
packages/kitcn/src/cli/cli.commands.ts
Why it exists:
- users still need a manual static
JWKS path on backend concave
kitcn env is correctly Convex-only today
Delete when:
- Concave exposes a stable env management seam kitcn can wrap directly, or
- kitcn ships a real cross-backend env abstraction and no longer needs a
JWKS-specific manual helper
Removed Bandaids
Internal runtime execution via /api/execute
Removed in alpha.14 verification.
Old workaround:
- bypass
concave run for generated/server:*
POST /api/execute
- call
_system:systemExecuteFunction
Why it died:
- raw
concave run now succeeds for generated/server:migrationRun and
generated/aggregate:aggregateBackfill
Forced 3210 dev port on Concave
Removed in alpha.14 verification.
Old workaround:
- always append
--port 3210 to concave dev when kitcn owned local
dev boot
Why it died:
- raw
concave dev now defaults to 3210
Source-backed Concave API type override
Removed in alpha.14 verification.
Old workaround:
- wait briefly after Concave codegen
- overwrite
_generated/api.d.ts with a source-backed version
Why it died:
- raw
concave codegen --static now emits the same api.d.ts shape our
override used to force
Watchlist: Known Gaps Without a kitcn Bandaid
staticDataModel mismatch
Current repo truth:
fixtures/next/convex.json sets codegen.staticDataModel: true
- Concave-generated
_generated/dataModel.d.ts is still dynamic
Current location:
.claude/skills/concave/concave.mdc
Meaning:
- treat this as an upstream parity gap
- do not silently document it as if Concave already matches Convex here
Read First
Start with the active bandaid seams:
packages/kitcn/src/cli/commands/dev.ts
tooling/scenarios.ts
Then read the solution notes:
docs/solutions/integration-issues/concave-local-dev-auth-cycle-20260319.md
docs/solutions/integration-issues/concave-internal-runtime-calls-20260322.md
docs/solutions/integration-issues/concave-alpha14-generated-auth-and-run-output-20260323.md
docs/solutions/integration-issues/scenario-vite-dev-split-and-react18-runtime-20260322.md
Verification
When touching any active Concave parity bandaid, run the smallest real gate
that proves the seam:
bun test packages/kitcn/src/cli/commands/dev.test.ts \
packages/kitcn/src/cli/commands/migrate.test.ts \
packages/kitcn/src/auth/generated-contract.test.ts \
tooling/scenarios.test.ts
bun run test:concave
bun run scenario:test -- next-auth
bun run scenario:test -- vite