Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
b10445d
feat(project-system): recover malformed element files without ever re…
yuto-trd Jul 31, 2026
1688213
fix(review): harden malformed-element recovery per review findings
yuto-trd Jul 31, 2026
b8acc32
fix(review): preserve recovered sidecars as raw bytes and reject bad …
yuto-trd Jul 31, 2026
e663648
fix(review): harden recovery detection, identity, and rehome writes
yuto-trd Jul 31, 2026
13d9a62
fix(review): make the rehome write atomic and null-guard generic disc…
yuto-trd Jul 31, 2026
29f8926
fix(review): guard nested discriminators, animation warnings, delete …
yuto-trd Jul 31, 2026
be2f05d
fix(review): tighten rehome failure handling, recovered-id determinis…
yuto-trd Jul 31, 2026
59bd61d
fix(review): stabilize recovered identities cross-platform and unbloc…
yuto-trd Jul 31, 2026
0b0eb8f
fix(review): reserve recovered ids scene-wide, persist them authorita…
yuto-trd Jul 31, 2026
defc57d
fix(review): project all recovered fallbacks and expose structured re…
yuto-trd Jul 31, 2026
e69843f
fix(review): deduplicate recovered elements' descendant ids determini…
yuto-trd Jul 31, 2026
c285943
fix(review): survive repairs, migrations, and wrapped IO across the r…
yuto-trd Jul 31, 2026
1f6048e
fix(review): stabilize remap keys, undoable repairs, and richer recov…
yuto-trd Jul 31, 2026
ef21083
fix(review): keep lossy elements frozen, surface incident-only recove…
yuto-trd Jul 31, 2026
6e14fe9
fix(review): resume persistence on every repair path and harden claim…
yuto-trd Jul 31, 2026
cd491cc
fix(review): migrate reference expressions, resume persistence on eve…
yuto-trd Aug 8, 2026
7ad8efc
fix(review): resume persistence on remove/target assignment, harden e…
yuto-trd Aug 8, 2026
eb982ce
fix(review): preserve recovered references and sidecars
yuto-trd Aug 9, 2026
cf86c1d
fix(review): close remaining recovery persistence gaps
yuto-trd Aug 9, 2026
b7c3029
fix(review): close nested recovery gaps
yuto-trd Aug 9, 2026
c559def
fix(review): preserve escaped recovered element ids
yuto-trd Aug 9, 2026
920a767
fix(review): cover extended recovery graphs
yuto-trd Aug 9, 2026
7085180
fix(review): close remaining recovery gaps
yuto-trd Aug 9, 2026
714efed
fix(review): preserve recovery integrity
yuto-trd Aug 9, 2026
ccf5e4d
fix(review): close recovery gaps
yuto-trd Aug 9, 2026
4402ffb
fix(review): harden recovered sidecar state
yuto-trd Aug 9, 2026
c532e37
fix(review): resume persistence for cleared presenter targets
yuto-trd Aug 9, 2026
1a0b98d
fix(review): harden recovery migrations and edits
yuto-trd Aug 9, 2026
b01b8b9
fix(review): close recovery traversal gaps
yuto-trd Aug 9, 2026
400f7a9
fix(review): complete recovery graph handling
yuto-trd Aug 9, 2026
d0db527
fix(review): harden recovery boundaries
yuto-trd Aug 9, 2026
cbb2493
fix(review): preserve recovered reference state
yuto-trd Aug 9, 2026
81cfb0c
refactor!: harden malformed-element recovery
yuto-trd Aug 9, 2026
5dd66cd
style: satisfy format check
yuto-trd Aug 9, 2026
9c0ccf9
fix: preserve recovery repair workflows
yuto-trd Aug 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ A `session` may be **file-opened** (headless server) or **live** (in-app host bo

### `open_project`
- **Input**: `{ "path": string }` (read — unrestricted).
- **Output**: `{ "session": string, "source": "File", "summary": { scenes, elements, duration, frameSize } }`.
- **Output**: `{ "session": string, "source": "File", "summary": { scenes, elements, duration, frameSize }, "warnings": string[], "recoveryIncidents": [{ "sceneId": string, "sceneName": string, "elementFile": string, "reason": "TypeNotFound" | "DeserializationFailed", "typeName": string | null, "message": string | null }] }`. `warnings` remains the presentation-oriented recovery summary; `recoveryIncidents` exposes the same incidents as stable structured data. `sceneId` and `sceneName` identify the containing scene when different scenes contain the same relative element path. `elementFile` is a forward-slash scene-relative path when available, otherwise the element name. `typeName` is the original serialized discriminator when available, otherwise `null`; `message` is the unmodified nullable deserialization error rather than a presentation fallback.
- **Errors**: `media_not_found`, `schema_version_mismatch` (project written by an incompatible schema — surfaced, not silently dropped, per FR-031/FR-013).

### `attach_active_editor` *(in-app host only)*
Expand Down
147 changes: 0 additions & 147 deletions src/Beutl.AgentToolkit/Common/PathBoundary.cs

This file was deleted.

8 changes: 0 additions & 8 deletions src/Beutl.AgentToolkit/Common/PathComparison.cs

This file was deleted.

21 changes: 20 additions & 1 deletion src/Beutl.AgentToolkit/Documents/DeclarativeDocumentApplier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,11 @@ private void ApplyKeyFrame(IKeyFrame keyFrame, JsonObject desired)

if (desired.TryGetPropertyValue(nameof(KeyFrame.Easing), out JsonNode? easingNode) && easingNode is not null)
{
keyFrame.Easing = DeserializeEasing(easingNode);
Easing desiredEasing = DeserializeEasing(easingNode);
if (!AreEquivalentEasings(keyFrame.Easing, desiredEasing))
{
keyFrame.Easing = desiredEasing;
}
}

if (desired.TryGetPropertyValue(nameof(KeyFrame.KeyTime), out JsonNode? keyTimeNode) && keyTimeNode is not null)
Expand Down Expand Up @@ -823,6 +827,21 @@ private static Easing DeserializeEasing(JsonNode node)
"Easing must be a type string or spline object."));
}

private static bool AreEquivalentEasings(Easing current, Easing desired)
{
if (current.GetType() != desired.GetType())
{
return false;
}

return current is not SplineEasing currentSpline
|| desired is SplineEasing desiredSpline
&& currentSpline.X1 == desiredSpline.X1
&& currentSpline.Y1 == desiredSpline.Y1
&& currentSpline.X2 == desiredSpline.X2
&& currentSpline.Y2 == desiredSpline.Y2;
}

internal static string? ValidateEasingNode(JsonNode? node)
{
if (node is JsonValue value && value.TryGetValue(out string? typeName))
Expand Down
Loading