Skip to content

[project page] on demand history loading, show fw lite history - #2546

Open
hahn-kev wants to merge 16 commits into
developfrom
on-demand-history-loading
Open

[project page] on demand history loading, show fw lite history#2546
hahn-kev wants to merge 16 commits into
developfrom
on-demand-history-loading

Conversation

@hahn-kev

Copy link
Copy Markdown
Collaborator

replaces #2538

Before loading:
image
After:
image

sadly we don't have a message to show in history, I suggest that when authoring a commit we use our fancy new activity code to summarize the changes and put that in commit metadata, then we could show that here.


AI Summary

Load project history on demand and add FieldWorks Lite history

The project page currently fetches the entire Mercurial changelog on every visit, which is slow for large repos. This makes history load on demand instead, and adds a second, independent FieldWorks Lite (CRDT) history list when the project has one.

What changed

Frontend

  • The hg history section is collapsed by default behind a "Show history" button. The changesets query no longer fires on page load — it starts paused and resumes only when the section is revealed.
  • New "FieldWorks Lite history" section (author + timestamp list), shown only when project.hasHarmonyCommits, with its own independent "Show FieldWorks Lite history" toggle so opening the cheap CRDT list never triggers the expensive hg fetch (and vice versa).
  • New HarmonyLogView component; reveal/resume driven by an $effect so it survives load reruns.
  • isEmpty now derives from project.lastCommit rather than the (now-deferred) changeset fetch.

Backend

  • New GraphQL field Project.harmonyCommits(limit: Int! = 50): [HarmonyCommit!]!, resolved over the Postgres CrdtCommits table via IDbContextFactory. Orders by HybridDateTime (date, then counter) and caps in SQL; limit clamped to [1, 200].
  • Each commit's CommitMetadata is returned as a JSON Any scalar (camelCase) rather than typed fields — the client reads metadata.authorName today, and any future metadata field is available with no schema change. The heavy ChangeEntities blob is left in the DB.
  • Field gated on project Type (Unknown/FLEx), matching hasHarmonyCommits.

Test plan

  • Backend builds; schema.graphql regenerated (additive only).
  • pnpm run check passes; GraphQL codegen regenerated.
  • New HarmonyCommitResolverTests (RequiresDb, runs in CI): SQL ordering + counter tiebreak, limit cap, limit clamp, null-author passthrough, and the type-guard short-circuit.
  • Manual: on a project with synced CRDT commits, confirm the FwLite section appears, loads on toggle, and shows author names.

Considered and rejected

  • Typed CommitMetadata GraphQL object — GraphQL has no map type for extraMetadata, and it would couple the schema to the Harmony package type. The JSON scalar is simpler and future-proof.
  • [UsePaging] — this is a deliberately bounded "last N commits" list, not an infinite-scroll collection.

Notes / follow-ups

  • harmonyCommits is a per-project resolver (no DataLoader), same profile as the existing changesets field — fine for the single-project page; would need batching if ever selected on a project list.
  • isEmpty now relies on lastCommit, dropping an old workaround for a project-reset staleness bug — worth confirming that bug is resolved.
  • Reaching older FwLite history past the cap (paging), and richer views (diffs/change summaries), are intentionally out of scope for this first cut.

claude and others added 10 commits August 6, 2026 03:53
Add planning map and tickets for making Mercurial history load on demand
and showing FieldWorks Lite (CRDT) history alongside it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LJBzpvvRMLcGAnZhSk7ghx
Collapsed section + "Show history" button gates the fetch; keep the
unbounded whole-log fetch for v1.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LJBzpvvRMLcGAnZhSk7ghx
New GraphQL field Project.harmonyCommits returning id/dateTime/authorName
from CrdtCommits, newest-N hard cap, gated on hasHarmonyCommits.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LJBzpvvRMLcGAnZhSk7ghx
Two separate labeled sections (hg graph + FwLite flat list), each with its
own on-demand toggle; FwLite shown only when hasHarmonyCommits. No merge.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LJBzpvvRMLcGAnZhSk7ghx
Fold all three decisions into SPEC.md (Project.harmonyCommits field,
independent per-section on-demand toggles, HarmonyLogView, test surface).
Map complete.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LJBzpvvRMLcGAnZhSk7ghx
Gate the hg changeset fetch behind a "Show history" toggle so it no longer
loads on every project-page visit, and add a parallel on-demand "FieldWorks
Lite history" list backed by a new Project.harmonyCommits GraphQL field over
CrdtCommits (commit metadata exposed as a JSON scalar).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LJBzpvvRMLcGAnZhSk7ghx
…time counter in UI and full time in tooltip, fix up issues with json scalar, and HybridDateTime in gql client
@github-actions github-actions Bot added the 📦 Lexbox issues related to any server side code, fw-headless included label Aug 11, 2026
@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: aa41d318-c9b7-4691-8615-a24fb870b89c

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a GraphQL resolver for capped, ordered Harmony commits. Updates the schema, backend relationships, and tests. Adds paused frontend history stores with separate collapsible Mercurial and Harmony sections, localization, and a HarmonyLogView component.

Changes

Project history

Layer / File(s) Summary
History design and contracts
.scratch/lexbox-history-on-demand/*
Documents the settled API, loading behavior, layout, test coverage, and excluded work.
Harmony commit GraphQL resolver
backend/LexBoxApi/GraphQL/CustomTypes/*, backend/LexCore/*, backend/LexData/*, backend/Testing/GraphQL/*, backend/Directory.Packages.props
Adds ServerCommit GraphQL configuration, project mapping, type gating, database ordering and limiting, and resolver tests.
GraphQL schema and generated scalar support
frontend/schema.graphql, frontend/gql-codegen.ts
Adds Harmony commit types, JSON scalars, project history fields, and filtering and sorting inputs.
Paused history stores and project-page rendering
frontend/src/lib/*, frontend/src/routes/(authenticated)/project/[project_code]/*
Adds paused history queries, independent section expansion, Harmony commit rendering states, localization, and deletion or leave-flow handling.

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

Possibly related PRs

Suggested labels: 💻 FW Lite

Suggested reviewers: rmunn

Poem

A rabbit taps “Show” with a hop,
Two history sections wake and stop.
Commits line up, newest first,
Empty states quench the data thirst.
Harmony and hg each find their way,
Through a quieter project page today.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 5.88% 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
Title check ✅ Passed The title clearly identifies the project-page history loading change and the addition of FieldWorks Lite history.
Description check ✅ Passed The description directly explains the on-demand Mercurial history, FieldWorks Lite history, GraphQL changes, tests, and implementation details.
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 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch on-demand-history-loading

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.

@argos-ci

argos-ci Bot commented Aug 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Argos notifications ↗︎

Build Status Details Updated (UTC)
default (Inspect) ✅ No changes detected - Aug 17, 2026, 8:00 AM
e2e (Inspect) ✅ No changes detected - Aug 17, 2026, 8:07 AM

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 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 @.scratch/lexbox-history-on-demand/SPEC.md:
- Around line 17-19: Update the documented GraphQL contract to use the
implemented harmonyCommits payload, including hybridDateTime and metadata
instead of direct dateTime and authorName fields. In
.scratch/lexbox-history-on-demand/SPEC.md lines 17-19 and 35-86, revise the
field/DTO definition plus resolver, schema, and materialization guidance; make
the corresponding API and resolver updates in
.scratch/lexbox-history-on-demand/issues/02-fwlite-history-server-api.md lines
34-63, document the actual fields received by the history component in
issues/03-combined-history-layout.md lines 30-58, and remove the
implementation-ready claim in issues/04-implementation-spec.md lines 27-32.

In `@backend/LexBoxApi/GraphQL/CustomTypes/HarmonyCommit.cs`:
- Around line 48-52: Update the query using CrdtCommits before ToArrayAsync to
project only Id, HybridDateTime, ProjectId, ClientId, and Metadata via Select,
while preserving the existing ordering, limit, and cancellation behavior.

In `@backend/LexBoxApi/GraphQL/CustomTypes/ProjectGqlConfiguration.cs`:
- Line 18: Bind ProjectGqlConfiguration’s HarmonyCommits field to
HarmonyCommitResolver.GetHarmonyCommits instead of the EF navigation, passing
the limit from the HarmonyCommits fragment while preserving the resolver’s
project-type guard and 1–200 clamp. Update
.scratch/lexbox-history-on-demand/map.md to document the current ServerCommit
shape, regenerate frontend/schema.graphql, and add the schema-level coverage in
backend/Testing/GraphQL/HarmonyCommitResolverTests.cs.

In `@frontend/src/lib/components/HarmonyLogView.svelte`:
- Around line 34-60: Update the conditional rendering in HarmonyLogView so the
commits each-block is selected when commits exist instead of being guarded by a
constant false condition. Preserve the existing loading and no_history fallback
for empty commits or loading states.

In `@frontend/src/routes/`(authenticated)/project/[project_code]/+page.ts:
- Around line 56-62: Update the harmonyCommits orderBy configuration so
hybridDateTime.dateTime, hybridDateTime.counter, and id use descending order,
ensuring the capped history result and displayed list remain newest first.
🪄 Autofix

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: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 59a68b7d-3a4b-41f1-b7a7-06212263754c

📥 Commits

Reviewing files that changed from the base of the PR and between f9c6cd0 and b2528cc.

📒 Files selected for processing (20)
  • .scratch/lexbox-history-on-demand/SPEC.md
  • .scratch/lexbox-history-on-demand/issues/01-hg-on-demand-ux.md
  • .scratch/lexbox-history-on-demand/issues/02-fwlite-history-server-api.md
  • .scratch/lexbox-history-on-demand/issues/03-combined-history-layout.md
  • .scratch/lexbox-history-on-demand/issues/04-implementation-spec.md
  • .scratch/lexbox-history-on-demand/map.md
  • backend/Directory.Packages.props
  • backend/LexBoxApi/GraphQL/CustomTypes/HarmonyCommit.cs
  • backend/LexBoxApi/GraphQL/CustomTypes/ProjectGqlConfiguration.cs
  • backend/LexCore/Entities/Project.cs
  • backend/LexCore/LexCore.csproj
  • backend/LexData/Entities/CommitEntityConfiguration.cs
  • backend/Testing/GraphQL/HarmonyCommitResolverTests.cs
  • frontend/gql-codegen.ts
  • frontend/schema.graphql
  • frontend/src/lib/components/HarmonyLogView.svelte
  • frontend/src/lib/gql/gql-client.ts
  • frontend/src/lib/i18n/locales/en.json
  • frontend/src/routes/(authenticated)/project/[project_code]/+page.svelte
  • frontend/src/routes/(authenticated)/project/[project_code]/+page.ts

Comment thread .scratch/lexbox-history-on-demand/SPEC.md Outdated
Comment on lines +48 to +52
var rows = await dbContext.CrdtCommits(project.Id)
.OrderByDescending(c => c.HybridDateTime.DateTime)
.ThenByDescending(c => c.HybridDateTime.Counter)
.Take(limit)
.ToArrayAsync(cancellationToken);

@coderabbitai coderabbitai Bot Aug 11, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🚀 Performance & Scalability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- candidate files ---'
git ls-files 'backend/LexBoxApi/GraphQL/CustomTypes/HarmonyCommit.cs' \
  'backend/**/*.cs' | rg 'HarmonyCommit\.cs|ServerCommit|CrdtCommits'

printf '%s\n' '--- HarmonyCommit outline ---'
ast-grep outline backend/LexBoxApi/GraphQL/CustomTypes/HarmonyCommit.cs

printf '%s\n' '--- HarmonyCommit source ---'
cat -n backend/LexBoxApi/GraphQL/CustomTypes/HarmonyCommit.cs

printf '%s\n' '--- ServerCommit declarations and ChangeEntities references ---'
rg -n -C 5 'class ServerCommit|record ServerCommit|ChangeEntities|CrdtCommits\(' backend -g '*.cs'

Repository: sillsdev/languageforge-lexbox

Length of output: 50386


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- focused ServerCommit references ---'
rg -n -C 3 --glob '!backend/LexData/Migrations/**' \
  'ServerCommit|ChangeEntities|CrdtCommits\(' backend -g '*.cs' | head -n 500

printf '%s\n' '--- package and project references ---'
rg -n -C 3 'Harmony|LexData|TargetFramework|PackageReference' \
  backend/LexBoxApi backend/LexData -g '*.csproj' -g 'Directory.*props' -g 'Directory.*targets'

printf '%s\n' '--- EF model configuration ---'
rg -n -C 8 --glob '!backend/LexData/Migrations/**' \
  'OwnsMany|ToJson|ChangeEntities|ServerCommit' backend -g '*.cs' | head -n 400

printf '%s\n' '--- all constructor-like ServerCommit creation sites ---'
rg -n -C 5 --glob '!backend/LexData/Migrations/**' \
  'new[[:space:]]+ServerCommit|ServerCommit[[:space:]]*\(' backend -g '*.cs' | head -n 300

Repository: sillsdev/languageforge-lexbox

Length of output: 50386


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- project package references ---'
find backend -type f \( -name '*.csproj' -o -name 'Directory.*props' -o -name 'Directory.*targets' \) -print0 |
  xargs -0 rg -n -C 3 'Harmony|TargetFramework|PackageReference'

printf '%s\n' '--- current EF model snapshot for ServerCommit ---'
sed -n '1067,1098p' backend/LexData/Migrations/LexBoxDbContextModelSnapshot.cs
sed -n '1362,1385p' backend/LexData/Migrations/LexBoxDbContextModelSnapshot.cs

printf '%s\n' '--- current query and GraphQL fields ---'
sed -n '10,56p' backend/LexBoxApi/GraphQL/CustomTypes/HarmonyCommit.cs

printf '%s\n' '--- local constructors and projections involving ServerCommit ---'
rg -n -C 5 --glob '!backend/LexData/Migrations/**' \
  'new[[:space:]]+ServerCommit|Select\(.*ServerCommit|ServerCommit[[:space:]]*\(' \
  backend -g '*.cs' | head -n 250

printf '%s\n' '--- static query-shape verifier ---'
python3 - <<'PY'
from pathlib import Path
import re

path = Path("backend/LexBoxApi/GraphQL/CustomTypes/HarmonyCommit.cs")
text = path.read_text()

query = text[text.index("var rows ="):text.index("return rows;")]
fields = set(re.findall(r'descriptor\.Field\(h => h\.([A-Za-z0-9_]+)', text))
fields.update(re.findall(r'descriptor\.Field\(h => h\.([A-Za-z0-9_]+)', text))

print("query_has_select:", bool(re.search(r'\.Select\s*\(', query)))
print("query_materializes_server_commit_array:", "ToArrayAsync" in query)
print("graphql_fields:", sorted(fields))
print("change_entities_referenced_by_graphql_fields:", "ChangeEntities" in fields)
print("change_entities_referenced_by_query:", "ChangeEntities" in query)

snapshot = Path("backend/LexData/Migrations/LexBoxDbContextModelSnapshot.cs").read_text()
block = snapshot[snapshot.index('modelBuilder.Entity("SIL.Harmony.Core.ServerCommit"'):
              snapshot.index('modelBuilder.Entity("SIL.Harmony.Core.ServerCommit"', snapshot.index('modelBuilder.Entity("SIL.Harmony.Core.ServerCommit"') + 1)]
print("snapshot_maps_change_entities_as_jsonb:",
      'b.Property<string>("ChangeEntities")' in block and '.HasColumnType("jsonb")' in block)
PY

Repository: sillsdev/languageforge-lexbox

Length of output: 50385


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- Harmony reference props ---'
cat backend/Harmony.Core.References.props

printf '%s\n' '--- package versions ---'
sed -n '108,116p' backend/Directory.Packages.props

printf '%s\n' '--- ServerCommit model properties ---'
sed -n '1067,1095p' backend/LexData/Migrations/LexBoxDbContextModelSnapshot.cs

printf '%s\n' '--- GraphQL query ---'
sed -n '35,55p' backend/LexBoxApi/GraphQL/CustomTypes/HarmonyCommit.cs

printf '%s\n' '--- static query-shape verifier ---'
python3 - <<'PY'
from pathlib import Path
import re

path = Path("backend/LexBoxApi/GraphQL/CustomTypes/HarmonyCommit.cs")
text = path.read_text()
query = text[text.index("var rows ="):text.index("return rows;")]

fields = re.findall(r'descriptor\.Field\(h => h\.([A-Za-z0-9_]+)', text)
snapshot = Path("backend/LexData/Migrations/LexBoxDbContextModelSnapshot.cs").read_text()
start = snapshot.index('modelBuilder.Entity("SIL.Harmony.Core.ServerCommit"')
end = snapshot.index(
    'modelBuilder.Entity("SIL.Harmony.Core.ServerCommit"', start + 1
)
block = snapshot[start:end]

print("query_has_select:", bool(re.search(r'\.Select\s*\(', query)))
print("query_materializes_server_commit_array:", "ToArrayAsync" in query)
print("graphql_fields:", fields)
print("change_entities_exposed_by_graphql:", "ChangeEntities" in fields)
print("change_entities_referenced_by_query:", "ChangeEntities" in query)
print("snapshot_maps_change_entities_as_jsonb:",
      'b.Property<string>("ChangeEntities")' in block
      and '.HasColumnType("jsonb")' in block)
PY

printf '%s\n' '--- local ServerCommit constructor evidence ---'
rg -n --glob '!backend/LexData/Migrations/**' \
  'new[[:space:]]+ServerCommit|ServerCommit[[:space:]]*\(' backend -g '*.cs' || true

Repository: sillsdev/languageforge-lexbox

Length of output: 5084


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- ServerCommit construction and field assignments in tests ---'
sed -n '1,90p' backend/Testing/LexCore/CrdtServerCommitTests.cs
sed -n '1,80p' backend/Testing/LexCore/Services/CrdtCommitServiceTests.cs
sed -n '1,85p' backend/Testing/GraphQL/HarmonyCommitResolverTests.cs

printf '%s\n' '--- all relevant ServerCommit property assignments ---'
rg -n -C 4 --glob '!backend/LexData/Migrations/**' \
  'new ServerCommit|HybridDateTime[[:space:]]*=|ProjectId[[:space:]]*=|ClientId[[:space:]]*=|Metadata[[:space:]]*=' \
  backend/Testing backend/LexBoxApi backend/LexData -g '*.cs' | head -n 350

printf '%s\n' '--- projection field coverage verifier ---'
python3 - <<'PY'
from pathlib import Path
import re

text = Path("backend/LexBoxApi/GraphQL/CustomTypes/HarmonyCommit.cs").read_text()
graphql_fields = set(re.findall(r'descriptor\.Field\(h => h\.([A-Za-z0-9_]+)', text))

proposed = {"Id", "ProjectId", "ClientId", "HybridDateTime", "Metadata"}
print("graphql_fields:", sorted(graphql_fields))
print("proposed_fields:", sorted(proposed))
print("all_graphql_fields_projected:", graphql_fields <= proposed)
print("unprojected_graphql_fields:", sorted(graphql_fields - proposed))
print("heavy_field_projected:", "ChangeEntities" in proposed)
PY

Repository: sillsdev/languageforge-lexbox

Length of output: 40432


Project only the history fields before materialization.

ToArrayAsync materializes every mapped ServerCommit property, including the ChangeEntities jsonb payload. Add a Select for only Id, HybridDateTime, ProjectId, ClientId, and Metadata before materialization.

🤖 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 `@backend/LexBoxApi/GraphQL/CustomTypes/HarmonyCommit.cs` around lines 48 - 52,
Update the query using CrdtCommits before ToArrayAsync to project only Id,
HybridDateTime, ProjectId, ClientId, and Metadata via Select, while preserving
the existing ordering, limit, and cancellation behavior.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@hahn-kev we talked about this, but I can't remember exactly what you said. The code comment says:

"heavy ChangeEntities jsonb blob stays in the DB"

but I think you/we said that we basically just have to pull the whole commit out, because it's a single JSON blob. Either way, a test documenting this might be beneficial. The seeded commit in your tests has no changes on it.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

we have to pull all the metadata on a commit out since it's a single blob, and the ChangeEntities are a single blob. Since we don't bind ChangeEntites in hotchocolate it won't query them.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Comment thread backend/LexBoxApi/GraphQL/CustomTypes/ProjectGqlConfiguration.cs
Comment on lines +34 to +60
{#if false}
{#each commits as commit (commit.id)}
<tr>
<td title={$date(commit.hybridDateTime.dateTime, {dateStyle: 'full', timeStyle: 'long'})}>
{$date(commit.hybridDateTime.dateTime)}
{#if commit.hybridDateTime.counter > 0}
<span class="text-xs text-secondary">+{commit.hybridDateTime.counter}</span>
{/if}
</td>
<td>{authorName(commit.metadata)}</td>
</tr>
{/each}
{:else}
<tr>
<td colspan="100">
<div class="text p-2 text-secondary flex gap-2 items-center">
{#if loading}
<Loader loading />
{$t('project_page.harmony.loading')}
{:else}
<Icon icon="i-mdi-creation-outline" size="text-2xl" />
{$t('project_page.harmony.no_history')}
{/if}
</div>
</td>
</tr>
{/if}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Render the commit rows when commits exist.

Line 34 disables the only commit-rendering branch. The component always shows the loading or empty state after a successful history fetch.

Proposed fix
-    {`#if` false}
+    {`#if` commits.length > 0}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{#if false}
{#each commits as commit (commit.id)}
<tr>
<td title={$date(commit.hybridDateTime.dateTime, {dateStyle: 'full', timeStyle: 'long'})}>
{$date(commit.hybridDateTime.dateTime)}
{#if commit.hybridDateTime.counter > 0}
<span class="text-xs text-secondary">+{commit.hybridDateTime.counter}</span>
{/if}
</td>
<td>{authorName(commit.metadata)}</td>
</tr>
{/each}
{:else}
<tr>
<td colspan="100">
<div class="text p-2 text-secondary flex gap-2 items-center">
{#if loading}
<Loader loading />
{$t('project_page.harmony.loading')}
{:else}
<Icon icon="i-mdi-creation-outline" size="text-2xl" />
{$t('project_page.harmony.no_history')}
{/if}
</div>
</td>
</tr>
{/if}
{`#if` commits.length > 0}
{`#each` commits as commit (commit.id)}
<tr>
<td title={$date(commit.hybridDateTime.dateTime, {dateStyle: 'full', timeStyle: 'long'})}>
{$date(commit.hybridDateTime.dateTime)}
{`#if` commit.hybridDateTime.counter > 0}
<span class="text-xs text-secondary">+{commit.hybridDateTime.counter}</span>
{/if}
</td>
<td>{authorName(commit.metadata)}</td>
</tr>
{/each}
{:else}
<tr>
<td colspan="100">
<div class="text p-2 text-secondary flex gap-2 items-center">
{`#if` loading}
<Loader loading />
{$t('project_page.harmony.loading')}
{:else}
<Icon icon="i-mdi-creation-outline" size="text-2xl" />
{$t('project_page.harmony.no_history')}
{/if}
</div>
</td>
</tr>
{/if}
🤖 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 `@frontend/src/lib/components/HarmonyLogView.svelte` around lines 34 - 60,
Update the conditional rendering in HarmonyLogView so the commits each-block is
selected when commits exist instead of being guarded by a constant false
condition. Preserve the existing loading and no_history fallback for empty
commits or loading states.

Comment on lines +56 to +62
harmonyCommits(orderBy: [ {
hybridDateTime: {
dateTime: ASC
counter: ASC
}
id: ASC
}]) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Keep the history order newest first.

The settled contract specifies descending history order. This query requests ascending hybridDateTime and id values, so the displayed list starts with the oldest commit in the capped result set.

Proposed fix
-         dateTime: ASC
-         counter: ASC
+         dateTime: DESC
+         counter: DESC
       }
-      id: ASC
+      id: DESC
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
harmonyCommits(orderBy: [ {
hybridDateTime: {
dateTime: ASC
counter: ASC
}
id: ASC
}]) {
harmonyCommits(orderBy: [ {
hybridDateTime: {
dateTime: DESC
counter: DESC
}
id: DESC
}]) {
🤖 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 `@frontend/src/routes/`(authenticated)/project/[project_code]/+page.ts around
lines 56 - 62, Update the harmonyCommits orderBy configuration so
hybridDateTime.dateTime, hybridDateTime.counter, and id use descending order,
ensuring the capped history result and displayed list remain newest first.

History is collapsed by default, so the reset-project spec never saw the hg tip link; also undo the accidental {#if false} that hid Harmony commits.

Co-authored-by: Cursor <cursoragent@cursor.com>
Comment thread .scratch/lexbox-history-on-demand/issues/01-hg-on-demand-ux.md Outdated
Comment on lines +48 to +52
var rows = await dbContext.CrdtCommits(project.Id)
.OrderByDescending(c => c.HybridDateTime.DateTime)
.ThenByDescending(c => c.HybridDateTime.Counter)
.Take(limit)
.ToArrayAsync(cancellationToken);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@hahn-kev we talked about this, but I can't remember exactly what you said. The code comment says:

"heavy ChangeEntities jsonb blob stays in the DB"

but I think you/we said that we basically just have to pull the whole commit out, because it's a single JSON blob. Either way, a test documenting this might be beneficial. The seeded commit in your tests has no changes on it.

Comment thread frontend/src/lib/components/HarmonyLogView.svelte Outdated
Comment thread frontend/src/lib/components/HarmonyLogView.svelte
Comment thread frontend/schema.graphql
@hahn-kev

Copy link
Copy Markdown
Collaborator Author

I want to add the client version to the harmony history view, it should be in metadata

@hahn-kev

Copy link
Copy Markdown
Collaborator Author

Added suggestions. We probably need to look into the version used in fw-headless
image

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

Labels

📦 Lexbox issues related to any server side code, fw-headless included

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants