feat(files): workspace file version history over the v2 API, CLI, and MCP - #7997
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
There was a problem hiding this comment.
All reported issues were addressed across 72 files
Tip: instead of fixing issues one by one fix them all with cubic
Re-trigger cubic
…arrow stored provenance status
0dd256a to
e43846c
Compare
|
@cubic-dev-ai review this PR |
@waleedlatif1 I have started the AI code review. It will take a few minutes to complete. |
There was a problem hiding this comment.
All reported issues were addressed across 76 files
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
|
@cubic-dev-ai review this PR |
@waleedlatif1 I have started the AI code review. It will take a few minutes to complete. |
There was a problem hiding this comment.
All reported issues were addressed across 76 files
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
|
@cubic-dev-ai review this PR |
@waleedlatif1 I have started the AI code review. It will take a few minutes to complete. |
There was a problem hiding this comment.
All reported issues were addressed across 76 files
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
There was a problem hiding this comment.
All reported issues were addressed across 76 files
You've manually re-run cubic several times on this PR. Each manual re-review checks the full PR again and counts toward your usage quota. To preserve your usage limits, we recommend letting cubic automatically review new commits.
Fix all with cubic | Re-trigger cubic
|
@cubic-dev-ai review this PR |
@waleedlatif1 I have started the AI code review. It will take a few minutes to complete. |
There was a problem hiding this comment.
All reported issues were addressed across 76 files
You've manually re-run cubic several times on this PR. Each manual re-review checks the full PR again and counts toward your usage quota. To preserve your usage limits, we recommend letting cubic automatically review new commits.
Fix all with cubic | Re-trigger cubic
|
@cubic-dev-ai review this PR |
@waleedlatif1 I have started the AI code review. It will take a few minutes to complete. |
There was a problem hiding this comment.
No issues found across 76 files
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
You've manually re-run cubic several times on this PR. Each manual re-review checks the full PR again and counts toward your usage quota. To preserve your usage limits, we recommend letting cubic automatically review new commits.
Re-trigger cubic
- read metadata and its current version in one statement; drop the retry and 409 - move provenance policy branching into the provenance module - project stored provenance out of list, head, and get reads; revert reads it on demand - chunk storage-cleanup enqueues to the outbox bulk limit in one place - drop the write-only content_updated_at version column (unreleased 0365) - reuse findCause, the shared cleanup batch constants, and the version-number primitives - share the v2 text presenter between the file and version routes
|
@cubic-dev-ai review this PR |
@waleedlatif1 I have started the AI code review. It will take a few minutes to complete. |
…-api # Conflicts: # .github/workflows/test-build.yml
|
@cubic-dev-ai review this PR |
@waleedlatif1 I have started the AI code review. It will take a few minutes to complete. |
|
@cubic-dev-ai review this PR |
@waleedlatif1 I have started the AI code review. It will take a few minutes to complete. |
There was a problem hiding this comment.
2 issues found across 83 files
Confidence score: 3/5
apps/sim/background/cleanup-file-versions.tscan process unbounded batches during one Trigger run because the 50-batch limit resets for each file and workspace chunk, potentially causing excessive runtime or resource usage—enforce a run-wide row or batch budget.apps/sim/lib/api/contracts/v2/openapi/files-audit.tsdocuments ten-minute write folding, but after five minutes of writer inactivity a collaborative or workflow write may create a new version sooner, producing unexpected audit-version splits—align the implementation and API contract, then add coverage for this timing case.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="apps/sim/lib/api/contracts/v2/openapi/files-audit.ts">
<violation number="1" location="apps/sim/lib/api/contracts/v2/openapi/files-audit.ts:450">
P3: After five minutes of writer inactivity, a collaborative or workflow write starts a new version even when the existing version is under ten minutes old. This description says all writes within ten minutes fold, so callers will mispredict version boundaries; document both coalescing cutoffs.</violation>
</file>
<file name="apps/sim/background/cleanup-file-versions.ts">
<violation number="1" location="apps/sim/background/cleanup-file-versions.ts:152">
P2: With enough candidate files, this job resets the 50-batch loop for each file and workspace chunk, so one Trigger run can process unbounded batches. Carry a run-wide row or batch budget and stop when it is exhausted.</violation>
</file>
You've manually re-run cubic several times on this PR. Each manual re-review checks the full PR again and counts toward your usage quota. To preserve your usage limits, we recommend letting cubic automatically review new commits.
Fix all with cubic | Re-trigger cubic
| for (const group of chunkArray(workspaceIds, DEFAULT_WORKSPACE_CHUNK_SIZE)) { | ||
| const candidates = await selectCandidateFileIds(group, cutoff, maxSuperseded) | ||
| for (const fileIds of chunkArray(candidates, FILES_PER_QUERY)) { | ||
| for (let batch = 0; batch < DEFAULT_MAX_BATCHES_PER_TABLE; batch++) { |
There was a problem hiding this comment.
P2: With enough candidate files, this job resets the 50-batch loop for each file and workspace chunk, so one Trigger run can process unbounded batches. Carry a run-wide row or batch budget and stop when it is exhausted.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/sim/background/cleanup-file-versions.ts, line 152:
<comment>With enough candidate files, this job resets the 50-batch loop for each file and workspace chunk, so one Trigger run can process unbounded batches. Carry a run-wide row or batch budget and stop when it is exhausted.</comment>
<file context>
@@ -0,0 +1,172 @@
+ for (const group of chunkArray(workspaceIds, DEFAULT_WORKSPACE_CHUNK_SIZE)) {
+ const candidates = await selectCandidateFileIds(group, cutoff, maxSuperseded)
+ for (const fileIds of chunkArray(candidates, FILES_PER_QUERY)) {
+ for (let batch = 0; batch < DEFAULT_MAX_BATCHES_PER_TABLE; batch++) {
+ const expired = await selectExpiredVersions(fileIds, cutoff, maxSuperseded)
+ if (expired.length === 0) break
</file context>
| operationId: 'listFileVersions', | ||
| summary: 'List File Versions', | ||
| description: | ||
| 'List the versions of a file, newest first by default. Each write that changes the bytes records one; identical rewrites do not. Collaborative edits within ten minutes fold into one version, as do repeated workflow writes by one author. Renames and moves are not versions. An empty file is version 1 until its first content replaces it. Retention keeps the newest ten and removes older versions by plan, so numbers can have gaps.', |
There was a problem hiding this comment.
P3: After five minutes of writer inactivity, a collaborative or workflow write starts a new version even when the existing version is under ten minutes old. This description says all writes within ten minutes fold, so callers will mispredict version boundaries; document both coalescing cutoffs.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/sim/lib/api/contracts/v2/openapi/files-audit.ts, line 450:
<comment>After five minutes of writer inactivity, a collaborative or workflow write starts a new version even when the existing version is under ten minutes old. This description says all writes within ten minutes fold, so callers will mispredict version boundaries; document both coalescing cutoffs.</comment>
<file context>
@@ -418,6 +440,216 @@ const declaredRoutes = [
+ operationId: 'listFileVersions',
+ summary: 'List File Versions',
+ description:
+ 'List the versions of a file, newest first by default. Each write that changes the bytes records one; identical rewrites do not. Collaborative edits within ten minutes fold into one version, as do repeated workflow writes by one author. Renames and moves are not versions. An empty file is version 1 until its first content replaces it. Retention keeps the newest ten and removes older versions by plan, so numbers can have gaps.',
+ errors: RESOURCE_ERRORS,
+ success: { description: 'A page of file versions.' },
</file context>
| 'List the versions of a file, newest first by default. Each write that changes the bytes records one; identical rewrites do not. Collaborative edits within ten minutes fold into one version, as do repeated workflow writes by one author. Renames and moves are not versions. An empty file is version 1 until its first content replaces it. Retention keeps the newest ten and removes older versions by plan, so numbers can have gaps.', | |
| 'List the versions of a file, newest first by default. Each write that changes the bytes records one; identical rewrites do not. Collaborative edits and repeated workflow writes by one author fold only while the current version is less than ten minutes old and has received a write within the last five minutes. Renames and moves are not versions. An empty file is version 1 until its first content replaces it. Retention keeps the newest ten and removes older versions by plan, so numbers can have gaps.', |
Summary
workspace_file_versiontable. Content writes were already copy-on-write, so the outgoing object is kept instead of deletedexpectedCurrentVersionprecondition), delete a superseded version. File metadata now returnscurrentVersioncleanup-file-versionsjob + cron route; free 30d / pro+team 180d / enterprise configurable (fileVersionRetentionHours, API-only for now), newest 10 versions always kept, free capped at 100 versions, and a 500-superseded-version ceiling enforced inline on writeType of Change
Testing
bun run lint,check:audits(OpenAPI/CLI/MCP generation in sync),check:api-validation:strict,check:migrations(new table only),turbo run type-checkall passChecklist