Skip to content

feat(projects): doc-review stamp store + routes (#1802 slice 3)#1834

Closed
jaylfc wants to merge 2 commits into
devfrom
feat/docreview-stamp-store
Closed

feat(projects): doc-review stamp store + routes (#1802 slice 3)#1834
jaylfc wants to merge 2 commits into
devfrom
feat/docreview-stamp-store

Conversation

@jaylfc

@jaylfc jaylfc commented Jul 15, 2026

Copy link
Copy Markdown
Owner

Part of #1802 (document-review-surface). Slice 3: per-document doc-review stamp store, project-scoped agent-token gated routes, desktop stamp badge, and tests.

  • tinyagentos/projects/doc_review_store.py: review_state machine (awaiting_review/approved/changes_requested) with actor recording and timestamps.
  • tinyagentos/routes/project_doc_review.py: PUT/GET /api/projects/{project_id}/doc-review/{doc_path}, agent-scope gated writes, 409 on invalid transitions.
  • Wired in tinyagentos/app.py beside the other projects stores; router registered in tinyagentos/routes/__init__.py.
  • tinyagentos/auth_middleware.py: allow agent bearer tokens to reach the doc-review routes.
  • desktop/src/apps/FilesApp.tsx + desktop/src/lib/projects.ts: stamp badge column and typed API client.
  • tests/test_doc_review.py: state machine, actor recording, 409s, agent-scope gating.

DO NOT MERGE

Summary by CodeRabbit

  • New Features

    • Added document review statuses for files within projects: Awaiting review, Approved, and Changes requested.
    • Review badges now appear in both grid and list views, with a dedicated Review column in list view.
    • Added support for viewing, updating, and filtering document review statuses.
    • Authorized project-scoped agents can manage reviews while access remains restricted to their permitted project.
  • Bug Fixes

    • Improved error messages when emptying the workspace trash fails.

Add per-document review_state machine (awaiting_review/approved/changes_requested)
with actor recording and timestamps, project-scoped agent-token gated routes, and
the desktop stamp badge column plus typed API client.

Docs-Reviewed: doc-review stamp store + routes slice per document-review-surface.md
@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@jaylfc, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 52 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 1c9c122e-2086-4fb0-905a-275d3a4f76b2

📥 Commits

Reviewing files that changed from the base of the PR and between 83b6baf and 0de7099.

📒 Files selected for processing (2)
  • desktop/src/apps/FilesApp.tsx
  • desktop/src/lib/projects.ts
📝 Walkthrough

Walkthrough

Adds project-scoped document review persistence and authenticated API routes, then displays review badges for project files in the desktop file browser. Store, route, authorization, lifecycle, client API, and UI behavior receive test coverage.

Changes

Project document review

Layer / File(s) Summary
Review storage and app lifecycle
tinyagentos/projects/doc_review_store.py, tinyagentos/app.py
Adds SQLite-backed review records, valid state transitions, actor timestamps, listing/deletion operations, and application lifecycle management.
Review routes and authorization
tinyagentos/routes/project_doc_review.py, tinyagentos/routes/__init__.py, tinyagentos/auth_middleware.py
Adds read, list, and update endpoints for document reviews, owner or scoped-agent authorization, registry-JWT route allowlisting, and HTTP error mappings.
Desktop review status display
desktop/src/lib/projects.ts, desktop/src/apps/FilesApp.tsx
Adds review API types and methods, fetches states for project navigation, and renders review badges in grid and list views.
Store and route coverage
tests/test_doc_review.py
Tests state transitions, actor metadata, persistence operations, route responses, authentication, project binding, and scope enforcement.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant FilesApp
  participant AuthMiddleware
  participant project_doc_review
  participant DocReviewStore
  FilesApp->>AuthMiddleware: Fetch project review states
  AuthMiddleware->>project_doc_review: Authorize review route
  project_doc_review->>DocReviewStore: list_reviews(project_id)
  DocReviewStore-->>project_doc_review: Review records
  project_doc_review-->>FilesApp: Review state items
  FilesApp->>FilesApp: Render file review badges
Loading

Possibly related PRs

  • jaylfc/taOS#710: Both changes modify registry JWT and session route authorization in auth_middleware.py.
  • jaylfc/taOS#1825: Both changes extend bearer-token route allowlists in AuthMiddleware.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately highlights the main change: adding doc-review store support and routes for projects.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/docreview-stamp-store

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gitar-bot

gitar-bot Bot commented Jul 15, 2026

Copy link
Copy Markdown

Gitar is working

Gitar

…ts.ts types

- Add ReviewBadge component with onClick support for cycling review state
- Add cycleDocReview callback for in-place state transitions
- Wire badge into FileRow (list view) and grid cards (project: locations only)
- Fetch review states on project-location navigation via projectsApi.docReviews.list
- Remove duplicate DocReviewState/DocReview type definitions from projects.ts
- Remove duplicate docReview API block; keep single canonical docReviews namespace
- Use DocReview | DocReviewMissing union for GET response type
- Apply encodeURIComponent to state filter query parameter

Docs-Reviewed: doc-review stamp store + routes slice per document-review-surface.md

@coderabbitai coderabbitai 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.

Actionable comments posted: 5

🧹 Nitpick comments (3)
tests/test_doc_review.py (1)

231-242: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Verify actor recording for owner-session writes.

This test only writes awaiting_review, which intentionally records no actor. Add an owner approval or changes-requested write and assert the corresponding actor equals ctx.uid.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_doc_review.py` around lines 231 - 242, Extend
test_owner_can_write_and_read with an owner approval or changes-requested write
after the awaiting_review update, then assert the response records the expected
review state and actor field equals ctx.uid. Keep the existing read/write
assertions intact.
tinyagentos/routes/project_doc_review.py (1)

70-74: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Chain the raised exceptions.

When raising an exception inside an except block, it is best practice to use from exc to preserve the original traceback for debugging purposes.

♻️ Proposed refactor
-    except ValueError as exc:
-        detail = str(exc)
-        if "invalid transition" in detail:
-            raise HTTPException(status_code=409, detail=detail)
-        raise HTTPException(status_code=400, detail=detail)
+    except ValueError as exc:
+        detail = str(exc)
+        if "invalid transition" in detail:
+            raise HTTPException(status_code=409, detail=detail) from exc
+        raise HTTPException(status_code=400, detail=detail) from exc
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tinyagentos/routes/project_doc_review.py` around lines 70 - 74, Update the
ValueError handling block to chain both HTTPException raises from the caught
exception using from exc, preserving the existing status codes and detail
messages for invalid transitions and other validation errors.
tinyagentos/projects/doc_review_store.py (1)

38-39: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Specify strict=True for zip().

Explicitly declaring that keys and row must be of equal length ensures safer iteration and satisfies static analysis (Ruff B905).

♻️ Proposed refactor
-        keys = [d[0] for d in description]
-        return dict(zip(keys, row))
+        keys = [d[0] for d in description]
+        return dict(zip(keys, row, strict=True))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tinyagentos/projects/doc_review_store.py` around lines 38 - 39, Update the
dict construction in the description-to-row mapping to call zip() with
strict=True, ensuring keys and row must have equal lengths while preserving the
existing mapping behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@desktop/src/apps/FilesApp.tsx`:
- Around line 544-564: Update fetchReviewStates to map each review using
item.doc_path directly, removing the prefix construction and path parameter
because the endpoint returns project-root-relative paths. Update its callers,
including the useEffect dependency at line 674, to avoid refetching review
states on every directory navigation while preserving project-location changes
and error handling.

In `@desktop/src/lib/projects.ts`:
- Around line 81-95: Remove the earlier DocReviewState and DocReview type
declarations, retaining the later definitions around the existing
DocReviewMissing type. Ensure the remaining DocReview definition preserves its
non-nullable review_state while DocReviewMissing represents the nullable
variant.
- Around line 365-421: Consolidate the duplicated
projectsApi.docReview/docReviews definitions into one docReview namespace,
removing the duplicate object key and the separate docReviews property. Preserve
the complete get, set/setState, and list functionality from both definitions,
using the existing DocReview and DocReviewMissing/response types consistently
and retaining URL encoding and state query behavior.

In `@tests/test_doc_review.py`:
- Around line 327-338: Extend test_agent_other_project_is_404 to cover
cross-project document-review reads: issue a document GET and a document-list
GET against pid_b using token_a, and assert both return the same
existence-hiding 404 as the existing PUT case.
- Around line 40-166: Update the direct store tests around
test_get_missing_returns_none, test_awaiting_to_approved_records_actor,
test_awaiting_to_changes_requested_records_actor,
test_approved_back_to_awaiting_keeps_actor,
test_changes_requested_back_to_awaiting_keeps_actor,
test_invalid_transition_raises_value_error,
test_unknown_state_raises_value_error,
test_first_write_can_be_approved_or_changes_requested,
test_list_reviews_filters_by_state, and test_delete_review to use an async
fixture or equivalent try/finally cleanup that closes every initialized
DocReviewStore. Ensure both store and store2 in
test_invalid_transition_raises_value_error are closed even when assertions or
exceptions occur.

---

Nitpick comments:
In `@tests/test_doc_review.py`:
- Around line 231-242: Extend test_owner_can_write_and_read with an owner
approval or changes-requested write after the awaiting_review update, then
assert the response records the expected review state and actor field equals
ctx.uid. Keep the existing read/write assertions intact.

In `@tinyagentos/projects/doc_review_store.py`:
- Around line 38-39: Update the dict construction in the description-to-row
mapping to call zip() with strict=True, ensuring keys and row must have equal
lengths while preserving the existing mapping behavior.

In `@tinyagentos/routes/project_doc_review.py`:
- Around line 70-74: Update the ValueError handling block to chain both
HTTPException raises from the caught exception using from exc, preserving the
existing status codes and detail messages for invalid transitions and other
validation errors.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 6241e0aa-defd-42de-943e-0e7c6ef5a46c

📥 Commits

Reviewing files that changed from the base of the PR and between 47c3358 and 83b6baf.

📒 Files selected for processing (8)
  • desktop/src/apps/FilesApp.tsx
  • desktop/src/lib/projects.ts
  • tests/test_doc_review.py
  • tinyagentos/app.py
  • tinyagentos/auth_middleware.py
  • tinyagentos/projects/doc_review_store.py
  • tinyagentos/routes/__init__.py
  • tinyagentos/routes/project_doc_review.py

Comment thread desktop/src/apps/FilesApp.tsx Outdated
Comment thread desktop/src/lib/projects.ts Outdated
Comment thread desktop/src/lib/projects.ts
Comment thread tests/test_doc_review.py
Comment on lines +40 to +166
@pytest.mark.asyncio
async def test_get_missing_returns_none(tmp_path):
store = DocReviewStore(tmp_path / "projects.db")
await store.init()
assert await store.get_review("p1", "a.md") is None


@pytest.mark.asyncio
async def test_awaiting_to_approved_records_actor(tmp_path):
store = DocReviewStore(tmp_path / "projects.db")
await store.init()
first = await store.set_review_state("p1", "a.md", "awaiting_review", "user-1")
assert first["review_state"] == "awaiting_review"
# First write to awaiting_review does not stamp an approver.
assert first["reviewed_by"] is None
assert first["changes_requested_by"] is None

approved = await store.set_review_state("p1", "a.md", "approved", "agent-7")
assert approved["review_state"] == "approved"
assert approved["reviewed_by"] == "agent-7"
assert approved["reviewed_at"] is not None
assert approved["changes_requested_by"] is None


@pytest.mark.asyncio
async def test_awaiting_to_changes_requested_records_actor(tmp_path):
store = DocReviewStore(tmp_path / "projects.db")
await store.init()
await store.set_review_state("p1", "b.md", "awaiting_review", "user-1")
r = await store.set_review_state("p1", "b.md", "changes_requested", "agent-3")
assert r["review_state"] == "changes_requested"
assert r["changes_requested_by"] == "agent-3"
assert r["changes_requested_at"] is not None
assert r["reviewed_by"] is None


@pytest.mark.asyncio
async def test_approved_back_to_awaiting_keeps_actor(tmp_path):
store = DocReviewStore(tmp_path / "projects.db")
await store.init()
await store.set_review_state("p1", "c.md", "awaiting_review", "u")
await store.set_review_state("p1", "c.md", "approved", "a1")
r = await store.set_review_state("p1", "c.md", "awaiting_review", "u")
assert r["review_state"] == "awaiting_review"
# Returning to awaiting_review does not clear the stamped approver.
assert r["reviewed_by"] == "a1"
assert r["reviewed_at"] is not None


@pytest.mark.asyncio
async def test_changes_requested_back_to_awaiting_keeps_actor(tmp_path):
store = DocReviewStore(tmp_path / "projects.db")
await store.init()
await store.set_review_state("p1", "c.md", "awaiting_review", "u")
await store.set_review_state("p1", "c.md", "changes_requested", "a2")
r = await store.set_review_state("p1", "c.md", "awaiting_review", "u")
assert r["review_state"] == "awaiting_review"
assert r["changes_requested_by"] == "a2"
assert r["changes_requested_at"] is not None


@pytest.mark.asyncio
async def test_invalid_transition_raises_value_error(tmp_path):
store = DocReviewStore(tmp_path / "projects.db")
await store.init()
await store.set_review_state("p1", "d.md", "awaiting_review", "u")
await store.set_review_state("p1", "d.md", "approved", "a1")
# approved -> changes_requested is not a permitted transition.
with pytest.raises(ValueError) as exc:
await store.set_review_state("p1", "d.md", "changes_requested", "a2")
assert "invalid transition" in str(exc.value)

# changes_requested -> approved is likewise invalid.
store2 = DocReviewStore(tmp_path / "projects2.db")
await store2.init()
await store2.set_review_state("p1", "e.md", "awaiting_review", "u")
await store2.set_review_state("p1", "e.md", "changes_requested", "a2")
with pytest.raises(ValueError) as exc2:
await store2.set_review_state("p1", "e.md", "approved", "a1")
assert "invalid transition" in str(exc2.value)


@pytest.mark.asyncio
async def test_unknown_state_raises_value_error(tmp_path):
store = DocReviewStore(tmp_path / "projects.db")
await store.init()
with pytest.raises(ValueError):
await store.set_review_state("p1", "f.md", "banana", "u")


@pytest.mark.asyncio
async def test_first_write_can_be_approved_or_changes_requested(tmp_path):
store = DocReviewStore(tmp_path / "projects.db")
await store.init()
# A brand-new doc may be stamped approved (or changes_requested) directly.
approved = await store.set_review_state("p1", "g.md", "approved", "a1")
assert approved["review_state"] == "approved"
assert approved["reviewed_by"] == "a1"
cr = await store.set_review_state("p1", "h.md", "changes_requested", "a2")
assert cr["review_state"] == "changes_requested"
assert cr["changes_requested_by"] == "a2"


@pytest.mark.asyncio
async def test_list_reviews_filters_by_state(tmp_path):
store = DocReviewStore(tmp_path / "projects.db")
await store.init()
await store.set_review_state("p1", "x.md", "awaiting_review", "u")
await store.set_review_state("p1", "y.md", "approved", "a1")
await store.set_review_state("p1", "z.md", "awaiting_review", "u")

approved = await store.list_reviews("p1", state="approved")
assert [r["doc_path"] for r in approved] == ["y.md"]

all_reviews = await store.list_reviews("p1")
assert len(all_reviews) == 3
assert {r["doc_path"] for r in all_reviews} == {"x.md", "y.md", "z.md"}


@pytest.mark.asyncio
async def test_delete_review(tmp_path):
store = DocReviewStore(tmp_path / "projects.db")
await store.init()
await store.set_review_state("p1", "k.md", "awaiting_review", "u")
assert await store.delete_review("p1", "k.md") is True
assert await store.get_review("p1", "k.md") is None
assert await store.delete_review("p1", "missing.md") is False

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Close the stores created by direct store tests.

Lines 40-166 repeatedly call store.init() without store.close(), leaving database handles open. Use an async fixture with try/finally to close each store, including store2.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_doc_review.py` around lines 40 - 166, Update the direct store
tests around test_get_missing_returns_none,
test_awaiting_to_approved_records_actor,
test_awaiting_to_changes_requested_records_actor,
test_approved_back_to_awaiting_keeps_actor,
test_changes_requested_back_to_awaiting_keeps_actor,
test_invalid_transition_raises_value_error,
test_unknown_state_raises_value_error,
test_first_write_can_be_approved_or_changes_requested,
test_list_reviews_filters_by_state, and test_delete_review to use an async
fixture or equivalent try/finally cleanup that closes every initialized
DocReviewStore. Ensure both store and store2 in
test_invalid_transition_raises_value_error are closed even when assertions or
exceptions occur.

Comment thread tests/test_doc_review.py
Comment on lines +327 to +338
async def test_agent_other_project_is_404(self, ctx):
pid_a = await _new_project(ctx, "alpha")
pid_b = await _new_project(ctx, "bravo")
_cid, token_a = await _mint_agent(ctx, pid_a)
async with _bare(ctx.app) as bare:
resp = await bare.put(
f"/api/projects/{pid_b}/doc-review/README.md",
json={"state": "awaiting_review"},
headers=_hdr(token_a),
)
# Existence-hiding 404, identical to a non-owner session.
assert resp.status_code == 404, resp.text

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Cover cross-project reads as well as writes.

The stated isolation invariant applies to all document-review routes, but this test only exercises PUT. Add cross-project document GET and list GET cases expecting the same existence-hiding 404.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_doc_review.py` around lines 327 - 338, Extend
test_agent_other_project_is_404 to cover cross-project document-review reads:
issue a document GET and a document-list GET against pid_b using token_a, and
assert both return the same existence-hiding 404 as the existing PUT case.

async (docPath: string, current: string | null) => {
if (!isProjectLocation(location)) return;
const pid = projectSlug(location);
const order: DocReviewState[] = ["awaiting_review", "approved", "changes_requested"];

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

WARNING: Doc-review cycle includes an invalid transition (approved -> changes_requested)

The backend state machine (VALID_TRANSITIONS in tinyagentos/projects/doc_review_store.py) only permits approved -> awaiting_review. This cycle order is [awaiting_review, approved, changes_requested], so clicking the badge while a doc is approved attempts approved -> changes_requested, which the route rejects with HTTP 409. That error is swallowed by the catch block below, so the badge silently stays "Approved" and appears stuck.

No linear 3-state cycle is possible because approved and changes_requested are not connected to each other (both only return to awaiting_review). Use a per-state next mapping instead, e.g.:

const NEXT_STATE: Record<DocReviewState, DocReviewState> = {
  awaiting_review: "approved",
  approved: "awaiting_review",
  changes_requested: "awaiting_review",
};
const next = NEXT_STATE[(current as DocReviewState) ?? "awaiting_review"];

(Note this still cannot reach changes_requested from the badge - you may want a dedicated affordance for that state.)


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

const nextMap: Record<string, string | null> = { ...prev, [docPath]: next };
return nextMap;
});
} catch {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

SUGGESTION: Surface rejected writes to the user instead of silently swallowing

The catch {} discards every failure (403/409/401/offline), so when a write is rejected the badge simply does not change with no explanation. Consider calling setError(...) (or re-throwing) so the user knows the action was not applied.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

sets: list[str] = ["review_state = ?", "updated_at = ?"]
params: list = [new_state, now]

if new_state == "approved":

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

SUGGESTION: Opposite actor columns are not cleared on transition

When moving into approved you set reviewed_by/reviewed_at but never clear changes_requested_by/changes_requested_at, and vice versa. Because transitions route back through awaiting_review (e.g. approved -> awaiting_review -> changes_requested), a doc can end in changes_requested while still carrying a stale reviewed_by from the earlier approval. Consider clearing the non-applicable actor columns on each transition for cleaner audit semantics.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

@kilo-code-bot

kilo-code-bot Bot commented Jul 15, 2026

Copy link
Copy Markdown

Code Review Summary

Status: 3 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 2
Issue Details (click to expand)

CRITICAL

(none)

WARNING

File Line Issue
desktop/src/apps/FilesApp.tsx 587 Doc-review cycle includes an invalid transition (approved -> changes_requested); 409 swallowed, badge stuck at "Approved"

SUGGESTION

File Line Issue
desktop/src/apps/FilesApp.tsx 596 Swallowed write errors give no user feedback
tinyagentos/projects/doc_review_store.py 108 Opposite actor columns not cleared on transition (stale reviewed_by on changes_requested)
Files Reviewed (8 files)
  • desktop/src/apps/FilesApp.tsx - 2 issues
  • desktop/src/lib/projects.ts - 0 issues
  • tests/test_doc_review.py - 0 issues
  • tinyagentos/app.py - 0 issues
  • tinyagentos/auth_middleware.py - 0 issues
  • tinyagentos/projects/doc_review_store.py - 1 issue
  • tinyagentos/routes/__init__.py - 0 issues
  • tinyagentos/routes/project_doc_review.py - 0 issues

Fix these issues in Kilo Cloud


Reviewed by hy3:free · Input: 93.2K · Output: 32.8K · Cached: 802.1K

@jaylfc

jaylfc commented Jul 15, 2026

Copy link
Copy Markdown
Owner Author

Superseded by #1835 (same branch, complete work + tests).

@jaylfc jaylfc closed this Jul 15, 2026
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.

1 participant