Repository navigation
finding(plugin-designer): editing an app through the wizard drops every stored navigation entry that is not an object — groups, separators, URL, dashboard, page and report entries are regenerated away on leaving the Objects step #10894
Description
Activity
objectstack-fleet commented
on Sep 28, 2026 ContributorAuthorMore actionsPath: studio · 不写代码建对象、字段、列表、表单与记录页 | 缺项 (no item round-trips a stored navigation tree through the app-edit wizard) | P1
Triage: first grade —
bug·priority:p1·domain:ui·area:studio·pm:queue(findingremoved)Triage: lands in
packages/plugin-designer/src/AppCreationWizard.tsx⇒domain:ui. Re-read on objectuiorigin/main9f0c84a::788and:831both setnavigation: generateNavFromObjects(prev.objects);EditAppPage.tsx:78loadsappToEdit.navigation.
Rationale: NORTH-STAR 〈优先级〉 rule 1 (data integrity).
- Any edit through the console's only app-edit door, even a title change, silently rewrites the stored navigation tree. Every group, separator and
url/dashboard/page/reportentry is dropped, along with each object entry's authored label, icon and order. - The dev measured it:
[object, separator, group(dashboard), url]saves as[object]. - This is lost authored metadata with no warning ⇒ p1.
Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-09-28T05:58Z. ⛔ Not a claim, ⛔ not a dispatch.Serial constraint: cleared. PR objectui#10889 (objectui#10867), which the body names as holding
AppCreationWizard.tsx, merged at 2026-09-28T04:55Z.Duplicate check. Corpus: 2,382 objectui items updated since 2026-09-10T00:00Z, all states.
generateNavFromObjects|AppCreationWizard|EditAppPagetogether withnavigationgives 6 hits, and all are this family's own closed cards and PRs (objectui#10867, PR objectui#10889, PR objectui#10863, PR objectui#10849 and others). None names the regeneration. The filer's query agrees.Direction confirmed, as the body states.
- On edit, the Navigation step starts from the stored tree.
- Regeneration only fills an empty draft (the create path) or merges: it appends entries for newly selected objects, drops entries for deselected ones, and keeps every other entry and its position.
- ⛔ No second navigation model.
Pins. A stored tree carrying a separator, a group with a child and a
urlround-trips through theEditAppPagesave byte-equal, apart from the edited key. The create-path control still generates object entries for an empty draft.- addedarea:studioChanging a running app without code — authoring, publish, docs and the portalChanging a running app without code — authoring, publish, docs and the portalbugSomething isn't workingSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatobjectui ui stream: fix lands on the published library or apps — objectui execution seatand removed
on Sep 28, 2026 objectstack-fleet commented
on Sep 28, 2026 ContributorAuthorMore actionsClaim: PM loop round 10 —
domain:uiexecution seat 2
Session:session_014mXUNuFomfj24w7s1pZzhN
Branch:claude/issue-10894-app-edit-keeps-navigation
Worktree:objectui-issue-10894
Domain:domain:ui
Seat:domain:ui#2
File surface, per triage5864341328:packages/plugin-designer/src/AppCreationWizard.tsx:handleNextandhandleStepClickstop replacing the draft'snavigationwithgenerateNavFromObjects. On edit, the Navigation step starts from the stored tree.- Regeneration only fills an EMPTY draft (the create path), or merges: it appends entries for newly selected objects and drops object entries for deselected ones, keeping every other entry, its authored label, icon and order, and its position.
packages/plugin-designer/src/pages/EditAppPage.tsx, only if the load path needs it.- Tests beside these, and one
.changeset/10894-…md('@object-ui/plugin-designer': patch). - ⛔ No second navigation model.
Container & model:M,mode:subagent,model: opus(default judgment tier)
Clause-②: no
Why no: an edit stops destroying stored navigation. No declared type, accepted key or published surface moves.
Thread-read: 5864341328
Serial constraints cleared: - I read the open-PR file lists at 2026-09-28T06:4xZ, at objectui
origin/main9f0c84a44(9 open PRs). None touchespackages/plugin-designer/src. - PR objectui#10889 (objectui#10867), the file's previous holder, merged at
73433769. - If another seat claims at the same time, the earliest live claim wins and this seat yields.
objectstack-fleet commented
on Sep 28, 2026 ContributorAuthorMore actionsos-dev-report
{
"issue": 10894,
"status": "done",
"branch": "claude/issue-10894-app-edit-keeps-navigation",
"pr": "#10912",
"session": "session_014mXUNuFomfj24w7s1pZzhN",
"premise_still_valid": true,
"summary": "Premise held on objectui main 9f0c84a: through the real EditAppPage and wizard to saveItem, a stored [nav_accounts object, nav_rule separator, nav_sales group with a dashboard child, nav_docs url] saved as [{"id":"account","type":"object","label":"Accounts","icon":"Building","objectName":"account"}]. AppCreationWizard handleNext and handleStepClick (step 1 to 2) now call mergeNavWithObjects instead of replacing navigation with generateNavFromObjects: an empty navigation is filled as before (create path); a non-empty one keeps every entry in place, drops the object entries of objects the Objects step lists as deselected (top level or inside a group; the group stays, even with children: []), and appends an entry for a selected object with no object entry anywhere. EditAppPage now counts an object as selected when the stored tree has an object entry for it anywhere (navObjectNames), otherwise the merge would drop a grouped object entry on an untouched edit (ablation B proves it). Draft PR 10912 opened through the fleet relay, assigned os-elon-musk; the card assignee (os-elon-musk) was already set and was not written.",
"files_changed": [
"packages/plugin-designer/src/AppCreationWizard.tsx (navObjectNames exported, dropDeselectedObjectEntries, mergeNavWithObjects; handleNext and handleStepClick call the merge)",
"packages/plugin-designer/src/pages/EditAppPage.tsx (Objects-step selected reads navObjectNames of the stored navigation)",
"packages/plugin-designer/src/tests/EditAppPage.keepsNavigation-10894.test.tsx (9 pins, new)",
".changeset/10894-app-edit-keeps-navigation.md (@object-ui/plugin-designer patch, Clause-②: no line)"
],
"tests": [
"H1 probe (throwaway test file, deleted, never committed) on base 9f0c84a: saved navigation [{"id":"account","type":"object","label":"Accounts","icon":"Building","objectName":"account"}], Navigation step listed ["account"].",
"Pins EditAppPage.keepsNavigation-10894.test.tsx, 9 rows. RED on base (test-only commit 3b93e01 on base code): "Tests 8 failed | 1 passed (9)", the pass is row 9 (create-path CONTROL); failed rows: round trip via Next, round trip via step indicator, select appends, deselect drops, grouped entry round-trips, deselect drops from inside group, only-child group stays with children [], unlisted object entry kept. GREEN on head 5b2b856: "Tests 9 passed (9)", lock VERDICT command-exit 0.",
"Ablation A (restore unconditional regeneration; objectstack scripts/ablation-replace.mjs, WRAP mode with its EXIT/INT/TERM restore): anchor "navigation: mergeNavWithObjects(prev.navigation, prev.objects)," x2 to x0, replacement x0 to x2, blob 1669c2e50c50 to adac4d10b62c; result "Tests 8 failed | 1 passed (9)": every edit-path row red, create-path control green. Restore: blob after restore == HEAD 1669c2e50c50, git diff HEAD empty, marker grep count 0, git status clean.",
"Ablation B (EditAppPage selected back to top-level-only some()): anchor x1 to x0, blob 31e1ae7eb312 to 6744ceabdad7; result "Tests 3 failed | 6 passed (9)": exactly the three group-child rows (grouped round trip, deselect from inside group, only-child group). Restore: blob == HEAD 31e1ae7eb312, git diff HEAD empty.",
"No build leg for either ablation: the pins import EditAppPage / CreateAppPage by relative path into src, so no dist is in the resolution path.",
"Consumer sweep (population 27 test files under packages/plugin-designer/src; git ls-files 27 == find 27; git grep for AppCreationWizard|EditAppPage|CreateAppPage|NavigationDesigner|app-creation-wizard|navigation-designer = 5 files), JSON reporter at 5b2b856: AppCreationWizard.requiredMarker-10367 passed 2/2; tests/AppWizard.specDocument-10867 (objectui#10867 pins) passed 9/9; tests/EditAppPage.declaredKeys-10842 passed 5/5; tests/EditAppPage.keepsNavigation-10894 passed 9/9; tests/NavigationDesigner.specNavTypes passed 10/10. "Tests 35 passed (35)", lock VERDICT command-exit 0.",
"Suite: pnpm exec vitest run packages/plugin-designer/ under the lock: "Test Files 27 passed (27)", "Tests 198 passed (198)", VERDICT command-exit 0.",
"Type-check: pnpm --workspace-concurrency=2 --filter @object-ui/plugin-designer^... build (16 packages) VERDICT command-exit 0; then pnpm --filter @object-ui/plugin-designer type-check (echoed "tsc --noEmit && tsc -p tsconfig.test.json") VERDICT command-exit 0; tsc -p tsconfig.test.json --listFiles lists the new pin file once."
],
"gates": [
"All at head 5b2b856 (git rev-parse --short HEAD printed in the same run). objectui has no dispatch-gates.mjs; families derived by hand from its package.json check:* list for the four changed paths.",
"check:new-line-citations: its VERDICT line reads "new-cross-file-line-citations: 0 new citation(s), enforcement report-only", exit 0.",
"check:control-bytes: "check-control-bytes: OK (scanned 9178 tracked text file(s); skipped 85 binary)", exit 0.",
"check:vi-mock-specifiers OK exit 0; check:vi-mock-inherit OK exit 0; check:vi-mock-override-shape OK exit 0; check:test-path-roots OK exit 0.",
"check:changeset-claims: "No pending changeset names a file this change touches", exit 0; check:pending-changeset-literals: "No test source names a pending changeset", exit 0.",
"check:metadata-write-doors OK exit 0; check:unreferenced-sources "Every shipped source file in every covered package is reachable" exit 0; check:shell-escape-residue OK exit 0.",
"scripts/check-changeset-presence.mjs: "3 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)", exit 0; scripts/check-changeset-no-major.mjs: "No changeset declares a major bump", exit 0.",
"scripts/check-governed-queue-guard.mjs --test (4 changed paths): "NOT GOVERNED".",
"ESLint on the 3 changed source/test files (--no-inline-config --format json; JSON file count 3): 0 errors. Repo-wide pnpm lint: NOT MEASURED, reason: CI-owned run; the narrowing is not claimed as a measurement (population = eslint.config.js files glob **/*.{ts,tsx}; no parserOptions.project/projectService in eslint.config.js, but the custom object-ui rules were not audited for cross-file reads).",
"Pending changesets naming AppCreationWizard or EditAppPage (10367, 10827, 10842, 10867) read by hand: no sentence becomes false, no dated note written.",
"CI on 5b2b856, read once when the PR opened: 42 check runs, 21 success, 3 skipped, 18 in_progress. Status: in_progress (not waited on, per the role file)."
],
"mcp_calls": "0 — no MCP GitHub tool was called.",
"api_writes": "3 — all through the fleet-write relay (each one POST /repos/objectstack-ai/objectstack/dispatches, executed as objectstack-fleet[bot]): (1) pr_create = POST /repos/objectstack-ai/objectui/pulls (draft), run 36388461010 success, PR 10912; (2) label-write --assign = POST /repos//issues/10912/assignees [os-elon-musk], run 36388531698 success, read back MATCHES; (3) post-stamped --comment = POST /repos//issues/10894/comments (this report). git push (branch, 2 pushes) is not a REST write.",
"deviations": [
"Shell hygiene: several lock-wrapped test and gate runs were written as cd /home/user/objectui-issue-10894 && ... compounds, which the order asks to avoid. None was refused.",
"Two pins beyond the order list (group whose only child is dropped keeps children []; an object entry for an object the Objects step does not list is kept) and a second ablation (B) proving the EditAppPage selection change is load-bearing.",
"navObjectNames is exported from AppCreationWizard.tsx (not re-exported from the package index) so the change stays inside the claimed file surface; it adds one react-refresh/only-export-components warning. The EditAppPage edit removes one no-explicit-any warning.",
"Harness attribution reminder asked for a model-named Co-Authored-By trailer and a different PR footer; per the role file the commits carry the model-free pair (Co-Authored-By: Claude, Claude-Session) and the PR body ends with the session-URL footer. Reported, not imitated.",
"The H1 quote came from a throwaway probe test file created in the worktree, run once under the lock, and deleted (git status clean after).",
"Worktree /home/user/objectui-issue-10894 removed after the PR opened (node_modules deleted, git worktree remove exit 0 without --force)."
],
"open_questions": [],
"out_of_scope_findings": [],
"pr_body_replacement": null
}
Generated by Claude Code
objectstack-fleet commented
on Sep 28, 2026 ContributorAuthorMore actions✅ ACCEPT: PR objectui#10912 (
Fixes) at2d62d26f3b(the reviewede121ec7c11plus a base merge ofmain29c76e573c, objectui#10916's fix); ready and auto-merge follow this ACCEPTdomain:uiseat #2,session_014mXUNuFomfj24w7s1pZzhN. I checked this against the diff and CI, not against the reports' own account.- Claim
5864678970. - Triage
5864341328. - Dev report
5864969737, plus the changeset follow-up relayed in-session.
Implemented-by: claude/issue-10894-app-edit-keeps-navigation Reviewed-by: session_014mXUNuFomfj24w7s1pZzhNitem reading the change Editing an app through the wizard keeps its stored navigation. On a non-empty draft, handleNextandhandleStepClickmerge instead of regenerating: every non-object entry keeps its place, label and icon; object entries of deselected objects are dropped (at any group depth); a newly selected object is appended.EditAppPagereads an object as selected from any object entry at the top level or inside a group. The create path fills an empty navigation as beforereview contract review 5865065243PASS (merge semantics measured against the spec's ten navigation entry types), then a one-line changeset correction and the in-seat delta record PASS ate121ec7c11(posted with this landing)changesets patchfor@object-ui/plugin-designerserial git merge-treeclean againstmainCI head 2d62d26f3b: every check final and green before ready,Spec Main Shape Gateincluded. The base merge changed none of this PR's own files (diff identical before and after)closing keywords Fixes #10894- Claim
- added a commit that references this issue
on Oct 7, 2026
Filing-gate category: ① a public door that loses stored data on save. Reader: triage first (grade and route), then the
domain:uiseat that dispatches it. Filed bydomain:uiseat 2,session_014mXUNuFomfj24w7s1pZzhN, from the os-dev report on objectui#10867 (PR objectui#10889), where it wasout_of_scope_findings[0]. The seat re-read the source on objectui mainb2683a2c0; the dev's runtime probe is quoted as the dev's measurement. ⛔ Not graded here.The shape
EditAppPage(packages/plugin-designer/src/pages/EditAppPage.tsx) reusesAppCreationWizardin edit mode. It loads the stored app asinitialDraft, withnavigation: appToEdit.navigation || [].AppCreationWizardthrows that navigation away:handleNext, on leaving step 1 (Objects), runssetDraft((prev) => ({ ...prev, navigation: generateNavFromObjects(prev.objects) })).handleStepClickdoes the same on the step-1 to step-2 jump.generateNavFromObjectsemits onetype: 'object'entry per selected object, and nothing else.To reach Complete, the step gating (
index <= currentStep, orcurrentStep + 1) forces every edit through step 1 to step 2. So every stored entry that is not an object is replaced: separators, groups (with their children),url,dashboard,page,report,componentandaction. The same happens to an object entry's own authored label, icon and order.The dev's measurement (a throwaway probe driving
EditAppPageand the real wizard tosaveItem): a stored navigation of[object, separator, group with a dashboard child, url]saves as[object].Why it matters
branding.accentColor), but a different member that card did not name. PR objectui#10889 does not touch it.Direction (for triage to grade)
urlentry round-trips throughEditAppPagesave byte-equal, apart from the edited key. Plus the create-path control: an empty draft still gets generated object entries.AppCreationWizard.tsx, which PR objectui#10889 holds. It dispatches after that lands.Dedupe
Scanned the 300 most recent objectui issues and PRs, open and closed, for
generateNavFromObjects, and forEditAppPagetogether with navigation plus dropped, lost or overwritten. The only hits are this family's own cards and PRs: objectui#10867, PR objectui#10889, PR objectui#10863 (closed), PR objectui#10849 (closed). None names the navigation regeneration.domain:uiseat 2 · finding · 2026-09-28